返回 CodeWhale
product-telemetry-route.test.ts
根目录 / web / lib / product-telemetry-route.test.ts
1 import { readdirSync, readFileSync } from "node:fs";
2 import { join } from "node:path";
3 import { fileURLToPath } from "node:url";
4 import { describe, expect, it } from "vitest";
5 import { handleProductTelemetry } from "@/app/api/product-telemetry/route";
6
7 const APP_DIR = fileURLToPath(new URL("../app", import.meta.url));
8
9 function sourceFiles(dir: string): string[] {
10 return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
11 const path = join(dir, entry.name);
12 if (entry.isDirectory()) return sourceFiles(path);
13 return /\.(m?[jt]sx?)$/.test(entry.name) ? [path] : [];
14 });
15 }
16
17 // `export const runtime = "edge"`, `runtime: 'experimental-edge'`, and so on.
18 // Route segment config only takes effect in app/ files, so that is the scan.
19 const EDGE_RUNTIME =
20 /(?:\bexport\s+const\s+runtime\s*=|\bruntime\s*:)\s*["'](?:experimental-)?edge["']/;
21
22 describe("/api/product-telemetry", () => {
23 it("recognizes edge and experimental-edge declarations", () => {
24 for (const source of [
25 'export const runtime = "edge";',
26 "export const runtime = 'experimental-edge';",
27 'export const config = { runtime: "edge" };',
28 ]) {
29 expect(EDGE_RUNTIME.test(source), source).toBe(true);
30 }
31 expect(EDGE_RUNTIME.test('export const runtime = "nodejs";')).toBe(false);
32 });
33
34 // @opennextjs/cloudflare does not support the edge runtime (its migrate
35 // command says to remove the declaration). This is a source guard; it does
36 // not exercise the adapter or the deployed worker.
37 it("no app route or page opts into the edge runtime", () => {
38 const edge = sourceFiles(APP_DIR).filter((file) =>
39 EDGE_RUNTIME.test(readFileSync(file, "utf8")),
40 );
41 expect(edge).toEqual([]);
42 });
43
44 it("answers an empty POST without a server error", async () => {
45 const post = () =>
46 new Request("https://codewhale.net/api/product-telemetry", {
47 method: "POST",
48 headers: { "content-type": "application/json" },
49 body: "{}",
50 });
51
52 const disabled = await handleProductTelemetry(post(), { ingestUrl: null });
53 expect(disabled.status).toBe(200);
54 expect(await disabled.json()).toEqual({ accepted: false, reason: "disabled" });
55
56 const enabled = await handleProductTelemetry(post(), {
57 ingestUrl: "https://telemetry.codewhale.net/v1/telemetry",
58 forward: async () => {
59 throw new Error("an invalid envelope must not be forwarded");
60 },
61 });
62 expect(enabled.status).toBe(422);
63 expect(await enabled.json()).toEqual({ accepted: false, reason: "schema" });
64 });
65 });
66
66 lines TYPESCRIPT