Ctrl K
ComunidadGuías…

frontend/e2e/media-processing-settings.test.ts

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import assert from 'node:assert/strict';
import { mkdir } from 'node:fs/promises';
import path from 'node:path';
import { after, before, describe, it } from 'node:test';
import type { Browser, Page } from 'playwright-core';
import { launch, layout, settle, visit, VIEWPORTS } from './harness.ts';

/** 这台机器的媒体处理偏好:页面写进来的值留在这一份里,重新载入读回的就是它。 */
function mediaProcessing() {
  const state = { disabled: false, timeline: 'coarse', previewAcceleration: 'auto', playbackAcceleration: 'auto' };
  const writes: unknown[] = [];
  const route = async (page: Page) => {
    await page.route('**/api/media-processing', async route => {
      if (route.request().method() === 'POST') {
        const body = route.request().postDataJSON();
        writes.push(body);
        if ('metadata_only' in body) {
          state.disabled = body.metadata_only;
          if (state.disabled) state.timeline = 'off';
        }
        if ('preview_acceleration' in body) state.previewAcceleration = body.preview_acceleration;
        if ('playback_acceleration' in body) state.playbackAcceleration = body.playback_acceleration;
      }
      await route.fulfill({ json: { metadata_only: state.disabled,
        preview_acceleration: state.previewAcceleration, playback_acceleration: state.playbackAcceleration } });
    });
    await page.route('**/api/thumbnail-jobs', route => route.fulfill({ json: { mode: state.timeline, status: 'idle' } }));
  };
  return { state, writes, route };
}

describe('视频预览设置', () => {
  let browser: Browser;
  before(async () => { browser = await launch() });
  after(async () => { await browser?.close() });
  for (const viewport of VIEWPORTS) {
    it(`${viewport.name}:总开关持久化并控制时间轴设置,重新开启后时间轴由用户选择`, async () => {
      const { state, writes, route } = mediaProcessing();
      const opened = await visit(browser, '/settings/library', viewport, route);
      const { page } = opened;
      try {
        const toggle = page.getByRole('switch', { name: '生成视频预览', exact: true });
        const interval = page.locator('#videoThumbnailSetting button');
        await toggle.waitFor();
        await settle(page);
        assert.equal(await toggle.isChecked(), true);
        assert.equal(await interval.isDisabled(), false);
        await page.locator('label').filter({ has: toggle }).click();
        await page.getByText('已关闭视频预览生成', { exact: true }).waitFor();
        assert.equal(await toggle.isChecked(), false);
        assert.equal(await interval.isDisabled(), true);
        await page.reload();
        await toggle.waitFor();
        await settle(page);
        assert.equal(await toggle.isChecked(), false);
        assert.equal(await interval.isDisabled(), true);
        assert.match(await interval.innerText(), /关闭/);
        await toggle.focus();
        await page.keyboard.press('Space');
        await page.getByText('已开启视频预览生成', { exact: true }).waitFor();
        assert.equal(await interval.isDisabled(), false);
        assert.match(await interval.innerText(), /关闭/);
        assert.deepEqual(writes, [{ metadata_only: true }, { metadata_only: false }]);
        const preview = page.locator('#previewAccelerationSetting button');
        await preview.click();
        await page.getByRole('option', { name: '软件解码', exact: true }).click();
        await page.getByText('已保存抽帧解码方式', { exact: true }).waitFor();
        assert.equal(state.previewAcceleration, 'software');
        assert.equal(state.playbackAcceleration, 'auto');
        assert.deepEqual(writes.slice(-1), [{ preview_acceleration: 'software' }]);
        // 播放转码在「应用与维护 → 视频播放」,这一页签里只有抽帧解码方式。
        assert.equal(await page.locator('.ui-board-group-active #playbackAccelerationSetting').count(), 0);
        await page.reload();
        await preview.waitFor();
        await settle(page);
        assert.match(await preview.innerText(), /软件解码/);
        const measured = await layout(page);
        assert.ok(measured.scrollWidth <= measured.viewportWidth, JSON.stringify(measured));
        assert.deepEqual(measured.offenders, []);
        const artifacts = path.resolve('..', 'build', 'agent-verification', 'media-processing');
        await mkdir(artifacts, { recursive: true });
        await page.screenshot({ path: path.join(artifacts, `${viewport.name}.png`), fullPage: true });
        assert.deepEqual(opened.problems, []);
      } finally { await opened.close() }
    });

    it(`${viewport.name}:「应用与维护 → 视频播放」里改转码方式,只写这一项,重新载入读回`, async () => {
      const { state, writes, route } = mediaProcessing();
      const opened = await visit(browser, '/settings/maintenance', viewport, route);
      const { page } = opened;
      try {
        const section = page.getByRole('region', { name: '视频播放', exact: true });
        const trigger = section.locator('#playbackAccelerationSetting button');
        await trigger.waitFor({ state: 'visible' });
        await page.waitForFunction(() => document.querySelector('#playbackAccelerationSetting button')?.hasAttribute('disabled') === false);
        await settle(page);
        assert.match(await trigger.innerText(), /自动/);
        /* 这张卡排在首屏以下。先滚到位、等两帧让滚动事件派发完:下拉打开之后再收到触发框所在页面的
           滚动,React Aria 会把它合上。 */
        await trigger.scrollIntoViewIfNeeded();
        await page.evaluate(() => new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve))));
        await trigger.click();
        await page.getByRole('option', { name: '软件编解码', exact: true }).click();
        await page.getByText('已保存转码方式', { exact: true }).waitFor();
        assert.equal(state.playbackAcceleration, 'software');
        assert.equal(state.previewAcceleration, 'auto');
        assert.deepEqual(writes, [{ playback_acceleration: 'software' }]);
        // 「视频播放」排在「开机自启」之后、「存储空间」之前(没有这两张卡的环境只比相对次序)。
        const order = await page.locator('.ui-board-group-active').evaluate((group) =>
          [...group.querySelectorAll('section[aria-label], form[aria-label]')].map((node) => node.getAttribute('aria-label')));
        const at = order.indexOf('视频播放');
        assert.ok(at >= 0 && order.slice(0, at).every((name) => ['检查更新', '自动修复', '自动更新', '开机自启'].includes(name ?? '')), JSON.stringify(order));
        await page.reload();
        await trigger.waitFor({ state: 'visible' });
        await page.waitForFunction(() => /软件编解码/.test(document.querySelector('#playbackAccelerationSetting button')?.textContent || ''));
        const measured = await layout(page);
        assert.ok(measured.scrollWidth <= measured.viewportWidth, JSON.stringify(measured));
        assert.deepEqual(measured.offenders, []);
        assert.deepEqual(opened.problems, []);
      } finally { await opened.close() }
    });
  }
});