Docs › Reference
Conformance suite
476 language-neutral test cases for validate(rows, rules). A server port in another language must pass all of them.
The dist/conformance/ folder of the 82excel npm package (npm i 82excel, then node_modules/82excel/dist/conformance/) holds 476 language-neutral test cases for validate(rows, rules): rules, input rows, and the expected errors, warnings and cleaned rows, one JSON file each. The Node implementation (82excel) passes all of them. A port to another language must pass 100% of these files, unchanged, before it can claim the same results as the browser check().
Case format
{
"name": "types/date-dots",
"why": "research §3 Korean dates: 2024.01.05",
"rules": { "columns": [{ "key": "v", "type": "date" }] },
"rows": [{ "v": "2024.01.05" }],
"expect": {
"ok": true,
"errors": [],
"warnings": [],
"rows": [{ "$row": 2, "v": "2024-01-05" }]
}
}rulesare 0.2 rules JSON passed as is;rowsare input rows keyed by columnkey(they may carry$row). Inputs are plain JSON only.expect.errorsandexpect.warningsare lists of{ row, key?, code }; row-level issues (BLANK_ROW,ROWS_TOO_FEW,ROWS_TOO_MANY) have nokey.expect.rowsare the cleaned result rows with$row;expect.maskedgives the maskedraw/valuein personal data cases;expect.throwsis the message text aninvalid/case must throw.- About a third of the cases carry a
whynaming the spec section, research note or ruling behind them. Expected values were written from the spec, never pasted from engine output.
Groups
| Folder | Covers |
|---|---|
types/ | Every column type: valid, invalid, canonical re-input, Excel error values |
rules/ | Column rules, failOn |
rowrules/ | when / compare / uniqueWith |
blank/ | rows.blank |
injection/ | formulaInjection |
pii/ | Detection, forbid/allow, masking |
normalize/ | The normalize switches |
idempotency/ | Cleaned rows fed back |
edge/ | Row numbers, boundaries, rows.min/rows.max |
invalid/ | Rules that must be rejected |
Comparison rules
- Call
validate(case.rows, case.rules)with no options. errors/warnings: compare the set of(row, key, code); order does not matter.okmust be equal;rowsmust be strictly deep-equal, in order (no missing or extra keys; numbers compare as numbers).throws: the message starts with82excel:and contains the given text verbatim. That text is part of the contract.- Messages,
rule,col,headerandsummaryare not compared. Issues with akeyalso carryheader(the column's header from the rules), which is not compared.
Behaviour the suite pins down
Where the spec is silent, the suite decides: result rows (a cell failing its type keeps its raw input, other failures keep the cleaned value), row numbers ($row when it is a positive integer, else index + headerRow + 1), emptiness, cleanup order, per-cell check order, issue keys, row counts (rows.min/rows.max count result rows, reported at the header row with no key), failOn, Excel error values (#REF! … are CELL_TYPE in every column), formula injection, personal data candidates and mask shapes, patterns (u flag, test() semantics — re.search in Python), Korean phone shapes and date ranges. The full list is in the README.
Out of scope
Anything that needs the file is tested in the Node package instead: file-level checks (password, encoding, hidden content, merged cells, macros, sheet choice, column mapping, totals rows), warnings about stored cells (PRECISION_LOSS, SCIENTIFIC_NOTATION), real formula cells, Excel date serials and the 1904 system, message text and locales, and JS row hooks.
Running it
Node (reference implementation):
pnpm --filter 82excel exec vitest run test/conformance.test.tsOther languages: walk cases/**/*.json, apply the comparison rules above and report each case by name. What the server does with it is in Server second pass.