Skip to content

Commit 2ba3dd6

Browse files
committed
more tests
1 parent 6643d93 commit 2ba3dd6

File tree

2 files changed

+61
-18
lines changed

2 files changed

+61
-18
lines changed

packages/validation/src/no.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,14 @@ type PersonalIdentityNumberOptions = ValidatorOptions;
109109
/**
110110
* Validates that the input value is a Norwegian national identity number.
111111
*
112-
* Supports both fødselsnummer and d-number.
112+
* Supports both fødselsnummer and d-nummer.
113113
* @example
114114
* ```
115+
* // Fødselsnummer
115116
* validatePersonalIdentityNumber('21075417753') // => true
116-
* validatePersonalIdentityNumber('61075440676') // => true
117+
*
118+
* // D-nummer
119+
* validatePersonalIdentityNumber('53097248016') // => true
117120
* ```
118121
*/
119122
export function validateNationalIdentityNumber(
@@ -125,30 +128,37 @@ export function validateNationalIdentityNumber(
125128
value = stripFormatting(value);
126129
}
127130

128-
// Fødselsn
129-
// Fødselsnummer and d numbers have two control digits.
130-
// where the first one is calculated using the first 10 digits.
131+
// Norwegian national identity numbers use mod 11 with two control digits.
132+
// The first one is calculated for the first 10d digits
133+
// while the last one uses all 11 digits
131134
const valueForControlDigit1 = value.slice(0, -1);
132135
const controlDigit1 = mod11(
133136
valueForControlDigit1,
134137
[3, 7, 6, 1, 8, 9, 4, 5, 2],
135138
);
139+
136140
const controlDigit2 = mod11(value, [5, 4, 3, 2, 7, 6, 5, 4, 3, 2]);
137141

138-
if (!controlDigit1 && !controlDigit2) {
142+
if (!controlDigit1 || !controlDigit2) {
139143
return false;
140144
}
141145

142146
let day = Number(value.substring(0, 2));
143147
const month = Number(value.substring(2, 4));
144-
const year = Number(value.substring(4, 6));
148+
let year = Number(value.substring(4, 6));
149+
150+
// 1900 isn't a leap year
151+
if (year === 0) {
152+
year = 2000;
153+
}
145154

146155
// for a d-number the first digit is increased by 4. Eg the 31st of a month would be 71, or the 3rd would be 43.
147156
// thus we need to subtract 40 to get the correct day of the month
148157
if (day >= 40) {
149158
day = day - 40;
150159
}
151160

161+
// important to use UTC so the user's timezone doesn't affect the validation
152162
const date = new Date(Date.UTC(year, month - 1, day));
153163

154164
return date && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;

packages/validation/src/validation.test.ts

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,20 +60,53 @@ describe('no', () => {
6060
expect(no.validateObosMembershipNumber(input, options)).toBe(expected);
6161
});
6262

63-
test('validateNationalIdentityNumber()', () => {
63+
test('validateNationalIdentityNumber() - validates fødselsnummer', () => {
6464
for (let i = 0; i < 1000; ++i) {
65-
expect(
66-
no.validateNationalIdentityNumber(
67-
navfaker.personIdentifikator.fødselsnummer(),
68-
),
69-
).toBe(true);
70-
expect(
71-
no.validateNationalIdentityNumber(
72-
navfaker.personIdentifikator.dnummer(),
73-
),
74-
).toBe(true);
65+
const fnr = navfaker.personIdentifikator.fødselsnummer();
66+
expect(no.validateNationalIdentityNumber(fnr), `${fnr} is valid`).toBe(
67+
true,
68+
);
7569
}
7670
});
71+
72+
test('validateNationalIdentityNumber() - validates d-nummer', () => {
73+
for (let i = 0; i < 1000; ++i) {
74+
const dnr = navfaker.personIdentifikator.dnummer();
75+
expect(no.validateNationalIdentityNumber(dnr), `${dnr} is valid`).toBe(
76+
true,
77+
);
78+
}
79+
});
80+
81+
test('validateNationalIdentityNumber() - validates leap years', () => {
82+
expect(no.validateNationalIdentityNumber('29029648784')).toBe(true);
83+
});
84+
85+
test('validateNationalIdentityNumber() - validates 00 as a leap year', () => {
86+
expect(no.validateNationalIdentityNumber('29020075838')).toBe(true);
87+
});
88+
89+
test('validateNationalIdentityNumber() - returns false for invalid identity numbers', () => {
90+
expect(
91+
no.validateNationalIdentityNumber('13097248032'),
92+
'1st control digit is invalid',
93+
).toBe(false);
94+
95+
expect(
96+
no.validateNationalIdentityNumber('13097248023'),
97+
'2nd control digit is invalid',
98+
).toBe(false);
99+
100+
expect(
101+
no.validateNationalIdentityNumber('32127248022'),
102+
'day is invalid',
103+
).toBe(false);
104+
105+
expect(
106+
no.validateNationalIdentityNumber('13137248022'),
107+
'month is invalid',
108+
).toBe(false);
109+
});
77110
});
78111

79112
describe('se', () => {

0 commit comments

Comments
 (0)