From 0b9fe8267f3aaef73a23ea2691624062a31fcd40 Mon Sep 17 00:00:00 2001 From: Teffen Ellis Date: Fri, 26 Sep 2025 00:28:33 +0200 Subject: [PATCH] wip: Flesh out. --- web/e2e/fixtures/FormFixture.ts | 62 +++++- web/e2e/fixtures/PointerFixture.ts | 10 +- .../admin/applications/ApplicationListPage.ts | 2 +- .../admin/enterprise/EnterpriseLicenseForm.ts | 2 +- web/src/admin/groups/MemberSelectModal.ts | 37 ++-- web/src/admin/groups/RelatedUserList.ts | 51 +++-- .../PropertyMappingListPage.ts | 51 +++-- web/src/admin/users/ServiceAccountForm.ts | 109 +++++---- web/src/admin/users/UserForm.ts | 207 ++++++++++-------- web/src/admin/users/UserListPage.ts | 71 +++--- web/src/common/styles/authentik.css | 16 +- web/src/common/styles/theme-dark.css | 4 - .../components/HorizontalLightComponent.ts | 55 +++-- web/src/components/ak-hidden-text-input.ts | 6 + web/src/components/ak-label.ts | 13 +- web/src/components/ak-radio-input.ts | 7 +- web/src/components/ak-search-ql/index.ts | 99 ++++++--- web/src/components/ak-status-label.ts | 2 +- web/src/components/ak-text-input.ts | 19 +- web/src/elements/buttons/ModalButton.ts | 4 + web/src/elements/forms/ModalForm.ts | 12 +- web/src/elements/table/Table.ts | 84 +++---- web/src/elements/table/TablePage.ts | 10 +- web/src/elements/table/TablePagination.ts | 37 +++- web/src/elements/table/TableSearch.ts | 64 +++--- web/src/elements/table/shared.ts | 5 +- web/src/elements/tasks/ScheduleList.ts | 41 ++-- web/src/elements/tasks/TaskList.ts | 73 +++--- web/test/browser/providers.test.ts | 11 +- web/test/browser/users.test.ts | 113 ++++++++++ 30 files changed, 802 insertions(+), 475 deletions(-) create mode 100644 web/test/browser/users.test.ts diff --git a/web/e2e/fixtures/FormFixture.ts b/web/e2e/fixtures/FormFixture.ts index 80bdb7fae1c1..a1130b53e6a9 100644 --- a/web/e2e/fixtures/FormFixture.ts +++ b/web/e2e/fixtures/FormFixture.ts @@ -1,7 +1,7 @@ import { PageFixture } from "#e2e/fixtures/PageFixture"; import type { LocatorContext } from "#e2e/selectors/types"; -import { expect, Page } from "@playwright/test"; +import { expect, Locator, Page } from "@playwright/test"; export class FormFixture extends PageFixture { static fixtureName = "Form"; @@ -18,22 +18,62 @@ export class FormFixture extends PageFixture { * @param fieldName The name of the form element. * @param value the value to set. */ - public fill = async ( - fieldName: string, - value: string, - parent: LocatorContext = this.page, - ): Promise => { - const control = parent - .getByRole("textbox", { - name: fieldName, + public findTextualInput = async ( + fieldName: string | RegExp, + context: LocatorContext = this.page, + ) => { + const control = context + .getByLabel(fieldName, { exact: true }) + .filter({ + hasNot: context.getByRole("presentation"), }) .or( - parent.getByRole("spinbutton", { + context.getByRole("textbox", { + name: fieldName, + }), + ) + .or( + context.getByRole("spinbutton", { name: fieldName, }), ); - await expect(control, `Field (${fieldName}) should be visible`).toBeVisible(); + const role = await control.getAttribute("role"); + + let textbox: Locator; + + if (role === "combobox") { + // Comboboxes, such as our Query Language input need additional handling... + const textbox = control.getByRole("textbox"); + + return textbox; + } else { + textbox = control; + } + + await expect(textbox, `Field (${fieldName}) should be visible`).toBeVisible(); + + return textbox; + }; + + /** + * Set the value of a text input. + * + * @param target The name of the form element. + * @param value the value to set. + */ + public fill = async ( + target: string | RegExp | Locator, + value: string, + context: LocatorContext = this.page, + ): Promise => { + let control: Locator; + + if (typeof target === "string" || target instanceof RegExp) { + control = await this.findTextualInput(target, context); + } else { + control = target; + } await control.fill(value); }; diff --git a/web/e2e/fixtures/PointerFixture.ts b/web/e2e/fixtures/PointerFixture.ts index 04453e89241f..e7d540cdf66c 100644 --- a/web/e2e/fixtures/PointerFixture.ts +++ b/web/e2e/fixtures/PointerFixture.ts @@ -18,12 +18,14 @@ export class PointerFixture extends PageFixture { public static fixtureName = "Pointer"; public click = ( - name: string, + name: string | RegExp, optionsOrRole?: ARIAOptions | ARIARole, context: LocatorContext = this.page, ): Promise => { if (typeof optionsOrRole === "string") { - return context.getByRole(optionsOrRole, { name }).click(); + return context.getByRole(optionsOrRole, { name }).click({ + force: true, + }); } const options = { @@ -36,7 +38,9 @@ export class PointerFixture extends PageFixture { // --- .getByRole("button", options) .or(context.getByRole("link", options)) - .click() + .click({ + force: true, + }) ); }; } diff --git a/web/src/admin/applications/ApplicationListPage.ts b/web/src/admin/applications/ApplicationListPage.ts index 199f1e21e73c..1e6f25726792 100644 --- a/web/src/admin/applications/ApplicationListPage.ts +++ b/web/src/admin/applications/ApplicationListPage.ts @@ -80,7 +80,7 @@ export class ApplicationListPage extends WithBrandConfig(TablePage) protected renderSidebarAfter(): TemplateResult { return html`