Files
twitter-lite/e2e/integrations/pwa.spec.ts
T

104 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { chromium, expect, test } from "@playwright/test";
test.skip(process.env.TWITTER_LITE_E2E_PRODUCTION !== "1", "PWA requires the production build.");
test("publishes an installable manifest and correctly sized icons before login", async ({
page,
request,
}) => {
await page.goto("/");
await expect(page.locator('link[rel="manifest"]')).toHaveAttribute(
"href",
"/manifest.webmanifest",
);
const response = await request.get("/manifest.webmanifest");
expect(response.ok()).toBe(true);
const manifest = await response.json();
expect(manifest).toMatchObject({
id: "/",
name: "Personal Workspace",
start_url: "/",
scope: "/",
display: "standalone",
});
expect(manifest.icons).toEqual(
expect.arrayContaining([
expect.objectContaining({ sizes: "192x192", purpose: "any" }),
expect.objectContaining({ sizes: "512x512", purpose: "any" }),
expect.objectContaining({ sizes: "512x512", purpose: "maskable" }),
]),
);
for (const icon of manifest.icons) {
const dimensions = await page.evaluate(async (src: string) => {
const image = new Image();
image.src = src;
await image.decode();
return `${image.naturalWidth}x${image.naturalHeight}`;
}, icon.src);
expect(dimensions).toBe(icon.sizes);
}
});
test("passes Chromium installation checks in a regular browser profile", async ({
baseURL,
}, testInfo) => {
// Playwright's default incognito contexts cannot install apps.
const context = await chromium.launchPersistentContext("", {
executablePath: process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,
baseURL,
extraHTTPHeaders: { "Tailscale-User-Login": "[email protected]" },
viewport: testInfo.project.use.viewport,
isMobile: testInfo.project.use.isMobile,
});
try {
const page = await context.newPage();
await page.goto("/");
await page.evaluate(() => navigator.serviceWorker.ready.then(() => true));
const client = await context.newCDPSession(page);
expect((await client.send("Page.getAppManifest")).errors).toEqual([]);
await expect
.poll(async () => (await client.send("Page.getInstallabilityErrors")).installabilityErrors)
.toEqual([]);
} finally {
await context.close();
}
});
test("shows a private offline fallback and retries the original URL online", async ({
page,
context,
baseURL,
}) => {
await page.goto("/");
await expect
.poll(() => page.evaluate(() => navigator.serviceWorker.controller?.scriptURL))
.toBe(new URL("/sw.js", baseURL).href);
await context.setOffline(true);
const destination = "/login?returnTo=%2Fjournal";
await page.goto(destination);
await expect(page).toHaveURL(new URL(destination, baseURL).href);
await expect(page.getByRole("heading", { name: "You’re offline" })).toBeVisible();
expect(
await page.evaluate(() =>
fetch("/api/auth").then(
() => false,
() => true,
),
),
).toBe(true);
const cachedPaths = await page.evaluate(async () => {
const names = await caches.keys();
const requests = await Promise.all(names.map(async (name) => (await caches.open(name)).keys()));
return requests.flat().map((request) => new URL(request.url).pathname);
});
expect(cachedPaths).toEqual(["/offline.html"]);
await context.setOffline(false);
await page.getByRole("button", { name: "Try again" }).click();
await expect(page).toHaveURL(/\/(?:login|setup)(?:\?|$)/);
await expect(page.getByRole("heading", { name: "You’re offline" })).toHaveCount(0);
await expect(page.getByRole("button", { name: /Create account|Sign in/i })).toBeVisible();
});