Initial commit: RHINE LAB · ANALYSIS OS:三维界面与动效实验(本仓库不含个人归档索引数据)
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import { createRequire } from 'node:module';
|
||||
import { mkdir, writeFile, readFile } from 'node:fs/promises';
|
||||
import assert from 'node:assert/strict';
|
||||
const require = createRequire(import.meta.url);
|
||||
const { chromium } = require(process.env.PLAYWRIGHT_MODULE || 'playwright');
|
||||
const browser = await chromium.launch({ channel: 'msedge', headless: true });
|
||||
const context = await browser.newContext({ viewport: { width: 1600, height: 900 } });
|
||||
const page = await context.newPage(), errors = [], results = {};
|
||||
page.on('pageerror', error => errors.push(String(error)));
|
||||
page.on('console', message => { if (message.type() === 'error' && /THREE|shader|WebGL/.test(message.text())) errors.push(message.text()); });
|
||||
const origin = process.env.REVIEW_URL || 'http://127.0.0.1:5188';
|
||||
await mkdir('verification/web-integration', { recursive: true });
|
||||
const stats = () => page.evaluate(() => window.rhine.stats());
|
||||
const close = async () => { await page.locator('[data-action="close-modal"]').click(); await page.waitForTimeout(350); };
|
||||
try {
|
||||
await page.goto(origin);
|
||||
await page.waitForFunction(() => window.rhine?.stats().ready);
|
||||
assert.equal((await stats()).startup, 'waiting');
|
||||
assert.equal(await page.locator('.entry-start').isVisible(), true);
|
||||
await page.locator('.entry-start').click();
|
||||
await page.waitForFunction(() => window.rhine.stats().startup === 'started');
|
||||
await page.evaluate(() => window.rhine.archive());
|
||||
await page.waitForTimeout(1000);
|
||||
assert.equal((await stats()).wallpaper, null);
|
||||
assert.equal(await page.locator('.three-toggle').count(), 0);
|
||||
assert.equal(await page.evaluate(() => typeof window.wallpaperPropertyListener), 'undefined');
|
||||
await page.locator('[data-action="settings"]').click();
|
||||
await page.locator('[data-color-theme="dark"]').click();
|
||||
await page.locator('[data-pref="superPerformance"]').check();
|
||||
await page.waitForTimeout(2000);
|
||||
results.fast = await stats();
|
||||
assert.equal(results.fast.superPerformance, true);
|
||||
assert.equal(results.fast.motion.reduced, false);
|
||||
const savedQuality = await page.evaluate(() => JSON.parse(localStorage.getItem('rhine-settings')).rendering);
|
||||
await close();
|
||||
await page.screenshot({ path: 'verification/web-integration/dark-fast.png' });
|
||||
await page.reload(); await page.waitForFunction(() => window.rhine?.stats().ready);
|
||||
await page.locator('.entry-start').click(); await page.waitForFunction(() => window.rhine.stats().startup === 'started');
|
||||
await page.evaluate(() => window.rhine.archive()); await page.waitForTimeout(800);
|
||||
assert.equal((await stats()).superPerformance, true);
|
||||
assert.equal(await page.evaluate(() => document.documentElement.dataset.darkSurface), 'true');
|
||||
await page.locator('[data-action="settings"]').click();
|
||||
await page.locator('[data-pref="superPerformance"]').uncheck();
|
||||
await close(); await page.waitForTimeout(1000);
|
||||
assert.equal((await stats()).superPerformance, false);
|
||||
assert.deepEqual(await page.evaluate(() => JSON.parse(localStorage.getItem('rhine-settings')).rendering), savedQuality);
|
||||
const before = (await stats()).selected;
|
||||
await page.keyboard.press('ArrowRight'); await page.waitForTimeout(700);
|
||||
assert.notEqual((await stats()).selected, before);
|
||||
const moving = await page.evaluate(async () => {
|
||||
for (let i = 0; i < 30; i++) { if (document.querySelector('#clock').getAnimations({ subtree: true }).some(a => a.playState === 'running')) return true; await new Promise(r => setTimeout(r, 60)); } return false;
|
||||
});
|
||||
assert.equal(moving, true);
|
||||
await page.evaluate(() => window.rhine.detail()); await page.waitForTimeout(2800);
|
||||
assert.equal((await stats()).mode, 'detail');
|
||||
await page.screenshot({ path: 'verification/web-integration/dark-detail.png' });
|
||||
await page.locator('[data-action="model-viewer"]').click(); await page.waitForTimeout(1600);
|
||||
assert.ok(await page.locator('canvas').count() >= 2);
|
||||
await page.keyboard.press('Escape'); await page.waitForTimeout(400);
|
||||
results.viewports = [];
|
||||
for (const [width, height] of [[2560,1080],[390,844],[844,390]]) {
|
||||
await page.setViewportSize({ width, height }); await page.waitForTimeout(600);
|
||||
assert.equal((await stats()).ready, true);
|
||||
const overflow = await page.evaluate(() => document.documentElement.scrollWidth > innerWidth + 1);
|
||||
assert.equal(overflow, false);
|
||||
results.viewports.push({ width, height, overflow });
|
||||
}
|
||||
await page.screenshot({ path: 'verification/web-integration/mobile-landscape.png' });
|
||||
const html = await readFile('dist/index.html', 'utf8');
|
||||
assert.match(html, /rel="manifest"/); assert.doesNotMatch(html, /wallpaperPropertyListener/);
|
||||
const worker = await readFile('dist/sw.js', 'utf8'); assert.ok(worker.length > 1000);
|
||||
assert.deepEqual(errors, []);
|
||||
results.startupGesture = results.persistedPerformance = results.restoredQuality = results.numericMotion = results.viewer = results.pwaBuild = true;
|
||||
results.errors = errors;
|
||||
await writeFile('verification/web-integration/results.json', JSON.stringify(results, null, 2));
|
||||
console.log('Web entry, host isolation, theme, performance persistence/restoration, keyboard, clock animation, detail/viewer, responsive and PWA build passed.');
|
||||
} finally { await browser.close(); }
|
||||
Reference in New Issue
Block a user