C内核流量计算方法优化,前端文件名称读取优化
This commit is contained in:
1 parent
5d5a2e1843
commit
808c484f5b
94 files changed
+20163
-4418
No files matched your search
@@ -0,0 +1,89 @@
|
||||
// Real browser/HTTP/native execution. No API routes or result data are mocked.
|
||||
import { chromium } from '../../frontend/node_modules/playwright/index.mjs';
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { performance } from 'node:perf_hooks';
|
||||
import assert from 'node:assert/strict';
|
||||
import { createHash } from 'node:crypto';
|
||||
const [input, output, baseURL = 'http://127.0.0.1:8011', runCount = '3'] = process.argv.slice(2);
|
||||
if (!input || !output) throw new Error('Usage: node browser_native_simulation.mjs MODEL.json OUTPUT_DIR [URL] [RUNS]');
|
||||
await fs.mkdir(output, { recursive: true });
|
||||
const inputText = await fs.readFile(input, 'utf8');
|
||||
const project = JSON.parse(inputText);
|
||||
const curveNodeId = project.nodes.find(node => node.id === 'amesim_pnl0002_10')?.id
|
||||
?? project.nodes.find(node => node.data.modelType === 'amesim_pnl0002')?.id;
|
||||
if (!curveNodeId) throw new Error('Curve verification requires a PNL0002 component.');
|
||||
await fs.writeFile(path.join(output, 'input.json'), inputText);
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
const context = await browser.newContext({ viewport: { width: 1600, height: 1000 }, acceptDownloads: true });
|
||||
const page = await context.newPage();
|
||||
page.setDefaultTimeout(30000);
|
||||
const errors = [];
|
||||
page.on('pageerror', error => errors.push(String(error)));
|
||||
const rows = [];
|
||||
try {
|
||||
await page.goto(baseURL);
|
||||
await page.locator('input[type="file"][accept*=".json"]').setInputFiles(path.resolve(input));
|
||||
await page.getByRole('textbox', { name: '工程', exact: true }).waitFor();
|
||||
await page.waitForFunction(name => document.querySelector('input[aria-label="工程"]')?.value === name || [...document.querySelectorAll('input')].some(input => input.value === name), path.basename(input, path.extname(input)));
|
||||
await page.screenshot({ path: path.join(output, 'model.png'), fullPage: true });
|
||||
for (let i = 0; i <= Number(runCount); i++) {
|
||||
const oldMarker = await page.evaluate(() => sessionStorage.getItem('system-simulation-flow:latest-result'));
|
||||
const responsePromise = page.waitForResponse(response => response.url().endsWith('/api/system-xml/simulate-stream'), { timeout: 180000 });
|
||||
const started = performance.now();
|
||||
await page.getByRole('button', { name: '运行仿真', exact: true }).click();
|
||||
const response = await responsePromise;
|
||||
await response.finished();
|
||||
if (!response.ok()) throw new Error(`Simulation HTTP ${response.status()}`);
|
||||
const receivedMs = performance.now() - started;
|
||||
await page.waitForFunction(old => {
|
||||
const marker = sessionStorage.getItem('system-simulation-flow:latest-result');
|
||||
return marker && marker !== old && JSON.parse(marker).storage === 'indexeddb';
|
||||
}, oldMarker, { timeout: 180000 });
|
||||
await page.getByRole('button', { name: '运行仿真', exact: true }).waitFor({ state: 'visible' });
|
||||
await page.waitForFunction(() => !document.querySelector('button[aria-label="运行仿真"]')?.disabled);
|
||||
await page.getByRole('tab', { name: /^结果/ }).click();
|
||||
await page.getByRole('button', { name: '下载结果文件', exact: true }).waitFor();
|
||||
const readyMs = performance.now() - started;
|
||||
await page.waitForFunction(old => {
|
||||
const marker = sessionStorage.getItem('system-simulation-flow:latest-result');
|
||||
return marker && marker !== old && JSON.parse(marker).storage === 'indexeddb';
|
||||
}, oldMarker);
|
||||
const downloadPromise = page.waitForEvent('download');
|
||||
await page.getByRole('button', { name: '下载结果文件', exact: true }).click();
|
||||
await (await downloadPromise).saveAs(path.join(output, `run-${i}.simresult`));
|
||||
const exported = JSON.parse(await fs.readFile(path.join(output, `run-${i}.simresult`), 'utf8'));
|
||||
const result = exported.snapshot.result;
|
||||
if (!result.success) throw new Error(result.message);
|
||||
assert.equal(result.diagnostics.integration.rtol, 1e-8);
|
||||
assert.equal(result.simulatedUntil, project.simulation.t_stop);
|
||||
const row = { run: i, receivedMs, readyMs, sampleCount: result.series.time.length,
|
||||
...result.diagnostics.native };
|
||||
rows.push(row);
|
||||
console.log(JSON.stringify(row));
|
||||
if (i < Number(runCount)) await page.getByRole('tab', { name: '建模', exact: true }).click();
|
||||
}
|
||||
await page.getByRole('button', { name: '适应系统图窗口', exact: true }).click();
|
||||
await page.locator(`.results-system-panel .react-flow__node[data-id=${JSON.stringify(curveNodeId)}]`).click();
|
||||
await page.locator('.results-variable-list button').filter({ has: page.locator('small', { hasText: /^K$/ }) }).first().click();
|
||||
await page.locator('.results-chart-panel .result-chart-window svg').first().waitFor();
|
||||
const csvDownload = page.waitForEvent('download');
|
||||
await page.getByRole('button', { name: '下载结果 CSV', exact: true }).click();
|
||||
await (await csvDownload).saveAs(path.join(output, 'result.csv'));
|
||||
await page.screenshot({ path: path.join(output, 'result.png'), fullPage: true });
|
||||
await page.reload();
|
||||
await page.getByRole('tab', { name: /^结果/ }).click();
|
||||
await page.getByRole('button', { name: '下载结果文件', exact: true }).waitFor();
|
||||
const restored = page.waitForEvent('download');
|
||||
await page.getByRole('button', { name: '下载结果文件', exact: true }).click();
|
||||
await (await restored).saveAs(path.join(output, 'restored.simresult'));
|
||||
const restoredData = JSON.parse(await fs.readFile(path.join(output, 'restored.simresult'), 'utf8'));
|
||||
const lastData = JSON.parse(await fs.readFile(path.join(output, `run-${runCount}.simresult`), 'utf8'));
|
||||
assert.deepEqual(restoredData.snapshot.result, lastData.snapshot.result);
|
||||
await fs.writeFile(path.join(output, 'summary.json'), JSON.stringify({ input: path.resolve(input), inputSha256: createHash('sha256').update(inputText).digest('hex'), baseURL, browser: browser.version(), rows, errors, restored: true, restoredResultIdentical: true, csvExported: true }, null, 2));
|
||||
if (errors.length) throw new Error(`Browser errors: ${errors.join('\n')}`);
|
||||
} catch (error) {
|
||||
await page.screenshot({ path: path.join(output, 'failure.png'), fullPage: true });
|
||||
await fs.writeFile(path.join(output, 'failure.txt'), `${error.stack}\nPage errors: ${JSON.stringify(errors)}\n${await page.locator('body').innerText()}`);
|
||||
throw error;
|
||||
} finally { await context.close(); await browser.close(); }
|
||||
Reference in new issue
Block a user