Files
PageManager/CLAUDE.md
T
2026-03-15 22:31:31 +02:00

133 lines
5.4 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository Structure
Mono-repo with two projects:
- `PageManager.Api/` — .NET 10 Web API (solution root contains `PageManager.Api.slnx`)
- `PageManager.Api/PageManager.Api/` — the actual C# project
- `PageManager.Api/PageManager.Api.Tests/` — xunit test project
- `PageManager.Web/` — React 19 + Vite + TypeScript SPA
- `compose.yaml` — root-level Docker Compose orchestrating both services
## Development Commands
### API (`PageManager.Api/`)
```bash
cd PageManager.Api
dotnet run --project PageManager.Api # runs on http://localhost:5278
dotnet build
dotnet test # all tests
dotnet test --filter "FullyQualifiedName~Unit" # unit only (no Docker needed)
dotnet test --filter "FullyQualifiedName~Integration" # integration only (Docker required)
```
### Migrations (`PageManager.Api/`)
EF Core tooling targets the `PageManager.Api` project. All commands run from `PageManager.Api/`.
```bash
# Create a migration after changing Data/Models
dotnet ef migrations add <MigrationName> --project PageManager.Api
# Apply pending migrations to the database
dotnet ef database update --project PageManager.Api
# Roll back to a specific migration
dotnet ef database update <MigrationName> --project PageManager.Api
# Generate SQL script for a migration (useful for production deploys)
dotnet ef migrations script --project PageManager.Api
```
Install the EF global tool if not present: `dotnet tool install --global dotnet-ef`
### Web (`PageManager.Web/`)
```bash
cd PageManager.Web
npm install
npm run dev # http://localhost:5173
npm run build
npm run preview # preview production build locally
npm test # single pass (CI)
npm run test:watch # interactive watch (development)
npm run test:coverage
```
### Docker (both services)
```bash
docker compose up --build # web → :8080, api → :5278
```
## Architecture
### API → Web connection
**Dev:** Vite dev server proxies `/api/*` to `http://localhost:5278` (configured in `PageManager.Web/vite.config.ts`). The API enables CORS for `http://localhost:5173` in `Program.cs` — only in the `Development` environment.
**Production (Docker):** nginx (`PageManager.Web/nginx.conf`) proxies `/api/*` to `http://pagemanager.api:8080` (the compose service name). All other routes fall back to `index.html` for SPA routing.
## Conventions
- Controllers are thin — logic lives in Services
- EF Core models in Data/Models, DTOs in Api/Dtos
- React components in PascalCase, files match component name
- API calls go through src/api/*.ts typed wrappers, never raw fetch in components
- Design reference: src/Leafreader.Web/design-reference.html
## Testing
**Rule: every code change must be followed by running the relevant tests and fixing any failures before the task is considered done.**
### After API changes
```bash
cd PageManager.Api
dotnet test --filter "FullyQualifiedName~Unit" # always run; no Docker needed
# If integration-relevant (endpoint, EF query, DB schema): also run:
dotnet test --filter "FullyQualifiedName~Integration" # requires Docker
```
### After Web changes
```bash
cd PageManager.Web
npm test
```
### Test locations
| Layer | Location | Tool |
|---|---|---|
| API unit | `PageManager.Api.Tests/Unit/Services/` | xunit + NSubstitute + FluentAssertions |
| API integration | `PageManager.Api.Tests/Integration/` | xunit + Testcontainers (postgres:17-alpine) + WebApplicationFactory |
| Web unit | `src/**/__tests__/` | Vitest + Testing Library |
### What to test and when
- **New service method or DTO mapping** → add unit test in `Unit/Services/`
- **New or changed endpoint** → add integration test in `Integration/BooksControllerTests.cs` (or a new `*ControllerTests.cs`)
- **New utility function** (`utils.ts`) → add unit test in a sibling `__tests__/` folder
- **New React component with logic** → add component test in `__tests__/`
- **Private logic inside a component** → extract to `utils.ts` first, then test the exported function
### What does NOT get tested
- `BooksRepository` — pure EF Include chains, covered by integration tests
- `BooksController` — too thin, covered by integration tests
- CSS Modules, `Sidebar` (static nav), `App.tsx` routing
- `importQueue.ts` — currently mock stubs; add tests when real HTTP is introduced
### Decision rules
- Unit test: any service method, utility function, or DTO mapping with conditional logic or data transformation
- Integration test: any new endpoint, EF Core query change, or PostgreSQL-specific feature
- Don't duplicate: if unit tests own mapping correctness, integration tests own HTTP contract + DB round-trip
- Extract before testing: private logic inside a component must move to `utils.ts` before writing tests
### Infrastructure notes
- Integration tests use `[Collection("Postgres")]` — one container shared across all integration test classes
- Each integration test class truncates tables in `InitializeAsync` to ensure isolation
- `Book.Formats` and `Book.Genres` are `text[]` (PostgreSQL-specific) — always use real Postgres for integration tests, never InMemory
- `TestWebAppFactory` sets `UseEnvironment("Testing")` — CORS and OpenAPI middleware are skipped