Files
ComfyAssets-ComfyUI_PromptM…/tests/vendor/workflow-artifacts.test.mjs
Vito e7cfcc2bfb style(workspace): align browsing with the approved concept (#219)
* style(workspace): align approved shell and visual fixtures

* test(workflows): preserve evidence across browser projects

* style(workspace): match approved image browsing geometry

* style(workspace): match natural library card layout

* fix(workspace): retain wheel motion during row correction

* fix(workspace): contain zoomed controls and image metadata (#215)
2026-10-18 02:53:26 -07:00

71 lines
4.1 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { mkdtemp, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises';
import { execFileSync } from 'node:child_process';
import { tmpdir } from 'node:os';
import { isAbsolute, join, relative, resolve, sep } from 'node:path';
import { fileURLToPath } from 'node:url';
import workflowConfig from '../../tools/vendor/playwright.workflows.config.mjs';
const configUrl = new URL('../../tools/vendor/playwright.workflows.config.mjs', import.meta.url);
const runner = fileURLToPath(new URL('../../tools/vendor/node_modules/@playwright/test/cli.js', import.meta.url));
const testModule = new URL('../../tools/vendor/node_modules/@playwright/test/index.mjs', import.meta.url).href;
async function evidenceFiles(directory) {
const files = [];
for (const entry of await readdir(directory, { withFileTypes: true })) {
const path = join(directory, entry.name);
if (entry.isDirectory()) files.push(...await evidenceFiles(path));
else if (entry.name === 'evidence.json') files.push(path);
}
return files;
}
test('sequential workflow project runs retain all four project evidence sets', async t => {
const root = await mkdtemp(join(tmpdir(), 'pm-workflow-artifacts-'));
t.after(() => rm(root, { recursive: true, force: true }));
const uploadedAncestor = resolve(root, 'test-results/workflows');
const isolateOutput = value => {
assert.equal(typeof value, 'string');
assert.equal(isAbsolute(value), false, 'configured output must remain relative');
const output = resolve(root, value);
assert.ok(output.startsWith(root + sep), 'runner output must stay inside its owned temporary root');
const uploadedRelative = relative(uploadedAncestor, output);
assert.ok(uploadedRelative === '' || (!uploadedRelative.startsWith('..') && !isAbsolute(uploadedRelative)),
'project evidence must remain beneath the uploaded workflow ancestor');
return output;
};
// Validate every output before launching a runner that removes output directories.
const outputDir = isolateOutput(workflowConfig.outputDir);
const projects = workflowConfig.projects.map(project => ({
...project, outputDir: isolateOutput(project.outputDir ?? workflowConfig.outputDir),
}));
const testDir = join(root, 'specs');
await mkdir(testDir);
await writeFile(join(testDir, 'evidence-retention.spec.mjs'), `
import { test } from ${JSON.stringify(testModule)};
import { writeFile } from 'node:fs/promises';
test('writes project evidence without a browser or host', async ({}, testInfo) => {
await writeFile(testInfo.outputPath('evidence.json'), JSON.stringify({ project: testInfo.project.name }));
});
`);
const configPath = join(root, 'playwright.config.mjs');
await writeFile(configPath, `
import config from ${JSON.stringify(configUrl.href)};
export default { ...config, testDir: ${JSON.stringify(testDir)}, webServer: undefined,
outputDir: ${JSON.stringify(outputDir)}, projects: ${JSON.stringify(projects)} };
`);
const run = names => execFileSync(process.execPath, [runner, 'test', '--config', configPath,
...names.flatMap(name => ['--project', name])], {
cwd: root, encoding: 'utf8', timeout: 30_000,
env: { ...process.env, PM_JS_COVERAGE: '', NODE_V8_COVERAGE: '' },
});
assert.match(run(['chromium', 'touch']), /2 passed/);
const first = new Map(await Promise.all((await evidenceFiles(uploadedAncestor)).map(async path => [path, await readFile(path, 'utf8')])));
assert.deepEqual([...first.values()].map(value => JSON.parse(value).project).sort(), ['chromium', 'touch']);
assert.match(run(['firefox', 'webkit']), /2 passed/);
const retained = new Map(await Promise.all((await evidenceFiles(uploadedAncestor)).map(async path => [path, await readFile(path, 'utf8')])));
assert.deepEqual([...retained.values()].map(value => JSON.parse(value).project).sort(), ['chromium', 'firefox', 'touch', 'webkit']);
for (const [path, contents] of first) assert.equal(retained.get(path), contents, 'later runs preserve earlier evidence bytes and paths');
});