-
Notifications
You must be signed in to change notification settings - Fork 0
Add test coverage analysis with prioritized improvement proposals #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
blackboxprogramming
wants to merge
4
commits into
main
Choose a base branch
from
claude/analyze-test-coverage-tMD7S
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
0622ebc
Add test coverage analysis with prioritized improvement proposals
claude 7a18cf4
Add test infrastructure and 107 tests for API and UI components
claude caf8486
Enhance homework API with full CRUD, search, and 34 tests
claude f35ff47
Add tests for server_full.js LLM bridge and design token validation
claude File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -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. | ||||||
|
||||||
| **Recommended framework:** [Vitest](https://vitest.dev/) + [supertest](https://github.com/ladakh/supertest) for HTTP assertions. | |
| **Recommended framework:** [Vitest](https://vitest.dev/) + [supertest](https://github.com/visionmedia/supertest) for HTTP assertions. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| import { describe, it, expect } from 'vitest'; | ||
| import { readFileSync } from 'fs'; | ||
| import { resolve } from 'path'; | ||
|
|
||
| const tokensPath = resolve(__dirname, '../blackroad/design-tokens.json'); | ||
| const tokens = JSON.parse(readFileSync(tokensPath, 'utf-8')); | ||
|
|
||
| describe('Design tokens', () => { | ||
| it('is valid parseable JSON', () => { | ||
| expect(tokens).toBeDefined(); | ||
| expect(typeof tokens).toBe('object'); | ||
| }); | ||
|
|
||
| // ── Colors ────────────────────────────────────────────────────── | ||
|
|
||
| describe('colors', () => { | ||
| const requiredColors = [ | ||
| 'primary', | ||
| 'secondary', | ||
| 'accent', | ||
| 'neutral', | ||
| 'info', | ||
| 'danger', | ||
| 'warning', | ||
| 'success', | ||
| ]; | ||
|
|
||
| it('has a color section', () => { | ||
| expect(tokens.color).toBeDefined(); | ||
| }); | ||
|
|
||
| it.each(requiredColors)('defines the "%s" color', (name) => { | ||
| expect(tokens.color[name]).toBeDefined(); | ||
| }); | ||
|
|
||
| it.each(requiredColors)('"%s" is a valid hex color', (name) => { | ||
| expect(tokens.color[name]).toMatch(/^#[0-9A-Fa-f]{6}$/); | ||
| }); | ||
| }); | ||
|
|
||
| // ── Fonts ─────────────────────────────────────────────────────── | ||
|
|
||
| describe('fonts', () => { | ||
| it('has a font section', () => { | ||
| expect(tokens.font).toBeDefined(); | ||
| }); | ||
|
|
||
| it('defines sans and mono font families', () => { | ||
| expect(tokens.font.family.sans).toBeDefined(); | ||
| expect(tokens.font.family.mono).toBeDefined(); | ||
| }); | ||
|
|
||
| it('has standard font sizes', () => { | ||
| const requiredSizes = ['xs', 'sm', 'base', 'lg', 'xl']; | ||
| for (const size of requiredSizes) { | ||
| expect(tokens.font.size[size]).toBeDefined(); | ||
| expect(tokens.font.size[size]).toMatch(/^\d+(\.\d+)?rem$/); | ||
| } | ||
| }); | ||
|
|
||
| it('has standard font weights', () => { | ||
| expect(tokens.font.weight.normal).toBe(400); | ||
| expect(tokens.font.weight.medium).toBe(500); | ||
| expect(tokens.font.weight.bold).toBe(700); | ||
| }); | ||
|
|
||
| it('font sizes are in ascending order', () => { | ||
| const sizes = ['xs', 'sm', 'base', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl']; | ||
| const values = sizes.map((s) => parseFloat(tokens.font.size[s])); | ||
| for (let i = 1; i < values.length; i++) { | ||
| expect(values[i]).toBeGreaterThan(values[i - 1]); | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| // ── Border radius ────────────────────────────────────────────── | ||
|
|
||
| describe('border radius', () => { | ||
| it('has a radius section', () => { | ||
| expect(tokens.radius).toBeDefined(); | ||
| }); | ||
|
|
||
| const requiredRadii = ['none', 'sm', 'md', 'lg', 'xl', 'full']; | ||
|
|
||
| it.each(requiredRadii)('defines the "%s" radius', (name) => { | ||
| expect(tokens.radius[name]).toBeDefined(); | ||
| }); | ||
|
|
||
| it('"none" radius is "0"', () => { | ||
| expect(tokens.radius.none).toBe('0'); | ||
| }); | ||
|
|
||
| it('"full" radius is a very large value', () => { | ||
| expect(parseFloat(tokens.radius.full)).toBeGreaterThan(100); | ||
| }); | ||
|
|
||
| it('radii are in ascending order (excluding full)', () => { | ||
| const ordered = ['none', 'sm', 'md', 'lg', 'xl']; | ||
| const values = ordered.map((r) => parseFloat(tokens.radius[r])); | ||
| for (let i = 1; i < values.length; i++) { | ||
| expect(values[i]).toBeGreaterThan(values[i - 1]); | ||
| } | ||
| }); | ||
| }); | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The line counts in the inventory table are consistently off by 1 for all files. For example, apps/api/index.js is listed as 49 lines but is actually 50 lines. This pattern repeats for all entries. Please verify and correct the line counts using the actual file sizes.