test(nor): add fødselsnummer, D-nummer, checksum/parse tests + D-nummer support#96
Merged
test(nor): add fødselsnummer, D-nummer, checksum/parse tests + D-nummer support#96
Conversation
…upport
- Extend NationalIdParseResult with idType discriminator ('fodselsnummer' | 'd-nummer')
- Update parse() to detect D-nummer (DD 41-71): subtract 40 from day field, set idType
- Add comprehensive test file covering all three milestone v1.6.0 issues:
- 14 fødselsnummer validation tests (valid/invalid, century logic, date edge cases)
- 8 D-nummer validation tests (valid, boundary negatives, differentiation)
- 5 checksum tests (valid/invalid first+second check digits, malformed input)
- 11 parse() function tests (birth date, gender, idType, checksum field, errors)
- 5 integration tests (validateNationalId, parseIdInfo via public API)
- Remove redundant `as const` from idType literal assignment - Extract mmNum to avoid double parseInt(mm, 10) in date construction/validation - Shorten D-nummer detection comment to non-obvious why only - Import NationalIdParseResult in test for clean type assertion
- Fix misleading test.each label for 29029600013: individual 000 (not 001), gender FEMALE (not male) - Add 1800s century test vector (10107055008): individual 550, yy=70>=54 → century 18
- Make idType field optional on NationalIdParseResult to avoid breaking change for downstream consumers constructing the type literally; parse() always populates it - Document Python parity deviation in source comment and CHANGELOG: D-nummer support is a TypeScript-side extension required by issue #29 acceptance criteria; checksum and other behaviors remain identical to Python source - Fix DD=72 test: clarify isDNummer=false (72>71), use checksum-valid vector 72019000290 to isolate date-overflow rejection from checksum rejection
- Remove dead try/catch in parse(): JS Date never throws on overflow; date validity is already enforced by getFullYear/getMonth/getDate comparisons - Add typeof string guard at top of parse() to mirror validate() and prevent parse() from accidentally accepting non-string inputs whose toString() returns 11 valid digits - Make idType field required (drop optional ?): NationalIdParseResult is not re-exported via the country barrel, so no external consumer constructs it - Fix Feb 29 1999 leap-year reject test: assert parse() returns null directly to isolate the date-validation path from checksum validation - Add DD=32 gap regression test (32019000035, checksum-valid) covering the range 32-40 between fødselsnummer max (31) and D-nummer min (41) - Add 1900s D-nummer test vector 45055590110 covering interaction between D-nummer day adjustment and individual 900-999/yy>=40 century branch
This was referenced Apr 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #28, #29, #30 — test coverage for Norway
NationalID, milestone v1.6.0.NationalID.parse(): detects DD field 41–71, subtracts 40 to recover the actual day, and exposes a new requiredidType: 'fodselsnummer' | 'd-nummer'discriminator onNationalIdParseResult.src/__tests__/issue-28-30-nor-national-id.test.ts) covering all three issues: fødselsnummer validation across 1800s/1900s/2000s centuries, D-nummer validation (1900s + 2000s centuries, DD=41/55/71 boundaries, DD=40/72 rejection, DD=32 gap rejection), mod-11 checksum,parse()output fields, and public API integration.try/catcharoundnew Date()(JS Date never throws on overflow), added missingtypeof stringguard inparse()to mirrorvalidate(), extractedmmNum/fullYearto avoid redundantparseIntcalls.Python parity deviation (documented)
The Python
idnumberssource library currently rejects D-nummer inputs because itsparse()callsdate(yyyy, mm, int(dd))directly and raisesValueErrorfordd >= 32. Issue #29 explicitly requires valid D-nummer validation, so this PR extendsparse()in TypeScript only. The checksum algorithm and all other behaviors remain identical to Python. The deviation is documented insrc/countries/nor/nationalId.tsandCHANGELOG.md. The Python library should add the same logic to restore full parity.Changes
src/countries/nor/nationalId.tssrc/__tests__/issue-28-30-nor-national-id.test.tsCHANGELOG.mdTest plan
issue-28-30-nor-national-id.test.ts: 49 tests across 5 describe blocks (fødselsnummer, D-nummer, checksum, parse, integration) — all passingparseIdInfo-migration.test.ts): still exactly 80 primary validators40019000119/72019000290) so rejection is purely from date overflow, not checksum failure29029900013) assertsparse()returns null directly to isolate the date-validation pathReview rounds
Internal review + 3 external review rounds (reviewer agent). All P0/P1 items resolved:
29029600013test label (individual 000, female), added 1800s century vector (10107055008)idTypeoptional → then round 3 made it required again (interface not re-exported, no breaking consumer); documented Python parity deviation; added DD=72 checksum-valid vectortry/catch, addedtypeofguard toparse(), madeidTyperequired, fixed leap-year test to isolate path, added DD=32 gap test, added 1900s-century D-nummer test vectorFinal verdict: APPROVED (Test Coverage 10/10, Code Quality 9/10).