@@ -48,6 +48,192 @@ describe('parse TD1', () => {
4848 } ) ;
4949 } ) ;
5050
51+ it ( 'Portuguese ID - valid' , ( ) => {
52+ // source: https://media.timeout.com/images/106144795/image.jpg
53+ const MRZ = [
54+ 'I<PRT007777779<ZZ92<<<<<<<<<<<' ,
55+ '8303143M3405282PRT<<<<<<<<<<<2' ,
56+ 'CACADOR<DE<ARAUJO<<ANDRE<ESTEV' ,
57+ ] ;
58+
59+ const result = parse ( MRZ ) ;
60+
61+ expect ( result ) . toMatchObject ( {
62+ format : 'TD1' ,
63+ valid : true ,
64+ documentNumber : result . fields . documentNumber ,
65+ } ) ;
66+
67+ expect ( result . fields ) . toStrictEqual ( {
68+ documentCode : 'I' ,
69+ issuingState : 'PRT' ,
70+ documentNumber : '007777779ZZ9' ,
71+ documentNumberCheckDigit : '2' ,
72+ birthDate : '830314' ,
73+ birthDateCheckDigit : '3' ,
74+ sex : 'male' ,
75+ expirationDate : '340528' ,
76+ expirationDateCheckDigit : '2' ,
77+ nationality : 'PRT' ,
78+ optional1 : 'ZZ92' ,
79+ optional2 : '' ,
80+ compositeCheckDigit : '2' ,
81+ lastName : 'CACADOR DE ARAUJO' ,
82+ firstName : 'ANDRE ESTEV' ,
83+ } ) ;
84+
85+ const optional1Details = result . details . find (
86+ ( f ) => f . field === 'optional1' ,
87+ ) ;
88+
89+ expect ( optional1Details ) . toMatchObject ( {
90+ value : 'ZZ92' ,
91+ line : 0 ,
92+ start : 15 ,
93+ end : 19 ,
94+ } ) ;
95+ } ) ;
96+
97+ it ( 'Portuguese ID PRT-BO-04001 - valid' , ( ) => {
98+ // source: https://www.consilium.europa.eu/prado/en/PRT-BO-04001/index.html
99+ const MRZ = [
100+ 'I<PRT007666667<ZZ00<<<<<<<<<<<' ,
101+ '8303143M3405293PRT<<<<<<<<<<<4' ,
102+ 'CACADOR<DE<ARAUJO<<ANDRE<ESTEV' ,
103+ ] ;
104+
105+ const result = parse ( MRZ ) ;
106+
107+ expect ( result ) . toMatchObject ( {
108+ format : 'TD1' ,
109+ valid : true ,
110+ documentNumber : result . fields . documentNumber ,
111+ } ) ;
112+
113+ expect ( result . fields ) . toStrictEqual ( {
114+ documentCode : 'I' ,
115+ issuingState : 'PRT' ,
116+ documentNumber : '007666667ZZ0' ,
117+ documentNumberCheckDigit : '0' ,
118+ birthDate : '830314' ,
119+ birthDateCheckDigit : '3' ,
120+ sex : 'male' ,
121+ expirationDate : '340529' ,
122+ expirationDateCheckDigit : '3' ,
123+ nationality : 'PRT' ,
124+ optional1 : 'ZZ00' ,
125+ optional2 : '' ,
126+ compositeCheckDigit : '4' ,
127+ lastName : 'CACADOR DE ARAUJO' ,
128+ firstName : 'ANDRE ESTEV' ,
129+ } ) ;
130+
131+ const optional1Details = result . details . find (
132+ ( f ) => f . field === 'optional1' ,
133+ ) ;
134+
135+ expect ( optional1Details ) . toMatchObject ( {
136+ value : 'ZZ00' ,
137+ line : 0 ,
138+ start : 15 ,
139+ end : 19 ,
140+ } ) ;
141+ } ) ;
142+
143+ it ( 'Belgium ID BEL-BO-11005 - valid' , ( ) => {
144+ // source: https://www.consilium.europa.eu/prado/en/BEL-BO-11005/index.html
145+ // Changed the country code from UTO to BEL to make it pass the country validation,
146+ // but that this part does not affect any check digit checks.
147+ const MRZ = [
148+ 'IDBEL600001795<0152<<<<<<<<<<<' ,
149+ '1301014F2311207BEL130101987398' ,
150+ 'SPECIMEN<<SPECIMEN<<<<<<<<<<<<' ,
151+ ] ;
152+
153+ const result = parse ( MRZ ) ;
154+
155+ expect ( result ) . toMatchObject ( {
156+ format : 'TD1' ,
157+ valid : true ,
158+ documentNumber : result . fields . documentNumber ,
159+ } ) ;
160+
161+ expect ( result . fields ) . toStrictEqual ( {
162+ documentCode : 'ID' ,
163+ issuingState : 'BEL' ,
164+ documentNumber : '600001795015' ,
165+ documentNumberCheckDigit : '2' ,
166+ birthDate : '130101' ,
167+ birthDateCheckDigit : '4' ,
168+ sex : 'female' ,
169+ expirationDate : '231120' ,
170+ expirationDateCheckDigit : '7' ,
171+ nationality : 'BEL' ,
172+ optional1 : '0152' ,
173+ optional2 : '13010198739' ,
174+ compositeCheckDigit : '8' ,
175+ lastName : 'SPECIMEN' ,
176+ firstName : 'SPECIMEN' ,
177+ } ) ;
178+
179+ const optional1Details = result . details . find (
180+ ( f ) => f . field === 'optional1' ,
181+ ) ;
182+
183+ expect ( optional1Details ) . toMatchObject ( {
184+ value : '0152' ,
185+ line : 0 ,
186+ start : 15 ,
187+ end : 19 ,
188+ } ) ;
189+ } ) ;
190+
191+ it ( 'Finland ID FIN-BO-12001 - valid' , ( ) => {
192+ // source: https://www.consilium.europa.eu/prado/en/FIN-BO-12001/index.html
193+ const MRZ = [
194+ 'I<FINXA10000585010195<112X<<<<' ,
195+ '9501016F2803135FIN<<<<<<<<<<<7' ,
196+ 'SPECIMEN<TRAVEL<<VILMA<SOFIA<<' ,
197+ ] ;
198+
199+ const result = parse ( MRZ ) ;
200+
201+ expect ( result ) . toMatchObject ( {
202+ format : 'TD1' ,
203+ valid : true ,
204+ documentNumber : result . fields . documentNumber ,
205+ } ) ;
206+
207+ expect ( result . fields ) . toStrictEqual ( {
208+ documentCode : 'I' ,
209+ issuingState : 'FIN' ,
210+ documentNumber : 'XA1000058' ,
211+ documentNumberCheckDigit : '5' ,
212+ birthDate : '950101' ,
213+ birthDateCheckDigit : '6' ,
214+ sex : 'female' ,
215+ expirationDate : '280313' ,
216+ expirationDateCheckDigit : '5' ,
217+ nationality : 'FIN' ,
218+ optional1 : '010195 112X' ,
219+ optional2 : '' ,
220+ compositeCheckDigit : '7' ,
221+ lastName : 'SPECIMEN TRAVEL' ,
222+ firstName : 'VILMA SOFIA' ,
223+ } ) ;
224+
225+ const optional1Details = result . details . find (
226+ ( f ) => f . field === 'optional1' ,
227+ ) ;
228+
229+ expect ( optional1Details ) . toMatchObject ( {
230+ value : '010195 112X' ,
231+ line : 0 ,
232+ start : 15 ,
233+ end : 26 ,
234+ } ) ;
235+ } ) ;
236+
51237 it ( 'Utopia example' , ( ) => {
52238 const MRZ = [
53239 'I<UTOD231458907ABC<<<<<<<<<<<<' ,
@@ -107,8 +293,8 @@ describe('parse TD1', () => {
107293
108294 it ( 'parse document number' , ( ) => {
109295 const MRZ = [
110- 'I<UTOD23145890<1240<XYZ <<<<<<<' ,
111- '7408122F1204159UTO<<<<<<<<<<<8 ' ,
296+ 'I<UTOD23145890<1233<<<< <<<<<<<' ,
297+ '7408122F1204159UTO<<<<<<<<<<<2 ' ,
112298 'ERIKSSON<<ANNA<MARIA<<<<<<<<<<' ,
113299 ] ;
114300
@@ -129,20 +315,73 @@ describe('parse TD1', () => {
129315 expect ( documentNumberDetails ) . toStrictEqual ( {
130316 label : 'Document number' ,
131317 field : 'documentNumber' ,
132- value : 'D23145890124' ,
318+ value : 'D23145890123' ,
319+ valid : true ,
320+ ranges : [
321+ { line : 0 , start : 5 , end : 14 , raw : 'D23145890' } ,
322+ { line : 0 , start : 14 , end : 15 , raw : '<' } ,
323+ { line : 0 , start : 15 , end : 30 , raw : '1233<<<<<<<<<<<' } ,
324+ ] ,
325+ line : 0 ,
326+ start : 5 ,
327+ end : 18 ,
328+ autocorrect : [ ] ,
329+ } ) ;
330+ expect ( result . fields . documentNumber ) . toBe ( 'D23145890123' ) ;
331+ expect ( result . fields . documentNumberCheckDigit ) . toBe ( '3' ) ;
332+
333+ const documentNumberCheckDigitDetails = result . details . find (
334+ ( d ) => d . field === 'documentNumberCheckDigit' ,
335+ ) ;
336+
337+ expect ( documentNumberCheckDigitDetails ) . toMatchObject ( {
338+ line : 0 ,
339+ start : 18 ,
340+ end : 19 ,
341+ value : '3' ,
342+ } ) ;
343+ } ) ;
344+
345+ it ( 'parse document number ICAO Doc 9303 Sample' , ( ) => {
346+ // source: https://www.icao.int/sites/default/files/publications/DocSeries/9303_p11_cons_en.pdf
347+ // page 88, D.2 DERIVATION OF DOCUMENT BASIC ACCESS KEYS
348+ const MRZ = [
349+ 'I<UTOD23145890<7349<<<<<<<<<<<' ,
350+ '3407127M9507122UTO<<<<<<<<<<<2' ,
351+ 'STEVENSON<<PETER<JOHN<<<<<<<<<' ,
352+ ] ;
353+
354+ const result = parse ( MRZ ) ;
355+
356+ expect ( result ) . toMatchObject ( {
357+ format : 'TD1' ,
358+ valid : false ,
359+ documentNumber : result . fields . documentNumber ,
360+ } ) ;
361+
362+ expect ( result . details . filter ( ( f ) => ! f . valid ) ) . toHaveLength ( 2 ) ;
363+
364+ const documentNumberDetails = result . details . find (
365+ ( d ) => d . field === 'documentNumber' ,
366+ ) ;
367+
368+ expect ( documentNumberDetails ) . toStrictEqual ( {
369+ label : 'Document number' ,
370+ field : 'documentNumber' ,
371+ value : 'D23145890734' ,
133372 valid : true ,
134373 ranges : [
135374 { line : 0 , start : 5 , end : 14 , raw : 'D23145890' } ,
136375 { line : 0 , start : 14 , end : 15 , raw : '<' } ,
137- { line : 0 , start : 15 , end : 30 , raw : '1240<XYZ <<<<<<<' } ,
376+ { line : 0 , start : 15 , end : 30 , raw : '7349<<<< <<<<<<<' } ,
138377 ] ,
139378 line : 0 ,
140379 start : 5 ,
141380 end : 18 ,
142381 autocorrect : [ ] ,
143382 } ) ;
144- expect ( result . fields . documentNumber ) . toBe ( 'D23145890124 ' ) ;
145- expect ( result . fields . documentNumberCheckDigit ) . toBe ( '0 ' ) ;
383+ expect ( result . fields . documentNumber ) . toBe ( 'D23145890734 ' ) ;
384+ expect ( result . fields . documentNumberCheckDigit ) . toBe ( '9 ' ) ;
146385
147386 const documentNumberCheckDigitDetails = result . details . find (
148387 ( d ) => d . field === 'documentNumberCheckDigit' ,
@@ -152,7 +391,7 @@ describe('parse TD1', () => {
152391 line : 0 ,
153392 start : 18 ,
154393 end : 19 ,
155- value : '0 ' ,
394+ value : '9 ' ,
156395 } ) ;
157396 } ) ;
158397
0 commit comments