mirror of
https://github.com/goauthentik/authentik
synced 2026-04-27 18:07:15 +02:00
* Close dialog on navigation. * web: update dialog, form, and sidebar styles with logical properties and scroll shadows Migrate dialog padding CSS variables from physical (top/right/bottom/left) to logical (block-start/inline-end/block-end/inline-start) naming. Add scroll shadow utility class (ak-m-scroll-shadows) for scrollable regions. Rework radio input and form control styles including transparent backgrounds, checkbox-style indicators, and improved hover states. Refactor FormGroup marker to use CSS custom properties for open/closed states. Move sidebar padding from nav container to scrollable list. * web: refine elements and components for accessibility, type safety, and consistency Add ARIA role and label to dialog body, apply scroll shadow classes to modal body, sidebar nav, and wizard main. Update ak-status-label to support tri-state (good/bad/null) rendering with ts-pattern matching and a neutral label. Simplify FormGroup by removing wrapper div around default slot, adding part attributes for header styling, and changing description to nullable type. Clean up LogViewer and StaticTable with proper access modifiers, override annotations, and nullable item types. Simplify ak-switch-input checked binding and remove unused slot attribute from ak-radio-input help text. * web: modernize application pages with modalInvoker and updated form patterns Refactor ApplicationCheckAccessForm to use static form metadata properties (verboseName, submitVerb, createLabel), formatAPISuccessMessage, and a private CoreApi instance. Migrate ApplicationViewPage from ak-forms-modal slots to the modalInvoker directive for both edit and check-access actions. Accept nullable input in createPaginatedResponse for better null-safety. Fix casing of dropdown menu items in ApplicationListPage. * web: migrate remaining view pages to modalInvoker (#21592) * Fix visibility check, search params. * Add scroll shadow. * Partial revert of input layout. * Tidy groups. * Fix check access form invoker, styles. * Optional sizing. * Lowercase * Revise checkbox style. * Close dialog on navigation. * Fix padding. * Touch up shadow heights. * Migrate remaining view pages to modalInvoker, add e2e coverage. * Fix alignment. * Fix click handler, add placeholders. * Fix issue where form field is not serialized.
173 lines
5.8 KiB
TypeScript
173 lines
5.8 KiB
TypeScript
import { expect, test } from "#e2e";
|
|
import { randomName } from "#e2e/utils/generators";
|
|
|
|
import { IDGenerator } from "@goauthentik/core/id";
|
|
|
|
test.describe("Roles", () => {
|
|
const roleNames = new Map<string, string>();
|
|
|
|
//#region Lifecycle
|
|
|
|
test.beforeEach("Prepare role", async ({ session }, { testId }) => {
|
|
const seed = IDGenerator.randomID(6);
|
|
const roleName = `${randomName(seed)} (${seed})`;
|
|
|
|
roleNames.set(testId, roleName);
|
|
|
|
await test.step("Authenticate", async () => {
|
|
await session.login({
|
|
to: "/if/admin/#/identity/roles",
|
|
});
|
|
});
|
|
});
|
|
|
|
//#endregion
|
|
|
|
//#region Tests
|
|
|
|
test("Simple role", async ({ form, pointer, page }, testInfo) => {
|
|
const roleName = roleNames.get(testInfo.testId)!;
|
|
|
|
const { fill, search } = form;
|
|
const { click } = pointer;
|
|
|
|
const dialog = page.getByRole("dialog", { name: "New Role" });
|
|
|
|
await test.step("Create role", async () => {
|
|
await expect(dialog, "Dialog is initially closed").toBeHidden();
|
|
|
|
await click("New Role", "button");
|
|
|
|
await expect(dialog, "Dialog opens").toBeVisible();
|
|
|
|
await fill(/^Role Name/, roleName, dialog);
|
|
|
|
await dialog.getByRole("button", { name: "Create Role" }).click();
|
|
|
|
await expect(dialog, "Dialog closes after creating role").toBeHidden();
|
|
});
|
|
|
|
await test.step("Verify role creation", async () => {
|
|
const $role = await search(roleName);
|
|
|
|
await expect($role, "Role is visible in the table").toBeVisible();
|
|
});
|
|
});
|
|
|
|
test("Edit role", async ({ form, pointer, page }, testInfo) => {
|
|
const roleName = roleNames.get(testInfo.testId)!;
|
|
|
|
const { fill, search } = form;
|
|
const { click } = pointer;
|
|
|
|
const newRoleDialog = page.getByRole("dialog", { name: "New Role" });
|
|
const editRoleDialog = page.getByRole("dialog", { name: "Edit Role" });
|
|
|
|
await test.step("Create role", async () => {
|
|
await click("New Role", "button");
|
|
|
|
await expect(newRoleDialog, "Dialog opens").toBeVisible();
|
|
|
|
await fill(/^Role Name/, roleName, newRoleDialog);
|
|
|
|
await newRoleDialog.getByRole("button", { name: "Create Role" }).click();
|
|
|
|
await expect(newRoleDialog, "Dialog closes after creating role").toBeHidden();
|
|
});
|
|
|
|
const updatedName = `${roleName} Edited`;
|
|
|
|
await test.step("Edit role via row action", async () => {
|
|
const $role = await search(roleName);
|
|
|
|
await expect($role, "Role is visible").toBeVisible();
|
|
|
|
await $role.getByRole("button", { name: "Edit" }).click();
|
|
|
|
await expect(editRoleDialog, "Edit dialog opens").toBeVisible();
|
|
|
|
const nameInput = editRoleDialog.getByRole("textbox", { name: /Role Name/ });
|
|
|
|
await expect(nameInput, "Name input is visible").toBeVisible();
|
|
|
|
await expect(nameInput, "Name is pre-filled").toHaveValue(roleName);
|
|
|
|
await nameInput.fill(updatedName);
|
|
|
|
await editRoleDialog.getByRole("button", { name: "Save Changes" }).click();
|
|
|
|
await expect(editRoleDialog, "Edit dialog closes after saving").toBeHidden();
|
|
});
|
|
|
|
await test.step("Verify role was updated", async () => {
|
|
const $updatedRole = await search(updatedName);
|
|
|
|
await expect($updatedRole, "Updated role is visible in the table").toBeVisible();
|
|
});
|
|
});
|
|
|
|
test("Edit role from view page", async ({ navigator, form, pointer, page }, testInfo) => {
|
|
const roleName = roleNames.get(testInfo.testId)!;
|
|
|
|
const { fill, search } = form;
|
|
const { click } = pointer;
|
|
|
|
const newRoleDialog = page.getByRole("dialog", { name: "New Role" });
|
|
const editRoleDialog = page.getByRole("dialog", { name: "Edit Role" });
|
|
|
|
await test.step("Create role", async () => {
|
|
await click("New Role", "button");
|
|
|
|
await expect(newRoleDialog, "Dialog opens").toBeVisible();
|
|
|
|
await fill(/^Role Name/, roleName, newRoleDialog);
|
|
|
|
await newRoleDialog.getByRole("button", { name: "Create Role" }).click();
|
|
|
|
await expect(newRoleDialog, "Dialog closes after creating role").toBeHidden();
|
|
});
|
|
|
|
await test.step("Navigate to role view page", async () => {
|
|
const $role = await search(roleName);
|
|
|
|
await expect($role, "Role is visible").toBeVisible();
|
|
|
|
const viewLink = $role.getByRole("link", { name: "view details" });
|
|
await expect(viewLink, "View details link is visible").toBeVisible();
|
|
|
|
const viewURL = await viewLink.evaluate((el: HTMLAnchorElement) => el.href);
|
|
await navigator.navigate(viewURL);
|
|
});
|
|
|
|
const updatedName = `${roleName} View Edited`;
|
|
|
|
await test.step("Edit role from view page", async () => {
|
|
await expect(editRoleDialog, "Edit dialog is initially closed").toBeHidden();
|
|
|
|
await click("Edit", "button");
|
|
|
|
await expect(editRoleDialog, "Edit dialog opens").toBeVisible();
|
|
|
|
const nameInput = editRoleDialog.getByRole("textbox", { name: /Role Name/ });
|
|
|
|
await expect(nameInput, "Name input is visible").toBeVisible();
|
|
await expect(nameInput, "Name is pre-filled").toHaveValue(roleName);
|
|
|
|
await nameInput.fill(updatedName);
|
|
|
|
await editRoleDialog.getByRole("button", { name: "Save Changes" }).click();
|
|
|
|
await expect(editRoleDialog, "Edit dialog closes after saving").toBeHidden();
|
|
});
|
|
|
|
await test.step("Verify role name updated on view page", async () => {
|
|
await expect(
|
|
page.getByText(updatedName),
|
|
"Updated role name is visible on view page",
|
|
).toBeVisible();
|
|
});
|
|
});
|
|
|
|
//#endregion
|
|
});
|