一键导入
testing-functions
Tests pure functions, utilities, and logic with Vitest. Input: Function/module to test. Output: Test file with unit tests for all cases.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Tests pure functions, utilities, and logic with Vitest. Input: Function/module to test. Output: Test file with unit tests for all cases.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | testing-functions |
| description | Tests pure functions, utilities, and logic with Vitest. Input: Function/module to test. Output: Test file with unit tests for all cases. |
Creates unit tests for pure functions, utilities, and business logic.
1. Create test file:
- [ ] Create `[filename].test.ts` next to source
- [ ] Import function(s) to test
2. Identify test cases:
- [ ] Happy path (normal inputs)
- [ ] Edge cases (empty, null, boundaries)
- [ ] Error cases (invalid inputs)
3. Write tests:
- [ ] Use descriptive `it()` names
- [ ] One assertion per test (usually)
- [ ] Group related tests in `describe()`
4. Run and verify:
- [ ] Run `bun run test [file]`
// lib/utils/format.test.ts
import { describe, it, expect } from "vitest";
import { formatBytes, formatDuration, truncate } from "./format";
describe("formatBytes", () => {
it("formats bytes correctly", () => {
expect(formatBytes(0)).toBe("0 B");
expect(formatBytes(1024)).toBe("1 KB");
expect(formatBytes(1048576)).toBe("1 MB");
});
it("handles large values", () => {
expect(formatBytes(1073741824)).toBe("1 GB");
});
it("rounds to 2 decimal places", () => {
expect(formatBytes(1536)).toBe("1.5 KB");
});
});
describe("truncate", () => {
it("returns string unchanged if under limit", () => {
expect(truncate("hello", 10)).toBe("hello");
});
it("truncates with ellipsis", () => {
expect(truncate("hello world", 8)).toBe("hello...");
});
it("handles empty string", () => {
expect(truncate("", 10)).toBe("");
});
});
// lib/config/models.test.ts
import { describe, it, expect } from "vitest";
import { MODEL_REGISTRY, getModel, getModelConstraints } from "./models";
describe("MODEL_REGISTRY", () => {
it("contains expected image models", () => {
expect(MODEL_REGISTRY.flux).toBeDefined();
expect(MODEL_REGISTRY.flux.type).toBe("image");
});
it("contains expected video models", () => {
expect(MODEL_REGISTRY.veo).toBeDefined();
expect(MODEL_REGISTRY.veo.type).toBe("video");
});
it("all models have required fields", () => {
Object.values(MODEL_REGISTRY).forEach((model) => {
expect(model.id).toBeDefined();
expect(model.displayName).toBeDefined();
expect(model.type).toMatch(/^(image|video)$/);
expect(model.constraints).toBeDefined();
});
});
});
describe("getModel", () => {
it("returns model by ID", () => {
const model = getModel("flux");
expect(model?.displayName).toBe("Flux Schnell");
});
it("returns undefined for unknown model", () => {
expect(getModel("unknown")).toBeUndefined();
});
it("is case-insensitive", () => {
expect(getModel("FLUX")).toEqual(getModel("flux"));
});
});
// lib/api/client.test.ts
import { describe, it, expect, vi, beforeEach } from "vitest";
import { fetchWithRetry } from "./client";
describe("fetchWithRetry", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("returns data on success", async () => {
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ data: "test" }),
});
const result = await fetchWithRetry("/api/test");
expect(result).toEqual({ data: "test" });
});
it("retries on 5xx errors", async () => {
global.fetch = vi
.fn()
.mockResolvedValueOnce({ ok: false, status: 500 })
.mockResolvedValueOnce({ ok: true, json: () => ({ data: "test" }) });
const result = await fetchWithRetry("/api/test");
expect(fetch).toHaveBeenCalledTimes(2);
expect(result).toEqual({ data: "test" });
});
it("throws on 4xx errors without retry", async () => {
global.fetch = vi.fn().mockResolvedValue({ ok: false, status: 400 });
await expect(fetchWithRetry("/api/test")).rejects.toThrow();
expect(fetch).toHaveBeenCalledTimes(1);
});
});
| File | Tests |
|---|---|
lib/config/models.test.ts | Model registry validation |
lib/config/resolution-tiers.test.ts | Resolution calculations |
lib/config/standard-resolutions.test.ts | Resolution presets |
convex/lib/pollinations.test.ts | API URL building |
convex/lib/retry.test.ts | Retry logic |
convex/lib/r2.test.ts | Storage helpers |
convex/rateLimits.test.ts | Rate limiting |
it.each([
[768, 768, true], // square within limit
[1024, 768, true], // landscape within limit
[2048, 2048, false], // exceeds max pixels
])("validates dimensions (%i x %i) = %s", (width, height, expected) => {
expect(isValidDimension(width, height)).toBe(expected);
});
it("throws on invalid input", () => {
expect(() => parseConfig(null)).toThrow("Config is required");
});
// Async errors
it("rejects with error message", async () => {
await expect(fetchData("invalid")).rejects.toThrow(/not found/i);
});
it("generates correct config", () => {
const config = buildConfig({ model: "flux", width: 768 });
expect(config).toMatchSnapshot();
});
## Summary
Added tests for `[module/function]`.
## Test Cases
- [x] handles normal input
- [x] handles edge case: empty
- [x] handles edge case: max value
- [x] throws on invalid input
## Coverage
- Functions tested: `formatBytes`, `truncate`
- Edge cases covered: empty, null, boundaries
## Verification
- `bun run test [file]` passed ✅
- [N] tests, [M] assertions
Adds a new table to Convex schema with indexes. Input: Table name, fields, and query patterns. Output: Updated schema.ts with new table definition.
Creates a new page/route in Next.js App Router with all boilerplate. Input: Route path (e.g., "/dashboard") and page purpose. Output: page.tsx, layout.tsx (if needed), loading.tsx, error.tsx.
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.
Creates interactive React Client Components with hooks and event handlers. Input: Component name, purpose, required interactivity. Output: Client component file with proper structure and tests.
Creates pages, layouts, and server/client components in Next.js 16 App Router. Use for: new routes, RSC/RCC decisions, Server Actions, loading/error states. DO NOT use for: Convex mutations (use managing-convex), styling (use styling-ui).
Generates images using Pollinations API. Validates model constraints and dimensions. Use for: image generation logic, model selection, constraint validation. DO NOT use for: video generation (use generating-videos), UI styling (use styling-ui).