Set up automated testing
This commit is contained in:
parent
e9f89e1bdb
commit
dca9c3c39e
@ -1,6 +1,10 @@
|
||||
version: '3'
|
||||
version: "3"
|
||||
|
||||
tasks:
|
||||
fmt:
|
||||
cmds:
|
||||
- npm run fmt
|
||||
|
||||
dev:
|
||||
cmds:
|
||||
# - cd ../visions-types && task build
|
||||
|
@ -1,28 +1,29 @@
|
||||
import js from '@eslint/js'
|
||||
import globals from 'globals'
|
||||
import reactHooks from 'eslint-plugin-react-hooks'
|
||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import js from "@eslint/js";
|
||||
import globals from "globals";
|
||||
import reactHooks from "eslint-plugin-react-hooks";
|
||||
import reactRefresh from "eslint-plugin-react-refresh";
|
||||
import tseslint from "typescript-eslint";
|
||||
import eslintConfigPrettier from "eslint-config-prettier";
|
||||
|
||||
export default tseslint.config(
|
||||
{ ignores: ['dist'] },
|
||||
{ ignores: ["dist"] },
|
||||
{
|
||||
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
extends: [js.configs.recommended, ...tseslint.configs.recommended, eslintConfigPrettier],
|
||||
files: ["**/*.{ts,tsx}"],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2020,
|
||||
globals: globals.browser,
|
||||
},
|
||||
plugins: {
|
||||
'react-hooks': reactHooks,
|
||||
'react-refresh': reactRefresh,
|
||||
"react-hooks": reactHooks,
|
||||
"react-refresh": reactRefresh,
|
||||
},
|
||||
rules: {
|
||||
...reactHooks.configs.recommended.rules,
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
"react-refresh/only-export-components": [
|
||||
"warn",
|
||||
{ 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",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.19.0",
|
||||
"@types/react": "^19.0.8",
|
||||
"@types/react-dom": "^19.0.3",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"eslint": "^9.19.0",
|
||||
"eslint-plugin-react-hooks": "^5.0.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.18",
|
||||
"globals": "^15.14.0",
|
||||
"typescript": "~5.7.2",
|
||||
"typescript-eslint": "^8.22.0",
|
||||
"vite": "^6.1.0"
|
||||
}
|
||||
"name": "visions-ui",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint .",
|
||||
"fmt": "prettier -w src",
|
||||
"preview": "vite preview",
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.19.0",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/react": "^19.0.8",
|
||||
"@types/react-dom": "^19.0.3",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"eslint": "^9.19.0",
|
||||
"eslint-plugin-react-hooks": "^5.0.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.18",
|
||||
"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