summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/web-nfc/NDEFReader_write.https.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/web-nfc/NDEFReader_write.https.html')
-rw-r--r--testing/web-platform/tests/web-nfc/NDEFReader_write.https.html480
1 files changed, 480 insertions, 0 deletions
diff --git a/testing/web-platform/tests/web-nfc/NDEFReader_write.https.html b/testing/web-platform/tests/web-nfc/NDEFReader_write.https.html
new file mode 100644
index 0000000000..0463b779de
--- /dev/null
+++ b/testing/web-platform/tests/web-nfc/NDEFReader_write.https.html
@@ -0,0 +1,480 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Web NFC: NDEFReader.write Tests</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-write-method - Step 8.
+ createMessage([{}]),
+
+ // NDEFMessageSource: not NDEF-formatable.
+ // https://w3c.github.io/web-nfc/#the-write-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 either a string,
+ // an arrayBuffer, or an arrayBufferView.
+ createMessage([createTextRecord(test_json_data)]),
+
+ // NDEFRecord.encoding for 'text' record must be either "utf-8",
+ // "utf-16", "utf-16le" or "utf-16be".
+ createMessage([createTextRecord(test_buffer_data, "chinese")]),
+
+ // https://w3c.github.io/web-nfc/#dfn-map-a-url-to-ndef
+ // NDEFRecord must have data.
+ createMessage([createUrlRecord()]),
+
+ // https://w3c.github.io/web-nfc/#dfn-map-a-url-to-ndef
+ // NDEFRecord must have data.
+ createMessage([createUrlRecord(undefined, true)]),
+
+ // NDEFRecord.data for 'url' record must be string.
+ createMessage([createUrlRecord(test_buffer_data)]),
+ createMessage([createUrlRecord(test_json_data)]),
+
+ // NDEFRecord.data for 'absolute-url' record must be string.
+ createMessage([createUrlRecord(test_buffer_data, true)]),
+ createMessage([createUrlRecord(test_json_data, true)]),
+
+ // https://w3c.github.io/web-nfc/#dfn-map-binary-data-to-ndef
+ // NDEFRecord must have data.
+ createMessage([createMimeRecord()]),
+
+ // NDEFRecord.data for 'mime' record must be BufferSource.
+ createMessage([createMimeRecord(test_text_data)]),
+ createMessage([createMimeRecord(test_number_data)]),
+ createMessage([createMimeRecord(test_json_data)]),
+
+ // NDEFRecord must have data.
+ createMessage([createUnknownRecord()]),
+
+ // NDEFRecord.data for 'unknown' record must be BufferSource.
+ createMessage([createUnknownRecord(test_text_data)]),
+ createMessage([createUnknownRecord(test_number_data)]),
+ createMessage([createUnknownRecord(test_json_data)]),
+
+ // https://w3c.github.io/web-nfc/#dfn-map-external-data-to-ndef
+ // NDEFRecord must have data.
+ createMessage([createRecord('w3.org:xyz')]),
+
+ // NDEFRecord.data for external record must be a BufferSource or NDEFMessageInit.
+ createMessage([createRecord('w3.org:xyz', test_text_data)]),
+ createMessage([createRecord('w3.org:xyz', test_number_data)]),
+ createMessage([createRecord('w3.org:xyz', test_json_data)]),
+
+ // https://w3c.github.io/web-nfc/#dfn-map-local-type-to-ndef
+ // NDEFRecord must have data.
+ createMessage([createRecord(':xyz')]),
+
+ // NDEFRecord.data for local type record must be a BufferSource or NDEFMessageInit.
+ createMessage([createRecord(':xyz', test_text_data)]),
+ createMessage([createRecord(':xyz', test_number_data)]),
+ createMessage([createRecord(':xyz', test_json_data)]),
+
+ // https://w3c.github.io/web-nfc/#dfn-map-smart-poster-to-ndef
+ // NDEFRecord must have data.
+ createMessage([createRecord('smart-poster')]),
+
+ // NDEFRecord.data for smart-poster record must be a NDEFMessageInit.
+ createMessage([createRecord('smart-poster', test_text_data)]),
+ createMessage([createRecord('smart-poster', test_number_data)]),
+ createMessage([createRecord('smart-poster', test_json_data)]),
+ createMessage([createRecord('smart-poster', test_buffer_data)]),
+
+ // https://w3c.github.io/web-nfc/#ndef-record-types
+ // The record type is neither a known type ('text', 'mime' etc.) nor a
+ // valid external/local type.
+ createMessage([createRecord('unmatched_type', test_buffer_data)])
+ ];
+
+const invalid_syntax_messages =
+ [
+ // Data for 'url' or 'absolute-url' record, must be a valid URL.
+ createMessage([createUrlRecord('Invalid URL:// Data')]),
+ createMessage([createUrlRecord('Invalid URL:// Data', true)]),
+
+ // NDEFRecord.lang length for 'text' record must be lower than 64.
+ createMessage([createTextRecord(test_text_data, undefined /* encoding */,
+ [...Array(64)].map(_ => 'a'))]),
+ ];
+
+const invalid_signals = [
+ "string",
+ 123,
+ {},
+ true,
+ Symbol(),
+ () => {},
+ self
+];
+
+nfc_test(async t => {
+ const ndef = new NDEFReader();
+ const promises = [];
+ invalid_type_messages.forEach(message => {
+ promises.push(
+ promise_rejects_js(t, TypeError, ndef.write(message)));
+ });
+ await Promise.all(promises);
+}, "Test that promise is rejected with TypeError if NDEFMessageSource is invalid.");
+
+nfc_test(async t => {
+ const ndef = new NDEFReader();
+ const promises = [];
+ invalid_syntax_messages.forEach(message => {
+ promises.push(
+ promise_rejects_dom(t, 'SyntaxError', ndef.write(message)));
+ });
+ await Promise.all(promises);
+}, "Test that promise is rejected with SyntaxError if NDEFMessageSource contains\
+ invalid records.");
+
+nfc_test(async t => {
+ await test_driver.set_permission({ name: 'nfc' }, 'denied');
+ const ndef = new NDEFReader();
+ await promise_rejects_dom(t, 'NotAllowedError', ndef.write(test_text_data));
+}, 'NDEFReader.write should fail if user permission is not granted.');
+
+// We do not provide NFC mock here to simulate that there has no available
+// implementation for NFC Mojo interface.
+nfc_test(async (t, mockNFC) => {
+ mockNFC.simulateClosedPipe();
+ const ndef = new NDEFReader();
+ await promise_rejects_dom(t, 'NotSupportedError', ndef.write(test_text_data));
+}, 'NDEFReader.write should fail if no implementation for NFC Mojo interface is available.');
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ const controller = new AbortController();
+
+ //Make sure push is pending
+ mockNFC.setPendingPushCompleted(false);
+ const p = ndef.write(test_text_data, { signal: controller.signal });
+ const rejected = promise_rejects_dom(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');
+}, "NDEFReader.write should fail if abort write request before write happends.");
+
+nfc_test(async t => {
+ const ndef = new NDEFReader();
+ const controller = new AbortController();
+ assert_false(controller.signal.aborted);
+ controller.abort();
+ assert_true(controller.signal.aborted);
+ await promise_rejects_dom(t, 'AbortError',
+ ndef.write(test_text_data, { signal: controller.signal }));
+}, "NDEFReader.write should fail if signal's aborted flag is set.");
+
+nfc_test(async t => {
+ const ndef = new NDEFReader();
+ const promises = [];
+ invalid_signals.forEach(invalid_signal => {
+ promises.push(promise_rejects_js(t, TypeError,
+ ndef.write(test_text_data, { signal: invalid_signal })));
+ });
+ await Promise.all(promises);
+}, "NDEFReader.write should fail if signal is not an AbortSignal.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef1 = new NDEFReader();
+ const ndef2 = new NDEFReader();
+ const controller = new AbortController();
+ const p1 = ndef1.write(test_text_data, { signal: controller.signal });
+
+ // Even though write request is grantable,
+ // this abort should be processed synchronously.
+ controller.abort();
+ await promise_rejects_dom(t, 'AbortError', p1);
+
+ await ndef2.write(test_text_data);
+ assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage());
+}, "Synchronously signaled abort.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ mockNFC.setHWStatus(NFCHWStatus.DISABLED);
+ await promise_rejects_dom(t, 'NotReadableError', ndef.write(test_text_data));
+}, "NDEFReader.write should fail when NFC HW is disabled.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ mockNFC.setHWStatus(NFCHWStatus.NOT_SUPPORTED);
+ await promise_rejects_dom(t, 'NotSupportedError', ndef.write(test_text_data));
+}, "NDEFReader.write should fail when NFC HW is not supported.");
+
+nfc_test(async () => {
+ await new Promise((resolve,reject) => {
+ const iframe = document.createElement('iframe');
+ iframe.srcdoc = `<script>
+ window.onmessage = async (message) => {
+ if (message.data === "Ready") {
+ try {
+ const ndef = new NDEFReader();
+ await ndef.write("Test");
+ parent.postMessage("Failure", "*");
+ } catch (error) {
+ if (error.name == "InvalidStateError") {
+ parent.postMessage("Success", "*");
+ } else {
+ 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 ndef = new NDEFReader();
+ await ndef.write(test_text_data);
+}, 'NDEFReader.write should succeed when NFC HW is enabled');
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ const message = createMessage([createTextRecord(test_text_data),
+ createMimeRecordFromJson(test_json_data),
+ createMimeRecord(test_buffer_data),
+ createUnknownRecord(test_buffer_data),
+ createUrlRecord(test_url_data),
+ createUrlRecord(test_url_data, true),
+ createRecord('w3.org:xyz', test_buffer_data)],
+ test_message_origin);
+ await ndef.write(message);
+ assertNDEFMessagesEqual(message, mockNFC.pushedMessage());
+}, "NDEFReader.write NDEFMessage containing text, mime, unknown, url, absolute-url \
+and external records with default NDEFWriteOptions.");
+
+nfc_test(async (t, mockNFC) => {
+ const messageContainText = createMessage([createTextRecord(test_text_data)]);
+
+ // Prepare a local type record that uses |messageContainText| as its payload.
+ const messageContainLocal = createMessage([createRecord(':containsTextRecord', messageContainText)]);
+
+ // Prepare an external type record that uses |messageContainLocal| as its payload.
+ const message = createMessage([createRecord('example.com:containsLocalRecord', messageContainLocal)]);
+
+ const ndef = new NDEFReader();
+ await ndef.write(message);
+ const pushed_message = mockNFC.pushedMessage();
+
+ // The mojom message received by mock nfc contains only the external type record.
+ assert_equals(pushed_message.data.length, 1);
+ assert_equals(pushed_message.data[0].recordType, 'example.com:containsLocalRecord', 'recordType');
+
+ // The external type record's payload is from the original |messageContainLocal|,
+ // containing only the local type record.
+ assert_array_equals(pushed_message.data[0].data, new Uint8Array(0),
+ 'payloadMessage is used instead');
+ assert_equals(pushed_message.data[0].payloadMessage.data.length, 1);
+ assert_equals(pushed_message.data[0].payloadMessage.data[0].recordType, ':containsTextRecord', 'recordType');
+
+ // The local type record's payload is from the original |messageContainText|,
+ // containing only the text record.
+ assert_array_equals(pushed_message.data[0].payloadMessage.data[0].data, new Uint8Array(0),
+ 'payloadMessage is used instead');
+ assertNDEFMessagesEqual(messageContainText, pushed_message.data[0].payloadMessage.data[0].payloadMessage);
+}, "NDEFReader.write NDEFMessage containing embedded records.");
+
+nfc_test(async (t, mockNFC) => {
+ // A smart-poster record contains a uri record, text record.
+ const uri_record = createUrlRecord(test_url_data);
+ const text_record = createTextRecord(test_text_data);
+ const payload_message = createMessage([uri_record, text_record]);
+ const message = createMessage([createRecord(
+ 'smart-poster', payload_message, "dummy_record_id")]);
+
+ const ndef = new NDEFReader();
+ await ndef.write(message);
+ const pushed_message = mockNFC.pushedMessage();
+
+ // The mojom message received by mock nfc contains only the smart-poster record.
+ assert_equals(pushed_message.data.length, 1);
+ assert_equals(pushed_message.data[0].recordType, 'smart-poster', 'recordType');
+ assert_equals(pushed_message.data[0].mediaType, null, 'mediaType');
+ assert_equals(pushed_message.data[0].id, 'dummy_record_id', 'id');
+
+ const embedded_records = pushed_message.data[0].payloadMessage.data;
+ assert_equals(embedded_records.length, 2);
+
+ let embedded_record_types = [];
+ for(let record of embedded_records) {
+ embedded_record_types.push(record.recordType);
+ switch(record.recordType) {
+ case 'url':
+ compareNDEFRecords(uri_record, record);
+ break;
+ case 'text':
+ compareNDEFRecords(text_record, record);
+ break;
+ default:
+ assert_unreached("Unknown recordType");
+ }
+ }
+ assert_array_equals(embedded_record_types.sort(), ['text', 'url'],
+ 'smart-poster record\'s contained record types');
+}, "NDEFReader.write NDEFMessage containing smart-poster record.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ await ndef.write(test_text_data);
+ assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage());
+}, "Test that NDEFReader.write succeeds when message is DOMString.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ await ndef.write(test_buffer_data);
+ assertNDEFMessagesEqual(test_buffer_data, mockNFC.pushedMessage());
+}, "Test that NDEFReader.write succeeds when message is ArrayBuffer.");
+
+nfc_test(async (t, mockNFC) => {
+ let buffer_view = new Uint8Array(test_buffer_data, 2, 5);
+ const ndef = new NDEFReader();
+ await ndef.write(buffer_view);
+ assertNDEFMessagesEqual(buffer_view, mockNFC.pushedMessage());
+}, "Test that NDEFReader.write succeeds when message is ArrayBufferView.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ await ndef.write(createMessage([createRecord('empty')]));
+ const receivedMessage = mockNFC.pushedMessage();
+ assert_equals(receivedMessage.data.length, 1);
+ assert_equals(receivedMessage.data[0].recordType, 'empty', 'recordType');
+}, "NDEFReader.write with 'empty' record should succeed.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ await ndef.write(test_text_data);
+ assertNDEFWriteOptionsEqual({overwrite: true}, mockNFC.writeOptions());
+}, "Check that default NDEFWriteOptions values are correctly set.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ await ndef.write(test_text_data, {overwrite: false});
+ assertNDEFWriteOptionsEqual({overwrite: false}, mockNFC.writeOptions());
+}, "Check that provided NDEFWriteOptions values are correctly converted.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef1 = new NDEFReader();
+ const ndef2 = new NDEFReader();
+
+ const p1 = ndef1.write(test_text_data, {overwrite: false});
+ const p2 = ndef2.write(test_url_data, {overwrite: true});
+
+ await new Promise((resolve, reject) => {
+ // Make first push pending
+ mockNFC.setPendingPushCompleted(false);
+ let err = "";
+ p1.then(() => {
+ reject("pending push should not be fulfilled");
+ }).catch(e => {
+ err = e.name;
+ });
+ p2.then(() => {
+ assertNDEFMessagesEqual(test_url_data, mockNFC.pushedMessage());
+ assertNDEFWriteOptionsEqual( {overwrite: true}, mockNFC.writeOptions());
+ assert_equals(err, "AbortError", "the pending push should be aborted");
+ resolve();
+ });
+ });
+}, "NDEFReader.write should replace all previously configured write operations.");
+
+nfc_test(async () => {
+ const ndef = new NDEFReader();
+
+ const controller1 = new AbortController();
+ await ndef.write(test_text_data, {signal: controller1.signal});
+
+ const controller2 = new AbortController();
+ const promise = ndef.write(test_text_data, {signal: controller2.signal});
+ controller1.abort();
+ await promise;
+}, 'NDEFReader.write signals are independent.');
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ await ndef.write({ records: [{ recordType: "mime", data: test_buffer_data }] });
+ assertNDEFMessagesEqual(test_buffer_data, mockNFC.pushedMessage());
+}, "Test that mediaType should be set to 'application/octet-stream' if \
+NDEFRecordInit.record's recordType is 'mime' and NDEFRecordInit.record's \
+mediaType is undefined.");
+
+nfc_test(async (t, mockNFC) => {
+ // Make sure the push will be pending in the mock.
+ mockNFC.setPendingPushCompleted(false);
+
+ const ndef1 = new NDEFReader();
+ const promise = ndef1.write(test_text_data);
+
+ // Just to make sure the write() request has already reached to the mock.
+ const ndef2 = new NDEFReader();
+ await ndef2.scan();
+
+ mockNFC.simulateNonNDEFTagDiscovered();
+ await promise_rejects_dom(t, 'NotSupportedError', promise);
+}, "NDEFReader.write should fail when the NFC device coming up does not expose \
+NDEF technology.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ await ndef.write(test_text_data, {overwrite: false});
+ assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage());
+}, "NDEFReader.write should succeed to write data to an unformatted NFC device \
+when the NDEFWriteOptions.overwrite is false.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ await ndef.write(test_buffer_data);
+ assertNDEFMessagesEqual(test_buffer_data, mockNFC.pushedMessage());
+ await ndef.write(test_text_data, {overwrite: true});
+ assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage());
+}, "NDEFReader.write should succeed to overwrite the existing data \
+when the NDEFWriteOptions.overwrite is true.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ const p = ndef.write(test_text_data, {overwrite: false});
+ mockNFC.setIsFormattedTag(true);
+ await promise_rejects_dom(t, 'NotAllowedError', p);
+}, "NDEFReader.write should fail when there are NDEF records on the NFC device \
+and NDEFWriteOptions.overwrite is false.");
+
+nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ mockNFC.simulateDataTransferFails();
+ await promise_rejects_dom(t, 'NetworkError', ndef.write(test_text_data));
+}, "NDEFReader.write should fail with NetworkError when NFC data transfer fails.");
+
+</script>