constructor-validate-payment-method-data.https.html (14412B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <meta name="timeout" content="long"> 4 <title>Tests for the 'secure-payment-confirmation' steps to validate payment method data</title> 5 <link rel="help" href="https://w3c.github.io/secure-payment-confirmation/#sctn-steps-to-validate-payment-method-data"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script> 9 'use strict'; 10 11 const details = {total: 12 {label: 'Total', amount: {value: '0.01', currency: 'USD'}}}; 13 14 // This file contains tests for the 'steps to validate payment method data', 15 // which occurs during construction of the PaymentRequest. For general tests 16 // around construction, see constructor.https.html. 17 18 test(() => { 19 assert_throws_js(RangeError, () => { 20 new PaymentRequest([{ 21 supportedMethods: 'secure-payment-confirmation', 22 data: { 23 relyingPartyId: 'relying-party.example', 24 // Empty credentialIds field. 25 credentialIds: [], 26 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 27 payeeOrigin: window.location.origin, 28 timeout: 60000, 29 instrument: { 30 displayName: 'X', 31 icon: 'https://example.test/icon.png', 32 }, 33 rpId: 'relying-party.example', 34 }, 35 }], details); 36 }); 37 }, 'Empty credentialIds field throws exception.'); 38 39 test(() => { 40 assert_throws_js(RangeError, () => { 41 new PaymentRequest([{ 42 supportedMethods: 'secure-payment-confirmation', 43 data: { 44 relyingPartyId: 'relying-party.example', 45 credentialIds: [ 46 Uint8Array.from('c1', c => c.charCodeAt(0)), 47 new Uint8Array(), // Empty 48 Uint8Array.from('c2', c => c.charCodeAt(0)), 49 ], 50 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 51 payeeOrigin: window.location.origin, 52 timeout: 60000, 53 instrument: { 54 displayName: 'X', 55 icon: 'https://example.test/icon.png', 56 }, 57 rpId: 'relying-party.example', 58 }, 59 }], details); 60 }); 61 }, 'Empty ID within credentialIds field throws exception.'); 62 63 test(() => { 64 new PaymentRequest([{ 65 supportedMethods: 'secure-payment-confirmation', 66 data: { 67 credentialIds: [ 68 Uint8Array.from('c1', c => c.charCodeAt(0)), 69 Uint8Array.from('c2', c => c.charCodeAt(0)) 70 ], 71 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 72 // Omitted payee origin, instead with payee name. 73 payeeName: 'Example Merchant', 74 timeout: 60000, 75 instrument: { 76 displayName: 'X', 77 icon: 'https://example.test/icon.png', 78 }, 79 rpId: 'relying-party.example', 80 }, 81 }], details); 82 }, 'Multiple IDs in credentialIds is valid.'); 83 84 test(() => { 85 assert_throws_js(TypeError, () => { 86 new PaymentRequest([{ 87 supportedMethods: 'secure-payment-confirmation', 88 data: { 89 // Large credentialIds value. 90 credentialIds: [Uint8Array.from( 91 'x'.repeat(1024 * 1024), c => c.charCodeAt(0))], 92 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 93 payeeOrigin: window.location.origin, 94 timeout: 60000, 95 instrument: { 96 displayName: 'X', 97 icon: 'https://example.test/icon.png', 98 }, 99 rpId: 'relying-party.example', 100 }, 101 }], details); 102 }); 103 }, 'Large credentialIds value throws exception.'); 104 105 test(() => { 106 assert_throws_js(TypeError, () => { 107 new PaymentRequest([{ 108 supportedMethods: 'secure-payment-confirmation', 109 data: { 110 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 111 // Null challenge fields. 112 challenge: null, 113 payeeOrigin: window.location.origin, 114 timeout: 60000, 115 instrument: { 116 displayName: 'X', 117 icon: 'https://example.test/icon.png', 118 }, 119 rpId: 'relying-party.example', 120 }, 121 }], details); 122 }); 123 }, 'Null challenge field throws exception.'); 124 125 test(() => { 126 assert_throws_js(TypeError, () => { 127 new PaymentRequest([{ 128 supportedMethods: 'secure-payment-confirmation', 129 data: { 130 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 131 // Empty challenge fields. 132 challenge: [], 133 payeeOrigin: window.location.origin, 134 timeout: 60000, 135 instrument: { 136 displayName: 'X', 137 icon: 'https://example.test/icon.png', 138 }, 139 rpId: 'relying-party.example', 140 }, 141 }], details); 142 }); 143 }, 'Empty challenge field throws exception.'); 144 145 test(() => { 146 assert_throws_js(TypeError, () => { 147 new PaymentRequest([{ 148 supportedMethods: 'secure-payment-confirmation', 149 data: { 150 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 151 // Large challenge value. 152 challenge: Uint8Array.from('x'.repeat(1024 * 1024), c => c.charCodeAt(0)), 153 payeeOrigin: window.location.origin, 154 timeout: 60000, 155 instrument: { 156 displayName: 'X', 157 icon: 'https://example.test/icon.png', 158 }, 159 rpId: 'relying-party.example', 160 }, 161 }], details); 162 }); 163 }, 'Large challenge value throws exception.'); 164 165 test(() => { 166 assert_throws_js(TypeError, () => { 167 new PaymentRequest([{ 168 supportedMethods: 'secure-payment-confirmation', 169 data: { 170 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 171 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 172 payeeOrigin: window.location.origin, 173 timeout: 60000, 174 instrument: { 175 displayName: '', 176 icon: 'https://example.test/icon.png', 177 }, 178 rpId: 'relying-party.example', 179 }, 180 }], details); 181 }); 182 }, 'Empty instrument.displayName field throws exception.'); 183 184 test(() => { 185 assert_throws_js(TypeError, () => { 186 new PaymentRequest([{ 187 supportedMethods: 'secure-payment-confirmation', 188 data: { 189 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 190 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 191 payeeOrigin: window.location.origin, 192 timeout: 60000, 193 instrument: { 194 displayName: 'X', 195 icon: '', 196 }, 197 rpId: 'relying-party.example', 198 }, 199 }], details); 200 }); 201 }, 'Empty instrument.icon field throws exception.'); 202 203 test(() => { 204 assert_throws_js(TypeError, () => { 205 new PaymentRequest([{ 206 supportedMethods: 'secure-payment-confirmation', 207 data: { 208 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 209 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 210 payeeOrigin: window.location.origin, 211 timeout: 60000, 212 instrument: { 213 displayName: 'X', 214 icon: 'thisisnotaurl', 215 }, 216 rpId: 'relying-party.example', 217 }, 218 }], details); 219 }); 220 }, 'Invalid instrument.icon URL throws exception.'); 221 222 test(() => { 223 assert_throws_js(TypeError, () => { 224 new PaymentRequest([{ 225 supportedMethods: 'secure-payment-confirmation', 226 data: { 227 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 228 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 229 payeeOrigin: window.location.origin, 230 timeout: 60000, 231 instrument: { 232 displayName: 'X', 233 icon: 'https://example.test/icon.png', 234 // Details can be omitted, but if present cannot be empty. 235 details: '', 236 }, 237 rpId: 'relying-party.example', 238 }, 239 }], details); 240 }); 241 }, 'Empty instrument.details field throws exception.'); 242 243 test(() => { 244 assert_throws_js(TypeError, () => { 245 new PaymentRequest([{ 246 supportedMethods: 'secure-payment-confirmation', 247 data: { 248 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 249 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 250 payeeOrigin: window.location.origin, 251 timeout: 60000, 252 instrument: { 253 displayName: 'X', 254 icon: 'https://example.test/icon.png', 255 }, 256 rpId: 'domains cannot have spaces.com', 257 }, 258 }], details); 259 }); 260 }, 'Invalid rpId field throws exception.'); 261 262 test(() => { 263 assert_throws_js(TypeError, () => { 264 new PaymentRequest([{ 265 supportedMethods: 'secure-payment-confirmation', 266 data: { 267 // Omitted payee origin and payee name. 268 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 269 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 270 timeout: 60000, 271 instrument: { 272 displayName: 'X', 273 icon: 'https://example.test/icon.png', 274 }, 275 rpId: 'relying-party.example', 276 }, 277 }], details); 278 }); 279 }, 'Omitting both payee origin and payee name throws exception.'); 280 281 test(() => { 282 new PaymentRequest([{ 283 supportedMethods: 'secure-payment-confirmation', 284 data: { 285 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 286 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 287 // Omitted payee origin, instead with payee name. 288 payeeName: 'Example Merchant', 289 timeout: 60000, 290 instrument: { 291 displayName: 'X', 292 icon: 'https://example.test/icon.png', 293 }, 294 rpId: 'relying-party.example', 295 }, 296 }], details); 297 }, 'Payee name without payee origin is valid.'); 298 299 test(() => { 300 new PaymentRequest([{ 301 supportedMethods: 'secure-payment-confirmation', 302 data: { 303 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 304 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 305 // Both payee origin and payee name. 306 payeeName: 'Example Merchant', 307 payeeOrigin: window.location.origin, 308 timeout: 60000, 309 instrument: { 310 displayName: 'X', 311 icon: 'https://example.test/icon.png', 312 }, 313 rpId: 'relying-party.example', 314 }, 315 }], details); 316 }, 'Providing both payee name and payee origin is valid.'); 317 318 test(() => { 319 assert_throws_js(TypeError, () => { 320 new PaymentRequest([{ 321 supportedMethods: 'secure-payment-confirmation', 322 data: { 323 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 324 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 325 // Empty payee name 326 payeeName: '', 327 payeeOrigin: window.location.origin, 328 timeout: 60000, 329 instrument: { 330 displayName: 'X', 331 icon: 'https://example.test/icon.png', 332 }, 333 rpId: 'relying-party.example', 334 }, 335 }], details); 336 }); 337 }, 'Empty payee name throws exception.'); 338 339 test(() => { 340 assert_throws_js(TypeError, () => { 341 new PaymentRequest([{ 342 supportedMethods: 'secure-payment-confirmation', 343 data: { 344 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 345 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 346 payeeName: 'Example Merchant', 347 // Empty payee origin 348 payeeOrigin: '', 349 timeout: 60000, 350 instrument: { 351 displayName: 'X', 352 icon: 'https://example.test/icon.png', 353 }, 354 rpId: 'relying-party.example', 355 }, 356 }], details); 357 }); 358 }, 'Empty payee origin throws exception.'); 359 360 test(() => { 361 assert_throws_js(TypeError, () => { 362 new PaymentRequest([{ 363 supportedMethods: 'secure-payment-confirmation', 364 data: { 365 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 366 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 367 payeeName: 'Example Merchant', 368 payeeOrigin: 'http://thepayee.com', 369 timeout: 60000, 370 instrument: { 371 displayName: 'X', 372 icon: 'https://example.test/icon.png', 373 }, 374 rpId: 'relying-party.example', 375 }, 376 }], details); 377 }); 378 }, 'Non-HTTPS payee origin throws exception.'); 379 380 test(() => { 381 new PaymentRequest([{ 382 supportedMethods: 'secure-payment-confirmation', 383 data: { 384 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 385 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 386 payeeOrigin: window.location.origin, 387 timeout: 60000, 388 instrument: { 389 displayName: 'X', 390 icon: 'https://example.test/icon.png', 391 }, 392 rpId: 'relying-party.example', 393 paymentEntitiesLogos: [], 394 }, 395 }], details); 396 }, 'Empty paymentEntitiesLogo field is valid.'); 397 398 test(() => { 399 assert_throws_js(TypeError, () => { 400 new PaymentRequest([{ 401 supportedMethods: 'secure-payment-confirmation', 402 data: { 403 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 404 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 405 payeeOrigin: window.location.origin, 406 timeout: 60000, 407 instrument: { 408 displayName: 'X', 409 icon: 'https://example.test/icon.png', 410 }, 411 rpId: 'relying-party.example', 412 paymentEntitiesLogos: [{ 413 url: '', 414 label: 'Payment Entity Label', 415 }], 416 }, 417 }], details); 418 }); 419 }, 'Empty url field in a PaymentEntityLogo throws exception.'); 420 421 test(() => { 422 assert_throws_js(TypeError, () => { 423 new PaymentRequest([{ 424 supportedMethods: 'secure-payment-confirmation', 425 data: { 426 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 427 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 428 payeeOrigin: window.location.origin, 429 timeout: 60000, 430 instrument: { 431 displayName: 'X', 432 icon: 'https://example.test/icon.png', 433 }, 434 rpId: 'relying-party.example', 435 paymentEntitiesLogos: [{ 436 url: 'thisisnotaurl', 437 label: 'Payment Entity Label', 438 }], 439 }, 440 }], details); 441 }); 442 }, 'Invalid url field in a PaymentEntityLogo throws exception.'); 443 444 test(() => { 445 assert_throws_js(TypeError, () => { 446 new PaymentRequest([{ 447 supportedMethods: 'secure-payment-confirmation', 448 data: { 449 credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))], 450 challenge: Uint8Array.from('x', c => c.charCodeAt(0)), 451 payeeOrigin: window.location.origin, 452 timeout: 60000, 453 instrument: { 454 displayName: 'X', 455 icon: 'https://example.test/icon.png', 456 }, 457 rpId: 'relying-party.example', 458 paymentEntitiesLogos: [{ 459 url: 'https://example.test/logo.png', 460 label: '', 461 }], 462 }, 463 }], details); 464 }); 465 }, 'Empty logo field in a PaymentEntityLogo throws exception.'); 466 </script>