frontend/e2e/detail-link-return.test.ts
Rama master · réplica de lectura del repositorio original.
import assert from 'node:assert/strict';
import { after, before, describe, it } from 'node:test';
import type { Browser } from 'playwright-core';
import { launch, layout, VIEWPORTS } from './harness.ts';
import { FAILED_JOB } from './design-fixture.ts';
import { ITEM, openItemPage } from './item-fixture.ts';
describe('问题清单详情返回', () => {
let browser: Browser;
before(async () => { browser = await launch() });
after(async () => { await browser?.close() });
for (const viewport of VIEWPORTS) {
it(`${viewport.name}:退出详情保留数据管理页、展开的清单与来源地址`, { timeout: 60_000 }, async () => {
const opened = await openItemPage(browser, '/', viewport, { ready: '#grid [data-media-card]' });
const { page } = opened;
try {
await page.route('**/api/library-processing{,?*}', route => route.fulfill({ json: {
...FAILED_JOB, issue_preview: [{ ...FAILED_JOB.issue_preview[0], asset_id: ITEM.plain }],
} }));
const source = '/data-cleanup?view=issues#libraryProcessing';
await page.goto(new URL(source, page.url()).href);
const summary = page.locator('#libraryProcessing summary');
await summary.click();
const link = page.locator(`#libraryProcessing a[href^="/assets/${ITEM.plain}"]`);
const requests: string[] = [];
page.on('request', request => { if (request.isNavigationRequest()) requests.push(request.url()) });
await link.scrollIntoViewIfNeeded();
const sourceScroll = await page.evaluate(() => scrollY);
await link.click();
await page.locator('#stage[open] [data-item-side]').waitFor();
assert.deepEqual(requests, [], '站内打开详情保持当前文档');
await page.locator('#closeStage').click();
await page.waitForFunction(expected => location.pathname + location.search + location.hash === expected, source);
await link.waitFor({ state: 'visible' });
assert.equal(await summary.getAttribute('aria-expanded'), 'true');
assert.ok(Math.abs(await page.evaluate(() => scrollY) - sourceScroll) < 2, '关闭详情保留原来的滚动位置');
await link.evaluate(element => { element.setAttribute('href', element.getAttribute('href') + '?t=1') });
await link.click();
await page.waitForFunction(() => location.search === '?t=1');
await page.locator('#stage[open] [data-item-side]').waitFor();
assert.deepEqual(await page.evaluate(() => history.state?.usr?.backgroundLocation), {
pathname: '/data-cleanup', search: '?view=issues', hash: '#libraryProcessing',
});
await page.goBack();
await page.waitForFunction(expected => location.pathname + location.search + location.hash === expected, source);
await summary.waitFor({ state: 'visible' });
await page.goForward();
await page.locator('#stage[open] [data-item-side]').waitFor();
await page.locator('#closeStage').click();
await page.waitForFunction(expected => location.pathname + location.search + location.hash === expected, source);
await summary.waitFor({ state: 'visible' });
assert.deepEqual(requests, []);
const geometry = await layout(page);
assert.ok(geometry.scrollWidth <= geometry.viewportWidth, JSON.stringify(geometry));
assert.deepEqual(geometry.offenders, []);
assert.deepEqual(opened.problems.filter(line => !line.includes('VIDEOJS')), []);
} finally { await opened.close() }
});
}
});