test: add deterministic resilience matrix
This commit is contained in:
76
tests/browser/context-loss.spec.ts
Normal file
76
tests/browser/context-loss.spec.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { expect, test } from '../helpers/serve-dist';
|
||||
import {
|
||||
assertSemanticFaultOracle,
|
||||
authorizedFaultUrl,
|
||||
collectBrowserErrors,
|
||||
readUnhandledRejections,
|
||||
triggerFaultAction,
|
||||
} from '../helpers/test-build-auth';
|
||||
import { installSceneInstrumentation, readSceneInstrumentation } from '../helpers/scene-instrumentation';
|
||||
|
||||
test.beforeEach(async ({ page }, testInfo) => {
|
||||
test.skip(testInfo.project.name !== 'desktop-chromium', 'Lifecycle faults run once on current desktop Chromium.');
|
||||
await installSceneInstrumentation(page);
|
||||
});
|
||||
|
||||
const assertContained = async (page: import('@playwright/test').Page, pageErrors: readonly string[]): Promise<void> => {
|
||||
expect(pageErrors).toEqual([]);
|
||||
expect(await readUnhandledRejections(page)).toEqual([]);
|
||||
const resources = await readSceneInstrumentation(page);
|
||||
expect(resources.unhandledRejections).toEqual([]);
|
||||
expect(resources.maximumCanvasCount).toBeLessThanOrEqual(1);
|
||||
expect(resources.activeAnimationFrames).toBeLessThanOrEqual(1);
|
||||
};
|
||||
|
||||
test('F4 restores one visible lost context before the five-second cutoff', async ({ page, distUrl }) => {
|
||||
const errors = await collectBrowserErrors(page);
|
||||
await page.goto(authorizedFaultUrl(distUrl, 'F4-context-loss-restore'), { waitUntil: 'domcontentloaded' });
|
||||
await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'running');
|
||||
const firstGeneration = await page.locator('.journey-world').getAttribute('data-scene-generation');
|
||||
|
||||
await triggerFaultAction(page, 'context-loss');
|
||||
await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'loading');
|
||||
await triggerFaultAction(page, 'context-restore');
|
||||
await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'running');
|
||||
|
||||
await expect(page.locator('.journey-world')).not.toHaveAttribute('data-scene-generation', firstGeneration ?? '');
|
||||
await expect(page.locator('.journey-canvas')).toHaveCount(1);
|
||||
await assertSemanticFaultOracle(page);
|
||||
await assertContained(page, errors.pageErrors);
|
||||
});
|
||||
|
||||
test('F5 defers a hidden restoration until the first visible lifecycle task', async ({ page, distUrl }) => {
|
||||
const errors = await collectBrowserErrors(page);
|
||||
await page.goto(authorizedFaultUrl(distUrl, 'F5-hidden-context-loss'), { waitUntil: 'domcontentloaded' });
|
||||
await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'running');
|
||||
|
||||
await page.evaluate(() => window.dispatchEvent(new PageTransitionEvent('pagehide', { persisted: true })));
|
||||
await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'paused');
|
||||
await triggerFaultAction(page, 'context-loss');
|
||||
await triggerFaultAction(page, 'context-restore');
|
||||
await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'loading');
|
||||
|
||||
await page.evaluate(() => window.dispatchEvent(new PageTransitionEvent('pageshow', { persisted: true })));
|
||||
await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'running');
|
||||
await expect(page.locator('.journey-canvas')).toHaveCount(1);
|
||||
await assertSemanticFaultOracle(page);
|
||||
await assertContained(page, errors.pageErrors);
|
||||
});
|
||||
|
||||
test('F6 makes a later context loss terminal for the session', async ({ page, distUrl }) => {
|
||||
const errors = await collectBrowserErrors(page);
|
||||
await page.goto(authorizedFaultUrl(distUrl, 'F6-repeated-context-loss'), { waitUntil: 'domcontentloaded' });
|
||||
await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'running');
|
||||
|
||||
await triggerFaultAction(page, 'context-loss');
|
||||
await triggerFaultAction(page, 'context-restore');
|
||||
await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'running');
|
||||
await triggerFaultAction(page, 'context-loss');
|
||||
|
||||
await expect(page.locator('.journey-world')).toHaveAttribute('data-scene-state', 'static');
|
||||
await expect(page.locator('.journey-world')).toHaveAttribute('data-static-fallback', 'true');
|
||||
await expect(page.locator('.journey-canvas')).toHaveCount(0);
|
||||
await expect(page.locator('.drive-controls__status')).toHaveText('Visuals unavailable');
|
||||
await assertSemanticFaultOracle(page);
|
||||
await assertContained(page, errors.pageErrors);
|
||||
});
|
||||
Reference in New Issue
Block a user