Skip to main content

test-coverage

MUST be used whenever fixing test coverage for a Flows app to meet the 80% line coverage hard gate. This skill finds AND fixes coverage gaps — it configures tooling, writes missing tests, covers untested paths, and refactors code for testability. It does not just report. Triggers: test coverage, fix tests, write tests, add tests, coverage fix, 80% coverage, coverage gate, missing tests, testability, vitest coverage, jest coverage.

Ir a la instalación

Datos de origen

Repositorio
cognitedata/builder-skills
Última actividad en el origen
7 de mayo de 2026 a las 16:46
Idioma detectado de SKILL.md
inglés
Estrellas
6
Forks
1

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
test-coverage
description
MUST be used whenever fixing test coverage for a Flows app to meet the 80% line coverage hard gate. This skill finds AND fixes coverage gaps — it configures tooling, writes missing tests, covers untested paths, and refactors code for testability. It does not just report. Triggers: test coverage, fix tests, write tests, add tests, coverage fix, 80% coverage, coverage gate, missing tests, testability, vitest coverage, jest coverage.
allowed-tools
Read, Glob, Grep, Shell, Write
metadata
{"argument-hint":"[directory or file to audit, or leave blank for the whole app]"}
# Test Coverage Fix Fix test coverage for **$ARGUMENTS** (or the whole app if no argument is given). This skill enforces the **80% line coverage hard gate** required for Flows app approval by finding AND fixing coverage gaps. Work through every step in order. --- ## Step 1 — Verify test framework and coverage tooling Check that the project has a working test framework with coverage configured: ```bash # Check for vitest or jest in package.json grep -E "(vitest|jest)" package.json # Check for coverage configuration cat vitest.config.ts 2>/dev/null || cat vitest.config.js 2>/dev/null || cat jest.config.ts 2>/dev/null || cat jest.config.js 2>/dev/null ``` Verify: - A test framework (Vitest or Jest) is installed and configured - The config file has a `coverage` section (e.g. `coverage: { provider: 'v8', ... }` in vitest.config.ts) - A coverage reporter is configured (at least `text` and `lcov` or `json-summary`) **If coverage tooling is not configured, fix it now:** 1. Install the coverage provider: ```bash pnpm add -D @vitest/coverage-v8 ``` 2. Add the coverage configuration to `vitest.config.ts`. Read the existing config file, then add the `coverage` section inside `test`: ```typescript // vitest.config.ts — minimum coverage configuration to add test: { coverage: { provider: 'v8', reporter: ['text', 'text-summary', 'lcov'], include: ['src/**/*.{ts,tsx}'], exclude: [ 'src/**/*.test.{ts,tsx}', 'src/**/*.spec.{ts,tsx}', 'src/**/vite-env.d.ts', 'src/main.tsx', ], }, } ``` Write the updated config file. If no vitest.config.ts exists at all, create one with the full `defineConfig` wrapper. --- ## Step 2 — Validate coverage scope The 80% threshold applies to **all `.ts` and `.tsx` files** under `src/`, excluding only: - Test files (`*.test.ts`, `*.test.tsx`, `*.spec.ts`, `*.spec.tsx`) - Type declaration files (`vite-env.d.ts`) - The entry point (`main.tsx`) Apps must **not** exclude pages, components, hooks, or other production code from coverage measurement. ```bash # Check what files are excluded from coverage in the config grep -A 20 "exclude" vitest.config.ts 2>/dev/null || grep -A 20 "exclude" vitest.config.js 2>/dev/null # Check for coveragePathIgnorePatterns in jest config grep -A 10 "coveragePathIgnorePatterns\|collectCoverageFrom" jest.config.ts 2>/dev/null ``` **If the config excludes production files, fix it now:** Remove any exclusion that hides production code from coverage measurement. Only test files, type declarations, and the entry point should be excluded. Rewrite the `exclude` array to contain only: ```typescript exclude: [ 'src/**/*.test.{ts,tsx}', 'src/**/*.spec.{ts,tsx}', 'src/**/vite-env.d.ts', 'src/main.tsx', ], ``` Specifically remove any exclusions for: - `src/pages/` or `src/components/` or `src/hooks/` — **NOT allowed** - Specific feature files — **NOT allowed** unless they are generated code - `src/**/*.tsx` (all components) — **NOT allowed**, this hides the majority of the app Write the corrected config file. --- ## Step 3 — Run tests and collect coverage ```bash # Try common coverage commands based on project setup npx vitest run --coverage 2>/dev/null || npx jest --coverage 2>/dev/null || npm test -- --coverage 2>/dev/null ``` Record the coverage summary: - **Statements:** X% - **Branches:** X% - **Functions:** X% - **Lines:** X% **Hard gate:** Overall line coverage must be **at least 80%**. Apps below this threshold are listed as **must fix**. **If tests fail to run, fix them now:** Common fixes: - **Missing imports:** Read the failing test file, add the missing import statement, write the fixed file. - **Broken mocks:** Read the test to understand what is being mocked. Fix the mock to match the current API of the mocked module. - **Outdated snapshots:** Run `npx vitest run --update` to update snapshots, then review the diff to ensure correctness. - **Missing dependencies:** Run `pnpm add -D <missing-package>` for any test utilities not yet installed. - **Config errors:** Read the config file, fix syntax or option errors, write the corrected file. Re-run tests after each fix until all tests pass. Then record the coverage summary. --- ## Step 4 — Find and write missing test files For every non-trivial `.ts`/`.tsx` file under `src/`, check whether a corresponding test file exists: ```bash # List all production files and check for test counterparts for file in $(find src -name "*.ts" -o -name "*.tsx" | grep -v ".test." | grep -v ".spec." | grep -v "node_modules" | grep -v "vite-env" | sort); do base="${file%.*}" ext="${file##*.}" dir=$(dirname "$file") filename=$(basename "$base") # Check for test file in same directory or __tests__ directory test_exists="false" for pattern in "${base}.test.${ext}" "${base}.spec.${ext}" "${base}.test.ts" "${base}.spec.ts" "${dir}/__tests__/${filename}.test.${ext}" "${dir}/__tests__/${filename}.spec.${ext}"; do if [ -f "$pattern" ]; then test_exists="true" break fi done if [ "$test_exists" = "false" ]; then echo "NO TEST: $file" fi done ``` Categorize each file without a test: - **Services, hooks, utils, contexts, ViewModel hooks** — **Write the test file now** (see below) - **Pure presentational components** with no logic — Mark as **N/A** (no test required) - **Barrel exports** (`index.ts` that only re-exports) — Mark as **N/A** - **Type-only files** (`.d.ts`, files with only type/interface exports) — Mark as **N/A** **For each file missing a test, create a comprehensive test file.** Use context injection for dependency mocking where the production code supports it. If the production code uses hard-coded imports, note this as a testability concern but still write the test using `vi.mock` with a justification comment. Follow this process for each: 1. **Read the source file** to understand its exports, dependencies, and logic. 2. **Create a `.test.ts` or `.test.tsx` file** in the same directory as the source file. 3. **Write tests covering:** happy path, error path, empty state, and edge cases. Use the right testing pattern for each file type: **For hooks:** - Test with `renderHook` from `@testing-library/react` - Wrap with necessary providers (QueryClientProvider, custom context providers, etc.) - Test initial state, loading state, success state, and error state - Example structure: ```typescript import { renderHook, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; // import the hook const createWrapper = () => { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } }, }); return ({ children }: { children: React.ReactNode }) => ( <QueryClientProvider client={queryClient}>{children}</QueryClientProvider> ); }; describe('useMyHook', () => { it('returns data on success', async () => { const { result } = renderHook(() => useMyHook(), { wrapper: createWrapper() }); await waitFor(() => expect(result.current.data).toBeDefined()); }); it('handles errors', async () => { // set up error condition const { result } = renderHook(() => useMyHook(), { wrapper: createWrapper() }); await waitFor(() => expect(result.current.error).toBeDefined()); }); }); ``` **For services/utils:** - Test with direct function calls - Mock CDF SDK responses where needed - Test return values, side effects, and thrown errors - Example structure: ```typescript import { describe, it, expect, vi } from 'vitest'; // import the service/util functions describe('myService', () => { it('returns expected result for valid input', () => { const result = myFunction(validInput); expect(result).toEqual(expectedOutput); }); it('throws on invalid input', () => { expect(() => myFunction(invalidInput)).toThrow(); }); }); ``` **For components with logic:** - Test with `render` from `@testing-library/react` - Verify loading, error, and data states - Test user interactions that trigger state changes - Example structure: ```typescript import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; // import the component and providers describe('MyComponent', () => { it('shows loading state initially', () => { render(<MyComponent />, { wrapper: createWrapper() }); expect(screen.getByText(/loading/i)).toBeInTheDocument(); }); it('renders data after loading', async () => { render(<MyComponent />, { wrapper: createWrapper() }); await waitFor(() => { expect(screen.getByText('expected content')).toBeInTheDocument(); }); }); }); ``` **Dependency mocking guidelines:** - Use context injection (not `vi.mock`) where possible — provide test dependencies via the hook's context. - If the production code uses hard-coded imports that prevent context injection, use `vi.mock` with a justification comment explaining why (e.g., `// vi.mock required: useDataSource uses direct import, not context injection`). - Ensure mocks are type-safe — no `as unknown as T` casts. Define proper mock objects that satisfy the interface. After writing each test file, run `npx vitest run <test-file>` to verify it passes. --- ## Step 5 — Fix low-coverage files If the coverage tool produces per-file metrics, list files below 80% line coverage: ```bash # Parse lcov or text output for per-file coverage cat coverage/coverage-summary.json 2>/dev/null | node -e " const data = JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); Object.entries(data).forEach(([file, metrics]) => { if (file === 'total') return; const pct = metrics.lines?.pct ?? 0; if (pct < 80) console.log(pct.toFixed(1) + '% — ' + file); }); " 2>/dev/null ``` **For each file below 80% coverage, read the uncovered lines from the coverage report, then add test cases that exercise those specific code paths:** 1. **Read the uncovered lines** from the coverage report. Check the `coverage/` directory for detailed per-file reports (lcov or html) that show which lines are uncovered. 2. **Read the source file** to understand what those uncovered lines do. 3. **Add test cases** that exercise those specific code paths: - **Uncovered error paths:** Add tests that trigger error conditions (network failures, invalid input, null values, permission errors). Force errors by providing bad input or mocking dependencies to throw. - **Uncovered branches:** Add tests for each conditional branch. If an `if/else` has only the `true` branch tested, write a test that triggers the `false` branch. - **Uncovered functions:** Add tests that call each exported function that lacks coverage. Verify return values and side effects. - **Uncovered catch blocks:** Mock the upstream call to reject/throw, verify the catch block behavior. 4. **Run coverage again** after adding tests to verify the file now meets 80%: ```bash npx vitest run --coverage <test-file> ``` Repeat until each file reaches at least 80% line coverage or you have covered all feasible paths. --- ## Step 6 — Fix testability patterns Assess and fix testability issues in the codebase: ```bash # Check for dependency injection via context grep -rn --include="*.ts" --include="*.tsx" "useContext\|createContext" src/hooks/ src/contexts/ # Check for vi.mock usage (red flag for testability) grep -rn --include="*.ts" --include="*.tsx" "vi\.mock" src/ # Check for unsafe casts in tests grep -rn --include="*.ts" --include="*.tsx" "as unknown as" src/ | grep -E "\.test\.|\.spec\." # Check for interface-based services grep -rn --include="*.ts" --include="*.tsx" -E "implements\s+\w+" src/ ``` **For each testability issue found, refactor the production code to support better testing patterns. Then update the corresponding test to use the improved pattern.** | Issue | Fix |
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub