Skip to content

Test Fixtures ​

Custom Playwright fixtures for RHDH testing.

Import ​

typescript
import { test, expect } from "@red-hat-developer-hub/e2e-test-utils/test";

Fixtures ​

rhdh ​

Scope: Worker

Type: RHDHDeployment

Shared RHDH deployment across all tests in a worker. deploy() automatically skips if the deployment already succeeded, even after worker restarts.

typescript
test.beforeAll(async ({ rhdh }) => {
  await rhdh.configure({ auth: "keycloak" });
  await rhdh.deploy();
});

test("access rhdh", async ({ rhdh }) => {
  console.log(rhdh.rhdhUrl);
  console.log(rhdh.deploymentConfig.namespace);
});

uiHelper ​

Scope: Test

Type: UIhelper

UI interaction helper for Material-UI components.

typescript
test("ui interactions", async ({ uiHelper }) => {
  await uiHelper.verifyHeading("Welcome");
  await uiHelper.clickButton("Submit");
  await uiHelper.openSidebar("Catalog");
});

loginHelper ​

Scope: Test

Type: LoginHelper

Authentication helper for various providers.

typescript
test.beforeEach(async ({ loginHelper }) => {
  await loginHelper.loginAsKeycloakUser();
});

test.afterEach(async ({ loginHelper }) => {
  await loginHelper.signOut();
});

baseURL ​

Scope: Test

Type: string

Automatically set to the RHDH instance URL.

typescript
test("using baseURL", async ({ page, baseURL }) => {
  console.log(`Base URL: ${baseURL}`);
  // page.goto("/") uses this automatically
  await page.goto("/");
});

test.runOnce ​

typescript
test.runOnce(key: string, fn: () => Promise<void> | void): Promise<boolean>

Executes fn exactly once per test run, even across worker restarts. Returns true if executed, false if skipped.

TIP

rhdh.deploy() already uses runOnce internally, so you don't need to wrap simple deployments. Use test.runOnce when you have additional expensive operations (external services, scripts, data seeding) alongside deploy().

ParameterTypeDescription
keystringUnique identifier for this operation, across every spec file and every project in the run
fn() => Promise<void> | voidFunction to execute once

One key, two projects

The flag file is keyed on the key string alone, in a directory shared by every project in the run. When one spec runs in two projects, the first project's setup satisfies the second, and the second silently skips its own. End the key with ${rhdh.deploymentConfig.namespace} whenever the setup belongs to one project, the way deploy() does internally. A literal key is correct only when the setup really is shared by every project.

typescript
// Wrap pre-deploy setup that shouldn't repeat
test.beforeAll(async ({ rhdh }) => {
  await test.runOnce(`full-setup-${rhdh.deploymentConfig.namespace}`, async () => {
    await $`bash deploy-external-service.sh`;
    await rhdh.configure({ auth: "keycloak" });
    await rhdh.deploy(); // safe to nest, has its own internal protection
  });
});

See Deployment Protection and test.runOnce for details.

Exported Types ​

typescript
import type { Page, BrowserContext, Locator } from "@red-hat-developer-hub/e2e-test-utils/test";

Re-exports all Playwright types for convenience.

Complete Example ​

typescript
import { test, expect } from "@red-hat-developer-hub/e2e-test-utils/test";

test.describe("My Tests", () => {
  test.beforeAll(async ({ rhdh }) => {
    await rhdh.configure({ auth: "keycloak" });
    await rhdh.deploy();
  });

  test.beforeEach(async ({ page, loginHelper }) => {
    await page.goto("/");
    await loginHelper.loginAsKeycloakUser();
  });

  test("verify heading", async ({ uiHelper }) => {
    await uiHelper.verifyHeading("Red Hat Developer Hub");
  });

  test("navigate to catalog", async ({ page, uiHelper }) => {
    await uiHelper.openSidebar("Catalog");
    await expect(page).toHaveURL(/.*catalog/);
  });
});

Released under the Apache-2.0 License.