@seedalina/test-client
v0.3.12
Published
Typed client for ordering and releasing Seedalina test data entities from Playwright (or any Node) test suites.
Readme
@seedalina/test-client
Typed client for ordering and releasing Seedalina test data entities from Playwright (or any Node) test suites.
Install
pnpm add -D @seedalina/test-clientUsage
import { SeedalinaClient } from '@seedalina/test-client';
const seedalina = new SeedalinaClient({
baseUrl: process.env.SEEDALINA_API_URL!, // e.g. "https://seedalina.internal/api"
token: process.env.SEEDALINA_TOKEN!, // a pre-obtained JWT bearer token
});
test('checkout with an overdue invoice', async ({ page }) => {
const order = await seedalina.orderAndWait({
templateKey: 'customer.with-overdue-invoice',
parameters: { country: 'CH' },
});
const customer = order.businessObjects[0].assets[0].data;
// ... use customer in the test ...
await seedalina.release(order.id);
});API
Orders
order(input)— places an order, returns immediately (statusREQUESTED/PROCESSING).getOrder(id)— fetches the current order state, including generated entities/assets once ready.orderAndWait(input, { timeoutMs?, pollIntervalMs? })— places an order and polls untilREADY, throwingSeedalinaOrderFailedErroronFAILEDorSeedalinaOrderTimeoutErrorpast the deadline (defaults: 30s timeout, 1s poll interval).executeOrder(orderId)— kicks off generation for an order that hasn't run yet.waitForOrder(orderId, { timeoutMs?, pollIntervalMs? })— polls an order you already have an id for (vs.orderAndWait, which places a new one).release(id)— marks the order as released so its test data can be cleaned up. Call this inafterEach/afterAllonce a test no longer needs the entity.businessObjectsFromOrder(order)— flattens an order'sbusinessObjects[].assets[].data.outputsinto plain camelCased records (pure helper, no API call).
Pulling pooled test data
For parametrized tests where you just want whatever Seedalina already has on hand, without placing a new order:
const users = await seedalina.getTestDataPool('test-user', 'qa');
for (const user of users) {
test(`logs in as ${user.username}`, async ({ page }) => { /* ... */ });
}getTestData(templateKey, variantKey, { lock?, newState?, consume? })— validates the variant exists on the template, then fetches the pooledNEWbusiness object for that exact variant and returns its real generated data (camelCased) pluslock()/release()/consume()/setStatus()lifecycle methods bound to it. Falls back to the template's static variant values (with no-op lifecycle methods) when the pool has nothing for that variant yet.getTestDataPool(templateKey, environmentKey, { status? })— fetches every pooled business object for a template/environment (defaultstatus: 'NEW'), flattened to plain camelCased data records.getTestDataObjectFromPool(templateKey, variantKey, status?)— fetches a single pooled object for a specific variant; returnsundefinedif none match.lockBusinessObject(id)/releaseBusinessObject(id)/consumeBusinessObject(id)/setBusinessObjectStatus(id, status)— direct lifecycle control by id.savePoolEntry(templateKey, variantKey, environmentKey, data, status?)— saves a plain object straight into the pool as a brand-new business object. No order parameters, no template steps, no stepKey —datais stored exactly as given, unvalidated against the template's properties (mismatched/missing keys are on the caller). PassvariantKey: undefinedfor no particular variant.statusdefaults to'NEW'.await seedalina.savePoolEntry( 'studiengang', 'Variant2', 'integration', { name: 'Computer Science', code: 'CS-101' }, 'NEW', );Not to be confused with the standalone
saveTestData()reporting function below —savePoolEntry()creates a new pool entry from any script;saveTestData()reports outputs into an order's existing business object/step from inside a Seedalina-launched executor script.
Static template variants (no pool involved)
Some templates are just fixed reference data — a set of login credentials, lookup rows — with no business-object pool at all (mark the template "No pool orders" in the editor). Read their variants: directly instead:
const users = await seedalina.getBOAllVariants('user');
const admin = await seedalina.getBOVariant('user', 'AC5-Admin');
const fallback = await seedalina.getBOVariant('user'); // template's base property defaultsgetBOAllVariants(templateKey)— every variant on the template, flattened to plain camelCased records;idis the variant key (not a business object id).getBOVariant(templateKey, variantKey?)— one variant by key, or the template's baseproperties[].defaultvalues whenvariantKeyis omitted. Returnsundefinedwhen the key doesn't match any variant.
All methods throw SeedalinaApiError (with a status field) on non-2xx responses.
Reporting from executor scripts
When a script is launched by Seedalina (template step executor: playwright), the runner injects short-lived env vars (SEEDALINA_API_URL, SEEDALINA_JWT_TOKEN, SEEDALINA_BUSINESS_OBJECT_ID, etc.) — there's no client to construct yet, so these are standalone functions:
import { saveTestData, seedParams, shouldSaveTestData } from '@seedalina/test-client';
const { country } = seedParams<{ country: string }>();
// ... generate data ...
await saveTestData({ username, password, customerId });seedParams<T>()— parsesSEEDALINA_PARAMS(templatescriptParams) as JSON.shouldSaveTestData()—trueonly when the script was launched by Seedalina (SEEDALINA_REPORT === 'true').saveTestData(outputs, { status?, force? })— reports generated outputs back to Seedalina. Silent no-op when run standalone (npx playwright test), so scripts work unchanged in both contexts. Pass{ force: true }to report even whenSEEDALINA_REPORTisn't"true"—SEEDALINA_BUSINESS_OBJECT_ID/SEEDALINA_STEP_KEYare still required;forceonly bypasses the on/off switch, not the destination.
Auth
This client expects a pre-obtained JWT — it does not perform login itself. How you obtain that token (service account, CI secret, etc.) is up to your pipeline.
