Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/improsocial/impro
An extensible Bluesky client for web impro.social
Something went wrong. Try again.
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229import { test, expect } from "../../base.js";import { login } from "../../helpers.js";import { MockServer } from "../../mockServer.js";import { createConvo, createMessage, createPost, createProfile,} from "../../../shared/factories.js";
const BLACKSKY_APPVIEW_DID = "did:web:api.blacksky.community#bsky_appview";const BLACKSKY_CHAT_DID = "did:web:api.blacksky.community#bsky_chat";const BLUESKY_APPVIEW_DID = "did:web:api.bsky.app#bsky_appview";const BLUESKY_CHAT_DID = "did:web:api.bsky.chat#bsky_chat";
async function seedAppViewConfig(page, config) { // Seed on the first page load only; otherwise addInitScript would re-seed // on every subsequent navigation and defeat things like the reset flow. await page.addInitScript((seeded) => { if (sessionStorage.getItem("test-appview-seeded") === "true") return; localStorage.setItem("appview-config", JSON.stringify(seeded)); sessionStorage.setItem("test-appview-seeded", "true"); }, config);}
function collectProxyHeaders(page, pathFragment) { const headers = []; page.on("request", (request) => { if (request.url().includes(pathFragment)) { const header = request.headers()["atproto-proxy"]; if (header) { headers.push(header); } } }); return headers;}
function buildTimelineMockServer() { const mockServer = new MockServer(); const author = createProfile({ did: "did:plc:someone", handle: "someone.bsky.social", displayName: "Someone", }); mockServer.addProfile(author); mockServer.addTimelinePosts([ createPost({ uri: "at://did:plc:someone/app.bsky.feed.post/post1", text: "Hello", authorHandle: author.handle, authorDisplayName: author.displayName, }), ]); return mockServer;}
test.describe("Switch app view flow", () => { test("uses the stored app view DID as the atproto-proxy header on app.bsky requests", async ({ page, }) => { const mockServer = buildTimelineMockServer(); await mockServer.setup(page);
const appProxyHeaders = collectProxyHeaders(page, "/xrpc/app.bsky.");
await seedAppViewConfig(page, { id: "blacksky", appViewServiceDid: BLACKSKY_APPVIEW_DID, chatServiceDid: BLACKSKY_CHAT_DID, }); await login(page);
await page.goto("/"); await expect( page.locator("#home-view").locator('[data-testid="feed-item"]'), ).toHaveCount(1, { timeout: 10000 });
expect(appProxyHeaders.length).toBeGreaterThan(0); for (const header of appProxyHeaders) { expect(header).toBe(BLACKSKY_APPVIEW_DID); } });
test("uses the stored chat DID as the atproto-proxy header on chat.bsky requests", async ({ page, }) => { const mockServer = new MockServer(); const otherMember = createProfile({ did: "did:plc:alice1", handle: "alice.bsky.social", displayName: "Alice", }); const lastMessage = createMessage({ id: "msg-1", text: "Hello", senderDid: otherMember.did, sentAt: "2025-01-15T12:00:00.000Z", }); mockServer.addConvos([ createConvo({ id: "convo-1", otherMember, lastMessage }), ]); await mockServer.setup(page);
const chatProxyHeaders = collectProxyHeaders(page, "/xrpc/chat.bsky.");
await seedAppViewConfig(page, { id: "blacksky", appViewServiceDid: BLACKSKY_APPVIEW_DID, chatServiceDid: BLACKSKY_CHAT_DID, }); await login(page);
await page.goto("/messages"); await expect(page.locator("#chat-view .convo-item")).toHaveCount(1, { timeout: 10000, });
expect(chatProxyHeaders.length).toBeGreaterThan(0); for (const header of chatProxyHeaders) { expect(header).toBe(BLACKSKY_CHAT_DID); } });
test("reset-appview query param clears the stored config and strips the param", async ({ page, }) => { const mockServer = new MockServer(); await mockServer.setup(page);
await seedAppViewConfig(page, { id: "blacksky", appViewServiceDid: BLACKSKY_APPVIEW_DID, chatServiceDid: BLACKSKY_CHAT_DID, });
await page.goto("/?reset-appview=1");
await expect .poll(() => page.evaluate(() => localStorage.getItem("appview-config"))) .toBeNull();
const currentUrl = new URL(page.url()); expect(currentUrl.searchParams.has("reset-appview")).toBe(false); });
test("reverts to the Bluesky defaults after reset", async ({ page }) => { const mockServer = buildTimelineMockServer(); const otherMember = createProfile({ did: "did:plc:alice1", handle: "alice.bsky.social", displayName: "Alice", }); mockServer.addConvos([ createConvo({ id: "convo-1", otherMember, lastMessage: createMessage({ id: "msg-1", text: "Hello", senderDid: otherMember.did, sentAt: "2025-01-15T12:00:00.000Z", }), }), ]); await mockServer.setup(page);
const appProxyHeaders = collectProxyHeaders(page, "/xrpc/app.bsky."); const chatProxyHeaders = collectProxyHeaders(page, "/xrpc/chat.bsky.");
await seedAppViewConfig(page, { id: "blacksky", appViewServiceDid: BLACKSKY_APPVIEW_DID, chatServiceDid: BLACKSKY_CHAT_DID, }); await login(page);
// Only assert on requests made after the reset; wait for any lingering // requests from the /login page to complete before clearing. await page.waitForLoadState("networkidle"); appProxyHeaders.length = 0; chatProxyHeaders.length = 0; await page.goto("/?reset-appview=1"); await expect( page.locator("#home-view").locator('[data-testid="feed-item"]'), ).toHaveCount(1, { timeout: 10000 });
await page.goto("/messages"); await expect(page.locator("#chat-view .convo-item")).toHaveCount(1, { timeout: 10000, });
expect(appProxyHeaders.length).toBeGreaterThan(0); for (const header of appProxyHeaders) { expect(header).toBe(BLUESKY_APPVIEW_DID); } expect(chatProxyHeaders.length).toBeGreaterThan(0); for (const header of chatProxyHeaders) { expect(header).toBe(BLUESKY_CHAT_DID); } });
test("persists the selected App View to localStorage when the form is submitted", async ({ page, }) => { const mockServer = new MockServer(); await mockServer.setup(page);
await page.goto("/login"); await page.locator("#login-advanced summary").click(); await page.locator('select[name="appview"]').selectOption("blacksky"); await page.locator('input[name="handle"]').fill("someone.bsky.social"); await page.locator('button[type="submit"]').click();
await expect .poll(() => page.evaluate(() => { const raw = localStorage.getItem("appview-config"); return raw ? JSON.parse(raw) : null; }), ) .toEqual({ id: "blacksky", appViewServiceDid: BLACKSKY_APPVIEW_DID, chatServiceDid: BLUESKY_CHAT_DID, }); });});