diff --git a/.github/workflows/core-ci.yml b/.github/workflows/core-ci.yml index a6b97acf8..603ceb7e0 100644 --- a/.github/workflows/core-ci.yml +++ b/.github/workflows/core-ci.yml @@ -13,9 +13,24 @@ jobs: - name: Guardrail run: echo "CORE repo guardrail active" - lint: + test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Lint placeholder - run: echo "Add lint/test here" + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Run root tests (server + design tokens) + run: pnpm test + - name: Run API tests + run: pnpm --filter @blackroad/api test + - name: Run UI tests + run: pnpm --filter @blackroad/ui test diff --git a/TEST_COVERAGE_ANALYSIS.md b/TEST_COVERAGE_ANALYSIS.md new file mode 100644 index 000000000..a2cffdd1a --- /dev/null +++ b/TEST_COVERAGE_ANALYSIS.md @@ -0,0 +1,263 @@ +# Test Coverage Analysis + +## Current State: No Tests Exist + +The BlackRoad monorepo currently has **zero test files, zero test configuration, and zero CI test execution**. No testing framework (Jest, Vitest, Mocha, Testing Library, Playwright, etc.) is installed in any workspace. The CI pipeline (`core-ci.yml`) contains only a placeholder: `echo "Add lint/test here"`. + +This means every module described below has **0% test coverage**. + +--- + +## Codebase Inventory + +| Module | Location | Language | Lines | Test Files | Coverage | +|---|---|---|---|---|---| +| API server | `apps/api/index.js` | JS | 49 | 0 | 0% | +| Standalone server | `server_full.js` | JS | 44 | 0 | 0% | +| Homework portal | `apps/homework/pages/index.tsx` | TSX | 63 | 0 | 0% | +| RoadBook site | `apps/roadbook/pages/*.tsx` | TSX | ~135 | 0 | 0% | +| UI: Button | `packages/ui/src/components/Button.tsx` | TSX | 76 | 0 | 0% | +| UI: Input | `packages/ui/src/components/Input.tsx` | TSX | 53 | 0 | 0% | +| UI: Tabs | `packages/ui/src/components/Tabs.tsx` | TSX | 60 | 0 | 0% | +| UI: Badge | `packages/ui/src/components/Badge.tsx` | TSX | 61 | 0 | 0% | +| UI: Card | `packages/ui/src/components/Card.tsx` | TSX | 37 | 0 | 0% | +| UI: Dialog | `packages/ui/src/components/Dialog.tsx` | TSX | 85 | 0 | 0% | +| UI: Drawer | `packages/ui/src/components/Drawer.tsx` | TSX | 93 | 0 | 0% | +| UI: DataTable | `packages/ui/src/components/DataTable.tsx` | TSX | 92 | 0 | 0% | +| UI: Toast | `packages/ui/src/components/Toast.tsx` | TSX | 78 | 0 | 0% | + +--- + +## Proposed Testing Strategy + +### Priority 1 (High) — API Server Unit/Integration Tests + +**Why:** The API layer (`apps/api/index.js` and `server_full.js`) is the highest-risk code. It handles user input, manages in-memory state, and bridges to external services. Bugs here affect every consumer. + +**Recommended framework:** [Vitest](https://vitest.dev/) + [supertest](https://github.com/ladakh/supertest) for HTTP assertions. + +**What to test:** + +1. **`GET /api/health`** — returns `{ ok: true }` with status 200. +2. **`GET /api/homework`** — returns an empty array initially; returns items after POST. +3. **`POST /api/homework`** — with valid body creates a homework item and returns 201. +4. **`POST /api/homework`** — with missing `title` returns 400 with error message. +5. **`POST /api/homework`** — with missing `description` returns 400 with error message. +6. **`POST /api/homework`** — with empty body returns 400. +7. **CORS middleware** — `OPTIONS` requests return 200 with correct headers; `Access-Control-Allow-Origin` is `*`. +8. **`server_full.js` — `GET /api/hello`** — returns expected JSON. +9. **`server_full.js` — `GET /health`** — returns `{ status: 'ok', service: 'blackroad-api' }`. +10. **`server_full.js` — `POST /api/llm/chat`** — with missing/empty message returns 400; with valid message and unreachable upstream returns 502. + +**Example test file location:** `apps/api/__tests__/api.test.ts` + +--- + +### Priority 2 (High) — UI Component Library Tests + +**Why:** The `@blackroad/ui` package is a shared dependency consumed by multiple apps. Regressions here cascade across the entire platform. The components contain variant logic, conditional rendering, keyboard event handling, and timer-based behavior that are all easy to break silently. + +**Recommended framework:** Vitest + [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro/) + jsdom. + +**What to test per component:** + +#### Button (`Button.tsx`) +- Renders children text. +- Applies correct CSS classes for each `variant` (primary, secondary, accent, neutral, info, danger, warning, success, outline). +- Applies correct CSS classes for each `size` (sm, md, lg). +- Defaults to `variant="primary"` and `size="md"` when no props are passed. +- Forwards native button attributes (`disabled`, `onClick`, `type`). +- Merges custom `className` with generated classes. + +#### Input (`Input.tsx`) +- Renders an `` element. +- Renders a `