Capturing the service documentation
A service's documentation is produced by its own journey. While the journey runs, it captures a screenshot of each step, the issued documents, the payment and the notifications. The kit then writes a Markdown document and a Word document from the standard template. Because the documentation is regenerated by the same run that tests the service, it never drifts from the software.
The capture calls
Create one capture object per service at the top of the spec:
const { serviceDocs } = require('./support/serviceDocs');
const docs = serviceDocs(test, { service: () => examplePermit(), mda: 'EXAMPLE', key: 'example-vendor-permit' });
Options: service returns the service (its id is enough: the name, owner and summary are read from the public service API); mda and key override the folder names; when: { topology: 'federated' } captures only in that topology, for a node's service.
Then, in the tests:
| Call | Captures |
|---|---|
docs.step(page, { actor, title, description }) | A numbered step with screenshots |
docs.step(page, { ..., section: 'payment' }) | A step shown in the Payment section |
docs.payment([['Invoice number', inv], ['Amount', 'ZMW 250.00']]) | Payment facts |
docs.output(pdfBuffer, { title, fields, seal, verification }) | An issued document: an image of its first page, its fields, seal and verification |
docs.notifications(list) | The notices the run produced (docsData.js reads them for a case) |
docs.meta({ eligibility, legacy }) | Facts the service API does not hold, such as the legacy mapping |
Step options: focus scrolls an element into view before the screenshot; hide blanks elements by CSS selector, for example a test double's placeholder (say so in the description).
Write each step's description in plain English for a reader who has never seen the service: what the person does and what they see. For example: "The citizen opens My Workplace, which lists the application with the status Received."
Capture is off by default. Unless E2E_SERVICE_DOCS=1 is set, every docs.* call returns at once, so ordinary test runs are not slowed down. npm run docs:services sets it for you.
Screenshots at two widths
- Every step gets a desktop screenshot.
- Every citizen step also gets a 375 px screenshot, automatically. Officer steps in the back office are
desktop only.
- Each issued document gets an image of its first page.
The capture refuses to run unless the stack is the local e2e stack with the kit's seeded @example.test accounts. This is a safeguard: documentation images must only ever show synthetic data from a local test installation.
Registering and generating
Register the service in docs/services/services.json:
{
"mda": "EXAMPLE",
"key": "example-vendor-permit",
"title": "Example Vendor Permit",
"kind": "permit: apply, inspection, fee, approval, sealed permit",
"topology": "combined",
"profile": "mihud",
"specs": ["48-example-permit.spec.js"]
}
Then generate:
npm run docs:services -- --only example-vendor-permit # one service, on a fresh stack
npm run docs:services # every documented service
npm run docs:services -- --use-running # on a stack you started with npm run stack
npm run docs:check # no run: published docs complete, journeys passed
docs:services starts a fresh stack per topology (so reference numbers start at 00001 and differences stay small), runs the journeys with capture on, and publishes a service's folder only when all its journeys passed and its documentation is complete: every step image, a 375 px image for each citizen step, and a .docx with every placeholder filled. If any journey fails, the command exits with code 1 and the old folder stays as it was. Documentation whose issued documents came from the LibreOffice stand-in is not published either.
Several spec files can document one service; they add to the same capture in file order.
The folder it produces
docs/services/EXAMPLE/example-vendor-permit/
screenshots/
01-find-the-service-desktop.png
01-find-the-service-mobile.png
02-review-the-application-desktop.png
doc-01-vendor-permit-sealed-pdf.png
example-vendor-permit.md
example-vendor-permit.docx
capture.json
capture.json holds what the run recorded: the service summary, the run's topology and seed profile, the commits of each application, the steps (actor, title, description, view, images, spec), the outputs, the payment, the notifications (recipients masked) and each test's result. Both documents are generated from it.
The standard template
The Word document is filled from docs/services/_template/service-template.docx (and the Markdown from service-template.md). The template decides the look and the order of sections; the generator only writes content into marked places. The sections are fixed:
- Service summary: owner MDA, purpose, eligibility, fees, turnaround, required documents.
- Application process, step by step, with screenshots, for the citizen and each officer role.
- Payment.
- Output documents: an image of each, its fields, seal and verification.
- Notifications.
- Legacy mapping, when the service replaces a legacy service.
- Version and date: the service version, the platform snapshot, the journeys and their results.
The cover page states that all data is synthetic.
Fix the source, not the output
Never edit a generated document. If something is wrong:
| Problem | Fix |
|---|---|
| Summary wrong or empty (purpose, fees, documents) | The service's configuration in the back office |
| A step's wording or screenshot | The journey's docs.step call |
| Layout, fonts, section headings | The template (in Word, or in code with npm run docs:template), then regenerate |
Check your understanding
- Why does
docs.stepdo nothing in an ordinarynpm run e2e? - Which steps get a 375 px screenshot?
- Where does the service summary in the documentation come from, and how do you correct it?
- Under which conditions does
docs:servicespublish a service's folder? - What four kinds of file does a published service folder contain?
- Name the seven sections of the standard template.
Sign in to record your progress.
Previous: Writing a journey spec Next: The service status list and publishing