import { expect, test, type Page } from "@playwright/test"; import { POST_CHANNEL, POST_CHANNEL_SLUG, POST_REPLY_ID, POST_ROOT_ID, postsPage, } from "./fixtures/data"; import { installRoutes, openFilters } from "./helpers"; // X posts are private (release 17 slice XP): with `social.x.visibility` // "private", a PUBLIC site's build carries no X channel and a PRIVATE site's // build carries all of it. The build itself — the index build's per-site posts // manifest and compose's posts tree — is pinned through the real code by // common/bin/compose-site.postsVisibility.test.ts: this suite's data is // route-mocked, never built. Here the two posts manifests that build writes // are served, and the visitor's side is checked: the Search in row's Posts box // and the post hits come and go with the manifest, with nothing special-cased. // // The fixture posts say "kappa" (two of them); no video does. const X_POST_SLUGS = [ `${POST_CHANNEL_SLUG}/${POST_ROOT_ID}`, `${POST_CHANNEL_SLUG}/${POST_REPLY_ID}`, ]; const fulfillJson = (body: unknown) => ({ status: 200, contentType: "application/json", body: JSON.stringify(body), }); // The site posts manifest compose writes: the X channel listed (a private // site's build), or no channel at all (a public site whose only posts were X // posts). Routed after installRoutes, so these answers win. async function servePostsManifest(page: Page, built: "public" | "private") { await page.route("**/posts/manifest.json", (route) => route.fulfill( fulfillJson({ version: 1, channels: built === "private" ? [{ name: POST_CHANNEL, slug: POST_CHANNEL_SLUG, postCount: 4, platform: "twitter" }] : [], totalCount: built === "private" ? 4 : 0, generatedAt: new Date().toISOString(), }), ), ); await page.route(/\/posts\/[^/]+\/page-\d+\.json$/, (route) => route.fulfill( fulfillJson( postsPage().map((p) => ({ ...p, platform: "twitter", url: `https://x.com/tester/status/${p.id}`, })), ), ), ); } const postsBox = (page: Page) => page.getByTestId("search-in-row").getByRole("checkbox", { name: "Posts", exact: true }); async function search(page: Page, q: string) { await page.locator('input[data-testid^="leaf-query-"]').first().fill(q); await page.getByTestId("search-submit").click(); } test.describe("X posts private", () => { test.beforeEach(async ({ page }) => { await installRoutes(page); }); test("a public site built with X posts private has no Posts box and finds no X post", async ({ page, }) => { await servePostsManifest(page, "public"); await page.goto("/"); await openFilters(page); await expect(page.getByRole("checkbox", { name: "Transcripts", exact: true })).toBeVisible(); await expect(postsBox(page)).toHaveCount(0); await search(page, "kappa"); await expect(page.getByText(/^searched \d+\/\d+$/)).toBeVisible({ timeout: 15_000 }); await expect(page.getByTestId("results-summary")).toHaveText("Matching videos (0)"); await expect(page.locator(`[data-result-slug^="${POST_CHANNEL_SLUG}/"]`)).toHaveCount(0); }); test("a private site's build shows the X posts", async ({ page }) => { await servePostsManifest(page, "private"); await page.goto("/"); await openFilters(page); await expect(postsBox(page)).toBeChecked(); await search(page, "kappa"); const cards = page.locator("[data-card-header]"); await expect(async () => { const got = await cards.evaluateAll((els) => els.map((e) => e.getAttribute("data-result-slug") ?? ""), ); expect(got.slice().sort()).toEqual(X_POST_SLUGS.slice().sort()); }).toPass({ timeout: 15_000 }); }); });