Skip to content

E2E Testing ​

End-to-end tests for the spread app using Playwright. Tests run against a real backend with a dedicated test workspace.

Prerequisites ​

ServiceHow to start
PostgreSQL + RabbitMQcd schemastack-be && docker-compose up -d
Backendcd schemastack-be && ./mvnw quarkus:dev
Frontendcd schemastack-fe && npx ng serve app

First-Time Setup ​

Run the setup script once to create the test database, user, organisation, and workspace:

bash
cd schemastack-fe
bash e2e/setup.sh

This will:

  1. Create an e2e_test PostgreSQL database (via docker exec)
  2. Seed it with 5 tables covering all relationship types (authors, books, tags, book_tags, book_details)
  3. Register a test user (e2e-test@schemastack.io) and verify their email
  4. Create an organisation (e2e-test-org) and workspace (e2e-workspace)
  5. Trigger a schema sync (creates 5 views)
  6. Write .env.e2e with all configuration

The setup is idempotent — safe to re-run if the database or workspace already exists.

Running Tests ​

bash
# Load environment and run all E2E tests (Chromium only)
source .env.e2e && npx playwright test --project chromium

# Run a specific test suite
source .env.e2e && npx playwright test relationships.spec.ts --project chromium

# Run with browser visible
source .env.e2e && npx playwright test --project chromium --headed

# Run in interactive UI mode
source .env.e2e && npx playwright test --ui

# Run across all browsers (Chromium, Firefox, WebKit, Brave)
source .env.e2e && npx playwright test

# View the HTML test report
npx playwright show-report

WARNING

Always source .env.e2e before running tests. Without it, tests use fallback credentials that won't match your setup.

Test Suites ​

SuiteFileTestsWhat it covers
Relationshipsrelationships.spec.ts21ManyToOne, OneToMany, M2M, column types, sort, filter, add row, inline editing, selection, infinite scroll
Constraintsconstraints.spec.ts11NOT_BLANK, MIN/MAX, EMAIL, URL, numeric, date, entity-level, unique
Permissionspermissions.spec.ts11View toggles (addable/editable/sortable), toolbar, selection, bulk bar, properties panel
Filter & Sortfilter-sort.spec.ts11ASC/DESC sort, add/remove filter, presets, conditional styles
Schema Opsschema-ops.spec.ts10Column display, drag reorder, resize, properties, view tabs
Bulk Operationsbulk-operations.spec.ts5Selection, bulk delete, export, edit
Import/Exportimport-export.spec.ts8CSV import, export formats, SSE, theme switching

Test Data ​

The setup script seeds the e2e_test database with these tables:

authors         (id, name, email, bio, active, created_at)
    ↑
books           (id, title, isbn, author_id FK, pages, price, published_date, ...)
    ↕
book_tags       (book_id, tag_id)  — junction table
    ↓
tags            (id, name, color)

book_details    (id, book_id UNIQUE FK, edition, publisher, language, weight_grams)

This covers:

  • ManyToOne: books.author_id → authors.id
  • OneToMany: authors → books (reverse)
  • ManyToMany: books ↔ tags via book_tags
  • OneToOne: book_details.book_id → books.id (unique FK)
  • Nullable FK: one book has author_id = NULL
  • All column types: VARCHAR, TEXT, INTEGER, DECIMAL, BOOLEAN, DATE, TIMESTAMP, UUID

Architecture ​

API Client (e2e/helpers/api.ts) ​

A Playwright APIRequestContext-based client that authenticates via POST /api/auth/login-with-org and provides methods for CRUD, schema ops, and test data management. Used in beforeAll to set up test state.

Spread Auth (e2e/helpers/spread-auth.ts) ​

Injects the JWT token into localStorage and navigates directly to a view URL, bypassing the login UI for speed. Each test gets a fresh page context.

Configuration (e2e/helpers/test-config.ts) ​

Reads from environment variables with sensible defaults:

VariableDefaultPurpose
E2E_API_URLhttp://localhost:8080Backend API
E2E_BASE_URLhttp://localhost:4200Frontend app
E2E_USER_EMAILe2e-test@schemastack.ioTest user
E2E_USER_PASSWORDE2eTestPassword123!Test password
E2E_ORG_SLUGe2e-test-orgOrganisation
E2E_WORKSPACE_SLUGe2e-workspaceWorkspace

Test Resilience ​

Tests use test.skip() when required features aren't available (e.g., no M2M columns, not enough rows for infinite scroll). This means the same tests work against any workspace — they skip gracefully instead of failing.

Writing New Tests ​

typescript
import { test, expect } from '@playwright/test';
import { TestApi } from './helpers/api';
import { loginToSpread } from './helpers/spread-auth';
import { testConfig } from './helpers/test-config';

let api: TestApi;

test.beforeAll(async () => {
  api = new TestApi(testConfig.apiUrl, testConfig.user);
  await api.login(testConfig.orgSlug);
});

test.afterAll(async () => {
  await api.dispose();
});

test('my test', async ({ page }) => {
  const views = await api.listViews(testConfig.orgSlug, testConfig.workspaceSlug);
  test.skip(!views?.length, 'No views available');

  await loginToSpread(page, api, {
    orgSlug: testConfig.orgSlug,
    workspaceSlug: testConfig.workspaceSlug,
    viewSlug: views[0].slug,
  });

  // Wait for data to load
  await page.waitForSelector('.data-row', { timeout: 15000 });

  // Your assertions here
  expect(await page.locator('.data-row').count()).toBeGreaterThan(0);
});

Tips ​

  • Don't use networkidle — SSE connections keep the network active, causing timeouts
  • Use test.skip() for features that depend on schema — makes tests portable across workspaces
  • Seed data via API in beforeAll, not via UI — faster and more reliable
  • Use --headed when debugging — watch the browser interact with the app
  • Use --ui for interactive debugging — step through tests, inspect DOM snapshots
  • Check screenshots on failure — saved in test-results/ with traces

SchemaStack Internal Developer Documentation