@przeslijmi/real-fake-data-playwright
v0.1.0
Published
Playwright fixtures for Real Fake Data — seeded, realistic Polish test data (PESEL, NIP, REGON, IBAN, addresses, companies, people, vehicle plates).
Downloads
205
Maintainers
Readme
@przeslijmi/real-fake-data-playwright
Playwright fixtures for Real Fake Data — realistic, synthetic Polish test data with one line per record: valid PESELs (correct checksums), NIPs, REGONs, IBANs, addresses drawn from real cities and streets, people, company names, and vehicle plates.
Output looks real but is fake — safe for staging, demos, and seed data.
- Seeded and reproducible by default. Each test derives a stable seed from its title, so a failing test replays the exact same data on the next run — no flakiness, trivial repro.
- Typed end to end. One method per generator, fully typed inputs and results.
- Zero ceremony. A
fakeDatafixture; no manual client wiring.
Install
npm install -D @przeslijmi/real-fake-data-playwright
# or: pnpm add -D @przeslijmi/real-fake-data-playwrightRequires @playwright/test (peer dependency) and Node 18+ (for global fetch).
Quick start
Point the fixture at a Real Fake Data API instance, then pull data inside any test:
import { test, expect } from '@przeslijmi/real-fake-data-playwright';
test.use({ realFakeData: { baseUrl: 'https://api.real-fake-data.example' } });
test('registers a new customer', async ({ page, fakeData }) => {
const person = await fakeData.person({ sex: 'f' });
await page.goto('/signup');
await page.getByLabel('First name').fill(person.name);
await page.getByLabel('Surname').fill(person.surname);
await page.getByLabel('PESEL').fill(person.pesel);
await page.getByRole('button', { name: 'Create account' }).click();
await expect(page.getByText(person.surname)).toBeVisible();
});test and expect are the standard Playwright exports, extended with the fakeData fixture — use them exactly as you would @playwright/test.
Configuration
Set options with test.use({ realFakeData: { … } }), at any scope (file, describe, or project, via your Playwright config).
| Option | Type | Description |
| --------- | ------------------------ | ------------------------------------------------------------------------------------------------------- |
| baseUrl | string (required) | Base URL of the Real Fake Data API, e.g. https://api.example.com. |
| seed | number | Base seed for the test. Omit to derive a stable seed from the test title (reproducible-by-default). |
| headers | Record<string, string> | Extra headers sent with every request (e.g. an API key once your plan requires one). |
Determinism
With a base seed in play, the Nth call within a test uses seed + N — so calls are reproducible across runs yet distinct from one another. Because the default seed comes from the test title, every test is already deterministic without configuring anything; set seed explicitly only when you want to pin a test to a known fixed dataset.
test.use({ realFakeData: { baseUrl, seed: 42 } }); // pin this file to a fixed datasetGenerators
Every method returns a typed result and accepts optional constraints. Pass seed on any call to override that call's automatic seed.
| Method | Returns | Common options |
| --------------------------------- | ------------------------------------------------------------ | --------------------------------------------------------------------- |
| fakeData.pesel(opts?) | { value, birthDate, sex } | sex, atAge, olderThan, youngerThan, bornOn/Before/After, invalid |
| fakeData.person(opts?) | { name, surname, initials, birthDate, pesel } | same as pesel |
| fakeData.address(opts?) | { buildingNumber, postalCode, cityName, …, terytCodes } | teryt (1–7 digit prefix) |
| fakeData.nip(opts?) | { value, digits } | format, invalid |
| fakeData.iban(opts?) | { value, electronicFormat, bankCode, bankName } | format, bankCode, bankName, invalid |
| fakeData.regon(opts?) | { value, variant } | variant (short/long/any), invalid |
| fakeData.companyName(opts?) | { value, legalForm, strategy } | strategy, legalForm, activityPrefix |
| fakeData.vehicleRegistration(opts?) | { value, prefix, individualPart, type, … } | type, voivodeship, county, format |
Testing your validators
Every checksum generator accepts invalid: true to produce a value with a deliberately wrong check digit (the rest stays well-formed) — for asserting that your own validators reject bad input:
const bad = await fakeData.nip({ invalid: true });
await expect(submitNip(bad.value)).rejects.toThrow('invalid checksum');Error handling
A non-2xx API response throws a RealFakeDataError carrying status (HTTP code), code (the API's machine error code), and details (per-field validation messages):
import { RealFakeDataError } from '@przeslijmi/real-fake-data-playwright';
try {
await fakeData.address({ teryt: 'not-digits' });
} catch (error) {
if (error instanceof RealFakeDataError) {
console.log(error.status, error.code, error.details);
// 400 'VALIDATION_ERROR' [{ path: 'teryt', message: 'teryt must be 1–7 digits' }]
}
}Advanced: using the client without the fixture
The fixture is a thin wrapper over a provider and a facade you can use directly — handy in global setup, scripts, or non-Playwright code:
import { CloudFakeDataProvider, createFakeData } from '@przeslijmi/real-fake-data-playwright';
const provider = new CloudFakeDataProvider({ baseUrl: 'https://api.example.com' });
const fakeData = createFakeData(provider, { seed: 42 });
const company = await fakeData.companyName({ legalForm: 'S.A.' });The FakeDataProvider interface is the swap point: the cloud provider talks HTTP to the hosted API, and the same facade can run against other backends.
License
MIT
