web: improve testing by adding test admin user via blueprint

This commit is contained in:
Ken Sternberg 2023-09-25 15:55:50 -07:00
parent 66ae52bf8e
commit 4fa6744edb
15 changed files with 1082 additions and 1264 deletions

View file

@ -1,26 +1,38 @@
.PHONY: help
.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
SPEC = $(WDIO) -- --logLevel warn --spec ./test/specs
LOCAL_BLUEPRINTS=$(ROOT)/blueprints/local
node_modules: ## Runs `npm install` to prepare this feature
npm ci
.PHONY: precommit
precommit: node_modules ## Run the precommit: spell check all comments, eslint with sonarJS, prettier-write
npm run precommit
# Actual tests are down below:
.PHONY: test-good-login
test-good-login: node_modules ## Test that we can log into the server. Requires a running instance of the server.
$(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
.PHONY: test-bad-login
test-bad-login: node_modules ## Test that bad usernames and passwords create appropriate error messages
test-bad-login: node_modules admin-user ## Test that bad usernames and passwords create appropriate error messages
$(SPEC)/bad-logins.ts

View file

@ -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

View file

@ -1,5 +1,5 @@
import Page from "../pageobjects/page.js";
import { browser } from "@wdio/globals";
import Page from "../pageobjects/page.js";
const CLICK_TIME_DELAY = 250;

View file

@ -1,10 +0,0 @@
import Page from "./page.js";
import { $ } from "@wdio/globals";
export class ApplicationForm extends Page {
get name() {
return $('>>>ak-form-element-horizontal input[name="name"]');
}
}
export default new ApplicationForm();

View file

@ -1,40 +0,0 @@
import AdminPage from "./admin.page.js";
import ApplicationForm from "./application-form.view.js";
import LdapForm from "./ldap-form.view.js";
import OauthForm from "./oauth-form.view.js";
import { $ } from "@wdio/globals";
/**
* sub page containing specific selectors and methods for a specific page
*/
class ApplicationWizardView extends AdminPage {
/**
* define selectors using getter methods
*/
ldap = LdapForm;
oauth = OauthForm;
app = ApplicationForm;
get wizardTitle() {
return $(">>>ak-application-wizard-commit-application h1.pf-c-title");
}
get providerList() {
return $(">>>ak-application-wizard-authentication-method-choice");
}
get nextButton() {
return $(">>>ak-wizard-frame footer button.pf-m-primary");
}
async getProviderType(type: string) {
return await this.providerList.$(`>>>input[value="${type}"]`);
}
get commitMessage() {
return $(">>>ak-application-wizard-commit-application h1.pf-c-title");
}
}
export default new ApplicationWizardView();

View file

@ -9,9 +9,14 @@ class ApplicationsListPage extends AdminPage {
* define selectors using getter methods
*/
async startCreateApplicationWizard() {
await $('>>>ak-wizard-frame button[slot="trigger"]').click();
get startWizardButton() {
return $('>>>ak-wizard-frame button[slot="trigger"]');
}
async open() {
return await super.open("if/admin/#/core/applications");
}
}
export default new ApplicationsListPage();

View file

@ -1,13 +0,0 @@
import Page from "./page.js";
export class LdapForm extends Page {
async setBindFlow(selector: string) {
await this.searchSelect(
'>>>ak-tenanted-flow-search[name="authorizationFlow"] input[type="text"]',
"authorizationFlow",
`button*=${selector}`,
);
}
}
export default new LdapForm();

View file

@ -1,13 +0,0 @@
import Page from "./page.js";
export class OauthForm extends Page {
async setAuthorizationFlow(selector: string) {
await this.searchSelect(
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
"authorizationFlow",
`button*=${selector}`,
);
}
}
export default new OauthForm();

View file

@ -1 +0,0 @@
export type Constructor<T = object> = new (...args: any[]) => T;

View file

@ -1,20 +1,21 @@
import LoginPage from "../pageobjects/login.page.js";
import { BAD_PASSWORD, BAD_USERNAME, GOOD_USERNAME } from "../utils/constants.js";
import { expect } from "@wdio/globals";
describe("Log into Authentik", () => {
it("should fail on a bad username", async () => {
await LoginPage.open();
await LoginPage.username("bad-username@bad-logio.io");
await LoginPage.username(BAD_USERNAME);
const failure = await LoginPage.authFailure;
expect(failure).toHaveText("Failed to authenticate.");
});
});
it("should fail on a bad password", async () => {
await LoginPage.open();
await LoginPage.username("ken@goauthentik.io");
await LoginPage.username(GOOD_USERNAME);
await LoginPage.pause();
await LoginPage.password("-this-is-a-bad-password-");
await LoginPage.password(BAD_PASSWORD);
const failure = await LoginPage.authFailure;
expect(failure).toHaveText("Failed to authenticate.");
});
});
});

View file

@ -1,11 +1,5 @@
import LoginPage from "../pageobjects/login.page.js";
import UserLibraryPage from "../pageobjects/user-library.page.js";
import { expect } from "@wdio/globals";
import { login } from "../utils/login.js";
describe("Log into Authentik", () => {
it("should login with valid credentials and reach the UserLibrary", async () => {
await LoginPage.open();
await LoginPage.login("ken@goauthentik.io", "eat10bugs");
await expect(UserLibraryPage.pageHeader).toHaveText("My applications");
});
it("should login with valid credentials and reach the UserLibrary", login);
});

View file

@ -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"

View file

@ -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");
};

View file

@ -60,7 +60,22 @@ export const config: Options.Testrunner = {
//
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",
]
: [];
})()
),
},
},
],