smithery/codename-co

tdd-testing

Guide for Test-Driven Development in the DEVS platform. Use this when asked to write tests, implement TDD, or add test coverage for lib/ and stores/ code.

Installation

$ npx skills add smithery/codename-co --skill tdd-testing

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/codename-co.

npx skills add smithery/codename-co

Browse all from smithery/codename-co

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 8,300 B
  • docs SUMMARY.md 173 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Test-Driven Development (TDD) for DEVS

TDD is mandatory for all code in src/lib/ and src/stores/. This ensures LLMs can safely enhance features without causing regressions.

TDD Workflow

  1. Red: Write a failing test that describes the expected behavior
  2. Green: Write the minimum code necessary to make the test pass
  3. Refactor: Improve the code while keeping tests green
  4. Verify: Run npm run test:coverage before committing

Test File Structure

Tests mirror the source structure:

  • src/lib/orchestrator.tssrc/test/lib/orchestrator.test.ts
  • src/stores/agentStore.tssrc/test/stores/agentStore.test.ts
  • src/components/AgentCard.tsxsrc/test/components/AgentCard.test.tsx

Coverage Requirements

Category Target Priority
src/lib/** 60%+ 🔴 Critical
src/stores/** 60%+ 🔴 Critical
src/components/** 30%+ 🟡 Medium
src/pages/** 20%+ 🟢 Low

Test Commands

# Run tests in watch mode (recommended during development)
npm run test:watch

# Run all tests once
npm run test:run

# Run with coverage report
npm run test:coverage

# Run E2E tests
npm run test:e2e

Unit Test Template

import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'

// Import the module under test
import { myFunction, MyClass } from '@/lib/my-module'

// Mock dependencies
vi.mock('@/lib/db', () => ({
  db: {
    entities: {
      toArray: vi.fn(),
      add: vi.fn(),
      update: vi.fn(),
      delete: vi.fn(),
    },
  },
}))

describe('myFunction', () => {
  beforeEach(() => {
    // Reset mocks and state before each test
    vi.clearAllMocks()
  })

  afterEach(() => {
    // Cleanup after each test
  })

  describe('when given valid input', () => {
    it('should return expected result', () => {
      const result = myFunction('valid input')
      expect(result).toBe('expected output')
    })

    it('should handle edge cases', () => {
      const result = myFunction('')
      expect(result).toBe('')
    })
  })

  describe('when given invalid input', () => {
    it('should throw an error', () => {
      expect(() => myFunction(null as any)).toThrow('Invalid input')
    })
  })
})

describe('MyClass', () => {
  let instance: MyClass

  beforeEach(() => {
    instance = new MyClass()
  })

  it('should initialize with default values', () => {
    expect(instance.value).toBe(0)
  })

  it('should update value correctly', () => {
    instance.setValue(42)
    expect(instance.value).toBe(42)
  })
})

Store Test Template

import { describe, it, expect, beforeEach, vi } from 'vitest'
import { useEntityStore } from '@/stores/entityStore'
import { db } from '@/lib/db'

// Mock the database
vi.mock('@/lib/db', () => ({
  db: {
    entities: {
      toArray: vi.fn(),
      add: vi.fn(),
      update: vi.fn(),
      delete: vi.fn(),
      get: vi.fn(),
    },
  },
}))

describe('entityStore', () => {
  beforeEach(() => {
    // Reset store state
    useEntityStore.setState({
      entities: [],
      isLoading: false,
      error: null,
    })
    vi.clearAllMocks()
  })

  describe('loadEntities', () => {
    it('should load entities from database', async () => {
      const mockEntities = [
        { id: '1', name: 'Entity 1' },
        { id: '2', name: 'Entity 2' },
      ]
      vi.mocked(db.entities.toArray).mockResolvedValue(mockEntities)

      await useEntityStore.getState().loadEntities()

      expect(useEntityStore.getState().entities).toEqual(mockEntities)
      expect(useEntityStore.getState().isLoading).toBe(false)
    })

    it('should handle errors gracefully', async () => {
      vi.mocked(db.entities.toArray).mockRejectedValue(new Error('DB error'))

      await useEntityStore.getState().loadEntities()

      expect(useEntityStore.getState().error).toBe('DB error')
      expect(useEntityStore.getState().isLoading).toBe(false)
    })
  })

  describe('createEntity', () => {
    it('should create entity with generated id', async () => {
      vi.mocked(db.entities.add).mockResolvedValue('new-id')

      const result = await useEntityStore.getState().createEntity({
        name: 'New Entity',
      })

      expect(result).toHaveProperty('id')
      expect(result.name).toBe('New Entity')
      expect(db.entities.add).toHaveBeenCalledWith(
        expect.objectContaining({
          name: 'New Entity',
        }),
      )
    })
  })

  describe('getEntityById', () => {
    it('should return entity when found', () => {
      useEntityStore.setState({
        entities: [{ id: '1', name: 'Test' }],
      })

      const result = useEntityStore.getState().getEntityById('1')
      expect(result).toEqual({ id: '1', name: 'Test' })
    })

    it('should return undefined when not found', () => {
      const result = useEntityStore.getState().getEntityById('nonexistent')
      expect(result).toBeUndefined()
    })
  })
})

Component Test Template

import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { describe, it, expect, vi } from 'vitest'
import { MyComponent } from '@/components/MyComponent'

// Mock translations
vi.mock('react-i18next', () => ({
  useTranslation: () => ({
    t: (key: string) => key,
  }),
}))

describe('MyComponent', () => {
  it('renders correctly with required props', () => {
    render(<MyComponent title="Test Title" />)
    expect(screen.getByText('Test Title')).toBeInTheDocument()
  })

  it('calls onAction when button is clicked', async () => {
    const mockOnAction = vi.fn()
    render(<MyComponent title="Test" onAction={mockOnAction} />)

    fireEvent.click(screen.getByRole('button'))

    await waitFor(() => {
      expect(mockOnAction).toHaveBeenCalledTimes(1)
    })
  })

  it('disables button when isDisabled is true', () => {
    render(<MyComponent title="Test" isDisabled />)
    expect(screen.getByRole('button')).toBeDisabled()
  })

  it('renders children correctly', () => {
    render(
      <MyComponent title="Test">
        <span>Child content</span>
      </MyComponent>
    )
    expect(screen.getByText('Child content')).toBeInTheDocument()
  })
})

Async Testing Patterns

import { describe, it, expect, vi } from 'vitest'

describe('async operations', () => {
  // Testing async functions
  it('should resolve with expected value', async () => {
    const result = await asyncFunction()
    expect(result).toBe('expected')
  })

  // Testing rejected promises
  it('should reject with error', async () => {
    await expect(asyncFunction('invalid')).rejects.toThrow('Error message')
  })

  // Testing with fake timers
  it('should debounce calls', async () => {
    vi.useFakeTimers()
    const callback = vi.fn()

    debouncedFunction(callback)
    debouncedFunction(callback)
    debouncedFunction(callback)

    expect(callback).not.toHaveBeenCalled()

    vi.advanceTimersByTime(500)

    expect(callback).toHaveBeenCalledTimes(1)

    vi.useRealTimers()
  })
})

Mocking Patterns

// Mock module
vi.mock('@/lib/llm', () => ({
  LLMService: {
    chat: vi.fn().mockResolvedValue({ content: 'mocked response' }),
  },
}))

// Mock function
const mockFn = vi.fn()
mockFn.mockReturnValue('value')
mockFn.mockResolvedValue('async value')
mockFn.mockImplementation((x) => x * 2)

// Spy on existing function
const spy = vi.spyOn(object, 'method')
expect(spy).toHaveBeenCalledWith(expectedArgs)

// Mock crypto.randomUUID
vi.stubGlobal('crypto', {
  randomUUID: () => 'test-uuid-123',
})

Best Practices

  1. One assertion per test when possible, or related assertions
  2. Descriptive test names: it('should return null when user is not found')
  3. Arrange-Act-Assert pattern: Setup → Execute → Verify
  4. Isolate tests: Each test should be independent
  5. Test behavior, not implementation: Focus on what, not how
  6. Use meaningful test data: Avoid magic numbers/strings