Skip to content

Commit fe563b7

Browse files
committed
cleanup
1 parent acdc496 commit fe563b7

File tree

6 files changed

+12
-56
lines changed

6 files changed

+12
-56
lines changed

src/mocks/server.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,26 @@ import { config } from "dotenv";
44
import { HttpResponse, http } from "msw";
55
import { handlers } from "./handlers";
66

7-
// Load .env first, then .env.local (which overrides .env)
87
config();
98
config({ path: ".env.local" });
109

11-
// Mock server runs on the port configured in API_BASE_URL
12-
// This ensures the app can reach the mock server at the expected URL
1310
const apiBaseUrl = process.env.API_BASE_URL;
14-
1511
if (!apiBaseUrl) {
1612
throw new Error("API_BASE_URL environment variable is required");
1713
}
1814

1915
const port = new URL(apiBaseUrl).port;
20-
2116
if (!port) {
2217
throw new Error("API_BASE_URL must include a port number");
2318
}
2419

25-
// Add health check endpoint for CI readiness checks
2620
const healthHandler = http.get("*/health", () => {
2721
return HttpResponse.json({ status: "ok" });
2822
});
2923

3024
const httpServer = createServer(healthHandler, ...handlers);
3125

3226
httpServer.on("request", (req: IncomingMessage, _res: ServerResponse) => {
33-
// Skip logging health checks to reduce CI noise
3427
if (req.url?.includes("/health")) return;
3528
console.log(`[mock] ${req.method} ${req.url}`);
3629
});

tests/bdd/steps/global.steps.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,16 @@ Given("I am on {string}", async function (this: PlaywrightWorld, path: string) {
88
});
99

1010
Given("I am logged in", async function (this: PlaywrightWorld) {
11-
// Perform login in a separate page and inject cookies into context
1211
await injectAuthCookies(this.requireContext());
1312
});
1413

15-
// Generic click step using the {role} parameter type (canonical phrases only)
1614
When(
1715
"I click on the {string} {role}",
1816
async function (this: PlaywrightWorld, label: string, role: AriaRole) {
1917
await this.requirePage().getByRole(role, { name: label }).click();
2018
},
2119
);
2220

23-
// Intentionally avoid per-role variants (e.g., button) to keep steps DRY and consistent.
24-
2521
Then(
2622
"I should see the text {string}",
2723
async function (this: PlaywrightWorld, text: string) {

tests/bdd/support/auth.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,18 @@ import type { BrowserContext } from "@playwright/test";
33
const BASE_URL = process.env.BASE_URL || "http://localhost:3000";
44

55
/**
6-
* Performs programmatic login by navigating through the OIDC flow
7-
* in an isolated context, then extracts and injects the cookies.
8-
*
9-
* This is faster than UI-based login for tests that need auth
10-
* but aren't testing the login flow itself.
6+
* Logs in via OIDC flow in a temporary page, leaving auth cookies in the context.
117
*/
128
export async function injectAuthCookies(
139
context: BrowserContext,
1410
): Promise<void> {
15-
// Create a temporary page to perform login
1611
const page = await context.newPage();
17-
1812
try {
19-
// Navigate to signin and click the Okta button
2013
await page.goto(`${BASE_URL}/signin`);
2114
await page.getByRole("button", { name: "Okta" }).click();
22-
23-
// Wait for auth to complete (redirects away from signin)
2415
await page.waitForURL((url) => !url.pathname.startsWith("/signin"), {
2516
timeout: 30000,
2617
});
27-
28-
// Cookies are now set in the context - they'll persist for other pages
2918
} finally {
3019
await page.close();
3120
}

tests/bdd/support/hooks.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import type { PlaywrightWorld } from "./world";
1616
let browser: Browser | undefined;
1717
const TRACE_ENABLED = process.env.PWTRACE === "1";
1818

19-
setDefaultTimeout(60 * 1000); // 60s per step
19+
setDefaultTimeout(60_000);
2020

2121
Before(async function (this: PlaywrightWorld) {
2222
const isDebug = !!process.env.PWDEBUG;
@@ -31,8 +31,8 @@ Before(async function (this: PlaywrightWorld) {
3131
this.context = context;
3232
this.page = page;
3333

34-
// Hide Next.js dev overlay to keep traces clean
3534
await this.page.addInitScript(() => {
35+
// Hide Next.js dev overlay
3636
const style = document.createElement("style");
3737
style.textContent = "nextjs-portal { display: none !important; }";
3838
document.head.appendChild(style);

tests/bdd/support/parameter-types.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,18 @@ import { defineParameterType } from "@cucumber/cucumber";
22
import type { AriaRole } from "@playwright/test";
33
import { allowedRolePhrases } from "./roles.ts";
44

5-
// Build a tight, case-insensitive pattern from the canonical phrases
65
const escapeRegex = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
76
const phrases = Object.keys(allowedRolePhrases).map(escapeRegex).join("|");
8-
// Important: do not anchor (no ^ or $). Cucumber composes parameter regexps
9-
// into a larger expression; anchors can prevent proper matching.
107
const rolePattern = new RegExp(`(?:${phrases})`);
118

129
defineParameterType({
1310
name: "role",
14-
// keep snippets focused on canonical phrases in feature files
1511
useForSnippets: false,
1612
regexp: rolePattern,
1713
transformer: (text: string): AriaRole => {
1814
const key = text.trim().toLowerCase();
1915
const role = allowedRolePhrases[key];
2016
if (role) return role;
21-
const examples = Object.keys(allowedRolePhrases).slice(0, 10).join(", ");
22-
throw new Error(
23-
`Unknown role phrase "${text}". Use one of the canonical phrases (e.g., ${examples} ...).`,
24-
);
17+
throw new Error(`Unknown role phrase "${text}".`);
2518
},
2619
});

tests/bdd/support/roles.ts

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,26 @@
11
import type { AriaRole } from "@playwright/test";
22
import { roles as ariaRolesMap } from "aria-query";
33

4-
// Set of all valid ARIA roles sourced from aria-query (for diagnostics)
5-
export const validAriaRoles = new Set<string>([...ariaRolesMap.keys()]);
6-
7-
// Customized human-friendly phrases → ARIA roles.
8-
// Only add entries here when the preferred phrase differs from the raw ARIA role name.
9-
const customizedRoleNames: Record<string, AriaRole> = {
10-
// Prefer "menu item" over the raw ARIA role string "menuitem"
4+
// Custom phrases for ARIA roles (when the phrase differs from the role name)
5+
const customPhrases: Record<string, AriaRole> = {
116
"menu item": "menuitem",
127
};
138

14-
// Build the canonical mapping of phrases allowed in features → ARIA roles.
15-
// - Start from customized phrases
16-
// - Then add every remaining ARIA role mapping to itself (phrase === role)
17-
// - Do NOT add a self-mapping for roles already covered by a custom phrase,
18-
// so there is exactly one canonical phrase per role.
19-
const buildAllowedRolePhrases = (): Record<string, AriaRole> => {
9+
function buildAllowedRolePhrases(): Record<string, AriaRole> {
2010
const mapping: Record<string, AriaRole> = {};
2111

22-
// Seed with custom phrases (lowercased keys)
23-
for (const [phrase, role] of Object.entries(customizedRoleNames)) {
12+
for (const [phrase, role] of Object.entries(customPhrases)) {
2413
mapping[phrase.trim().toLowerCase()] = role;
2514
}
2615

27-
const customizedRoles = new Set(Object.values(customizedRoleNames));
16+
const customRoles = new Set(Object.values(customPhrases));
2817
for (const roleName of ariaRolesMap.keys()) {
2918
const role = String(roleName) as AriaRole;
30-
if (!customizedRoles.has(role)) {
31-
mapping[role] = role; // default: phrase equals role name
19+
if (!customRoles.has(role)) {
20+
mapping[role] = role;
3221
}
3322
}
3423
return mapping;
35-
};
24+
}
3625

3726
export const allowedRolePhrases = buildAllowedRolePhrases();
38-
39-
// Inverse lookup for recommendations (ARIA role → preferred phrase)
40-
// Note: We intentionally omit an inverse mapping (role -> preferred phrase)
41-
// to keep this surface minimal. Add it here if you want suggestion messages.

0 commit comments

Comments
 (0)