web: Fix css loading in unit tests, remove unneeded dot paths (#11629)

* Adding the aliases to Vite helped, but now why are the E2E tests failing?

* web: fix CSS loading with unit tests

- Fix the CSS loader and replace the cut-and-paste loader with a standardized one.
- Fix the aliasing for Wdio's "browser"-based unit testing (Vite)
  - With the aliasing fixed, remove all of the dotted paths in tests.
- Update the End-to-End tests to run in Firefox and Safari.
- Put an (optional) pause at the end of each unit test so we can visually confirm the CSS works.
  - Environment flag is `WDIO_LEMME_SEE=true`
- Reduce the verbosity of the tests to level `warn` or higher

* This change was due to a misunderstanding. It is not needed in 9.

* Fix the Oauth2 Provider test.
This commit is contained in:
Ken Sternberg
2024-10-08 08:31:17 -07:00
committed by GitHub
parent 72a904512c
commit 9200a598ec
13 changed files with 130 additions and 115 deletions

View File

@ -1,25 +1,13 @@
import { render } from "@goauthentik/elements/tests/utils.js";
import { $, expect } from "@wdio/globals";
import { msg } from "@lit/localize";
import { TemplateResult, html, render as litRender } from "lit";
import AKGlobal from "../../common/styles/authentik.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { html } from "lit";
import { LicenseForecast, LicenseSummary, LicenseSummaryStatusEnum } from "@goauthentik/api";
import { ensureCSSStyleSheet } from "../../elements/utils/ensureCSSStyleSheet.js";
import "./EnterpriseStatusCard.js";
const render = (body: TemplateResult) => {
document.adoptedStyleSheets = [
...document.adoptedStyleSheets,
ensureCSSStyleSheet(PFBase),
ensureCSSStyleSheet(AKGlobal),
];
return litRender(body, document.body);
};
describe("ak-enterprise-status-card", () => {
it("should not error when no data is loaded", async () => {
render(html`<ak-enterprise-status-card></ak-enterprise-status-card>`);

View File

@ -1,22 +1,10 @@
import { $, expect } from "@wdio/globals";
import { msg } from "@lit/localize";
import { TemplateResult, html, render as litRender } from "lit";
import AKGlobal from "../common/styles/authentik.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { html } from "lit";
import "./EmptyState.js";
import { ensureCSSStyleSheet } from "./utils/ensureCSSStyleSheet.js";
const render = (body: TemplateResult) => {
document.adoptedStyleSheets = [
...document.adoptedStyleSheets,
ensureCSSStyleSheet(PFBase),
ensureCSSStyleSheet(AKGlobal),
];
return litRender(body, document.body);
};
import { render } from "./tests/utils.js";
describe("ak-empty-state", () => {
it("should render the default loader", async () => {

View File

@ -1,7 +1,8 @@
import { render } from "@goauthentik/elements/tests/utils.js";
import { $, browser } from "@wdio/globals";
import { slug } from "github-slugger";
import { html, render } from "lit";
import { html } from "lit";
import "../ak-select-table.js";
import { nutritionDbUSDA as unsortedNutritionDbUSDA } from "../stories/sample_nutrition_db.js";

View File

@ -1,7 +1,8 @@
import { render } from "@goauthentik/elements/tests/utils.js";
import { $ } from "@wdio/globals";
import { slug } from "github-slugger";
import { html, render } from "lit";
import { html } from "lit";
import "../ak-simple-table.js";
import { nutritionDbUSDA } from "../stories/sample_nutrition_db.js";

View File

@ -1,22 +1,10 @@
import { render } from "@goauthentik/elements/tests/utils.js";
import { $, expect } from "@wdio/globals";
import { TemplateResult, html, render as litRender } from "lit";
import { html } from "lit";
import AKGlobal from "../../../common/styles/authentik.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { ensureCSSStyleSheet } from "../../utils/ensureCSSStyleSheet.js";
import "../AggregateCard.js";
const render = (body: TemplateResult) => {
document.adoptedStyleSheets = [
...document.adoptedStyleSheets,
ensureCSSStyleSheet(PFBase),
ensureCSSStyleSheet(AKGlobal),
];
return litRender(body, document.body);
};
describe("ak-aggregate-card", () => {
it("should render the standard card without an icon, link, or subtext", async () => {
render(

View File

@ -1,22 +1,10 @@
import { render } from "@goauthentik/elements/tests/utils.js";
import { $, expect } from "@wdio/globals";
import { TemplateResult, html, render as litRender } from "lit";
import { html } from "lit";
import AKGlobal from "../../../common/styles/authentik.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { ensureCSSStyleSheet } from "../../utils/ensureCSSStyleSheet.js";
import "../AggregatePromiseCard.js";
const render = (body: TemplateResult) => {
document.adoptedStyleSheets = [
...document.adoptedStyleSheets,
ensureCSSStyleSheet(PFBase),
ensureCSSStyleSheet(AKGlobal),
];
return litRender(body, document.body);
};
const DELAY = 1000; // milliseconds
describe("ak-aggregate-card-promise", () => {

View File

@ -1,23 +1,11 @@
import { render } from "@goauthentik/elements/tests/utils.js";
import { $, expect } from "@wdio/globals";
import { TemplateResult, html, render as litRender } from "lit";
import { html } from "lit";
import AKGlobal from "../../../common/styles/authentik.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { ensureCSSStyleSheet } from "../../utils/ensureCSSStyleSheet.js";
import { QuickAction } from "../QuickActionsCard.js";
import "../QuickActionsCard.js";
const render = (body: TemplateResult) => {
document.adoptedStyleSheets = [
...document.adoptedStyleSheets,
ensureCSSStyleSheet(PFBase),
ensureCSSStyleSheet(AKGlobal),
];
return litRender(body, document.body);
};
const ACTIONS: QuickAction[] = [
["Create a new application", "/core/applications"],
["Check the logs", "/events/log"],

View File

@ -1,8 +1,9 @@
import { render } from "@goauthentik/elements/tests/utils.js";
import { $, browser, expect } from "@wdio/globals";
import { slug } from "github-slugger";
import { Key } from "webdriverio";
import { html, render } from "lit";
import { html } from "lit";
import "../ak-search-select-view.js";
import { sampleData } from "../stories/sampleData.js";

View File

@ -1,14 +1,15 @@
/* eslint-env jest */
import { AKElement } from "@goauthentik/elements/Base.js";
import { bound } from "@goauthentik/elements/decorators/bound.js";
import { render } from "@goauthentik/elements/tests/utils.js";
import { CustomListenerElement } from "@goauthentik/elements/utils/eventEmitter";
import { $, browser, expect } from "@wdio/globals";
import { slug } from "github-slugger";
import { html, render } from "lit";
import { html } from "lit";
import { customElement } from "lit/decorators.js";
import { property, query } from "lit/decorators.js";
import { AKElement } from "../../../../elements/Base.js";
import { bound } from "../../../../elements/decorators/bound.js";
import { CustomListenerElement } from "../../../../elements/utils/eventEmitter";
import "../ak-search-select.js";
import { SearchSelect } from "../ak-search-select.js";
import { type ViewSample, sampleData } from "../stories/sampleData.js";

View File

@ -0,0 +1,19 @@
import { TemplateResult, render as litRender } from "lit";
import AKGlobal from "@goauthentik/common/styles/authentik.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { ensureCSSStyleSheet } from "../utils/ensureCSSStyleSheet.js";
// A special version of render that ensures our style sheets will always be available
// to all elements under test. Ensures they look right during testing, and that any
// CSS-based checks for visibility will return correct values.
export const render = (body: TemplateResult) => {
document.adoptedStyleSheets = [
...document.adoptedStyleSheets,
ensureCSSStyleSheet(PFBase),
ensureCSSStyleSheet(AKGlobal),
];
return litRender(body, document.body);
};

View File

@ -9,7 +9,7 @@ async function reachTheProvider() {
await ProvidersListPage.logout();
await login();
await ProvidersListPage.open();
await expect(await ProvidersListPage.pageHeader).toHaveText("Providers");
await expect(await ProvidersListPage.pageHeader()).toHaveText("Providers");
await ProvidersListPage.startWizardButton.click();
await ProviderWizardView.wizardTitle.waitForDisplayed();
@ -22,16 +22,13 @@ describe("Configure Oauth2 Providers", () => {
await reachTheProvider();
await ProviderWizardView.providerList.waitForDisplayed();
// @ts-expect-error "TSC does not understand metaprogramming."
await ProviderWizardView.oauth2Provider.scrollIntoView();
// @ts-expect-error "TSC does not understand metaprogramming."
await ProviderWizardView.oauth2Provider.click();
await $("ak-wizard-page-type-create").waitForDisplayed();
await $('div[data-ouid-component-name="oauth2provider"]').scrollIntoView();
await $('div[data-ouid-component-name="oauth2provider"]').click();
await ProviderWizardView.nextButton.click();
await ProviderWizardView.pause();
// @ts-expect-error "TSC does not understand ChainablePromiseElement"
await ProviderWizardView.oauth.providerName.setValue(newProviderName);
return await $('ak-form-element-horizontal[name="name"]').$("input");
await ProviderWizardView.oauth.setAuthorizationFlow(
"default-provider-authorization-explicit-consent",
);

View File

@ -1,3 +1,50 @@
import { browser } from "@wdio/globals";
const lemmeSee = process.env.WDIO_LEMME_SEE !== undefined;
const testSafari = process.env.WDIO_TEST_SAFARI !== undefined;
const testFirefox = process.env.WDIO_TEST_FIREFOX !== undefined;
const skipChrome = process.env.WDIO_SKIP_CHROME !== undefined;
const runHeadless = process.env.CI !== undefined;
const capabilities = [];
if (!skipChrome) {
capabilities.push({
"browserName": "chrome",
"wdio:chromedriverOptions": {
binary: "./node_modules/.bin/chromedriver",
},
"goog:chromeOptions": {
args: ["disable-infobars", "window-size=1280,800"].concat(
(function () {
return runHeadless
? [
"headless",
"no-sandbox",
"disable-gpu",
"disable-setuid-sandbox",
"disable-dev-shm-usage",
]
: [];
})(),
),
},
});
}
if (testSafari) {
capabilities.push({
browserName: "safari", // or "firefox", "microsoftedge", "safari"
});
}
if (testFirefox) {
capabilities.push({
browserName: "firefox", // or "firefox", "microsoftedge", "safari"
});
}
export const config: WebdriverIO.Config = {
//
// ====================
@ -50,30 +97,7 @@ export const config: WebdriverIO.Config = {
// Sauce Labs platform configurator - a great tool to configure your capabilities:
// https://saucelabs.com/platform/platform-configurator
//
capabilities: [
{
"browserName": "chrome",
"wdio:chromedriverOptions": {
binary: "./node_modules/.bin/chromedriver",
},
"goog:chromeOptions": {
args: ["--disable-infobars", "--window-size=1280,800"].concat(
(function () {
return process.env.HEADLESS_CHROME === "1"
? [
"--headless",
"--no-sandbox",
"--disable-gpu",
"--disable-setuid-sandbox",
"--disable-dev-shm-usage",
]
: [];
})(),
),
},
},
],
capabilities,
//
// ===================
// Test Configurations
@ -246,9 +270,13 @@ export const config: WebdriverIO.Config = {
* @param {boolean} result.passed true if test has passed, otherwise false
* @param {object} result.retries information about spec related retries, e.g. `{ attempts: 0, limit: 0 }`
*/
// afterTest: function(test, context, { error, result, duration, passed, retries }) {
// },
// Below is the full signature; we're not using any of them.
// afterTest: async function (test, context, { error, result, duration, passed, retries }) {
afterTest: async function () {
if (lemmeSee) {
await browser.pause(500);
}
},
/**
* Hook that gets executed after the suite has ended
* @param {object} suite suite details

View File

@ -1,9 +1,14 @@
import replace from "@rollup/plugin-replace";
import { browser } from "@wdio/globals";
import path from "path";
import { cwd } from "process";
import { fileURLToPath } from "url";
import type { UserConfig } from "vite";
import litCss from "vite-plugin-lit-css";
import tsconfigPaths from "vite-tsconfig-paths";
const __dirname = fileURLToPath(new URL(".", import.meta.url));
const isProdBuild = process.env.NODE_ENV === "production";
const apiBasePath = process.env.AK_API_BASE_PATH || "";
const runHeadless = process.env.CI !== undefined;
@ -11,6 +16,7 @@ const runHeadless = process.env.CI !== undefined;
const testSafari = process.env.WDIO_TEST_SAFARI !== undefined;
const testFirefox = process.env.WDIO_TEST_FIREFOX !== undefined;
const skipChrome = process.env.WDIO_SKIP_CHROME !== undefined;
const lemmeSee = process.env.WDIO_LEMME_SEE !== undefined;
const capabilities = [];
@ -80,6 +86,20 @@ export const config: WebdriverIO.Config = {
...(userConfig?.plugins ?? []),
tsconfigPaths(),
],
resolve: {
alias: {
"@goauthentik/admin": path.resolve(__dirname, "src/admin"),
"@goauthentik/common": path.resolve(__dirname, "src/common"),
"@goauthentik/components": path.resolve(__dirname, "src/components"),
"@goauthentik/docs": path.resolve(__dirname, "../website/docs"),
"@goauthentik/elements": path.resolve(__dirname, "src/elements"),
"@goauthentik/flow": path.resolve(__dirname, "src/flow"),
"@goauthentik/locales": path.resolve(__dirname, "src/locales"),
"@goauthentik/polyfill": path.resolve(__dirname, "src/polyfill"),
"@goauthentik/standalone": path.resolve(__dirname, "src/standalone"),
"@goauthentik/user": path.resolve(__dirname, "src/user"),
},
},
}),
},
],
@ -143,7 +163,7 @@ export const config: WebdriverIO.Config = {
// Define all options that are relevant for the WebdriverIO instance here
//
// Level of logging verbosity: trace | debug | info | warn | error | silent
logLevel: "info",
logLevel: "warn",
//
// Set specific log levels per logger
// loggers:
@ -309,8 +329,15 @@ export const config: WebdriverIO.Config = {
* @param {boolean} result.passed true if test has passed, otherwise false
* @param {object} result.retries information about spec related retries, e.g. `{ attempts: 0, limit: 0 }`
*/
// afterTest: function(test, context, { error, result, duration, passed, retries }) {
// },
afterTest: async function (
_test,
_context,
{ error: _error, result: _result, duration: _duration, passed: _passed, retries: _retries },
) {
if (lemmeSee) {
await browser.pause(500);
}
},
/**
* Hook that gets executed after the suite has ended