summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/web-nfc/resources/nfc-helpers.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/web-nfc/resources/nfc-helpers.js')
-rw-r--r--testing/web-platform/tests/web-nfc/resources/nfc-helpers.js232
1 files changed, 232 insertions, 0 deletions
diff --git a/testing/web-platform/tests/web-nfc/resources/nfc-helpers.js b/testing/web-platform/tests/web-nfc/resources/nfc-helpers.js
new file mode 100644
index 0000000000..10229f0b06
--- /dev/null
+++ b/testing/web-platform/tests/web-nfc/resources/nfc-helpers.js
@@ -0,0 +1,232 @@
+'use strict';
+// These tests rely on the User Agent providing an implementation of
+// platform nfc backends.
+//
+// In Chromium-based browsers this implementation is provided by a polyfill
+// in order to reduce the amount of test-only code shipped to users. To enable
+// these tests the browser must be run with these options:
+//
+// --enable-blink-features=MojoJS,MojoJSTest
+
+async function loadChromiumResources() {
+ await loadScript('/resources/testdriver.js');
+ await loadScript('/resources/testdriver-vendor.js');
+ await import('/resources/chromium/nfc-mock.js');
+}
+
+async function initialize_nfc_tests() {
+ if (typeof WebNFCTest === 'undefined') {
+ const script = document.createElement('script');
+ script.src = '/resources/test-only-api.js';
+ script.async = false;
+ const p = new Promise((resolve, reject) => {
+ script.onload = () => { resolve(); };
+ script.onerror = e => { reject(e); };
+ })
+ document.head.appendChild(script);
+ await p;
+
+ if (isChromiumBased) {
+ await loadChromiumResources();
+ }
+ }
+ assert_implements( WebNFCTest, 'WebNFC testing interface is unavailable.');
+ let NFCTest = new WebNFCTest();
+ await NFCTest.initialize();
+ return NFCTest;
+}
+
+function nfc_test(func, name, properties) {
+ promise_test(async t => {
+ let NFCTest = await initialize_nfc_tests();
+ t.add_cleanup(async () => {
+ await NFCTest.reset();
+ });
+ await func(t, NFCTest.getMockNFC());
+ }, name, properties);
+}
+
+const test_text_data = 'Test text data.';
+const test_text_byte_array = new TextEncoder().encode(test_text_data);
+const test_number_data = 42;
+const test_json_data = {level: 1, score: 100, label: 'Game'};
+const test_url_data = 'https://w3c.github.io/web-nfc/';
+const test_message_origin = 'https://127.0.0.1:8443';
+const test_buffer_data = new ArrayBuffer(test_text_byte_array.length);
+const test_buffer_view = new Uint8Array(test_buffer_data);
+test_buffer_view.set(test_text_byte_array);
+const fake_tag_serial_number = 'c0:45:00:02';
+const test_record_id = '/test_path/test_id';
+
+const NFCHWStatus = {};
+// OS-level NFC setting is ON
+NFCHWStatus.ENABLED = 1;
+// no NFC chip
+NFCHWStatus.NOT_SUPPORTED = NFCHWStatus.ENABLED + 1;
+// OS-level NFC setting OFF
+NFCHWStatus.DISABLED = NFCHWStatus.NOT_SUPPORTED + 1;
+
+function encodeTextToArrayBuffer(string, encoding) {
+ // Only support 'utf-8', 'utf-16', 'utf-16be', and 'utf-16le'.
+ assert_true(
+ encoding === 'utf-8' || encoding === 'utf-16' ||
+ encoding === 'utf-16be' || encoding === 'utf-16le');
+
+ if (encoding === 'utf-8') {
+ return new TextEncoder().encode(string).buffer;
+ }
+
+ if (encoding === 'utf-16') {
+ let uint16array = new Uint16Array(string.length);
+ for (let i = 0; i < string.length; i++) {
+ uint16array[i] = string.codePointAt(i);
+ }
+ return uint16array.buffer;
+ }
+
+ const littleEndian = encoding === 'utf-16le';
+ const buffer = new ArrayBuffer(string.length * 2);
+ const view = new DataView(buffer);
+ for (let i = 0; i < string.length; i++) {
+ view.setUint16(i * 2, string.codePointAt(i), littleEndian);
+ }
+ return buffer;
+}
+
+function createMessage(records) {
+ if (records !== undefined) {
+ let message = {};
+ message.records = records;
+ return message;
+ }
+}
+
+function createRecord(recordType, data, id, mediaType, encoding, lang) {
+ let record = {};
+ if (recordType !== undefined)
+ record.recordType = recordType;
+ if (id !== undefined)
+ record.id = id;
+ if (mediaType !== undefined)
+ record.mediaType = mediaType;
+ if (encoding !== undefined)
+ record.encoding = encoding;
+ if (lang !== undefined)
+ record.lang = lang;
+ if (data !== undefined)
+ record.data = data;
+ return record;
+}
+
+function createTextRecord(data, encoding, lang) {
+ return createRecord('text', data, test_record_id, undefined, encoding, lang);
+}
+
+function createMimeRecordFromJson(json) {
+ return createRecord(
+ 'mime', new TextEncoder().encode(JSON.stringify(json)),
+ test_record_id, 'application/json');
+}
+
+function createMimeRecord(buffer) {
+ return createRecord(
+ 'mime', buffer, test_record_id, 'application/octet-stream');
+}
+
+function createUnknownRecord(buffer) {
+ return createRecord('unknown', buffer, test_record_id);
+}
+
+function createUrlRecord(url, isAbsUrl) {
+ if (isAbsUrl) {
+ return createRecord('absolute-url', url, test_record_id);
+ }
+ return createRecord('url', url, test_record_id);
+}
+
+// Compares NDEFMessageSource that was provided to the API
+// (e.g. NDEFReader.write), and NDEFMessage that was received by the
+// mock NFC service.
+function assertNDEFMessagesEqual(providedMessage, receivedMessage) {
+ // If simple data type is passed, e.g. String or ArrayBuffer or
+ // ArrayBufferView, convert it to NDEFMessage before comparing.
+ // https://w3c.github.io/web-nfc/#dom-ndefmessagesource
+ let provided = providedMessage;
+ if (providedMessage instanceof ArrayBuffer ||
+ ArrayBuffer.isView(providedMessage))
+ provided = createMessage([createRecord(
+ 'mime', providedMessage, undefined /* id */,
+ 'application/octet-stream')]);
+ else if (typeof providedMessage === 'string')
+ provided = createMessage([createRecord('text', providedMessage)]);
+
+ assert_equals(provided.records.length, receivedMessage.data.length,
+ 'NDEFMessages must have same number of NDEFRecords');
+
+ // Compare contents of each individual NDEFRecord
+ for (let i = 0; i < provided.records.length; ++i)
+ compareNDEFRecords(provided.records[i], receivedMessage.data[i]);
+}
+
+// Used to compare two NDEFMessage, one that is received from
+// NDEFReader.onreading() EventHandler and another that is provided to mock NFC
+// service.
+function assertWebNDEFMessagesEqual(message, expectedMessage) {
+ assert_equals(message.records.length, expectedMessage.records.length);
+
+ for(let i in message.records) {
+ let record = message.records[i];
+ let expectedRecord = expectedMessage.records[i];
+ assert_equals(record.recordType, expectedRecord.recordType);
+ assert_equals(record.mediaType, expectedRecord.mediaType);
+ assert_equals(record.id, expectedRecord.id);
+ assert_equals(record.encoding, expectedRecord.encoding);
+ assert_equals(record.lang, expectedRecord.lang);
+ // Compares record data
+ assert_array_equals(new Uint8Array(record.data),
+ new Uint8Array(expectedRecord.data));
+ }
+}
+
+function testMultiScanOptions(message, scanOptions, unmatchedScanOptions, desc) {
+ nfc_test(async (t, mockNFC) => {
+ const ndef1 = new NDEFReader();
+ const ndef2 = new NDEFReader();
+ const controller = new AbortController();
+
+ // Reading from unmatched ndef will not be triggered
+ ndef1.onreading = t.unreached_func("reading event should not be fired.");
+ unmatchedScanOptions.signal = controller.signal;
+ await ndef1.scan(unmatchedScanOptions);
+
+ const ndefWatcher = new EventWatcher(t, ndef2, ["reading", "readingerror"]);
+ const promise = ndefWatcher.wait_for("reading").then(event => {
+ controller.abort();
+ assertWebNDEFMessagesEqual(event.message, new NDEFMessage(message));
+ });
+ scanOptions.signal = controller.signal;
+ await ndef2.scan(scanOptions);
+
+ mockNFC.setReadingMessage(message);
+ await promise;
+ }, desc);
+}
+
+function testMultiMessages(message, scanOptions, unmatchedMessage, desc) {
+ nfc_test(async (t, mockNFC) => {
+ const ndef = new NDEFReader();
+ const controller = new AbortController();
+ const ndefWatcher = new EventWatcher(t, ndef, ["reading", "readingerror"]);
+ const promise = ndefWatcher.wait_for("reading").then(event => {
+ controller.abort();
+ assertWebNDEFMessagesEqual(event.message, new NDEFMessage(message));
+ });
+ scanOptions.signal = controller.signal;
+ await ndef.scan(scanOptions);
+
+ // Unmatched message will not be read
+ mockNFC.setReadingMessage(unmatchedMessage);
+ mockNFC.setReadingMessage(message);
+ await promise;
+ }, desc);
+}