web: unify unit and end-to-end tests (#11598)

* Just cleaning up.

* web: removing sonarjs from yet another branch.

* web: everything except the tests are up-to-date.  There was a lot, it turns out, we simply weren't using.

* web: update package.json to support WebdriverIO 9

This commit:

- Upgrades to WebdriverIO 9.1.2
- Resets our `devDependencies` collection to remove all imports that we either were not using or
  were duplicates of existing dependencies:
  - *Babel*, of all things
  - Storybook addon css user preferences, now native to Storybook 8
  - SonarJS, *again*, sigh.
  - React

- Fixes a bug where ESLint would report missing features in our build scripts
- Fixes a bug where Wdio might not reach a headless browser before timeout
- Replaces Rollup's CSSLit with Vite's CSSLit, which actually works without hacks, for testing.
- Moves the package-lock scanner to its own script, with better reporting and tool verification,
  which also cleans up the package.lock file a little.

* web: unify unit and end-to-end tests

This commit builds on the Upgrade to WebdriverIO 9.1 and provides *two* variants of the wdio.conf
file: One in `browser` mode, so that standalone component tests are uploaded to the browser and run
independently, and one in `local` mode that allows the Webdriver-DOM framework to run end-to-end
tests.  This means that both Component and End-to-End tests use the same drivers, same framework,
and same versions, and all tests for the WebUI are contained in this folder.

* Prettier just opinionatin' all over the place.

* Eslint bein' disagreeable.

* Tests embedded like ticks.

* Someday I'll get prettier to agree with my IDE.

* Re-ran the installation with resolutions enforced.

* web: fix type errors in tests

Typechecking the tests is pretty messy, first because WebdriverIO passes around a lot of `ChainablePromise` objects, which TSC does not know
how to resolve to their final form after a full `await`, and second because I used a lot of metaprogramming to provide getters for the
different kinds of subtypes (here: providers) that we are targeting.  So there are a lot of compromises here, none of which make me
spectacularly happy, but they're all well-commented, so there's that.

* But I am done with you, orc.

* Fixed broken comment.
This commit is contained in:
Ken Sternberg
2024-10-03 11:40:47 -07:00
committed by GitHub
parent dec8cfbb39
commit 22a77a7fc4
41 changed files with 283 additions and 16012 deletions

View File

@ -23,7 +23,6 @@ updates:
- package-ecosystem: npm - package-ecosystem: npm
directories: directories:
- "/web" - "/web"
- "/tests/wdio"
- "/web/sfe" - "/web/sfe"
schedule: schedule:
interval: daily interval: daily

View File

@ -24,17 +24,11 @@ jobs:
- prettier-check - prettier-check
project: project:
- web - web
- tests/wdio
include: include:
- command: tsc - command: tsc
project: web project: web
- command: lit-analyse - command: lit-analyse
project: web project: web
exclude:
- command: lint:lockfile
project: tests/wdio
- command: tsc
project: tests/wdio
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4

109
tests/wdio/.gitignore vendored
View File

@ -1,109 +0,0 @@
# Created by https://www.gitignore.io/api/node
# Edit at https://www.gitignore.io/?templates=node
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
dist
# Uncomment the public line if your project uses Gatsby
# https://nextjs.org/blog/next-9-1#public-directory-support
# https://create-react-app.dev/docs/using-the-public-folder/#docsNav
# public
# Storybook build outputs
.out
.storybook-out
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# Temporary folders
tmp/
temp/
# End of https://www.gitignore.io/api/node

View File

@ -1,7 +0,0 @@
# don't ever lint node_modules
node_modules
# don't lint nyc coverage output
coverage
# Prettier breaks the tsconfig file
tsconfig.json
.eslintrc.json

View File

@ -1,22 +0,0 @@
{
"arrowParens": "always",
"bracketSpacing": true,
"embeddedLanguageFormatting": "auto",
"htmlWhitespaceSensitivity": "css",
"insertPragma": false,
"jsxSingleQuote": false,
"printWidth": 100,
"proseWrap": "preserve",
"quoteProps": "consistent",
"requirePragma": false,
"semi": true,
"singleQuote": false,
"tabWidth": 4,
"trailingComma": "all",
"useTabs": false,
"vueIndentScriptAndStyle": false,
"plugins": ["@trivago/prettier-plugin-sort-imports"],
"importOrderSeparation": true,
"importOrderSortSpecifiers": true,
"importOrderParserPlugins": ["typescript", "classProperties", "decorators-legacy"]
}

View File

@ -1,41 +0,0 @@
.PHONY: help precommit admin-user test-good-login test-bad-login
help: ## Show this help
@echo "\nSpecify a command. The choices are:\n"
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[0;36m%-20s\033[m %s\n", $$1, $$2}'
@echo ""
ROOT := $(shell git rev-parse --show-toplevel 2> /dev/null)
WDIO = npm run wdio
SPEC = $(WDIO) -- --logLevel warn --spec ./test/specs
LOCAL_BLUEPRINTS=$(ROOT)/blueprints/local
node_modules: ## Runs `npm install` to prepare this feature
npm ci
precommit: node_modules ## Run the precommit: spell check all comments, eslint with sonarJS, prettier-write
npm run precommit
# Actual tests are down below:
$(ROOT)/blueprints/local/admin-user.yaml:
mkdir -p $(LOCAL_BLUEPRINTS)
cp ./blueprints/admin-user.yaml $(LOCAL_BLUEPRINTS)
cd $(ROOT) && ak apply_blueprint local/admin-user.yaml
admin-user: $(ROOT)/blueprints/local/admin-user.yaml
test-good-login: node_modules admin-user ## Test that we can log into the server. Requires a running instance of the server.
$(SPEC)/good-login.ts
test-bad-login: node_modules admin-user ## Test that bad usernames and passwords create appropriate error messages
$(SPEC)/bad-logins.ts
test-application-wizard: node_modules admin-user ## Test that the application wizard works as expected
$(SPEC)/new-application-by-wizard.ts

View File

@ -1,16 +0,0 @@
version: 1
entries:
- attrs:
email: test-admin@goauthentik.io
is_active: true
name: authentik Default Admin
password: test-runner
path: users
type: internal
groups:
- !Find [authentik_core.group, [name, "authentik Admins"]]
conditions: []
identifiers:
username: akadmin
model: authentik_core.user
state: present

View File

@ -1,84 +0,0 @@
import eslint from "@eslint/js";
import tsparser from "@typescript-eslint/parser";
import litconf from "eslint-plugin-lit";
import wcconf from "eslint-plugin-wc";
import globals from "globals";
import tseslint from "typescript-eslint";
export default [
// You would not believe how much this change has frustrated users: ["if an ignores key is used
// without any other keys in the configuration object, then the patterns act as global
// ignores"](https://eslint.org/docs/latest/use/configure/ignore)
{
ignores: [
"dist/",
// don't lint the cache
".wireit/",
// let packages have their own configurations
"packages/",
// don't ever lint node_modules
"node_modules/",
".storybook/*",
// don't lint build output (make sure it's set to your correct build folder name)
// don't lint nyc coverage output
"coverage/",
"src/locale-codes.ts",
"storybook-static/",
"src/locales/",
],
},
eslint.configs.recommended,
wcconf.configs["flat/recommended"],
litconf.configs["flat/recommended"],
...tseslint.configs.recommended,
{
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 12,
sourceType: "module",
},
},
files: ["src/**"],
rules: {
"no-unused-vars": "off",
"no-console": ["error", { allow: ["debug", "warn", "error"] }],
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
},
},
{
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 12,
sourceType: "module",
},
globals: {
...globals.nodeBuiltin,
},
},
files: ["scripts/*.mjs", "*.ts", "*.mjs"],
rules: {
"no-unused-vars": "off",
// We WANT our scripts to output to the console!
"no-console": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
},
},
];

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +0,0 @@
{
"name": "@goauthentik/web-tests",
"dependencies": {
"chromedriver": "^129.0.2",
"lockfile-lint": "^4.14.0",
"syncpack": "^13.0.0"
},
"devDependencies": {
"@eslint/js": "^9.11.1",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/mocha": "^10.0.8",
"@typescript-eslint/eslint-plugin": "^8.8.0",
"@typescript-eslint/parser": "^8.8.0",
"@wdio/cli": "^9.1.2",
"@wdio/local-runner": "^9.1.2",
"@wdio/mocha-framework": "^9.1.2",
"@wdio/spec-reporter": "^9.1.2",
"eslint-plugin-lit": "^1.14.0",
"eslint-plugin-sonarjs": "^2.0.3",
"eslint-plugin-wc": "^2.1.0",
"eslint": "^9.11.1",
"npm-run-all": "^4.1.5",
"prettier": "^3.3.3",
"typescript-eslint": "^8.8.0",
"typescript": "^5.6.2",
"wdio-wait-for": "^3.0.11"
},
"engines": {
"node": ">=20"
},
"private": true,
"scripts": {
"lint": "eslint . --max-warnings 0 --fix",
"lint:lockfile": "lockfile-lint --path package.json --type npm --allowed-hosts npm --validate-https",
"lint:package": "syncpack format -i ' '",
"lint:precommit": "eslint --max-warnings 0 --config ./.eslintrc.precommit.json $(git status --porcelain . | grep '^[AM?][M?]' | cut -d'/' -f3- | grep -E '\\.(ts|js|tsx|jsx)$')",
"lint:spelling": "codespell -D - -D $(git rev-parse --show-toplevel 2> /dev/null)/.github/codespell-dictionary.txt -I $(git rev-parse --show-toplevel 2> /dev/null)/.github/codespell-words.txt ./test -s",
"precommit": "run-s lint:precommit lint:spelling prettier",
"prettier": "prettier --write .",
"prettier-check": "prettier --check .",
"wdio": "wdio run ./wdio.conf.ts"
},
"type": "module"
}

254
web/package-lock.json generated
View File

@ -75,11 +75,13 @@
"@types/mocha": "^10.0.8", "@types/mocha": "^10.0.8",
"@types/node": "^22.7.4", "@types/node": "^22.7.4",
"@types/showdown": "^2.0.6", "@types/showdown": "^2.0.6",
"@typescript-eslint/eslint-plugin": "^8.8.0",
"@typescript-eslint/parser": "^8.8.0", "@typescript-eslint/parser": "^8.8.0",
"@wdio/browser-runner": "^9.1.2", "@wdio/browser-runner": "^9.1.2",
"@wdio/cli": "^9.1.2", "@wdio/cli": "^9.1.2",
"@wdio/spec-reporter": "^9.1.2", "@wdio/spec-reporter": "^9.1.2",
"chokidar": "^4.0.1", "chokidar": "^4.0.1",
"chromedriver": "^129.0.2",
"esbuild": "^0.24.0", "esbuild": "^0.24.0",
"eslint": "^9.11.1", "eslint": "^9.11.1",
"eslint-plugin-lit": "^1.15.0", "eslint-plugin-lit": "^1.15.0",
@ -3459,102 +3461,102 @@
"dev": true "dev": true
}, },
"node_modules/@sentry-internal/browser-utils": { "node_modules/@sentry-internal/browser-utils": {
"version": "8.33.0", "version": "8.33.1",
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.33.0.tgz", "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.33.1.tgz",
"integrity": "sha512-zwjmD+XI3pgxxiqKGLXYDGSd+zfO7az9zzbLn1le8Vv9cRL2lZyMLcwiwEaTpwz3B0pPONeDZMT8+bzMGRs8zw==", "integrity": "sha512-TW6/r+Gl5jiXv54iK1xZ3mlVgTS/jaBp4vcQ0xGMdgiQ3WchEPcFSeYovL+YHT3tSud0GZqVtDQCz+5i76puqA==",
"dependencies": { "dependencies": {
"@sentry/core": "8.33.0", "@sentry/core": "8.33.1",
"@sentry/types": "8.33.0", "@sentry/types": "8.33.1",
"@sentry/utils": "8.33.0" "@sentry/utils": "8.33.1"
}, },
"engines": { "engines": {
"node": ">=14.18" "node": ">=14.18"
} }
}, },
"node_modules/@sentry-internal/feedback": { "node_modules/@sentry-internal/feedback": {
"version": "8.33.0", "version": "8.33.1",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.33.0.tgz", "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.33.1.tgz",
"integrity": "sha512-KSW/aiNgmJc8PDl2NsM+ONvGure4tPaluj7O1Nw+947Dh8W6CJnQ9srB7xPyoYYWyQW8Hyl1vzxY9W0J+fjlhA==", "integrity": "sha512-qauMRTm3qDaLqZ3ibI03cj4gLF40y0ij65nj+cns6iWxGCtPrO8tjvXFWuQsE7Aye9dGMnBgmv7uN+NTUtC3RA==",
"dependencies": { "dependencies": {
"@sentry/core": "8.33.0", "@sentry/core": "8.33.1",
"@sentry/types": "8.33.0", "@sentry/types": "8.33.1",
"@sentry/utils": "8.33.0" "@sentry/utils": "8.33.1"
}, },
"engines": { "engines": {
"node": ">=14.18" "node": ">=14.18"
} }
}, },
"node_modules/@sentry-internal/replay": { "node_modules/@sentry-internal/replay": {
"version": "8.33.0", "version": "8.33.1",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.33.0.tgz", "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.33.1.tgz",
"integrity": "sha512-GFBaDA4yhlEf3wTXOVXnJVG/diuKxeqZuXcuhsAwJb+YcFR0NhgsRn3wIGuYOZZF8GBXzx9PFnb9yIuFgx5Nbw==", "integrity": "sha512-fm4coIOjmanU29NOVN9MyaP4fUCOYytbtFqVSKRFNZQ/xAgNeySiBIbUd6IjujMmnOk9bY0WEUMcdm3Uotjdog==",
"dependencies": { "dependencies": {
"@sentry-internal/browser-utils": "8.33.0", "@sentry-internal/browser-utils": "8.33.1",
"@sentry/core": "8.33.0", "@sentry/core": "8.33.1",
"@sentry/types": "8.33.0", "@sentry/types": "8.33.1",
"@sentry/utils": "8.33.0" "@sentry/utils": "8.33.1"
}, },
"engines": { "engines": {
"node": ">=14.18" "node": ">=14.18"
} }
}, },
"node_modules/@sentry-internal/replay-canvas": { "node_modules/@sentry-internal/replay-canvas": {
"version": "8.33.0", "version": "8.33.1",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.33.0.tgz", "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.33.1.tgz",
"integrity": "sha512-9fEhMP+gQYQrtn/SQd1Vd7U7emTSGBpLKc5h5f0iV0yDmjYAhNVbq4RgPTYAgnBEcdVo3qgboL6UIz9Dv+dYRQ==", "integrity": "sha512-nsxTFTPCT10Ty/v6+AiST3+yotGP1sUb8xqfKB9fPnS1hZHFryp0NnEls7xFjBsBbZPU1GpFkzrk/E6JFzixDQ==",
"dependencies": { "dependencies": {
"@sentry-internal/replay": "8.33.0", "@sentry-internal/replay": "8.33.1",
"@sentry/core": "8.33.0", "@sentry/core": "8.33.1",
"@sentry/types": "8.33.0", "@sentry/types": "8.33.1",
"@sentry/utils": "8.33.0" "@sentry/utils": "8.33.1"
}, },
"engines": { "engines": {
"node": ">=14.18" "node": ">=14.18"
} }
}, },
"node_modules/@sentry/browser": { "node_modules/@sentry/browser": {
"version": "8.33.0", "version": "8.33.1",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.33.0.tgz", "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.33.1.tgz",
"integrity": "sha512-qu/g20ZskywEU8BWc4Fts1kXFFBtw1vS+XvPq7Ta9zCeRG5dlXhhYDVQ4/v4nAL/cs0o6aLCq73m109CFF0Kig==", "integrity": "sha512-c6zI/igexkLwZuGk+u8Rj26ChjxGgkhe6ZbKFsXCYaKAp5ep5X7HQRkkqgbxApiqlC0LduHdd/ymzh139JLg8w==",
"dependencies": { "dependencies": {
"@sentry-internal/browser-utils": "8.33.0", "@sentry-internal/browser-utils": "8.33.1",
"@sentry-internal/feedback": "8.33.0", "@sentry-internal/feedback": "8.33.1",
"@sentry-internal/replay": "8.33.0", "@sentry-internal/replay": "8.33.1",
"@sentry-internal/replay-canvas": "8.33.0", "@sentry-internal/replay-canvas": "8.33.1",
"@sentry/core": "8.33.0", "@sentry/core": "8.33.1",
"@sentry/types": "8.33.0", "@sentry/types": "8.33.1",
"@sentry/utils": "8.33.0" "@sentry/utils": "8.33.1"
}, },
"engines": { "engines": {
"node": ">=14.18" "node": ">=14.18"
} }
}, },
"node_modules/@sentry/core": { "node_modules/@sentry/core": {
"version": "8.33.0", "version": "8.33.1",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.33.0.tgz", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.33.1.tgz",
"integrity": "sha512-618PQGHQLBVCpAq1s+e/rpIUaLUnj19IPUgn97rUGXLLna8ETIAoyQoG70wz4q9niw4Z4GlS5kZNrael2O3+2w==", "integrity": "sha512-3SS41suXLFzxL3OQvTMZ6q92ZapELVq2l2SoWlZopcamWhog2Ru0dp2vkunq97kFHb2TzKRTlFH4+4gbT8SJug==",
"dependencies": { "dependencies": {
"@sentry/types": "8.33.0", "@sentry/types": "8.33.1",
"@sentry/utils": "8.33.0" "@sentry/utils": "8.33.1"
}, },
"engines": { "engines": {
"node": ">=14.18" "node": ">=14.18"
} }
}, },
"node_modules/@sentry/types": { "node_modules/@sentry/types": {
"version": "8.33.0", "version": "8.33.1",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.33.0.tgz", "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.33.1.tgz",
"integrity": "sha512-V/A+72ZdnfGtXeXIpz1kUo3LRdq3WKEYYFUR2RKpCdPh9yeOrHq6u/rmzTWx49+om0yhZN+JhVoxDzt75UoFRg==", "integrity": "sha512-GjoAMvwtpIemoF/IiwZ7A60g4nQv3qwzR21GvJqDVUoKD0e8pv9OLX+HyXoUat4wEDGSuDUcUyUKD2G+od73QA==",
"engines": { "engines": {
"node": ">=14.18" "node": ">=14.18"
} }
}, },
"node_modules/@sentry/utils": { "node_modules/@sentry/utils": {
"version": "8.33.0", "version": "8.33.1",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.33.0.tgz", "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.33.1.tgz",
"integrity": "sha512-TdwtGdevJij2wq2x/hDUr+x5TXt47ZhWxZ8zluai/lnIDTUB3Xs/L9yHtj1J+H9hr8obkMASE9IanUrWXzrP6Q==", "integrity": "sha512-uzuYpiiJuFY3N4WNHMBWUQX5oNv2t/TbG0OHRp3Rr7yeu+HSfD542TIp9/gMZ+G0Cxd8AmVO3wkKIFbk0TL4Qg==",
"dependencies": { "dependencies": {
"@sentry/types": "8.33.0" "@sentry/types": "8.33.1"
}, },
"engines": { "engines": {
"node": ">=14.18" "node": ">=14.18"
@ -5446,6 +5448,12 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/@testim/chrome-version": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz",
"integrity": "sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g==",
"dev": true
},
"node_modules/@tokenizer/token": { "node_modules/@tokenizer/token": {
"version": "0.3.0", "version": "0.3.0",
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
@ -5774,9 +5782,9 @@
} }
}, },
"node_modules/@types/lodash": { "node_modules/@types/lodash": {
"version": "4.17.9", "version": "4.17.10",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.9.tgz", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w==", "integrity": "sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==",
"dev": true "dev": true
}, },
"node_modules/@types/mdx": { "node_modules/@types/mdx": {
@ -8611,6 +8619,28 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/chromedriver": {
"version": "129.0.2",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-129.0.2.tgz",
"integrity": "sha512-rUEFCJAmAwOdFfaDFtveT97fFeA7NOxlkgyPyN+G09Ws4qGW39aLDxMQBbS9cxQQHhTihqZZobgF5CLVYXnmGA==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
"@testim/chrome-version": "^1.1.4",
"axios": "^1.7.4",
"compare-versions": "^6.1.0",
"extract-zip": "^2.0.1",
"proxy-agent": "^6.4.0",
"proxy-from-env": "^1.1.0",
"tcp-port-used": "^1.0.2"
},
"bin": {
"chromedriver": "bin/chromedriver"
},
"engines": {
"node": ">=18"
}
},
"node_modules/ci-info": { "node_modules/ci-info": {
"version": "3.9.0", "version": "3.9.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
@ -8854,6 +8884,12 @@
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
"dev": true "dev": true
}, },
"node_modules/compare-versions": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz",
"integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==",
"dev": true
},
"node_modules/compatx": { "node_modules/compatx": {
"version": "0.1.8", "version": "0.1.8",
"resolved": "https://registry.npmjs.org/compatx/-/compatx-0.1.8.tgz", "resolved": "https://registry.npmjs.org/compatx/-/compatx-0.1.8.tgz",
@ -9995,9 +10031,9 @@
} }
}, },
"node_modules/dompurify": { "node_modules/dompurify": {
"version": "3.1.7", "version": "3.1.6",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.6.tgz",
"integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==" "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ=="
}, },
"node_modules/domutils": { "node_modules/domutils": {
"version": "3.1.0", "version": "3.1.0",
@ -12936,6 +12972,15 @@
"node": ">= 12" "node": ">= 12"
} }
}, },
"node_modules/ip-regex": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz",
"integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/ipaddr.js": { "node_modules/ipaddr.js": {
"version": "1.9.1", "version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@ -13374,6 +13419,12 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/is-url": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
"integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==",
"dev": true
},
"node_modules/is-valid-element-name": { "node_modules/is-valid-element-name": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-valid-element-name/-/is-valid-element-name-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-valid-element-name/-/is-valid-element-name-1.0.0.tgz",
@ -13407,6 +13458,20 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/is2": {
"version": "2.0.9",
"resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz",
"integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==",
"dev": true,
"dependencies": {
"deep-is": "^0.1.3",
"ip-regex": "^4.1.0",
"is-url": "^1.2.4"
},
"engines": {
"node": ">=v0.10.0"
}
},
"node_modules/isarray": { "node_modules/isarray": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
@ -13947,6 +14012,7 @@
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
"integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
"dev": true, "dev": true,
"optional": true,
"bin": { "bin": {
"jiti": "bin/jiti.js" "jiti": "bin/jiti.js"
} }
@ -14179,9 +14245,9 @@
} }
}, },
"node_modules/knip": { "node_modules/knip": {
"version": "5.30.6", "version": "5.31.0",
"resolved": "https://registry.npmjs.org/knip/-/knip-5.30.6.tgz", "resolved": "https://registry.npmjs.org/knip/-/knip-5.31.0.tgz",
"integrity": "sha512-YkcnRVl0N99xZ7eaXE7KlH/4cPTCn6BGuk9KxINEdCMFN3yita2vGBizApy97ZOHgghy8tb589gQ3xvLMFIO4w==", "integrity": "sha512-4hR+qHx/id7mniCWWUqA4MXwGjYFN75xv3qLmEkl9Hm6eCKAhv0wGP0CyrXKUYxVyDplJQsqQaAlsjuRKYsdPA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -14203,7 +14269,7 @@
"easy-table": "1.2.0", "easy-table": "1.2.0",
"enhanced-resolve": "^5.17.1", "enhanced-resolve": "^5.17.1",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"jiti": "^1.21.6", "jiti": "^2.1.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"minimist": "^1.2.8", "minimist": "^1.2.8",
"picocolors": "^1.0.0", "picocolors": "^1.0.0",
@ -14227,6 +14293,15 @@
"typescript": ">=5.0.4" "typescript": ">=5.0.4"
} }
}, },
"node_modules/knip/node_modules/jiti": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.1.2.tgz",
"integrity": "sha512-cYNjJus5X9J4jLzTaI8rYoIq1k6YySiA1lK4wxSnOrBRXkbVyreZfhoboJhsUmwgU82lpPjj1IoU7Ggrau8r3g==",
"dev": true,
"bin": {
"jiti": "lib/jiti-cli.mjs"
}
},
"node_modules/knip/node_modules/strip-json-comments": { "node_modules/knip/node_modules/strip-json-comments": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.1.tgz",
@ -14870,9 +14945,9 @@
} }
}, },
"node_modules/mermaid": { "node_modules/mermaid": {
"version": "11.2.1", "version": "11.3.0",
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.2.1.tgz", "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.3.0.tgz",
"integrity": "sha512-F8TEaLVVyxTUmvKswVFyOkjPrlJA5h5vNR1f7ZnSWSpqxgEZG1hggtn/QCa7znC28bhlcrNh10qYaIiill7q4A==", "integrity": "sha512-fFmf2gRXLtlGzug4wpIGN+rQdZ30M8IZEB1D3eZkXNqC7puhqeURBcD/9tbwXsqBO+A6Nzzo3MSSepmnw5xSeg==",
"dependencies": { "dependencies": {
"@braintree/sanitize-url": "^7.0.1", "@braintree/sanitize-url": "^7.0.1",
"@iconify/utils": "^2.1.32", "@iconify/utils": "^2.1.32",
@ -14884,7 +14959,7 @@
"d3-sankey": "^0.12.3", "d3-sankey": "^0.12.3",
"dagre-d3-es": "7.0.10", "dagre-d3-es": "7.0.10",
"dayjs": "^1.11.10", "dayjs": "^1.11.10",
"dompurify": "^3.0.11", "dompurify": "^3.0.11 <3.1.7",
"katex": "^0.16.9", "katex": "^0.16.9",
"khroma": "^2.1.0", "khroma": "^2.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
@ -17775,9 +17850,9 @@
} }
}, },
"node_modules/readdirp": { "node_modules/readdirp": {
"version": "4.0.1", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
"integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==", "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 14.16.0" "node": ">= 14.16.0"
@ -17864,15 +17939,15 @@
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
}, },
"node_modules/regexp.prototype.flags": { "node_modules/regexp.prototype.flags": {
"version": "1.5.2", "version": "1.5.3",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz",
"integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.6", "call-bind": "^1.0.7",
"define-properties": "^1.2.1", "define-properties": "^1.2.1",
"es-errors": "^1.3.0", "es-errors": "^1.3.0",
"set-function-name": "^2.0.1" "set-function-name": "^2.0.2"
}, },
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@ -19558,6 +19633,39 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/tcp-port-used": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz",
"integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==",
"dev": true,
"dependencies": {
"debug": "4.3.1",
"is2": "^2.0.6"
}
},
"node_modules/tcp-port-used/node_modules/debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/tcp-port-used/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"node_modules/telejson": { "node_modules/telejson": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz",
@ -20778,9 +20886,9 @@
} }
}, },
"node_modules/untyped/node_modules/jiti": { "node_modules/untyped/node_modules/jiti": {
"version": "2.1.0", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.1.0.tgz", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.1.2.tgz",
"integrity": "sha512-Nftp80J8poC3u+93ZxpjstsgfQ5d0o5qyD6yStv32sgnWr74xRxBppEwsUoA/GIdrJpgGRkC1930YkLcAsFdSw==", "integrity": "sha512-cYNjJus5X9J4jLzTaI8rYoIq1k6YySiA1lK4wxSnOrBRXkbVyreZfhoboJhsUmwgU82lpPjj1IoU7Ggrau8r3g==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"bin": { "bin": {

View File

@ -63,11 +63,13 @@
"@types/mocha": "^10.0.8", "@types/mocha": "^10.0.8",
"@types/node": "^22.7.4", "@types/node": "^22.7.4",
"@types/showdown": "^2.0.6", "@types/showdown": "^2.0.6",
"@typescript-eslint/eslint-plugin": "^8.8.0",
"@typescript-eslint/parser": "^8.8.0", "@typescript-eslint/parser": "^8.8.0",
"@wdio/browser-runner": "^9.1.2", "@wdio/browser-runner": "^9.1.2",
"@wdio/cli": "^9.1.2", "@wdio/cli": "^9.1.2",
"@wdio/spec-reporter": "^9.1.2", "@wdio/spec-reporter": "^9.1.2",
"chokidar": "^4.0.1", "chokidar": "^4.0.1",
"chromedriver": "^129.0.2",
"esbuild": "^0.24.0", "esbuild": "^0.24.0",
"eslint": "^9.11.1", "eslint": "^9.11.1",
"eslint-plugin-lit": "^1.15.0", "eslint-plugin-lit": "^1.15.0",
@ -130,7 +132,8 @@
"storybook:build": "wireit", "storybook:build": "wireit",
"storybook:build-import-map": "wireit", "storybook:build-import-map": "wireit",
"test": "wireit", "test": "wireit",
"test-watch": "wireit", "test:e2e:watch": "wireit",
"test:watch": "wireit",
"tsc": "wireit", "tsc": "wireit",
"watch": "run-s build-locales esbuild:watch" "watch": "run-s build-locales esbuild:watch"
}, },
@ -233,10 +236,14 @@
"lint:imports": { "lint:imports": {
"command": "knip --config scripts/knip.config.ts" "command": "knip --config scripts/knip.config.ts"
}, },
"lint:types:tests": {
"command": "tsc --noEmit -p ./tests"
},
"lint:types": { "lint:types": {
"command": "tsc --noEmit -p .", "command": "tsc --noEmit -p .",
"dependencies": [ "dependencies": [
"build-locales" "build-locales",
"lint:types:tests"
] ]
}, },
"lint:lockfile": { "lint:lockfile": {
@ -315,7 +322,13 @@
"TS_NODE_PROJECT": "tsconfig.test.json" "TS_NODE_PROJECT": "tsconfig.test.json"
} }
}, },
"test-watch": { "test:e2e:watch": {
"command": "wdio run ./tests/wdio.conf.ts",
"env": {
"TS_NODE_PROJECT": "./tests/tsconfig.test.json"
}
},
"test:watch": {
"command": "wdio run ./wdio.conf.ts", "command": "wdio run ./wdio.conf.ts",
"env": { "env": {
"TS_NODE_PROJECT": "tsconfig.test.json" "TS_NODE_PROJECT": "tsconfig.test.json"

View File

@ -1,3 +1,5 @@
import { $ } from "@wdio/globals";
import Page from "../pageobjects/page.js"; import Page from "../pageobjects/page.js";
export default class AdminPage extends Page { export default class AdminPage extends Page {

View File

@ -1,3 +1,5 @@
import { $ } from "@wdio/globals";
import AdminPage from "./admin.page.js"; import AdminPage from "./admin.page.js";
import ApplicationForm from "./forms/application.form.js"; import ApplicationForm from "./forms/application.form.js";
import ForwardProxyForm from "./forms/forward-proxy.form.js"; import ForwardProxyForm from "./forms/forward-proxy.form.js";
@ -7,7 +9,6 @@ import RadiusForm from "./forms/radius.form.js";
import SamlForm from "./forms/saml.form.js"; import SamlForm from "./forms/saml.form.js";
import ScimForm from "./forms/scim.form.js"; import ScimForm from "./forms/scim.form.js";
import TransparentProxyForm from "./forms/transparent-proxy.form.js"; import TransparentProxyForm from "./forms/transparent-proxy.form.js";
import { $ } from "@wdio/globals";
/** /**
* sub page containing specific selectors and methods for a specific page * sub page containing specific selectors and methods for a specific page
@ -40,6 +41,7 @@ class ApplicationWizardView extends AdminPage {
} }
async getProviderType(type: string) { async getProviderType(type: string) {
// @ts-expect-error "TSC does not understand the ChainablePromiseElement type at all."
return await this.providerList().$(`input[value="${type}"]`); return await this.providerList().$(`input[value="${type}"]`);
} }

View File

@ -1,6 +1,7 @@
import AdminPage from "./admin.page.js";
import { $ } from "@wdio/globals"; import { $ } from "@wdio/globals";
import AdminPage from "./admin.page.js";
/** /**
* sub page containing specific selectors and methods for a specific page * sub page containing specific selectors and methods for a specific page
*/ */

View File

@ -1,6 +1,7 @@
import Page from "../page.js";
import { $ } from "@wdio/globals"; import { $ } from "@wdio/globals";
import Page from "../page.js";
export class ApplicationForm extends Page { export class ApplicationForm extends Page {
async name() { async name() {
return await $('ak-text-input[name="name"]').$("input"); return await $('ak-text-input[name="name"]').$("input");

View File

@ -1,6 +1,7 @@
import Page from "../page.js";
import { $ } from "@wdio/globals"; import { $ } from "@wdio/globals";
import Page from "../page.js";
export class ForwardProxyForm extends Page { export class ForwardProxyForm extends Page {
async setAuthorizationFlow(selector: string) { async setAuthorizationFlow(selector: string) {
await this.searchSelect( await this.searchSelect(

View File

@ -1,6 +1,7 @@
import Page from "../page.js";
import { $ } from "@wdio/globals"; import { $ } from "@wdio/globals";
import Page from "../page.js";
export class OauthForm extends Page { export class OauthForm extends Page {
async setAuthorizationFlow(selector: string) { async setAuthorizationFlow(selector: string) {
await this.searchSelect( await this.searchSelect(

View File

@ -1,6 +1,7 @@
import Page from "../page.js";
import { $ } from "@wdio/globals"; import { $ } from "@wdio/globals";
import Page from "../page.js";
export class SamlForm extends Page { export class SamlForm extends Page {
async setAuthorizationFlow(selector: string) { async setAuthorizationFlow(selector: string) {
await this.searchSelect( await this.searchSelect(

View File

@ -1,6 +1,7 @@
import Page from "../page.js";
import { $ } from "@wdio/globals"; import { $ } from "@wdio/globals";
import Page from "../page.js";
export class TransparentProxyForm extends Page { export class TransparentProxyForm extends Page {
async setAuthorizationFlow(selector: string) { async setAuthorizationFlow(selector: string) {
await this.searchSelect( await this.searchSelect(

View File

@ -1,6 +1,7 @@
import { $ } from "@wdio/globals";
import Page from "./page.js"; import Page from "./page.js";
import UserLibraryPage from "./user-library.page.js"; import UserLibraryPage from "./user-library.page.js";
import { $ } from "@wdio/globals";
/** /**
* sub page containing specific selectors and methods for a specific page * sub page containing specific selectors and methods for a specific page
@ -13,12 +14,16 @@ class LoginPage extends Page {
return await $('input[name="uidField"]'); return await $('input[name="uidField"]');
} }
async inputPassword() { async usernameBtnSubmit() {
return await $('input[name="password"]'); return await $('button[type="submit"]');
} }
async btnSubmit() { async inputPassword() {
return await $('button[type="submit"]'); return await $("input#ak-stage-password-input");
}
async passwordBtnSubmit() {
return await $("ak-stage-password").$('button[type="submit"]');
} }
async authFailure() { async authFailure() {
@ -31,14 +36,16 @@ class LoginPage extends Page {
async username(username: string) { async username(username: string) {
await (await this.inputUsername()).setValue(username); await (await this.inputUsername()).setValue(username);
await (await this.btnSubmit()).waitForEnabled(); const submitBtn = await this.usernameBtnSubmit();
await (await this.btnSubmit()).click(); await submitBtn.waitForEnabled();
await submitBtn.click();
} }
async password(password: string) { async password(password: string) {
await (await this.inputPassword()).setValue(password); await (await this.inputPassword()).setValue(password);
await (await this.btnSubmit()).waitForEnabled(); const submitBtn = await this.passwordBtnSubmit();
await (await this.btnSubmit()).click(); await submitBtn.waitForEnabled();
await submitBtn.click();
} }
async login(username: string, password: string) { async login(username: string, password: string) {

View File

@ -40,12 +40,17 @@ export default class Page {
await $(`div[data-managed-for="${managedSelector}"]`).$("ak-list-select") await $(`div[data-managed-for="${managedSelector}"]`).$("ak-list-select")
).shadow$$("button"); ).shadow$$("button");
let target: WebdriverIO.Element; let target: WebdriverIO.Element;
// @ts-expect-error "Types break on shadow$$"
for (const button of searchBlock) { for (const button of searchBlock) {
if ((await button.getText()).includes(buttonSelector)) { if ((await button.getText()).includes(buttonSelector)) {
target = button; target = button;
break; break;
} }
} }
// @ts-expect-error "TSC cannot tell if the `for` loop actually performs the assignment."
if (!target) {
throw new Error(`Expected to find an entry matching the spec ${buttonSelector}`);
}
await (await target).click(); await (await target).click();
await browser.keys(Key.Tab); await browser.keys(Key.Tab);
} }

View File

@ -1,6 +1,7 @@
import { $ } from "@wdio/globals";
import AdminPage from "./admin.page.js"; import AdminPage from "./admin.page.js";
import OauthForm from "./forms/oauth.form.js"; import OauthForm from "./forms/oauth.form.js";
import { $ } from "@wdio/globals";
/** /**
* sub page containing specific selectors and methods for a specific page * sub page containing specific selectors and methods for a specific page

View File

@ -1,7 +1,8 @@
import AdminPage from "./admin.page.js";
import { $, browser } from "@wdio/globals"; import { $, browser } from "@wdio/globals";
import { Key } from "webdriverio"; import { Key } from "webdriverio";
import AdminPage from "./admin.page.js";
/** /**
* sub page containing specific selectors and methods for a specific page * sub page containing specific selectors and methods for a specific page
*/ */

View File

@ -1,6 +1,7 @@
import Page from "./page.js";
import { $ } from "@wdio/globals"; import { $ } from "@wdio/globals";
import Page from "./page.js";
/** /**
* sub page containing specific selectors and methods for a specific page * sub page containing specific selectors and methods for a specific page
*/ */

View File

@ -1,6 +1,7 @@
import { expect } from "@wdio/globals";
import LoginPage from "../pageobjects/login.page.js"; import LoginPage from "../pageobjects/login.page.js";
import { BAD_PASSWORD, GOOD_USERNAME } from "../utils/constants.js"; import { BAD_PASSWORD, GOOD_USERNAME } from "../utils/constants.js";
import { expect } from "@wdio/globals";
describe("Log into authentik", () => { describe("Log into authentik", () => {
it("should fail on a bad password", async () => { it("should fail on a bad password", async () => {

View File

@ -1,6 +1,7 @@
import { expect } from "@wdio/globals";
import LoginPage from "../pageobjects/login.page.js"; import LoginPage from "../pageobjects/login.page.js";
import { BAD_USERNAME, GOOD_PASSWORD } from "../utils/constants.js"; import { BAD_USERNAME, GOOD_PASSWORD } from "../utils/constants.js";
import { expect } from "@wdio/globals";
describe("Log into authentik", () => { describe("Log into authentik", () => {
it("should fail on a bad username", async () => { it("should fail on a bad username", async () => {

View File

@ -1,8 +1,14 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
// ^^^^^^^^^^^ Because TSC cannot handle metaprogramming, and metaprogramming
// via `defineProperties` is how we installed the OUID finders for the various
// wizard types.
import { expect } from "@wdio/globals";
import ApplicationWizardView from "../pageobjects/application-wizard.page.js"; import ApplicationWizardView from "../pageobjects/application-wizard.page.js";
import ApplicationsListPage from "../pageobjects/applications-list.page.js"; import ApplicationsListPage from "../pageobjects/applications-list.page.js";
import { randomId } from "../utils/index.js"; import { randomId } from "../utils/index.js";
import { login } from "../utils/login.js"; import { login } from "../utils/login.js";
import { expect } from "@wdio/globals";
async function reachTheProvider(title: string) { async function reachTheProvider(title: string) {
const newPrefix = randomId(); const newPrefix = randomId();
@ -43,7 +49,6 @@ describe("Configure Applications with the Application Wizard", () => {
await (await ApplicationWizardView.providerList()).waitForDisplayed(); await (await ApplicationWizardView.providerList()).waitForDisplayed();
await (await ApplicationWizardView.ldapProvider).scrollIntoView(); await (await ApplicationWizardView.ldapProvider).scrollIntoView();
await (await ApplicationWizardView.ldapProvider).click(); await (await ApplicationWizardView.ldapProvider).click();
await (await ApplicationWizardView.nextButton()).click(); await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause(); await ApplicationWizardView.pause();

View File

@ -1,8 +1,9 @@
import { expect } from "@wdio/globals";
import ProviderWizardView from "../pageobjects/provider-wizard.page.js"; import ProviderWizardView from "../pageobjects/provider-wizard.page.js";
import ProvidersListPage from "../pageobjects/providers-list.page.js"; import ProvidersListPage from "../pageobjects/providers-list.page.js";
import { randomId } from "../utils/index.js"; import { randomId } from "../utils/index.js";
import { login } from "../utils/login.js"; import { login } from "../utils/login.js";
import { expect } from "@wdio/globals";
async function reachTheProvider() { async function reachTheProvider() {
await ProvidersListPage.logout(); await ProvidersListPage.logout();
@ -22,11 +23,14 @@ describe("Configure Oauth2 Providers", () => {
await reachTheProvider(); await reachTheProvider();
await ProviderWizardView.providerList.waitForDisplayed(); await ProviderWizardView.providerList.waitForDisplayed();
// @ts-expect-error "TSC does not understand metaprogramming."
await ProviderWizardView.oauth2Provider.scrollIntoView(); await ProviderWizardView.oauth2Provider.scrollIntoView();
// @ts-expect-error "TSC does not understand metaprogramming."
await ProviderWizardView.oauth2Provider.click(); await ProviderWizardView.oauth2Provider.click();
await ProviderWizardView.nextButton.click(); await ProviderWizardView.nextButton.click();
await ProviderWizardView.pause(); await ProviderWizardView.pause();
// @ts-expect-error "TSC does not understand ChainablePromiseElement"
await ProviderWizardView.oauth.providerName.setValue(newProviderName); await ProviderWizardView.oauth.providerName.setValue(newProviderName);
await ProviderWizardView.oauth.setAuthorizationFlow( await ProviderWizardView.oauth.setAuthorizationFlow(
"default-provider-authorization-explicit-consent", "default-provider-authorization-explicit-consent",
@ -38,7 +42,7 @@ describe("Configure Oauth2 Providers", () => {
await ProvidersListPage.clickSearchButton(); await ProvidersListPage.clickSearchButton();
await ProvidersListPage.pause(); await ProvidersListPage.pause();
const newProvider = await ProvidersListPage.findProviderRow(newProviderName); const newProvider = await ProvidersListPage.findProviderRow();
await newProvider.waitForDisplayed(); await newProvider.waitForDisplayed();
expect(newProvider).toExist(); expect(newProvider).toExist();
expect(await newProvider.getText()).toHaveText(newProviderName); expect(await newProvider.getText()).toHaveText(newProviderName);

View File

@ -1,9 +1,17 @@
{ {
"compilerOptions": { "compilerOptions": {
"strict": true,
"baseUrl": ".",
"moduleResolution": "node", "moduleResolution": "node",
"module": "ESNext", "module": "ESNext",
"target": "es2022", "target": "es2022",
"types": ["node", "@wdio/globals/types", "expect-webdriverio", "@wdio/mocha-framework", "@types/mocha"], "types": [
"node",
"@wdio/globals/types",
"expect-webdriverio",
"@wdio/mocha-framework",
"@types/mocha"
],
"skipLibCheck": true, "skipLibCheck": true,
"noEmit": true, "noEmit": true,
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
@ -14,5 +22,5 @@
"noUnusedParameters": true, "noUnusedParameters": true,
"noFallthroughCasesInSwitch": true "noFallthroughCasesInSwitch": true
}, },
"include": ["test"] "include": ["."]
} }

View File

@ -1,7 +1,8 @@
import { expect } from "@wdio/globals";
import LoginPage from "../pageobjects/login.page.js"; import LoginPage from "../pageobjects/login.page.js";
import UserLibraryPage from "../pageobjects/user-library.page.js"; import UserLibraryPage from "../pageobjects/user-library.page.js";
import { GOOD_PASSWORD, GOOD_USERNAME } from "./constants.js"; import { GOOD_PASSWORD, GOOD_USERNAME } from "./constants.js";
import { expect } from "@wdio/globals";
export const login = async () => { export const login = async () => {
await LoginPage.open(); await LoginPage.open();

View File

@ -23,7 +23,7 @@ export const config: WebdriverIO.Config = {
// then the current working directory is where your `package.json` resides, so `wdio` // then the current working directory is where your `package.json` resides, so `wdio`
// will be called from there. // will be called from there.
// //
specs: ["./test/specs/**/*.ts"], specs: ["./specs/**/*.ts"],
// Patterns to exclude. // Patterns to exclude.
exclude: [ exclude: [
// 'path/to/excluded/files' // 'path/to/excluded/files'
@ -204,6 +204,7 @@ export const config: WebdriverIO.Config = {
* @param {Array.<String>} specs List of spec file paths that are to be run * @param {Array.<String>} specs List of spec file paths that are to be run
* @param {object} browser instance of created browser/device session * @param {object} browser instance of created browser/device session
*/ */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
before: function (_capabilities, _specs) {}, before: function (_capabilities, _specs) {},
/** /**
* Runs before a WebdriverIO command gets executed. * Runs before a WebdriverIO command gets executed.

View File

@ -57,5 +57,6 @@
} }
} }
] ]
} },
"exclude": ["./tests"]
} }

View File

@ -93,7 +93,15 @@ export const config: WebdriverIO.Config = {
"goog:chromeOptions": { "goog:chromeOptions": {
args: [ args: [
"disable-search-engine-choice-screen", "disable-search-engine-choice-screen",
...(runHeadless ? ["headless", "disable-gpu", "no-sandbox"] : []), ...(runHeadless
? [
"headless",
"disable-gpu",
"no-sandbox",
"window-size=1280,672",
"browser-test",
]
: []),
], ],
}, },
}, },