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:
@@ -3,6 +3,7 @@ import path from "node:path";
|
||||
import { createRequire } from "node:module";
|
||||
|
||||
import { chromium } from "@playwright/test";
|
||||
import harnessStoryContract from "../../tests/e2e/support/story-harness-contract.json" with { type: "json" };
|
||||
|
||||
import { repoRoot } from "./core.mjs";
|
||||
|
||||
@@ -16,65 +17,36 @@ const axeSourcePath = require.resolve("axe-core/axe.min.js");
|
||||
const reportDir = path.join(repoRoot, ".artifacts", "a11y");
|
||||
const reportPath = path.join(reportDir, "storybook-a11y.json");
|
||||
|
||||
const stories = [
|
||||
{
|
||||
id: "components-button--playground",
|
||||
label: "Button playground"
|
||||
const a11yPrepareHandlers = {
|
||||
"open-date-picker": async (page) => {
|
||||
await page.getByRole("combobox", { name: "Launch date" }).click();
|
||||
await page.getByRole("dialog", { name: "Launch date calendar" }).waitFor({ state: "visible" });
|
||||
},
|
||||
{
|
||||
id: "components-combobox--controlled",
|
||||
label: "Combobox controlled"
|
||||
"open-dialog": async (page) => {
|
||||
await page.getByRole("button", { name: "Open approval dialog" }).click();
|
||||
await page.getByRole("dialog", { name: "Launch this release?" }).waitFor({ state: "visible" });
|
||||
},
|
||||
{
|
||||
id: "components-data-table--playground",
|
||||
label: "Data table playground"
|
||||
"open-dropdown-menu": async (page) => {
|
||||
await page.getByRole("button", { name: "Review lane menu" }).click();
|
||||
await page.getByRole("menu").waitFor({ state: "visible" });
|
||||
},
|
||||
{
|
||||
id: "components-datepicker--playground",
|
||||
label: "Date picker playground",
|
||||
prepare: async (page) => {
|
||||
await page.getByRole("combobox", { name: "Launch date" }).click();
|
||||
await page.getByRole("dialog", { name: "Launch date calendar" }).waitFor({ state: "visible" });
|
||||
}
|
||||
"open-popover": async (page) => {
|
||||
await page.getByRole("button", { name: "Inspect summary" }).click();
|
||||
await page.getByText("Release health").waitFor({ state: "visible" });
|
||||
},
|
||||
{
|
||||
id: "components-dialog--playground",
|
||||
label: "Dialog playground",
|
||||
prepare: async (page) => {
|
||||
await page.getByRole("button", { name: "Open approval dialog" }).click();
|
||||
await page.getByRole("dialog", { name: "Launch this release?" }).waitFor({ state: "visible" });
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "components-dropdownmenu--states",
|
||||
label: "Dropdown menu states",
|
||||
prepare: async (page) => {
|
||||
await page.getByRole("button", { name: "Review lane menu" }).click();
|
||||
await page.getByRole("menu").waitFor({ state: "visible" });
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "components-form--launch-settings",
|
||||
label: "Form launch settings",
|
||||
query: "globals=motion:reduced"
|
||||
},
|
||||
{
|
||||
id: "components-popover--playground",
|
||||
label: "Popover playground",
|
||||
prepare: async (page) => {
|
||||
await page.getByRole("button", { name: "Inspect summary" }).click();
|
||||
await page.getByText("Release health").waitFor({ state: "visible" });
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "components-sheet--playground",
|
||||
label: "Sheet playground",
|
||||
prepare: async (page) => {
|
||||
await page.getByRole("button", { name: "Open right sheet" }).click();
|
||||
await page.getByRole("dialog", { name: "Launch settings" }).waitFor({ state: "visible" });
|
||||
}
|
||||
"open-sheet": async (page) => {
|
||||
await page.getByRole("button", { name: "Open right sheet" }).click();
|
||||
await page.getByRole("dialog", { name: "Launch settings" }).waitFor({ state: "visible" });
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
const stories = harnessStoryContract.stories.filter((story) => story.suites.includes("a11y"));
|
||||
|
||||
for (const story of stories) {
|
||||
if (story.a11yPrepare && !(story.a11yPrepare in a11yPrepareHandlers)) {
|
||||
throw new Error(`Unknown a11y prepare handler "${story.a11yPrepare}" for ${story.id}.`);
|
||||
}
|
||||
}
|
||||
|
||||
function buildStoryUrl(story) {
|
||||
const params = new URLSearchParams({
|
||||
@@ -215,8 +187,8 @@ async function main() {
|
||||
try {
|
||||
await gotoStory(page, story);
|
||||
|
||||
if (story.prepare) {
|
||||
await story.prepare(page);
|
||||
if (story.a11yPrepare) {
|
||||
await a11yPrepareHandlers[story.a11yPrepare](page);
|
||||
}
|
||||
|
||||
const result = await runAxe(page);
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// @vitest-environment node
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import harnessStoryContract from "../../tests/e2e/support/story-harness-contract.json";
|
||||
|
||||
describe("story harness contract", () => {
|
||||
it("uses unique story ids", () => {
|
||||
const storyIds = harnessStoryContract.stories.map((story) => story.id);
|
||||
|
||||
expect(new Set(storyIds).size).toBe(storyIds.length);
|
||||
});
|
||||
|
||||
it("requires a reason for every curated story", () => {
|
||||
expect(harnessStoryContract.stories.every((story) => story.reason.trim().length > 0)).toBe(true);
|
||||
});
|
||||
|
||||
it("requires smoke scenarios for docs-smoke coverage", () => {
|
||||
expect(
|
||||
harnessStoryContract.stories
|
||||
.filter((story) => story.suites.includes("docs-smoke"))
|
||||
.every((story) => Boolean(story.smokeScenario))
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("keeps every story on at least one supported suite", () => {
|
||||
const supportedSuites = new Set(["a11y", "docs-smoke"]);
|
||||
|
||||
expect(
|
||||
harnessStoryContract.stories.every(
|
||||
(story) => story.suites.length > 0 && story.suites.every((suite) => supportedSuites.has(suite))
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user