@pagopa/io-react-native-iso18013 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +10 -5
  2. package/android/build.gradle +7 -1
  3. package/android/src/main/java/com/ioreactnativeiso18013/IoReactNativeCborModule.kt +69 -134
  4. package/android/src/main/java/com/ioreactnativeiso18013/IoReactNativeIso18013Module.kt +254 -183
  5. package/android/src/test/java/com/ioreactnativeiso18013/Base64UtilsTest.kt +66 -0
  6. package/android/src/test/java/com/ioreactnativeiso18013/IoReactNativeIso18013Test.kt +508 -0
  7. package/ios/Base64Utils.swift +10 -3
  8. package/ios/IoReactNativeCbor.mm +21 -21
  9. package/ios/IoReactNativeCbor.swift +116 -138
  10. package/ios/IoReactNativeIso18013.mm +10 -10
  11. package/ios/IoReactNativeIso18013.swift +172 -193
  12. package/lib/module/cbor/cbor/README.md +39 -59
  13. package/lib/module/cbor/cbor/decoder.js +13 -23
  14. package/lib/module/cbor/cbor/decoder.js.map +1 -1
  15. package/lib/module/cbor/cbor/error.js +15 -0
  16. package/lib/module/cbor/cbor/error.js.map +1 -0
  17. package/lib/module/cbor/cbor/index.js +1 -0
  18. package/lib/module/cbor/cbor/index.js.map +1 -1
  19. package/lib/module/cbor/cose/README.md +39 -9
  20. package/lib/module/cbor/cose/error.js +17 -0
  21. package/lib/module/cbor/cose/error.js.map +1 -0
  22. package/lib/module/cbor/cose/index.js +1 -0
  23. package/lib/module/cbor/cose/index.js.map +1 -1
  24. package/lib/module/cbor/cose/sign.js +4 -3
  25. package/lib/module/cbor/cose/sign.js.map +1 -1
  26. package/lib/module/iso18013/index.js +0 -1
  27. package/lib/module/iso18013/index.js.map +1 -1
  28. package/lib/module/iso18013/iso18013-5/README.md +120 -44
  29. package/lib/module/iso18013/iso18013-5/error.js +25 -0
  30. package/lib/module/iso18013/iso18013-5/error.js.map +1 -0
  31. package/lib/module/iso18013/iso18013-5/index.js +3 -2
  32. package/lib/module/iso18013/iso18013-5/index.js.map +1 -1
  33. package/lib/module/iso18013/iso18013-5/proximity.js +20 -15
  34. package/lib/module/iso18013/iso18013-5/proximity.js.map +1 -1
  35. package/lib/module/iso18013/iso18013-5/{schema.js → request.js} +1 -37
  36. package/lib/module/iso18013/iso18013-5/request.js.map +1 -0
  37. package/lib/module/iso18013/iso18013-7/README.md +66 -41
  38. package/lib/module/iso18013/iso18013-7/error.js +15 -0
  39. package/lib/module/iso18013/iso18013-7/error.js.map +1 -0
  40. package/lib/module/iso18013/iso18013-7/index.js +1 -0
  41. package/lib/module/iso18013/iso18013-7/index.js.map +1 -1
  42. package/lib/module/iso18013/iso18013-7/remote.js +11 -24
  43. package/lib/module/iso18013/iso18013-7/remote.js.map +1 -1
  44. package/lib/module/schema.js +46 -0
  45. package/lib/module/schema.js.map +1 -0
  46. package/lib/typescript/src/cbor/cbor/decoder.d.ts +12 -22
  47. package/lib/typescript/src/cbor/cbor/decoder.d.ts.map +1 -1
  48. package/lib/typescript/src/cbor/cbor/error.d.ts +68 -0
  49. package/lib/typescript/src/cbor/cbor/error.d.ts.map +1 -0
  50. package/lib/typescript/src/cbor/cbor/index.d.ts +1 -1
  51. package/lib/typescript/src/cbor/cbor/index.d.ts.map +1 -1
  52. package/lib/typescript/src/cbor/cose/error.d.ts +68 -0
  53. package/lib/typescript/src/cbor/cose/error.d.ts.map +1 -0
  54. package/lib/typescript/src/cbor/cose/index.d.ts +1 -1
  55. package/lib/typescript/src/cbor/cose/index.d.ts.map +1 -1
  56. package/lib/typescript/src/cbor/cose/sign.d.ts +4 -3
  57. package/lib/typescript/src/cbor/cose/sign.d.ts.map +1 -1
  58. package/lib/typescript/src/iso18013/index.d.ts +0 -1
  59. package/lib/typescript/src/iso18013/index.d.ts.map +1 -1
  60. package/lib/typescript/src/iso18013/iso18013-5/error.d.ts +73 -0
  61. package/lib/typescript/src/iso18013/iso18013-5/error.d.ts.map +1 -0
  62. package/lib/typescript/src/iso18013/iso18013-5/index.d.ts +4 -3
  63. package/lib/typescript/src/iso18013/iso18013-5/index.d.ts.map +1 -1
  64. package/lib/typescript/src/iso18013/iso18013-5/proximity.d.ts +21 -14
  65. package/lib/typescript/src/iso18013/iso18013-5/proximity.d.ts.map +1 -1
  66. package/lib/typescript/src/iso18013/iso18013-5/{schema.d.ts → request.d.ts} +1 -39
  67. package/lib/typescript/src/iso18013/iso18013-5/request.d.ts.map +1 -0
  68. package/lib/typescript/src/iso18013/iso18013-7/error.d.ts +68 -0
  69. package/lib/typescript/src/iso18013/iso18013-7/error.d.ts.map +1 -0
  70. package/lib/typescript/src/iso18013/iso18013-7/index.d.ts +3 -2
  71. package/lib/typescript/src/iso18013/iso18013-7/index.d.ts.map +1 -1
  72. package/lib/typescript/src/iso18013/iso18013-7/remote.d.ts +11 -25
  73. package/lib/typescript/src/iso18013/iso18013-7/remote.d.ts.map +1 -1
  74. package/lib/typescript/src/iso18013/types.d.ts +25 -0
  75. package/lib/typescript/src/iso18013/types.d.ts.map +1 -1
  76. package/lib/typescript/src/schema.d.ts +76 -0
  77. package/lib/typescript/src/schema.d.ts.map +1 -0
  78. package/package.json +1 -1
  79. package/src/cbor/cbor/README.md +39 -59
  80. package/src/cbor/cbor/decoder.ts +13 -23
  81. package/src/cbor/cbor/error.ts +23 -0
  82. package/src/cbor/cbor/index.ts +5 -1
  83. package/src/cbor/cose/README.md +39 -9
  84. package/src/cbor/cose/error.ts +23 -0
  85. package/src/cbor/cose/index.ts +5 -1
  86. package/src/cbor/cose/sign.ts +5 -4
  87. package/src/iso18013/index.ts +0 -7
  88. package/src/iso18013/iso18013-5/README.md +120 -44
  89. package/src/iso18013/iso18013-5/error.ts +35 -0
  90. package/src/iso18013/iso18013-5/index.ts +9 -8
  91. package/src/iso18013/iso18013-5/proximity.ts +21 -17
  92. package/src/iso18013/iso18013-5/{schema.ts → request.ts} +0 -42
  93. package/src/iso18013/iso18013-7/README.md +66 -41
  94. package/src/iso18013/iso18013-7/error.ts +21 -0
  95. package/src/iso18013/iso18013-7/index.ts +6 -5
  96. package/src/iso18013/iso18013-7/remote.ts +12 -34
  97. package/src/iso18013/types.ts +24 -0
  98. package/src/schema.ts +55 -0
  99. package/lib/module/cbor/cbor/failure.js +0 -2
  100. package/lib/module/cbor/cbor/failure.js.map +0 -1
  101. package/lib/module/cbor/cose/failure.js +0 -2
  102. package/lib/module/cbor/cose/failure.js.map +0 -1
  103. package/lib/module/iso18013/iso18013-5/schema.js.map +0 -1
  104. package/lib/typescript/src/cbor/cbor/failure.d.ts +0 -15
  105. package/lib/typescript/src/cbor/cbor/failure.d.ts.map +0 -1
  106. package/lib/typescript/src/cbor/cose/failure.d.ts +0 -15
  107. package/lib/typescript/src/cbor/cose/failure.d.ts.map +0 -1
  108. package/lib/typescript/src/iso18013/iso18013-5/schema.d.ts.map +0 -1
  109. package/src/cbor/cbor/failure.ts +0 -18
  110. package/src/cbor/cose/failure.ts +0 -20
@@ -0,0 +1,508 @@
1
+ package com.ioreactnativeiso18013
2
+
3
+ import com.facebook.react.bridge.JavaOnlyArray
4
+ import com.facebook.react.bridge.JavaOnlyMap
5
+ import it.pagopa.io.wallet.proximity.request.DocRequested
6
+ import java.util.UUID
7
+ import kotlin.io.encoding.Base64
8
+ import kotlin.io.encoding.ExperimentalEncodingApi
9
+ import kotlin.random.Random
10
+ import org.junit.Assert.assertThrows
11
+ import org.junit.Test
12
+ import kotlin.collections.emptyList
13
+
14
+ class IoReactNativeIso18013Test {
15
+
16
+ /**
17
+ * Checks if two parsed certificates lists are equal.
18
+ * This is required because ByteArray are compared by reference.
19
+ * @param a - The first list to be compared
20
+ * @param b - The second list to be compared
21
+ * @returns true if they are equal, false otherwise
22
+ */
23
+ private fun areCertificatesListsEqual(
24
+ a: List<List<ByteArray>>,
25
+ b: List<List<ByteArray>>
26
+ ): Boolean {
27
+ if (a.size != b.size) return false
28
+ return a.indices.all { i ->
29
+ val innerA = a[i]
30
+ val innerB = b[i]
31
+ if (innerA.size != innerB.size) return false
32
+ innerA.indices.all { j ->
33
+ innerA[j].contentEquals(innerB[j])
34
+ }
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Checks if two array of documents equal.
40
+ * TThis is needed because DocRequest contains a ByteArray which is compared by reference
41
+ * @param a - The first array to be compared
42
+ * @param b - The second array to be compared
43
+ * @returns true if they are equal, false otherwise
44
+ */
45
+ private fun areDocumentsArrayEqual(
46
+ a: Array<DocRequested>,
47
+ b: Array<DocRequested>
48
+ ): Boolean {
49
+ if (a.size != b.size) return false
50
+ return a.indices.all { i ->
51
+ val innerA = a[i]
52
+ val innerB = b[i]
53
+ innerA.alias == innerB.alias &&
54
+ innerA.docType == innerB.docType &&
55
+ innerA.issuerSignedContent.contentEquals(innerB.issuerSignedContent)
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Tests for parseCertificates
61
+ */
62
+
63
+ @Test
64
+ fun `should parse multiple certificates from the bridge with an empty inner array into a 2 dimensional byte array`() {
65
+ val certificatesBase64 = listOf(
66
+ JavaOnlyArray.from(listOf("dGVzdA==", "dGVzdDEyMw==", "cmFuZG9tU3RyaW5nMTIz")),
67
+ JavaOnlyArray(),
68
+ )
69
+ val certificatesByteArray = listOf(
70
+ listOf(
71
+ byteArrayOf(116, 101, 115, 116),
72
+ byteArrayOf(116, 101, 115, 116, 49, 50, 51),
73
+ byteArrayOf(114, 97, 110, 100, 111, 109, 83, 116, 114, 105, 110, 103, 49, 50, 51)
74
+ ),
75
+ emptyList<ByteArray>()
76
+ )
77
+ val nativeArray = JavaOnlyArray.from(certificatesBase64)
78
+ val parsedCertificates = IoReactNativeIso18013Module.parseCertificates(nativeArray)
79
+ print(parsedCertificates.toString())
80
+ assert(areCertificatesListsEqual(certificatesByteArray, parsedCertificates))
81
+ }
82
+
83
+ @Test
84
+ fun `should parse multiple certificates from the bridge into a 2 dimensional byte array`() {
85
+ val certificatesBase64 = listOf(
86
+ JavaOnlyArray.from(listOf("dGVzdA==", "dGVzdDEyMw==", "cmFuZG9tU3RyaW5nMTIz")),
87
+ JavaOnlyArray.from(listOf("aWVybnF3aWRuczEyNA==", "MTIzeHhxcWVy")),
88
+ )
89
+ val certificatesByteArray = listOf(
90
+ listOf(
91
+ byteArrayOf(116, 101, 115, 116),
92
+ byteArrayOf(116, 101, 115, 116, 49, 50, 51),
93
+ byteArrayOf(114, 97, 110, 100, 111, 109, 83, 116, 114, 105, 110, 103, 49, 50, 51)
94
+ ),
95
+ listOf(
96
+ byteArrayOf(105, 101, 114, 110, 113, 119, 105, 100, 110, 115, 49, 50, 52),
97
+ byteArrayOf(49, 50, 51, 120, 120, 113, 113, 101, 114)
98
+ )
99
+ )
100
+ val nativeArray = JavaOnlyArray.from(certificatesBase64)
101
+ val parsedCertificates = IoReactNativeIso18013Module.parseCertificates(nativeArray)
102
+ assert(areCertificatesListsEqual(certificatesByteArray, parsedCertificates))
103
+ }
104
+
105
+ @Test
106
+ fun `should parse a single certificates array from the bridge into a 2 dimensional byte array`() {
107
+ val certificatesBase64 = listOf(
108
+ JavaOnlyArray.from(listOf("dGVzdA==")),
109
+ )
110
+ val certificatesByteArray = listOf(listOf(byteArrayOf(116, 101, 115, 116)))
111
+ val nativeArray = JavaOnlyArray.from(certificatesBase64)
112
+ val parsedCertificates = IoReactNativeIso18013Module.parseCertificates(nativeArray)
113
+ assert(areCertificatesListsEqual(certificatesByteArray, parsedCertificates))
114
+ }
115
+
116
+
117
+ @Test
118
+ fun `should return an empty list if the array of certificates is empty`() {
119
+ val nativeArray = JavaOnlyArray()
120
+ val parsedCertificates = IoReactNativeIso18013Module.parseCertificates(nativeArray)
121
+ assert(parsedCertificates.isEmpty())
122
+ }
123
+
124
+ @Test
125
+ fun `should throw an IllegalArgumentException if the provided certificate is not a valid base64 string`() {
126
+ val certificatesBase64 = listOf(
127
+ JavaOnlyArray.from(listOf("123~")),
128
+ )
129
+ val nativeArray = JavaOnlyArray.from(certificatesBase64)
130
+ assertThrows(
131
+ IllegalArgumentException::class.java
132
+ ) {
133
+ IoReactNativeIso18013Module.parseCertificates(nativeArray)
134
+ }
135
+ }
136
+
137
+ @Test
138
+ fun `should throw an IllegalArgumentException if the provided certificate is not a string`() {
139
+ val certificatesBase64 = listOf(
140
+ JavaOnlyArray.from(listOf("dGVzdA==", 123)),
141
+ )
142
+ val nativeArray = JavaOnlyArray.from(certificatesBase64)
143
+ assertThrows(
144
+ IllegalArgumentException::class.java
145
+ ) {
146
+ IoReactNativeIso18013Module.parseCertificates(nativeArray)
147
+ }
148
+ }
149
+
150
+ @Test
151
+ fun `should throw an IllegalArgumentException if an array of array of certificates is not provided`() {
152
+ val nativeArray = JavaOnlyArray.from("dGVzdA==".toList())
153
+ assertThrows(
154
+ IllegalArgumentException::class.java
155
+ ) {
156
+ IoReactNativeIso18013Module.parseCertificates(nativeArray)
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Tests for parseDocRequested
162
+ */
163
+
164
+ @OptIn(ExperimentalEncodingApi::class)
165
+ @Test
166
+ fun `should parse a valid set of documents with issuerSignedContent as base64`() {
167
+ val randomDocs = List(2) {
168
+ val randomBytes = ByteArray(10).apply { Random.nextBytes(this) }
169
+ val alias = UUID.randomUUID().toString()
170
+ val docType = UUID.randomUUID().toString()
171
+ DocRequested(randomBytes, alias, docType)
172
+ }
173
+ val nativeArray = JavaOnlyArray.from(
174
+ randomDocs.map { doc ->
175
+ JavaOnlyMap.of(
176
+ "alias", doc.alias,
177
+ "docType", doc.docType,
178
+ "issuerSignedContent", Base64.encode(doc.issuerSignedContent)
179
+ )
180
+ }
181
+ )
182
+ val result = IoReactNativeIso18013Module.parseDocRequested(nativeArray)
183
+ assert(areDocumentsArrayEqual(result, randomDocs.toTypedArray()))
184
+ }
185
+
186
+ @OptIn(ExperimentalEncodingApi::class)
187
+ @Test
188
+ fun `should parse a valid set of documents with issuerSignedContent as base64url`() {
189
+ val randomDocs = List(2) {
190
+ val randomBytes = ByteArray(10).apply { Random.nextBytes(this) }
191
+ val alias = UUID.randomUUID().toString()
192
+ val docType = UUID.randomUUID().toString()
193
+ DocRequested(randomBytes, alias, docType)
194
+ }
195
+ val nativeArray = JavaOnlyArray.from(
196
+ randomDocs.map { doc ->
197
+ JavaOnlyMap.of(
198
+ "alias", doc.alias,
199
+ "docType", doc.docType,
200
+ "issuerSignedContent", Base64.UrlSafe.encode(doc.issuerSignedContent)
201
+ )
202
+ }
203
+ )
204
+ val result = IoReactNativeIso18013Module.parseDocRequested(nativeArray)
205
+ assert(areDocumentsArrayEqual(result, randomDocs.toTypedArray()))
206
+ }
207
+
208
+ @Test
209
+ fun `should parse an empty set of documents`() {
210
+ val nativeArray = JavaOnlyArray()
211
+ val result = IoReactNativeIso18013Module.parseDocRequested(nativeArray)
212
+ assert(result.isEmpty())
213
+ }
214
+
215
+ @Test
216
+ fun `should throw an IllegalArgumentException if the document is missing the issuerSignedContent field`() {
217
+ val nativeArray = JavaOnlyArray.from(
218
+ listOf(
219
+ JavaOnlyMap.of("alias", "test", "docType", "test", "somethingElse", "test")
220
+ )
221
+ )
222
+ assertThrows(
223
+ IllegalArgumentException::class.java
224
+ ) {
225
+ IoReactNativeIso18013Module.parseDocRequested(nativeArray)
226
+ }
227
+ }
228
+
229
+ @Test
230
+ fun `should throw an IllegalArgumentException if the document issuerSignedContent field is null`() {
231
+ val nativeArray = JavaOnlyArray.from(
232
+ listOf(
233
+ JavaOnlyMap.of("alias", "test", "docType", "test", "issuerSignedContent", null)
234
+ )
235
+ )
236
+ assertThrows(
237
+ IllegalArgumentException::class.java
238
+ ) {
239
+ IoReactNativeIso18013Module.parseDocRequested(nativeArray)
240
+ }
241
+ }
242
+
243
+ @Test
244
+ fun `should throw an IllegalArgumentException if the document issuerSignedContent field is not a string`() {
245
+ val nativeArray = JavaOnlyArray.from(
246
+ listOf(
247
+ JavaOnlyMap.of("alias", "test", "docType", "test", "issuerSignedContent", 123)
248
+ )
249
+ )
250
+ assertThrows(
251
+ IllegalArgumentException::class.java
252
+ ) {
253
+ IoReactNativeIso18013Module.parseDocRequested(nativeArray)
254
+ }
255
+ }
256
+
257
+ @Test
258
+ fun `should throw an IllegalArgumentException if the document issuerSignedContent is not a valid base64 or base64url string`() {
259
+ val nativeArray = JavaOnlyArray.from(
260
+ listOf(
261
+ JavaOnlyMap.of(
262
+ "alias", "test", "docType", "test", "issuerSignedContent", "123~"
263
+ )
264
+ )
265
+ )
266
+ assertThrows(
267
+ IllegalArgumentException::class.java
268
+ ) {
269
+ IoReactNativeIso18013Module.parseDocRequested(nativeArray)
270
+ }
271
+ }
272
+
273
+ @Test
274
+ fun `should throw an IllegalArgumentException if the document is missing the alias field`() {
275
+ val nativeArray = JavaOnlyArray.from(
276
+ listOf(
277
+ JavaOnlyMap.of(
278
+ "somethingElse", "test", "docType", "test", "issuerSignedContent", "test"
279
+ )
280
+ )
281
+ )
282
+ assertThrows(
283
+ IllegalArgumentException::class.java
284
+ ) {
285
+ IoReactNativeIso18013Module.parseDocRequested(nativeArray)
286
+ }
287
+ }
288
+
289
+ @Test
290
+ fun `should throw an IllegalArgumentException if the document alias field is null`() {
291
+ val nativeArray = JavaOnlyArray.from(
292
+ listOf(
293
+ JavaOnlyMap.of(
294
+ "alias", null, "docType", "test", "issuerSignedContent", "test"
295
+ )
296
+ )
297
+ )
298
+ assertThrows(
299
+ IllegalArgumentException::class.java
300
+ ) {
301
+ IoReactNativeIso18013Module.parseDocRequested(nativeArray)
302
+ }
303
+ }
304
+
305
+ @Test
306
+ fun `should throw an IllegalArgumentException if the document alias field not a string`() {
307
+ val nativeArray = JavaOnlyArray.from(
308
+ listOf(
309
+ JavaOnlyMap.of(
310
+ "alias", 123, "docType", "test", "issuerSignedContent", "test"
311
+ )
312
+ )
313
+ )
314
+ assertThrows(
315
+ IllegalArgumentException::class.java
316
+ ) {
317
+ IoReactNativeIso18013Module.parseDocRequested(nativeArray)
318
+ }
319
+ }
320
+
321
+ @Test
322
+ fun `should throw an IllegalArgumentException if the document is missing the docType field`() {
323
+ val nativeArray = JavaOnlyArray.from(
324
+ listOf(
325
+ JavaOnlyMap.of(
326
+ "alias", "test", "somethingElse", "test", "issuerSignedContent", "test"
327
+ )
328
+ )
329
+ )
330
+ assertThrows(
331
+ IllegalArgumentException::class.java
332
+ ) {
333
+ IoReactNativeIso18013Module.parseDocRequested(nativeArray)
334
+ }
335
+ }
336
+
337
+ @Test
338
+ fun `should throw an IllegalArgumentException if the document docType field is null`() {
339
+ val nativeArray = JavaOnlyArray.from(
340
+ listOf(
341
+ JavaOnlyMap.of(
342
+ "alias", "test", "docType", null, "issuerSignedContent", "test"
343
+ )
344
+ )
345
+ )
346
+ assertThrows(
347
+ IllegalArgumentException::class.java
348
+ ) {
349
+ IoReactNativeIso18013Module.parseDocRequested(nativeArray)
350
+ }
351
+ }
352
+
353
+ @Test
354
+ fun `should throw an IllegalArgumentException if the document docType field is not a string`() {
355
+ val nativeArray = JavaOnlyArray.from(
356
+ listOf(
357
+ JavaOnlyMap.of(
358
+ "alias", "test", "docType", 123, "issuerSignedContent", "test"
359
+ )
360
+ )
361
+ )
362
+ assertThrows(
363
+ IllegalArgumentException::class.java
364
+ ) {
365
+ IoReactNativeIso18013Module.parseDocRequested(nativeArray)
366
+ }
367
+ }
368
+
369
+ @Test
370
+ fun `should throw an IllegalArgumentException if the elements in the array are not map of documents`() {
371
+ val nativeArray = JavaOnlyArray.from(
372
+ listOf(123, 123)
373
+ )
374
+ assertThrows(
375
+ IllegalArgumentException::class.java
376
+ ) {
377
+ IoReactNativeIso18013Module.parseDocRequested(nativeArray)
378
+ }
379
+ }
380
+
381
+ /**
382
+ * Tests for parseAcceptedFields
383
+ */
384
+
385
+ @Test
386
+ fun `should parse a valid map of accepted fields`() {
387
+ val nativeMap = JavaOnlyMap.of(
388
+ "org.iso.18013.5.1.mDL",
389
+ JavaOnlyMap.of(
390
+ "org.iso.18013.5.1",
391
+ JavaOnlyMap.of(
392
+ "hair_colour",
393
+ true,
394
+ "given_name_national_character",
395
+ true,
396
+ "family_name_national_character",
397
+ false
398
+ ),
399
+ "org.iso.18013.5.1_ext",
400
+ JavaOnlyMap.of(
401
+ "name", true, "surname", false
402
+ )
403
+ )
404
+ )
405
+ val result = IoReactNativeIso18013Module.parseAcceptedFields(nativeMap)
406
+ assert(result.contentEquals(nativeMap.toString()))
407
+ }
408
+
409
+ @Test
410
+ fun `should parse an empty map of accepted fields`() {
411
+ val nativeMap = JavaOnlyMap()
412
+ val result = IoReactNativeIso18013Module.parseAcceptedFields(nativeMap)
413
+ print(result)
414
+ assert(result == "{}")
415
+ }
416
+
417
+ @Test
418
+ fun `should throw an IllegalArgumentException if the credential type is not a map`() {
419
+ val nativeMap = JavaOnlyMap.of(
420
+ "org.iso.18013.5.1.mDL", 123
421
+ )
422
+ assertThrows(
423
+ IllegalArgumentException::class.java
424
+ ) {
425
+ IoReactNativeIso18013Module.parseAcceptedFields(nativeMap)
426
+ }
427
+ }
428
+
429
+ @Test
430
+ fun `should throw an IllegalArgumentException if the namespace type is not a map`() {
431
+ val nativeMap = JavaOnlyMap.of(
432
+ "org.iso.18013.5.1.mDL",
433
+ JavaOnlyMap.of(
434
+ "org.iso.18013.5.1",
435
+ JavaOnlyMap.of(
436
+ "hair_colour",
437
+ true,
438
+ "given_name_national_character",
439
+ true,
440
+ "family_name_national_character",
441
+ false
442
+ ),
443
+ "org.iso.18013.5.1_ext", 123
444
+ )
445
+ )
446
+ assertThrows(
447
+ IllegalArgumentException::class.java
448
+ ) {
449
+ IoReactNativeIso18013Module.parseAcceptedFields(nativeMap)
450
+ }
451
+ }
452
+
453
+ @Test
454
+ fun `should throw an IllegalArgumentException if no namespace are provided for the credential`() {
455
+ val nativeMap = JavaOnlyMap.of(
456
+ "org.iso.18013.5.1.mDL",
457
+ JavaOnlyMap()
458
+ )
459
+ assertThrows(
460
+ IllegalArgumentException::class.java
461
+ ) {
462
+ IoReactNativeIso18013Module.parseAcceptedFields(nativeMap)
463
+ }
464
+ }
465
+
466
+ @Test
467
+ fun `should throw an IllegalArgumentException if no fields are provided for the namespace`() {
468
+ val nativeMap = JavaOnlyMap.of(
469
+ "org.iso.18013.5.1.mDL",
470
+ JavaOnlyMap.of(
471
+ "org.iso.18013.5.1",
472
+ JavaOnlyMap()
473
+ )
474
+ )
475
+ assertThrows(
476
+ IllegalArgumentException::class.java
477
+ ) {
478
+ IoReactNativeIso18013Module.parseAcceptedFields(nativeMap)
479
+ }
480
+ }
481
+
482
+ @Test
483
+ fun `should throw an IllegalArgumentException if the field type is not a boolean`() {
484
+ val nativeMap = JavaOnlyMap.of(
485
+ "org.iso.18013.5.1.mDL",
486
+ JavaOnlyMap.of(
487
+ "org.iso.18013.5.1",
488
+ JavaOnlyMap.of(
489
+ "hair_colour",
490
+ true,
491
+ "given_name_national_character",
492
+ true,
493
+ "family_name_national_character",
494
+ false
495
+ ),
496
+ "org.iso.18013.5.1_ext",
497
+ JavaOnlyMap.of(
498
+ "name", true, "surname", 123
499
+ )
500
+ )
501
+ )
502
+ assertThrows(
503
+ IllegalArgumentException::class.java
504
+ ) {
505
+ IoReactNativeIso18013Module.parseAcceptedFields(nativeMap)
506
+ }
507
+ }
508
+ }
@@ -4,8 +4,15 @@ import Foundation
4
4
  * This class contains a set of utilities for encoding and decoding base64 and base64url strings.
5
5
  */
6
6
  class Base64Utils {
7
- enum Base64DecodingError: Error {
8
- case invalidBase64(String)
7
+ enum Base64DecodingError: LocalizedError {
8
+ case invalidBase64
9
+
10
+ var errorDescription: String? {
11
+ switch self {
12
+ case .invalidBase64:
13
+ return "Input is not a valid Base64 or Base64URL string"
14
+ }
15
+ }
9
16
  }
10
17
 
11
18
  /**
@@ -24,7 +31,7 @@ class Base64Utils {
24
31
  } else if let data = Data(base64Encoded: base) {
25
32
  return data
26
33
  } else {
27
- throw Base64DecodingError.invalidBase64("Input is not valid Base64 or Base64URL")
34
+ throw Base64DecodingError.invalidBase64
28
35
  }
29
36
  }
30
37
 
@@ -2,27 +2,27 @@
2
2
 
3
3
  @interface RCT_EXTERN_MODULE(IoReactNativeCbor, NSObject)
4
4
 
5
- RCT_EXTERN_METHOD(decode: (NSString)cbor
6
- resolver: (RCTPromiseResolveBlock)resolve
7
- rejecter: (RCTPromiseRejectBlock)reject)
8
-
9
- RCT_EXTERN_METHOD(decodeDocuments: (NSString)mdoc
10
- resolver: (RCTPromiseResolveBlock)resolve
11
- rejecter: (RCTPromiseRejectBlock)reject)
12
-
13
- RCT_EXTERN_METHOD(decodeIssuerSigned: (NSString)issuerSigned
14
- resolver: (RCTPromiseResolveBlock)resolve
15
- rejecter: (RCTPromiseRejectBlock)reject)
16
-
17
- RCT_EXTERN_METHOD(sign: (NSString)payload
18
- keyTag: (NSString*)keyTag
19
- resolver: (RCTPromiseResolveBlock)resolve
20
- rejecter: (RCTPromiseRejectBlock)reject)
21
-
22
- RCT_EXTERN_METHOD(verify: (NSString)sign1Data
23
- jwk: (NSDictionary*)jwk
24
- resolver: (RCTPromiseResolveBlock)resolve
25
- rejecter: (RCTPromiseRejectBlock)reject)
5
+ RCT_EXTERN_METHOD(decode: (NSString *)data
6
+ withResolver: (RCTPromiseResolveBlock)resolve
7
+ withRejecter: (RCTPromiseRejectBlock)reject)
8
+
9
+ RCT_EXTERN_METHOD(decodeDocuments: (NSString *)data
10
+ withResolver: (RCTPromiseResolveBlock)resolve
11
+ withRejecter: (RCTPromiseRejectBlock)reject)
12
+
13
+ RCT_EXTERN_METHOD(decodeIssuerSigned: (NSString *)data
14
+ withResolver: (RCTPromiseResolveBlock)resolve
15
+ withRejecter: (RCTPromiseRejectBlock)reject)
16
+
17
+ RCT_EXTERN_METHOD(sign: (NSString *)data
18
+ withKeyTag: (NSString *)keyTag
19
+ withResolver: (RCTPromiseResolveBlock)resolve
20
+ withRejecter: (RCTPromiseRejectBlock)reject)
21
+
22
+ RCT_EXTERN_METHOD(verify: (NSString *)data
23
+ withJwk: (NSDictionary *)jwk
24
+ withResolver: (RCTPromiseResolveBlock)resolve
25
+ withRejecter: (RCTPromiseRejectBlock)reject)
26
26
 
27
27
  + (BOOL)requiresMainQueueSetup
28
28
  {