+ Try again with a different filter
+ `,
+ );
+
+ const message = await $("ak-empty-state").$(">>>.pf-c-empty-state__body").$(">>>p");
+ await expect(message).toHaveText("Try again with a different filter");
+ });
+});
diff --git a/web/tsconfig.json b/web/tsconfig.json
index 887178d6d3..824799c71a 100644
--- a/web/tsconfig.json
+++ b/web/tsconfig.json
@@ -14,5 +14,6 @@
"@goauthentik/standalone/*": ["src/standalone/*"],
"@goauthentik/user/*": ["src/user/*"]
},
- }
+ },
+ "exclude": ["src/**/*.test.ts", "src/**/*.stories.ts", "src/**/tests", "src/**/stories"]
}
diff --git a/web/tsconfig.test.json b/web/tsconfig.test.json
new file mode 100644
index 0000000000..d2f4132590
--- /dev/null
+++ b/web/tsconfig.test.json
@@ -0,0 +1,35 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "types": ["node", "webdriverio/async", "@wdio/cucumber-framework", "expect-webdriverio"],
+ "target": "esnext",
+ "forceConsistentCasingInFileNames": true,
+ "experimentalDecorators": true,
+ "lib": [
+ "ES5",
+ "ES2015",
+ "ES2016",
+ "ES2017",
+ "ES2018",
+ "ES2019",
+ "ES2020",
+ "ESNext",
+ "DOM",
+ "DOM.Iterable",
+ "WebWorker"
+ ],
+ "paths": {
+ "@goauthentik/authentik/*": ["src/*"],
+ "@goauthentik/admin/*": ["src/admin/*"],
+ "@goauthentik/common/*": ["src/common/*"],
+ "@goauthentik/components/*": ["src/components/*"],
+ "@goauthentik/docs/*": ["../website/docs/*"],
+ "@goauthentik/elements/*": ["src/elements/*"],
+ "@goauthentik/flow/*": ["src/flow/*"],
+ "@goauthentik/locales/*": ["src/locales/*"],
+ "@goauthentik/polyfill/*": ["src/polyfill/*"],
+ "@goauthentik/standalone/*": ["src/standalone/*"],
+ "@goauthentik/user/*": ["src/user/*"]
+ }
+ }
+}
diff --git a/web/wdio.conf.ts b/web/wdio.conf.ts
new file mode 100644
index 0000000000..f1fd0c9f62
--- /dev/null
+++ b/web/wdio.conf.ts
@@ -0,0 +1,347 @@
+import replace from "@rollup/plugin-replace";
+import type { Options } from "@wdio/types";
+import { cwd } from "process";
+// @ts-ignore
+import * as modify from "rollup-plugin-modify";
+import * as postcssLit from "rollup-plugin-postcss-lit";
+import type { UserConfig } from "vite";
+import tsconfigPaths from "vite-tsconfig-paths";
+
+import { cssImportMaps } from "./.storybook/css-import-maps";
+
+const isProdBuild = process.env.NODE_ENV === "production";
+const apiBasePath = process.env.AK_API_BASE_PATH || "";
+const runHeadless = process.env.CI !== undefined;
+
+export const config: Options.Testrunner = {
+ //
+ // ====================
+ // Runner Configuration
+ // ====================
+ // WebdriverIO supports running e2e tests as well as unit and component tests.
+ runner: [
+ "browser",
+ {
+ viteConfig: (config: UserConfig = { plugins: [] }) => ({
+ ...config,
+ plugins: [
+ modify(cssImportMaps),
+ replace({
+ "process.env.NODE_ENV": JSON.stringify(
+ isProdBuild ? "production" : "development",
+ ),
+ "process.env.CWD": JSON.stringify(cwd()),
+ "process.env.AK_API_BASE_PATH": JSON.stringify(apiBasePath),
+ "preventAssignment": true,
+ }),
+ ...(config?.plugins ?? []),
+ // @ts-ignore
+ postcssLit(),
+ tsconfigPaths(),
+ ],
+ }),
+ },
+ ],
+
+ autoCompileOpts: {
+ autoCompile: true,
+ tsNodeOpts: {
+ project: "./tsconfig.json",
+ transpileOnly: true,
+ },
+ },
+
+ //
+ // ==================
+ // Specify Test Files
+ // ==================
+ // Define which test specs should run. The pattern is relative to the directory
+ // of the configuration file being run.
+ //
+ // The specs are defined as an array of spec files (optionally using wildcards
+ // that will be expanded). The test for each spec file will be run in a separate
+ // worker process. In order to have a group of spec files run in the same worker
+ // process simply enclose them in an array within the specs array.
+ //
+ // The path of the spec files will be resolved relative from the directory of
+ // of the config file unless it's absolute.
+ //
+ specs: ["./src/**/*.test.ts"],
+ // Patterns to exclude.
+ exclude: [
+ // 'path/to/excluded/files'
+ ],
+ //
+ // ============
+ // Capabilities
+ // ============
+ // Define your capabilities here. WebdriverIO can run multiple capabilities at the same
+ // time. Depending on the number of capabilities, WebdriverIO launches several test
+ // sessions. Within your capabilities you can overwrite the spec and exclude options in
+ // order to group specific specs to a specific capability.
+ //
+ // First, you can define how many instances should be started at the same time. Let's
+ // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have
+ // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec
+ // files and you set maxInstances to 10, all spec files will get tested at the same time
+ // and 30 processes will get spawned. The property handles how many capabilities
+ // from the same test should run tests.
+ //
+ maxInstances: 10,
+ //
+ // If you have trouble getting all important capabilities together, check out the
+ // Sauce Labs platform configurator - a great tool to configure your capabilities:
+ // https://saucelabs.com/platform/platform-configurator
+ //
+ capabilities: [
+ {
+ // capabilities for local browser web tests
+ browserName: "chrome", // or "firefox", "microsoftedge", "safari"
+ ...(runHeadless
+ ? {
+ "goog:chromeOptions": {
+ args: ["headless", "disable-gpu"],
+ },
+ }
+ : {}),
+ },
+ ],
+
+ //
+ // ===================
+ // Test Configurations
+ // ===================
+ // Define all options that are relevant for the WebdriverIO instance here
+ //
+ // Level of logging verbosity: trace | debug | info | warn | error | silent
+ logLevel: "info",
+ //
+ // Set specific log levels per logger
+ // loggers:
+ // - webdriver, webdriverio
+ // - @wdio/browserstack-service, @wdio/devtools-service, @wdio/sauce-service
+ // - @wdio/mocha-framework, @wdio/jasmine-framework
+ // - @wdio/local-runner
+ // - @wdio/sumologic-reporter
+ // - @wdio/cli, @wdio/config, @wdio/utils
+ // Level of logging verbosity: trace | debug | info | warn | error | silent
+ // logLevels: {
+ // webdriver: 'info',
+ // '@wdio/appium-service': 'info'
+ // },
+ //
+ // If you only want to run your tests until a specific amount of tests have failed use
+ // bail (default is 0 - don't bail, run all tests).
+ bail: 0,
+ //
+ // Set a base URL in order to shorten url command calls. If your `url` parameter starts
+ // with `/`, the base url gets prepended, not including the path portion of your baseUrl.
+ // If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url
+ // gets prepended directly.
+ // baseUrl: 'http://localhost:8080',
+ //
+ // Default timeout for all waitFor* commands.
+ waitforTimeout: 10000,
+ //
+ // Default timeout in milliseconds for request
+ // if browser driver or grid doesn't send response
+ connectionRetryTimeout: 120000,
+ //
+ // Default request retries count
+ connectionRetryCount: 3,
+ //
+ // Test runner services
+ // Services take over a specific job you don't want to take care of. They enhance
+ // your test setup with almost no effort. Unlike plugins, they don't add new
+ // commands. Instead, they hook themselves up into the test process.
+ // services: [],
+ //
+ // Framework you want to run your specs with.
+ // The following are supported: Mocha, Jasmine, and Cucumber
+ // see also: https://webdriver.io/docs/frameworks
+ //
+ // Make sure you have the wdio adapter package for the specific framework installed
+ // before running any tests.
+ framework: "mocha",
+
+ //
+ // The number of times to retry the entire specfile when it fails as a whole
+ // specFileRetries: 1,
+ //
+ // Delay in seconds between the spec file retry attempts
+ // specFileRetriesDelay: 0,
+ //
+ // Whether or not retried spec files should be retried immediately or deferred to the end of the queue
+ // specFileRetriesDeferred: false,
+ //
+ // Test reporter for stdout.
+ // The only one supported by default is 'dot'
+ // see also: https://webdriver.io/docs/dot-reporter
+ reporters: ["spec"],
+
+ // Options to be passed to Mocha.
+ // See the full list at http://mochajs.org/
+ mochaOpts: {
+ ui: "bdd",
+ timeout: 60000,
+ },
+
+ //
+ // =====
+ // Hooks
+ // =====
+ // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance
+ // it and to build services around it. You can either apply a single function or an array of
+ // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got
+ // resolved to continue.
+ /**
+ * Gets executed once before all workers get launched.
+ * @param {object} config wdio configuration object
+ * @param {Array.