mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
test(desktop): scale zoom visual expectations
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
This commit is contained in:
co-authored by
Taylor Ho
parent
7e241e2372
commit
f2cd060c19
@@ -90,13 +90,13 @@ test("estimateRowHeight: bare URL line adds a preview card", () => {
|
||||
assert.ok(withUrl > withoutUrl + 50, `url ${withUrl} vs ${withoutUrl}`);
|
||||
});
|
||||
|
||||
test("timelineRowReserveStyle: message item yields containIntrinsicSize", () => {
|
||||
test("timelineRowReserveStyle: message item yields rem containIntrinsicSize", () => {
|
||||
const style = timelineRowReserveStyle({
|
||||
kind: "message",
|
||||
key: "k",
|
||||
entry: { message: msg({ body: "hi" }), summary: null },
|
||||
});
|
||||
assert.match(String(style.containIntrinsicSize), /^auto \d+px$/);
|
||||
assert.match(String(style.containIntrinsicSize), /^auto \d+(?:\.\d+)?rem$/);
|
||||
});
|
||||
|
||||
test("timelineRowReserveStyle: divider is short fixed height", () => {
|
||||
@@ -105,5 +105,5 @@ test("timelineRowReserveStyle: divider is short fixed height", () => {
|
||||
key: "k",
|
||||
headingTimestamp: 0,
|
||||
});
|
||||
assert.equal(style.containIntrinsicSize, "auto 32px");
|
||||
assert.equal(style.containIntrinsicSize, "auto 2rem");
|
||||
});
|
||||
|
||||
@@ -175,5 +175,5 @@ export function timelineRowReserveStyle(
|
||||
: item.kind === "system"
|
||||
? estimateRowHeight(item.entry.message)
|
||||
: DIVIDER_HEIGHT;
|
||||
return { containIntrinsicSize: `auto ${height}px` };
|
||||
return { containIntrinsicSize: `auto ${height / 16}rem` };
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
installMockBridge,
|
||||
openChannelBrowser,
|
||||
} from "../helpers/bridge";
|
||||
import { expectedScaledPx } from "../helpers/css";
|
||||
|
||||
const GENERAL_CHANNEL_ID = "9a1657ac-f7aa-5db0-b632-d8bbeb6dfb50";
|
||||
const MOCK_IDENTITY_PUBKEY = "deadbeef".repeat(8);
|
||||
@@ -276,7 +277,9 @@ async function expectSameLeftInset(
|
||||
throw new Error(`Could not measure ${firstTestId} against ${secondTestId}`);
|
||||
}
|
||||
|
||||
expect(Math.abs(firstBox.x - secondBox.x)).toBeLessThanOrEqual(4);
|
||||
expect(Math.abs(firstBox.x - secondBox.x)).toBeLessThanOrEqual(
|
||||
await expectedScaledPx(page.getByTestId(firstTestId), 4),
|
||||
);
|
||||
}
|
||||
|
||||
async function expectIntroSpacedAboveDayDivider(
|
||||
@@ -325,9 +328,14 @@ async function expectIntroActionCardLayout(
|
||||
}
|
||||
|
||||
expect(actionBox.height).toBeGreaterThan(actionBox.width);
|
||||
expect(Math.round(actionBox.width)).toBe(220);
|
||||
expect(Math.round(iconBox.width)).toBe(48);
|
||||
expect(Math.round(iconBox.height)).toBe(48);
|
||||
expect(Math.round(actionBox.width)).toBe(
|
||||
Math.round(await expectedScaledPx(page.getByTestId(actionTestId), 220)),
|
||||
);
|
||||
const expectedIconSize = Math.round(
|
||||
await expectedScaledPx(page.getByTestId(`${actionTestId}-icon`), 48),
|
||||
);
|
||||
expect(Math.round(iconBox.width)).toBe(expectedIconSize);
|
||||
expect(Math.round(iconBox.height)).toBe(expectedIconSize);
|
||||
const introIconRadius = await page
|
||||
.getByTestId("message-channel-intro-icon")
|
||||
.evaluate((element) => window.getComputedStyle(element).borderRadius);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
import { installMockBridge } from "../helpers/bridge";
|
||||
import { expectedScaledPx } from "../helpers/css";
|
||||
|
||||
// Custom-emoji end-to-end guard.
|
||||
//
|
||||
@@ -271,14 +272,34 @@ test("reacting with a custom emoji renders via the loopback media proxy", async
|
||||
}),
|
||||
)
|
||||
.toBe("0");
|
||||
const expectedInlineReactionButtonWidth = Math.round(
|
||||
await expectedScaledPx(inlineAddReactionButton, 40),
|
||||
);
|
||||
const minExpectedInlineReactionButtonHeight = Math.round(
|
||||
await expectedScaledPx(inlineAddReactionButton, 28),
|
||||
);
|
||||
await expect
|
||||
.poll(() =>
|
||||
inlineAddReactionButton.evaluate((button) => {
|
||||
const rect = button.getBoundingClientRect();
|
||||
return `${Math.round(rect.width)}x${Math.round(rect.height)}`;
|
||||
return {
|
||||
height: Math.round(rect.height),
|
||||
width: Math.round(rect.width),
|
||||
};
|
||||
}),
|
||||
)
|
||||
.toBe("40x28");
|
||||
.toEqual({
|
||||
height: expect.any(Number),
|
||||
width: expectedInlineReactionButtonWidth,
|
||||
});
|
||||
await expect
|
||||
.poll(() =>
|
||||
inlineAddReactionButton.evaluate((button) => {
|
||||
const rect = button.getBoundingClientRect();
|
||||
return Math.round(rect.height);
|
||||
}),
|
||||
)
|
||||
.toBeGreaterThanOrEqual(minExpectedInlineReactionButtonHeight);
|
||||
await expect
|
||||
.poll(() =>
|
||||
inlineAddReactionButton.evaluate((button) => {
|
||||
@@ -292,10 +313,24 @@ test("reacting with a custom emoji renders via the loopback media proxy", async
|
||||
.poll(() =>
|
||||
inlineAddReactionButton.evaluate((button) => {
|
||||
const rect = button.getBoundingClientRect();
|
||||
return `${Math.round(rect.width)}x${Math.round(rect.height)}`;
|
||||
return {
|
||||
height: Math.round(rect.height),
|
||||
width: Math.round(rect.width),
|
||||
};
|
||||
}),
|
||||
)
|
||||
.toBe("40x28");
|
||||
.toEqual({
|
||||
height: expect.any(Number),
|
||||
width: expectedInlineReactionButtonWidth,
|
||||
});
|
||||
await expect
|
||||
.poll(() =>
|
||||
inlineAddReactionButton.evaluate((button) => {
|
||||
const rect = button.getBoundingClientRect();
|
||||
return Math.round(rect.height);
|
||||
}),
|
||||
)
|
||||
.toBeGreaterThanOrEqual(minExpectedInlineReactionButtonHeight);
|
||||
|
||||
// Toggle the reaction back off: click the pill, which fires remove_reaction
|
||||
// -> emits a kind:5 deletion targeting the reaction event. The pill must
|
||||
|
||||
@@ -47,7 +47,7 @@ test("upload a file and see a FileCard in the timeline", async ({ page }) => {
|
||||
// escapes the webview to the OS browser and hits a corporate CDN page.
|
||||
const card = page.getByTestId("file-card").last();
|
||||
await expect(card).toBeVisible();
|
||||
await expectCornerRadiusPx(card, 16);
|
||||
await expectCornerRadiusPx(card, 16, { scaleWithRootFont: true });
|
||||
await expectSmoothCorners(card);
|
||||
await expect(card).toContainText("quarterly-report.pdf");
|
||||
|
||||
|
||||
@@ -126,8 +126,10 @@ test("image bundle lightbox navigates as a gallery", async ({ page }) => {
|
||||
|
||||
const triggers = row.getByTestId("message-image-lightbox-trigger");
|
||||
await expect(triggers).toHaveCount(3);
|
||||
await expectCornerRadiusPx(triggers.first(), 16);
|
||||
await expectCornerRadiusPx(triggers.first().locator("img"), 16);
|
||||
await expectCornerRadiusPx(triggers.first(), 16, { scaleWithRootFont: true });
|
||||
await expectCornerRadiusPx(triggers.first().locator("img"), 16, {
|
||||
scaleWithRootFont: true,
|
||||
});
|
||||
await expectSmoothCorners(triggers.first().locator("img"));
|
||||
await triggers.first().click();
|
||||
|
||||
@@ -137,7 +139,7 @@ test("image bundle lightbox navigates as a gallery", async ({ page }) => {
|
||||
const lightboxSurface = page
|
||||
.locator("[data-image-lightbox-frame] > div > div")
|
||||
.first();
|
||||
await expectCornerRadiusPx(lightboxSurface, 16);
|
||||
await expectCornerRadiusPx(lightboxSurface, 16, { scaleWithRootFont: true });
|
||||
await expectSmoothCorners(lightboxSurface);
|
||||
await expect(
|
||||
page.getByRole("button", { name: "Previous image" }),
|
||||
@@ -174,6 +176,7 @@ test("image bundle lightbox navigates as a gallery", async ({ page }) => {
|
||||
await expectCornerRadiusPx(
|
||||
page.locator("[data-image-lightbox-frame] > div > div").first(),
|
||||
16,
|
||||
{ scaleWithRootFont: true },
|
||||
);
|
||||
|
||||
expect(Math.abs(closingFrameBox.x - currentThumbnailBox.x)).toBeLessThan(2);
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { expect, test, type Locator } from "@playwright/test";
|
||||
|
||||
import { installMockBridge, TEST_IDENTITIES } from "../helpers/bridge";
|
||||
import { expectCornerRadiusPx, expectSmoothCorners } from "../helpers/css";
|
||||
import {
|
||||
expectCornerRadiusPx,
|
||||
expectSmoothCorners,
|
||||
expectedScaledPx,
|
||||
} from "../helpers/css";
|
||||
import { openSettings } from "../helpers/settings";
|
||||
|
||||
async function expectThreadReplyUnobscured(row: Locator) {
|
||||
@@ -179,7 +183,7 @@ test("supported link previews keep the message link visible", async ({
|
||||
).toBeVisible();
|
||||
const previewCard = row.locator('[data-link-preview="github-pull-request"]');
|
||||
await expect(previewCard).toBeVisible();
|
||||
await expectCornerRadiusPx(previewCard, 16);
|
||||
await expectCornerRadiusPx(previewCard, 16, { scaleWithRootFont: true });
|
||||
await expectSmoothCorners(previewCard);
|
||||
});
|
||||
|
||||
@@ -233,7 +237,9 @@ test("copy a rendered code block and paste it back as code", async ({
|
||||
|
||||
const codeBlock = page.locator("[data-code-block]");
|
||||
await expect(codeBlock).toHaveCount(1);
|
||||
await expectCornerRadiusPx(codeBlock.locator("pre"), 16);
|
||||
await expectCornerRadiusPx(codeBlock.locator("pre"), 16, {
|
||||
scaleWithRootFont: true,
|
||||
});
|
||||
await expectSmoothCorners(codeBlock.locator("pre"));
|
||||
|
||||
const copyButton = page.getByLabel("Copy code block");
|
||||
@@ -647,7 +653,19 @@ test("opens a single-level thread panel with inline expansion", async ({
|
||||
return `${Math.round(rect.width)}x${Math.round(rect.height)}`;
|
||||
}),
|
||||
)
|
||||
.toBe("24x24");
|
||||
.toBe(
|
||||
`${Math.round(
|
||||
await expectedScaledPx(
|
||||
rootSummaryRow.getByTestId("message-thread-summary-participant"),
|
||||
24,
|
||||
),
|
||||
)}x${Math.round(
|
||||
await expectedScaledPx(
|
||||
rootSummaryRow.getByTestId("message-thread-summary-participant"),
|
||||
24,
|
||||
),
|
||||
)}`,
|
||||
);
|
||||
const summaryGeometry = await measureThreadSummaryGeometry(rootSummaryRow);
|
||||
expect(
|
||||
Math.abs(summaryGeometry.authorLeft - summaryGeometry.bodyLeft),
|
||||
|
||||
@@ -253,7 +253,7 @@ test("video upload previews use poster frames and inline videos open review mode
|
||||
|
||||
const inlinePlayer = page.getByTestId("video-player").last();
|
||||
const inlineSurface = inlinePlayer.locator("[data-smooth-corners]").first();
|
||||
await expectCornerRadiusPx(inlineSurface, 16);
|
||||
await expectCornerRadiusPx(inlineSurface, 16, { scaleWithRootFont: true });
|
||||
await expectSmoothCorners(inlineSurface);
|
||||
const inlineVideo = inlinePlayer.locator("video");
|
||||
await inlinePlayer.getByRole("button", { name: "Play video" }).click();
|
||||
|
||||
@@ -1,8 +1,25 @@
|
||||
import { expect, type Locator } from "@playwright/test";
|
||||
|
||||
export async function currentRootFontScale(locator: Locator) {
|
||||
const rootFontSize = await locator.evaluate(() =>
|
||||
Number.parseFloat(
|
||||
window.getComputedStyle(document.documentElement).fontSize,
|
||||
),
|
||||
);
|
||||
return Number.isFinite(rootFontSize) ? rootFontSize / 16 : 1;
|
||||
}
|
||||
|
||||
export async function expectedScaledPx(
|
||||
locator: Locator,
|
||||
pxAtDefaultScale: number,
|
||||
) {
|
||||
return pxAtDefaultScale * (await currentRootFontScale(locator));
|
||||
}
|
||||
|
||||
export async function expectCornerRadiusPx(
|
||||
locator: Locator,
|
||||
expectedRadiusPx: number,
|
||||
options: { scaleWithRootFont?: boolean } = {},
|
||||
) {
|
||||
const measurement = await locator.evaluate((element) => {
|
||||
const style = window.getComputedStyle(element);
|
||||
@@ -65,13 +82,18 @@ export async function expectCornerRadiusPx(
|
||||
className: element.getAttribute("class") ?? "",
|
||||
radius,
|
||||
rawRadius,
|
||||
rootFontSize,
|
||||
};
|
||||
});
|
||||
|
||||
const expected = options.scaleWithRootFont
|
||||
? expectedRadiusPx * (measurement.rootFontSize / 16)
|
||||
: expectedRadiusPx;
|
||||
|
||||
expect(
|
||||
measurement.radius,
|
||||
`Expected ${expectedRadiusPx}px corner radius, got ${measurement.rawRadius} on class "${measurement.className}".`,
|
||||
).toBeCloseTo(expectedRadiusPx, 0);
|
||||
`Expected ${expected}px corner radius, got ${measurement.rawRadius} on class "${measurement.className}".`,
|
||||
).toBeCloseTo(expected, 0);
|
||||
}
|
||||
|
||||
export async function expectSmoothCorners(
|
||||
|
||||
Reference in New Issue
Block a user