Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions csv-table-hub-main/src/__tests__/log-step-contract.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// The upload response is validated against a schema. A log step the API emits but the schema does not
// list makes zod reject the WHOLE response, so an import that succeeded on the server is reported as
// "Failed: Unexpected response shape" (what #186 did when it added the header_mapping step).

import { readdirSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { processingLogSchema } from "@/lib/csv.functions";

const API = join(__dirname, "../../../api");

/** Every step name the loaders pass to _log(logs, "<step>", ...). */
function stepsTheApiEmits(): Set<string> {
const steps = new Set<string>();
for (const dir of ["services", "routers"]) {
for (const file of readdirSync(join(API, dir)).filter((f) => f.endsWith(".py"))) {
const source = readFileSync(join(API, dir, file), "utf8");
for (const m of source.matchAll(/_log\(\s*logs,\s*"([a-z_]+)"/g)) steps.add(m[1]);
}
}
return steps;
}

describe("processing log steps", () => {
it("finds the steps the API emits (guards the scan itself)", () => {
const steps = stepsTheApiEmits();
expect(steps.size).toBeGreaterThan(8);
expect(steps.has("receive")).toBe(true);
});

it("the schema accepts every step the API can emit", () => {
const known = new Set<string>(processingLogSchema.shape.step.options);
const unknown = [...stepsTheApiEmits()].filter((s) => !known.has(s));
expect(unknown).toEqual([]);
});

it("accepts the header_mapping entry a dynamic upload with a header mapping returns", () => {
const entry = { ts: 1, step: "header_mapping", level: "info", message: "Applied 2 header renames" };
expect(processingLogSchema.safeParse(entry).success).toBe(true);
});
});
3 changes: 2 additions & 1 deletion csv-table-hub-main/src/lib/csv.functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ const rowErrorSchema = z.object({
});
export type RowError = z.infer<typeof rowErrorSchema>;

const processingLogSchema = z.object({
export const processingLogSchema = z.object({
ts: z.number(),
step: z.enum([
"receive",
"hash",
"duplicate_check",
"parse",
"header_mapping",
"validate_columns",
"create_table",
"cast_rows",
Expand Down
Loading