From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- testing/web-platform/tests/contacts/META.yml | 1 + .../tests/contacts/contacts-select.https.window.js | 185 +++++++++++++++++++++ .../tests/contacts/resources/helpers.js | 41 +++++ .../contacts/resources/non-main-frame-select.html | 9 + 4 files changed, 236 insertions(+) create mode 100644 testing/web-platform/tests/contacts/META.yml create mode 100644 testing/web-platform/tests/contacts/contacts-select.https.window.js create mode 100644 testing/web-platform/tests/contacts/resources/helpers.js create mode 100644 testing/web-platform/tests/contacts/resources/non-main-frame-select.html (limited to 'testing/web-platform/tests/contacts') diff --git a/testing/web-platform/tests/contacts/META.yml b/testing/web-platform/tests/contacts/META.yml new file mode 100644 index 0000000000..aa55f896ee --- /dev/null +++ b/testing/web-platform/tests/contacts/META.yml @@ -0,0 +1 @@ +spec: https://wicg.github.io/contact-api/spec/ diff --git a/testing/web-platform/tests/contacts/contacts-select.https.window.js b/testing/web-platform/tests/contacts/contacts-select.https.window.js new file mode 100644 index 0000000000..850217aadf --- /dev/null +++ b/testing/web-platform/tests/contacts/contacts-select.https.window.js @@ -0,0 +1,185 @@ +// META: script=/resources/test-only-api.js +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=resources/helpers.js +'use strict'; + +// Verifies that |func|, when invoked, throws a TypeError exception. +async function expectTypeError(func) { + try { + await func(); + } catch (e) { + assert_equals(e.name, 'TypeError'); + return; + } + + assert_unreached('expected a TypeError, but none was thrown'); +} + +promise_test(async () => { + try { + await navigator.contacts.select(['name']); + assert_unreached('expected a SecurityError, but none was thrown'); + } catch (e) { + assert_equals(e.name, 'SecurityError'); + } +}, 'The Contact API requires a user gesture') + +contactsTestWithUserActivation(async (test, setSelectedContacts) => { + // At least one property must be provided. + await expectTypeError(() => navigator.contacts.select()); + await expectTypeError(() => navigator.contacts.select([])); + + // Per WebIDL parsing, no invalid values may be provided. + await expectTypeError(() => + navigator.contacts.select([''])); + await expectTypeError(() => + navigator.contacts.select(['foo'])); + await expectTypeError(() => + navigator.contacts.select(['name', 'photo'])); + +}, 'The Contact API requires valid properties to be provided'); + +contactsTestWithUserActivation(async (test, setSelectedContacts) => { + // Returns a NULL result, indicating that no results are available. + setSelectedContacts(null); + + await expectTypeError(() => navigator.contacts.select(['name'])); + +}, 'The Contact API can fail when the selector cannot be opened'); + +contactsTestWithUserActivation(async (test, setSelectedContacts) => { + setSelectedContacts([]); + + const properties = await navigator.contacts.getProperties(); + assert_true(properties.length > 0); + + // Requesting the available properties should not fail. + await navigator.contacts.select(properties); + +}, 'Supported contact properties are exposed.'); + +contactsTestWithUserActivation(async (test, setSelectedContacts) => { + const dwightAddress = { + country: 'US', + city: 'Scranton', + addressLine: ['Schrute Farms'], + }; + const michaelIcons = [new Blob('image binary data'.split(''), {type: 'image/test'})]; + + // Returns two contacts with all information available. + setSelectedContacts([ + { name: ['Dwight Schrute'], email: ['dwight@schrutefarmsbnb.com'], tel: ['000-0000'], address: [dwightAddress] }, + { name: ['Michael Scott', 'Prison Mike'], email: ['michael@dundermifflin.com'], icon: michaelIcons }, + ]); + + let results = await navigator.contacts.select(['name', 'email', 'icon', 'tel', 'address'], { multiple: true }); + assert_equals(results.length, 2); + results = results.sort((c1, c2) => JSON.stringify(c1) < JSON.stringify(c2) ? -1 : 1); + + { + const michael = results[0]; + + assert_own_property(michael, 'name'); + assert_own_property(michael, 'email'); + assert_own_property(michael, 'tel'); + assert_own_property(michael, 'address'); + assert_own_property(michael, 'icon'); + + assert_array_equals(michael.name, ['Michael Scott', 'Prison Mike']); + assert_array_equals(michael.email, ['michael@dundermifflin.com']); + assert_array_equals(michael.tel, []); + assert_array_equals(michael.address, []); + + assert_equals(michael.icon.length, michaelIcons.length); + assert_equals(michael.icon[0].type, michaelIcons[0].type); + assert_equals(michael.icon[0].size, michaelIcons[0].size); + assert_equals(await michael.icon[0].text(), await michaelIcons[0].text()); + } + + { + const dwight = results[1]; + assert_own_property(dwight, 'name'); + assert_own_property(dwight, 'email'); + assert_own_property(dwight, 'tel'); + assert_own_property(dwight, 'address'); + assert_own_property(dwight, 'icon'); + + assert_array_equals(dwight.name, ['Dwight Schrute']); + assert_array_equals(dwight.email, ['dwight@schrutefarmsbnb.com']); + assert_array_equals(dwight.tel, ['000-0000']); + assert_array_equals(dwight.icon, []); + + assert_equals(dwight.address.length, 1); + const selectedAddress = dwight.address[0]; + assert_object_equals({ + country: selectedAddress.country, + city: selectedAddress.city, + addressLine: selectedAddress.addressLine, + }, dwightAddress); + } +}, 'The Contact API correctly returns ContactInfo entries'); + +contactsTestWithUserActivation(async (test, setSelectedContacts) => { + // Returns two contacts with all information available. + setSelectedContacts([ + { name: ['Dwight Schrute'], email: ['dwight@schrutefarmsbnb.com'], tel: ['000-0000'] }, + { name: ['Michael Scott', 'Prison Mike'], email: ['michael@dundermifflin.com'] }, + ]); + + const results = await navigator.contacts.select(['name', 'email', 'tel']); + assert_equals(results.length, 1); + +}, 'Only one contact is returned if `multiple` is not set.'); + +contactsTestWithUserActivation(async (test, setSelectedContacts) => { + // Returns partial information since no e-mail addresses are requested. + setSelectedContacts([{ name: ['Creed'], email: ['creedthoughts@www.creedthoughts.gov.www'] }]); + + const results = await navigator.contacts.select(['name']); + + assert_equals(results.length, 1); + + { + const creed = results[0]; + + assert_array_equals(creed.name, ['Creed']); + assert_equals(creed.email, undefined); + assert_equals(creed.tel, undefined); + } +}, 'The Contact API does not include fields that were not requested'); + +contactsTestWithUserActivation(async (test, setSelectedContacts) => { + // Returns partial information since no e-mail addresses are requested. + setSelectedContacts([{ name: ['Kelly'] }]); + + // First request should work. + const promise1 = new Promise((resolve, reject) => { + navigator.contacts.select(['name']).then(resolve) + .catch(e => reject(e.message)); + }); + + // Second request should fail (since the first one didn't complete yet). + const promise2 = new Promise((resolve, reject) => { + navigator.contacts.select(['name']).then(contacts => reject('This was supposed to fail')) + .catch(e => resolve(e.name)); + }); + + const results = await Promise.all([promise1, promise2]); + const contacts = results[0]; + assert_equals(contacts.length, 1); + const contact = contacts[0]; + assert_equals(contact.name[0], 'Kelly'); + assert_equals(results[1], 'InvalidStateError'); + +}, 'The Contact API cannot be used again until the first operation is complete.'); + +contactsTestWithUserActivation(async (test, setSelectedContacts) => { + const iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + iframe.src = 'resources/non-main-frame-select.html'; + await new Promise(resolve => window.addEventListener('message', event => resolve(event.data))) + .then(data => assert_equals(data.errorMsg, 'InvalidStateError')) + .finally(() => iframe.remove()) + +}, 'Test contacts.select() throws an InvalidStateError in a sub-frame'); diff --git a/testing/web-platform/tests/contacts/resources/helpers.js b/testing/web-platform/tests/contacts/resources/helpers.js new file mode 100644 index 0000000000..8bac86b9b9 --- /dev/null +++ b/testing/web-platform/tests/contacts/resources/helpers.js @@ -0,0 +1,41 @@ +'use strict'; + +// These tests rely on the User Agent providing an implementation of +// platform contacts 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 import('/resources/chromium/contacts_manager_mock.js'); +} + +// User Agents must provide their own implementation of `WebContacts`, +// which must contain the following this interface: +// class WebContactsTest { +// /** @param {?Array} contacts */ +// setSelectedContacts(contacts); +// } +async function createWebContactsTest() { + if (typeof WebContactsTest === 'undefined') { + if (isChromiumBased) { + await loadChromiumResources(); + } + } + assert_implements(WebContactsTest, 'WebContactsTest is unavailable.'); + return new WebContactsTest(); +} + +// Creates a Promise test for |func| given the |description|. The |func| will +// be executed with `setSelectedContacts` which will allow tests to mock out +// the result of calling navigator.contacts.select. `setSelectedContacts` +// accepts a nullable Array of ContactInfos. +function contactsTestWithUserActivation(func, description) { + promise_test(async test => { + const webContactsTest = await createWebContactsTest(); + await window.test_driver.bless('request contacts'); + return func(test, contacts => webContactsTest.setSelectedContacts(contacts)); + }, description); +} diff --git a/testing/web-platform/tests/contacts/resources/non-main-frame-select.html b/testing/web-platform/tests/contacts/resources/non-main-frame-select.html new file mode 100644 index 0000000000..c64ecd067c --- /dev/null +++ b/testing/web-platform/tests/contacts/resources/non-main-frame-select.html @@ -0,0 +1,9 @@ + -- cgit v1.2.3