Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ xvfb-run -a yarn test:webos
xvfb-run -a -s '-screen 0 1920x1080x24' yarn test:webos
```

The fixture starts the extracted Simulator executable directly with `--ozone-platform=x11` and `--no-sandbox`. It connects the installed Playwright package through `chromium.connectOverCDP()`. It selects the exact `file://` application target. It installs fixture interception before the tested reload. DNS resolution stays disabled, and unexpected external requests fail the test.
The fixture starts the extracted Simulator executable directly with `--ozone-platform=x11` and `--no-sandbox`. It connects the installed Playwright package through `chromium.connectOverCDP()`. It waits for the exact `file://` application target to initialize. Then it installs fixture interception before the tested reload. DNS resolution stays disabled, and unexpected external requests fail the test.

Each test gets a separate Simulator storage directory. Restart tests reuse that directory. Navigation uses CDP input, including webOS Back keycode `461`. The reports contain application screenshots, Simulator output, console errors, target details, Chromium versions, launch arguments, HTML, and JUnit. CI retains them for 14 days. The fixture stops the Simulator process group after each test. CI also stops remaining Simulator processes after a failure.

Expand Down
7 changes: 4 additions & 3 deletions tests/webos/simulator.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export class Simulator {
this.browser = await chromium.connectOverCDP(endpoint, { timeout: 15_000 });
const context = this.browser.contexts()[0];
if (!context) throw new Error('Simulator has no default context.');
// Interception can miss CDP targets that are still initializing.
await expect.poll(() => context.pages().filter(page => page.url() === appURL).length,
{ timeout: 15_000, message: 'Simulator must create exactly one application target.' }).toBe(1);
this.page = context.pages().find(page => page.url() === appURL)!;
await context.route('**/*', async route => {
const request = route.request();
if ([path.resolve('dist'), path.dirname(executable)].some(directory =>
Expand Down Expand Up @@ -106,9 +110,6 @@ export class Simulator {
}
await route.fulfill({ ...response, headers });
});
await expect.poll(() => context.pages().filter(page => page.url() === appURL).length,
{ timeout: 15_000, message: 'Simulator must create exactly one application target.' }).toBe(1);
this.page = context.pages().find(page => page.url() === appURL)!;
this.page.on('pageerror', error => this.errors.push(error.message));
this.page.on('console', message => { if (message.type() === 'error') this.consoleErrors.push(message.text()); });
this.input = await context.newCDPSession(this.page);
Expand Down
30 changes: 30 additions & 0 deletions tests/webos/startup.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { chromium, type Browser } from '@playwright/test';
import { test, expect } from './simulator.fixture';

const connect = chromium.connectOverCDP;

test.beforeAll(() => {
chromium.connectOverCDP = new Proxy(connect, {
async apply(target, receiver, args) {
const browser: Browser = await Reflect.apply(target, receiver, args);
const context = browser.contexts()[0];
const route = context.route.bind(context);
// Delay routing to reproduce the application target initialization race.
context.route = async (...args: Parameters<typeof context.route>) => {
await new Promise(resolve => setTimeout(resolve, 500));
return route(...args);
};
return browser;
},
});
});

test.afterAll(() => { chromium.connectOverCDP = connect; });

test('startup: fixtures work when interception is delayed', async ({ simulator }) => {
const page = simulator.page;
await expect(page.locator('#boot')).toHaveCount(0);
await expect(page.locator('.carouselTitle').first()).toHaveText('Fixture conference 0');
await simulator.key('ArrowRight');
await expect(page.locator('.embla__slide.active .embla__slide__title')).toHaveText('Other talk 0');
});
Loading