Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,82 @@ In order to prepare a production-ready version of the app, run:
pnpm build # or: pnpm run build
```

## Testing

Tests are written with [Vitest](https://vitest.dev/) and
[React Testing Library](https://testing-library.com/docs/react-testing-library/intro/),
and run in a simulated browser DOM ([jsdom](https://github.com/jsdom/jsdom)).

Run all tests once:

```sh
pnpm test
```

Run tests in watch mode while developing:

```sh
pnpm test:watch
```

Test files live next to the code they test (`*.test.ts` / `*.test.tsx`).
Shared helpers and fixtures live in `src/test/`:

- `setup.ts` adds the [jest-dom](https://github.com/testing-library/jest-dom)
matchers (e.g. `toBeInTheDocument`) and clears the DOM and `localStorage`
after every test.
- `renderWithQueryClient.tsx` renders components inside a
`QueryClientProvider`, which components that use `useBooks` need.
- `fixtures/` holds saved Open Library responses (a search and a work) and a
sample book.

### What is tested

We test where there is logic, state or several parts working together. Static
markup (like `Header` and `Footer`) is not tested: such tests break on every
intended change without catching real bugs.

- **Unit tests** for the API layer (`src/api/openLibrary.test.ts`): `toBook`
and `toDescription` map Open Library data to our types (with fallbacks for
missing fields), and `searchBooks` and `fetchWork` build the right request
and throw on HTTP errors.
- **Component tests** for `BookCard`, `BookDetails`, `FavoriteButton`,
`Pagination`, `SearchBar` and `BookGrid`: rendering based on props, user
interaction (clicks, typing) and state (favorites in `localStorage`; loading,
error and empty states; paging; loading the description).
- **Snapshot test** for `BookCard`. The rendered HTML is stored in
`__snapshots__/` next to the test and compared on every run. If a markup
change is intended, update the snapshot with `pnpm test -u`.
- **Integration test** for `App`: selecting a book shows its details and
description, and going back shows the grid again without a new API request.

### Mocking

No test sends requests to openlibrary.org:

- `openLibrary.test.ts` replaces the global `fetch` with a mock (`vi.spyOn`)
that answers with the saved responses in `src/test/fixtures/`.
- The `App` and `BookDetails` tests replace `searchBooks` and `fetchWork`
with mocks (`vi.mock`), so the components receive the fixture data
(`searchResponse.json`, `workResponse.json`) right away.
- `BookGrid` does not fetch anything itself; its tests pass a fake query
result in as a prop.

### Browsers and devices

The application is checked manually in the browsers and screen sizes below.
The grid should show 4/3/2/1 columns as the viewport gets narrower, and the
details view should stack vertically below 900px.

| Browser / device | Viewport | Result | Date |
| --------------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------- | ---------- |
| Chromium (Claude Code built-in browser) | 1280 × 800 (desktop) | OK: 4-column grid, details side by side | 2026-09-16 |
| Chromium (Claude Code built-in browser) | 768 × 1024 (tablet, emulated) | OK: 2-column grid | 2026-09-16 |
| Chromium (Claude Code built-in browser) | 375 × 812 (phone, emulated) | Grid and details stack in one column. **Bug:** the header title is cut off by the "Mine favorittbøker" button | 2026-09-16 |
| Safari (macOS) | | Not yet tested | |
| Firefox | | Not yet tested | |
| iPhone / Android (real device) | | Not yet tested | |

## Working in this repository

`main` is protected — you cannot push to it directly. Work on a branch and
Expand Down
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
"preview": "vite preview",
"test": "vitest run",
"test:watch": "vitest"
},
"dependencies": {
"@tanstack/react-query": "^5.102.8",
Expand All @@ -22,6 +24,10 @@
"@babel/core": "^7.29.7",
"@eslint/js": "^10.0.1",
"@rolldown/plugin-babel": "^0.2.3",
"@testing-library/dom": "^10.4.2",
"@testing-library/jest-dom": "^7.0.1",
"@testing-library/react": "^16.3.3",
"@testing-library/user-event": "^14.6.7",
"@types/babel__core": "^7.20.5",
"@types/node": "^24.13.3",
"@types/react": "^19.2.18",
Expand All @@ -32,9 +38,11 @@
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.4",
"globals": "^17.11.0",
"jsdom": "^30.0.1",
"prettier": "3.9.6",
"typescript": "~6.0.2",
"typescript-eslint": "^8.67.0",
"vite": "^8.2.2"
"vite": "^8.2.2",
"vitest": "^5.0.1"
}
}
Loading