summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/contacts/contacts-select.https.window.js
blob: 850217aadfa7e6cab4d5551ae2b892286080ab34 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
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');