[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6G2Q6V2F7G03VAAF27FXPJR":3,"skill-same:01M6G2Q6V2F7G03VAAF27FXPJR":78},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":31,"publishedAt":49,"linkOnly":50,"markdownContent":51,"markdownBody":52,"frontMatter":53,"refName":55,"commitSha":56,"skillDirectory":57,"forksCount":58,"repositoryHtmlUrl":59,"repositoryHomepageUrl":6,"ownerHtmlUrl":60,"ownerBlogUrl":61,"ownerDescription":62,"updatedAt":63,"install":64,"resources":77},"01M6G2Q6V2F7G03VAAF27FXPJR","tdd-workflow",null,"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.","oabdelmaksoud\u002FAgention","oabdelmaksoud","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F50699149?v=4","01M6D5CVVN778ZCDP1WHS816SP","Omar Abdelmaksoud","01M6D8A4TE76V3DCSH3D94VG1V",2,"MIT","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",[18,23,26],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":27,"categoryName":28,"taxonomyType":29,"taxonomyTypeDesc":30},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48],"tdd","tdd workflow","workflow","test","e2e tests","development","code","integration","writing","e2e","refactoring","coverage","use","tests","driven","unit","with","2026-11-10 10:12:30",false,"---\nname: tdd-workflow\ndescription: 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.\norigin: ECC\n---\n\n# Test-Driven Development Workflow\n\nThis skill ensures all code development follows TDD principles with comprehensive test coverage.\n\n## When to Activate\n\n- Writing new features or functionality\n- Fixing bugs or issues\n- Refactoring existing code\n- Adding API endpoints\n- Creating new components\n\n## Core Principles\n\n### 1. Tests BEFORE Code\nALWAYS write tests first, then implement code to make tests pass.\n\n### 2. Coverage Requirements\n- Minimum 80% coverage (unit + integration + E2E)\n- All edge cases covered\n- Error scenarios tested\n- Boundary conditions verified\n\n### 3. Test Types\n\n#### Unit Tests\n- Individual functions and utilities\n- Component logic\n- Pure functions\n- Helpers and utilities\n\n#### Integration Tests\n- API endpoints\n- Database operations\n- Service interactions\n- External API calls\n\n#### E2E Tests (Playwright)\n- Critical user flows\n- Complete workflows\n- Browser automation\n- UI interactions\n\n## TDD Workflow Steps\n\n### Step 1: Write User Journeys\n```\nAs a [role], I want to [action], so that [benefit]\n\nExample:\nAs a user, I want to search for markets semantically,\nso that I can find relevant markets even without exact keywords.\n```\n\n### Step 2: Generate Test Cases\nFor each user journey, create comprehensive test cases:\n\n```typescript\ndescribe('Semantic Search', () => {\n  it('returns relevant markets for query', async () => {\n    \u002F\u002F Test implementation\n  })\n\n  it('handles empty query gracefully', async () => {\n    \u002F\u002F Test edge case\n  })\n\n  it('falls back to substring search when Redis unavailable', async () => {\n    \u002F\u002F Test fallback behavior\n  })\n\n  it('sorts results by similarity score', async () => {\n    \u002F\u002F Test sorting logic\n  })\n})\n```\n\n### Step 3: Run Tests (They Should Fail)\n```bash\nnpm test\n# Tests should fail - we haven't implemented yet\n```\n\n### Step 4: Implement Code\nWrite minimal code to make tests pass:\n\n```typescript\n\u002F\u002F Implementation guided by tests\nexport async function searchMarkets(query: string) {\n  \u002F\u002F Implementation here\n}\n```\n\n### Step 5: Run Tests Again\n```bash\nnpm test\n# Tests should now pass\n```\n\n### Step 6: Refactor\nImprove code quality while keeping tests green:\n- Remove duplication\n- Improve naming\n- Optimize performance\n- Enhance readability\n\n### Step 7: Verify Coverage\n```bash\nnpm run test:coverage\n# Verify 80%+ coverage achieved\n```\n\n## Testing Patterns\n\n### Unit Test Pattern (Jest\u002FVitest)\n```typescript\nimport { render, screen, fireEvent } from '@testing-library\u002Freact'\nimport { Button } from '.\u002FButton'\n\ndescribe('Button Component', () => {\n  it('renders with correct text', () => {\n    render(\u003CButton>Click me\u003C\u002FButton>)\n    expect(screen.getByText('Click me')).toBeInTheDocument()\n  })\n\n  it('calls onClick when clicked', () => {\n    const handleClick = jest.fn()\n    render(\u003CButton onClick={handleClick}>Click\u003C\u002FButton>)\n\n    fireEvent.click(screen.getByRole('button'))\n\n    expect(handleClick).toHaveBeenCalledTimes(1)\n  })\n\n  it('is disabled when disabled prop is true', () => {\n    render(\u003CButton disabled>Click\u003C\u002FButton>)\n    expect(screen.getByRole('button')).toBeDisabled()\n  })\n})\n```\n\n### API Integration Test Pattern\n```typescript\nimport { NextRequest } from 'next\u002Fserver'\nimport { GET } from '.\u002Froute'\n\ndescribe('GET \u002Fapi\u002Fmarkets', () => {\n  it('returns markets successfully', async () => {\n    const request = new NextRequest('http:\u002F\u002Flocalhost\u002Fapi\u002Fmarkets')\n    const response = await GET(request)\n    const data = await response.json()\n\n    expect(response.status).toBe(200)\n    expect(data.success).toBe(true)\n    expect(Array.isArray(data.data)).toBe(true)\n  })\n\n  it('validates query parameters', async () => {\n    const request = new NextRequest('http:\u002F\u002Flocalhost\u002Fapi\u002Fmarkets?limit=invalid')\n    const response = await GET(request)\n\n    expect(response.status).toBe(400)\n  })\n\n  it('handles database errors gracefully', async () => {\n    \u002F\u002F Mock database failure\n    const request = new NextRequest('http:\u002F\u002Flocalhost\u002Fapi\u002Fmarkets')\n    \u002F\u002F Test error handling\n  })\n})\n```\n\n### E2E Test Pattern (Playwright)\n```typescript\nimport { test, expect } from '@playwright\u002Ftest'\n\ntest('user can search and filter markets', async ({ page }) => {\n  \u002F\u002F Navigate to markets page\n  await page.goto('\u002F')\n  await page.click('a[href=\"\u002Fmarkets\"]')\n\n  \u002F\u002F Verify page loaded\n  await expect(page.locator('h1')).toContainText('Markets')\n\n  \u002F\u002F Search for markets\n  await page.fill('input[placeholder=\"Search markets\"]', 'election')\n\n  \u002F\u002F Wait for debounce and results\n  await page.waitForTimeout(600)\n\n  \u002F\u002F Verify search results displayed\n  const results = page.locator('[data-testid=\"market-card\"]')\n  await expect(results).toHaveCount(5, { timeout: 5000 })\n\n  \u002F\u002F Verify results contain search term\n  const firstResult = results.first()\n  await expect(firstResult).toContainText('election', { ignoreCase: true })\n\n  \u002F\u002F Filter by status\n  await page.click('button:has-text(\"Active\")')\n\n  \u002F\u002F Verify filtered results\n  await expect(results).toHaveCount(3)\n})\n\ntest('user can create a new market', async ({ page }) => {\n  \u002F\u002F Login first\n  await page.goto('\u002Fcreator-dashboard')\n\n  \u002F\u002F Fill market creation form\n  await page.fill('input[name=\"name\"]', 'Test Market')\n  await page.fill('textarea[name=\"description\"]', 'Test description')\n  await page.fill('input[name=\"endDate\"]', '2025-12-31')\n\n  \u002F\u002F Submit form\n  await page.click('button[type=\"submit\"]')\n\n  \u002F\u002F Verify success message\n  await expect(page.locator('text=Market created successfully')).toBeVisible()\n\n  \u002F\u002F Verify redirect to market page\n  await expect(page).toHaveURL(\u002F\\\u002Fmarkets\\\u002Ftest-market\u002F)\n})\n```\n\n## Test File Organization\n\n```\nsrc\u002F\n├── components\u002F\n│   ├── Button\u002F\n│   │   ├── Button.tsx\n│   │   ├── Button.test.tsx          # Unit tests\n│   │   └── Button.stories.tsx       # Storybook\n│   └── MarketCard\u002F\n│       ├── MarketCard.tsx\n│       └── MarketCard.test.tsx\n├── app\u002F\n│   └── api\u002F\n│       └── markets\u002F\n│           ├── route.ts\n│           └── route.test.ts         # Integration tests\n└── e2e\u002F\n    ├── markets.spec.ts               # E2E tests\n    ├── trading.spec.ts\n    └── auth.spec.ts\n```\n\n## Mocking External Services\n\n### Supabase Mock\n```typescript\njest.mock('@\u002Flib\u002Fsupabase', () => ({\n  supabase: {\n    from: jest.fn(() => ({\n      select: jest.fn(() => ({\n        eq: jest.fn(() => Promise.resolve({\n          data: [{ id: 1, name: 'Test Market' }],\n          error: null\n        }))\n      }))\n    }))\n  }\n}))\n```\n\n### Redis Mock\n```typescript\njest.mock('@\u002Flib\u002Fredis', () => ({\n  searchMarketsByVector: jest.fn(() => Promise.resolve([\n    { slug: 'test-market', similarity_score: 0.95 }\n  ])),\n  checkRedisHealth: jest.fn(() => Promise.resolve({ connected: true }))\n}))\n```\n\n### OpenAI Mock\n```typescript\njest.mock('@\u002Flib\u002Fopenai', () => ({\n  generateEmbedding: jest.fn(() => Promise.resolve(\n    new Array(1536).fill(0.1) \u002F\u002F Mock 1536-dim embedding\n  ))\n}))\n```\n\n## Test Coverage Verification\n\n### Run Coverage Report\n```bash\nnpm run test:coverage\n```\n\n### Coverage Thresholds\n```json\n{\n  \"jest\": {\n    \"coverageThresholds\": {\n      \"global\": {\n        \"branches\": 80,\n        \"functions\": 80,\n        \"lines\": 80,\n        \"statements\": 80\n      }\n    }\n  }\n}\n```\n\n## Common Testing Mistakes to Avoid\n\n### ❌ WRONG: Testing Implementation Details\n```typescript\n\u002F\u002F Don't test internal state\nexpect(component.state.count).toBe(5)\n```\n\n### ✅ CORRECT: Test User-Visible Behavior\n```typescript\n\u002F\u002F Test what users see\nexpect(screen.getByText('Count: 5')).toBeInTheDocument()\n```\n\n### ❌ WRONG: Brittle Selectors\n```typescript\n\u002F\u002F Breaks easily\nawait page.click('.css-class-xyz')\n```\n\n### ✅ CORRECT: Semantic Selectors\n```typescript\n\u002F\u002F Resilient to changes\nawait page.click('button:has-text(\"Submit\")')\nawait page.click('[data-testid=\"submit-button\"]')\n```\n\n### ❌ WRONG: No Test Isolation\n```typescript\n\u002F\u002F Tests depend on each other\ntest('creates user', () => { \u002F* ... *\u002F })\ntest('updates same user', () => { \u002F* depends on previous test *\u002F })\n```\n\n### ✅ CORRECT: Independent Tests\n```typescript\n\u002F\u002F Each test sets up its own data\ntest('creates user', () => {\n  const user = createTestUser()\n  \u002F\u002F Test logic\n})\n\ntest('updates user', () => {\n  const user = createTestUser()\n  \u002F\u002F Update logic\n})\n```\n\n## Continuous Testing\n\n### Watch Mode During Development\n```bash\nnpm test -- --watch\n# Tests run automatically on file changes\n```\n\n### Pre-Commit Hook\n```bash\n# Runs before every commit\nnpm test && npm run lint\n```\n\n### CI\u002FCD Integration\n```yaml\n# GitHub Actions\n- name: Run Tests\n  run: npm test -- --coverage\n- name: Upload Coverage\n  uses: codecov\u002Fcodecov-action@v3\n```\n\n## Best Practices\n\n1. **Write Tests First** - Always TDD\n2. **One Assert Per Test** - Focus on single behavior\n3. **Descriptive Test Names** - Explain what's tested\n4. **Arrange-Act-Assert** - Clear test structure\n5. **Mock External Dependencies** - Isolate unit tests\n6. **Test Edge Cases** - Null, undefined, empty, large\n7. **Test Error Paths** - Not just happy paths\n8. **Keep Tests Fast** - Unit tests \u003C 50ms each\n9. **Clean Up After Tests** - No side effects\n10. **Review Coverage Reports** - Identify gaps\n\n## Success Metrics\n\n- 80%+ code coverage achieved\n- All tests passing (green)\n- No skipped or disabled tests\n- Fast test execution (\u003C 30s for unit tests)\n- E2E tests cover critical user flows\n- Tests catch bugs before production\n\n---\n\n**Remember**: Tests are not optional. They are the safety net that enables confident refactoring, rapid development, and production reliability.\n","# Test-Driven Development Workflow\n\nThis skill ensures all code development follows TDD principles with comprehensive test coverage.\n\n## When to Activate\n\n- Writing new features or functionality\n- Fixing bugs or issues\n- Refactoring existing code\n- Adding API endpoints\n- Creating new components\n\n## Core Principles\n\n### 1. Tests BEFORE Code\nALWAYS write tests first, then implement code to make tests pass.\n\n### 2. Coverage Requirements\n- Minimum 80% coverage (unit + integration + E2E)\n- All edge cases covered\n- Error scenarios tested\n- Boundary conditions verified\n\n### 3. Test Types\n\n#### Unit Tests\n- Individual functions and utilities\n- Component logic\n- Pure functions\n- Helpers and utilities\n\n#### Integration Tests\n- API endpoints\n- Database operations\n- Service interactions\n- External API calls\n\n#### E2E Tests (Playwright)\n- Critical user flows\n- Complete workflows\n- Browser automation\n- UI interactions\n\n## TDD Workflow Steps\n\n### Step 1: Write User Journeys\n```\nAs a [role], I want to [action], so that [benefit]\n\nExample:\nAs a user, I want to search for markets semantically,\nso that I can find relevant markets even without exact keywords.\n```\n\n### Step 2: Generate Test Cases\nFor each user journey, create comprehensive test cases:\n\n```typescript\ndescribe('Semantic Search', () => {\n  it('returns relevant markets for query', async () => {\n    \u002F\u002F Test implementation\n  })\n\n  it('handles empty query gracefully', async () => {\n    \u002F\u002F Test edge case\n  })\n\n  it('falls back to substring search when Redis unavailable', async () => {\n    \u002F\u002F Test fallback behavior\n  })\n\n  it('sorts results by similarity score', async () => {\n    \u002F\u002F Test sorting logic\n  })\n})\n```\n\n### Step 3: Run Tests (They Should Fail)\n```bash\nnpm test\n# Tests should fail - we haven't implemented yet\n```\n\n### Step 4: Implement Code\nWrite minimal code to make tests pass:\n\n```typescript\n\u002F\u002F Implementation guided by tests\nexport async function searchMarkets(query: string) {\n  \u002F\u002F Implementation here\n}\n```\n\n### Step 5: Run Tests Again\n```bash\nnpm test\n# Tests should now pass\n```\n\n### Step 6: Refactor\nImprove code quality while keeping tests green:\n- Remove duplication\n- Improve naming\n- Optimize performance\n- Enhance readability\n\n### Step 7: Verify Coverage\n```bash\nnpm run test:coverage\n# Verify 80%+ coverage achieved\n```\n\n## Testing Patterns\n\n### Unit Test Pattern (Jest\u002FVitest)\n```typescript\nimport { render, screen, fireEvent } from '@testing-library\u002Freact'\nimport { Button } from '.\u002FButton'\n\ndescribe('Button Component', () => {\n  it('renders with correct text', () => {\n    render(\u003CButton>Click me\u003C\u002FButton>)\n    expect(screen.getByText('Click me')).toBeInTheDocument()\n  })\n\n  it('calls onClick when clicked', () => {\n    const handleClick = jest.fn()\n    render(\u003CButton onClick={handleClick}>Click\u003C\u002FButton>)\n\n    fireEvent.click(screen.getByRole('button'))\n\n    expect(handleClick).toHaveBeenCalledTimes(1)\n  })\n\n  it('is disabled when disabled prop is true', () => {\n    render(\u003CButton disabled>Click\u003C\u002FButton>)\n    expect(screen.getByRole('button')).toBeDisabled()\n  })\n})\n```\n\n### API Integration Test Pattern\n```typescript\nimport { NextRequest } from 'next\u002Fserver'\nimport { GET } from '.\u002Froute'\n\ndescribe('GET \u002Fapi\u002Fmarkets', () => {\n  it('returns markets successfully', async () => {\n    const request = new NextRequest('http:\u002F\u002Flocalhost\u002Fapi\u002Fmarkets')\n    const response = await GET(request)\n    const data = await response.json()\n\n    expect(response.status).toBe(200)\n    expect(data.success).toBe(true)\n    expect(Array.isArray(data.data)).toBe(true)\n  })\n\n  it('validates query parameters', async () => {\n    const request = new NextRequest('http:\u002F\u002Flocalhost\u002Fapi\u002Fmarkets?limit=invalid')\n    const response = await GET(request)\n\n    expect(response.status).toBe(400)\n  })\n\n  it('handles database errors gracefully', async () => {\n    \u002F\u002F Mock database failure\n    const request = new NextRequest('http:\u002F\u002Flocalhost\u002Fapi\u002Fmarkets')\n    \u002F\u002F Test error handling\n  })\n})\n```\n\n### E2E Test Pattern (Playwright)\n```typescript\nimport { test, expect } from '@playwright\u002Ftest'\n\ntest('user can search and filter markets', async ({ page }) => {\n  \u002F\u002F Navigate to markets page\n  await page.goto('\u002F')\n  await page.click('a[href=\"\u002Fmarkets\"]')\n\n  \u002F\u002F Verify page loaded\n  await expect(page.locator('h1')).toContainText('Markets')\n\n  \u002F\u002F Search for markets\n  await page.fill('input[placeholder=\"Search markets\"]', 'election')\n\n  \u002F\u002F Wait for debounce and results\n  await page.waitForTimeout(600)\n\n  \u002F\u002F Verify search results displayed\n  const results = page.locator('[data-testid=\"market-card\"]')\n  await expect(results).toHaveCount(5, { timeout: 5000 })\n\n  \u002F\u002F Verify results contain search term\n  const firstResult = results.first()\n  await expect(firstResult).toContainText('election', { ignoreCase: true })\n\n  \u002F\u002F Filter by status\n  await page.click('button:has-text(\"Active\")')\n\n  \u002F\u002F Verify filtered results\n  await expect(results).toHaveCount(3)\n})\n\ntest('user can create a new market', async ({ page }) => {\n  \u002F\u002F Login first\n  await page.goto('\u002Fcreator-dashboard')\n\n  \u002F\u002F Fill market creation form\n  await page.fill('input[name=\"name\"]', 'Test Market')\n  await page.fill('textarea[name=\"description\"]', 'Test description')\n  await page.fill('input[name=\"endDate\"]', '2025-12-31')\n\n  \u002F\u002F Submit form\n  await page.click('button[type=\"submit\"]')\n\n  \u002F\u002F Verify success message\n  await expect(page.locator('text=Market created successfully')).toBeVisible()\n\n  \u002F\u002F Verify redirect to market page\n  await expect(page).toHaveURL(\u002F\\\u002Fmarkets\\\u002Ftest-market\u002F)\n})\n```\n\n## Test File Organization\n\n```\nsrc\u002F\n├── components\u002F\n│   ├── Button\u002F\n│   │   ├── Button.tsx\n│   │   ├── Button.test.tsx          # Unit tests\n│   │   └── Button.stories.tsx       # Storybook\n│   └── MarketCard\u002F\n│       ├── MarketCard.tsx\n│       └── MarketCard.test.tsx\n├── app\u002F\n│   └── api\u002F\n│       └── markets\u002F\n│           ├── route.ts\n│           └── route.test.ts         # Integration tests\n└── e2e\u002F\n    ├── markets.spec.ts               # E2E tests\n    ├── trading.spec.ts\n    └── auth.spec.ts\n```\n\n## Mocking External Services\n\n### Supabase Mock\n```typescript\njest.mock('@\u002Flib\u002Fsupabase', () => ({\n  supabase: {\n    from: jest.fn(() => ({\n      select: jest.fn(() => ({\n        eq: jest.fn(() => Promise.resolve({\n          data: [{ id: 1, name: 'Test Market' }],\n          error: null\n        }))\n      }))\n    }))\n  }\n}))\n```\n\n### Redis Mock\n```typescript\njest.mock('@\u002Flib\u002Fredis', () => ({\n  searchMarketsByVector: jest.fn(() => Promise.resolve([\n    { slug: 'test-market', similarity_score: 0.95 }\n  ])),\n  checkRedisHealth: jest.fn(() => Promise.resolve({ connected: true }))\n}))\n```\n\n### OpenAI Mock\n```typescript\njest.mock('@\u002Flib\u002Fopenai', () => ({\n  generateEmbedding: jest.fn(() => Promise.resolve(\n    new Array(1536).fill(0.1) \u002F\u002F Mock 1536-dim embedding\n  ))\n}))\n```\n\n## Test Coverage Verification\n\n### Run Coverage Report\n```bash\nnpm run test:coverage\n```\n\n### Coverage Thresholds\n```json\n{\n  \"jest\": {\n    \"coverageThresholds\": {\n      \"global\": {\n        \"branches\": 80,\n        \"functions\": 80,\n        \"lines\": 80,\n        \"statements\": 80\n      }\n    }\n  }\n}\n```\n\n## Common Testing Mistakes to Avoid\n\n### ❌ WRONG: Testing Implementation Details\n```typescript\n\u002F\u002F Don't test internal state\nexpect(component.state.count).toBe(5)\n```\n\n### ✅ CORRECT: Test User-Visible Behavior\n```typescript\n\u002F\u002F Test what users see\nexpect(screen.getByText('Count: 5')).toBeInTheDocument()\n```\n\n### ❌ WRONG: Brittle Selectors\n```typescript\n\u002F\u002F Breaks easily\nawait page.click('.css-class-xyz')\n```\n\n### ✅ CORRECT: Semantic Selectors\n```typescript\n\u002F\u002F Resilient to changes\nawait page.click('button:has-text(\"Submit\")')\nawait page.click('[data-testid=\"submit-button\"]')\n```\n\n### ❌ WRONG: No Test Isolation\n```typescript\n\u002F\u002F Tests depend on each other\ntest('creates user', () => { \u002F* ... *\u002F })\ntest('updates same user', () => { \u002F* depends on previous test *\u002F })\n```\n\n### ✅ CORRECT: Independent Tests\n```typescript\n\u002F\u002F Each test sets up its own data\ntest('creates user', () => {\n  const user = createTestUser()\n  \u002F\u002F Test logic\n})\n\ntest('updates user', () => {\n  const user = createTestUser()\n  \u002F\u002F Update logic\n})\n```\n\n## Continuous Testing\n\n### Watch Mode During Development\n```bash\nnpm test -- --watch\n# Tests run automatically on file changes\n```\n\n### Pre-Commit Hook\n```bash\n# Runs before every commit\nnpm test && npm run lint\n```\n\n### CI\u002FCD Integration\n```yaml\n# GitHub Actions\n- name: Run Tests\n  run: npm test -- --coverage\n- name: Upload Coverage\n  uses: codecov\u002Fcodecov-action@v3\n```\n\n## Best Practices\n\n1. **Write Tests First** - Always TDD\n2. **One Assert Per Test** - Focus on single behavior\n3. **Descriptive Test Names** - Explain what's tested\n4. **Arrange-Act-Assert** - Clear test structure\n5. **Mock External Dependencies** - Isolate unit tests\n6. **Test Edge Cases** - Null, undefined, empty, large\n7. **Test Error Paths** - Not just happy paths\n8. **Keep Tests Fast** - Unit tests \u003C 50ms each\n9. **Clean Up After Tests** - No side effects\n10. **Review Coverage Reports** - Identify gaps\n\n## Success Metrics\n\n- 80%+ code coverage achieved\n- All tests passing (green)\n- No skipped or disabled tests\n- Fast test execution (\u003C 30s for unit tests)\n- E2E tests cover critical user flows\n- Tests catch bugs before production\n\n---\n\n**Remember**: Tests are not optional. They are the safety net that enables confident refactoring, rapid development, and production reliability.\n",{"name":5,"origin":54,"description":7},"ECC","main","a318f48de3c5718e8ea2e9f6fae7790e8a759e85","upstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Ftdd-workflow",0,"https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fo-abdelmaksoud\u002F","Full-Stack Engineer | AI Systems Architect | Building autonomous multi-agent systems","2026-03-08 21:23:03",{"source":8,"skillName":5,"commands":65,"prompt":75,"zipAvailable":76},[66,69,72],{"tool":67,"command":68},"npx","npx skills add oabdelmaksoud\u002FAgention --skill tdd-workflow",{"tool":70,"command":71},"bunx","bunx skills add oabdelmaksoud\u002FAgention --skill tdd-workflow",{"tool":73,"command":74},"pnpm","pnpm dlx skills add oabdelmaksoud\u002FAgention --skill tdd-workflow","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",true,[],[79,100,113,139,159,171],{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":88,"publishedAt":49},"01M6G2QFCBNBYAJF2KTK85G9A6","visa-doc-translate","Translate visa application documents (images) to English and create a bilingual PDF with original and translation","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fvisa-doc-translate\u002FSKILL.md",[85],{"categoryNo":86,"categoryName":87,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000002","文档处理",[89,90,91,48,92,93,94,95,96,97,98,99],"translate","doc","visa doc translate","bilingual","english","application","translation","PDF","images","documents","create",{"skillNo":101,"name":102,"nameZh":6,"description":103,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":49},"01M6G2QB09TSK6BY4ME5X20EVQ","verification-loop","A comprehensive verification system for Claude Code sessions.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fverification-loop\u002FSKILL.md",[],[107,108,109,38,110,111,112],"verification","loop","verification loop","sessions","claude code sessions","system",{"skillNo":114,"name":115,"nameZh":6,"description":116,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":119,"publishedAt":49},"01M6G2Q359YJRWAR2PFCEQAXF3","swiftui-patterns","SwiftUI architecture patterns, state management with @Observable, view composition, navigation, performance optimization, and modern iOS\u002FmacOS UI best practices.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswiftui-patterns\u002FSKILL.md",[],[120,121,122,123,124,125,126,127,128,129,48,130,131,132,133,134,135,136,137,138],"swiftui patterns","swiftui","patterns","navigation","swiftui architecture","management","view","performance optimization","Composition","architecture patterns","ios","macos","performance","architecture","state management","best practices","state","ui","Optimization",{"skillNo":140,"name":141,"nameZh":6,"description":142,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":143,"categories":144,"keywords":146,"publishedAt":49},"01M6G2PY8B2FWZTWPZ84H83Y7C","swift-protocol-di-testing","Protocol-based dependency injection for testable Swift code — mock file system, network, and external APIs using focused protocols and Swift Testing.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-protocol-di-testing\u002FSKILL.md",[145],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[147,148,149,150,151,38,152,153,154,112,155,156,157,158],"swift protocol di testing","protocol","swift","testing","injection","protocols","file","network","dependency","swift testing","dependency injection","mock",{"skillNo":160,"name":161,"nameZh":6,"description":162,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":163,"categories":164,"keywords":165,"publishedAt":49},"01M6G2PSCN2GXV9FFZDRRRWVB6","swift-concurrency-6-2","Swift 6.2 Approachable Concurrency — single-threaded by default, @concurrent for explicit background offloading, isolated conformances for main actor types.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-concurrency-6-2\u002FSKILL.md",[],[166,167,149,168,169,55,170],"swift concurrency 6 2","concurrency","swift concurrency","default","types",{"skillNo":172,"name":173,"nameZh":6,"description":174,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":175,"categories":176,"keywords":180,"publishedAt":49},"01M6G2PMSS5S9ZW0YM7X2BAP8D","swift-actor-persistence","Thread-safe data persistence in Swift using actors — in-memory cache with file-backed storage, eliminating data races by design.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-actor-persistence\u002FSKILL.md",[177],{"categoryNo":178,"categoryName":179,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",[149,181,182,183,184,185,186,153,187,188,48],"swift actor persistence","persistence","design","safe","memory","storage","cache","data"]