feat: remember per-community navigation location (#2629)

Signed-off-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz>
Co-authored-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz>
This commit is contained in:
Kalvin C
2026-07-23 15:52:25 -07:00
committed by GitHub
parent 5afa16157a
commit 95478919fc
13 changed files with 890 additions and 32 deletions

View File

@@ -116,6 +116,278 @@ test.describe("community rail", () => {
.toBe(COMMUNITY_B.id);
});
test("restores the last Home or channel destination per community", async ({
page,
}) => {
await installMockBridge(page, undefined, { skipCommunitySeed: true });
await seedCommunities(page, [COMMUNITY_A, COMMUNITY_B], COMMUNITY_A.id);
await page.goto("/");
await page.getByTestId("channel-general").click();
await expect(page).toHaveURL(/#\/channels\//);
const generalUrl = page.url();
await page.getByTestId(`community-rail-button-${COMMUNITY_B.id}`).click();
await expect(page).toHaveURL(/#\/$/);
await page.getByTestId("channel-random").click();
await expect(page).toHaveURL(/#\/channels\//);
const randomUrl = page.url();
await page.getByTestId(`community-rail-button-${COMMUNITY_A.id}`).click();
await expect(page).toHaveURL(generalUrl);
await page.getByTestId(`community-rail-button-${COMMUNITY_B.id}`).click();
await expect(page).toHaveURL(randomUrl);
await page.getByRole("button", { name: "Inbox" }).click();
await expect(page).toHaveURL(/#\/$/);
await page.getByTestId(`community-rail-button-${COMMUNITY_A.id}`).click();
await expect(page).toHaveURL(generalUrl);
await page.getByTestId(`community-rail-button-${COMMUNITY_B.id}`).click();
await expect(page).toHaveURL(/#\/$/);
});
test("enters a remembered channel before live validation completes", async ({
page,
}) => {
await installMockBridge(page, undefined, { skipCommunitySeed: true });
await seedCommunities(page, [COMMUNITY_A, COMMUNITY_B], COMMUNITY_A.id);
await page.goto("/");
await expect(page.getByTestId("app-sidebar")).toBeVisible();
const rememberedChannelId = await page.evaluate((communityId) => {
const source = window.localStorage.getItem(
"buzz-channels.v1:ws://localhost:3000",
);
if (!source) throw new Error("missing source channel snapshot");
const snapshot = JSON.parse(source) as {
channels: Array<{ id: string; name: string }>;
};
const generalChannel = snapshot.channels.find(
(channel) => channel.name === "general",
);
if (!generalChannel) throw new Error("missing general channel snapshot");
window.localStorage.setItem(
"buzz-channels.v1:ws://localhost:3001",
source,
);
window.localStorage.setItem(
"buzz-community-destinations",
JSON.stringify({
[communityId]: {
kind: "channel",
channelId: generalChannel.id,
},
}),
);
return generalChannel.id;
}, COMMUNITY_B.id);
await page.evaluate(() => {
const testWindow = window as typeof window & {
__BUZZ_E2E__?: { mock?: { channelsReadDelayMs?: number } };
};
if (!testWindow.__BUZZ_E2E__) {
throw new Error("missing E2E config");
}
testWindow.__BUZZ_E2E__.mock = {
...testWindow.__BUZZ_E2E__.mock,
channelsReadDelayMs: 800,
};
});
await page.getByTestId(`community-rail-button-${COMMUNITY_B.id}`).click();
await expect(page).toHaveURL(
new RegExp(`#/channels/${rememberedChannelId}$`),
{ timeout: 700 },
);
await expect(page.getByTestId("message-timeline")).toBeVisible({
timeout: 700,
});
});
test("clears a remembered channel that is unavailable after switching", async ({
page,
}) => {
await installMockBridge(page, undefined, { skipCommunitySeed: true });
await seedCommunities(page, [COMMUNITY_A, COMMUNITY_B], COMMUNITY_A.id);
await page.addInitScript((communityId) => {
window.localStorage.setItem(
"buzz-community-destinations",
JSON.stringify({
[communityId]: { kind: "channel", channelId: "missing-channel" },
}),
);
}, COMMUNITY_B.id);
await page.goto("/");
await expect
.poll(() =>
page.evaluate(() =>
window.localStorage.getItem("buzz-channels.v1:ws://localhost:3000"),
),
)
.not.toBeNull();
await page.evaluate(() => {
const source = window.localStorage.getItem(
"buzz-channels.v1:ws://localhost:3000",
);
if (!source) throw new Error("missing source channel snapshot");
const snapshot = JSON.parse(source);
snapshot.channels = snapshot.channels.map(
(channel: Record<string, unknown>, index: number) =>
index === 0 ? { ...channel, id: "missing-channel" } : channel,
);
window.localStorage.setItem(
"buzz-channels.v1:ws://localhost:3001",
JSON.stringify(snapshot),
);
});
await page.getByTestId(`community-rail-button-${COMMUNITY_B.id}`).click();
await expect(page).not.toHaveURL(/#\/channels\//);
await expect
.poll(() =>
page.evaluate((communityId) => {
const raw = window.localStorage.getItem(
"buzz-community-destinations",
);
if (!raw) return null;
return JSON.parse(raw)[communityId];
}, COMMUNITY_B.id),
)
.toEqual({ kind: "home" });
});
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 seedCommunities(page, [COMMUNITY_A, COMMUNITY_B], COMMUNITY_A.id);
await page.addInitScript((communityId) => {
window.localStorage.setItem(
"buzz-community-destinations",
JSON.stringify({
[communityId]: { kind: "channel", channelId: "general" },
}),
);
}, COMMUNITY_B.id);
await page.goto("/");
await expect(page.getByTestId("app-sidebar")).toBeVisible();
await expect
.poll(() =>
page.evaluate(() =>
window.localStorage.getItem("buzz-channels.v1:ws://localhost:3000"),
),
)
.not.toBeNull();
await page.evaluate(() => {
const source = window.localStorage.getItem(
"buzz-channels.v1:ws://localhost:3000",
);
if (!source) throw new Error("missing source channel snapshot");
const snapshot = JSON.parse(source);
snapshot.channels = snapshot.channels.filter(
(channel: { id: string }) => channel.id !== "general",
);
window.localStorage.setItem(
"buzz-channels.v1:ws://localhost:3001",
JSON.stringify(snapshot),
);
});
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
.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 expect(page.getByTestId("channel-general")).toBeVisible();
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" });
});
test("does not restore a remembered destination on cold boot", async ({
page,
}) => {
await installMockBridge(page, undefined, { skipCommunitySeed: true });
await seedCommunities(page, [COMMUNITY_A, COMMUNITY_B], COMMUNITY_A.id);
await page.addInitScript((communityId) => {
window.localStorage.setItem(
"buzz-community-destinations",
JSON.stringify({
[communityId]: { kind: "channel", channelId: "general" },
}),
);
}, COMMUNITY_A.id);
await page.goto("/");
await expect(page).not.toHaveURL(/#\/channels\//);
});
test("removing the active community restores the fallback destination", async ({
page,
}) => {
await installMockBridge(page, undefined, { skipCommunitySeed: true });
await seedCommunities(page, [COMMUNITY_A, COMMUNITY_B], COMMUNITY_A.id);
await page.goto("/");
await page.getByTestId(`community-rail-button-${COMMUNITY_B.id}`).click();
await page.getByTestId("channel-random").click();
const randomUrl = page.url();
await page.getByTestId(`community-rail-button-${COMMUNITY_A.id}`).click();
await page.getByTestId("channel-general").click();
await page
.getByTestId(`community-rail-button-${COMMUNITY_A.id}`)
.click({ button: "right" });
await page.getByRole("menuitem", { name: "Community settings" }).click();
await page.getByRole("button", { name: "Remove Community" }).click();
await expect(page).toHaveURL(randomUrl);
await expect
.poll(() =>
page.evaluate(() =>
window.localStorage.getItem("buzz-active-community-id"),
),
)
.toBe(COMMUNITY_B.id);
});
test("shows the quiet switch gate, not the boot splash, while switching", async ({
page,
}) => {