# kit - six rules, in your own test suite Source: https://truecopy.dev/docs/kit/ Module: truecopy/kit An interface is dodged with a return null. An assertion is not. Drop the conformance kit into your gate with a corpus of your own documents. `selfCheck() { return null }` compiles, passes review and ships, and that is exactly what one of the two readers this library came from had, until a check like this one measured it from the outside. ```ts import { checkContract, contractReport, failures, pdfWithText } from 'truecopy/kit'; it('holds the reading contract', async () => { const results = await checkContract( myReader, [ { name: 'balances', document: aSoundDocument, expected: 'read' }, { name: 'does not balance', document: aWrongDocument, expected: 'needs-review' } ], { referencePdf: pdfWithText([{ word: '2018', x: 50, y: 700 }]), open: openLikeTheApp, foreign: [{ name: 'a payslip', document: aPayslip }] } ); expect(failures(results)).toEqual([]); writeFileSync('contract.txt', contractReport(results)); }); ``` ## The six rules 1. **The verdict the corpus announces is the verdict returned.** 2. **A reading that contradicts its document never comes back as sound.** 3. **Everything read is reviewable by the person.** 4. **The chain from bytes to records really runs**, on a _real_ PDF. 5. **A document without substance is refused**, not silently returned empty. 6. **A document of another kind is refused.** Not one of them knows your domain. ## Your door, not the kit's `open` is required, and it is **your** function. Both readers that gave rise to this already had an extractor of their own, and a kit that imposes one stops measuring the project's reader and starts measuring its own, the one thing a conformance suite must never do. ## Rule 6 needs a corpus only you have A foreign document often carries the **shape** of what you seek (years, numbers, amounts) without being it. A payslip carries the vocabulary of retirement. An invoice carries dates and totals. Only you know what your reader has to be told apart from, so `foreign` comes from you. This is the rule nobody writes and every reader lacks. ## A real PDF, not a stub `pdfWithText(words)` builds one: a real content stream, a real cross-reference table. Longer than a stub, and that is the point: what a reader must be able to do is open the file the person downloaded, and **a test that fakes the PDF engine proves none of it**. `pdfWithPages(pages)` does the same over several pages, which is the only way to exercise what appears across them: a blank page in the middle, or two pages cut into a different number of columns. ## A report you commit ```ts writeFileSync('contract.txt', contractReport(results)); ``` Pact's idea, and the reason it outlived the assertion helpers that did the same work: the contract lives outside both sides, as an artifact you can version, review and diff. A green suite says the rules held today; a committed report says **what** held, and a pull request that moves a line makes the change argue for itself. The counts are in it on purpose. A reading that quietly falls from twenty-six records to twenty-four still passes every rule, and no assertion anywhere is going to notice. The diff is. Nothing here touches the filesystem: this library runs in a browser, and one that imports `fs` stops doing that. You write the string where you want it. Map of this site for a model: https://truecopy.dev/llms.txt Every page in one file: https://truecopy.dev/llms-full.txt