Release Flow Tools 0.2.0
Verify / verify (push) Canceled after 0s

This commit is contained in:
2026-09-02 08:10:52 +02:00
parent 12d0ac0155
commit 57dd710275
28 changed files with 810 additions and 66 deletions
+1 -1
View File
@@ -58,6 +58,6 @@ test("PWA theme, offline reload, and manifest", async ({
const m = await request.get("/deep/nested/flow/toolbox-app.json");
await expect(m.json()).resolves.toMatchObject({
id: "de.add-ideas.flow-tools",
version: "0.1.0",
version: "0.2.0",
});
});
+18
View File
@@ -0,0 +1,18 @@
import { expect, test } from "@playwright/test";
test("keeps the primary workspace inside a narrow viewport", async ({
page,
}) => {
await page.goto("/deep/nested/flow/");
await expect(page.locator("main").first()).toBeVisible();
await expect(
page.locator("main .loading, main .workbench-loading"),
).toHaveCount(0);
const widths = await page.evaluate(() => ({
content: document.documentElement.scrollWidth,
viewport: document.documentElement.clientWidth,
}));
expect(widths.viewport).toBeLessThanOrEqual(430);
expect(widths.content).toBeLessThanOrEqual(widths.viewport + 1);
});
+51
View File
@@ -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");
});
});