[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71H79ZFS2WC1112B04NGJEK":3,"skill-same:01M71H79ZFS2WC1112B04NGJEK":66},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":25,"publishedAt":41,"linkOnly":42,"markdownContent":43,"markdownBody":44,"frontMatter":45,"refName":46,"commitSha":47,"skillDirectory":48,"forksCount":13,"repositoryHtmlUrl":49,"repositoryHomepageUrl":6,"ownerHtmlUrl":50,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":51,"install":52,"resources":65},"01M71H79ZFS2WC1112B04NGJEK","04-bun-test",null,"Bun built-in test runner — zero-config testing for Effect, React, and TypeScript projects","lambda-solver\u002Flambdabench-pro","lambda-solver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F279071046?v=4","01M71H55W2WK3PM6RRAY9JZWAJ","01M71H55WRT9XAFDAVACTCC2XP",0,"MIT","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Feffect-ts\u002Ftesting\u002F04-bun-test\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000009","前端开发",[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"test","bun test","bun","04 bun test","effect","projects","runner","ZeRO","for","testing","react","opencode","config","typescript","test runner","2026-11-10 10:12:30",false,"---\nname: 04-bun-test\ndescription: Bun built-in test runner — zero-config testing for Effect, React, and TypeScript projects\nlicense: MIT\ncompatibility: opencode\n---\n\n# Bun Test\n\n**Package**: Built into Bun (no installation needed)\n**Command**: `bun test`\n\nBun's built-in test runner replaces Vitest\u002FJest with zero configuration. Same API, faster execution, no extra dependencies.\n\n## Why bun:test over Vitest\n\n| Feature        | bun:test           | Vitest                    |\n| -------------- | ------------------ | ------------------------- |\n| Installation   | Built-in           | `npm i -D vitest`         |\n| Config file    | None needed        | `vitest.config.ts`        |\n| Startup        | Instant            | ~1-2s                     |\n| Effect support | Native             | Via plugin                |\n| DOM testing    | Requires happy-dom | Built-in via browser mode |\n\n**Rule of thumb**: Use `bun:test` for all logic\u002Fserver tests. Use Storybook for visual component inspection. Skip DOM-heavy component tests.\n\n## Basic Test\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\n\ndescribe(\"fmtModel\", () => {\n  test(\"strips openrouter\u002F prefix\", () => {\n    expect(fmtModel(\"openrouter\u002Fgoogle\u002Fgemini-2.5-pro\")).toBe(\"google\u002Fgemini-2.5-pro\");\n  });\n});\n```\n\n## Effect Tests\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { Effect } from \"effect\";\n\ndescribe(\"TaskService\", () => {\n  test(\"getTask returns cached task\", async () => {\n    const program = Effect.gen(function* () {\n      const svc = yield* TaskService;\n      return yield* svc.getTask(\"bool_not\");\n    });\n\n    const result = await Effect.runPromise(program.pipe(Effect.provide(TaskServiceLive)));\n\n    expect(result.id).toBe(\"bool_not\");\n  });\n});\n```\n\n## Async Tests\n\n```typescript\ntest(\"async operation\", async () => {\n  const result = await fetchData();\n  expect(result).toBeDefined();\n});\n```\n\n## Snapshots\n\n```typescript\ntest(\"snapshot comparison\", () => {\n  expect(data).toMatchSnapshot();\n});\n```\n\nUpdate snapshots: `bun test -u`\n\n## Skipping and TODO\n\n```typescript\ntest.skip(\"not ready yet\", () => { ... });\ntest.todo(\"implement this later\");\ntest.only(\"run only this\", () => { ... });\n```\n\n## Test Files\n\nBun automatically discovers:\n\n- `*.test.ts`\n- `*.test.tsx`\n- `*.spec.ts`\n- `*.spec.tsx`\n\n## React Component Testing\n\n**Philosophy**: Test logic, not DOM. Use Storybook for visual inspection.\n\n```typescript\n\u002F\u002F ❌ Don't test DOM rendering\nimport { render } from \"@testing-library\u002Freact\";\nconst { container } = render(\u003CBarChart pct={50} \u002F>);\nexpect(container.querySelector(\"span\")).toBeDefined();\n\n\u002F\u002F ✅ Test pure logic\nfunction getBarColor(pct: number): string {\n  if (pct >= 70) return \"green\";\n  if (pct >= 45) return \"blue\";\n  if (pct >= 20) return \"yellow\";\n  return \"red\";\n}\n\ndescribe(\"getBarColor\", () => {\n  test(\"green at 70+\", () => {\n    expect(getBarColor(70)).toBe(\"green\");\n    expect(getBarColor(100)).toBe(\"green\");\n  });\n\n  test(\"blue at 45-69\", () => {\n    expect(getBarColor(45)).toBe(\"blue\");\n    expect(getBarColor(69)).toBe(\"blue\");\n  });\n\n  test(\"yellow at 20-44\", () => {\n    expect(getBarColor(20)).toBe(\"yellow\");\n    expect(getBarColor(44)).toBe(\"yellow\");\n  });\n\n  test(\"red below 20\", () => {\n    expect(getBarColor(0)).toBe(\"red\");\n    expect(getBarColor(19)).toBe(\"red\");\n  });\n});\n```\n\n## Mocking\n\n```typescript\nimport { mock, spyOn } from \"bun:test\";\n\n\u002F\u002F Mock a function\nconst mockFn = mock((x: number) => x * 2);\nexpect(mockFn(5)).toBe(10);\nexpect(mockFn).toHaveBeenCalledTimes(1);\n\n\u002F\u002F Spy on module\nimport * as fs from \"node:fs\";\nconst readSpy = spyOn(fs, \"readFileSync\").mockReturnValue(\"test\");\n\n\u002F\u002F Restore\nreadSpy.mockRestore();\n```\n\n## Running Tests\n\n```bash\n# All tests\nbun test\n\n# Specific file\nbun test src\u002Flib\u002Ffmt.test.ts\n\n# Watch mode\nbun test --watch\n\n# Update snapshots\nbun test -u\n\n# Coverage\nbun test --coverage\n\n# Bail on first failure\nbun test --bail\n```\n\n## Package.json Scripts\n\n```json\n{\n  \"scripts\": {\n    \"test\": \"bun test\",\n    \"test:watch\": \"bun test --watch\",\n    \"test:coverage\": \"bun test --coverage\"\n  }\n}\n```\n\n## CI Integration\n\n```yaml\n# .github\u002Fworkflows\u002Ftest.yml\n- name: Run tests\n  run: bun test\n```\n\nNo config file needed. No setup files. Just `bun test`.\n\n## Comparison: When to Use What\n\n| Test Type         | Tool                 | Example                       |\n| ----------------- | -------------------- | ----------------------------- |\n| Pure functions    | `bun:test`           | `fmtModel()`, `getBarColor()` |\n| Effect services   | `bun:test`           | `TaskService.getTask()`       |\n| React logic       | `bun:test`           | Hook utilities, helpers       |\n| Visual appearance | Storybook            | Component fixtures            |\n| Browser behavior  | Manual QA            | Click flows, responsive       |\n| E2E API           | `bun:test` + `fetch` | HTTP endpoint tests           |\n\n## Migrating from Vitest\n\n1. Replace `import { ... } from \"vitest\"` with `import { ... } from \"bun:test\"`\n2. Replace `vi.fn()` with `mock()`\n3. Replace `vi.spyOn()` with `spyOn()`\n4. Remove `vitest.config.ts`\n5. Remove `@vitest\u002F*` dependencies\n6. Convert DOM tests to logic tests or Storybook fixtures\n7. Update package.json scripts\n\n## Anti-Patterns\n\n```typescript\n\u002F\u002F ❌ Testing implementation details\ntest(\"sets internal state\", () => { ... });\n\n\u002F\u002F ❌ Testing React DOM structure\ntest(\"has 3 divs\", () => { ... });\n\n\u002F\u002F ❌ Heavy mocking\nmock(\".\u002Fmodule\", () => ({ ... }));\n\n\u002F\u002F ✅ Test behavior\n\u002F\u002F ✅ Test pure logic\n\u002F\u002F ✅ Test public API\n\u002F\u002F ✅ Visual inspection in Storybook\n```\n","# Bun Test\n\n**Package**: Built into Bun (no installation needed)\n**Command**: `bun test`\n\nBun's built-in test runner replaces Vitest\u002FJest with zero configuration. Same API, faster execution, no extra dependencies.\n\n## Why bun:test over Vitest\n\n| Feature        | bun:test           | Vitest                    |\n| -------------- | ------------------ | ------------------------- |\n| Installation   | Built-in           | `npm i -D vitest`         |\n| Config file    | None needed        | `vitest.config.ts`        |\n| Startup        | Instant            | ~1-2s                     |\n| Effect support | Native             | Via plugin                |\n| DOM testing    | Requires happy-dom | Built-in via browser mode |\n\n**Rule of thumb**: Use `bun:test` for all logic\u002Fserver tests. Use Storybook for visual component inspection. Skip DOM-heavy component tests.\n\n## Basic Test\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\n\ndescribe(\"fmtModel\", () => {\n  test(\"strips openrouter\u002F prefix\", () => {\n    expect(fmtModel(\"openrouter\u002Fgoogle\u002Fgemini-2.5-pro\")).toBe(\"google\u002Fgemini-2.5-pro\");\n  });\n});\n```\n\n## Effect Tests\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { Effect } from \"effect\";\n\ndescribe(\"TaskService\", () => {\n  test(\"getTask returns cached task\", async () => {\n    const program = Effect.gen(function* () {\n      const svc = yield* TaskService;\n      return yield* svc.getTask(\"bool_not\");\n    });\n\n    const result = await Effect.runPromise(program.pipe(Effect.provide(TaskServiceLive)));\n\n    expect(result.id).toBe(\"bool_not\");\n  });\n});\n```\n\n## Async Tests\n\n```typescript\ntest(\"async operation\", async () => {\n  const result = await fetchData();\n  expect(result).toBeDefined();\n});\n```\n\n## Snapshots\n\n```typescript\ntest(\"snapshot comparison\", () => {\n  expect(data).toMatchSnapshot();\n});\n```\n\nUpdate snapshots: `bun test -u`\n\n## Skipping and TODO\n\n```typescript\ntest.skip(\"not ready yet\", () => { ... });\ntest.todo(\"implement this later\");\ntest.only(\"run only this\", () => { ... });\n```\n\n## Test Files\n\nBun automatically discovers:\n\n- `*.test.ts`\n- `*.test.tsx`\n- `*.spec.ts`\n- `*.spec.tsx`\n\n## React Component Testing\n\n**Philosophy**: Test logic, not DOM. Use Storybook for visual inspection.\n\n```typescript\n\u002F\u002F ❌ Don't test DOM rendering\nimport { render } from \"@testing-library\u002Freact\";\nconst { container } = render(\u003CBarChart pct={50} \u002F>);\nexpect(container.querySelector(\"span\")).toBeDefined();\n\n\u002F\u002F ✅ Test pure logic\nfunction getBarColor(pct: number): string {\n  if (pct >= 70) return \"green\";\n  if (pct >= 45) return \"blue\";\n  if (pct >= 20) return \"yellow\";\n  return \"red\";\n}\n\ndescribe(\"getBarColor\", () => {\n  test(\"green at 70+\", () => {\n    expect(getBarColor(70)).toBe(\"green\");\n    expect(getBarColor(100)).toBe(\"green\");\n  });\n\n  test(\"blue at 45-69\", () => {\n    expect(getBarColor(45)).toBe(\"blue\");\n    expect(getBarColor(69)).toBe(\"blue\");\n  });\n\n  test(\"yellow at 20-44\", () => {\n    expect(getBarColor(20)).toBe(\"yellow\");\n    expect(getBarColor(44)).toBe(\"yellow\");\n  });\n\n  test(\"red below 20\", () => {\n    expect(getBarColor(0)).toBe(\"red\");\n    expect(getBarColor(19)).toBe(\"red\");\n  });\n});\n```\n\n## Mocking\n\n```typescript\nimport { mock, spyOn } from \"bun:test\";\n\n\u002F\u002F Mock a function\nconst mockFn = mock((x: number) => x * 2);\nexpect(mockFn(5)).toBe(10);\nexpect(mockFn).toHaveBeenCalledTimes(1);\n\n\u002F\u002F Spy on module\nimport * as fs from \"node:fs\";\nconst readSpy = spyOn(fs, \"readFileSync\").mockReturnValue(\"test\");\n\n\u002F\u002F Restore\nreadSpy.mockRestore();\n```\n\n## Running Tests\n\n```bash\n# All tests\nbun test\n\n# Specific file\nbun test src\u002Flib\u002Ffmt.test.ts\n\n# Watch mode\nbun test --watch\n\n# Update snapshots\nbun test -u\n\n# Coverage\nbun test --coverage\n\n# Bail on first failure\nbun test --bail\n```\n\n## Package.json Scripts\n\n```json\n{\n  \"scripts\": {\n    \"test\": \"bun test\",\n    \"test:watch\": \"bun test --watch\",\n    \"test:coverage\": \"bun test --coverage\"\n  }\n}\n```\n\n## CI Integration\n\n```yaml\n# .github\u002Fworkflows\u002Ftest.yml\n- name: Run tests\n  run: bun test\n```\n\nNo config file needed. No setup files. Just `bun test`.\n\n## Comparison: When to Use What\n\n| Test Type         | Tool                 | Example                       |\n| ----------------- | -------------------- | ----------------------------- |\n| Pure functions    | `bun:test`           | `fmtModel()`, `getBarColor()` |\n| Effect services   | `bun:test`           | `TaskService.getTask()`       |\n| React logic       | `bun:test`           | Hook utilities, helpers       |\n| Visual appearance | Storybook            | Component fixtures            |\n| Browser behavior  | Manual QA            | Click flows, responsive       |\n| E2E API           | `bun:test` + `fetch` | HTTP endpoint tests           |\n\n## Migrating from Vitest\n\n1. Replace `import { ... } from \"vitest\"` with `import { ... } from \"bun:test\"`\n2. Replace `vi.fn()` with `mock()`\n3. Replace `vi.spyOn()` with `spyOn()`\n4. Remove `vitest.config.ts`\n5. Remove `@vitest\u002F*` dependencies\n6. Convert DOM tests to logic tests or Storybook fixtures\n7. Update package.json scripts\n\n## Anti-Patterns\n\n```typescript\n\u002F\u002F ❌ Testing implementation details\ntest(\"sets internal state\", () => { ... });\n\n\u002F\u002F ❌ Testing React DOM structure\ntest(\"has 3 divs\", () => { ... });\n\n\u002F\u002F ❌ Heavy mocking\nmock(\".\u002Fmodule\", () => ({ ... }));\n\n\u002F\u002F ✅ Test behavior\n\u002F\u002F ✅ Test pure logic\n\u002F\u002F ✅ Test public API\n\u002F\u002F ✅ Visual inspection in Storybook\n```\n",{"name":5,"license":14,"description":7,"compatibility":37},"main","816c073aaf171300af3605b06f7ec5aa7370ef0b",".opencode\u002Fskills\u002Feffect-ts\u002Ftesting\u002F04-bun-test","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro","https:\u002F\u002Fgithub.com\u002Flambda-solver","2026-05-31 17:08:46",{"source":8,"skillName":5,"commands":53,"prompt":63,"zipAvailable":64},[54,57,60],{"tool":55,"command":56},"npx","npx skills add lambda-solver\u002Flambdabench-pro --skill 04-bun-test",{"tool":58,"command":59},"bunx","bunx skills add lambda-solver\u002Flambdabench-pro --skill 04-bun-test",{"tool":61,"command":62},"pnpm","pnpm dlx skills add lambda-solver\u002Flambdabench-pro --skill 04-bun-test","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Feffect-ts\u002Ftesting\u002F04-bun-test\u002FSKILL.md",true,[],[67,95,114,133,154,172],{"skillNo":68,"name":69,"nameZh":6,"description":70,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":76,"publishedAt":41},"01M71H9FNA5D6Y4ANXD18Z1Z3X","tmux-workflow","Development workflow with tmux — run dev servers, Storybook, and background processes in persistent sessions with live logs, while keeping OpenCode free for chat","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Ftmux\u002FSKILL.md",[73],{"categoryNo":74,"categoryName":75,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[77,78,79,80,81,82,83,84,85,86,87,37,88,89,90,91,92,93,34,94],"tmux","workflow","tmux workflow","chat","dev servers","background","processes","storybook","live","servers","run","with","logs","development workflow","free","dev","sessions","development",{"skillNo":96,"name":97,"nameZh":6,"description":98,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":102,"publishedAt":41},"01M71H9DQJDAJVZX37NDN99D3P","04-anti-patterns","React anti-patterns to avoid — manual JSX repetition, useEffect misuse, reference instability, prop drilling, conditional hooks, and common performance traps","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F04-anti-patterns\u002FSKILL.md",[101],{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},[103,104,105,106,107,108,109,110,111,112,113,37,36],"patterns","anti patterns","04 anti patterns","common","jsx","reference","conditional","hooks","manual","performance","anti-patterns",{"skillNo":115,"name":116,"nameZh":6,"description":117,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":118,"categories":119,"keywords":121,"publishedAt":41},"01M71H9BXF511W2R3B73S5P9ZN","03-state-management","React state management patterns — lifting state, colocation, URL state, server state with TanStack Query, local state with useState\u002FuseReducer","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F03-state-management\u002FSKILL.md",[120],{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},[122,123,124,125,36,126,103,127,128,129,130,37,131,88,132],"management","state management","state","03 state management","query","URL","tanstack","react state management","local","server","tanstack query",{"skillNo":134,"name":135,"nameZh":6,"description":136,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":137,"categories":138,"keywords":140,"publishedAt":41},"01M71H9AAGVWMYQ4NG82QPYCTE","02-component-composition","React component composition patterns — render props, compound components, list rendering with map, slot patterns, and layout primitives","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F02-component-composition\u002FSKILL.md",[139],{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},[141,142,143,37,88,144,145,36,146,103,147,148,149,150,151,152,153],"02 component composition","component","Composition","compound","components","primitives","composition patterns","list","map","rendering","render","react component","layout",{"skillNo":155,"name":156,"nameZh":6,"description":157,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":158,"categories":159,"keywords":161,"publishedAt":41},"01M71H98RDXRQZDR496SRD906M","01-fp-style","React functional programming style — pure components, hooks conventions, Effect Atom integration, and Tailwind patterns","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F01-fp-style\u002FSKILL.md",[160],{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},[162,163,164,103,165,166,37,167,36,168,145,110,169,170,171,30],"01 fp style","style","atom","conventions","integration","functional","programming","Tailwind","tailwind patterns","functional programming",{"skillNo":173,"name":174,"nameZh":6,"description":175,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":176,"categories":177,"keywords":179,"publishedAt":41},"01M71H95PYGAWBS5C8KN0C4WGT","react-animation","React animation with react\u002Fmotion (Framer Motion) — declarative animations, gestures, layout animations, and performance best practices","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fanimation\u002FSKILL.md",[178],{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},[36,180,181,112,182,37,153,183,184,88,185,186,187,188],"react animation","Animation","framer motion","motion","best practices","framer","gestures","animations","declarative"]