From 1f8368d6612e0f5d7d51b9c8debe12a3dae569aa Mon Sep 17 00:00:00 2001 From: Honey <47c18026466e670a1618fd7de0ef32b9ff75d6e0b5ccf255d13c8c3d674ed115@buzz.block.builderlab.xyz> Date: Wed, 5 Aug 2026 17:45:23 +0100 Subject: [PATCH] Wait for emoji picker overrides before asserting control styling The new picker assertions read overridden properties (48px control heights, the resting search background) immediately after the search input becomes visible. The Buzz stylesheet is appended from a `requestAnimationFrame` loop that only starts once `em-emoji-picker` has attached its shadow root, so it can land a frame or more later. An instrumented probe caught that gap: on 2 of 5 runs the shadow root had no `#buzz-emoji-mart-style` at that read point and the input measured Emoji Mart's un-overridden 36px instead of 48px. The shipped tests passed only because incidental round-trips bought enough time. `expect(...).toBe(48)` does not retry, so the race was live. Add `expectEmojiMartStylesInstalled` to the CSS helpers, polling for the style element, and gate both specs on it before their un-retried reads. The install loop itself predates this branch and is unchanged. Also documents the second probe finding, which needed no fix: the resting background samples as transparent right after install because Emoji Mart puts a 225ms `background-color` transition on the input. It settles to `rgb(229, 229, 230)`, and the override does win the cascade over the vendor `var(--em-color-border)` rule. Co-authored-by: kenny lopez Signed-off-by: kenny lopez --- .../tests/e2e/onboarding-avatar-skip.spec.ts | 2 ++ desktop/tests/e2e/profile.spec.ts | 2 ++ desktop/tests/helpers/css.ts | 20 +++++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/desktop/tests/e2e/onboarding-avatar-skip.spec.ts b/desktop/tests/e2e/onboarding-avatar-skip.spec.ts index 1aad4ea2de..38870199cf 100644 --- a/desktop/tests/e2e/onboarding-avatar-skip.spec.ts +++ b/desktop/tests/e2e/onboarding-avatar-skip.spec.ts @@ -2,6 +2,7 @@ import { expect, test } from "@playwright/test"; import { installMockBridge, TEST_IDENTITIES } from "../helpers/bridge"; import { waitForAnimations } from "../helpers/animations"; +import { expectEmojiMartStylesInstalled } from "../helpers/css"; import { seedActiveIdentity } from "../helpers/onboarding"; const BLANK_TYLER_IDENTITY = { @@ -51,6 +52,7 @@ test("avatar step shares the profile emoji picker controls", async ({ const picker = page.locator("em-emoji-picker"); await expect(picker.locator("input[type='search']")).toBeVisible(); + await expectEmojiMartStylesInstalled(picker); await expect(page.getByTestId("onboarding-avatar-emoji-picker")).toHaveCSS( "height", "384px", diff --git a/desktop/tests/e2e/profile.spec.ts b/desktop/tests/e2e/profile.spec.ts index 25764c8e97..c5175516cd 100644 --- a/desktop/tests/e2e/profile.spec.ts +++ b/desktop/tests/e2e/profile.spec.ts @@ -5,6 +5,7 @@ import { installMockBridge, TEST_IDENTITIES, } from "../helpers/bridge"; +import { expectEmojiMartStylesInstalled } from "../helpers/css"; import { openProfileMenu, openSettings } from "../helpers/settings"; async function expectHomeView(page: import("@playwright/test").Page) { @@ -597,6 +598,7 @@ test("offers emoji search and skin-tone controls for profile avatars", async ({ const picker = page.locator("em-emoji-picker"); const searchInput = picker.locator("input[type='search']"); await expect(searchInput).toBeVisible(); + await expectEmojiMartStylesInstalled(picker); await expect(page.getByTestId("profile-avatar-emoji-picker")).toHaveCSS( "height", "384px", diff --git a/desktop/tests/helpers/css.ts b/desktop/tests/helpers/css.ts index 0985fb7887..31b0ac036b 100644 --- a/desktop/tests/helpers/css.ts +++ b/desktop/tests/helpers/css.ts @@ -99,3 +99,23 @@ export async function expectSmoothCorners( ) .toBe(true); } + +/** + * Waits for the Buzz emoji-picker overrides to be present in the Emoji Mart + * shadow root. + * + * The stylesheet is appended from a `requestAnimationFrame` loop that starts + * only once the `em-emoji-picker` custom element has attached its shadow root, + * so it can land a frame or more after the search input becomes visible. Any + * assertion on an overridden property (control heights, resting background) + * must wait for this, otherwise it can read Emoji Mart's un-overridden defaults. + */ +export async function expectEmojiMartStylesInstalled(picker: Locator) { + await expect + .poll(async () => + picker.evaluate((element) => + Boolean(element.shadowRoot?.querySelector("#buzz-emoji-mart-style")), + ), + ) + .toBe(true); +}