Files
vercel__vercel-plugin/tests/notion-clone-patterns.test.ts
John Lindquist cd5f369dcb Add new skills, typecheck gate, remove arg/ms/serve skills, bump to 0.4.2
- Add 8 new skills: edge-runtime, geist, micro, ncc, satori, streamdown, styled-jsx, swr
- Remove arg, ms, serve skills (standalone utilities, not relevant to shipping apps on Vercel)
- Add typecheck script and wire into `bun run test` and pre-commit hook
- Fix StdioOptions type error in session-start-profiler
- Add hook-env module and posttooluse-shadcn-font-fix hook
- Refactor skill-map-frontmatter, patterns, pretooluse-skill-inject
- Update generated catalog and manifest (42 skills)
- Add .gitignore with .DS_Store
2026-03-06 19:04:25 -07:00

80 lines
2.6 KiB
TypeScript

import { describe, test, expect } from "bun:test";
import { join, resolve } from "node:path";
const ROOT = resolve(import.meta.dirname, "..");
const HOOK_SCRIPT = join(ROOT, "hooks", "pretooluse-skill-inject.mjs");
const UNLIMITED_BUDGET = "999999";
async function runHook(input: {
tool_name: string;
tool_input: Record<string, string>;
}): Promise<{ code: number; stdout: string; stderr: string }> {
const proc = Bun.spawn(["node", HOOK_SCRIPT], {
stdin: "pipe",
stdout: "pipe",
stderr: "pipe",
env: {
...process.env,
VERCEL_PLUGIN_INJECTION_BUDGET: UNLIMITED_BUDGET,
VERCEL_PLUGIN_HOOK_DEDUP: "off",
},
});
proc.stdin.write(
JSON.stringify({
...input,
session_id: "notion-clone-patterns",
}),
);
proc.stdin.end();
const code = await proc.exited;
const stdout = await new Response(proc.stdout).text();
const stderr = await new Response(proc.stderr).text();
return { code, stdout, stderr };
}
async function matchFile(filePath: string): Promise<string[]> {
const { code, stdout } = await runHook({
tool_name: "Read",
tool_input: { file_path: filePath },
});
expect(code).toBe(0);
const result = JSON.parse(stdout);
const ctx = result?.hookSpecificOutput?.additionalContext || "";
const match = ctx.match(/<!-- skillInjection: (\{.*?\}) -->/);
const si = match ? JSON.parse(match[1]) : {};
return si.injectedSkills ?? [];
}
describe("notion clone patterns", () => {
test("notion-clone app/layout.tsx injects observability before nextjs", async () => {
const injectedSkills = await matchFile("/Users/me/notion-clone/app/layout.tsx");
expect(injectedSkills).toEqual(["observability", "nextjs"]);
});
test("notion-clone middleware.ts injects routing-middleware", async () => {
const injectedSkills = await matchFile("/Users/me/notion-clone/middleware.ts");
expect(injectedSkills).toEqual(["auth", "routing-middleware"]);
});
test("notion-clone components/ui/dialog.tsx injects shadcn", async () => {
const injectedSkills = await matchFile(
"/Users/me/notion-clone/components/ui/dialog.tsx",
);
expect(injectedSkills).toEqual(["shadcn"]);
});
test("notion-clone app/(marketing)/(routes)/page.tsx injects nextjs", async () => {
const injectedSkills = await matchFile(
"/Users/me/notion-clone/app/(marketing)/(routes)/page.tsx",
);
expect(injectedSkills).toEqual(["nextjs"]);
});
test("notion-clone next.config.ts injects nextjs then turbopack", async () => {
const injectedSkills = await matchFile("/Users/me/notion-clone/next.config.ts");
expect(injectedSkills).toEqual(["nextjs", "turbopack"]);
});
});