Skip to content
Merged
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
4 changes: 4 additions & 0 deletions docs/VISUAL-REGRESSION-TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ The test runner automatically creates a dark mode variant for any fixture named
| `opacity` | Elements at 100%, 60%, 30% opacity; semi-transparent text |
| `all-fonts` | All 7 supported font families (Excalifont, Nunito, Lilita One, Comic Shanns, Virgil, Cascadia, Liberation Sans) |
| `colored-arrows` | Elbow/curved/straight arrows with non-transparent backgroundColor; verifies arrow paths are not filled |
| `combine-horizontal` | Combine command: horizontal layout of basic-shapes + arrows-lines |
| `combine-vertical` | Combine command: vertical layout of basic-shapes + arrows-lines |
| `combine-labels` | Combine command: horizontal layout with --labels flag |
| `combine-gap0` | Combine command: horizontal layout with --gap 0 (no gap) |

## Updating Baselines After Rendering Changes

Expand Down
Binary file added tests/visual/baselines/combine-gap0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/visual/baselines/combine-horizontal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/visual/baselines/combine-labels.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/visual/baselines/combine-vertical.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/visual/baselines/diff-test--dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
112 changes: 110 additions & 2 deletions tests/visual/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const MAX_DIFF_PERCENT = 1.0;
const MAX_SVG_DIFF_PERCENT = 5.0;

type TestFormat = "png" | "svg";
type TestType = "export" | "diff";
type TestType = "export" | "diff" | "combine";

interface TestCase {
name: string;
Expand All @@ -53,6 +53,10 @@ interface TestCase {
format: TestFormat;
type: TestType;
diffNewFixture?: string; // For diff tests: the "new" file
combineFixtures?: string[]; // For combine tests: array of fixture paths
layout?: "horizontal" | "vertical";
labels?: boolean;
gap?: number;
}

function discoverTests(): TestCase[] {
Expand Down Expand Up @@ -214,6 +218,62 @@ function discoverTests(): TestCase[] {
});
}

// Add combine tests
const combineFixtureA = join(FIXTURES_DIR, "basic-shapes.excalidraw");
const combineFixtureB = join(FIXTURES_DIR, "arrows-lines.excalidraw");
if (existsSync(combineFixtureA) && existsSync(combineFixtureB)) {
tests.push({
name: "combine-horizontal",
fixture: combineFixtureA,
combineFixtures: [combineFixtureA, combineFixtureB],
outputName: "combine-horizontal.png",
baselineName: "combine-horizontal.png",
darkMode: false,
scale: 1,
format: "png",
type: "combine",
});

tests.push({
name: "combine-vertical",
fixture: combineFixtureA,
combineFixtures: [combineFixtureA, combineFixtureB],
outputName: "combine-vertical.png",
baselineName: "combine-vertical.png",
darkMode: false,
scale: 1,
format: "png",
type: "combine",
layout: "vertical",
});

tests.push({
name: "combine-labels",
fixture: combineFixtureA,
combineFixtures: [combineFixtureA, combineFixtureB],
outputName: "combine-labels.png",
baselineName: "combine-labels.png",
darkMode: false,
scale: 1,
format: "png",
type: "combine",
labels: true,
});

tests.push({
name: "combine-gap0",
fixture: combineFixtureA,
combineFixtures: [combineFixtureA, combineFixtureB],
outputName: "combine-gap0.png",
baselineName: "combine-gap0.png",
darkMode: false,
scale: 1,
format: "png",
type: "combine",
gap: 0,
});
}

return tests;
}

Expand Down Expand Up @@ -312,6 +372,48 @@ async function runDiffCli(
return { success: exitCode === 0, stderr };
}

async function runCombineCli(
fixtures: string[],
outputPath: string,
options: {
layout?: "horizontal" | "vertical";
labels?: boolean;
gap?: number;
} = {},
): Promise<{ success: boolean; stderr: string }> {
const relOutput = relative(PROJECT_ROOT, outputPath);
const relFixtures = fixtures.map((f) => relative(PROJECT_ROOT, f));

const args = [
"docker",
"run",
"--rm",
"-v",
`${PROJECT_ROOT}:/data`,
"-w",
"/data",
"excalirender:test",
"combine",
...relFixtures,
"-o",
relOutput,
];
if (options.layout) args.push("--layout", options.layout);
if (options.labels) args.push("--labels");
if (options.gap !== undefined) args.push("--gap", String(options.gap));

const proc = Bun.spawn(args, {
cwd: PROJECT_ROOT,
stdout: "pipe",
stderr: "pipe",
});

const exitCode = await proc.exited;
const stderr = await new Response(proc.stderr).text();

return { success: exitCode === 0, stderr };
}

/**
* Render an SVG file to a PNG buffer using resvg-js.
*/
Expand Down Expand Up @@ -488,7 +590,13 @@ async function main() {

// Generate output via Docker
let result: { success: boolean; stderr: string };
if (test.type === "diff" && test.diffNewFixture) {
if (test.type === "combine" && test.combineFixtures) {
result = await runCombineCli(test.combineFixtures, outputPath, {
layout: test.layout,
labels: test.labels,
gap: test.gap,
});
} else if (test.type === "diff" && test.diffNewFixture) {
result = await runDiffCli(test.fixture, test.diffNewFixture, outputPath, {
darkMode: test.darkMode,
});
Expand Down