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>
13 const invalid_signals
= [
23 function waitSyntaxErrorPromise(t
, scan_options
) {
24 const ndef
= new NDEFReader();
25 return promise_rejects_dom(t
, 'SyntaxError', ndef
.scan(scan_options
));
29 const ndef
= new NDEFReader();
31 invalid_signals
.forEach(invalid_signal
=> {
32 promises
.push(promise_rejects_js(t
, TypeError
,
33 ndef
.scan({ signal
: invalid_signal
})));
35 await Promise
.all(promises
);
36 }, "Test that NDEFReader.scan rejects if signal is not an AbortSignal.");
39 await test_driver
.set_permission({ name
: 'nfc' }, 'denied', false);
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.");
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.");
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.");
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.");
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") {
71 const ndef = new NDEFReader();
73 parent.postMessage("Failure", "*");
75 if (error.name == "InvalidStateError") {
76 parent.postMessage("Success", "*");
78 parent.postMessage("Failure", "*");
84 iframe
.onload
= () => iframe
.contentWindow
.postMessage('Ready', '*');
85 document
.body
.appendChild(iframe
);
86 window
.onmessage
= message
=> {
87 if (message
.data
== 'Success') {
89 } else if (message
.data
== 'Failure') {
94 }, 'Test that WebNFC API is not accessible from iframe context.');
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
);
104 await ndef
.scan({signal
: controller
.signal
});
106 mockNFC
.setReadingMessage(createMessage([createTextRecord(test_text_data
)]));
108 }, "Test that nfc watch success if NFC HW is enabled.");
110 nfc_test(async (t
, mockNFC
) => {
111 const ndef
= new NDEFReader();
112 const controller
= new AbortController();
114 await
promise_rejects_dom(t
, 'AbortError', ndef
.scan({signal
: controller
.signal
}));
115 }, "Test that NDEFReader.scan rejects if NDEFScanOptions.signal is already aborted.");
117 nfc_test(async (t
, mockNFC
) => {
118 const ndef
= new NDEFReader();
119 const controller
= new AbortController();
120 const promise
= ndef
.scan({signal
: controller
.signal
});
122 await
promise_rejects_dom(t
, 'AbortError', promise
);
123 }, "Test that NDEFReader.scan rejects if NDEFScanOptions.signal aborts right after \
124 the scan invocation.");
126 nfc_test(async () => {
127 const ndef
= new NDEFReader();
129 const controller1
= new AbortController();
130 await ndef
.scan({signal
: controller1
.signal
});
134 const controller2
= new AbortController();
135 await ndef
.scan({signal
: controller2
.signal
});
136 }, "Test that NDEFReader.scan signals are independant.");
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
);
146 await ndef
.scan({signal
: controller
.signal
});
148 mockNFC
.setReadingMessage(message
);
151 ndef
.onreading
= t
.unreached_func("reading event should not be fired.");
152 mockNFC
.setReadingMessage(message
);
154 await
new Promise((resolve
, reject
) => {
155 t
.step_timeout(resolve
, 100);
157 }, "Test that NDEFReader can not get any reading events once the signal aborts.");
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
=> {
165 assert_true(event
instanceof NDEFReadingEvent
);
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',
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',
177 // The local type record contains only the text record.
178 assert_equals(event
.message
.records
[0].toRecords()[0].toRecords()[0].recordType
, 'text',
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');
184 await ndef
.scan({signal
: controller
.signal
});
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
);
194 }, "NDEFRecord.toRecords returns its embedded records correctly.");
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
=> {
202 assert_true(event
instanceof NDEFReadingEvent
);
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');
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);
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
) {
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');
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');
230 assert_unreached("Unknown recordType");
233 assert_array_equals(embedded_record_types
.sort(), ['text', 'url'],
234 'smart-poster record\'s contained record types');
236 await ndef
.scan({signal
: controller
.signal
});
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
);
246 }, "NDEFReader.scan returns smart-poster record correctly.");
248 nfc_test(async (t
, mockNFC
) => {
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
);
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
);
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.");
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);
277 await ndef
.scan({signal
: controller
.signal
});
279 mockNFC
.setReadingMessage({ records
: [] });
281 }, "Test that NDEFReader.onreading should be fired on an unformatted NFC tag \
282 with empty records array for NDEFMessage.");
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
));
301 await ndef
.scan({signal
: controller
.signal
});
303 mockNFC
.setReadingMessage(message
);
305 }, "Test that reading message with multiple records should succeed.");
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());
313 await
promise_rejects_dom(t
, 'InvalidStateError', ndef
.scan());
314 }, "Test that NDEFReader.scan rejects if there is already an ongoing scan.");
316 nfc_test(async (t
, mockNFC
) => {
317 const ndef
= new NDEFReader();
318 const controller
= new AbortController();
319 await ndef
.scan({signal
: controller
.signal
});
322 }, "Test that NDEFReader.scan can be started after the previous scan is aborted.");