Files
buzz/desktop/tests/e2e/sidebar-more-unread-overlap.spec.ts
cls 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
feat: import Chinese-localized Buzz source snapshot
Signed-off-by: cls_宁波本机 <908705107@qq.com>
2026-08-13 18:34:25 +08:00

92 lines
3.2 KiB
TypeScript

/**
* Visual regression for the sidebar `MoreUnreadButton` (top variant)
* overlapping the macOS traffic-light region in the global top chrome.
*
* The old bug: `position="top"` anchored the pill at `top-0` inside a column
* starting at window y=0, so it sat inside the 40px chrome strip where the
* macOS traffic lights live on the native window.
*
* The current layout keeps the global top chrome in normal flow above the
* sidebar row, so `top-0` inside the sidebar starts below the traffic-light
* strip.
*
* This spec injects a synthetic pill into the live sidebar channel-content
* container (the same relative wrapper that owns the real top unread pill) and
* asserts the pill clears the pinned header.
*/
import { expect, test } from "@playwright/test";
import { waitForAnimations } from "../helpers/animations";
import { installMockBridge } from "../helpers/bridge";
const TOP_CLASS = "top-0";
const PILL_BASE =
"pointer-events-none absolute inset-x-0 z-10 flex justify-center py-1";
const PILL_INNER_HTML = `
<button
type="button"
class="pointer-events-auto inline-flex items-center gap-1 rounded-full bg-destructive px-2.5 py-0.5 text-xs font-medium text-destructive-foreground shadow-sm"
>
<span>↑ 12 new</span>
</button>
`;
async function injectSyntheticPill(
page: import("@playwright/test").Page,
topClass: string,
testId: string,
) {
await page.evaluate(
({ topClass, base, html, testId }) => {
const container = document.querySelector(
'[data-testid="sidebar-channel-content"]',
) as HTMLElement | null;
if (!container) throw new Error("sidebar channel content not found");
// Remove any prior injection so retries start from a clean sidebar.
container
.querySelectorAll("[data-synthetic-more-unread]")
.forEach((el) => {
el.remove();
});
const pill = document.createElement("div");
pill.dataset.syntheticMoreUnread = "true";
pill.dataset.testid = testId;
pill.className = `${base} ${topClass}`;
pill.innerHTML = html;
container.appendChild(pill);
},
{ topClass, base: PILL_BASE, html: PILL_INNER_HTML, testId },
);
}
test.describe("sidebar MoreUnreadButton top chrome overlap", () => {
test.beforeEach(async ({ page }) => {
await installMockBridge(page);
await page.goto("/");
await expect(page.getByTestId("app-sidebar")).toBeVisible();
});
test("top pill clears the pinned header", async ({ page }) => {
await injectSyntheticPill(page, TOP_CLASS, "synthetic-top");
const pill = page.getByTestId("synthetic-top");
const pinnedHeader = page.getByTestId("sidebar-pinned-header");
await expect(pill).toBeVisible();
await expect(pinnedHeader).toBeVisible();
const pillBox = await pill.boundingBox();
const pinnedHeaderBox = await pinnedHeader.boundingBox();
expect(pillBox).not.toBeNull();
expect(pinnedHeaderBox).not.toBeNull();
expect(pillBox?.y ?? Number.NaN).toBeGreaterThanOrEqual(
pinnedHeaderBox?.y == null || pinnedHeaderBox.height == null
? Number.NaN
: pinnedHeaderBox.y + pinnedHeaderBox.height,
);
await waitForAnimations(page);
});
});