E2E Testing
Writing Tests

Writing Tests

E2E tests use Playwright Test (opens in a new tab) format with ShellApps-specific fixtures.

Basic Test

import { test, expect } from '@shellapps/e2e';
 
test('user can sign in', async ({ page }) => {
  await page.goto('https://auth.shellapps.com/login');
  await page.fill('[name="email"]', 'test@example.com');
  await page.fill('[name="password"]', 'password123');
  await page.click('button[type="submit"]');
 
  await expect(page).toHaveURL(/\/dashboard/);
  await expect(page.locator('h1')).toContainText('Welcome');
});

ShellApps Fixtures

The @shellapps/e2e package provides custom fixtures:

authenticatedPage

A page already signed in with a test account:

import { test, expect } from '@shellapps/e2e';
 
test('dashboard loads widgets', async ({ authenticatedPage: page }) => {
  await page.goto('https://experience.shellapps.com/dashboard');
  await expect(page.locator('.widget-grid')).toBeVisible();
});

testProfile

A fresh test profile for isolated testing:

test('profile switching', async ({ authenticatedPage: page, testProfile }) => {
  await page.goto('https://auth.shellapps.com/profiles');
  await expect(page.locator(`text=${testProfile.displayName}`)).toBeVisible();
});

testGroup

A test group with configurable members:

test('group permissions', async ({ authenticatedPage: page, testGroup }) => {
  await page.goto(`https://auth.shellapps.com/groups/${testGroup.id}`);
  await expect(page.locator('.members-list')).toBeVisible();
});

Visual Regression

Use toHaveScreenshot for visual comparisons:

test('dashboard visual', async ({ authenticatedPage: page }) => {
  await page.goto('https://experience.shellapps.com/dashboard');
  await page.waitForLoadState('networkidle');
 
  await expect(page).toHaveScreenshot('dashboard.png', {
    maxDiffPixelRatio: 0.01,
    fullPage: true,
  });
});

Update baselines:

npx @shellapps/e2e-cli run --suite visual --update-snapshots

Assertions

Common assertions for ShellApps tests:

// Page loaded without errors
await expect(page.locator('.error-boundary')).not.toBeVisible();
 
// Design system components rendered correctly
await expect(page.locator('[data-testid="theme-provider"]')).toHaveAttribute(
  'data-mode',
  'dark'
);
 
// Auth state
await expect(page.locator('[data-testid="user-menu"]')).toContainText('Alex');
 
// API response
const response = await page.waitForResponse('**/api/v1/**');
expect(response.status()).toBe(200);

Test Organisation

tests/
├── smoke/
│   ├── auth.spec.ts          # Login, logout, registration
│   ├── navigation.spec.ts    # Core navigation flows
│   └── dashboard.spec.ts     # Dashboard functionality
├── regression/
│   ├── experience/
│   │   ├── pages.spec.ts
│   │   └── editor.spec.ts
│   └── auth/
│       ├── profiles.spec.ts
│       └── groups.spec.ts
├── visual/
│   ├── dashboard.spec.ts
│   └── components.spec.ts
└── fixtures/
    └── index.ts              # Custom fixture definitions

Configuration

// playwright.config.ts
import { defineConfig } from '@shellapps/e2e';
 
export default defineConfig({
  target: 'https://experience.shellapps.com',
  retries: 2,
  workers: 4,
  browsers: ['chromium', 'firefox'],
  reporter: [['html'], ['@shellapps/e2e-reporter']],
});

Related


© 2026 Shell Technology. All rights reserved.