Pragmatic Testing in AdonisJS with Japa #7.0

The Browser Client

In This Lesson

We'll softly introduce Browser Testing, which allows powerful DOM assertions, in AdonisJS using Japa's Browser Client and Playwright. We'll get everything installed and configured and write our first simple test.

Created by
@tomgobich
Published

Notes Used to Craft this Lesson

Unlike the API Client, where we are making API requests similar to Axios and asserting against the responses, the Browser Client allows us to run tests with an actual browser. This gives us powerful assertion abilities against the actual HTML document that is rendered. So, for example, we'd be able to assert that a specific input is disabled using a query selector.

There is a ton of depth with this plugin; it could be a series on its own. Our focus here is just going to be a soft introduction to it. Needless to say, since we'll be testing with actual browsers here, these are going to be the slowest of our tests.

To start, let's go ahead and get it installed. The Browser Client uses Playwright to run the browser instances, so we'll need to install both here.

npm i -D playwright @japa/browser-client
Copied!

Now, for Playwright to work, it needs executables for the browsers. We can install those via:

npx playwright install
Copied!

That should pull down Chromeium, Firefox, WebKit, and FFMPEG. The output will look similar to the one below, depending on your system/shell.

> npx playwright install
Downloading Chromium 143.0.7499.4 (playwright build v1200) from https://cdn.playwright.dev/dbazure/download/playwright/builds/chromium/1200/chromium-mac-arm64.zip
159.6 MiB [====================] 100% 0.0s
Chromium 143.0.7499.4 (playwright build v1200) downloaded to /Users/<user>/Library/Caches/ms-playwright/chromium-1200
Downloading Chromium Headless Shell 143.0.7499.4 (playwright build v1200) from https://cdn.playwright.dev/dbazure/download/playwright/builds/chromium/1200/chromium-headless-shell-mac-arm64.zip
89.7 MiB [====================] 100% 0.0s
Chromium Headless Shell 143.0.7499.4 (playwright build v1200) downloaded to /Users/<user>/Library/Caches/ms-playwright/chromium_headless_shell-1200
Downloading Firefox 144.0.2 (playwright build v1497) from https://cdn.playwright.dev/dbazure/download/playwright/builds/firefox/1497/firefox-mac-arm64.zip
91.5 MiB [====================] 100% 0.0s
Firefox 144.0.2 (playwright build v1497) downloaded to /Users/<user>/Library/Caches/ms-playwright/firefox-1497
Downloading Webkit 26.0 (playwright build v2227) from https://cdn.playwright.dev/dbazure/download/playwright/builds/webkit/2227/webkit-mac-15-arm64.zip
71.9 MiB [====================] 100% 0.0s
Webkit 26.0 (playwright build v2227) downloaded to /Users/<user>/Library/Caches/ms-playwright/webkit-2227
Downloading FFMPEG playwright build v1011 from https://cdn.playwright.dev/dbazure/download/playwright/builds/ffmpeg/1011/ffmpeg-mac-arm64.zip
1 MiB [====================] 100% 0.0s
FFMPEG playwright build v1011 downloaded to /Users/<user>/Library/Caches/ms-playwright/ffmpeg-1011
Copied!

Next, we'll add a suite specifically for these so that it is only run when needed.

// adonisrc.ts
export default defineConfig({
  // ...

  tests: {
    suites: [
      {
        files: ["tests/unit/**/*.spec(.ts|.js)"],
        name: "unit",
        timeout: 2000,
      },
      {
        files: ["tests/functional/**/*.spec(.ts|.js)"],
        name: "functional",
        timeout: 30000,
      },
      {
        files: ["tests/browser/**/*.spec(.ts|.js)"],
        name: "browser",
        timeout: 30000,
      },
    ],
    forceExit: false,
  },
});
Copied!

Then, we'll register the plugin. As part of its options, we can provide which suite it should run in, and we'll want to set that to browser.

import { browserClient } from "@japa/browser-client";

export const plugins: Config["plugins"] = [
  assert(),
  openapi({
    schemas: [new URL("../docs/openapi.json", import.meta.url)],
  }),
  apiClient(),
  browserClient({
    runInSuites: ["browser"],
  }),
  pluginAdonisJS(app),
  sessionApiClient(app),
  authApiClient(app),
  shieldApiClient(),
  disallowPinnedTests({
    disallow: !!process.env.CI,
  }),
];
Copied!
  • tests
  • bootstrap.ts

Great, finally let's give it a test run!

node ace make:test pages/auth/login --suite=browser
Copied!

For our test, let's just confirm that our login page shows "Login" within an H1 element.

test.group("Pages auth login", () => {
  test("see an h1 saying login", async ({ visit, route }) => {});
});
Copied!

Similar to how the API Client provides a client to our tests, the Browser Client provides a visit which we can use to visit URLs and get back the rendered page. That page is an instance of Playwright's page, which contains a ton of methods to perform selections, actions, and determinations on the page itself. We'll walk through an example of those in the next lesson.

test.group("Pages auth login", () => {
  test("see an h1 saying login", async ({ visit, route }) => {
    const page = await visit(route("auth.login.show"));
  });
});
Copied!

Japa's plugin also adds a number of assertion utilities to the Playwright page, making testing super convenient.

test.group("Pages auth login", () => {
  test("see an h1 saying login", async ({ visit, route }) => {
    const page = await visit(route("auth.login.show"));
    await page.assertText("h1", "Login");
  });
});
Copied!

Here, with assertText, we're providing the query selector h1, which behaves similarly to running document.querySelector('h1') inside a browser. Then the method itself is asserting that the found H1 element's innerText equals "Login".

Join the Discussion 0 comments

Create a free account to join in on the discussion
robot comment bubble

Be the first to comment!