diff --git a/crates/buzz-relay/tests/boot_lifecycle.rs b/crates/buzz-relay/tests/boot_lifecycle.rs index 5d7dd2491f4..d907d4f1785 100644 --- a/crates/buzz-relay/tests/boot_lifecycle.rs +++ b/crates/buzz-relay/tests/boot_lifecycle.rs @@ -821,6 +821,12 @@ mod postgres_tests { /// last, after the cache already serves the report: observing it proves the /// whole cycle ran, with no window where the counters have landed but the /// timestamp has not. + /// + /// The scrape that first shows the gauge can't be asserted on: the exporter + /// renders counters, then gauges, then histograms, so a render overlapping + /// that first sample holds the gauge without the counters. A render that + /// starts after the gauge was seen holds everything `sample` wrote before + /// it, so the assertions read a second scrape. #[test] #[ignore = "requires PostgreSQL"] fn startup_owns_the_dependency_sampler() { @@ -842,11 +848,9 @@ mod postgres_tests { ("REDIS_URL", &redis_url), ("BUZZ_GIT_CONFORMANCE_PROBE", "false"), ]); - let scrape = wait_for_scraped_metric( - &mut process, - metrics_port, - "buzz_readiness_dependency_sample_completed_timestamp_seconds", - ); + let completed = "buzz_readiness_dependency_sample_completed_timestamp_seconds"; + wait_for_scraped_metric(&mut process, metrics_port, completed); + let scrape = wait_for_scraped_metric(&mut process, metrics_port, completed); let output = process.terminate(); let logs = format!( "{}{}", diff --git a/desktop/tests/e2e/thread-head-stale-edit.spec.ts b/desktop/tests/e2e/thread-head-stale-edit.spec.ts index c72ebc78f79..e88c09ce20e 100644 --- a/desktop/tests/e2e/thread-head-stale-edit.spec.ts +++ b/desktop/tests/e2e/thread-head-stale-edit.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 { openGeneral, pressRowAction } from "../helpers/channelHeadReady"; // Regression coverage for the reported bug: the top-level timeline shows the // EDITED message body, but opening its thread panel shows the STALE, un-edited @@ -59,7 +60,9 @@ test("thread head reflects the channel-window edit even before thread aux loads" // provably cannot land until we release it after asserting the head. await installMockBridge(page, { deferThreadReplies: true }); await page.goto("/"); - await page.getByTestId(`channel-${CHANNEL}`).click(); + // Let the head refresh land and the timeline pin to the bottom before + // touching a row. + await openGeneral(page); await expect(page.getByTestId("chat-title")).toHaveText(CHANNEL); await waitForMockLiveSubscription(page, CHANNEL); @@ -121,8 +124,7 @@ test("thread head reflects the channel-window edit even before thread aux loads" ); // 3. Open the thread via the reply action (the flow in the bug report). - const replyButton = page.getByTestId(`reply-message-${rootId}`); - await replyButton.click({ force: true }); + await pressRowAction(page.getByTestId(`reply-message-${rootId}`)); const threadPanel = page.getByTestId("message-thread-panel"); await expect(threadPanel).toBeVisible(); diff --git a/desktop/tests/helpers/channelHeadReady.ts b/desktop/tests/helpers/channelHeadReady.ts index d24edcb8b49..1c96590228c 100644 --- a/desktop/tests/helpers/channelHeadReady.ts +++ b/desktop/tests/helpers/channelHeadReady.ts @@ -1,4 +1,7 @@ -import { expect, type Page } from "@playwright/test"; +import { expect, type Locator, type Page } from "@playwright/test"; + +/** The seeded #general channel's id in the mock bridge. */ +export const GENERAL_CHANNEL_ID = "9a1657ac-f7aa-5db0-b632-d8bbeb6dfb50"; // These default mock fixtures have immediate EOSE and no injected reconnect. // Steady-state pagination begins after live admission and its head refresh, @@ -73,3 +76,17 @@ export async function waitForMockChannelHeadReady( }) .toBeLessThanOrEqual(2); } + +// Opening #general refreshes the head after the live subscription lands, and +// the timeline re-pins while it does. Wait for that before touching a row. +export async function openGeneral(page: Page) { + await page.getByTestId("channel-general").click(); + await waitForMockChannelHeadReady(page, "general", GENERAL_CHANNEL_ID); +} + +// Row actions are hover-only, and a moving row slips out from under the +// pointer. The action bar is also shown on focus-within, so use the keyboard. +export async function pressRowAction(button: Locator) { + await button.focus(); + await button.press("Enter"); +}