From ea26f67242604df77cdafb7d0861fdc044b5804d Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Sun, 3 Nov 2024 23:05:26 -0500 Subject: [PATCH] chore: (frontend) initial frontend tests Signed-off-by: Jacob Potter --- .github/workflows/build.yml | 2 +- .gitignore | 4 +- frontend/package-lock.json | 201 ++++++++++++++++++ frontend/package.json | 3 +- .../components/pokemon/PokemonList.spec.tsx | 19 ++ .../pokemon/PokemonListItem.spec.tsx | 37 ++++ .../pokemon/PokemonSummary.spec.tsx | 12 ++ .../src/components/pokemon/PokemonSummary.tsx | 4 +- .../ui/pokedex/KeyboardButton.spec.tsx | 16 ++ .../components/ui/pokedex/Pokedex.spec.tsx | 15 ++ .../components/ui/pokedex/TabButton.spec.tsx | 14 ++ .../src/components/ui/pokedex/TabButton.tsx | 2 +- frontend/vitest.workspace.ts | 1 + 13 files changed, 324 insertions(+), 6 deletions(-) create mode 100644 frontend/src/components/pokemon/PokemonList.spec.tsx create mode 100644 frontend/src/components/pokemon/PokemonListItem.spec.tsx create mode 100644 frontend/src/components/pokemon/PokemonSummary.spec.tsx create mode 100644 frontend/src/components/ui/pokedex/KeyboardButton.spec.tsx create mode 100644 frontend/src/components/ui/pokedex/Pokedex.spec.tsx create mode 100644 frontend/src/components/ui/pokedex/TabButton.spec.tsx diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7f48fb2..41893d4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -67,7 +67,7 @@ jobs: run: npm run build - name: Test - run: npm run test:browser + run: npm run test diff --git a/.gitignore b/.gitignore index 5652119..cbd0ef7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .DS_Store -api/.idea/dataSources.xml +api/.idea/ +/frontend/coverage/ +/.vite/vitest/results.json diff --git a/frontend/package-lock.json b/frontend/package-lock.json index edd8ae5..002a01b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -35,6 +35,7 @@ "@types/react": "^18.3.12", "@types/react-dom": "^18.3.0", "@vitest/browser": "^2.1.4", + "@vitest/coverage-v8": "^2.1.4", "autoprefixer": "^10.4.20", "eslint": "^9.9.0", "eslint-plugin-react-hooks": "^5.1.0-rc.0", @@ -372,6 +373,12 @@ "integrity": "sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==", "dev": true }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, "node_modules/@bundled-es-modules/cookie": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz", @@ -1108,6 +1115,15 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/@joshwooding/vite-plugin-react-docgen-typescript": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@joshwooding/vite-plugin-react-docgen-typescript/-/vite-plugin-react-docgen-typescript-0.3.0.tgz", @@ -3228,6 +3244,38 @@ } } }, + "node_modules/@vitest/coverage-v8": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.4.tgz", + "integrity": "sha512-FPKQuJfR6VTfcNMcGpqInmtJuVXFSCd9HQltYncfR01AzXhLucMEtQ5SinPdZxsT5x/5BK7I5qFJ5/ApGCmyTQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "@bcoe/v8-coverage": "^0.2.3", + "debug": "^4.3.7", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magic-string": "^0.30.12", + "magicast": "^0.3.5", + "std-env": "^3.7.0", + "test-exclude": "^7.0.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "2.1.4", + "vitest": "2.1.4" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, "node_modules/@vitest/expect": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.5.tgz", @@ -5565,6 +5613,12 @@ "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", "dev": true }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, "node_modules/html-tags": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", @@ -5871,6 +5925,104 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", @@ -6091,6 +6243,17 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -8147,6 +8310,44 @@ "memoizerific": "^1.11.3" } }, + "node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 4322422..826b1ef 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,7 +10,7 @@ "preview": "vite preview", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", - "test:browser": "vitest --workspace=vitest.workspace.ts --passWithNoTests" + "test": "vitest --workspace=vitest.workspace.ts --passWithNoTests" }, "dependencies": { "@fontsource/roboto": "^5.0.14", @@ -40,6 +40,7 @@ "@types/react": "^18.3.12", "@types/react-dom": "^18.3.0", "@vitest/browser": "^2.1.4", + "@vitest/coverage-v8": "^2.1.4", "autoprefixer": "^10.4.20", "eslint": "^9.9.0", "eslint-plugin-react-hooks": "^5.1.0-rc.0", diff --git a/frontend/src/components/pokemon/PokemonList.spec.tsx b/frontend/src/components/pokemon/PokemonList.spec.tsx new file mode 100644 index 0000000..c7cd48c --- /dev/null +++ b/frontend/src/components/pokemon/PokemonList.spec.tsx @@ -0,0 +1,19 @@ +import {describe, expect, it, vi} from "vitest"; +import {PokemonList} from "./PokemonList.tsx"; +import {render} from "vitest-browser-react"; +import pokemon_page_1 from '../../fixtures/pokemon_page_1.json' + + +describe("PokemonList", () => { + it("renders correctly", () => { + const mockPokemonSelect = vi.fn(); + const {getByRole} = render(); + + const buttons = getByRole("button"); + + expect(buttons.all()).toHaveLength(12) + + }) + +}) \ No newline at end of file diff --git a/frontend/src/components/pokemon/PokemonListItem.spec.tsx b/frontend/src/components/pokemon/PokemonListItem.spec.tsx new file mode 100644 index 0000000..1a60b99 --- /dev/null +++ b/frontend/src/components/pokemon/PokemonListItem.spec.tsx @@ -0,0 +1,37 @@ +import {describe, expect, it, vi} from "vitest"; +import {render} from "vitest-browser-react"; +import {PokemonListItem} from "./PokemonListItem.tsx"; +import pokemon_page_1 from '../../fixtures/pokemon_page_1.json' + + +describe("PokemonListItem", () => { + + const mockPokemonSelect = vi.fn() + + it("should render correctly", () => { + const {getByText, getByRole} = render() + + + expect(getByText("Bulbasaur")).toBeTruthy() + expect(getByRole("img")).toBeTruthy + }) + + it("should change style with active prop", () => { + const {getByRole} = render() + + expect(getByRole("button").element().className.includes("active")) + }) + + it("should pass id when clicked", async () => { + const {getByRole} = render() + + const button = getByRole("button"); + + await button.click() + + expect(mockPokemonSelect).toHaveBeenCalledWith(1) + }) +}) \ No newline at end of file diff --git a/frontend/src/components/pokemon/PokemonSummary.spec.tsx b/frontend/src/components/pokemon/PokemonSummary.spec.tsx new file mode 100644 index 0000000..b9c0ec7 --- /dev/null +++ b/frontend/src/components/pokemon/PokemonSummary.spec.tsx @@ -0,0 +1,12 @@ +import {describe, expect, it} from "vitest"; +import {render} from "vitest-browser-react"; +import {PokemonSummary} from "./PokemonSummary.tsx"; +import pokemon_page_1 from '../../fixtures/pokemon_page_1.json' + +describe("PokemonSummary", () => { + it("Should render correctly", () => { + const {getByText} = render(); + + expect(getByText('Bulbasaur')).toBeTruthy + }) +}) \ No newline at end of file diff --git a/frontend/src/components/pokemon/PokemonSummary.tsx b/frontend/src/components/pokemon/PokemonSummary.tsx index cfe9b1d..5b772a1 100644 --- a/frontend/src/components/pokemon/PokemonSummary.tsx +++ b/frontend/src/components/pokemon/PokemonSummary.tsx @@ -44,11 +44,11 @@ export const PokemonSummary = ({pokemonSpecies}: PokemonSummaryProps) => { audioRef.current.addEventListener("timeupdate", handleTimeUpdate); } - const to = setTimeout(handlePlay, 400); + // const to = setTimeout(handlePlay, 400); return () => { audioRef.current && audioRef.current.removeEventListener("timeupdate", handleTimeUpdate); - clearTimeout(to) + // clearTimeout(to) } }, [selectedPokemonVariety?.cry]); diff --git a/frontend/src/components/ui/pokedex/KeyboardButton.spec.tsx b/frontend/src/components/ui/pokedex/KeyboardButton.spec.tsx new file mode 100644 index 0000000..e24b086 --- /dev/null +++ b/frontend/src/components/ui/pokedex/KeyboardButton.spec.tsx @@ -0,0 +1,16 @@ +import {describe, expect, it, vi} from "vitest"; +import {KeyboardButton} from "./KeyboardButton.tsx"; +import {render} from "vitest-browser-react"; + +describe("KeyboardButton", () => { + + const mockOnClick = vi.fn() + + it("should render correctly", async () => { + const {getByRole} = render(); + + await getByRole("button").click() + + expect(mockOnClick).toHaveBeenCalled() + }) +}) \ No newline at end of file diff --git a/frontend/src/components/ui/pokedex/Pokedex.spec.tsx b/frontend/src/components/ui/pokedex/Pokedex.spec.tsx new file mode 100644 index 0000000..8b79cae --- /dev/null +++ b/frontend/src/components/ui/pokedex/Pokedex.spec.tsx @@ -0,0 +1,15 @@ +import {test} from "vitest"; +import {render} from "vitest-browser-react"; +import Pokedex from "./Pokedex.tsx"; + + +test("Pokedex should render", async () => { + + render( + + + + + ); + +}) \ No newline at end of file diff --git a/frontend/src/components/ui/pokedex/TabButton.spec.tsx b/frontend/src/components/ui/pokedex/TabButton.spec.tsx new file mode 100644 index 0000000..a1ce129 --- /dev/null +++ b/frontend/src/components/ui/pokedex/TabButton.spec.tsx @@ -0,0 +1,14 @@ +import {describe, expect, it} from "vitest"; +import {TabButton} from "./TabButton.tsx"; +import {render} from "vitest-browser-react"; + +describe("TabButton", () => { + + it("should render correctly", () => { + const {getByTestId} = render(); + + expect(getByTestId("info-icon")) + + }) + +}) \ No newline at end of file diff --git a/frontend/src/components/ui/pokedex/TabButton.tsx b/frontend/src/components/ui/pokedex/TabButton.tsx index 67e7aba..b016e4c 100644 --- a/frontend/src/components/ui/pokedex/TabButton.tsx +++ b/frontend/src/components/ui/pokedex/TabButton.tsx @@ -18,7 +18,7 @@ export const TabButton: FC = ({onClick, type, pulse}) => { switch (type) { case "info": - content = + content = break; case "details": content = diff --git a/frontend/vitest.workspace.ts b/frontend/vitest.workspace.ts index 339a04c..5c72a0d 100644 --- a/frontend/vitest.workspace.ts +++ b/frontend/vitest.workspace.ts @@ -12,6 +12,7 @@ export default defineWorkspace([ provider: 'playwright', // https://playwright.dev providerOptions: {}, + headless: true, }, },