@@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
importRecipe,
|
||||
records,
|
||||
renderPipelineSvg,
|
||||
runPipeline,
|
||||
type Stage,
|
||||
} from "../../src/core/pipeline";
|
||||
@@ -55,5 +56,55 @@ describe("pipeline", () => {
|
||||
'{"schema":"de.add-ideas.flow-tools.recipe.v1","stages":[{"type":"javascript","config":{}}]}',
|
||||
),
|
||||
).toThrow(/Invalid recipe/iu);
|
||||
expect(() =>
|
||||
importRecipe(
|
||||
'{"schema":"de.add-ideas.flow-tools.recipe.v1","stages":[{"id":"same","type":"sort","enabled":true,"config":{}},{"id":"same","type":"sort","enabled":true,"config":{}}]}',
|
||||
),
|
||||
).toThrow(/safe unique id/iu);
|
||||
});
|
||||
it("deduplicates, explodes arrays and slices deterministically", () => {
|
||||
const result = runPipeline(
|
||||
records([
|
||||
{ id: 1, tags: ["a", "b"] },
|
||||
{ id: 1, tags: ["a", "b"] },
|
||||
{ id: 2, tags: ["c"] },
|
||||
]),
|
||||
[
|
||||
{
|
||||
id: "d",
|
||||
type: "deduplicate",
|
||||
enabled: true,
|
||||
config: { fields: "id" },
|
||||
},
|
||||
{
|
||||
id: "e",
|
||||
type: "explode",
|
||||
enabled: true,
|
||||
config: { field: "tags", target: "tag" },
|
||||
},
|
||||
{
|
||||
id: "s",
|
||||
type: "slice",
|
||||
enabled: true,
|
||||
config: { offset: "1", count: "2" },
|
||||
},
|
||||
],
|
||||
);
|
||||
expect(result.rows.map((row) => row.tag)).toEqual(["b", "c"]);
|
||||
expect(result.analysis).toMatchObject({
|
||||
inputRows: 3,
|
||||
outputRows: 2,
|
||||
duplicateRows: 1,
|
||||
});
|
||||
expect(result.snapshots.at(-1)?.losses).toContain(
|
||||
"1 rows fall outside the selected slice.",
|
||||
);
|
||||
});
|
||||
it("exports an inert pipeline SVG", () => {
|
||||
const svg = renderPipelineSvg([
|
||||
{ id: "x", type: "map", enabled: true, config: {} },
|
||||
]);
|
||||
expect(svg).toContain("Flow pipeline");
|
||||
expect(svg).not.toContain("<script");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user