test(desktop): latch channel validation reads

Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@buzz.block.builderlab.xyz>
Signed-off-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@buzz.block.builderlab.xyz>
This commit is contained in:
npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta
2026-08-02 14:12:32 -04:00
parent 8614e6f71c
commit b225b8b7ee
2 changed files with 98 additions and 21 deletions
+28
View File
@@ -1254,6 +1254,12 @@ declare global {
__BUZZ_E2E_RELEASE_OBSERVER_ARCHIVE_POLICY__?: () => number;
/** Number of observer archive policy commands currently held by the seam. */
__BUZZ_E2E_OBSERVER_ARCHIVE_POLICY_PENDING__?: number;
/** Hold channel reads until released. */
__BUZZ_E2E_DEFER_NEXT_CHANNELS_READ__?: () => void;
/** Release every channel read held by the explicit E2E seam. */
__BUZZ_E2E_RELEASE_CHANNELS_READ__?: () => number;
/** Number of channel reads currently held by the seam. */
__BUZZ_E2E_CHANNELS_READ_PENDING__?: number;
}
}
@@ -1358,6 +1364,8 @@ type DeferredGetEvent = {
};
let deferredGetEventQueue: DeferredGetEvent[] = [];
let deferredObserverArchivePolicyQueue: Array<() => void> = [];
let deferChannelsReads = false;
let deferredChannelsReadQueue: Array<() => void> = [];
const mockDisplayNames = new Map<string, string>([
[MOCK_IDENTITY_PUBKEY, DEFAULT_MOCK_IDENTITY.display_name],
@@ -9783,6 +9791,19 @@ export function maybeInstallE2eTauriMocks() {
for (const resolve of queued) resolve();
return queued.length;
};
deferChannelsReads = false;
deferredChannelsReadQueue = [];
window.__BUZZ_E2E_CHANNELS_READ_PENDING__ = 0;
window.__BUZZ_E2E_DEFER_NEXT_CHANNELS_READ__ = () => {
deferChannelsReads = true;
};
window.__BUZZ_E2E_RELEASE_CHANNELS_READ__ = () => {
deferChannelsReads = false;
const queued = deferredChannelsReadQueue.splice(0);
window.__BUZZ_E2E_CHANNELS_READ_PENDING__ = 0;
for (const resolve of queued) resolve();
return queued.length;
};
window.__BUZZ_E2E_RELEASE_GET_EVENT__ = () => {
const queued = deferredGetEventQueue.splice(0);
for (const entry of queued) {
@@ -11087,6 +11108,13 @@ export function maybeInstallE2eTauriMocks() {
activeConfig,
);
case "get_channels":
if (deferChannelsReads) {
await new Promise<void>((resolve) => {
deferredChannelsReadQueue.push(resolve);
window.__BUZZ_E2E_CHANNELS_READ_PENDING__ =
deferredChannelsReadQueue.length;
});
}
return handleGetChannels(activeConfig);
case "get_feed":
return handleGetFeed(
+70 -21
View File
@@ -448,14 +448,7 @@ test.describe("community rail", () => {
test("does not repair a remembered channel until live validation succeeds", async ({
page,
}) => {
await installMockBridge(
page,
{
channelsReadDelayMs: 300,
channelsReadErrors: [null, "temporary channel read failure"],
},
{ skipCommunitySeed: true },
);
await installMockBridge(page, undefined, { skipCommunitySeed: true });
await seedCommunities(page, [COMMUNITY_A, COMMUNITY_B], COMMUNITY_A.id);
await page.addInitScript((communityId) => {
window.localStorage.setItem(
@@ -488,20 +481,39 @@ test.describe("community rail", () => {
JSON.stringify(snapshot),
);
});
await page.evaluate(() => {
const deferNextChannelsRead = (
window as Window & {
__BUZZ_E2E_DEFER_NEXT_CHANNELS_READ__?: () => void;
}
).__BUZZ_E2E_DEFER_NEXT_CHANNELS_READ__;
if (!deferNextChannelsRead) {
throw new Error("missing channel-read defer seam");
}
deferNextChannelsRead();
});
await page.evaluate(() => {
const invalidateChannels = (
window as Window & {
__BUZZ_E2E_INVALIDATE_CHANNELS__?: () => Promise<void>;
}
).__BUZZ_E2E_INVALIDATE_CHANNELS__;
if (!invalidateChannels) {
throw new Error("missing channel invalidation seam");
}
void invalidateChannels();
});
await page.waitForFunction(
() =>
(
window as Window & {
__BUZZ_E2E_CHANNELS_READ_PENDING__?: number;
}
).__BUZZ_E2E_CHANNELS_READ_PENDING__ === 1,
);
await page.getByTestId(`community-rail-button-${COMMUNITY_B.id}`).click();
await expect(page).toHaveURL(/#\/channels\/general$/);
await expect
.poll(() =>
page.evaluate((communityId) => {
const raw = window.localStorage.getItem(
"buzz-community-destinations",
);
return raw ? JSON.parse(raw)[communityId] : null;
}, COMMUNITY_B.id),
)
.toEqual({ kind: "channel", channelId: "general" });
await page.waitForTimeout(400);
await expect(page).not.toHaveURL(/#\/channels\/general$/);
await expect
.poll(() =>
page.evaluate((communityId) => {
@@ -513,7 +525,44 @@ test.describe("community rail", () => {
)
.toEqual({ kind: "channel", channelId: "general" });
await expect(page.getByTestId("channel-general")).toBeVisible();
await page.evaluate(() => {
const config = (
window as Window & {
__BUZZ_E2E__?: {
mock?: { channelsReadErrors?: (string | null)[] };
};
}
).__BUZZ_E2E__;
if (!config) throw new Error("missing E2E config");
config.mock = {
...config.mock,
channelsReadErrors: ["temporary channel read failure"],
};
});
await expect
.poll(() =>
page.evaluate(
() => window.__BUZZ_E2E__?.mock?.channelsReadErrors?.length ?? 0,
),
)
.toBe(1);
const released = await page.evaluate(
() =>
(
window as Window & {
__BUZZ_E2E_RELEASE_CHANNELS_READ__?: () => number;
}
).__BUZZ_E2E_RELEASE_CHANNELS_READ__?.() ?? 0,
);
expect(released).toBe(1);
await expect
.poll(() =>
page.evaluate(
() => window.__BUZZ_E2E__?.mock?.channelsReadErrors?.length ?? 0,
),
)
.toBe(0);
await expect
.poll(() =>
page.evaluate((communityId) => {