- release-links: bump to 1.0.0; Windows now points at AgentCompany-1.0.0-x64.exe (signed x64 NSIS, uploaded to R2); remove the Linux platform. macOS stays on 0.4.182 until the 1.0.0 mac build is ready. - platform-support / product-narrative / footer / layout / faq: remove Linux from availability copy, the FAQ, JSON-LD, and footer download links - e2e: adjust the tracked-download-link count (macOS x2 + Windows = 3)
100 lines
3.6 KiB
TypeScript
100 lines
3.6 KiB
TypeScript
import { test, expect, type Page } from "@playwright/test";
|
|
|
|
// The download counter endpoint is a Cloudflare Pages Function, absent from the
|
|
// static export served in tests; mock it so the client fetch resolves.
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.route("**/api/download-stats", (route) =>
|
|
route.fulfill({
|
|
status: 200,
|
|
contentType: "application/json",
|
|
body: JSON.stringify({ downloads: 12345 }),
|
|
}),
|
|
);
|
|
});
|
|
|
|
/** Step through the page so reveals fire and lazy images load. */
|
|
async function scrollThrough(page: Page): Promise<void> {
|
|
await page.evaluate(async () => {
|
|
const dwell = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
const step = Math.round(window.innerHeight * 0.7);
|
|
for (let y = 0; y < document.body.scrollHeight; y += step) {
|
|
window.scrollTo(0, y);
|
|
await dwell(150);
|
|
}
|
|
window.scrollTo(0, 0);
|
|
await dwell(200);
|
|
});
|
|
}
|
|
|
|
test("renders the hero and every core section", async ({ page }) => {
|
|
await page.goto("/");
|
|
await expect(page.getByRole("heading", { level: 1 })).toContainText("Autonomous AI Company");
|
|
for (const id of ["features", "how-it-works", "faq", "download"]) {
|
|
await expect(page.locator(`#${id}`)).toHaveCount(1);
|
|
}
|
|
await scrollThrough(page);
|
|
await expect(page.getByRole("heading", { name: "Launch your company now." })).toBeVisible();
|
|
});
|
|
|
|
test("download links use the tracked endpoint and never expose R2 URLs", async ({ page }) => {
|
|
await page.goto("/");
|
|
await scrollThrough(page);
|
|
|
|
const tracked = page.locator('#download a[href^="/api/download?asset="]');
|
|
expect(await tracked.count()).toBeGreaterThanOrEqual(3);
|
|
|
|
// Real release URLs must stay behind the server-side redirect.
|
|
expect(await page.locator('a[href*="r2.dev"]').count()).toBe(0);
|
|
|
|
await expect(page.getByText(/12,345 downloads/)).toBeVisible();
|
|
});
|
|
|
|
test("theme toggle flips light and dark", async ({ page }) => {
|
|
await page.goto("/");
|
|
const toggle = page.locator('button[aria-label*="mode"]:visible').first();
|
|
const wasDark = await page.evaluate(() => document.documentElement.classList.contains("dark"));
|
|
await toggle.click();
|
|
await expect
|
|
.poll(() => page.evaluate(() => document.documentElement.classList.contains("dark")))
|
|
.toBe(!wasDark);
|
|
});
|
|
|
|
test("all images load without breaking", async ({ page }) => {
|
|
await page.goto("/");
|
|
await scrollThrough(page);
|
|
const broken = await page.evaluate(() =>
|
|
[...document.querySelectorAll("img")]
|
|
.filter((img) => !img.complete || img.naturalWidth === 0)
|
|
.map((img) => img.currentSrc || img.src),
|
|
);
|
|
expect(broken).toEqual([]);
|
|
});
|
|
|
|
test("produces no console errors", async ({ page }) => {
|
|
const errors: string[] = [];
|
|
page.on("console", (message) => {
|
|
if (message.type() === "error") errors.push(message.text());
|
|
});
|
|
page.on("pageerror", (error) => errors.push(error.message));
|
|
await page.goto("/");
|
|
await scrollThrough(page);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
test("desktop navigation exposes the section links", async ({ page }) => {
|
|
test.skip(test.info().project.name !== "desktop", "desktop layout only");
|
|
await page.goto("/");
|
|
for (const href of ["#features", "#how-it-works", "#faq"]) {
|
|
await expect(page.locator(`nav a[href="${href}"]:visible`)).toBeVisible();
|
|
}
|
|
});
|
|
|
|
test("mobile navigation reveals the menu on tap", async ({ page }) => {
|
|
test.skip(test.info().project.name !== "mobile", "mobile layout only");
|
|
await page.goto("/");
|
|
const links = page.locator('#mobile-nav a[href="#features"]');
|
|
await expect(links).toBeHidden();
|
|
await page.getByRole("button", { name: /open navigation menu/i }).click();
|
|
await expect(links).toBeVisible();
|
|
});
|