Set up automated testing
This commit is contained in:
parent
e9f89e1bdb
commit
dca9c3c39e
@ -1,6 +1,10 @@
|
|||||||
version: '3'
|
version: "3"
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
|
fmt:
|
||||||
|
cmds:
|
||||||
|
- npm run fmt
|
||||||
|
|
||||||
dev:
|
dev:
|
||||||
cmds:
|
cmds:
|
||||||
# - cd ../visions-types && task build
|
# - cd ../visions-types && task build
|
||||||
|
@ -1,28 +1,29 @@
|
|||||||
import js from '@eslint/js'
|
import js from "@eslint/js";
|
||||||
import globals from 'globals'
|
import globals from "globals";
|
||||||
import reactHooks from 'eslint-plugin-react-hooks'
|
import reactHooks from "eslint-plugin-react-hooks";
|
||||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
import reactRefresh from "eslint-plugin-react-refresh";
|
||||||
import tseslint from 'typescript-eslint'
|
import tseslint from "typescript-eslint";
|
||||||
|
import eslintConfigPrettier from "eslint-config-prettier";
|
||||||
|
|
||||||
export default tseslint.config(
|
export default tseslint.config(
|
||||||
{ ignores: ['dist'] },
|
{ ignores: ["dist"] },
|
||||||
{
|
{
|
||||||
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
extends: [js.configs.recommended, ...tseslint.configs.recommended, eslintConfigPrettier],
|
||||||
files: ['**/*.{ts,tsx}'],
|
files: ["**/*.{ts,tsx}"],
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
ecmaVersion: 2020,
|
ecmaVersion: 2020,
|
||||||
globals: globals.browser,
|
globals: globals.browser,
|
||||||
},
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
'react-hooks': reactHooks,
|
"react-hooks": reactHooks,
|
||||||
'react-refresh': reactRefresh,
|
"react-refresh": reactRefresh,
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
...reactHooks.configs.recommended.rules,
|
...reactHooks.configs.recommended.rules,
|
||||||
'react-refresh/only-export-components': [
|
"react-refresh/only-export-components": [
|
||||||
'warn',
|
"warn",
|
||||||
{ allowConstantExport: true },
|
{ allowConstantExport: true },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
);
|
||||||
|
7
visions/ui/jest.config.js
Normal file
7
visions/ui/jest.config.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/** @type {import('ts-jest').JestConfigWithTsJest} **/
|
||||||
|
export default {
|
||||||
|
testEnvironment: "node",
|
||||||
|
transform: {
|
||||||
|
"^.+.tsx?$": ["ts-jest",{}],
|
||||||
|
},
|
||||||
|
};
|
9887
visions/ui/package-lock.json
generated
9887
visions/ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,29 +1,41 @@
|
|||||||
{
|
{
|
||||||
"name": "visions-ui",
|
"name": "visions-ui",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview"
|
"fmt": "prettier -w src",
|
||||||
},
|
"preview": "vite preview",
|
||||||
"dependencies": {
|
"test": "jest"
|
||||||
"react": "^19.0.0",
|
},
|
||||||
"react-dom": "^19.0.0"
|
"dependencies": {
|
||||||
},
|
"react": "^19.0.0",
|
||||||
"devDependencies": {
|
"react-dom": "^19.0.0"
|
||||||
"@eslint/js": "^9.19.0",
|
},
|
||||||
"@types/react": "^19.0.8",
|
"devDependencies": {
|
||||||
"@types/react-dom": "^19.0.3",
|
"@eslint/js": "^9.19.0",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@types/jest": "^29.5.14",
|
||||||
"eslint": "^9.19.0",
|
"@types/react": "^19.0.8",
|
||||||
"eslint-plugin-react-hooks": "^5.0.0",
|
"@types/react-dom": "^19.0.3",
|
||||||
"eslint-plugin-react-refresh": "^0.4.18",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"globals": "^15.14.0",
|
"eslint": "^9.19.0",
|
||||||
"typescript": "~5.7.2",
|
"eslint-plugin-react-hooks": "^5.0.0",
|
||||||
"typescript-eslint": "^8.22.0",
|
"eslint-plugin-react-refresh": "^0.4.18",
|
||||||
"vite": "^6.1.0"
|
"eslint-prettier-config": "^1.0.1",
|
||||||
}
|
"globals": "^15.14.0",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"prettier": "^3.5.1",
|
||||||
|
"ts-jest": "^29.2.5",
|
||||||
|
"typescript": "~5.7.2",
|
||||||
|
"typescript-eslint": "^8.22.0",
|
||||||
|
"vite": "^6.1.0"
|
||||||
|
},
|
||||||
|
"prettier": {
|
||||||
|
"singleQuote": true,
|
||||||
|
"semi": false,
|
||||||
|
"tabWidth": 4
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
53
visions/ui/src/client.test.ts
Normal file
53
visions/ui/src/client.test.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { Client, ReqResponse, SessionId } from "./client";
|
||||||
|
|
||||||
|
class MockClient implements Client {
|
||||||
|
users: { [_: string]: string }
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.users = { 'vakarian': 'aoeu', 'shephard': 'aoeu' }
|
||||||
|
}
|
||||||
|
|
||||||
|
async auth(username: string, password: string): Promise<ReqResponse<SessionId>> {
|
||||||
|
if (this.users[username] == password) {
|
||||||
|
if (username == 'shephard') {
|
||||||
|
return { type: 'password-reset' }
|
||||||
|
}
|
||||||
|
return { type: "ok", content: "auth-successful" }
|
||||||
|
} else {
|
||||||
|
return { type: "error", content: 401 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("what happens in an authentication", () => {
|
||||||
|
it("handles a successful response", async () => {
|
||||||
|
let client = new MockClient()
|
||||||
|
let response = await client.auth("vakarian", "aoeu")
|
||||||
|
expect(response).toEqual({ type: "ok", content: "auth-successful" })
|
||||||
|
})
|
||||||
|
|
||||||
|
it("handles an authentication failure", async () => {
|
||||||
|
let client = new MockClient();
|
||||||
|
{
|
||||||
|
let response = await client.auth("vakarian", "")
|
||||||
|
expect(response).toEqual({ type: "error", content: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let response = await client.auth("grunt", "")
|
||||||
|
expect(response).toEqual({ type: "error", content: 401 });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("handles a password-reset condition", async () => {
|
||||||
|
let client = new MockClient();
|
||||||
|
{
|
||||||
|
let response = await client.auth("shephard", "aoeu")
|
||||||
|
expect(response).toEqual({ type: "password-reset" });
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let response = await client.auth("shephard", "")
|
||||||
|
expect(response).toEqual({ type: "error", content: 401 });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
11
visions/ui/src/client.ts
Normal file
11
visions/ui/src/client.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export type UserId = string;
|
||||||
|
export type SessionId = string;
|
||||||
|
|
||||||
|
export type ReqResponse<A> = { type: "ok", content: A } | { type: "password-reset" } | { type: "error", content: number }
|
||||||
|
|
||||||
|
export interface Client {
|
||||||
|
auth: (username: string, password: string) => Promise<ReqResponse<SessionId>>
|
||||||
|
// createUser: (sessionId: SessionId, username: string) => Promise<ReqResponse<UserId>>
|
||||||
|
// deleteUser: (sessionId: SessionId, userId: string) => Promise<ReqResponse<void>>
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user