From ftitos-claude-code
Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.
npx claudepluginhub nassimbf/ftitos-claude-codeThis skill uses the workspace's default tool permissions.
This skill ensures all code development follows TDD principles with comprehensive test coverage.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Share bugs, ideas, or general feedback.
This skill ensures all code development follows TDD principles with comprehensive test coverage.
ALWAYS write tests first, then implement code to make tests pass.
HEAD on the active branch and belongs to the current task sequenceAs a [role], I want to [action], so that [benefit]
Example:
As a user, I want to search for items semantically,
so that I can find relevant results even without exact keywords.
For each user journey, create comprehensive test cases:
describe('Semantic Search', () => {
it('returns relevant results for query', async () => {
// Test implementation
})
it('handles empty query gracefully', async () => {
// Test edge case
})
it('falls back to substring search when cache unavailable', async () => {
// Test fallback behavior
})
it('sorts results by similarity score', async () => {
// Test sorting logic
})
})
npm test
# Tests should fail - we haven't implemented yet
This step is mandatory and is the RED gate for all production changes.
Before modifying business logic or other production code, you must verify a valid RED state via one of these paths:
A test that was only written but not compiled and executed does not count as RED.
Do not edit production code until this RED state is confirmed.
If the repository is under Git, create a checkpoint commit immediately after this stage is validated.
Write minimal code to make tests pass:
// Implementation guided by tests
export async function searchItems(query: string) {
// Implementation here
}
If the repository is under Git, stage the minimal fix now but defer the checkpoint commit until GREEN is validated in Step 5.
npm test
# Tests should now pass
Rerun the same relevant test target after the fix and confirm the previously failing test is now GREEN.
Only after a valid GREEN result may you proceed to refactor.
If the repository is under Git, create a checkpoint commit immediately after GREEN is validated.
Improve code quality while keeping tests green:
If the repository is under Git, create a checkpoint commit immediately after refactoring is complete and tests remain green.
npm run test:coverage
# Verify 80%+ coverage achieved
import { render, screen, fireEvent } from '@testing-library/react'
import { Button } from './Button'
describe('Button Component', () => {
it('renders with correct text', () => {
render(<Button>Click me</Button>)
expect(screen.getByText('Click me')).toBeInTheDocument()
})
it('calls onClick when clicked', () => {
const handleClick = jest.fn()
render(<Button onClick={handleClick}>Click</Button>)
fireEvent.click(screen.getByRole('button'))
expect(handleClick).toHaveBeenCalledTimes(1)
})
it('is disabled when disabled prop is true', () => {
render(<Button disabled>Click</Button>)
expect(screen.getByRole('button')).toBeDisabled()
})
})
describe('GET /api/items', () => {
it('returns items successfully', async () => {
const request = new Request('http://localhost/api/items')
const response = await GET(request)
const data = await response.json()
expect(response.status).toBe(200)
expect(data.success).toBe(true)
expect(Array.isArray(data.data)).toBe(true)
})
it('validates query parameters', async () => {
const request = new Request('http://localhost/api/items?limit=invalid')
const response = await GET(request)
expect(response.status).toBe(400)
})
it('handles database errors gracefully', async () => {
// Mock database failure
// Test error handling
})
})
import { test, expect } from '@playwright/test'
test('user can search and filter items', async ({ page }) => {
await page.goto('/')
await page.click('a[href="/items"]')
await expect(page.locator('h1')).toContainText('Items')
await page.fill('input[placeholder="Search"]', 'test query')
await page.waitForTimeout(600)
const results = page.locator('[data-testid="item-card"]')
await expect(results).toHaveCount(5, { timeout: 5000 })
})
src/
├── components/
│ ├── Button/
│ │ ├── Button.tsx
│ │ ├── Button.test.tsx # Unit tests
│ │ └── Button.stories.tsx # Storybook
├── app/
│ └── api/
│ └── items/
│ ├── route.ts
│ └── route.test.ts # Integration tests
└── e2e/
├── items.spec.ts # E2E tests
└── auth.spec.ts
// Don't test internal state
expect(component.state.count).toBe(5)
// Test what users see
expect(screen.getByText('Count: 5')).toBeInTheDocument()
await page.click('.css-class-xyz')
await page.click('button:has-text("Submit")')
await page.click('[data-testid="submit-button"]')
test('creates user', () => { /* ... */ })
test('updates same user', () => { /* depends on previous test */ })
test('creates user', () => {
const user = createTestUser()
// Test logic
})
test('updates user', () => {
const user = createTestUser()
// Update logic
})
Remember: Tests are not optional. They are the safety net that enables confident refactoring, rapid development, and production reliability.