Skip to main content

Testing

Unit Tests

Unit tests run on Vitest and live beside the source they cover, in src/**/__tests__/*.test.ts. The Nuxt package is the exception, keeping its tests in packages/nuxt/tests/unit.

pnpm test                                  # every package
pnpm --filter @thunderid/react test # one package

Packages that render components (browser, react, react-router, tanstack-router) also expose test:browser, which runs the same specs in a real browser environment.

End-to-end Testing

The end-to-end suite lives in tests/e2e and runs on Playwright. It drives the sample apps in a real browser against a real ThunderID server, covering what unit tests cannot: the redirect handoff to Gate, cookie and session behaviour across a reload, and each framework integration wiring the core SDK up correctly.

Six sample apps are exercised, each on its own port:

SamplePort
browser5173
react5174
vue5175
express3000
nextjs3001
nuxt3002

The samples/node/quickstart app has no UI and is spawned directly by its own spec.

Configure and Run

You need curl, jq, unzip, pnpm, and lsof on your PATH. One script does everything:

cd tests/e2e
./run-e2e.sh

Arguments pass through to Playwright, so run a single spec with:

./run-e2e.sh tests/react-quickstart/sign-in-out.spec.ts

The script owns the whole lifecycle. It downloads and starts a server, mints an admin token, imports the test applications, writes each sample's .env, starts all six apps, runs the tests, then stops the apps and restores any .env it replaced.

note

run-e2e.sh aborts if anything already answers on https://localhost:8090. Stop any server you started by hand before running it.

Set THUNDERID_VERSION to pin a specific server release instead of taking the latest:

THUNDERID_VERSION=1.0.1 ./run-e2e.sh

Configuration comes from defaults.env, copied to .env on the first run. Values in .env win, and defaults.env fills the gaps:

VariableDefault
SERVER_URLhttps://localhost:8090
ADMIN_USERNAME / ADMIN_PASSWORDadmin / admin
TEST_USER_USERNAMEe2e-test-user
TEST_USER_PASSWORDE2ePassword@123
BROWSER_APP_URLhttp://localhost:5173
REACT_APP_URLhttp://localhost:5174
VUE_APP_URLhttp://localhost:5175
EXPRESS_APP_URLhttp://localhost:3000
NEXTJS_APP_URLhttp://localhost:3001
NUXT_APP_URLhttp://localhost:3002

global-setup.ts fails the run and lists anything missing, so a partial .env surfaces immediately rather than midway through a spec.

Once a run has finished, pnpm report opens the HTML report and pnpm ui opens Playwright's interactive mode against an already-running server.

Writing Tests

Applications are declared, not created by hand. thunderid-config/sample-apps.yaml holds one entry per sample with a fixed application ID, imported through /import with upsert enabled. Add a sample by adding an entry there rather than clicking through the Console, so every contributor and CI provision the same thing.

The test user is different: global-setup.ts creates it through the API before the run and global-teardown.ts deletes it afterward. Teardown fails loudly if the delete does not succeed, so a leaked user surfaces as a failure rather than silently accumulating.

Tests use the page object model. Shared page classes live in pages/, and Playwright fixtures in fixtures/sample-apps/ expose one page object per sample. A spec asks for the fixture it needs and never constructs a page itself:

test('TC001: signs in with valid credentials', async ({reactQuickstartPage}) => {
await reactQuickstartPage.goto(appUrl);
await reactQuickstartPage.verifyHomePageLoaded();
await reactQuickstartPage.clickSignInButton();
await reactQuickstartPage.verifyLoginPageLoaded();
await reactQuickstartPage.login(username, password);
await reactQuickstartPage.verifyLoggedIn();
});

Specs are grouped one directory per sample under tests/, and each test name carries a TCnnn: identifier.

Put assertions about the login screen in the shared gate-login.page.ts, since every sample redirects to the same Gate DOM. The React, Vue, Next.js, and Nuxt samples share thunderid-web-sample.page.ts because they render the same markup; only the browser and Express samples need their own page objects.

Things to Know

  • The server uses a self-signed certificate. Playwright sets ignoreHTTPSErrors, and direct API calls go through an undici agent configured to accept it. A new HTTP call made outside those helpers fails certificate validation.
  • There is no Playwright webServer block. One backend and six sample apps are shared across the run, so the script starts them rather than Playwright.
  • Do not run a sample's own prepare-dev.cjs. It rewrites workspace:* dependencies to latest, which takes the sample off your local build.
  • Cleanup frees ports 8090, 5173-5175, and 3000-3002, and removes the downloaded server. A run interrupted with Ctrl+C may leave a port bound; rerun the script and it clears them.

Continuous Integration

pr-builder.yml runs on every pull request: an audit, dependency review, a build-lint-test job, and the end-to-end suite through the run-e2e-suite composite action. e2e-nightly.yml runs the same suite on a schedule at 18:30 UTC and uploads its report as an artifact.

Explore with AI

ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© Copyright Linux Foundation Europe.For web site terms of use, trademark policy and other project policies please see https://linuxfoundation.eu/en/policies.