web: merge branch 'web/wdio-2' into application-wizard-2-with-api-and-tests
* web/wdio-2: web/test: changed the name of one test to reflect it's 'good' status web/adding tests: added comments and cleaned up some administrative features. web/add webdriverIO testing layer
This commit is contained in:
commit
6c7e30dc7d
|
@ -0,0 +1,4 @@
|
||||||
|
# don't ever lint node_modules
|
||||||
|
node_modules
|
||||||
|
# don't lint nyc coverage output
|
||||||
|
coverage
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true
|
||||||
|
},
|
||||||
|
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 12,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": ["@typescript-eslint"],
|
||||||
|
"rules": {
|
||||||
|
"indent": "off",
|
||||||
|
"linebreak-style": ["error", "unix"],
|
||||||
|
"quotes": ["error", "double", { "avoidEscape": true }],
|
||||||
|
"semi": ["error", "always"],
|
||||||
|
"@typescript-eslint/ban-ts-comment": "off"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"plugin:sonarjs/recommended"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 12,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": ["@typescript-eslint", "sonarjs"],
|
||||||
|
"rules": {
|
||||||
|
"indent": "off",
|
||||||
|
"linebreak-style": ["error", "unix"],
|
||||||
|
"quotes": ["error", "double", { "avoidEscape": true }],
|
||||||
|
"semi": ["error", "always"],
|
||||||
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
|
"sonarjs/cognitive-complexity": ["error", 9],
|
||||||
|
"sonarjs/no-nested-template-literals": "off"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
# don't ever lint node_modules
|
||||||
|
node_modules
|
||||||
|
# don't lint nyc coverage output
|
||||||
|
coverage
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"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"]
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
.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) -- --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
|
|
@ -0,0 +1,18 @@
|
||||||
|
context: {}
|
||||||
|
entries:
|
||||||
|
- attrs:
|
||||||
|
attributes: {}
|
||||||
|
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: []
|
||||||
|
id: null
|
||||||
|
identifiers:
|
||||||
|
username: akadmin
|
||||||
|
model: authentik_core.user
|
||||||
|
state: present
|
File diff suppressed because it is too large
Load Diff
|
@ -1,16 +1,29 @@
|
||||||
{
|
{
|
||||||
"name": "my-new-project",
|
"name": "my-new-project",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@wdio/cli": "^8.16.11",
|
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
|
||||||
"@wdio/local-runner": "^8.16.11",
|
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
||||||
"@wdio/mocha-framework": "^8.16.11",
|
"@typescript-eslint/parser": "^6.7.2",
|
||||||
"@wdio/spec-reporter": "^8.16.9",
|
"@wdio/cli": "^8.16.11",
|
||||||
"ts-node": "^10.9.1",
|
"@wdio/local-runner": "^8.16.11",
|
||||||
"typescript": "^5.2.2",
|
"@wdio/mocha-framework": "^8.16.11",
|
||||||
"wdio-wait-for": "^3.0.7"
|
"@wdio/spec-reporter": "^8.16.9",
|
||||||
},
|
"eslint": "^8.49.0",
|
||||||
"scripts": {
|
"eslint-config-google": "^0.14.0",
|
||||||
"wdio": "wdio run ./wdio.conf.ts"
|
"eslint-plugin-sonarjs": "^0.21.0",
|
||||||
}
|
"npm-run-all": "^4.1.5",
|
||||||
|
"prettier": "^3.0.3",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"typescript": "^5.2.2",
|
||||||
|
"wdio-wait-for": "^3.0.7"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"wdio": "wdio run ./wdio.conf.ts",
|
||||||
|
"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-check": "prettier --check .",
|
||||||
|
"prettier": "prettier --write ."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { $ } from "@wdio/globals";
|
|
||||||
import AdminPage from "./admin.page.js";
|
import AdminPage from "./admin.page.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { $ } from "@wdio/globals";
|
|
||||||
import AdminPage from "./admin.page.js";
|
import AdminPage from "./admin.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
|
||||||
|
@ -9,9 +9,14 @@ class ApplicationsListPage extends AdminPage {
|
||||||
* define selectors using getter methods
|
* define selectors using getter methods
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async startCreateApplicationWizard() {
|
get startWizardButton() {
|
||||||
await $('>>>ak-wizard-frame button[slot="trigger"]').click();
|
return $('>>>ak-wizard-frame button[slot="trigger"]');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async open() {
|
||||||
|
return await super.open("if/admin/#/core/applications");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new ApplicationsListPage();
|
export default new ApplicationsListPage();
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
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
|
||||||
*/
|
*/
|
||||||
class LoginPage extends Page {
|
class LoginPage extends Page {
|
||||||
/**
|
/**
|
||||||
* define selectors using getter methods
|
* Selectors
|
||||||
*/
|
*/
|
||||||
get inputUsername() {
|
get inputUsername() {
|
||||||
return $('>>>input[name="uidField"]');
|
return $('>>>input[name="uidField"]');
|
||||||
|
@ -26,20 +26,20 @@ class LoginPage extends Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a method to encapsule automation code to interact with the page
|
* Specific interactions
|
||||||
* e.g. to login using username and password
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async username(username: string) {
|
async username(username: string) {
|
||||||
await this.inputPassword.isDisplayed();
|
await this.inputUsername.waitForClickable();
|
||||||
await this.inputUsername.setValue(username);
|
await this.inputUsername.setValue(username);
|
||||||
await this.btnSubmit.isEnabled();
|
await this.btnSubmit.waitForEnabled();
|
||||||
await this.btnSubmit.click();
|
await this.btnSubmit.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
async password(password: string) {
|
async password(password: string) {
|
||||||
await this.inputPassword.isDisplayed();
|
await this.inputPassword.waitForClickable();
|
||||||
await this.inputPassword.setValue(password);
|
await this.inputPassword.setValue(password);
|
||||||
await this.btnSubmit.isEnabled();
|
await this.btnSubmit.waitForEnabled();
|
||||||
await this.btnSubmit.click();
|
await this.btnSubmit.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ class LoginPage extends Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* overwrite specific options to adapt it to page object
|
* URL for accessing this page (if necessary)
|
||||||
*/
|
*/
|
||||||
open() {
|
open() {
|
||||||
return super.open("");
|
return super.open("");
|
||||||
|
|
|
@ -5,7 +5,7 @@ export class OauthForm extends Page {
|
||||||
await this.searchSelect(
|
await this.searchSelect(
|
||||||
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
|
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||||
"authorizationFlow",
|
"authorizationFlow",
|
||||||
`button*=${selector}`
|
`button*=${selector}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ import { browser } from "@wdio/globals";
|
||||||
const CLICK_TIME_DELAY = 250;
|
const CLICK_TIME_DELAY = 250;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* main page object containing all methods, selectors and functionality
|
* Main page object containing all methods, selectors and functionality that is shared across all
|
||||||
* that is shared across all page objects
|
* page objects
|
||||||
*/
|
*/
|
||||||
export default class Page {
|
export default class Page {
|
||||||
/**
|
/**
|
||||||
|
@ -22,6 +22,15 @@ export default class Page {
|
||||||
return browser.pause(CLICK_TIME_DELAY);
|
return browser.pause(CLICK_TIME_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Target a specific entry in SearchSelect. Requires that the SearchSelect have the `name`
|
||||||
|
* attribute set, so that the managed selector can find the *right* SearchSelect if there are
|
||||||
|
* multiple open SearchSelects on the board. See `./ldap-form.view:LdapForm.setBindFlow` for an
|
||||||
|
* example, and see `./oauth-form.view:OauthForm:setAuthorizationFlow` for a further example of
|
||||||
|
* why it would be hard to simplify this further (`flow` vs `tentanted-flow` vs a straight-up
|
||||||
|
* SearchSelect each have different a `searchSelector`).
|
||||||
|
*/
|
||||||
|
|
||||||
async searchSelect(searchSelector: string, managedSelector: string, buttonSelector: string) {
|
async searchSelect(searchSelector: string, managedSelector: string, buttonSelector: string) {
|
||||||
const inputBind = await $(searchSelector);
|
const inputBind = await $(searchSelector);
|
||||||
await inputBind.click();
|
await inputBind.click();
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export type Constructor<T = object> = new (...args: any[]) => T;
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { $ } from "@wdio/globals";
|
|
||||||
import Page from "./page.js";
|
import Page from "./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
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
import { expect } from "@wdio/globals";
|
|
||||||
import LoginPage from "../pageobjects/login.page.js";
|
|
||||||
import UserLibraryPage from "../pageobjects/user-library.page.js";
|
|
||||||
import AdminOverviewPage from "../pageobjects/admin-overview.page.js";
|
|
||||||
import ApplicationsListPage from "../pageobjects/applications-list.page.js";
|
|
||||||
import ApplicationWizard from "../pageobjects/application-wizard.page.js";
|
|
||||||
import { randomId } from "../utils/index.js";
|
|
||||||
|
|
||||||
describe("Configure new Application", () => {
|
|
||||||
it("should navigate to the wizard and configure LDAP", async () => {
|
|
||||||
const newId = randomId();
|
|
||||||
|
|
||||||
await LoginPage.open();
|
|
||||||
await LoginPage.login("ken@goauthentik.io", "eat10bugs");
|
|
||||||
|
|
||||||
expect(await UserLibraryPage.pageHeader).toHaveText("My Applications");
|
|
||||||
await UserLibraryPage.goToAdmin();
|
|
||||||
|
|
||||||
expect(await AdminOverviewPage.pageHeader).toHaveText("Welcome, ");
|
|
||||||
await AdminOverviewPage.openApplicationsListPage();
|
|
||||||
|
|
||||||
expect(await ApplicationsListPage.pageHeader).toHaveText("Applications");
|
|
||||||
ApplicationsListPage.startCreateApplicationWizard();
|
|
||||||
|
|
||||||
await ApplicationWizard.app.name.setValue(`Test application ${newId}`);
|
|
||||||
await ApplicationWizard.nextButton.click();
|
|
||||||
await (await ApplicationWizard.getProviderType("ldapprovider")).click();
|
|
||||||
await ApplicationWizard.nextButton.click();
|
|
||||||
await ApplicationWizard.ldap.setBindFlow("default-authentication-flow");
|
|
||||||
await ApplicationWizard.nextButton.click();
|
|
||||||
await expect(await ApplicationWizard.commitMessage).toHaveText(
|
|
||||||
"Your application has been saved"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,37 +0,0 @@
|
||||||
import { expect } from "@wdio/globals";
|
|
||||||
import LoginPage from "../pageobjects/login.page.js";
|
|
||||||
import UserLibraryPage from "../pageobjects/user-library.page.js";
|
|
||||||
import AdminOverviewPage from "../pageobjects/admin-overview.page.js";
|
|
||||||
import ApplicationsListPage from "../pageobjects/applications-list.page.js";
|
|
||||||
import ApplicationWizard from "../pageobjects/application-wizard.page.js";
|
|
||||||
import { randomId } from "../utils/index.js";
|
|
||||||
|
|
||||||
describe("Configure new Application", () => {
|
|
||||||
it("should navigate to the wizard and configure Oauth2", async () => {
|
|
||||||
const newId = randomId();
|
|
||||||
|
|
||||||
await LoginPage.open();
|
|
||||||
await LoginPage.login("ken@goauthentik.io", "eat10bugs");
|
|
||||||
|
|
||||||
expect(await UserLibraryPage.pageHeader).toHaveText("My Applications");
|
|
||||||
await UserLibraryPage.goToAdmin();
|
|
||||||
|
|
||||||
expect(await AdminOverviewPage.pageHeader).toHaveText("Welcome, ");
|
|
||||||
await AdminOverviewPage.openApplicationsListPage();
|
|
||||||
|
|
||||||
expect(await ApplicationsListPage.pageHeader).toHaveText("Applications");
|
|
||||||
ApplicationsListPage.startCreateApplicationWizard();
|
|
||||||
|
|
||||||
await ApplicationWizard.app.name.setValue(`Test application ${newId}`);
|
|
||||||
await ApplicationWizard.nextButton.click();
|
|
||||||
await (await ApplicationWizard.getProviderType("oauth2provider")).click();
|
|
||||||
await ApplicationWizard.nextButton.click();
|
|
||||||
await ApplicationWizard.oauth.setAuthorizationFlow(
|
|
||||||
"default-provider-authorization-explicit-consent"
|
|
||||||
);
|
|
||||||
await ApplicationWizard.nextButton.click();
|
|
||||||
await expect(await ApplicationWizard.commitMessage).toHaveText(
|
|
||||||
"Your application has been saved"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,21 +1,21 @@
|
||||||
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 { BAD_PASSWORD, BAD_USERNAME, 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 username", async () => {
|
it("should fail on a bad username", async () => {
|
||||||
await LoginPage.open();
|
await LoginPage.open();
|
||||||
await LoginPage.username("bad-username@bad-logio.io");
|
await LoginPage.username(BAD_USERNAME);
|
||||||
const failure = await LoginPage.authFailure;
|
const failure = await LoginPage.authFailure;
|
||||||
expect(failure).toHaveText("Failed to authenticate.");
|
expect(failure).toHaveText("Failed to authenticate.");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should fail on a bad password", async () => {
|
it("should fail on a bad password", async () => {
|
||||||
await LoginPage.open();
|
await LoginPage.open();
|
||||||
await LoginPage.username("ken@goauthentik.io");
|
await LoginPage.username(GOOD_USERNAME);
|
||||||
await LoginPage.pause();
|
await LoginPage.pause();
|
||||||
await LoginPage.password("-this-is-a-bad-password-");
|
await LoginPage.password(BAD_PASSWORD);
|
||||||
const failure = await LoginPage.authFailure;
|
const failure = await LoginPage.authFailure;
|
||||||
expect(failure).toHaveText("Failed to authenticate.");
|
expect(failure).toHaveText("Failed to authenticate.");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +1,5 @@
|
||||||
import { expect } from "@wdio/globals";
|
import { login } from "../utils/login.js";
|
||||||
import LoginPage from "../pageobjects/login.page.js";
|
|
||||||
import UserLibraryPage from "../pageobjects/user-library.page.js";
|
|
||||||
|
|
||||||
describe("Log into Authentik", () => {
|
describe("Log into Authentik", () => {
|
||||||
it("should login with valid credentials", async () => {
|
it("should login with valid credentials and reach the UserLibrary", login);
|
||||||
await LoginPage.open();
|
|
||||||
await LoginPage.login("ken@goauthentik.io", "eat10bugs");
|
|
||||||
await expect(UserLibraryPage.header).toHaveText("My applications");
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { login } from "../utils/login.js";
|
||||||
|
import { randomId } from "../utils/index.js";
|
||||||
|
import ApplicationsListPage from "../pageobjects/applications-list.page.js";
|
||||||
|
import ApplicationsWizardView from "../pageobjects/applications-wizard.page.js";
|
||||||
|
import ApplicationForm from "../pageobjects/application-form.view.js";
|
||||||
|
import { expect } from "@wdio/globals";
|
||||||
|
|
||||||
|
describe("Log into Authentik", () => {
|
||||||
|
it("should login with valid credentials and reach the UserLibrary", () => {
|
||||||
|
const newPrefix = randomId();
|
||||||
|
|
||||||
|
await login();
|
||||||
|
await ApplicationsListPage.open();
|
||||||
|
expect(await ApplicationsListPage.pageHeader).toHaveText("Applications");
|
||||||
|
|
||||||
|
await ApplicationsListPage.startWizardButton.click();
|
||||||
|
await ApplicationsWizardView.wizardTitle.toBeVisible();
|
||||||
|
expect(await ApplicationsWizardView.wizardTitle).toHaveText("Create Application");
|
||||||
|
|
||||||
|
await ApplicationForm.name.setValue(`New LDAP Application - ${newPrefix}`);
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,7 @@
|
||||||
|
export const BAD_USERNAME = process.env.AK_BAD_USERNAME ?? "bad-username@bad-login.io";
|
||||||
|
export const GOOD_USERNAME = process.env.AK_GOOD_USERNAME ?? "test-admin@goauthentik.io";
|
||||||
|
|
||||||
|
export const BAD_PASSWORD = process.env.AK_BAD_PASSWORD ?? "-this-is-a-bad-password-";
|
||||||
|
export const GOOD_PASSWORD = process.env.AK_GOOD_PASSWORD ?? "test-runner"
|
||||||
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
export function randomId() {
|
|
||||||
let dt = new Date().getTime();
|
|
||||||
return "xxxxxxxx".replace(/x/g, (c) => {
|
|
||||||
const r = (dt + Math.random() * 16) % 16 | 0;
|
|
||||||
dt = Math.floor(dt / 16);
|
|
||||||
return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function convertToSlug(text: string) {
|
|
||||||
return text
|
|
||||||
.toLowerCase()
|
|
||||||
.replace(/ /g, "-")
|
|
||||||
.replace(/[^\w-]+/g, "");
|
|
||||||
}
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
import LoginPage from "../pageobjects/login.page.js";
|
||||||
|
import UserLibraryPage from "../pageobjects/user-library.page.js";
|
||||||
|
import { expect } from "@wdio/globals";
|
||||||
|
import { GOOD_PASSWORD, GOOD_USERNAME } from "./constants.js";
|
||||||
|
|
||||||
|
export const login = async () => {
|
||||||
|
await LoginPage.open();
|
||||||
|
await LoginPage.login(GOOD_USERNAME, GOOD_PASSWORD);
|
||||||
|
await expect(UserLibraryPage.pageHeader).toHaveText("My applications");
|
||||||
|
};
|
|
@ -3,12 +3,7 @@
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"target": "es2022",
|
"target": "es2022",
|
||||||
"types": [
|
"types": ["node", "@wdio/globals/types", "expect-webdriverio", "@wdio/mocha-framework"],
|
||||||
"node",
|
|
||||||
"@wdio/globals/types",
|
|
||||||
"expect-webdriverio",
|
|
||||||
"@wdio/mocha-framework"
|
|
||||||
],
|
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"allowImportingTsExtensions": true,
|
"allowImportingTsExtensions": true,
|
||||||
|
@ -19,7 +14,5 @@
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["test"]
|
||||||
"test"
|
}
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import type { Options } from "@wdio/types";
|
import type { Options } from "@wdio/types";
|
||||||
|
|
||||||
export const config: Options.Testrunner = {
|
export const config: Options.Testrunner = {
|
||||||
//
|
//
|
||||||
// ====================
|
// ====================
|
||||||
|
@ -59,7 +60,22 @@ export const config: Options.Testrunner = {
|
||||||
//
|
//
|
||||||
capabilities: [
|
capabilities: [
|
||||||
{
|
{
|
||||||
browserName: "chrome",
|
"browserName": "chrome",
|
||||||
|
"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",
|
||||||
|
]
|
||||||
|
: [];
|
||||||
|
})()
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
Reference in New Issue