This project demonstrates how Loadmill can automate testing for a classic maker-checker approval flow.
Roles:
- Maker – initiates a funds‑transfer request
- Checker – reviews the request and approves or rejects it
The demo consists of:
- A Node.js/Express backend with
@loadmill/node-recorderfor traffic capture - A React frontend with dashboards for both roles
MAKER-CHECKER-DEMO/
├── backend/ # Express API with Loadmill recorder
│ └── index.js
├── frontend/ # React app (Maker + Checker UI)
│ ├── public/
│ ├── src/
│ ├── build/ # Created after frontend build
│ └── package.json
├── package.json # Root-level dependencies and scripts
├── Procfile # Used by Heroku to launch the app
└── README.md
git clone <repository-url>
cd MAKER-CHECKER-DEMOInstall dependencies for both the root (backend) and frontend:
npm install
cd frontend && npm install
cd ..No separate
backend/package.jsonexists — backend dependencies are declared in the root.
To capture traffic with your own Loadmill app ID:
export LOADMILL_CODE=<your-loadmill-tracking-id>If not set, a public sample code is used (see backend/index.js).
Supported environment variables:
| Variable | Default | Purpose |
|---|---|---|
LOADMILL_CODE |
sample code | App ID from Loadmill → Recordings |
DEBUG |
– | Set to loadmill:* for verbose logs |
npm run dev- Backend runs at:
http://localhost:3001 - Frontend runs at:
http://localhost:3000(proxy setup to backend)
| Role | Username | Password |
|---|---|---|
| Maker | maker | maker1234! |
| Checker | checker | checker1234! |
- Maker logs in and submits a transfer (amount + recipient).
- The transfer shows as PENDING.
- Checker logs in to approve or reject.
- Both dashboards update — Checker view auto-refreshes every 5 seconds.
- All requests go through
expressRecorder, generating a Loadmill recording.
All data is in-memory only. Refreshing the app resets state.
| Method | Path | Description (Auth: token header) |
|---|---|---|
| POST | /api/login |
Get token |
| POST | /api/transfer/initiate |
Maker creates transfer |
| GET | /api/transfer/my |
Maker lists own transfers |
| GET | /api/transfer/pending |
Checker lists pending transfers |
| POST | /api/transfer/approve |
Checker approves transfer |
| POST | /api/transfer/reject |
Checker rejects transfer |
| GET | /api/transfer/:id |
Fetch single transfer (any user) |
| GET | /api/audit |
Simple audit log |
The backend uses @loadmill/node-recorder to capture all API traffic:
npm i @loadmill/node-recorder --saveconst { expressRecorder } = require('@loadmill/node-recorder');
app.use(
expressRecorder({
loadmillCode: process.env.LOADMILL_CODE,
notSecure: true,
cookieExpiration: 10 * 60 * 1000,
basePath: 'http://localhost:3000'
})
);To enable detailed logging:
DEBUG=loadmill:* npm run backendWhen deploying, the heroku-postbuild script runs:
cd frontend && npm install && npm run buildThis builds static frontend files into frontend/build.
The backend serves these static files using:
app.use(express.static(path.join(__dirname, '../frontend/build')));npm startThis runs node backend/index.js — and serves everything from a single Node process.
- Run through a full Maker → Checker flow, then check Loadmill → Recordings.
- Convert the captured session into a test using Loadmill’s visual editor.
- Parameterize fields like
amount,recipient, and add negative test cases (e.g. too large, rejected twice, etc.). - Localhost is supported for recording thanks to
notSecure: true.