DOCUMENTATION

Playwright integration

Playwright and Seedalina meet in two directions. Your tests can call Seedalina through @seedalina/test-client to fetch or claim data, and Seedalina can run your scripts as template steps (executor: playwright) to generate data through the real UI. Both use the same npm package — see the test client reference for every method signature.

Pick the right pattern first

Four mechanisms involve "template values" and a web form. Picking the wrong one pollutes the pool or claims the wrong entity, so decide before writing code:

| Pattern | Use when | Key calls | |---------|----------|-----------| | A — Static reference data | The template is fixed rows (logins, lookup values) with no pool | getBOVariant(), getBOAllVariants() | | B — Order-driven generation | Seedalina launches your script to create data via the UI | seedParams(), saveTestData() | | C — Claim from the pool | The test needs an entity that already exists | getTestDataObjectFromPool(), lockBusinessObject(), releaseBusinessObject(), consumeBusinessObject() | | D — Plain save | Your script already has a finished object and just wants it pooled | savePoolEntry() |

A — Read static variants

For reference templates (no pool involved), read the variant values directly and use them. There is nothing to save, lock, or consume.

const admin = await seedalina.getBOVariant('user', 'AC5-Admin');
await page.locator('#username').fill(String(admin.username));
await page.locator('#password').fill(String(admin.password));

B — Generate through the UI, report back

When a template step declares executor: playwright, ordering the template makes Seedalina check out your script repo, resolve the step's scriptParams, and run the script with everything injected as environment variables. Whatever the script reports lands in the entity pool.

import { seedParams, saveTestData } from '@seedalina/test-client';

test('generate a user through the registration UI', async ({ page }) => {
  const seed = seedParams<{ firstName?: string; email?: string }>();
  const email = seed.email ?? `standalone.${Date.now()}@example.test`;

  // ... drive the registration form with the seed values ...
  const userId = await page.locator('[data-testid="user-id"]').textContent();

  // Report only what the system actually produced. Silent no-op when the
  // script is run standalone with npx playwright test.
  await saveTestData({ userId, email });
});

Template scriptParams can draw on synthetic values ({{safe.*}}), order parameters ({{parameters.*}}), earlier step outputs ({{outputs.*}}), and the ordered variant's values ({{variant.*}}).

C — Claim an existing entity

When the test only needs an entity that is already on the shelf, claim it from the pool, lock it if parallel runs might collide, and put it back — or consume it if the test used it up for good.

const user = await seedalina.getTestDataObjectFromPool('test-user', 'support');
await seedalina.lockBusinessObject(user.id);

// ... run the test ...

await seedalina.releaseBusinessObject(user.id);   // reusable
// or: await seedalina.consumeBusinessObject(user.id);  // used up

D — Push a finished object into the pool

No template steps, no order — one call stores an object you already have:

await seedalina.savePoolEntry('studiengang', 'Variant2', 'integration', {
  name: 'Computer Science',
  code: 'CS-101',
});

Environment variables

Orchestrated runs (pattern B) receive their context through short-lived environment variables — the same names you set manually for local runs:

| Variable | Purpose | |----------|---------| | SEEDALINA_API_URL | Base URL of your Seedalina instance's API. | | SEEDALINA_JWT_TOKEN | Bearer token for API calls. | | SEEDALINA_REPORT | true only when Seedalina launched the script — the switch behind saveTestData(). | | SEEDALINA_PARAMS | The resolved scriptParams, read via seedParams(). | | SEEDALINA_BUSINESS_OBJECT_ID / SEEDALINA_STEP_KEY | Which order step the report belongs to. | | SEEDALINA_TARGET_STATUS | Pool status for the reported entry (defaults to NEW). |

Failures in your script surface in the order's log with the script's own error output, so a broken generation run is diagnosed in Seedalina — not by re-running the pipeline blind.