| <!DOCTYPE html> |
| <meta charset=utf-8> |
| <title>Web NFC: Test exceptions in NFCWriter.push</title> |
| <link rel="author" title="Intel" href="http://www.intel.com"/> |
| <link rel="help" href="https://w3c.github.io/web-nfc/"/> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="resources/nfc-helpers.js"></script> |
| <script> |
| |
| "use strict"; |
| |
| const invalid_type_messages = |
| [ |
| // Invalid NDEFMessageSource type |
| undefined, |
| |
| // NDEFMessage.records: should have at least 1 valid record. |
| // https://w3c.github.io/web-nfc/#the-push-method - Step 8. |
| createMessage([{}]), |
| |
| // https://w3c.github.io/web-nfc/#dfn-map-text-to-ndef |
| // NDEFRecord must have data. |
| createMessage([createTextRecord()]), |
| |
| // NDEFRecord.data for 'text' record must be a string. |
| createMessage([createTextRecord(test_buffer_data)]), |
| createMessage([createTextRecord(test_json_data)]), |
| createMessage([createTextRecord(test_number_data)]), |
| |
| // https://w3c.github.io/web-nfc/#dfn-map-a-json-object-to-ndef |
| // NDEFRecord must have data. |
| createMessage([createJsonRecord()]), |
| |
| // https://w3c.github.io/web-nfc/#dfn-map-a-url-to-ndef |
| // NDEFRecord must have data. |
| createMessage([createUrlRecord()]), |
| |
| // NDEFRecord.data for 'url' record must be string. |
| createMessage([createUrlRecord(test_buffer_data)]), |
| createMessage([createUrlRecord(test_number_data)]), |
| createMessage([createUrlRecord(test_json_data)]), |
| |
| // https://w3c.github.io/web-nfc/#dfn-map-binary-data-to-ndef |
| // NDEFRecord must have data. |
| createMessage([createOpaqueRecord()]), |
| |
| // NDEFRecord.data for 'opaque' record must be ArrayBuffer. |
| createMessage([createOpaqueRecord(test_text_data)]), |
| createMessage([createOpaqueRecord(test_number_data)]), |
| createMessage([createOpaqueRecord(test_json_data)]) |
| ]; |
| |
| const invalid_syntax_messages = |
| [ |
| // NDEFRecord.mediaType for 'text' record must be 'text/*'. |
| createMessage([createRecord('text', 'application/json', |
| test_text_data)]), |
| |
| // Data for 'url' record, must be a valid URL. |
| createMessage([createUrlRecord('Invalid URL:// Data')]), |
| |
| // A JSON MIME type is any MIME type whose subtype ends in "+json" or |
| // whose essence is "application/json" or "text/json". |
| createMessage([createRecord('json', 'image/png', test_json_data)]), |
| createMessage([createRecord('json', 'application/x+y', test_json_data)]), |
| createMessage([createRecord('json', 'custom/app+jsonx', test_json_data)]), |
| ]; |
| |
| const invalid_signals = [ |
| "string", |
| 123, |
| {}, |
| true, |
| Symbol(), |
| () => {}, |
| self |
| ]; |
| |
| promise_test(async t => { |
| const writer = new NFCWriter(); |
| const promises = []; |
| invalid_type_messages.forEach(message => { |
| promises.push( |
| promise_rejects(t, new TypeError(), writer.push(message))); |
| }); |
| await Promise.all(promises); |
| }, "Test that promise is rejected with TypeError if NDEFMessageSource is invalid."); |
| |
| promise_test(async t => { |
| const writer = new NFCWriter(); |
| const promises = []; |
| invalid_syntax_messages.forEach(message => { |
| promises.push( |
| promise_rejects(t, 'SyntaxError', writer.push(message))); |
| }); |
| await Promise.all(promises); |
| }, "Test that promise is rejected with SyntaxError if NDEFMessageSource contains\ |
| invalid records."); |
| |
| nfc_test(async (t, mockNFC) => { |
| const writer = new NFCWriter(); |
| const controller = new AbortController(); |
| |
| //Make sure push is pending |
| mockNFC.setPendingPushCompleted(false); |
| const p = writer.push(test_text_data, |
| { signal: controller.signal, timeout: 100 }); |
| const rejected = promise_rejects(t, 'AbortError', p); |
| let callback_called = false; |
| await new Promise(resolve => { |
| t.step_timeout(() => { |
| callback_called = true; |
| controller.abort(); |
| resolve(); |
| }, 10); |
| }); |
| await rejected; |
| assert_true(callback_called, 'timeout should have caused the abort'); |
| }, "NFCWriter.push should fail if abort push request before push happends."); |
| |
| promise_test(async t => { |
| const writer = new NFCWriter(); |
| const controller = new AbortController(); |
| assert_false(controller.signal.aborted); |
| controller.abort(); |
| assert_true(controller.signal.aborted); |
| await promise_rejects(t, 'AbortError', |
| writer.push(test_text_data, { signal: controller.signal })); |
| }, "NFCWriter.push should fail if signal's aborted flag is set."); |
| |
| promise_test(async t => { |
| const writer = new NFCWriter(); |
| const promises = []; |
| invalid_signals.forEach(invalid_signal => { |
| promises.push(promise_rejects(t, new TypeError(), |
| writer.push(test_text_data, { signal: invalid_signal }))); |
| }); |
| await Promise.all(promises); |
| }, "NFCWriter.push should fail if signal is not an AbortSignal."); |
| |
| nfc_test(async (t, mockNFC) => { |
| const writer = new NFCWriter(); |
| mockNFC.setHWStatus(NFCHWStatus.DISABLED); |
| await promise_rejects(t, 'NotReadableError', writer.push(test_text_data)); |
| }, "NFCWriter.push should fail when NFC HW is disabled."); |
| |
| nfc_test(async (t, mockNFC) => { |
| const writer = new NFCWriter(); |
| mockNFC.setHWStatus(NFCHWStatus.NOT_SUPPORTED); |
| await promise_rejects(t, 'NotSupportedError', writer.push(test_text_data)); |
| }, "NFCWriter.push should fail when NFC HW is not supported."); |
| |
| promise_test(async t => { |
| const writer = new NFCWriter(); |
| await promise_rejects( |
| t, new TypeError(), writer.push(test_text_data, { timeout: "invalid"})); |
| }, "NFCWriter.push should fail with TypeError when invalid timeout is \ |
| provided."); |
| |
| promise_test(async t => { |
| const writer = new NFCWriter(); |
| await promise_rejects( |
| t, new TypeError(), writer.push(test_text_data, { timeout: -1 })); |
| }, "NFCWriter.push should fail with TypeError when invalid negative timeout \ |
| value is provided."); |
| |
| nfc_test(async (t, mockNFC) => { |
| const writer = new NFCWriter(); |
| mockNFC.setPendingPushCompleted(false); |
| const p = writer.push(test_text_data, { timeout: 1 }); |
| mockNFC.setPushShouldTimeout(true); |
| await promise_rejects(t, 'TimeoutError', p); |
| }, "NFCWriter.push should fail with TimeoutError when timer expires."); |
| |
| promise_test(async t => { |
| const writer = new NFCWriter(); |
| await promise_rejects( |
| t, 'NotSupportedError', writer.push(new ArrayBuffer(32 * 1024 + 1))); |
| }, "Reject promise with NotSupportedError if NFC message size exceeds 32KB."); |
| |
| promise_test(async t => { |
| const writer = new NFCWriter(); |
| const message = createMessage([createTextRecord(test_text_data)]); |
| message.url = '%00/invalid/ path'; |
| await promise_rejects(t, 'SyntaxError', writer.push(message)); |
| }, "Reject promise with SyntaxError if WebNFC Id cannot be created from \ |
| provided URL."); |
| |
| promise_test(async t => { |
| const writer = new NFCWriter(); |
| const message = createMessage([createRecord('json','application/json', |
| { get x(){ return this; } })]); |
| await promise_rejects(t, new TypeError(), writer.push(message)); |
| }, "Reject promise with exceptions thrown from serializing the 'json' record data."); |
| |
| promise_test(async t => { |
| const writer = new NFCWriter(); |
| await promise_rejects( |
| t, new TypeError(), writer.push(test_text_data, {target: "invalid"})); |
| }, "NFCWriter.push should fail with TypeError when invalid target value is \ |
| provided."); |
| |
| promise_test(async () => { |
| await new Promise((resolve,reject) => { |
| const iframe = document.createElement('iframe'); |
| iframe.srcdoc = `<script> |
| window.onmessage = message => { |
| if (message.data === "Ready") { |
| const onSuccess = () => { |
| parent.postMessage("Failure", "*"); |
| }; |
| const onError = error => { |
| if (error.name == "NotAllowedError") { |
| parent.postMessage("Success", "*"); |
| } else { |
| parent.postMessage("Failure", "*"); |
| } |
| }; |
| try { |
| const writer = new NFCWriter(); |
| writer.push("Test").then(onSuccess, onError); |
| } catch(e) { |
| parent.postMessage("Failure", "*"); |
| } |
| } |
| }; |
| <\/script>`; |
| iframe.onload = () => iframe.contentWindow.postMessage('Ready', '*'); |
| document.body.appendChild(iframe); |
| window.onmessage = message => { |
| if (message.data == 'Success') { |
| resolve(); |
| } else if (message.data == 'Failure') { |
| reject(); |
| } |
| } |
| }); |
| }, 'Test that WebNFC API is not accessible from iframe context.'); |
| |
| nfc_test(async () => { |
| const writer = new NFCWriter(); |
| await writer.push(test_text_data, { timeout: 1 }); |
| }, 'NFCWriter.push should succeed when NFC HW is enabled'); |
| |
| nfc_test(async (t, mockNFC) => { |
| const writer = new NFCWriter(); |
| let message = createMessage([createTextRecord(test_text_data), |
| createJsonRecord(test_json_data), |
| createJsonRecord(test_number_data), |
| createOpaqueRecord(test_buffer_data), |
| createUrlRecord(test_url_data)], |
| test_message_origin); |
| await writer.push(message); |
| assertNDEFMessagesEqual(message, mockNFC.pushedMessage()); |
| }, "NFCWriter.push NDEFMessage containing text, json, opaque and url records \ |
| with default NFCPushOptions."); |
| |
| nfc_test(async (t, mockNFC) => { |
| const writer = new NFCWriter(); |
| await writer.push(test_text_data); |
| assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage()); |
| }, "Test that NFCWriter.push succeeds when message is DOMString."); |
| |
| nfc_test(async (t, mockNFC) => { |
| const writer = new NFCWriter(); |
| await writer.push(test_buffer_data); |
| assertNDEFMessagesEqual(test_buffer_data, mockNFC.pushedMessage()); |
| }, "Test that NFCWriter.push succeeds when message is ArrayBuffer."); |
| |
| nfc_test(async () => { |
| const writer = new NFCWriter(); |
| await writer.push(createMessage([createRecord('empty')])); |
| }, "NFCWriter.push with 'empty' record should succeed."); |
| |
| nfc_test(async (t, mockNFC) => { |
| const writer = new NFCWriter(); |
| await writer.push(test_text_data); |
| assertNFCPushOptionsEqual(createNFCPushOptions('any', Infinity, true), |
| mockNFC.pushOptions()); |
| }, "Check that default NFCPushOptions values are correctly set."); |
| |
| nfc_test(async (t, mockNFC) => { |
| const writer = new NFCWriter(); |
| let nfcPushOptions = createNFCPushOptions('tag', 1, false); |
| await writer.push(test_text_data, nfcPushOptions); |
| assertNFCPushOptionsEqual(nfcPushOptions, mockNFC.pushOptions()); |
| }, "Check that provided NFCPushOptions values are correctly converted."); |
| |
| nfc_test(async (t, mockNFC) => { |
| const writer1 = new NFCWriter(); |
| const writer2 = new NFCWriter(); |
| const controller = new AbortController(); |
| mockNFC.setPendingPushCompleted(false); |
| const p1 = writer1.push(test_text_data, |
| { signal: controller.signal, timeout: 100 }); |
| |
| // Even though push request is grantable, |
| // this abort should be processed synchronously. |
| controller.abort(); |
| await promise_rejects(t, 'AbortError', p1); |
| |
| await writer2.push(test_text_data); |
| assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage()); |
| }, "Synchronously signaled abort."); |
| |
| </script> |