
Test fanout parsers with a runnable offline edge-case kit
Extract the kit, install locked dependencies with npm ci and run npm test. Sixteen parser and eleven export checks use original synthetic fixtures. Negative checks must reject bad input, not merely accept valid examples.
Use this before changing a parser or investigating an unclear import failure. After dependency installation, the kit works without network or provider keys.
Inspect your own result nextThe offline kit needs no API key. You can later inspect a separate bounded run in the free tool.Open the free toolRun an independent extracted copy
Check the tutorial using its download, not only a development checkout with dependencies already present. Extract the ZIP into a new folder. fanout-kit-v2 contains the README, parsers, tests, schema, validator, fixtures and lockfile. Installation needs package-registry access; subsequent checks stay offline.
npm test starts Node's built-in test runner. The checked kit passes 27 cases. npm run validate then checks the four export families separately. This count describes included checks rather than guaranteeing exhaustive coverage. A missing file or uninstalled Ajv is a setup problem, not a provider result.
Continue with understand the validated contracts.
The kit was executed with Node.js 24.15.0. It makes no API request and requires no key environment variable. Fictional domains, models and usage values are labelled synthetic. Keep your own private responses outside the public files when adding cases.
npm ci --ignore-scripts
npm test
npm run validateEach failure class needs its own expected result
A successful empty result expects exposedQueryCount 0. A partial run without visible strings expects null and state partial. An error response expects failed. Missing status stays unknown. Invalid output or steps containers must throw. Returning [] for every case would erase the distinctions that matter.
Other checks target data loss and invented relationships. Case, decomposed Unicode, whitespace and duplicates remain exact. Multiple actions retain their query groups. URL annotations do not enter an arbitrary query row. Credential URLs are discarded. A synthetic google_search_result marker must never appear in output.
Export checks must reject wrong counts, duplicate indexes, invented source fields and incorrect versions. This differs from parsing raw responses. A parser test can pass while an export check fails; investigate the layer named in the failure first.
Continue with inspect the Interactions parser.
Distinguish expected states
Offline teaching-parser contract. Not every rule is identical to website normalization.
| Input | Expected | Prevents |
|---|---|---|
| completed + [] | completed · 0 | Invented queries |
| incomplete + [] | partial · null | False successful-zero state |
| failed + error | failed · null | Error treated as observation |
| output: {} | INVALID_RESPONSE | Malformed shape treated as zero |
Add a reproducible new edge case
Write a small original input and expected result first. The short test below adds an HTTP-independent shape error. Save it inside the kit folder as extra.test.mjs and run node --test extra.test.mjs. It passes only if the parser actually rejects the invalid list.
When it fails, decide from the documented contract whether the implementation or expectation is wrong. Do not replace a bad-input case with valid input merely to obtain green output. For provider changes, record the field path, review date and affected parser version in your own change log.
Continue with review the extraction decisions.
Transport timeouts, actual provider reachability, permissions and lawful application storage require additional checks. The offline kit claims no proof for those. Green output also does not establish better rankings. Its value is a reproducible data contract for the next implementation decision.
import test from "node:test";
import assert from "node:assert/strict";
import { parseOpenAiResponse } from "./parsers.mjs";
test("reject malformed output", () => {
assert.throws(() => parseOpenAiResponse({
status: "completed", output: {}
}), /INVALID_RESPONSE/);
});Sources used
These sources support the functions and limits described here. They do not prove claims beyond that scope.
- Original runnable offline parser and edge-case test kitOpen source
Original educational parser code and 27 offline checks. Synthetic response fixtures are not provider output; exact strings, status states, source scope and retention exclusions are tested. No paid calls or new actual grounding data. The teaching helper explicitly differs from the live normalized wrapper.
- Current website export contracts and reference validationOpen source
Draft 2020-12 reference for the current native/modelled full runs, query selections and local comparisons. Schema checked against actual service/export functions with synthetic provider stubs and semantic negative tests. No root schemaVersion is invented for full runs. Legacy planner and handoff formats remain separate.