Commit Graph

2 Commits

Author SHA1 Message Date
9c45ec1918 web: fix e2e tests to work with latest WebdriverIO and authentik 2024.8 (#11105)
* 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
2024-08-29 07:04:53 -07:00
20dde50ed3 web: add webdriverIO testing layer (#6959)
* web/add webdriverIO testing layer

This commit adds WebdriverIO as an end-to-end solution to unit testing.  WebdriverIO can be run both
locally and remotely, supports strong integration with web components, and is generally robust for
use in pipelines.  I'll confess to working through a tutorial on how to do this for web components,
and this is just chapter 2 (I think there are 5 or so chapters...).

There's a makefile, with help!  If you just run `make` it tells you:

```
Specify a command. The choices are:

  help                 Show this help
  node_modules         Runs `npm install` to prepare this feature
  precommit            Run the precommit: spell check all comments, eslint with sonarJS, prettier-write
  test-good-login      Test that we can log into the server. Requires a running instance of the server.
  test-bad-login       Test that bad usernames and passwords create appropriate error messages
```

... because Makefiles are documentation, and documentation belongs in Makefiles.

I've chosen to go with a PageObject-oriented low-level DSL; what that means is that for each major
components (a page, a form, a wizard), there's a class that provides human-readable names for
human-interactable and human-viewable objects on the page.  The LoginPage object, for example, has
selectors for the username, password, submit button, and the failure alert; accessing those allows
us to test for items as expected., and to write a DSL for "a good login" that's as straightforward
as:

```
        await LoginPage.open();
        await LoginPage.login("ken@goauthentik.io", "eat10bugs");
        await expect(UserLibraryPage.pageHeader).toHaveText("My applications");
```

There was a *lot* of messing around with the LoginPage to get the username and password into the
system.  For example, I had to do this with all the `waitForClickable` and `waitForEnable` because
we both keep the buttons inaccessible until the form has something and we "black out" the page (put
a darkening filter over it) while accessing the flow, meaning there was a race condition such that
the test would attempt to interact with the username or password field before it was accessible.
But this works now, which is very nice.

``` JavaScript
    get inputUsername() {
        return $('>>>input[name="uidField"]');
    }

    get btnSubmit() {
        return $('>>>button[type="submit"]');
    }

    async username(username: string) {
        await this.inputUsername.waitForClickable();
        await this.inputUsername.setValue(username);
        await this.btnSubmit.waitForEnabled();
        await this.btnSubmit.click();
    }
```

The bells & whistles of *Prettier*, *Eslint*, and *Codespell* have also been enabled. I do like my
guardrails.

* web/adding tests: added comments and cleaned up some administrative features.

* web/test: changed the name of one test to reflect it's 'good' status

* web: improve testing by adding test admin user via blueprint

* fix blueprints

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update package name

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add dependabot

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* prettier run

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add basic CI

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* remove hooks

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 08:40:39 -07:00