97 lines
4.5 KiB
JavaScript
97 lines
4.5 KiB
JavaScript
/**
|
||
* Проверка панели деталей на снимках с нарушением качества.
|
||
*
|
||
* Все файлы из `Для теста` модель считает качественными, поэтому ветка
|
||
* «нарушение» (бейдж, overall_quality=POOR, severity=HIGH, текст заключения)
|
||
* иначе остаётся непроверенной.
|
||
*
|
||
* Требуется запущенный сервер:
|
||
* python -m uvicorn src.main:app --port 8123
|
||
* node tests/browser/ui_violation.js
|
||
*
|
||
* Переменные окружения: BASE_URL, PLAYWRIGHT (см. ui_check.js).
|
||
*/
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const os = require('os');
|
||
|
||
function resolvePlaywright() {
|
||
if (process.env.PLAYWRIGHT) return process.env.PLAYWRIGHT;
|
||
const base = path.join(os.homedir(), '.qwen', 'updates', 'npm');
|
||
if (!fs.existsSync(base)) return 'playwright-core';
|
||
const versions = fs.readdirSync(path.join(base, fs.readdirSync(base)[0], 'versions')).sort();
|
||
for (const v of versions.reverse()) {
|
||
const candidate = path.join(
|
||
base, fs.readdirSync(base)[0], 'versions', v,
|
||
'node_modules/@qwen-code/qwen-code/bundled/browser-use/runtime/node_modules/playwright-core'
|
||
);
|
||
if (fs.existsSync(candidate)) return candidate;
|
||
}
|
||
return 'playwright-core';
|
||
}
|
||
|
||
const { chromium } = require(resolvePlaywright());
|
||
|
||
const BASE = process.env.BASE_URL || 'http://127.0.0.1:8123';
|
||
const REPO = path.resolve(__dirname, '..', '..');
|
||
const STUDY = 'dataset_hack/НД_для_обучения/Исследования';
|
||
// Два размеченных нарушения из обучающего набора (spine и hip_right).
|
||
const VIOLATIONS = [
|
||
path.join(REPO, STUDY, '2.25.11175860580562939441493697221497597640/series_003_2_CR/A2507431060 DXA/CR DXA/spine_01_bad.dcm'),
|
||
path.join(REPO, STUDY, '2.25.12798473087614376830819854616447908612/series_002_2_CR/A2507538847 DXA/CR DXA/r_hip_01_bad.dcm'),
|
||
];
|
||
|
||
(async () => {
|
||
const userDataDir = fs.mkdtempSync(path.join(require('os').tmpdir(), 'dxa-ui2-'));
|
||
const context = await chromium.launchPersistentContext(userDataDir, { channel: 'chrome', headless: true });
|
||
const page = context.pages()[0] || await context.newPage();
|
||
await page.setViewportSize({ width: 1400, height: 1200 });
|
||
|
||
const errors = [];
|
||
page.on('pageerror', (e) => errors.push('PAGEERROR ' + e.message));
|
||
await page.goto(BASE, { waitUntil: 'domcontentloaded' });
|
||
|
||
await page.setInputFiles('#fileInput', VIOLATIONS);
|
||
await page.waitForFunction(
|
||
() => document.querySelectorAll('#resultsTable tr').length === 2,
|
||
{ timeout: 60000 }
|
||
);
|
||
console.log('stats:', await page.evaluate(() => ({
|
||
total: document.getElementById('totalCount').innerText,
|
||
ok: document.getElementById('okCount').innerText,
|
||
violation: document.getElementById('violationCount').innerText,
|
||
})));
|
||
|
||
for (const idx of [0, 1]) {
|
||
await page.locator('#resultsTable tr').nth(idx).click();
|
||
await page.waitForTimeout(1200);
|
||
const s = await page.evaluate(() => {
|
||
const t = (id) => (document.getElementById(id) || {}).innerText?.replace(/\s+/g, ' ').trim();
|
||
const cards = (id) => Array.from((document.getElementById(id) || {}).children || [])
|
||
.map((c) => c.innerText.replace(/\s+/g, ' ').trim());
|
||
return {
|
||
badge: t('detailBadge'), quality: t('detailQuality'), overall: t('detailOverall'),
|
||
reason: t('detailReason'), roi: cards('detailArtifacts'), measurements: cards('detailMotion'),
|
||
spine: t('detailSpine'), hip: t('detailHip'),
|
||
spineHidden: document.getElementById('spineSection').classList.contains('hidden'),
|
||
hipHidden: document.getElementById('hipSection').classList.contains('hidden'),
|
||
};
|
||
});
|
||
console.log(`\n--- нарушение, строка ${idx} ---`);
|
||
console.log(' badge:', s.badge);
|
||
console.log(' quality:', s.quality);
|
||
console.log(' overall:', s.overall);
|
||
console.log(' roi:', s.roi);
|
||
console.log(' measurements:', s.measurements);
|
||
if (!s.spineHidden) console.log(' spine:', s.spine);
|
||
if (!s.hipHidden) console.log(' hip:', s.hip);
|
||
console.log(' reason:', s.reason);
|
||
await page.locator('#detailSection').scrollIntoViewIfNeeded();
|
||
await page.screenshot({ path: path.join(os.tmpdir(), `dxa_violation${idx}.png`) });
|
||
}
|
||
|
||
console.log('\npageerrors:', errors.length ? errors : 'none');
|
||
await context.close();
|
||
fs.rmSync(userDataDir, { recursive: true, force: true });
|
||
})().catch((e) => { console.error('FAILED:', e.message); process.exit(1); });
|