From dev-core
Generate/run unit, integration & Playwright e2e tests. Triggers: "test this file" | "write tests" | "add coverage" | "run tests" | "e2e tests" | "add tests" | "test coverage" | "generate tests" | "test this" | "write unit tests" | "add integration tests".
npx claudepluginhub roxabi/roxabi-plugins --plugin dev-coreThis skill is limited to using the following tools:
Let:
Writes TDD tests supporting Jest, Cypress, Detox, PHPUnit, PyTest, and Go testing. Adds unit, integration, E2E tests to improve coverage on existing code.
Generates Playwright tests from user stories, URLs, components, or features. Explores codebase, uses templates for auth, CRUD, checkout, and follows best practices for locators and assertions.
Share bugs, ideas, or general feedback.
Let:
τ := target file(s) under test
π := test file adjacent to source ({name}.test.ts | {name}.spec.ts | __tests__/{name}.test.ts)
Σ := {standards.testing}
Generate tests for changed/specified files. Follow existing codebase patterns.
/test → Generate tests for files changed vs base branch
/test src/auth/login.ts → Generate tests for a specific file
/test --e2e → Generate Playwright e2e tests for changed files
/test --run → Run existing tests ({commands.test})
| Step | ID | Required | Notes |
|---|---|---|---|
| 1 | run-shortcut | — | --run flag only, early exit |
| 2 | identify-targets | ✓ | — |
| 3 | read-standards | ✓ | — |
| 4 | check-coverage | ✓ | — |
| 5 | generate-tests | ✓ | — |
| 6 | approval | ✓ | — |
| 7 | write-and-verify | ✓ | retry 1 |
--run Shortcut--run ⇒ {commands.test} → report results → stop.
BASE=$(git branch -r | grep -q 'origin/staging' && echo staging || echo main)
git diff ${BASE}...HEAD --name-only
Include: .ts, .tsx. Exclude: *.config.ts, *.d.ts, *.test.*, *.spec.*, files with no exports.
Specific file arg ⇒ use directly. ¬testable τ ⇒ inform + stop.
Read Σ before generating — contains framework config, AAA requirements, mocking strategies, coverage targets.
Glob *.test.ts / *.spec.ts near τ → read 1–2 examples → extract: describe/it nesting, mock approach, assertion style, naming.
Framework: Vitest on Bun. Always import explicitly:
import { describe, it, expect, vi } from 'vitest'
Bun compat constraints:
| Avoid | Use instead |
|---|---|
vi.mocked(fn) | fn as ReturnType<typeof vi.fn> |
vi.stubGlobal('fetch', mock) | globalThis.fetch = mock as typeof fetch |
vi.stubGlobal('Bun', {...}) | vi.spyOn(Bun, 'spawn').mockImplementation(...) |
vi.restoreAllMocks() in beforeEach | vi.clearAllMocks() |
Mock factory hoisting: Bun validates vi.mock factories against real module at hoist time. Side-effectful imports run before process.env assignments. Fix: vi.mock('../../shared/config', factory) to intercept directly.
∀ τ → check for π. ∃ π ⇒ read, compare with source exports, offer to add missing coverage (¬overwrite). ¬π ⇒ generate full test file.
∀ τ:
it('should return user by id', () => {
// Arrange
const userId = 'abc-123'
// Act
const result = getUser(userId)
// Assert
expect(result).toBeDefined()
})
login.ts → login.test.ts→ DP(A) Approve and write all | Approve with modifications | Skip specific files ¬write without approval.
∀ approved τ: write via Write tool → {commands.test} {test_file_path} → report pass/fail.
∃ failures ⇒ → DP(A) show failing test + error → propose fix → re-run.
--e2e)Check Playwright:
bunx playwright --version 2>/dev/null
¬installed ⇒ inform install command for {package_manager}:
bun add -d @playwright/test && bunx playwright installpnpm add -D @playwright/test && pnpm exec playwright installnpm install --save-dev @playwright/test && npx playwright installyarn add --dev @playwright/test && yarn playwright install
Stop (¬install deps).E2E dir: {frontend.path}/e2e/ (fall back to e2e/ if {frontend.path} not set).
Check existing patterns first. Name: {feature}.spec.ts.
Follow approval + verification flow (Steps 6–7).
∃ page objects in {frontend.path}/e2e/ → follow them.
// e2e/pages/login.page.ts
import { type Page, type Locator } from '@playwright/test'
export class LoginPage {
readonly emailInput: Locator
readonly passwordInput: Locator
readonly submitButton: Locator
constructor(readonly page: Page) {
this.emailInput = page.getByLabel('Email')
this.passwordInput = page.getByLabel('Password')
this.submitButton = page.getByRole('button', { name: 'Sign in' })
}
async goto() { await this.page.goto('/login') }
async login(email: string, password: string) {
await this.emailInput.fill(email)
await this.passwordInput.fill(password)
await this.submitButton.click()
}
}
// e2e/auth/login.spec.ts
import { test, expect } from '@playwright/test'
import { LoginPage } from '../pages/login.page'
test.describe('Login flow', () => {
test('should login with valid credentials', async ({ page }) => {
const loginPage = new LoginPage(page)
await loginPage.goto()
await loginPage.login('user@example.com', 'password123')
await expect(page).toHaveURL('/dashboard')
})
})
Selectors: page.getByRole(), page.getByLabel(), page.getByText() (¬page.locator('css') unless no semantic alternative).
| Scenario | Behavior |
|---|---|
| File has no exports | Skip, inform user |
| Tests already exist | Offer to add missing coverage, ¬overwrite |
| Test framework not detected | → DP(B) which framework to use |
--run flag | Run {commands.test} and report only |
| React component | Generate component tests with appropriate render approach |
| File in monorepo package | Place tests relative to package, ¬root |
$ARGUMENTS