Skip to content

Commit

Permalink
added axe tests for flows
Browse files Browse the repository at this point in the history
Signed-off-by: Erik Jan de Wit <[email protected]>
  • Loading branch information
edewit committed Dec 20, 2024
1 parent 81f20fd commit f983362
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 55 deletions.
5 changes: 3 additions & 2 deletions js/apps/admin-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
}
},
"dependencies": {
"@axe-core/playwright": "^4.10.1",
"@keycloak/keycloak-admin-client": "workspace:*",
"@keycloak/keycloak-ui-shared": "workspace:*",
"@patternfly/patternfly": "^5.4.2",
Expand Down Expand Up @@ -134,10 +135,10 @@
"ldap-server-mock": "^6.0.1",
"lightningcss": "^1.28.2",
"ts-node": "^10.9.2",
"uuid": "^11.0.3",
"vite": "^6.0.3",
"vite-plugin-checker": "^0.8.0",
"vite-plugin-dts": "^4.3.0",
"vitest": "^2.1.8",
"uuid": "^11.0.3"
"vitest": "^2.1.8"
}
}
50 changes: 48 additions & 2 deletions js/apps/admin-ui/test/autentication/flow.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Page, expect } from "@playwright/test";
import { confirmModal } from "../utils/modal";
import AxeBuilder from "@axe-core/playwright";
import { selectItem } from "../utils/form";

export async function fillDuplicateFlowModal(
page: Page,
Expand Down Expand Up @@ -30,6 +32,29 @@ export async function goToRequiredActions(page: Page) {
await page.getByTestId("requiredActions").click();
}

export async function goToPoliciesTab(page: Page) {
await page.getByTestId("policies").click();
}

export async function goToOTPPolicyTab(page: Page) {
await goToPoliciesTab(page);
await page.getByTestId("otpPolicy").click();
}

export async function goToWebAuthnTab(page: Page) {
await goToPoliciesTab(page);
await page.getByTestId("webauthnPolicy").click();
}

export async function goToCIBAPolicyTab(page: Page) {
await goToPoliciesTab(page);
await page.getByTestId("tab-ciba-policy").click();
}

export async function addPolicy(page: Page, value) {
await selectItem(page, page.getByTestId("add-policy"), value);
}

const toKey = (name: string) => {
return name.replace(/\s/g, "-");
};
Expand All @@ -54,12 +79,33 @@ export async function assertSwitchPolicyChecked(
page: Page,
policyName: string,
) {
expect(getEnabledSwitch(page, policyName)).toBeChecked();
await expect(getEnabledSwitch(page, policyName)).toBeChecked();
}

export async function assertDefaultSwitchPolicyEnabled(
page: Page,
policyName: string,
) {
expect(getDefaultSwitch(page, policyName)).toBeEnabled();
await expect(getDefaultSwitch(page, policyName)).toBeEnabled();
}

export async function goToCreateItem(page: Page) {
await page.getByRole("link", { name: "Create flow" }).click();
}

export async function assertAxeViolations(page: Page) {
const { violations } = await new AxeBuilder({ page }).analyze();
expect(violations.length, violations.map((v) => v.help).join("\n")).toBe(0);
}

export async function fillCreateForm(
page: Page,
name: string,
description: string,
type: string,
) {
await page.getByTestId("alias").fill(name);
await page.getByTestId("description").fill(description);
await selectItem(page, page.getByLabel("Flow type"), type);
await page.getByTestId("create").click();
}
156 changes: 108 additions & 48 deletions js/apps/admin-ui/test/autentication/flows.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, test } from "@playwright/test";
import { v4 as uuidv4 } from "uuid";
import adminClient from "../../cypress/support/util/AdminClient";
import { assertRequiredFieldError } from "../utils/form";
import { assertRequiredFieldError, clickSaveButton } from "../utils/form";
import { login } from "../utils/login";
import { assertNotificationMessage } from "../utils/masthead";
import { goToAuthentication, goToRealm } from "../utils/sidebar";
Expand All @@ -14,13 +14,21 @@ import {
} from "../utils/table";
import {
addExecution,
addPolicy,
assertAxeViolations,
assertDefaultSwitchPolicyEnabled,
assertExecutionExists,
assertSwitchPolicyChecked,
clickDefaultSwitchPolicy,
clickSwitchPolicy,
fillCreateForm,
fillDuplicateFlowModal,
goToCIBAPolicyTab,
goToCreateItem,
goToOTPPolicyTab,
goToPoliciesTab,
goToRequiredActions,
goToWebAuthnTab,
} from "./flow";

test.describe("Authentication test", () => {

Check failure on line 34 in js/apps/admin-ui/test/autentication/flows.spec.ts

View workflow job for this annotation

GitHub Actions / Admin UI

test/autentication/flows.spec.ts

Error: Playwright Test did not expect test.describe() to be called here. Most common reasons include: - You are calling test.describe() in a configuration file. - You are calling test.describe() in a file that is imported by the configuration file. - You have two different versions of @playwright/test. This usually happens when one of the dependencies in your package.json depends on @playwright/test. ❯ TestTypeImpl._currentSuite ../../node_modules/.pnpm/[email protected]/node_modules/playwright/lib/common/testType.js:72:13 ❯ TestTypeImpl._describe ../../node_modules/.pnpm/[email protected]/node_modules/playwright/lib/common/testType.js:104:24 ❯ Function.describe ../../node_modules/.pnpm/[email protected]/node_modules/playwright/lib/transform/transform.js:288:12 ❯ test/autentication/flows.spec.ts:34:6
Expand Down Expand Up @@ -53,15 +61,15 @@ test.describe("Authentication test", () => {
});

test("Should fail duplicate with empty flow name", async ({ page }) => {
await selectRowKebab(page, "Browser");
await selectRowKebab(page, "Direct grant");
await clickRowKebabItem(page, "Duplicate");
await fillDuplicateFlowModal(page, "");

await assertRequiredFieldError(page, "alias");
});

test("Should fail duplicate with duplicated name", async ({ page }) => {
await selectRowKebab(page, "Browser");
await selectRowKebab(page, "Direct grant");
await clickRowKebabItem(page, "Duplicate");
await fillDuplicateFlowModal(page, "browser");

Expand All @@ -73,21 +81,22 @@ test.describe("Authentication test", () => {

test.describe("Flow details", () => {
let flowId: string | undefined;
const flowName = "Copy of browser test";
test.beforeAll(() =>
adminClient.inRealm(realmName, async () => {
await adminClient.copyFlow("browser", "Copy of browser");
flowId = (await adminClient.getFlow("Copy of browser"))!.id!;
await adminClient.copyFlow("browser", flowName);
flowId = (await adminClient.getFlow(flowName))!.id!;
}),
);
test.afterAll(() =>
adminClient.inRealm(realmName, () => adminClient.deleteFlow(flowId!)),
);

test("Should add a execution", async ({ page }) => {
await clickTableRowItem(page, "Copy of browser");
await clickTableRowItem(page, flowName);
await addExecution(
page,
"Copy of browser forms",
flowName + " forms",
"reset-credentials-choose-user",
);

Expand Down Expand Up @@ -153,55 +162,106 @@ test.describe("Password policies tab", () => {
test.beforeEach(async ({ page }) => {
await login(page);
await goToAuthentication(page);
await page.click("text=Password Policy");
await goToPoliciesTab(page);
});

test("should add password policies", async ({ page }) => {
await expect(page.locator('[data-testid="empty-state"]')).toBeVisible();
await page.selectOption(
'[data-testid="policy-select"]',
"Not Recently Used",
);
await page.click('[data-testid="save"]');
await addPolicy(page, "Not Recently Used");
await clickSaveButton(page);
await assertNotificationMessage(
page,
"Password policies successfully updated",
);
});

// Additional password policy tests...
});

// // Note: For accessibility tests, you would use the @axe-core/playwright package
// test.describe("Accessibility tests for authentication", () => {
// const realmName = "a11y-realm";

// test.beforeAll(async ({ request }) => {
// await request.post("/admin/realms", {
// data: { realm: realmName },
// });
// });

// test.beforeEach(async ({ page }) => {
// await login(page);
// await goToRealm(page, realmName);
// await goToAuthentication(page);
// });

// test.afterAll(async ({ request }) => {
// await request.delete(`/admin/realms/${realmName}`);
// });

// test("should pass accessibility checks on main page", async ({ page }) => {
// // Assuming you've configured axe-core
// const violations = await page.evaluate(async () => {
// // @ts-ignore
// const { axe } = window;
// const results = await axe.run();
// return results.violations;
// });
// expect(violations.length).toBe(0);
// });

// // Additional accessibility tests...
// });
test.describe("Accessibility tests for authentication", () => {
const realmName = "a11y-realm";
const flowName = `Flow-${uuidv4()}`;

test.beforeAll(() => adminClient.createRealm(realmName));
test.afterAll(() => adminClient.deleteRealm(realmName));

test.beforeEach(async ({ page }) => {
await login(page);
await goToRealm(page, realmName);
await goToAuthentication(page);
});

test("should pass accessibility checks on main page", async ({ page }) => {
await assertAxeViolations(page);
});

test("Check a11y violations on load/ authentication tab/ flows sub tab/ creating flow form", async ({
page,
}) => {
await goToCreateItem(page);

await assertAxeViolations(page);
await page.getByTestId("cancel").click();
});

test("Check a11y violations on load/ authentication tab/ flows sub tab/ creating flow", async ({
page,
}) => {
await goToCreateItem(page);
await fillCreateForm(
page,
flowName,
"Some nice description about what this flow does",
"Client flow",
);
await assertAxeViolations(page);
});

test("Check a11y violations on load/ authentication tab/ flows sub tab/ creating", async ({
page,
}) => {
await clickTableRowItem(page, "reset credentials");
await assertAxeViolations(page);
});

test("Check a11y violations on load/ authentication tab/ required actions sub tab", async ({
page,
}) => {
await goToRequiredActions(page);
await assertAxeViolations(page);
});

test("Check a11y violations on load/ policies tab/ password policy sub tab", async ({
page,
}) => {
await goToPoliciesTab(page);
await assertAxeViolations(page);
});

test("Check a11y violations on load/ authentication tab/ policies sub tab/ adding policy", async ({
page,
}) => {
await goToPoliciesTab(page);
await addPolicy(page, "Not Recently Used");
await assertAxeViolations(page);
});

test("Check a11y violations on load/ policies tab/ otp policy sub tab", async ({
page,
}) => {
await goToOTPPolicyTab(page);
await assertAxeViolations(page);
});

test("Check a11y violations on load/ policies tab/ WebAuthn Policies sub tab", async ({
page,
}) => {
await goToWebAuthnTab(page);
await assertAxeViolations(page);
});

test("Check a11y violations on load/ policies tab/ CIBA Policy sub tab", async ({
page,
}) => {
await goToCIBAPolicyTab(page);
await assertAxeViolations(page);
});
});
2 changes: 1 addition & 1 deletion js/apps/admin-ui/test/utils/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export async function assertFieldError(

export async function selectItem(page: Page, field: Locator, value: string) {
await field.click();
await page.getByRole("option", { name: value }).click();
await page.getByRole("option", { name: value, exact: true }).click();
}

export async function clickSaveButton(page: Page) {
Expand Down
19 changes: 17 additions & 2 deletions js/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f983362

Please sign in to comment.