
* web: fix e2e tests to work with latest WebdriverIO and authentik 2024.8 - Adjust the ApplicationWizard "select provider type" typeslist to have the right OUIA tags when running - Add OUIA tags to TypeCreateWizard - Provide default values for `.jwksSources` when needed. - Upgrade E2E WebUI tests to use WebdriverIO 9. - Upgrade the linters to include `package.json` and `package-lock.json`. - Adjust a *lot* of the WebdriverIO selectors! - Provide a driver for the TypeCreate card-based radio interface. - Split `Bad Logins` into two separate files. Aside from the obvious, "because testing needs this" or "because there were warnings on the console when this was running," the real issue is that WebdriverIO 9 has changed the syntax and semantics of its ShadowDOM-piercing `$` mechanism. For Oauth2 and Proxy, the field `.jwksSources` may be undefined, but `undefined` is not a legal value for ak-dual-select's `selected` field. Provide a default or use `ifDefined()`. I chose to provide a default of `[]`. In the previous iteration, `$(">>>ak-search-select input")` would be sufficient for WebdriverIO to find an input inside a component. Now, it needs to be written as: `$("ak-search-select").$("input")`. And in rare cases, when you have a floating component that is separated from its invocation (such as Notification or SearchSelect), even that doesn't work well and you have to fall back to some old-school hacking (see `./tests/wdio/test/pageobjects/page.ts` for an example) to find some child elements. Also, the monadic nature of `$` seems to have faded a bit. `$` used to wrap all child invocations in promises, making the entire expression a single valid promise; it seems that it is now necessary to unwrap the promises yourself under some circumstances, resulting in a lot of `await (await (await ... )))` blocks in the tests. We've slightly changed the semantics of our login mechanism, and now the default behavior is to not reveal when a username is invalid, but to treat the entire login as a single failure mechanism, so as not to expose any details about the username database. The problem arises that now, we (or Chrome) cache the username between roundtrips, and WebdriverIO's second pass was becoming confused by its presence. By putting the Bad Logins into two separate files, I get two separate browser instances with cleared caches, so each test can be run in the pristine environment it needs to validate the behavior I'm expecting. * web: added comment to explain the hack * Add comment to TypeCreateWizardPage to explain the component name hack. * web: fix some lint found by CI/CD
170 lines
7.5 KiB
TypeScript
170 lines
7.5 KiB
TypeScript
import ApplicationWizardView from "../pageobjects/application-wizard.page.js";
|
|
import ApplicationsListPage from "../pageobjects/applications-list.page.js";
|
|
import { randomId } from "../utils/index.js";
|
|
import { login } from "../utils/login.js";
|
|
import { expect } from "@wdio/globals";
|
|
|
|
async function reachTheProvider(title: string) {
|
|
const newPrefix = randomId();
|
|
|
|
await ApplicationsListPage.logout();
|
|
await login();
|
|
await ApplicationsListPage.open();
|
|
await ApplicationsListPage.pause("ak-page-header");
|
|
await expect(await ApplicationsListPage.pageHeader()).toBeDisplayed();
|
|
await expect(await ApplicationsListPage.pageHeader()).toHaveText("Applications");
|
|
|
|
await (await ApplicationsListPage.startWizardButton()).click();
|
|
await (await ApplicationWizardView.wizardTitle()).waitForDisplayed();
|
|
await expect(await ApplicationWizardView.wizardTitle()).toHaveText("New application");
|
|
|
|
await (await ApplicationWizardView.app.name()).setValue(`${title} - ${newPrefix}`);
|
|
await (await ApplicationWizardView.app.uiSettings()).scrollIntoView();
|
|
await (await ApplicationWizardView.app.uiSettings()).click();
|
|
await (await ApplicationWizardView.app.launchUrl()).scrollIntoView();
|
|
await (await ApplicationWizardView.app.launchUrl()).setValue("http://example.goauthentik.io");
|
|
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
return await ApplicationWizardView.pause();
|
|
}
|
|
|
|
async function getCommitMessage() {
|
|
await (await ApplicationWizardView.successMessage()).waitForDisplayed();
|
|
return await ApplicationWizardView.successMessage();
|
|
}
|
|
|
|
const SUCCESS_MESSAGE = "Your application has been saved";
|
|
const EXPLICIT_CONSENT = "default-provider-authorization-explicit-consent";
|
|
|
|
describe("Configure Applications with the Application Wizard", () => {
|
|
it("Should configure a simple LDAP Application", async () => {
|
|
await reachTheProvider("New LDAP Application");
|
|
|
|
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
|
await (await ApplicationWizardView.ldapProvider).scrollIntoView();
|
|
await (await ApplicationWizardView.ldapProvider).click();
|
|
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await ApplicationWizardView.ldap.setBindFlow("default-authentication-flow");
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
|
});
|
|
|
|
it("Should configure a simple Oauth2 Application", async () => {
|
|
await reachTheProvider("New Oauth2 Application");
|
|
|
|
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
|
await (await ApplicationWizardView.oauth2Provider).scrollIntoView();
|
|
await (await ApplicationWizardView.oauth2Provider).click();
|
|
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await ApplicationWizardView.oauth.setAuthorizationFlow(EXPLICIT_CONSENT);
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
|
});
|
|
|
|
it("Should configure a simple SAML Application", async () => {
|
|
await reachTheProvider("New SAML Application");
|
|
|
|
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
|
await (await ApplicationWizardView.samlProvider).scrollIntoView();
|
|
await (await ApplicationWizardView.samlProvider).click();
|
|
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await ApplicationWizardView.saml.setAuthorizationFlow(EXPLICIT_CONSENT);
|
|
await ApplicationWizardView.saml.acsUrl.setValue("http://example.com:8000/");
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
|
});
|
|
|
|
it("Should configure a simple SCIM Application", async () => {
|
|
await reachTheProvider("New SCIM Application");
|
|
|
|
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
|
await (await ApplicationWizardView.scimProvider).scrollIntoView();
|
|
await (await ApplicationWizardView.scimProvider).click();
|
|
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await ApplicationWizardView.scim.url.setValue("http://example.com:8000/");
|
|
await ApplicationWizardView.scim.token.setValue("a-very-basic-token");
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
|
});
|
|
|
|
it("Should configure a simple Radius Application", async () => {
|
|
await reachTheProvider("New Radius Application");
|
|
|
|
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
|
await (await ApplicationWizardView.radiusProvider).scrollIntoView();
|
|
await (await ApplicationWizardView.radiusProvider).click();
|
|
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await ApplicationWizardView.radius.setAuthenticationFlow("default-authentication-flow");
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
|
});
|
|
|
|
it("Should configure a simple Transparent Proxy Application", async () => {
|
|
await reachTheProvider("New Transparent Proxy Application");
|
|
|
|
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
|
await (await ApplicationWizardView.proxyProviderProxy).scrollIntoView();
|
|
await (await ApplicationWizardView.proxyProviderProxy).click();
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await ApplicationWizardView.transparentProxy.setAuthorizationFlow(EXPLICIT_CONSENT);
|
|
await ApplicationWizardView.transparentProxy.externalHost.setValue(
|
|
"http://external.example.com",
|
|
);
|
|
await ApplicationWizardView.transparentProxy.internalHost.setValue(
|
|
"http://internal.example.com",
|
|
);
|
|
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
|
});
|
|
|
|
it("Should configure a simple Forward Proxy Application", async () => {
|
|
await reachTheProvider("New Forward Proxy Application");
|
|
|
|
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
|
await (await ApplicationWizardView.proxyProviderForwardsingle).scrollIntoView();
|
|
await (await ApplicationWizardView.proxyProviderForwardsingle).click();
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await ApplicationWizardView.forwardProxy.setAuthorizationFlow(EXPLICIT_CONSENT);
|
|
await ApplicationWizardView.forwardProxy.externalHost.setValue(
|
|
"http://external.example.com",
|
|
);
|
|
|
|
await (await ApplicationWizardView.nextButton()).click();
|
|
await ApplicationWizardView.pause();
|
|
|
|
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
|
});
|
|
});
|