Skip to content

Commit f062171

Browse files
committed
test(ui): isolate mobile form control browser fixtures
1 parent b677ea6 commit f062171

1 file changed

Lines changed: 34 additions & 24 deletions

File tree

ui/src/ui/form-controls.browser.test.ts

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Control UI tests cover form controls behavior.
22
import { chromium, type Browser, type Page } from "playwright";
3-
import { afterAll, beforeAll, describe, expect, it } from "vitest";
3+
import { describe, expect, it } from "vitest";
44
import { readStyleSheet } from "../../../test/helpers/ui-style-fixtures.js";
55
import {
66
canRunPlaywrightChromium,
@@ -12,7 +12,10 @@ const describeBrowserLayout = canRunPlaywrightChromium(chromiumExecutablePath)
1212
? describe
1313
: describe.skip;
1414

15-
let browser: Browser;
15+
type MobileFixture = {
16+
browser: Browser;
17+
page: Page;
18+
};
1619

1720
function readUiCss(): string {
1821
const files = [
@@ -53,29 +56,35 @@ function controlsHtml() {
5356
`;
5457
}
5558

56-
async function openMobileFixture(): Promise<Page> {
57-
const page = await browser.newPage({
58-
hasTouch: true,
59-
isMobile: true,
60-
viewport: { width: 390, height: 844 },
61-
});
62-
await page.setContent(
63-
`<!doctype html><html data-theme-mode="light"><head><style>${readUiCss()}</style></head><body>${controlsHtml()}</body></html>`,
64-
);
65-
return page;
59+
async function openMobileFixture(): Promise<MobileFixture> {
60+
const browser = await chromium.launch({ executablePath: chromiumExecutablePath, headless: true });
61+
let page: Page | undefined;
62+
try {
63+
page = await browser.newPage({
64+
hasTouch: true,
65+
isMobile: true,
66+
viewport: { width: 390, height: 844 },
67+
});
68+
await page.setContent(
69+
`<!doctype html><html data-theme-mode="light"><head><style>${readUiCss()}</style></head><body>${controlsHtml()}</body></html>`,
70+
);
71+
return { browser, page };
72+
} catch (error) {
73+
await page?.close().catch(() => {});
74+
await browser.close().catch(() => {});
75+
throw error;
76+
}
6677
}
6778

68-
describeBrowserLayout("touch-primary form controls", () => {
69-
beforeAll(async () => {
70-
browser = await chromium.launch({ executablePath: chromiumExecutablePath, headless: true });
71-
});
72-
73-
afterAll(async () => {
74-
await browser.close();
75-
});
79+
async function closeMobileFixture(fixture: MobileFixture): Promise<void> {
80+
await fixture.page.close().catch(() => {});
81+
await fixture.browser.close().catch(() => {});
82+
}
7683

84+
describeBrowserLayout("touch-primary form controls", () => {
7785
it("keeps text-entry controls large enough to avoid mobile focus zoom", async () => {
78-
const page = await openMobileFixture();
86+
const fixture = await openMobileFixture();
87+
const { page } = fixture;
7988
try {
8089
const metrics = await page.evaluate(() => {
8190
const selectors = [
@@ -119,12 +128,13 @@ describeBrowserLayout("touch-primary form controls", () => {
119128
expect(size.fontSize, size.selector).toBeGreaterThanOrEqual(16);
120129
}
121130
} finally {
122-
await page.close();
131+
await closeMobileFixture(fixture);
123132
}
124133
});
125134

126135
it("keeps native select affordances visible in light mode", async () => {
127-
const page = await openMobileFixture();
136+
const fixture = await openMobileFixture();
137+
const { page } = fixture;
128138
try {
129139
const selects = await page.locator(".cfg-select, .field select").evaluateAll((nodes) =>
130140
nodes.map((node) => {
@@ -144,7 +154,7 @@ describeBrowserLayout("touch-primary form controls", () => {
144154
expect(select.repeat).toContain("no-repeat");
145155
}
146156
} finally {
147-
await page.close();
157+
await closeMobileFixture(fixture);
148158
}
149159
});
150160
});

0 commit comments

Comments
 (0)