99 lines
5.6 KiB
JavaScript
99 lines
5.6 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const test = require('node:test');
|
|
const fs = require('node:fs/promises');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
const Module = require('node:module');
|
|
const { pathToFileURL } = require('node:url');
|
|
const { promisify } = require('node:util');
|
|
const run = promisify(require('node:child_process').execFile);
|
|
|
|
test('generated flowcharts render offline and source clicks retain the actual location', async () => {
|
|
assert.ok(process.env.DEVER_TEST_BIN);
|
|
assert.ok(process.env.DEVER_BROWSER_TOOLS, 'directory containing existing playwright-core and @sparticuz/chromium');
|
|
const tools = Module.createRequire(path.join(process.env.DEVER_BROWSER_TOOLS, '..', 'package.json'));
|
|
const { chromium: playwright } = tools('playwright-core');
|
|
const chromium = tools('@sparticuz/chromium').default;
|
|
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'dever flow browser '));
|
|
const extension = path.resolve(__dirname, '../../editor/vscode');
|
|
const project = path.join(root, 'project');
|
|
const subscriptions = [];
|
|
let browser;
|
|
const originalLoad = Module._load;
|
|
try {
|
|
await run(process.env.DEVER_TEST_BIN, ['new', project]);
|
|
await run(process.env.DEVER_TEST_BIN, ['inspect', project, '--links']);
|
|
const uri = filename => ({ fsPath: filename, toString: () => pathToFileURL(filename).toString() });
|
|
const panels = [];
|
|
const vscode = {
|
|
Uri: { joinPath: (base, ...parts) => uri(path.join(base.fsPath, ...parts)) },
|
|
ViewColumn: { Beside: 2 },
|
|
window: { createWebviewPanel() {
|
|
const panel = { dispose() {}, onDidDispose() {}, webview: {
|
|
cspSource: 'https://dever-preview.test',
|
|
asWebviewUri: uri => `https://dever-preview.test/${path.basename(uri.fsPath)}`,
|
|
onDidReceiveMessage: () => ({ dispose() {} })
|
|
} };
|
|
panels.push(panel);
|
|
return panel;
|
|
} }
|
|
};
|
|
Module._load = function(request, ...rest) { return request === 'vscode' ? vscode : originalLoad.call(this, request, ...rest); };
|
|
const { openFlowPreview } = require('../../editor/vscode/dist/flow-preview.cjs');
|
|
Module._load = originalLoad;
|
|
browser = await playwright.launch({ executablePath: await chromium.executablePath(), args: chromium.args, headless: true });
|
|
const page = await browser.newPage();
|
|
page.on('pageerror', error => console.error('Browser error:', error.message));
|
|
page.on('console', message => { if (message.type() === 'error') console.error('Browser console:', message.text()); });
|
|
const scripts = new Map(await Promise.all(['flow-browser.js', 'mermaid.js'].map(async name => [`https://dever-preview.test/${name}`, await fs.readFile(path.join(extension, 'dist', name), 'utf8')])));
|
|
const messages = [];
|
|
await page.exposeFunction('deverMessage', message => messages.push(message));
|
|
await page.route('**/*', route => scripts.has(route.request().url())
|
|
? route.fulfill({ body: scripts.get(route.request().url()), contentType: 'text/javascript' }) : route.abort());
|
|
const projects = [project];
|
|
for (const relative of ['test/rust/fixtures/auth', 'test/rust/fixtures/adapters', 'skills/assets/examples/command', 'skills/assets/examples/external-lib']) {
|
|
const copy = path.join(root, path.basename(relative));
|
|
await fs.cp(path.resolve(__dirname, '../..', relative), copy, { recursive: true });
|
|
await run(process.env.DEVER_TEST_BIN, ['inspect', copy, '--links']);
|
|
projects.push(copy);
|
|
}
|
|
if (process.env.DEVER_FLOW_PROJECT) projects.push(process.env.DEVER_FLOW_PROJECT);
|
|
const targets = [];
|
|
for (const owner of projects) {
|
|
for await (const filename of fs.glob('module/*/*/link.md', { cwd: owner })) targets.push({ filename: path.join(owner, filename), owner });
|
|
}
|
|
let count = 0;
|
|
for (const { filename, owner } of targets) {
|
|
console.log(`Rendering ${filename}`);
|
|
await openFlowPreview({ subscriptions, extensionUri: uri(extension) }, uri(filename), owner);
|
|
const html = panels.at(-1).webview.html;
|
|
const expected = (html.match(/class="language-mermaid"/g) || []).length;
|
|
const nonce = /nonce="([^"]+)"/.exec(html)[1];
|
|
const bridge = `<script nonce="${nonce}">window.acquireVsCodeApi = () => ({postMessage: message => window.deverMessage(message)});</script>`;
|
|
await page.goto('about:blank');
|
|
await page.setContent(html.replace('<body ', `${bridge}<body `));
|
|
assert.equal(await page.evaluate(() => typeof globalThis.mermaid?.render), 'function');
|
|
await page.waitForSelector('body[data-rendered="true"]', { timeout: 60000 });
|
|
assert.deepEqual(await page.locator('.dever-flow-error').allTextContents(), [], filename);
|
|
assert.equal(await page.locator('.dever-flow > svg').count(), expected, filename);
|
|
assert.ok(expected > 0, filename);
|
|
count += expected;
|
|
const source = page.locator('.dever-flow a').first();
|
|
const href = await source.getAttribute('href') || await source.getAttribute('xlink:href');
|
|
await source.click();
|
|
await page.waitForTimeout(20);
|
|
assert.deepEqual(messages.at(-1), { type: 'open', href });
|
|
assert.match(href, /\.dever(?:\.md)?#L\d+,\d+$/);
|
|
if (process.env.DEVER_FLOW_SCREENSHOT && path.basename(path.dirname(filename)) === 'audit') {
|
|
await page.screenshot({ path: process.env.DEVER_FLOW_SCREENSHOT, fullPage: true });
|
|
}
|
|
}
|
|
console.log(`Rendered ${count} real generated diagrams in ${targets.length} pages without network dependencies`);
|
|
} finally {
|
|
Module._load = originalLoad;
|
|
await browser?.close();
|
|
for (const subscription of subscriptions) subscription.dispose();
|
|
await fs.rm(root, { recursive: true });
|
|
}
|
|
});
|