9dfa06ffee
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Signed-off-by: cls_宁波本机 <908705107@qq.com>
173 lines
5.7 KiB
TypeScript
173 lines
5.7 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
||
import { readFileSync } from "node:fs";
|
||
|
||
import { installMockBridge } from "../helpers/bridge";
|
||
|
||
type TauriConfig = {
|
||
app: {
|
||
windows: Array<{
|
||
trafficLightPosition?: { x: number; y: number };
|
||
}>;
|
||
};
|
||
};
|
||
|
||
const tauriConfig = JSON.parse(
|
||
readFileSync(
|
||
new URL("../../src-tauri/tauri.conf.json", import.meta.url),
|
||
"utf8",
|
||
),
|
||
) as TauriConfig;
|
||
const EXPECTED_TRAFFIC_LIGHT_POSITION = { x: 16, y: 25 };
|
||
const EXPECTED_NAV_CENTER_Y = 23;
|
||
|
||
// The macOS traffic lights are native chrome: with `trafficLightPosition`
|
||
// x:16 they occupy roughly x 16–68 regardless of the app's Cmd +/- text
|
||
// zoom. The top-chrome nav row must clear that band in fixed px, so the
|
||
// clearance cannot shrink when the root font size scales down.
|
||
const TRAFFIC_LIGHT_RIGHT_EDGE = 72;
|
||
|
||
async function spoofMacPlatform(page: import("@playwright/test").Page) {
|
||
await page.addInitScript(() => {
|
||
Object.defineProperty(navigator, "platform", { get: () => "MacIntel" });
|
||
});
|
||
}
|
||
|
||
async function firstNavButtonX(page: import("@playwright/test").Page) {
|
||
const toggle = page.locator('[data-testid="app-top-chrome"] button').first();
|
||
await expect(toggle).toBeVisible();
|
||
const box = await toggle.boundingBox();
|
||
expect(box).not.toBeNull();
|
||
return box?.x ?? 0;
|
||
}
|
||
|
||
// The chrome buttons are styled to visually match the fixed-size native
|
||
// controls, so their box must not follow the rem text scale either. The
|
||
// sidebar toggle is 28px square; the back/forward history buttons share the
|
||
// height but are deliberately narrower (24px).
|
||
const NAV_BUTTON_SIZE = 28;
|
||
const HISTORY_BUTTON_WIDTH = 24;
|
||
|
||
// The grabber/drag strip hosting the buttons must hold its height too —
|
||
// otherwise Cmd+ balloons the bar around the fixed-size buttons and Cmd-
|
||
// collapses it.
|
||
const TOP_CHROME_BAR_HEIGHT = 40;
|
||
|
||
async function expectTopChromeFixedHeight(
|
||
page: import("@playwright/test").Page,
|
||
) {
|
||
const bar = page.getByTestId("app-top-chrome");
|
||
await expect(bar).toBeVisible();
|
||
const box = await bar.boundingBox();
|
||
expect(box).not.toBeNull();
|
||
expect(box?.height ?? 0).toBe(TOP_CHROME_BAR_HEIGHT);
|
||
}
|
||
|
||
async function expectNavButtonsFixedSize(
|
||
page: import("@playwright/test").Page,
|
||
) {
|
||
const buttons = page.locator('[data-testid="app-top-chrome"] button');
|
||
const count = await buttons.count();
|
||
expect(count).toBeGreaterThan(0);
|
||
for (let i = 0; i < count; i += 1) {
|
||
const button = buttons.nth(i);
|
||
const label = await button.getAttribute("aria-label");
|
||
const isHistoryButton = label === "Go back" || label === "Go forward";
|
||
const box = await button.boundingBox();
|
||
expect(box).not.toBeNull();
|
||
expect(box?.width ?? 0).toBe(
|
||
isHistoryButton ? HISTORY_BUTTON_WIDTH : NAV_BUTTON_SIZE,
|
||
);
|
||
expect(box?.height ?? 0).toBe(NAV_BUTTON_SIZE);
|
||
}
|
||
}
|
||
|
||
async function seedTextScale(
|
||
page: import("@playwright/test").Page,
|
||
scale: number,
|
||
) {
|
||
await page.addInitScript((value) => {
|
||
window.localStorage.setItem("buzz:text-scale", String(value));
|
||
}, scale);
|
||
}
|
||
|
||
async function expectRootFontSize(
|
||
page: import("@playwright/test").Page,
|
||
fontSize: string,
|
||
) {
|
||
await expect
|
||
.poll(() =>
|
||
page.evaluate(() => getComputedStyle(document.documentElement).fontSize),
|
||
)
|
||
.toBe(fontSize);
|
||
}
|
||
|
||
test.describe("top chrome macOS traffic-light clearance under text zoom", () => {
|
||
test("nav buttons clear the traffic lights at default zoom", async ({
|
||
page,
|
||
}) => {
|
||
await spoofMacPlatform(page);
|
||
await installMockBridge(page);
|
||
await page.goto("/");
|
||
|
||
// Lock the native and webview placements together: removing this explicit
|
||
// Tauri inset or shifting the nav row regresses the macOS chrome alignment.
|
||
expect(tauriConfig.app.windows[0]?.trafficLightPosition).toEqual(
|
||
EXPECTED_TRAFFIC_LIGHT_POSITION,
|
||
);
|
||
const toggleBox = await page
|
||
.getByRole("button", { name: "Toggle Sidebar", exact: true })
|
||
.boundingBox();
|
||
expect(toggleBox).not.toBeNull();
|
||
// Tauri interprets y:25 as a native titlebar inset, not the literal
|
||
// traffic-light center. The native controls use a small optical correction
|
||
// while the adjacent web controls remain centered at y:23.
|
||
expect((toggleBox?.y ?? 0) + (toggleBox?.height ?? 0) / 2).toBe(
|
||
EXPECTED_NAV_CENTER_Y,
|
||
);
|
||
|
||
expect(await firstNavButtonX(page)).toBeGreaterThanOrEqual(
|
||
TRAFFIC_LIGHT_RIGHT_EDGE,
|
||
);
|
||
await expectNavButtonsFixedSize(page);
|
||
await expectTopChromeFixedHeight(page);
|
||
});
|
||
|
||
test("nav buttons still clear the traffic lights when zoomed out", async ({
|
||
page,
|
||
}) => {
|
||
await spoofMacPlatform(page);
|
||
// Seed the minimum Cmd- text scale (0.75). The old rem-based clearance
|
||
// (pl-20 = 5rem) shrank to 60px here, sliding the buttons under the
|
||
// fixed-position native controls.
|
||
await seedTextScale(page, 0.75);
|
||
await installMockBridge(page);
|
||
await page.goto("/");
|
||
|
||
// Confirm the zoomed-out scale actually applied to the root font size.
|
||
await expectRootFontSize(page, "12px");
|
||
|
||
expect(await firstNavButtonX(page)).toBeGreaterThanOrEqual(
|
||
TRAFFIC_LIGHT_RIGHT_EDGE,
|
||
);
|
||
await expectNavButtonsFixedSize(page);
|
||
await expectTopChromeFixedHeight(page);
|
||
});
|
||
|
||
test("nav buttons keep their fixed size when zoomed in", async ({ page }) => {
|
||
await spoofMacPlatform(page);
|
||
// Seed the maximum Cmd+ text scale (1.5). Rem-sized buttons (h-7 = 42px
|
||
// here) grew visibly taller than the fixed-size traffic lights.
|
||
await seedTextScale(page, 1.5);
|
||
await installMockBridge(page);
|
||
await page.goto("/");
|
||
|
||
await expectRootFontSize(page, "24px");
|
||
|
||
expect(await firstNavButtonX(page)).toBeGreaterThanOrEqual(
|
||
TRAFFIC_LIGHT_RIGHT_EDGE,
|
||
);
|
||
await expectNavButtonsFixedSize(page);
|
||
await expectTopChromeFixedHeight(page);
|
||
});
|
||
});
|