@egen-civitas/esm-platform 0.0.0-stage → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +117 -2
- package/dist/adapters/web/camera.d.ts +10 -0
- package/dist/adapters/web/camera.js +31 -0
- package/dist/adapters/web/file-registry.d.ts +7 -0
- package/dist/adapters/web/file-registry.js +26 -0
- package/dist/adapters/web/files.d.ts +7 -0
- package/dist/adapters/web/files.js +22 -0
- package/dist/adapters/web/index.d.ts +9 -0
- package/dist/adapters/web/index.js +9 -0
- package/dist/adapters/web/lifecycle.d.ts +3 -0
- package/dist/adapters/web/lifecycle.js +20 -0
- package/dist/adapters/web/open-external.d.ts +8 -0
- package/dist/adapters/web/open-external.js +32 -0
- package/dist/adapters/web/permissions.d.ts +12 -0
- package/dist/adapters/web/permissions.js +48 -0
- package/dist/adapters/web/pick-files.d.ts +17 -0
- package/dist/adapters/web/pick-files.js +49 -0
- package/dist/adapters/web/session.d.ts +12 -0
- package/dist/adapters/web/session.js +19 -0
- package/dist/adapters/web/web-adapter.test.js +1233 -0
- package/dist/bridge/client.d.ts +48 -0
- package/dist/bridge/client.js +212 -0
- package/dist/bridge/client.test.js +1264 -0
- package/dist/bridge/index.d.ts +4 -0
- package/dist/bridge/index.js +2 -0
- package/dist/bridge/protocol.d.ts +72 -0
- package/dist/bridge/protocol.js +66 -0
- package/dist/bridge/protocol.test.js +215 -0
- package/dist/capabilities.d.ts +34 -0
- package/dist/capabilities.js +48 -0
- package/dist/detect.d.ts +25 -0
- package/dist/detect.js +38 -0
- package/dist/detect.test.js +23 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.js +27 -0
- package/dist/errors.test.js +31 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +14 -0
- package/dist/native-platform.test.js +329 -0
- package/dist/native.d.ts +24 -0
- package/dist/native.js +46 -0
- package/dist/platform.d.ts +24 -0
- package/dist/platform.js +56 -0
- package/dist/platform.test.js +696 -0
- package/dist/register-capabilities.test.js +188 -0
- package/dist/registry.d.ts +52 -0
- package/dist/registry.js +101 -0
- package/dist/registry.test.js +681 -0
- package/dist/testing/index.d.ts +23 -0
- package/dist/testing/index.js +14 -0
- package/dist/testing/mock-host.d.ts +49 -0
- package/dist/testing/mock-host.js +86 -0
- package/dist/types.d.ts +108 -0
- package/dist/types.js +1 -0
- package/package.json +57 -3
|
@@ -0,0 +1,1233 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
|
+
try {
|
|
3
|
+
var info = gen[key](arg);
|
|
4
|
+
var value = info.value;
|
|
5
|
+
} catch (error) {
|
|
6
|
+
reject(error);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (info.done) {
|
|
10
|
+
resolve(value);
|
|
11
|
+
} else {
|
|
12
|
+
Promise.resolve(value).then(_next, _throw);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function _async_to_generator(fn) {
|
|
16
|
+
return function() {
|
|
17
|
+
var self = this, args = arguments;
|
|
18
|
+
return new Promise(function(resolve, reject) {
|
|
19
|
+
var gen = fn.apply(self, args);
|
|
20
|
+
function _next(value) {
|
|
21
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
22
|
+
}
|
|
23
|
+
function _throw(err) {
|
|
24
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
25
|
+
}
|
|
26
|
+
_next(undefined);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function _ts_generator(thisArg, body) {
|
|
31
|
+
var f, y, t, _ = {
|
|
32
|
+
label: 0,
|
|
33
|
+
sent: function() {
|
|
34
|
+
if (t[0] & 1) throw t[1];
|
|
35
|
+
return t[1];
|
|
36
|
+
},
|
|
37
|
+
trys: [],
|
|
38
|
+
ops: []
|
|
39
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
|
|
40
|
+
return d(g, "next", {
|
|
41
|
+
value: verb(0)
|
|
42
|
+
}), d(g, "throw", {
|
|
43
|
+
value: verb(1)
|
|
44
|
+
}), d(g, "return", {
|
|
45
|
+
value: verb(2)
|
|
46
|
+
}), typeof Symbol === "function" && d(g, Symbol.iterator, {
|
|
47
|
+
value: function() {
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
}), g;
|
|
51
|
+
function verb(n) {
|
|
52
|
+
return function(v) {
|
|
53
|
+
return step([
|
|
54
|
+
n,
|
|
55
|
+
v
|
|
56
|
+
]);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function step(op) {
|
|
60
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
61
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
62
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
63
|
+
if (y = 0, t) op = [
|
|
64
|
+
op[0] & 2,
|
|
65
|
+
t.value
|
|
66
|
+
];
|
|
67
|
+
switch(op[0]){
|
|
68
|
+
case 0:
|
|
69
|
+
case 1:
|
|
70
|
+
t = op;
|
|
71
|
+
break;
|
|
72
|
+
case 4:
|
|
73
|
+
_.label++;
|
|
74
|
+
return {
|
|
75
|
+
value: op[1],
|
|
76
|
+
done: false
|
|
77
|
+
};
|
|
78
|
+
case 5:
|
|
79
|
+
_.label++;
|
|
80
|
+
y = op[1];
|
|
81
|
+
op = [
|
|
82
|
+
0
|
|
83
|
+
];
|
|
84
|
+
continue;
|
|
85
|
+
case 7:
|
|
86
|
+
op = _.ops.pop();
|
|
87
|
+
_.trys.pop();
|
|
88
|
+
continue;
|
|
89
|
+
default:
|
|
90
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
91
|
+
_ = 0;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
95
|
+
_.label = op[1];
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
99
|
+
_.label = t[1];
|
|
100
|
+
t = op;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
if (t && _.label < t[2]) {
|
|
104
|
+
_.label = t[2];
|
|
105
|
+
_.ops.push(op);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
if (t[2]) _.ops.pop();
|
|
109
|
+
_.trys.pop();
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
op = body.call(thisArg, _);
|
|
113
|
+
} catch (e) {
|
|
114
|
+
op = [
|
|
115
|
+
6,
|
|
116
|
+
e
|
|
117
|
+
];
|
|
118
|
+
y = 0;
|
|
119
|
+
} finally{
|
|
120
|
+
f = t = 0;
|
|
121
|
+
}
|
|
122
|
+
if (op[0] & 5) throw op[1];
|
|
123
|
+
return {
|
|
124
|
+
value: op[0] ? op[1] : void 0,
|
|
125
|
+
done: true
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
130
|
+
import { getPlatform } from '../../platform';
|
|
131
|
+
import { isPlatformError } from '../../errors';
|
|
132
|
+
import { createWebCapabilities } from './index';
|
|
133
|
+
import { getWebFile, releaseWebFile } from './file-registry';
|
|
134
|
+
import { assertExternalUrl } from './open-external';
|
|
135
|
+
var w = window;
|
|
136
|
+
/** Simule le sélecteur de fichiers : à `click()`, l'input reçoit `files` (ou un événement `cancel`). */ function stubFilePicker(behaviour) {
|
|
137
|
+
var inputs = [];
|
|
138
|
+
vi.spyOn(HTMLInputElement.prototype, 'click').mockImplementation(function() {
|
|
139
|
+
var _this = this;
|
|
140
|
+
inputs.push(this);
|
|
141
|
+
// Le navigateur émet l'événement après le retour de `click()`.
|
|
142
|
+
queueMicrotask(function() {
|
|
143
|
+
var _behaviour_files;
|
|
144
|
+
if (behaviour.cancel) {
|
|
145
|
+
_this.dispatchEvent(new Event('cancel'));
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
Object.defineProperty(_this, 'files', {
|
|
149
|
+
value: (_behaviour_files = behaviour.files) !== null && _behaviour_files !== void 0 ? _behaviour_files : [],
|
|
150
|
+
configurable: true
|
|
151
|
+
});
|
|
152
|
+
_this.dispatchEvent(new Event('change'));
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
return inputs;
|
|
156
|
+
}
|
|
157
|
+
/** happy-dom fournit une API Permissions : l'absence doit être simulée explicitement. */ var removePermissionsApi = function removePermissionsApi() {
|
|
158
|
+
return Object.defineProperty(navigator, 'permissions', {
|
|
159
|
+
value: undefined,
|
|
160
|
+
configurable: true
|
|
161
|
+
});
|
|
162
|
+
};
|
|
163
|
+
var pdf = function pdf() {
|
|
164
|
+
return new File([
|
|
165
|
+
'contenu'
|
|
166
|
+
], 'bilan.pdf', {
|
|
167
|
+
type: 'application/pdf'
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
var rejection = function rejection(promise) {
|
|
171
|
+
return promise.then(function() {
|
|
172
|
+
throw new Error('devait rejeter');
|
|
173
|
+
}, function(error) {
|
|
174
|
+
return error;
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
beforeEach(function() {
|
|
178
|
+
delete w.egenTarget;
|
|
179
|
+
});
|
|
180
|
+
afterEach(function() {
|
|
181
|
+
vi.restoreAllMocks();
|
|
182
|
+
delete navigator.permissions;
|
|
183
|
+
delete w.Notification;
|
|
184
|
+
document.body.innerHTML = '';
|
|
185
|
+
});
|
|
186
|
+
describe('session (fournisseur vide : le cookie reste le mécanisme)', function() {
|
|
187
|
+
var session = getPlatform().session;
|
|
188
|
+
it('getAuthorization → null, refresh → false, clear → no-op', function() {
|
|
189
|
+
return _async_to_generator(function() {
|
|
190
|
+
return _ts_generator(this, function(_state) {
|
|
191
|
+
switch(_state.label){
|
|
192
|
+
case 0:
|
|
193
|
+
return [
|
|
194
|
+
4,
|
|
195
|
+
expect(session.getAuthorization()).resolves.toBeNull()
|
|
196
|
+
];
|
|
197
|
+
case 1:
|
|
198
|
+
_state.sent();
|
|
199
|
+
return [
|
|
200
|
+
4,
|
|
201
|
+
expect(session.refresh()).resolves.toBe(false)
|
|
202
|
+
];
|
|
203
|
+
case 2:
|
|
204
|
+
_state.sent();
|
|
205
|
+
return [
|
|
206
|
+
4,
|
|
207
|
+
expect(session.clear()).resolves.toBeUndefined()
|
|
208
|
+
];
|
|
209
|
+
case 3:
|
|
210
|
+
_state.sent();
|
|
211
|
+
return [
|
|
212
|
+
2
|
|
213
|
+
];
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
})();
|
|
217
|
+
});
|
|
218
|
+
it('setTokens → UNAVAILABLE : aucun jeton n’est stocké dans le navigateur', function() {
|
|
219
|
+
return _async_to_generator(function() {
|
|
220
|
+
var error;
|
|
221
|
+
return _ts_generator(this, function(_state) {
|
|
222
|
+
switch(_state.label){
|
|
223
|
+
case 0:
|
|
224
|
+
return [
|
|
225
|
+
4,
|
|
226
|
+
rejection(session.setTokens({
|
|
227
|
+
access: 'SECRET-ACCESS'
|
|
228
|
+
}))
|
|
229
|
+
];
|
|
230
|
+
case 1:
|
|
231
|
+
error = _state.sent();
|
|
232
|
+
expect(error).toMatchObject({
|
|
233
|
+
code: 'UNAVAILABLE',
|
|
234
|
+
capability: 'session',
|
|
235
|
+
method: 'setTokens'
|
|
236
|
+
});
|
|
237
|
+
expect(String(error.message)).not.toContain('SECRET-ACCESS');
|
|
238
|
+
expect(JSON.stringify(localStorage)).not.toContain('SECRET-ACCESS');
|
|
239
|
+
expect(JSON.stringify(sessionStorage)).not.toContain('SECRET-ACCESS');
|
|
240
|
+
return [
|
|
241
|
+
2
|
|
242
|
+
];
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
})();
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
describe('secureStorage, push, biometric : jamais simulés', function() {
|
|
249
|
+
it.each([
|
|
250
|
+
[
|
|
251
|
+
'secureStorage',
|
|
252
|
+
'get'
|
|
253
|
+
],
|
|
254
|
+
[
|
|
255
|
+
'secureStorage',
|
|
256
|
+
'set'
|
|
257
|
+
],
|
|
258
|
+
[
|
|
259
|
+
'secureStorage',
|
|
260
|
+
'remove'
|
|
261
|
+
],
|
|
262
|
+
[
|
|
263
|
+
'push',
|
|
264
|
+
'register'
|
|
265
|
+
],
|
|
266
|
+
[
|
|
267
|
+
'biometric',
|
|
268
|
+
'isAvailable'
|
|
269
|
+
],
|
|
270
|
+
[
|
|
271
|
+
'biometric',
|
|
272
|
+
'authenticate'
|
|
273
|
+
]
|
|
274
|
+
])('%s.%s → UNAVAILABLE en Web', function(capability, method) {
|
|
275
|
+
return _async_to_generator(function() {
|
|
276
|
+
var platform, target;
|
|
277
|
+
return _ts_generator(this, function(_state) {
|
|
278
|
+
switch(_state.label){
|
|
279
|
+
case 0:
|
|
280
|
+
platform = getPlatform();
|
|
281
|
+
expect(platform.has(capability)).toBe(false);
|
|
282
|
+
target = platform[capability];
|
|
283
|
+
return [
|
|
284
|
+
4,
|
|
285
|
+
expect(target[method]('k', 'v')).rejects.toMatchObject({
|
|
286
|
+
code: 'UNAVAILABLE',
|
|
287
|
+
capability: capability,
|
|
288
|
+
method: method
|
|
289
|
+
})
|
|
290
|
+
];
|
|
291
|
+
case 1:
|
|
292
|
+
_state.sent();
|
|
293
|
+
return [
|
|
294
|
+
2
|
|
295
|
+
];
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
})();
|
|
299
|
+
});
|
|
300
|
+
it('secureStorage.set n’écrit rien dans localStorage (pas de faux coffre)', function() {
|
|
301
|
+
return _async_to_generator(function() {
|
|
302
|
+
return _ts_generator(this, function(_state) {
|
|
303
|
+
switch(_state.label){
|
|
304
|
+
case 0:
|
|
305
|
+
return [
|
|
306
|
+
4,
|
|
307
|
+
getPlatform().secureStorage.set('clé', 'valeur-secrète').catch(function() {})
|
|
308
|
+
];
|
|
309
|
+
case 1:
|
|
310
|
+
_state.sent();
|
|
311
|
+
expect(localStorage.getItem('clé')).toBeNull();
|
|
312
|
+
expect(JSON.stringify(localStorage)).not.toContain('valeur-secrète');
|
|
313
|
+
return [
|
|
314
|
+
2
|
|
315
|
+
];
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
})();
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
describe('openExternal', function() {
|
|
322
|
+
it.each([
|
|
323
|
+
'https://exemple.ga/page?x=1',
|
|
324
|
+
'mailto:contact@exemple.ga',
|
|
325
|
+
'tel:+24101020304'
|
|
326
|
+
])('ouvre %s avec window.open(_blank, noopener,noreferrer)', function(url) {
|
|
327
|
+
return _async_to_generator(function() {
|
|
328
|
+
var open;
|
|
329
|
+
return _ts_generator(this, function(_state) {
|
|
330
|
+
switch(_state.label){
|
|
331
|
+
case 0:
|
|
332
|
+
open = vi.spyOn(window, 'open').mockReturnValue(null);
|
|
333
|
+
return [
|
|
334
|
+
4,
|
|
335
|
+
getPlatform().openExternal.open(url)
|
|
336
|
+
];
|
|
337
|
+
case 1:
|
|
338
|
+
_state.sent();
|
|
339
|
+
expect(open).toHaveBeenCalledTimes(1);
|
|
340
|
+
expect(open).toHaveBeenCalledWith(new URL(url).href, '_blank', 'noopener,noreferrer');
|
|
341
|
+
return [
|
|
342
|
+
2
|
|
343
|
+
];
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
})();
|
|
347
|
+
});
|
|
348
|
+
it.each([
|
|
349
|
+
'http://exemple.ga',
|
|
350
|
+
'javascript:alert(1)',
|
|
351
|
+
'data:text/html,<script>alert(1)</script>',
|
|
352
|
+
'file:///etc/passwd',
|
|
353
|
+
'ftp://exemple.ga',
|
|
354
|
+
'//exemple.ga',
|
|
355
|
+
'/chemin/relatif',
|
|
356
|
+
'pas une url',
|
|
357
|
+
''
|
|
358
|
+
])('refuse %j (INVALID_ARGS) sans rien ouvrir', function(url) {
|
|
359
|
+
return _async_to_generator(function() {
|
|
360
|
+
var open, error;
|
|
361
|
+
return _ts_generator(this, function(_state) {
|
|
362
|
+
switch(_state.label){
|
|
363
|
+
case 0:
|
|
364
|
+
open = vi.spyOn(window, 'open').mockReturnValue(null);
|
|
365
|
+
return [
|
|
366
|
+
4,
|
|
367
|
+
rejection(getPlatform().openExternal.open(url))
|
|
368
|
+
];
|
|
369
|
+
case 1:
|
|
370
|
+
error = _state.sent();
|
|
371
|
+
expect(error).toMatchObject({
|
|
372
|
+
code: 'INVALID_ARGS',
|
|
373
|
+
capability: 'openExternal',
|
|
374
|
+
method: 'open'
|
|
375
|
+
});
|
|
376
|
+
expect(open).not.toHaveBeenCalled();
|
|
377
|
+
return [
|
|
378
|
+
2
|
|
379
|
+
];
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
})();
|
|
383
|
+
});
|
|
384
|
+
it('refuse une valeur qui n’est pas une chaîne', function() {
|
|
385
|
+
return _async_to_generator(function() {
|
|
386
|
+
return _ts_generator(this, function(_state) {
|
|
387
|
+
switch(_state.label){
|
|
388
|
+
case 0:
|
|
389
|
+
return [
|
|
390
|
+
4,
|
|
391
|
+
expect(getPlatform().openExternal.open(undefined)).rejects.toMatchObject({
|
|
392
|
+
code: 'INVALID_ARGS'
|
|
393
|
+
})
|
|
394
|
+
];
|
|
395
|
+
case 1:
|
|
396
|
+
_state.sent();
|
|
397
|
+
return [
|
|
398
|
+
2
|
|
399
|
+
];
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
})();
|
|
403
|
+
});
|
|
404
|
+
it('le message d’erreur ne reprend jamais l’URL (elle peut contenir un secret)', function() {
|
|
405
|
+
try {
|
|
406
|
+
assertExternalUrl('javascript:steal("TOKEN-SECRET")');
|
|
407
|
+
} catch (error) {
|
|
408
|
+
expect(error.message).not.toContain('TOKEN-SECRET');
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
describe('lifecycle (visibilitychange)', function() {
|
|
413
|
+
var setVisibility = function setVisibility(state) {
|
|
414
|
+
Object.defineProperty(document, 'visibilityState', {
|
|
415
|
+
configurable: true,
|
|
416
|
+
get: function get() {
|
|
417
|
+
return state;
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
document.dispatchEvent(new Event('visibilitychange'));
|
|
421
|
+
};
|
|
422
|
+
afterEach(function() {
|
|
423
|
+
delete document.visibilityState;
|
|
424
|
+
});
|
|
425
|
+
it('onResume ne se déclenche que quand la page redevient visible ; onPause quand elle est masquée', function() {
|
|
426
|
+
var lifecycle = getPlatform().lifecycle;
|
|
427
|
+
var resume = vi.fn();
|
|
428
|
+
var pause = vi.fn();
|
|
429
|
+
var offResume = lifecycle.onResume(resume);
|
|
430
|
+
var offPause = lifecycle.onPause(pause);
|
|
431
|
+
setVisibility('hidden');
|
|
432
|
+
expect(pause).toHaveBeenCalledTimes(1);
|
|
433
|
+
expect(resume).not.toHaveBeenCalled();
|
|
434
|
+
setVisibility('visible');
|
|
435
|
+
expect(resume).toHaveBeenCalledTimes(1);
|
|
436
|
+
expect(pause).toHaveBeenCalledTimes(1);
|
|
437
|
+
offResume();
|
|
438
|
+
offPause();
|
|
439
|
+
});
|
|
440
|
+
it('la fonction retournée désabonne', function() {
|
|
441
|
+
var resume = vi.fn();
|
|
442
|
+
var off = getPlatform().lifecycle.onResume(resume);
|
|
443
|
+
off();
|
|
444
|
+
setVisibility('visible');
|
|
445
|
+
expect(resume).not.toHaveBeenCalled();
|
|
446
|
+
});
|
|
447
|
+
it('plusieurs abonnés sont indépendants', function() {
|
|
448
|
+
var lifecycle = getPlatform().lifecycle;
|
|
449
|
+
var a = vi.fn();
|
|
450
|
+
var b = vi.fn();
|
|
451
|
+
var offA = lifecycle.onResume(a);
|
|
452
|
+
var offB = lifecycle.onResume(b);
|
|
453
|
+
offA();
|
|
454
|
+
setVisibility('visible');
|
|
455
|
+
expect(a).not.toHaveBeenCalled();
|
|
456
|
+
expect(b).toHaveBeenCalledTimes(1);
|
|
457
|
+
offB();
|
|
458
|
+
});
|
|
459
|
+
it('un callback qui n’est pas une fonction lève INVALID_ARGS', function() {
|
|
460
|
+
expect(function() {
|
|
461
|
+
return getPlatform().lifecycle.onResume('x');
|
|
462
|
+
}).toThrowError(expect.objectContaining({
|
|
463
|
+
code: 'INVALID_ARGS',
|
|
464
|
+
method: 'onResume'
|
|
465
|
+
}));
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
describe('files', function() {
|
|
469
|
+
it('select : <input type="file"> éphémère, handles sans binaire, input retiré du document', function() {
|
|
470
|
+
return _async_to_generator(function() {
|
|
471
|
+
var inputs, handles;
|
|
472
|
+
return _ts_generator(this, function(_state) {
|
|
473
|
+
switch(_state.label){
|
|
474
|
+
case 0:
|
|
475
|
+
inputs = stubFilePicker({
|
|
476
|
+
files: [
|
|
477
|
+
pdf()
|
|
478
|
+
]
|
|
479
|
+
});
|
|
480
|
+
return [
|
|
481
|
+
4,
|
|
482
|
+
getPlatform().files.select({
|
|
483
|
+
accept: [
|
|
484
|
+
'application/pdf',
|
|
485
|
+
'.csv'
|
|
486
|
+
]
|
|
487
|
+
})
|
|
488
|
+
];
|
|
489
|
+
case 1:
|
|
490
|
+
handles = _state.sent();
|
|
491
|
+
expect(inputs).toHaveLength(1);
|
|
492
|
+
expect(inputs[0].type).toBe('file');
|
|
493
|
+
expect(inputs[0].accept).toBe('application/pdf,.csv');
|
|
494
|
+
expect(inputs[0].multiple).toBe(false);
|
|
495
|
+
expect(document.body.contains(inputs[0])).toBe(false);
|
|
496
|
+
expect(handles).toEqual([
|
|
497
|
+
{
|
|
498
|
+
id: expect.any(String),
|
|
499
|
+
name: 'bilan.pdf',
|
|
500
|
+
size: 7,
|
|
501
|
+
mime: 'application/pdf'
|
|
502
|
+
}
|
|
503
|
+
]);
|
|
504
|
+
expect(Object.keys(handles[0]).sort()).toEqual([
|
|
505
|
+
'id',
|
|
506
|
+
'mime',
|
|
507
|
+
'name',
|
|
508
|
+
'size'
|
|
509
|
+
]);
|
|
510
|
+
return [
|
|
511
|
+
2
|
|
512
|
+
];
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
})();
|
|
516
|
+
});
|
|
517
|
+
it('select multiple : un handle par fichier, identifiants distincts, fichiers retrouvables puis libérables', function() {
|
|
518
|
+
return _async_to_generator(function() {
|
|
519
|
+
var _getWebFile, inputs, handles;
|
|
520
|
+
return _ts_generator(this, function(_state) {
|
|
521
|
+
switch(_state.label){
|
|
522
|
+
case 0:
|
|
523
|
+
inputs = stubFilePicker({
|
|
524
|
+
files: [
|
|
525
|
+
pdf(),
|
|
526
|
+
new File([
|
|
527
|
+
'x'
|
|
528
|
+
], 'a.png', {
|
|
529
|
+
type: ''
|
|
530
|
+
})
|
|
531
|
+
]
|
|
532
|
+
});
|
|
533
|
+
return [
|
|
534
|
+
4,
|
|
535
|
+
getPlatform().files.select({
|
|
536
|
+
multiple: true
|
|
537
|
+
})
|
|
538
|
+
];
|
|
539
|
+
case 1:
|
|
540
|
+
handles = _state.sent();
|
|
541
|
+
expect(inputs[0].multiple).toBe(true);
|
|
542
|
+
expect(new Set(handles.map(function(h) {
|
|
543
|
+
return h.id;
|
|
544
|
+
})).size).toBe(2);
|
|
545
|
+
expect(handles[1].mime).toBe('application/octet-stream');
|
|
546
|
+
expect((_getWebFile = getWebFile(handles[0].id)) === null || _getWebFile === void 0 ? void 0 : _getWebFile.name).toBe('bilan.pdf');
|
|
547
|
+
expect(releaseWebFile(handles[0].id)).toBe(true);
|
|
548
|
+
expect(getWebFile(handles[0].id)).toBeUndefined();
|
|
549
|
+
expect(releaseWebFile(handles[0].id)).toBe(false);
|
|
550
|
+
return [
|
|
551
|
+
2
|
|
552
|
+
];
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
})();
|
|
556
|
+
});
|
|
557
|
+
it('annulation (événement cancel) → CANCELLED, input retiré', function() {
|
|
558
|
+
return _async_to_generator(function() {
|
|
559
|
+
var inputs, error;
|
|
560
|
+
return _ts_generator(this, function(_state) {
|
|
561
|
+
switch(_state.label){
|
|
562
|
+
case 0:
|
|
563
|
+
inputs = stubFilePicker({
|
|
564
|
+
cancel: true
|
|
565
|
+
});
|
|
566
|
+
return [
|
|
567
|
+
4,
|
|
568
|
+
rejection(getPlatform().files.select())
|
|
569
|
+
];
|
|
570
|
+
case 1:
|
|
571
|
+
error = _state.sent();
|
|
572
|
+
expect(error).toMatchObject({
|
|
573
|
+
code: 'CANCELLED',
|
|
574
|
+
capability: 'files',
|
|
575
|
+
method: 'select'
|
|
576
|
+
});
|
|
577
|
+
expect(document.body.contains(inputs[0])).toBe(false);
|
|
578
|
+
return [
|
|
579
|
+
2
|
|
580
|
+
];
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
})();
|
|
584
|
+
});
|
|
585
|
+
it('aucun fichier choisi → CANCELLED', function() {
|
|
586
|
+
return _async_to_generator(function() {
|
|
587
|
+
return _ts_generator(this, function(_state) {
|
|
588
|
+
switch(_state.label){
|
|
589
|
+
case 0:
|
|
590
|
+
stubFilePicker({
|
|
591
|
+
files: []
|
|
592
|
+
});
|
|
593
|
+
return [
|
|
594
|
+
4,
|
|
595
|
+
expect(getPlatform().files.select()).rejects.toMatchObject({
|
|
596
|
+
code: 'CANCELLED'
|
|
597
|
+
})
|
|
598
|
+
];
|
|
599
|
+
case 1:
|
|
600
|
+
_state.sent();
|
|
601
|
+
return [
|
|
602
|
+
2
|
|
603
|
+
];
|
|
604
|
+
}
|
|
605
|
+
});
|
|
606
|
+
})();
|
|
607
|
+
});
|
|
608
|
+
it.each([
|
|
609
|
+
[
|
|
610
|
+
'<script>'
|
|
611
|
+
],
|
|
612
|
+
[
|
|
613
|
+
'image/*;x'
|
|
614
|
+
],
|
|
615
|
+
[
|
|
616
|
+
''
|
|
617
|
+
],
|
|
618
|
+
[
|
|
619
|
+
'a b'
|
|
620
|
+
]
|
|
621
|
+
])('accept invalide %j → INVALID_ARGS, sélecteur jamais ouvert', function(entry) {
|
|
622
|
+
return _async_to_generator(function() {
|
|
623
|
+
var inputs;
|
|
624
|
+
return _ts_generator(this, function(_state) {
|
|
625
|
+
switch(_state.label){
|
|
626
|
+
case 0:
|
|
627
|
+
inputs = stubFilePicker({
|
|
628
|
+
files: [
|
|
629
|
+
pdf()
|
|
630
|
+
]
|
|
631
|
+
});
|
|
632
|
+
return [
|
|
633
|
+
4,
|
|
634
|
+
expect(getPlatform().files.select({
|
|
635
|
+
accept: [
|
|
636
|
+
entry
|
|
637
|
+
]
|
|
638
|
+
})).rejects.toMatchObject({
|
|
639
|
+
code: 'INVALID_ARGS'
|
|
640
|
+
})
|
|
641
|
+
];
|
|
642
|
+
case 1:
|
|
643
|
+
_state.sent();
|
|
644
|
+
expect(inputs).toHaveLength(0);
|
|
645
|
+
return [
|
|
646
|
+
2
|
|
647
|
+
];
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
})();
|
|
651
|
+
});
|
|
652
|
+
it('download n’est pas fourni en Web (UNAVAILABLE), select l’est', function() {
|
|
653
|
+
return _async_to_generator(function() {
|
|
654
|
+
var platform;
|
|
655
|
+
return _ts_generator(this, function(_state) {
|
|
656
|
+
switch(_state.label){
|
|
657
|
+
case 0:
|
|
658
|
+
platform = getPlatform();
|
|
659
|
+
expect(platform.has('files')).toBe(true);
|
|
660
|
+
return [
|
|
661
|
+
4,
|
|
662
|
+
expect(platform.files.download('https://exemple.ga/f.pdf', 'f.pdf')).rejects.toMatchObject({
|
|
663
|
+
code: 'UNAVAILABLE',
|
|
664
|
+
method: 'download'
|
|
665
|
+
})
|
|
666
|
+
];
|
|
667
|
+
case 1:
|
|
668
|
+
_state.sent();
|
|
669
|
+
return [
|
|
670
|
+
2
|
|
671
|
+
];
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
})();
|
|
675
|
+
});
|
|
676
|
+
});
|
|
677
|
+
describe('camera (input capture — choix documenté dans camera.ts)', function() {
|
|
678
|
+
it('capture arrière par défaut : accept image/*, attribut capture=environment', function() {
|
|
679
|
+
return _async_to_generator(function() {
|
|
680
|
+
var inputs, handle, capture;
|
|
681
|
+
return _ts_generator(this, function(_state) {
|
|
682
|
+
switch(_state.label){
|
|
683
|
+
case 0:
|
|
684
|
+
inputs = stubFilePicker({
|
|
685
|
+
files: [
|
|
686
|
+
new File([
|
|
687
|
+
'p'
|
|
688
|
+
], 'photo.jpg', {
|
|
689
|
+
type: 'image/jpeg'
|
|
690
|
+
})
|
|
691
|
+
]
|
|
692
|
+
});
|
|
693
|
+
return [
|
|
694
|
+
4,
|
|
695
|
+
getPlatform().camera.capture()
|
|
696
|
+
];
|
|
697
|
+
case 1:
|
|
698
|
+
handle = _state.sent();
|
|
699
|
+
expect(inputs[0].accept).toBe('image/*');
|
|
700
|
+
capture = inputs[0].getAttribute('capture');
|
|
701
|
+
expect(capture).toBe('environment');
|
|
702
|
+
expect(handle).toMatchObject({
|
|
703
|
+
name: 'photo.jpg',
|
|
704
|
+
mime: 'image/jpeg',
|
|
705
|
+
size: 1
|
|
706
|
+
});
|
|
707
|
+
return [
|
|
708
|
+
2
|
|
709
|
+
];
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
})();
|
|
713
|
+
});
|
|
714
|
+
it('facing "front" → capture=user ; "back" → environment', function() {
|
|
715
|
+
return _async_to_generator(function() {
|
|
716
|
+
var file, front, frontCapture, back, backCapture;
|
|
717
|
+
return _ts_generator(this, function(_state) {
|
|
718
|
+
switch(_state.label){
|
|
719
|
+
case 0:
|
|
720
|
+
file = new File([
|
|
721
|
+
'p'
|
|
722
|
+
], 'photo.jpg', {
|
|
723
|
+
type: 'image/jpeg'
|
|
724
|
+
});
|
|
725
|
+
front = stubFilePicker({
|
|
726
|
+
files: [
|
|
727
|
+
file
|
|
728
|
+
]
|
|
729
|
+
});
|
|
730
|
+
return [
|
|
731
|
+
4,
|
|
732
|
+
getPlatform().camera.capture({
|
|
733
|
+
facing: 'front'
|
|
734
|
+
})
|
|
735
|
+
];
|
|
736
|
+
case 1:
|
|
737
|
+
_state.sent();
|
|
738
|
+
frontCapture = front[0].getAttribute('capture');
|
|
739
|
+
expect(frontCapture).toBe('user');
|
|
740
|
+
vi.restoreAllMocks();
|
|
741
|
+
back = stubFilePicker({
|
|
742
|
+
files: [
|
|
743
|
+
file
|
|
744
|
+
]
|
|
745
|
+
});
|
|
746
|
+
return [
|
|
747
|
+
4,
|
|
748
|
+
getPlatform().camera.capture({
|
|
749
|
+
facing: 'back'
|
|
750
|
+
})
|
|
751
|
+
];
|
|
752
|
+
case 2:
|
|
753
|
+
_state.sent();
|
|
754
|
+
backCapture = back[0].getAttribute('capture');
|
|
755
|
+
expect(backCapture).toBe('environment');
|
|
756
|
+
return [
|
|
757
|
+
2
|
|
758
|
+
];
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
})();
|
|
762
|
+
});
|
|
763
|
+
it('facing invalide → INVALID_ARGS ; annulation → CANCELLED', function() {
|
|
764
|
+
return _async_to_generator(function() {
|
|
765
|
+
return _ts_generator(this, function(_state) {
|
|
766
|
+
switch(_state.label){
|
|
767
|
+
case 0:
|
|
768
|
+
return [
|
|
769
|
+
4,
|
|
770
|
+
expect(getPlatform().camera.capture({
|
|
771
|
+
facing: 'left'
|
|
772
|
+
})).rejects.toMatchObject({
|
|
773
|
+
code: 'INVALID_ARGS'
|
|
774
|
+
})
|
|
775
|
+
];
|
|
776
|
+
case 1:
|
|
777
|
+
_state.sent();
|
|
778
|
+
stubFilePicker({
|
|
779
|
+
cancel: true
|
|
780
|
+
});
|
|
781
|
+
return [
|
|
782
|
+
4,
|
|
783
|
+
expect(getPlatform().camera.capture()).rejects.toMatchObject({
|
|
784
|
+
code: 'CANCELLED',
|
|
785
|
+
capability: 'camera'
|
|
786
|
+
})
|
|
787
|
+
];
|
|
788
|
+
case 2:
|
|
789
|
+
_state.sent();
|
|
790
|
+
return [
|
|
791
|
+
2
|
|
792
|
+
];
|
|
793
|
+
}
|
|
794
|
+
});
|
|
795
|
+
})();
|
|
796
|
+
});
|
|
797
|
+
});
|
|
798
|
+
describe('permissions (API Permissions du navigateur)', function() {
|
|
799
|
+
var stubPermissions = function stubPermissions(query) {
|
|
800
|
+
return Object.defineProperty(navigator, 'permissions', {
|
|
801
|
+
value: {
|
|
802
|
+
query: query
|
|
803
|
+
},
|
|
804
|
+
configurable: true
|
|
805
|
+
});
|
|
806
|
+
};
|
|
807
|
+
it('sans API Permissions : capacité non fournie (has faux), méthodes UNAVAILABLE', function() {
|
|
808
|
+
return _async_to_generator(function() {
|
|
809
|
+
var platform;
|
|
810
|
+
return _ts_generator(this, function(_state) {
|
|
811
|
+
switch(_state.label){
|
|
812
|
+
case 0:
|
|
813
|
+
removePermissionsApi();
|
|
814
|
+
platform = getPlatform();
|
|
815
|
+
expect(platform.has('permissions')).toBe(false);
|
|
816
|
+
return [
|
|
817
|
+
4,
|
|
818
|
+
expect(platform.permissions.check('camera')).rejects.toMatchObject({
|
|
819
|
+
code: 'UNAVAILABLE'
|
|
820
|
+
})
|
|
821
|
+
];
|
|
822
|
+
case 1:
|
|
823
|
+
_state.sent();
|
|
824
|
+
return [
|
|
825
|
+
2
|
|
826
|
+
];
|
|
827
|
+
}
|
|
828
|
+
});
|
|
829
|
+
})();
|
|
830
|
+
});
|
|
831
|
+
it.each([
|
|
832
|
+
'granted',
|
|
833
|
+
'denied',
|
|
834
|
+
'prompt'
|
|
835
|
+
])('check retourne l’état du navigateur (%s)', function(state) {
|
|
836
|
+
return _async_to_generator(function() {
|
|
837
|
+
var query, platform;
|
|
838
|
+
return _ts_generator(this, function(_state) {
|
|
839
|
+
switch(_state.label){
|
|
840
|
+
case 0:
|
|
841
|
+
query = vi.fn(function() {
|
|
842
|
+
return _async_to_generator(function() {
|
|
843
|
+
return _ts_generator(this, function(_state) {
|
|
844
|
+
return [
|
|
845
|
+
2,
|
|
846
|
+
{
|
|
847
|
+
state: state
|
|
848
|
+
}
|
|
849
|
+
];
|
|
850
|
+
});
|
|
851
|
+
})();
|
|
852
|
+
});
|
|
853
|
+
stubPermissions(query);
|
|
854
|
+
platform = getPlatform();
|
|
855
|
+
expect(platform.has('permissions')).toBe(true);
|
|
856
|
+
return [
|
|
857
|
+
4,
|
|
858
|
+
expect(platform.permissions.check('microphone')).resolves.toBe(state)
|
|
859
|
+
];
|
|
860
|
+
case 1:
|
|
861
|
+
_state.sent();
|
|
862
|
+
expect(query).toHaveBeenCalledWith({
|
|
863
|
+
name: 'microphone'
|
|
864
|
+
});
|
|
865
|
+
return [
|
|
866
|
+
2
|
|
867
|
+
];
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
})();
|
|
871
|
+
});
|
|
872
|
+
it('un nom que le navigateur ne connaît pas → UNAVAILABLE (jamais une valeur inventée)', function() {
|
|
873
|
+
return _async_to_generator(function() {
|
|
874
|
+
return _ts_generator(this, function(_state) {
|
|
875
|
+
switch(_state.label){
|
|
876
|
+
case 0:
|
|
877
|
+
stubPermissions(function() {
|
|
878
|
+
return _async_to_generator(function() {
|
|
879
|
+
return _ts_generator(this, function(_state) {
|
|
880
|
+
throw new TypeError('inconnu');
|
|
881
|
+
});
|
|
882
|
+
})();
|
|
883
|
+
});
|
|
884
|
+
return [
|
|
885
|
+
4,
|
|
886
|
+
expect(getPlatform().permissions.check('camera')).rejects.toMatchObject({
|
|
887
|
+
code: 'UNAVAILABLE',
|
|
888
|
+
method: 'check'
|
|
889
|
+
})
|
|
890
|
+
];
|
|
891
|
+
case 1:
|
|
892
|
+
_state.sent();
|
|
893
|
+
return [
|
|
894
|
+
2
|
|
895
|
+
];
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
})();
|
|
899
|
+
});
|
|
900
|
+
it('files n’a pas d’équivalent Web → UNAVAILABLE, sans interroger le navigateur', function() {
|
|
901
|
+
return _async_to_generator(function() {
|
|
902
|
+
var query;
|
|
903
|
+
return _ts_generator(this, function(_state) {
|
|
904
|
+
switch(_state.label){
|
|
905
|
+
case 0:
|
|
906
|
+
query = vi.fn(function() {
|
|
907
|
+
return _async_to_generator(function() {
|
|
908
|
+
return _ts_generator(this, function(_state) {
|
|
909
|
+
return [
|
|
910
|
+
2,
|
|
911
|
+
{
|
|
912
|
+
state: 'granted'
|
|
913
|
+
}
|
|
914
|
+
];
|
|
915
|
+
});
|
|
916
|
+
})();
|
|
917
|
+
});
|
|
918
|
+
stubPermissions(query);
|
|
919
|
+
return [
|
|
920
|
+
4,
|
|
921
|
+
expect(getPlatform().permissions.check('files')).rejects.toMatchObject({
|
|
922
|
+
code: 'UNAVAILABLE'
|
|
923
|
+
})
|
|
924
|
+
];
|
|
925
|
+
case 1:
|
|
926
|
+
_state.sent();
|
|
927
|
+
expect(query).not.toHaveBeenCalled();
|
|
928
|
+
return [
|
|
929
|
+
2
|
|
930
|
+
];
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
})();
|
|
934
|
+
});
|
|
935
|
+
it('nom inconnu → INVALID_ARGS', function() {
|
|
936
|
+
return _async_to_generator(function() {
|
|
937
|
+
return _ts_generator(this, function(_state) {
|
|
938
|
+
switch(_state.label){
|
|
939
|
+
case 0:
|
|
940
|
+
stubPermissions(function() {
|
|
941
|
+
return _async_to_generator(function() {
|
|
942
|
+
return _ts_generator(this, function(_state) {
|
|
943
|
+
return [
|
|
944
|
+
2,
|
|
945
|
+
{
|
|
946
|
+
state: 'granted'
|
|
947
|
+
}
|
|
948
|
+
];
|
|
949
|
+
});
|
|
950
|
+
})();
|
|
951
|
+
});
|
|
952
|
+
return [
|
|
953
|
+
4,
|
|
954
|
+
expect(getPlatform().permissions.check('gps')).rejects.toMatchObject({
|
|
955
|
+
code: 'INVALID_ARGS'
|
|
956
|
+
})
|
|
957
|
+
];
|
|
958
|
+
case 1:
|
|
959
|
+
_state.sent();
|
|
960
|
+
return [
|
|
961
|
+
4,
|
|
962
|
+
expect(getPlatform().permissions.request('gps')).rejects.toMatchObject({
|
|
963
|
+
code: 'INVALID_ARGS'
|
|
964
|
+
})
|
|
965
|
+
];
|
|
966
|
+
case 2:
|
|
967
|
+
_state.sent();
|
|
968
|
+
return [
|
|
969
|
+
2
|
|
970
|
+
];
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
})();
|
|
974
|
+
});
|
|
975
|
+
it.each([
|
|
976
|
+
[
|
|
977
|
+
'granted',
|
|
978
|
+
'granted'
|
|
979
|
+
],
|
|
980
|
+
[
|
|
981
|
+
'denied',
|
|
982
|
+
'denied'
|
|
983
|
+
],
|
|
984
|
+
[
|
|
985
|
+
'default',
|
|
986
|
+
'denied'
|
|
987
|
+
]
|
|
988
|
+
])('request(notifications) : Notification.requestPermission = %s → %s', function(browser, expected) {
|
|
989
|
+
return _async_to_generator(function() {
|
|
990
|
+
return _ts_generator(this, function(_state) {
|
|
991
|
+
switch(_state.label){
|
|
992
|
+
case 0:
|
|
993
|
+
stubPermissions(function() {
|
|
994
|
+
return _async_to_generator(function() {
|
|
995
|
+
return _ts_generator(this, function(_state) {
|
|
996
|
+
return [
|
|
997
|
+
2,
|
|
998
|
+
{
|
|
999
|
+
state: 'prompt'
|
|
1000
|
+
}
|
|
1001
|
+
];
|
|
1002
|
+
});
|
|
1003
|
+
})();
|
|
1004
|
+
});
|
|
1005
|
+
w.Notification = {
|
|
1006
|
+
requestPermission: vi.fn(function() {
|
|
1007
|
+
return _async_to_generator(function() {
|
|
1008
|
+
return _ts_generator(this, function(_state) {
|
|
1009
|
+
return [
|
|
1010
|
+
2,
|
|
1011
|
+
browser
|
|
1012
|
+
];
|
|
1013
|
+
});
|
|
1014
|
+
})();
|
|
1015
|
+
})
|
|
1016
|
+
};
|
|
1017
|
+
return [
|
|
1018
|
+
4,
|
|
1019
|
+
expect(getPlatform().permissions.request('notifications')).resolves.toBe(expected)
|
|
1020
|
+
];
|
|
1021
|
+
case 1:
|
|
1022
|
+
_state.sent();
|
|
1023
|
+
return [
|
|
1024
|
+
2
|
|
1025
|
+
];
|
|
1026
|
+
}
|
|
1027
|
+
});
|
|
1028
|
+
})();
|
|
1029
|
+
});
|
|
1030
|
+
it.each([
|
|
1031
|
+
'camera',
|
|
1032
|
+
'microphone',
|
|
1033
|
+
'files'
|
|
1034
|
+
])('request(%s) → UNAVAILABLE (le navigateur demande à l’usage)', function(name) {
|
|
1035
|
+
return _async_to_generator(function() {
|
|
1036
|
+
return _ts_generator(this, function(_state) {
|
|
1037
|
+
switch(_state.label){
|
|
1038
|
+
case 0:
|
|
1039
|
+
stubPermissions(function() {
|
|
1040
|
+
return _async_to_generator(function() {
|
|
1041
|
+
return _ts_generator(this, function(_state) {
|
|
1042
|
+
return [
|
|
1043
|
+
2,
|
|
1044
|
+
{
|
|
1045
|
+
state: 'prompt'
|
|
1046
|
+
}
|
|
1047
|
+
];
|
|
1048
|
+
});
|
|
1049
|
+
})();
|
|
1050
|
+
});
|
|
1051
|
+
return [
|
|
1052
|
+
4,
|
|
1053
|
+
expect(getPlatform().permissions.request(name)).rejects.toMatchObject({
|
|
1054
|
+
code: 'UNAVAILABLE',
|
|
1055
|
+
method: 'request'
|
|
1056
|
+
})
|
|
1057
|
+
];
|
|
1058
|
+
case 1:
|
|
1059
|
+
_state.sent();
|
|
1060
|
+
return [
|
|
1061
|
+
2
|
|
1062
|
+
];
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
})();
|
|
1066
|
+
});
|
|
1067
|
+
});
|
|
1068
|
+
describe('assemblage Web', function() {
|
|
1069
|
+
it('createWebCapabilities : exactement les capacités fournies par un navigateur sans API Permissions', function() {
|
|
1070
|
+
removePermissionsApi();
|
|
1071
|
+
expect(Object.keys(createWebCapabilities()).sort()).toEqual([
|
|
1072
|
+
'camera',
|
|
1073
|
+
'files',
|
|
1074
|
+
'lifecycle',
|
|
1075
|
+
'openExternal',
|
|
1076
|
+
'session'
|
|
1077
|
+
]);
|
|
1078
|
+
});
|
|
1079
|
+
it('getPlatform() en Web : has() reflète les capacités réellement fournies', function() {
|
|
1080
|
+
return _async_to_generator(function() {
|
|
1081
|
+
var platform, provided, absent, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, name, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, name1;
|
|
1082
|
+
return _ts_generator(this, function(_state) {
|
|
1083
|
+
switch(_state.label){
|
|
1084
|
+
case 0:
|
|
1085
|
+
Object.defineProperty(navigator, 'permissions', {
|
|
1086
|
+
value: {
|
|
1087
|
+
query: function query() {
|
|
1088
|
+
return _async_to_generator(function() {
|
|
1089
|
+
return _ts_generator(this, function(_state) {
|
|
1090
|
+
return [
|
|
1091
|
+
2,
|
|
1092
|
+
{
|
|
1093
|
+
state: 'prompt'
|
|
1094
|
+
}
|
|
1095
|
+
];
|
|
1096
|
+
});
|
|
1097
|
+
})();
|
|
1098
|
+
}
|
|
1099
|
+
},
|
|
1100
|
+
configurable: true
|
|
1101
|
+
});
|
|
1102
|
+
platform = getPlatform();
|
|
1103
|
+
expect(platform.environment).toBe('web');
|
|
1104
|
+
return [
|
|
1105
|
+
4,
|
|
1106
|
+
expect(platform.ready).resolves.toBeUndefined()
|
|
1107
|
+
];
|
|
1108
|
+
case 1:
|
|
1109
|
+
_state.sent();
|
|
1110
|
+
provided = [
|
|
1111
|
+
'session',
|
|
1112
|
+
'openExternal',
|
|
1113
|
+
'lifecycle',
|
|
1114
|
+
'files',
|
|
1115
|
+
'camera',
|
|
1116
|
+
'permissions'
|
|
1117
|
+
];
|
|
1118
|
+
absent = [
|
|
1119
|
+
'secureStorage',
|
|
1120
|
+
'push',
|
|
1121
|
+
'biometric'
|
|
1122
|
+
];
|
|
1123
|
+
_iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
1124
|
+
try {
|
|
1125
|
+
for(_iterator = provided[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
1126
|
+
name = _step.value;
|
|
1127
|
+
expect(platform.has(name)).toBe(true);
|
|
1128
|
+
}
|
|
1129
|
+
} catch (err) {
|
|
1130
|
+
_didIteratorError = true;
|
|
1131
|
+
_iteratorError = err;
|
|
1132
|
+
} finally{
|
|
1133
|
+
try {
|
|
1134
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
1135
|
+
_iterator.return();
|
|
1136
|
+
}
|
|
1137
|
+
} finally{
|
|
1138
|
+
if (_didIteratorError) {
|
|
1139
|
+
throw _iteratorError;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
_iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
1144
|
+
try {
|
|
1145
|
+
for(_iterator1 = absent[Symbol.iterator](); !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
1146
|
+
name1 = _step1.value;
|
|
1147
|
+
expect(platform.has(name1)).toBe(false);
|
|
1148
|
+
}
|
|
1149
|
+
} catch (err) {
|
|
1150
|
+
_didIteratorError1 = true;
|
|
1151
|
+
_iteratorError1 = err;
|
|
1152
|
+
} finally{
|
|
1153
|
+
try {
|
|
1154
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
1155
|
+
_iterator1.return();
|
|
1156
|
+
}
|
|
1157
|
+
} finally{
|
|
1158
|
+
if (_didIteratorError1) {
|
|
1159
|
+
throw _iteratorError1;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
return [
|
|
1164
|
+
2
|
|
1165
|
+
];
|
|
1166
|
+
}
|
|
1167
|
+
});
|
|
1168
|
+
})();
|
|
1169
|
+
});
|
|
1170
|
+
it('en natif, l’adaptateur Web n’est JAMAIS utilisé (aucune capacité du navigateur ne fuit vers un Host absent)', function() {
|
|
1171
|
+
w.egenTarget = 'android';
|
|
1172
|
+
var platform = getPlatform();
|
|
1173
|
+
for(var _i = 0, _iter = [
|
|
1174
|
+
'session',
|
|
1175
|
+
'openExternal',
|
|
1176
|
+
'lifecycle',
|
|
1177
|
+
'files',
|
|
1178
|
+
'camera',
|
|
1179
|
+
'permissions',
|
|
1180
|
+
'secureStorage',
|
|
1181
|
+
'push',
|
|
1182
|
+
'biometric'
|
|
1183
|
+
]; _i < _iter.length; _i++){
|
|
1184
|
+
var name = _iter[_i];
|
|
1185
|
+
expect(platform.has(name)).toBe(false);
|
|
1186
|
+
}
|
|
1187
|
+
});
|
|
1188
|
+
it('toute erreur d’une capacité Web est une PlatformError (jamais une Error générique)', function() {
|
|
1189
|
+
return _async_to_generator(function() {
|
|
1190
|
+
var errors, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, error;
|
|
1191
|
+
return _ts_generator(this, function(_state) {
|
|
1192
|
+
switch(_state.label){
|
|
1193
|
+
case 0:
|
|
1194
|
+
return [
|
|
1195
|
+
4,
|
|
1196
|
+
Promise.all([
|
|
1197
|
+
rejection(getPlatform().openExternal.open('http://x')),
|
|
1198
|
+
rejection(getPlatform().files.download('https://x', 'f')),
|
|
1199
|
+
rejection(getPlatform().session.setTokens({
|
|
1200
|
+
access: 'a'
|
|
1201
|
+
}))
|
|
1202
|
+
])
|
|
1203
|
+
];
|
|
1204
|
+
case 1:
|
|
1205
|
+
errors = _state.sent();
|
|
1206
|
+
_iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
1207
|
+
try {
|
|
1208
|
+
for(_iterator = errors[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
1209
|
+
error = _step.value;
|
|
1210
|
+
expect(isPlatformError(error)).toBe(true);
|
|
1211
|
+
}
|
|
1212
|
+
} catch (err) {
|
|
1213
|
+
_didIteratorError = true;
|
|
1214
|
+
_iteratorError = err;
|
|
1215
|
+
} finally{
|
|
1216
|
+
try {
|
|
1217
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
1218
|
+
_iterator.return();
|
|
1219
|
+
}
|
|
1220
|
+
} finally{
|
|
1221
|
+
if (_didIteratorError) {
|
|
1222
|
+
throw _iteratorError;
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
return [
|
|
1227
|
+
2
|
|
1228
|
+
];
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
1231
|
+
})();
|
|
1232
|
+
});
|
|
1233
|
+
});
|