Recording a demo of the application

The end-to-end suites double as the demo. Every backend spec drives a real Fineract through the real UI, so recording them produces a walkthrough of what the application actually does — rather than a separate demo script that would drift from it the first time a screen changed.

npm run e2e:stack        # bring up Fineract (add --fresh for a clean volume)
npm run demo:record

Videos land in demo-recordings/, one directory per test, each containing video.webm. The directory is git-ignored.

What the switches do

VariableEffect
DEMO_RECORD=1Records every spec, not only the ones that fail. Read in playwright.config.ts.
DEMO_SLOW_MOMilliseconds Playwright waits before each action — click, fill, navigation. Defaults to 450 while recording, 0 otherwise. This is what makes a recording followable: the pause lands on the action rather than on the film.
DEMO_BEAT_MSInserts a pause between steps, on top of the per-action pause. Cosmetic: nothing synchronises on it, so the specs are equally correct with it unset. Honoured by full-demo.spec.ts.
PLAYWRIGHT_OUTPUT_DIRWhere the recordings are written.

npm run demo:record sets these and runs the backend project with a single worker, so the recordings are in a sensible order rather than interleaved.

Why pacing is recorded rather than added afterwards

Slowing the footage in post stretches everything uniformly, which lengthens a recording without giving the eye anywhere to land — a slowed fast-forward is still a fast-forward. slowMo pauses before each action, so the beat falls where the interaction is. Once that is in the source, no post-processing slowdown is needed.

Per-test budgets have to follow. A test's own test.setTimeout overrides both the project and the root config, so a paced run would otherwise be cut off mid-flow and the clip would end on a frozen screen. Specs therefore wrap their budget in recordingTimeout() from e2e/fixtures.ts, which scales it while filming and returns it untouched otherwise. captureJson() sizes its response-capture window the same way.

Two practical notes:

  • Playwright clears outputDir at the start of every run. Re-recording a single spec into the same directory deletes every other clip. Use a separate PLAYWRIGHT_OUTPUT_DIR for one-off re-records.
  • Do not change the working tree while a recording is in flight. The dev server recompiles from source, so a checkout or rebase mid-run films a moving target.

What each recording shows

FlowSpec
Offices, loan products, a client, the full loan lifecycle, custom fields, collateral, disbursement details, notes, and a repayment that is adjustedfull-demo.spec.ts
Center detail view: activate, assign and unassign staff, attach and detach groups, schedule the weekly meeting, notescenter-servicing.spec.ts
Group membership and lifecyclegroup-membership.spec.ts
Client transfers between officesclient-transfer.spec.ts
Savings transaction correction — deposits, holds, releases and undosavings-transaction-correction.spec.ts
Term deposit servicing — lifecycle, transactions and undodeposit-account-servicing.spec.ts
Deposit product configurationdeposit-product-configuration.spec.ts
Product accounting — loan and share products mapped to the ledgerloan-product-accounting.spec.ts, share-product-accounting.spec.ts
Reporting — dynamic and cascading parameters, and chart reportsreport-parameter-backend.spec.ts
Loan servicing — charge-off, schedule type, account actionsloan-charge-off.spec.ts, loan-schedule-type.spec.ts, loan-account-actions.spec.ts, loan-servicing.spec.ts
Share account servicingshare-account-servicing.spec.ts
Teller cash managementteller-cash-management.spec.ts
Login and tenant selectionlogin.spec.ts

To record one flow on its own:

DEMO_RECORD=1 DEMO_BEAT_MS=900 npm run test:e2e:local -- e2e/center-servicing.spec.ts

Stitching the recordings together

Playwright writes one webm per test. Any player handles them individually; to concatenate them into a single file, ffmpeg will do it — it is not needed to record or to watch them:

find demo-recordings -name video.webm | sort | sed "s|^|file '$PWD/|;s|$|'|" > /tmp/demo-list.txt
ffmpeg -f concat -safe 0 -i /tmp/demo-list.txt -c copy demo.webm

The clips have no audio and no captions. They are a record of the flows working, not a produced video — if a narrated demo is needed, these are the raw material for it.