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:
		| @ -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>`); | ||||
|  | ||||
| @ -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 () => { | ||||
|  | ||||
| @ -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"; | ||||
|  | ||||
| @ -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"; | ||||
|  | ||||
| @ -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( | ||||
|  | ||||
| @ -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", () => { | ||||
|  | ||||
| @ -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"], | ||||
|  | ||||
| @ -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"; | ||||
|  | ||||
| @ -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"; | ||||
|  | ||||
							
								
								
									
										19
									
								
								web/src/elements/tests/utils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								web/src/elements/tests/utils.ts
									
									
									
									
									
										Normal 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); | ||||
| }; | ||||
| @ -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", | ||||
|         ); | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Ken Sternberg
					Ken Sternberg