NDEFReader_scan.https.html (12922B)
1 <!DOCTYPE html> 2 <meta charset=utf-8> 3 <title>Web NFC: NDEFReader.scan tests</title> 4 <link rel="author" title="Intel" href="http://www.intel.com"/> 5 <link rel="help" href="https://w3c.github.io/web-nfc/"/> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="resources/nfc-helpers.js"></script> 9 <script> 10 11 "use strict"; 12 13 const invalid_signals = [ 14 "string", 15 123, 16 {}, 17 true, 18 Symbol(), 19 () => {}, 20 self 21 ]; 22 23 function waitSyntaxErrorPromise(t, scan_options) { 24 const ndef = new NDEFReader(); 25 return promise_rejects_dom(t, 'SyntaxError', ndef.scan(scan_options)); 26 } 27 28 nfc_test(async t => { 29 const ndef = new NDEFReader(); 30 const promises = []; 31 invalid_signals.forEach(invalid_signal => { 32 promises.push(promise_rejects_js(t, TypeError, 33 ndef.scan({ signal: invalid_signal }))); 34 }); 35 await Promise.all(promises); 36 }, "Test that NDEFReader.scan rejects if signal is not an AbortSignal."); 37 38 nfc_test(async t => { 39 await test_driver.set_permission({ name: 'nfc' }, 'denied'); 40 const ndef = new NDEFReader(); 41 await promise_rejects_dom(t, 'NotAllowedError', ndef.scan()); 42 }, "NDEFReader.scan should fail if user permission is not granted."); 43 44 // We do not provide NFC mock here to simulate that there has no available 45 // implementation for NFC Mojo interface. 46 nfc_test(async (t, mockNFC) => { 47 mockNFC.simulateClosedPipe(); 48 const ndef = new NDEFReader(); 49 await promise_rejects_dom(t, 'NotSupportedError', ndef.scan()); 50 }, "NDEFReader.scan should fail if no implementation for NFC Mojo interface."); 51 52 nfc_test(async (t, mockNFC) => { 53 mockNFC.setHWStatus(NFCHWStatus.DISABLED); 54 const ndef = new NDEFReader(); 55 await promise_rejects_dom(t, 'NotReadableError', ndef.scan()); 56 }, "NDEFReader.scan should fail if NFC HW is disabled."); 57 58 nfc_test(async (t, mockNFC) => { 59 mockNFC.setHWStatus(NFCHWStatus.NOT_SUPPORTED); 60 const ndef = new NDEFReader(); 61 await promise_rejects_dom(t, 'NotSupportedError', ndef.scan()); 62 }, "NDEFReader.scan should fail if NFC HW is not supported."); 63 64 nfc_test(async () => { 65 await new Promise((resolve,reject) => { 66 const iframe = document.createElement('iframe'); 67 iframe.srcdoc = `<script> 68 window.onmessage = async (message) => { 69 if (message.data === "Ready") { 70 try { 71 const ndef = new NDEFReader(); 72 await ndef.scan(); 73 parent.postMessage("Failure", "*"); 74 } catch (error) { 75 if (error.name == "InvalidStateError") { 76 parent.postMessage("Success", "*"); 77 } else { 78 parent.postMessage("Failure", "*"); 79 } 80 } 81 } 82 }; 83 <\/script>`; 84 iframe.onload = () => iframe.contentWindow.postMessage('Ready', '*'); 85 document.body.appendChild(iframe); 86 window.onmessage = message => { 87 if (message.data == 'Success') { 88 resolve(); 89 } else if (message.data == 'Failure') { 90 reject(); 91 } 92 } 93 }); 94 }, 'Test that WebNFC API is not accessible from iframe context.'); 95 96 nfc_test(async (t, mockNFC) => { 97 const ndef = new NDEFReader(); 98 const controller = new AbortController(); 99 const ndefWatcher = new EventWatcher(t, ndef, ["reading", "readingerror"]); 100 const promise = ndefWatcher.wait_for("reading").then(event => { 101 assert_true(event instanceof NDEFReadingEvent); 102 controller.abort(); 103 }); 104 await ndef.scan({signal : controller.signal}); 105 106 mockNFC.setReadingMessage(createMessage([createTextRecord(test_text_data)])); 107 await promise; 108 }, "Test that nfc watch success if NFC HW is enabled."); 109 110 nfc_test(async (t, mockNFC) => { 111 const ndef = new NDEFReader(); 112 const controller = new AbortController(); 113 controller.abort(); 114 await promise_rejects_dom(t, 'AbortError', ndef.scan({signal: controller.signal})); 115 }, "Test that NDEFReader.scan rejects if NDEFScanOptions.signal is already aborted."); 116 117 nfc_test(async (t, mockNFC) => { 118 const ndef = new NDEFReader(); 119 const controller = new AbortController(); 120 const promise = ndef.scan({signal: controller.signal}); 121 controller.abort(); 122 await promise_rejects_dom(t, 'AbortError', promise); 123 }, "Test that NDEFReader.scan rejects if NDEFScanOptions.signal aborts right after \ 124 the scan invocation."); 125 126 nfc_test(async () => { 127 const ndef = new NDEFReader(); 128 129 const controller1 = new AbortController(); 130 await ndef.scan({signal: controller1.signal}); 131 132 controller1.abort(); 133 134 const controller2 = new AbortController(); 135 await ndef.scan({signal: controller2.signal}); 136 }, "Test that NDEFReader.scan signals are independant."); 137 138 nfc_test(async (t, mockNFC) => { 139 const ndef = new NDEFReader(); 140 const controller = new AbortController(); 141 const ndefWatcher = new EventWatcher(t, ndef, ["reading", "readingerror"]); 142 const message = createMessage([createTextRecord(test_text_data)]); 143 const promise = ndefWatcher.wait_for("reading").then(event => { 144 assert_true(event instanceof NDEFReadingEvent); 145 }); 146 await ndef.scan({signal : controller.signal}); 147 148 mockNFC.setReadingMessage(message); 149 await promise; 150 151 ndef.onreading = t.unreached_func("reading event should not be fired."); 152 mockNFC.setReadingMessage(message); 153 controller.abort(); 154 await new Promise((resolve, reject) => { 155 t.step_timeout(resolve, 100); 156 }); 157 }, "Test that NDEFReader can not get any reading events once the signal aborts."); 158 159 nfc_test(async (t, mockNFC) => { 160 const ndef = new NDEFReader(); 161 const controller = new AbortController(); 162 const ndefWatcher = new EventWatcher(t, ndef, ["reading", "readingerror"]); 163 const promise = ndefWatcher.wait_for("reading").then(event => { 164 controller.abort(); 165 assert_true(event instanceof NDEFReadingEvent); 166 167 // The message in the event contains only the external type record. 168 assert_equals(event.message.records.length, 1); 169 assert_equals(event.message.records[0].recordType, 'example.com:containsLocalRecord', 170 'recordType'); 171 172 // The external type record contains only the local type record. 173 assert_equals(event.message.records[0].toRecords().length, 1); 174 assert_equals(event.message.records[0].toRecords()[0].recordType, ':containsTextRecord', 175 'recordType'); 176 177 // The local type record contains only the text record. 178 assert_equals(event.message.records[0].toRecords()[0].toRecords()[0].recordType, 'text', 179 'recordType'); 180 const decoder = new TextDecoder(); 181 assert_equals(decoder.decode(event.message.records[0].toRecords()[0].toRecords()[0].data), 182 test_text_data, 'data has the same content with the original dictionary'); 183 }); 184 await ndef.scan({signal : controller.signal}); 185 186 // An external type record --contains-> a local type record --contains-> a text record. 187 const messageContainText = createMessage([createTextRecord(test_text_data)]); 188 const messageContainLocal= createMessage([createRecord(':containsTextRecord', 189 messageContainText)]); 190 const message = createMessage([createRecord('example.com:containsLocalRecord', 191 messageContainLocal)]); 192 mockNFC.setReadingMessage(message); 193 await promise; 194 }, "NDEFRecord.toRecords returns its embedded records correctly."); 195 196 nfc_test(async (t, mockNFC) => { 197 const ndef = new NDEFReader(); 198 const controller = new AbortController(); 199 const ndefWatcher = new EventWatcher(t, ndef, ["reading", "readingerror"]); 200 const promise = ndefWatcher.wait_for("reading").then(event => { 201 controller.abort(); 202 assert_true(event instanceof NDEFReadingEvent); 203 204 // The message in the event contains only the smart-poster record. 205 assert_equals(event.message.records.length, 1); 206 assert_equals(event.message.records[0].recordType, 'smart-poster', 'recordType'); 207 assert_equals(event.message.records[0].mediaType, null, 'mediaType'); 208 assert_equals(event.message.records[0].id, 'dummy_record_id', 'id'); 209 210 // The smart-poster record contains one uri record and one text record. 211 const embedded_records = event.message.records[0].toRecords(); 212 assert_equals(embedded_records.length, 2); 213 214 const decoder = new TextDecoder(); 215 let embedded_record_types = []; 216 for(let record of embedded_records) { 217 embedded_record_types.push(record.recordType); 218 switch(record.recordType) { 219 case 'url': 220 assert_equals(record.mediaType, null, 'url record\'s mediaType'); 221 assert_equals(record.id, test_record_id, 'url record\'s id'); 222 assert_equals(decoder.decode(record.data), test_url_data, 'url record\'s data'); 223 break; 224 case 'text': 225 assert_equals(record.mediaType, null, 'text record\'s mediaType'); 226 assert_equals(record.id, test_record_id, 'text record\'s id'); 227 assert_equals(decoder.decode(record.data), test_text_data, 'text record\'s data'); 228 break; 229 default: 230 assert_unreached("Unknown recordType"); 231 } 232 } 233 assert_array_equals(embedded_record_types.sort(), ['text', 'url'], 234 'smart-poster record\'s contained record types'); 235 }); 236 await ndef.scan({signal : controller.signal}); 237 238 // A smart-poster record contains a uri record, text record. 239 const uri_record = createUrlRecord(test_url_data); 240 const text_record = createTextRecord(test_text_data); 241 const payload_message = createMessage([uri_record, text_record]); 242 const message = createMessage([createRecord( 243 'smart-poster', payload_message, "dummy_record_id")]); 244 mockNFC.setReadingMessage(message); 245 await promise; 246 }, "NDEFReader.scan returns smart-poster record correctly."); 247 248 nfc_test(async (t, mockNFC) => { 249 const promises = []; 250 251 const ndef1 = new NDEFReader(); 252 const ndefWatcher1 = new EventWatcher(t, ndef1, ["reading", "readingerror"]); 253 const promise1 = ndefWatcher1.wait_for("readingerror"); 254 promises.push(promise1); 255 await ndef1.scan(); 256 257 const ndef2 = new NDEFReader(); 258 const ndefWatcher2 = new EventWatcher(t, ndef2, ["reading", "readingerror"]); 259 const promise2 = ndefWatcher2.wait_for("readingerror"); 260 promises.push(promise2); 261 await ndef2.scan(); 262 263 mockNFC.simulateNonNDEFTagDiscovered(); 264 await Promise.all(promises); 265 }, "Test that NDEFReader.onreadingerror should be fired if the NFC tag does not \ 266 expose NDEF technology."); 267 268 nfc_test(async (t, mockNFC) => { 269 const ndef = new NDEFReader(); 270 const controller = new AbortController(); 271 const ndefWatcher = new EventWatcher(t, ndef, ["reading", "readingerror"]); 272 const promise = ndefWatcher.wait_for("reading").then(event => { 273 assert_equals(event.serialNumber, fake_tag_serial_number); 274 assert_equals(event.message.records.length, 0); 275 controller.abort(); 276 }); 277 await ndef.scan({signal : controller.signal}); 278 279 mockNFC.setReadingMessage({ records: [] }); 280 await promise; 281 }, "Test that NDEFReader.onreading should be fired on an unformatted NFC tag \ 282 with empty records array for NDEFMessage."); 283 284 nfc_test(async (t, mockNFC) => { 285 const ndef = new NDEFReader(); 286 const controller = new AbortController(); 287 const message = createMessage([createTextRecord(test_text_data), 288 createMimeRecordFromJson(test_json_data), 289 createMimeRecord(test_buffer_data), 290 createUnknownRecord(test_buffer_data), 291 createUrlRecord(test_url_data), 292 createUrlRecord(test_url_data, true), 293 createRecord('w3.org:xyz', test_buffer_data)], 294 test_message_origin); 295 const ndefWatcher = new EventWatcher(t, ndef, ["reading", "readingerror"]); 296 const promise = ndefWatcher.wait_for("reading").then(event => { 297 assert_equals(event.serialNumber, fake_tag_serial_number); 298 assertWebNDEFMessagesEqual(event.message, new NDEFMessage(message)); 299 controller.abort(); 300 }); 301 await ndef.scan({signal : controller.signal}); 302 303 mockNFC.setReadingMessage(message); 304 await promise; 305 }, "Test that reading message with multiple records should succeed."); 306 307 nfc_test(async (t, mockNFC) => { 308 const ndef = new NDEFReader(); 309 const promise1 = ndef.scan(); 310 const promise2 = promise_rejects_dom(t, 'InvalidStateError', ndef.scan()); 311 await promise1; 312 await promise2; 313 await promise_rejects_dom(t, 'InvalidStateError', ndef.scan()); 314 }, "Test that NDEFReader.scan rejects if there is already an ongoing scan."); 315 316 nfc_test(async (t, mockNFC) => { 317 const ndef = new NDEFReader(); 318 const controller = new AbortController(); 319 await ndef.scan({signal : controller.signal}); 320 controller.abort(); 321 await ndef.scan(); 322 }, "Test that NDEFReader.scan can be started after the previous scan is aborted."); 323 </script>