Skip to content

Testing

github-actions[bot] edited this page Jun 27, 2026 · 1 revision

Testing

Two levels of testing are provided: unit tests (Vitest, always run in CI) and E2E browser tests (Playwright, run locally against a live VM).


Unit Testing

Setup

The package ships a Vitest setup file that configures jsdom and installs jest-dom matchers. Reference it from your plugin's vitest.config.ts (handled automatically when you extend the base config):

import { createVitestConfig } from "@rxtx4816/cockpit-plugin-base-react/vitest.config.base";
export default createVitestConfig();

Test utilities

import { mockCockpit, mockHttpClient } from "@rxtx4816/cockpit-plugin-base-react/testing/helpers";

mockCockpit

Returns an in-memory mock of the cockpit browser global. Stubs out cockpit.spawn, cockpit.file, cockpit.http, and channel creation so tests never attempt real system calls.

beforeEach(() => {
  vi.stubGlobal("cockpit", mockCockpit());
});

Individual spawn calls can be configured to return specific output or to reject, letting you test both success and error paths.

mockHttpClient

Returns a mock of the Cockpit HTTP client with configurable per-path responses. Useful for testing components that call cockpit.http().get(path).

const client = mockHttpClient({ "/api/status": '{"running": true}' });

get, post, and request are all vi.fn() instances, so you can assert call counts and arguments with standard Vitest matchers.

Running unit tests

npm test            # single run
npm run test:watch  # watch mode

E2E Testing (Playwright)

Browser tests that drive a real Chromium instance against a running QEMU VM. They cover login, navigation, and actual UI interactions — the things unit tests cannot reach.

These tests do not run in CI. They require a VM to be running locally first. See VM Testing for how to start one.

What the base library provides

@rxtx4816/cockpit-plugin-base-react/playwright.config.base exports createPlaywrightConfig(pluginName, overrides?). It sets:

  • baseURL from BASE_URL env var (default: https://localhost:9090)
  • ignoreHTTPSErrors: true — VMs use a self-signed certificate
  • testDir: './e2e'
  • retries: 1, screenshot and video saved on failure
  • Single Chromium project using Desktop Chrome device settings

@rxtx4816/cockpit-plugin-base-react/e2e exports the pluginPage fixture and expect. The fixture:

  1. Navigates to / (the Cockpit login page)
  2. Fills in credentials from VM_USER / VM_PASSWORD env vars (defaults: test / test)
  3. Submits the login form and waits for the Cockpit shell to load
  4. Navigates to /cockpit/@localhost/<pluginName>/index.html
  5. Hands the authenticated page to your test

Setting up in a consumer plugin

1. Install and download Chromium (one-time):

npm install --save-dev @playwright/test
npx playwright install chromium

2. Create playwright.config.ts in your project root.

Pass one VmDefinition entry per VM defined in scripts/test-vm.config.sh. Ports are assigned sequentially from COCKPIT_BASE:

import { createPlaywrightConfig } from '@rxtx4816/cockpit-plugin-base-react/playwright.config.base';

export default createPlaywrightConfig('your-plugin-name', [
  { name: 'arch',   port: 9090 },
  { name: 'debian', port: 9091 },
  { name: 'fedora', port: 9092 },
]);

Each VM becomes a separate Playwright project. Keep the names in sync with ALL_VMS in your test-vm.config.sh.

3. Add npm scripts to package.json:

"test:e2e":        "playwright test",
"test:e2e:ui":     "playwright test --ui",
"test:e2e:codegen":"playwright codegen"

4. Add to .gitignore:

test-results/
playwright-report/

Writing tests

Put test files under e2e/. Import test and expect from the base package so every test gets the pluginPage fixture automatically:

import { test, expect } from '@rxtx4816/cockpit-plugin-base-react/e2e';

test('dashboard renders', async ({ pluginPage: page }) => {
  await expect(page.getByRole('heading', { name: 'My Plugin' })).toBeVisible();
});

Use pluginPage instead of the built-in page fixture — it's identical except it's already logged in and on your plugin's page.

Adding custom fixtures

Extend the provided test to layer in your own fixtures:

import { test as base, expect } from '@rxtx4816/cockpit-plugin-base-react/e2e';

export const test = base.extend<{ stackName: string }>({
  stackName: async ({}, use) => {
    await use('gotify');
  },
});
export { expect };

Then import from your local file instead of the base package.

Running E2E tests

Each VM is a Playwright project. Use --project to select which VM(s) to test:

# Start one or more VMs first
npm run vm start arch-podman && npm run vm wait arch-podman

# Run against a specific VM (Playwright --project flag)
npm run test:e2e -- --project=arch-podman

# Run against multiple VMs
npm run test:e2e -- --project=arch-podman --project=debian-podman

# Run against all defined VMs (all must be running)
npm run test:e2e

# Visual runner — shows every step, great for debugging
npm run test:e2e:ui

# Record a new test interactively (pass BASE_URL to target a specific VM)
BASE_URL=https://localhost:9090 npm run test:e2e:codegen

Check which VMs are up before running:

npm run vm status

Targeting a VM by URL

Use BASE_URL to bypass the project list entirely and target one specific VM:

BASE_URL=https://localhost:9094 npm run test:e2e   # single VM, any port

This creates a single "custom" project regardless of how many VMs are defined in the config.

Environment variables

Variable Default Description
BASE_URL (from vm list) Override: target a single VM by URL
VM_USER test Login username
VM_PASSWORD test Login password

Clone this wiki locally