


























11// Control UI tests cover form controls behavior.
22import { chromium, type Browser, type Page } from "playwright";
3-import { afterAll, beforeAll, describe, expect, it } from "vitest";
3+import { describe, expect, it } from "vitest";
44import { readStyleSheet } from "../../../test/helpers/ui-style-fixtures.js";
55import {
66canRunPlaywrightChromium,
@@ -12,7 +12,10 @@ const describeBrowserLayout = canRunPlaywrightChromium(chromiumExecutablePath)
1212 ? describe
1313 : describe.skip;
141415-let browser: Browser;
15+type MobileFixture = {
16+browser: Browser;
17+page: Page;
18+};
16191720function readUiCss(): string {
1821const files = [
@@ -53,29 +56,35 @@ function controlsHtml() {
5356 `;
5457}
555856-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}
677868-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+}
768384+describeBrowserLayout("touch-primary form controls", () => {
7785it("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;
7988try {
8089const metrics = await page.evaluate(() => {
8190const selectors = [
@@ -119,12 +128,13 @@ describeBrowserLayout("touch-primary form controls", () => {
119128expect(size.fontSize, size.selector).toBeGreaterThanOrEqual(16);
120129}
121130} finally {
122-await page.close();
131+await closeMobileFixture(fixture);
123132}
124133});
125134126135it("keeps native select affordances visible in light mode", async () => {
127-const page = await openMobileFixture();
136+const fixture = await openMobileFixture();
137+const { page } = fixture;
128138try {
129139const selects = await page.locator(".cfg-select, .field select").evaluateAll((nodes) =>
130140nodes.map((node) => {
@@ -144,7 +154,7 @@ describeBrowserLayout("touch-primary form controls", () => {
144154expect(select.repeat).toContain("no-repeat");
145155}
146156} finally {
147-await page.close();
157+await closeMobileFixture(fixture);
148158}
149159});
150160});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。