first commit
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
# Audit log
|
||||
|
||||
## Purpose
|
||||
|
||||
`AuditLog` is the request-recorder that backs the `lastRequest()` and
|
||||
`allRequests()` accessors on the mock IdP handle. Every HTTP request the
|
||||
server processes is captured as a frozen `AuditRecord` and appended to
|
||||
the log in serve-order. Tests can then assert on the recorded headers,
|
||||
query string, body, and ordering without re-running the flow.
|
||||
|
||||
The records are deep-frozen at insertion time so audit consumers cannot
|
||||
accidentally mutate captured state through their assertions.
|
||||
|
||||
## Features
|
||||
|
||||
- Frozen `AuditRecord` snapshots with method, path, headers, query,
|
||||
body, and `at` (millisecond epoch) timestamp.
|
||||
- `last()` returns the most recently appended record or `undefined`.
|
||||
- `all()` returns a frozen shallow-copy snapshot of the records array,
|
||||
preserving insert-order iteration.
|
||||
- `clear()` resets the log between scenarios.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { AuditLog } from "@suaveplan/testing-integration-oauth-mock/control";
|
||||
|
||||
const log = new AuditLog();
|
||||
log.push({ method: "GET", path: "/authorize", headers: {}, query: {}, body: "", at: Date.now() });
|
||||
log.last();
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
When asserting flows that involve multiple requests, snapshot the whole
|
||||
array up front and walk it deterministically rather than calling
|
||||
`last()` repeatedly:
|
||||
|
||||
```ts
|
||||
const events = log.all();
|
||||
expect(events.map((e) => `${e.method} ${e.path}`)).toEqual([
|
||||
"GET /authorize",
|
||||
"POST /token",
|
||||
"GET /userinfo",
|
||||
]);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `interface AuditRecord` — `{ method, path, headers, query, body, at }`,
|
||||
all read-only and frozen.
|
||||
- `class AuditLog`
|
||||
- `push(record: AuditRecord): void`
|
||||
- `last(): AuditRecord | undefined`
|
||||
- `all(): readonly AuditRecord[]`
|
||||
- `clear(): void`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`push` performs an `Object.freeze` not only on the record itself but on
|
||||
the nested `headers` and `query` objects, because callers can legally
|
||||
hold the input object and mutate it post-push otherwise. `all()` returns
|
||||
a frozen *copy* via `slice()` so the public snapshot can never reach
|
||||
back into the internal array — preventing test mutations from corrupting
|
||||
later assertions.
|
||||
Reference in New Issue
Block a user