Compare commits
5 Commits
npm-worksp
...
web/testin
Author | SHA1 | Date | |
---|---|---|---|
f0256a0535 | |||
142a985914 | |||
a8531d498a | |||
f8cb4e880b | |||
3ced637db3 |
@ -53,7 +53,7 @@ type Pair = [string, string];
|
||||
// Define a getter for each provider type in the radio button collection.
|
||||
|
||||
const providerValues: Pair[] = [
|
||||
["oauth2provider", "oauth2Provider"],
|
||||
["oauth2Provider", "oauth2Provider"],
|
||||
["ldapprovider", "ldapProvider"],
|
||||
["proxyprovider-proxy", "proxyProviderProxy"],
|
||||
["proxyprovider-forwardsingle", "proxyProviderForwardsingle"],
|
||||
@ -66,7 +66,7 @@ providerValues.forEach(([value, name]: Pair) => {
|
||||
Object.defineProperties(ApplicationWizardView.prototype, {
|
||||
[name]: {
|
||||
get: function () {
|
||||
return this.providerList.$(`>>>input[value="${value}"]`);
|
||||
return this.providerList.$(`>>>div[data-testid=wizard-provider-${value}]`);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -4,9 +4,9 @@ import { $ } from "@wdio/globals";
|
||||
export class ForwardProxyForm extends Page {
|
||||
async setAuthorizationFlow(selector: string) {
|
||||
await this.searchSelect(
|
||||
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||
'[name="authorizationFlow"]',
|
||||
"authorizationFlow",
|
||||
`button*=${selector}`,
|
||||
`div*=${selector}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,9 @@ import Page from "../page.js";
|
||||
export class LdapForm extends Page {
|
||||
async setBindFlow(selector: string) {
|
||||
await this.searchSelect(
|
||||
'>>>ak-branded-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||
"[name=authorizationFlow]",
|
||||
"authorizationFlow",
|
||||
`button*=${selector}`,
|
||||
`div*=${selector}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ import { $ } from "@wdio/globals";
|
||||
export class OauthForm extends Page {
|
||||
async setAuthorizationFlow(selector: string) {
|
||||
await this.searchSelect(
|
||||
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||
'[name="authorizationFlow"]',
|
||||
"authorizationFlow",
|
||||
`button*=${selector}`,
|
||||
`div*=${selector}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,9 @@ import Page from "../page.js";
|
||||
export class RadiusForm extends Page {
|
||||
async setAuthenticationFlow(selector: string) {
|
||||
await this.searchSelect(
|
||||
'>>>ak-branded-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||
'[name="authorizationFlow"]',
|
||||
"authorizationFlow",
|
||||
`button*=${selector}`,
|
||||
`div*=${selector}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ import { $ } from "@wdio/globals";
|
||||
export class SamlForm extends Page {
|
||||
async setAuthorizationFlow(selector: string) {
|
||||
await this.searchSelect(
|
||||
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||
'[name="authorizationFlow"]',
|
||||
"authorizationFlow",
|
||||
`button*=${selector}`,
|
||||
`div*=${selector}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,9 @@ import { $ } from "@wdio/globals";
|
||||
export class TransparentProxyForm extends Page {
|
||||
async setAuthorizationFlow(selector: string) {
|
||||
await this.searchSelect(
|
||||
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||
'[name="authorizationFlow"]',
|
||||
"authorizationFlow",
|
||||
`button*=${selector}`,
|
||||
`div*=${selector}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import Page from "./page.js";
|
||||
import UserLibraryPage from "./user-library.page.js";
|
||||
import { $ } from "@wdio/globals";
|
||||
import { and, or, presenceOf, textToBePresentInElement } from "wdio-wait-for";
|
||||
|
||||
/**
|
||||
* sub page containing specific selectors and methods for a specific page
|
||||
@ -48,6 +49,14 @@ class LoginPage extends Page {
|
||||
await this.pause();
|
||||
await this.password(password);
|
||||
await this.pause();
|
||||
|
||||
const redirect = await $(">>>a[type=submit]");
|
||||
await browser.waitUntil(or(presenceOf(redirect), presenceOf(UserLibraryPage.pageHeader)));
|
||||
|
||||
if (await redirect.isExisting()) {
|
||||
await redirect.click();
|
||||
}
|
||||
|
||||
await this.pause(">>>div.header h1");
|
||||
return UserLibraryPage;
|
||||
}
|
||||
|
@ -32,10 +32,16 @@ export default class Page {
|
||||
*/
|
||||
|
||||
async searchSelect(searchSelector: string, managedSelector: string, buttonSelector: string) {
|
||||
const inputBind = await $(searchSelector);
|
||||
const controlSelector = `>>>ak-search-select-view${searchSelector}`;
|
||||
const control = await $(controlSelector);
|
||||
control.scrollIntoView();
|
||||
const inputBind = await control.$(">>>input[type=text]");
|
||||
await inputBind.click();
|
||||
|
||||
const searchBlock = await $(`>>>div[data-managed-for="${managedSelector}"]`);
|
||||
const target = searchBlock.$(buttonSelector);
|
||||
const interior = searchBlock.$(">>>ul");
|
||||
interior.scrollIntoView();
|
||||
const target = interior.$(buttonSelector);
|
||||
return await target.click();
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,7 @@
|
||||
import LoginPage from "../pageobjects/login.page.js";
|
||||
import UserLibraryPage from "../pageobjects/user-library.page.js";
|
||||
import { GOOD_PASSWORD, GOOD_USERNAME } from "./constants.js";
|
||||
import { expect } from "@wdio/globals";
|
||||
|
||||
export const login = async () => {
|
||||
await LoginPage.open();
|
||||
await LoginPage.login(GOOD_USERNAME, GOOD_PASSWORD);
|
||||
await expect(UserLibraryPage.pageHeader).toHaveText("My applications");
|
||||
};
|
||||
|
@ -212,7 +212,9 @@ export const config: Options.Testrunner = {
|
||||
* @param {Array.<String>} specs List of spec file paths that are to be run
|
||||
* @param {object} browser instance of created browser/device session
|
||||
*/
|
||||
before: function (_capabilities, _specs) {},
|
||||
before: function (_capabilities, _specs) {
|
||||
browser.setWindowSize(1920, 1080);
|
||||
},
|
||||
/**
|
||||
* Runs before a WebdriverIO command gets executed.
|
||||
* @param {string} commandName hook command name
|
||||
|
10
web/package-lock.json
generated
10
web/package-lock.json
generated
@ -93,7 +93,7 @@
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-custom-elements": "0.0.8",
|
||||
"eslint-plugin-lit": "^1.11.0",
|
||||
"eslint-plugin-sonarjs": "^1.0.3",
|
||||
"eslint-plugin-sonarjs": "0.25.1",
|
||||
"eslint-plugin-storybook": "^0.8.0",
|
||||
"github-slugger": "^2.0.0",
|
||||
"glob": "^11.0.0",
|
||||
@ -14421,15 +14421,15 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/eslint-plugin-sonarjs": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-1.0.3.tgz",
|
||||
"integrity": "sha512-6s41HLPYPyDrp+5+7Db5yFYbod6h9pC7yx+xfcNwHRcLe1EZwbbQT/tdOAkR7ekVUkNGEvN3GmYakIoQUX7dEg==",
|
||||
"version": "0.25.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.25.1.tgz",
|
||||
"integrity": "sha512-5IOKvj/GMBNqjxBdItfotfRHo7w48496GOu1hxdeXuD0mB1JBlDCViiLHETDTfA8pDAVSBimBEQoetRXYceQEw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.0.0 || ^9.0.0"
|
||||
"eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-storybook": {
|
||||
|
@ -120,7 +120,7 @@
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-custom-elements": "0.0.8",
|
||||
"eslint-plugin-lit": "^1.11.0",
|
||||
"eslint-plugin-sonarjs": "^1.0.3",
|
||||
"eslint-plugin-sonarjs": "0.25.1",
|
||||
"eslint-plugin-storybook": "^0.8.0",
|
||||
"github-slugger": "^2.0.0",
|
||||
"glob": "^11.0.0",
|
||||
|
@ -1,55 +0,0 @@
|
||||
import { execFileSync } from "child_process";
|
||||
import { ESLint } from "eslint";
|
||||
import path from "path";
|
||||
import process from "process";
|
||||
|
||||
// Code assumes this script is in the './web/scripts' folder.
|
||||
const projectRoot = execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
||||
encoding: "utf8",
|
||||
}).replace("\n", "");
|
||||
process.chdir(path.join(projectRoot, "./web"));
|
||||
|
||||
const eslintConfig = {
|
||||
overrideConfig: {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
},
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:lit/recommended",
|
||||
"plugin:custom-elements/recommended",
|
||||
"plugin:storybook/recommended",
|
||||
"plugin:sonarjs/recommended",
|
||||
],
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
ecmaVersion: 12,
|
||||
sourceType: "module",
|
||||
},
|
||||
plugins: ["@typescript-eslint", "lit", "custom-elements", "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-duplicate-string": "off",
|
||||
"sonarjs/no-nested-template-literals": "off",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const updated = ["./src/", "./build.mjs", "./scripts/*.mjs"];
|
||||
|
||||
const eslint = new ESLint(eslintConfig);
|
||||
const results = await eslint.lintFiles(updated);
|
||||
const formatter = await eslint.loadFormatter("stylish");
|
||||
const resultText = formatter.format(results);
|
||||
const errors = results.reduce((acc, result) => acc + result.errorCount, 0);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(resultText);
|
||||
process.exit(errors > 1 ? 1 : 0);
|
@ -43,34 +43,53 @@ const eslintConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
const porcelainV1 = /^(..)\s+(.*$)/;
|
||||
const gitStatus = execFileSync("git", ["status", "--porcelain", "."], { encoding: "utf8" });
|
||||
function findChangedFiles() {
|
||||
const porcelainV1 = /^(..)\s+(.*$)/;
|
||||
const gitStatus = execFileSync("git", ["status", "--porcelain", "."], { encoding: "utf8" });
|
||||
|
||||
const statuses = gitStatus.split("\n").reduce((acc, line) => {
|
||||
const match = porcelainV1.exec(line.replace("\n"));
|
||||
if (!match) {
|
||||
return acc;
|
||||
}
|
||||
const [status, path] = Array.from(match).slice(1, 3);
|
||||
return [...acc, [status, path.split("\x00")[0]]];
|
||||
}, []);
|
||||
const statuses = gitStatus.split("\n").reduce((acc, line) => {
|
||||
const match = porcelainV1.exec(line.replace("\n"));
|
||||
if (!match) {
|
||||
return acc;
|
||||
}
|
||||
const [status, path] = Array.from(match).slice(1, 3);
|
||||
return [...acc, [status, path.split("\x00")[0]]];
|
||||
}, []);
|
||||
|
||||
const isModified = /^(M|\?|\s)(M|\?|\s)/;
|
||||
const modified = (s) => isModified.test(s);
|
||||
const isModified = /^(M|\?|\s)(M|\?|\s)/;
|
||||
const modified = (s) => isModified.test(s);
|
||||
|
||||
const isCheckable = /\.(ts|js|mjs)$/;
|
||||
const checkable = (s) => isCheckable.test(s);
|
||||
const isCheckable = /\.(ts|js|mjs)$/;
|
||||
const checkable = (s) => isCheckable.test(s);
|
||||
|
||||
const ignored = /\/\.storybook\//;
|
||||
const notIgnored = (s) => !ignored.test(s);
|
||||
const ignored = /\/\.storybook\//;
|
||||
const notIgnored = (s) => !ignored.test(s);
|
||||
|
||||
const updated = statuses.reduce(
|
||||
(acc, [status, filename]) =>
|
||||
modified(status) && checkable(filename) && notIgnored(filename)
|
||||
? [...acc, path.join(projectRoot, filename)]
|
||||
: acc,
|
||||
[],
|
||||
);
|
||||
return statuses.reduce(
|
||||
(acc, [status, filename]) =>
|
||||
modified(status) && checkable(filename) && notIgnored(filename)
|
||||
? [...acc, path.join(projectRoot, filename)]
|
||||
: acc,
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
if (process.argv.length > 2 && (process.argv[2] === "-h" || process.argv[2] === "--help")) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Run eslint with extra-hard checks
|
||||
|
||||
options:
|
||||
-c, --changed: (default) check only the files that have changed
|
||||
-n, --nightmare: check all the files in the repository
|
||||
-h, --help: This help message
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const updated =
|
||||
process.argv.length > 2 && (process.argv[2] === "-n" || process.argv[2] === "--nightmare")
|
||||
? ["./src/", "./build.mjs", "./scripts/*.mjs"]
|
||||
: findChangedFiles();
|
||||
|
||||
const eslint = new ESLint(eslintConfig);
|
||||
const results = await eslint.lintFiles(updated);
|
||||
|
@ -30,6 +30,7 @@ export type LocalTypeCreate = TypeCreate & {
|
||||
modelName: ProviderModelEnumType;
|
||||
converter: ModelConverter;
|
||||
note?: ProviderNote;
|
||||
testId: string;
|
||||
renderer: ProviderRenderer;
|
||||
};
|
||||
|
||||
@ -46,6 +47,7 @@ export const providerModelsList: LocalTypeCreate[] = [
|
||||
...(provider as OAuth2ProviderRequest),
|
||||
}),
|
||||
component: "",
|
||||
testId: "wizard-provider-oauth2Provider",
|
||||
iconUrl: "/static/authentik/sources/openidconnect.svg",
|
||||
},
|
||||
{
|
||||
@ -62,6 +64,7 @@ export const providerModelsList: LocalTypeCreate[] = [
|
||||
...(provider as LDAPProviderRequest),
|
||||
}),
|
||||
component: "",
|
||||
testId: "wizard-provider-ldapprovider",
|
||||
iconUrl: "/static/authentik/sources/ldap.png",
|
||||
},
|
||||
{
|
||||
@ -77,6 +80,7 @@ export const providerModelsList: LocalTypeCreate[] = [
|
||||
mode: ProxyMode.Proxy,
|
||||
}),
|
||||
component: "",
|
||||
testId: "wizard-provider-proxyprovider-proxy",
|
||||
iconUrl: "/static/authentik/sources/proxy.svg",
|
||||
},
|
||||
{
|
||||
@ -92,6 +96,7 @@ export const providerModelsList: LocalTypeCreate[] = [
|
||||
mode: ProxyMode.ForwardSingle,
|
||||
}),
|
||||
component: "",
|
||||
testId: "wizard-provider-proxyprovider-forwardsingle",
|
||||
iconUrl: "/static/authentik/sources/proxy.svg",
|
||||
},
|
||||
{
|
||||
@ -107,6 +112,7 @@ export const providerModelsList: LocalTypeCreate[] = [
|
||||
mode: ProxyMode.ForwardDomain,
|
||||
}),
|
||||
component: "",
|
||||
testId: "wizard-provider-proxyprovider-forwarddomain",
|
||||
iconUrl: "/static/authentik/sources/proxy.svg",
|
||||
},
|
||||
{
|
||||
@ -123,6 +129,7 @@ export const providerModelsList: LocalTypeCreate[] = [
|
||||
note: () => html`<ak-license-notice></ak-license-notice>`,
|
||||
requiresEnterprise: true,
|
||||
component: "",
|
||||
testId: "wizard-provider-racprovider",
|
||||
iconUrl: "/static/authentik/sources/rac.svg",
|
||||
},
|
||||
{
|
||||
@ -137,6 +144,7 @@ export const providerModelsList: LocalTypeCreate[] = [
|
||||
...(provider as SAMLProviderRequest),
|
||||
}),
|
||||
component: "",
|
||||
testId: "wizard-provider-samlprovider",
|
||||
iconUrl: "/static/authentik/sources/saml.png",
|
||||
},
|
||||
{
|
||||
@ -151,6 +159,7 @@ export const providerModelsList: LocalTypeCreate[] = [
|
||||
...(provider as RadiusProviderRequest),
|
||||
}),
|
||||
component: "",
|
||||
testId: "wizard-provider-radiusprovider",
|
||||
iconUrl: "/static/authentik/sources/radius.svg",
|
||||
},
|
||||
{
|
||||
@ -165,6 +174,7 @@ export const providerModelsList: LocalTypeCreate[] = [
|
||||
...(provider as SCIMProviderRequest),
|
||||
}),
|
||||
component: "",
|
||||
testId: "wizard-provider-scimprovider",
|
||||
iconUrl: "/static/authentik/sources/scim.png",
|
||||
},
|
||||
];
|
||||
|
@ -5,6 +5,7 @@ import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
import PFCard from "@patternfly/patternfly/components/Card/card.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
@ -19,10 +20,12 @@ export enum TypeCreateWizardPageLayouts {
|
||||
grid = "grid",
|
||||
}
|
||||
|
||||
type TypeCreateWithTestId = TypeCreate & { testId?: string };
|
||||
|
||||
@customElement("ak-wizard-page-type-create")
|
||||
export class TypeCreateWizardPage extends WithLicenseSummary(WizardPage) {
|
||||
@property({ attribute: false })
|
||||
types: TypeCreate[] = [];
|
||||
types: TypeCreateWithTestId[] = [];
|
||||
|
||||
@property({ attribute: false })
|
||||
selectedType?: TypeCreate;
|
||||
@ -51,7 +54,7 @@ export class TypeCreateWizardPage extends WithLicenseSummary(WizardPage) {
|
||||
|
||||
sidebarLabel = () => msg("Select type");
|
||||
|
||||
activeCallback: () => Promise<void> = async () => {
|
||||
activeCallback = async () => {
|
||||
this.host.isValid = false;
|
||||
if (this.selectedType) {
|
||||
this.selectDispatch(this.selectedType);
|
||||
@ -78,6 +81,7 @@ export class TypeCreateWizardPage extends WithLicenseSummary(WizardPage) {
|
||||
: "pf-m-selectable-raised"} ${this.selectedType == type
|
||||
? "pf-m-selected-raised"
|
||||
: ""}"
|
||||
data-testid=${ifDefined(type.testId)}
|
||||
tabindex=${idx}
|
||||
@click=${() => {
|
||||
if (requiresEnterprise) {
|
||||
|
@ -79,7 +79,7 @@ export class RedirectStage extends BaseStage<RedirectChallenge, FlowChallengeRes
|
||||
<div class="pf-c-login__main-body">
|
||||
<form class="pf-c-form">
|
||||
<div class="pf-c-form__group">
|
||||
<p>${msg("You're about to be redirect to the following URL.")}</p>
|
||||
<p>${msg("You will now be redirected to the following URL.")}</p>
|
||||
<code>${this.getURL()}</code>
|
||||
</div>
|
||||
<div class="pf-c-form__group pf-m-action">
|
||||
|
Reference in New Issue
Block a user