feat(harness): centralize browser coverage contract
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,76 +1,97 @@
|
||||
import { expect, test, type Page } from "@playwright/test";
|
||||
import harnessStoryContract from "./support/story-harness-contract.json";
|
||||
|
||||
async function gotoStory(page: Page, storyId: string) {
|
||||
await page.goto(`/iframe.html?id=${storyId}&viewMode=story`);
|
||||
await expect(page).toHaveTitle(new RegExp(storyId, "i"), { timeout: 15_000 });
|
||||
type StoryHarnessEntry = (typeof harnessStoryContract.stories)[number];
|
||||
|
||||
const smokeStories = harnessStoryContract.stories.filter((story) => story.suites.includes("docs-smoke"));
|
||||
|
||||
async function gotoStory(page: Page, story: StoryHarnessEntry) {
|
||||
const params = new URLSearchParams({
|
||||
id: story.id,
|
||||
viewMode: "story"
|
||||
});
|
||||
|
||||
if (story.query) {
|
||||
for (const [key, value] of new URLSearchParams(story.query).entries()) {
|
||||
params.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
await page.goto(`/iframe.html?${params.toString()}`);
|
||||
await expect(page).toHaveTitle(new RegExp(story.id, "i"), { timeout: 15_000 });
|
||||
}
|
||||
|
||||
test("storybook button, select, and static-motion form stories stay interactive", async ({
|
||||
page
|
||||
}) => {
|
||||
await page.goto("/");
|
||||
await expect(page).toHaveTitle(/storybook/i);
|
||||
const smokeScenarios: Record<string, (page: Page) => Promise<void>> = {
|
||||
"button-playground": async (page) => {
|
||||
const button = page.getByRole("button", { name: "Save changes" });
|
||||
await expect(button).toBeVisible();
|
||||
await button.focus();
|
||||
await expect(button).toBeFocused();
|
||||
},
|
||||
"select-playground": async (page) => {
|
||||
const selectTrigger = page.locator('[data-slot="trigger"]').first();
|
||||
await expect(selectTrigger).toBeVisible();
|
||||
await selectTrigger.click();
|
||||
await expect(page.getByRole("option", { name: "Legal review" })).toBeVisible();
|
||||
},
|
||||
"launch-settings-form": async (page) => {
|
||||
await page.getByRole("textbox", { name: "Email address" }).fill("team@cadence.dev");
|
||||
await page.getByRole("combobox", { name: "Review lane" }).click();
|
||||
await page.getByRole("option", { name: "Legal" }).click();
|
||||
await page.getByRole("textbox", { name: "Launch summary" }).fill(
|
||||
"This release coordinates approvals, copy, and rollout risks."
|
||||
);
|
||||
await page.getByRole("button", { name: "Save settings" }).click();
|
||||
await expect(page.locator("pre code").last()).toContainText('"role": "legal"');
|
||||
},
|
||||
"data-table-playground": async (page) => {
|
||||
const table = page.getByRole("table", { name: "Routing lanes" });
|
||||
await expect(table).toBeVisible();
|
||||
await expect(page.getByRole("searchbox", { name: "Search routing lanes" })).toBeVisible();
|
||||
|
||||
await gotoStory(page, "components-button--playground");
|
||||
const button = page.getByRole("button", { name: "Save changes" });
|
||||
await expect(button).toBeVisible();
|
||||
await button.focus();
|
||||
await expect(button).toBeFocused();
|
||||
const sortableHeader = page.getByRole("columnheader", { name: /owner/i });
|
||||
await sortableHeader.getByRole("button").click();
|
||||
await expect(sortableHeader).toHaveAttribute("aria-sort", "ascending");
|
||||
|
||||
await gotoStory(page, "components-select--playground");
|
||||
const selectTrigger = page.locator('[data-slot="trigger"]').first();
|
||||
await expect(selectTrigger).toBeVisible();
|
||||
await selectTrigger.click();
|
||||
await expect(page.getByRole("option", { name: "Legal review" })).toBeVisible();
|
||||
await page.getByRole("checkbox", { name: /select row/i }).first().click();
|
||||
await expect(page.getByRole("button", { name: "Clear selection" })).toBeVisible();
|
||||
|
||||
await page.goto("/iframe.html?id=components-form--launch-settings&viewMode=story&globals=motion:reduced");
|
||||
await expect(page).toHaveTitle(/components-form--launch-settings/i, { timeout: 15_000 });
|
||||
await page.getByRole("textbox", { name: "Email address" }).fill("team@cadence.dev");
|
||||
await page.getByRole("combobox", { name: "Review lane" }).click();
|
||||
await page.getByRole("option", { name: "Legal" }).click();
|
||||
await page.getByRole("textbox", { name: "Launch summary" }).fill(
|
||||
"This release coordinates approvals, copy, and rollout risks."
|
||||
);
|
||||
await page.getByRole("button", { name: "Save settings" }).click();
|
||||
await expect(page.locator("pre code").last()).toContainText('"role": "legal"');
|
||||
});
|
||||
const nextButton = page.getByRole("button", { name: "Next" });
|
||||
await expect(nextButton).toBeEnabled();
|
||||
await nextButton.click();
|
||||
await expect(page.getByRole("button", { name: "Previous" })).toBeEnabled();
|
||||
},
|
||||
"dialog-playground": async (page) => {
|
||||
await page.getByRole("button", { name: "Open approval dialog" }).click();
|
||||
await expect(page.getByRole("dialog", { name: "Launch this release?" })).toBeVisible();
|
||||
await page.getByRole("button", { name: "Close dialog" }).click();
|
||||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||||
},
|
||||
"popover-playground": async (page) => {
|
||||
await page.getByRole("button", { name: "Inspect summary" }).click();
|
||||
await expect(page.getByText("Release health")).toBeVisible();
|
||||
await page.getByRole("button", { name: "Dismiss" }).click();
|
||||
await expect(page.getByText("Release health")).toHaveCount(0);
|
||||
},
|
||||
"sheet-playground": async (page) => {
|
||||
await page.getByRole("button", { name: "Open right sheet" }).click();
|
||||
await expect(page.getByRole("dialog", { name: "Launch settings" })).toBeVisible();
|
||||
await page.getByRole("button", { name: "Close sheet" }).click();
|
||||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||||
}
|
||||
};
|
||||
|
||||
test("storybook data table story stays interactive", async ({ page }) => {
|
||||
await gotoStory(page, "components-data-table--playground");
|
||||
for (const story of smokeStories) {
|
||||
const scenario = story.smokeScenario ? smokeScenarios[story.smokeScenario] : null;
|
||||
|
||||
const table = page.getByRole("table", { name: "Routing lanes" });
|
||||
await expect(table).toBeVisible();
|
||||
await expect(page.getByRole("searchbox", { name: "Search routing lanes" })).toBeVisible();
|
||||
if (!scenario) {
|
||||
throw new Error(`Missing smoke scenario "${story.smokeScenario ?? "undefined"}" for ${story.id}.`);
|
||||
}
|
||||
|
||||
const sortableHeader = page.getByRole("columnheader", { name: /owner/i });
|
||||
await sortableHeader.getByRole("button").click();
|
||||
await expect(sortableHeader).toHaveAttribute("aria-sort", "ascending");
|
||||
|
||||
await page.getByRole("checkbox", { name: /select row/i }).first().click();
|
||||
await expect(page.getByRole("button", { name: "Clear selection" })).toBeVisible();
|
||||
|
||||
const nextButton = page.getByRole("button", { name: "Next" });
|
||||
await expect(nextButton).toBeEnabled();
|
||||
await nextButton.click();
|
||||
await expect(page.getByRole("button", { name: "Previous" })).toBeEnabled();
|
||||
});
|
||||
|
||||
test("storybook overlay stories stay interactive", async ({ page }) => {
|
||||
await gotoStory(page, "components-dialog--playground");
|
||||
await page.getByRole("button", { name: "Open approval dialog" }).click();
|
||||
await expect(page.getByRole("dialog", { name: "Launch this release?" })).toBeVisible();
|
||||
await page.getByRole("button", { name: "Close dialog" }).click();
|
||||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||||
|
||||
await gotoStory(page, "components-popover--playground");
|
||||
await page.getByRole("button", { name: "Inspect summary" }).click();
|
||||
await expect(page.getByText("Release health")).toBeVisible();
|
||||
await page.getByRole("button", { name: "Dismiss" }).click();
|
||||
await expect(page.getByText("Release health")).toHaveCount(0);
|
||||
|
||||
await gotoStory(page, "components-sheet--playground");
|
||||
await page.getByRole("button", { name: "Open right sheet" }).click();
|
||||
await expect(page.getByRole("dialog", { name: "Launch settings" })).toBeVisible();
|
||||
await page.getByRole("button", { name: "Close sheet" }).click();
|
||||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||||
});
|
||||
test(`storybook ${story.label} stays interactive`, async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await expect(page).toHaveTitle(/storybook/i);
|
||||
await gotoStory(page, story);
|
||||
await scenario(page);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user