testaro 42.0.1 → 43.0.2
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/README.md +19 -5
- package/actSpecs.js +2 -4
- package/package.json +1 -1
- package/procs/job.js +8 -13
- package/run.js +95 -116
- package/testaro/focAll.js +1 -1
- package/procs/device.js +0 -59
package/README.md
CHANGED
|
@@ -132,11 +132,26 @@ Here is an example of a job:
|
|
|
132
132
|
```javaScript
|
|
133
133
|
{
|
|
134
134
|
id: '250110T1200-7f-4',
|
|
135
|
+
what: 'monthly health check',
|
|
135
136
|
strict: true,
|
|
136
137
|
isolate: true,
|
|
137
138
|
standard: 'also',
|
|
138
139
|
observe: false,
|
|
139
|
-
|
|
140
|
+
device: {
|
|
141
|
+
id: 'iPhone 8',
|
|
142
|
+
windowOptions: {
|
|
143
|
+
reducedMotion: 'no-preference',
|
|
144
|
+
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1',
|
|
145
|
+
viewport: {
|
|
146
|
+
width: 375,
|
|
147
|
+
height: 667
|
|
148
|
+
},
|
|
149
|
+
deviceScaleFactor: 2,
|
|
150
|
+
isMobile: true,
|
|
151
|
+
hasTouch: true,
|
|
152
|
+
defaultBrowserType: 'webkit'
|
|
153
|
+
}
|
|
154
|
+
},
|
|
140
155
|
browserID: 'webkit',
|
|
141
156
|
lowMotion: false,
|
|
142
157
|
timeLimit: 80,
|
|
@@ -176,7 +191,7 @@ Here is an example of a job:
|
|
|
176
191
|
```
|
|
177
192
|
|
|
178
193
|
This job contains three _acts_, telling Testaro to:
|
|
179
|
-
1. Launch a Webkit browser without a reduced-motion setting, open a
|
|
194
|
+
1. Launch a Webkit browser without a reduced-motion setting, open a window with the properties of an iPhone 8 device, create a page (tab), and navigate to `https://abccorp.com/mgmt/realproperty.html`.
|
|
180
195
|
1. Perform the test for the `landmark-complementary-is-top-level` rule of the `axe` tool and report the test result with Axe detail level 2.
|
|
181
196
|
1. Perform the tests for rules `QW-BP25` and `QW-BP26` of the `qualWeb` tool on the existing page.
|
|
182
197
|
|
|
@@ -186,9 +201,8 @@ Job properties:
|
|
|
186
201
|
- `strict`: `true` or `false`, indicating whether _substantive redirections_ should be treated as failures. These are redirections that do more than add or subtract a final slash.
|
|
187
202
|
- `standard`: `'also'`, `'only'`, or `'no'`, indicating whether rule-violation instances are to be reported in tool-native formats and also in the Testaro standard format, only in the standard format, or only in the tool-native formats.
|
|
188
203
|
- `observe`: `true` or `false`, indicating whether tool and Testaro-rule invocations are to be reported to the server as they occur, so that the server can update a waiting client.
|
|
189
|
-
- `
|
|
204
|
+
- `device`: the ID of a device and the properties of each new browser context (window) that will be set for conformity to that device, unless overridden by a `launch` act. It must be `'default'` or the ID of one of [about 125 devices recognized by Playwright](https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/server/deviceDescriptorsSource.json).
|
|
190
205
|
- `browserID`: the ID of the browser to be used, unless overridden by a `launch` act. It must be `'chromium'`, `'firefox'`, or `'webkit`'.
|
|
191
|
-
- `lowMotion`: whether the browser is to create tabs with the `reduce-motion` option set to `reduce` instead of `no-preference`.
|
|
192
206
|
- `timeLimit`: the number of seconds allowed for the execution of the job.
|
|
193
207
|
- `creationTimeStamp`: a string in `yymmddThhMM` format, describing when the job was created.
|
|
194
208
|
- `executionTimeStamp`: a string in `yymmddThhMM` format, specifying a date and time before which the job is not to be performed.
|
|
@@ -237,7 +251,7 @@ When the texts of multiple elements of the same type will contain the same `whic
|
|
|
237
251
|
|
|
238
252
|
#### Navigations
|
|
239
253
|
|
|
240
|
-
An example of a **navigation** is the act of type `launch` above.
|
|
254
|
+
An example of a **navigation** is the act of type `launch` in the job example above. That `launch` act has only a `type` property. If you want a particular `launch` act to use a different browser type or to navigate to a different target from the job defaults, the `launch` act can have a `browserID` and/or a `target` property.
|
|
241
255
|
|
|
242
256
|
If any act alters the page, you can restore the page to its original state for the next act by inserting a new `launch` act (and, if necessary, additional page-specific acts) between them.
|
|
243
257
|
|
package/actSpecs.js
CHANGED
|
@@ -54,10 +54,8 @@ exports.actSpecs = {
|
|
|
54
54
|
launch: [
|
|
55
55
|
'Launch a Playwright browser',
|
|
56
56
|
{
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
browserID: [false, 'string', 'isBrowserID', 'chromium, firefox, or webkit if not job default'],
|
|
60
|
-
lowMotion: [false, 'boolean', '', 'set reduced-motion option if true'],
|
|
57
|
+
target: [false, 'object', '', 'target different from sources.target of the job'],
|
|
58
|
+
browserID: [false, 'string', 'isBrowserID', 'browser type different from browserID of the job'],
|
|
61
59
|
what: [false, 'string', 'hasLength', 'comment']
|
|
62
60
|
}
|
|
63
61
|
],
|
package/package.json
CHANGED
package/procs/job.js
CHANGED
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
|
|
30
30
|
// Requirements for acts.
|
|
31
31
|
const {actSpecs} = require('../actSpecs');
|
|
32
|
-
//
|
|
33
|
-
const {
|
|
32
|
+
// Data on devices.
|
|
33
|
+
const {devices} = require('playwright');
|
|
34
34
|
// Module to get dates from time stamps.
|
|
35
35
|
const {dateOf} = require('./dateOf');
|
|
36
36
|
|
|
@@ -82,9 +82,6 @@ const hasSubtype = (variable, subtype) => {
|
|
|
82
82
|
else if (subtype === 'isURL') {
|
|
83
83
|
return isURL(variable);
|
|
84
84
|
}
|
|
85
|
-
else if (subtype === 'isDeviceID') {
|
|
86
|
-
return isDeviceID(variable);
|
|
87
|
-
}
|
|
88
85
|
else if (subtype === 'isBrowserID') {
|
|
89
86
|
return isBrowserID(variable);
|
|
90
87
|
}
|
|
@@ -119,7 +116,7 @@ const hasSubtype = (variable, subtype) => {
|
|
|
119
116
|
}
|
|
120
117
|
};
|
|
121
118
|
// Validates a browser type.
|
|
122
|
-
const isBrowserID = type => ['chromium', 'firefox', 'webkit'].includes(type);
|
|
119
|
+
const isBrowserID = exports.isBrowserID = type => ['chromium', 'firefox', 'webkit'].includes(type);
|
|
123
120
|
// Validates a load state.
|
|
124
121
|
const isState = string => ['loaded', 'idle'].includes(string);
|
|
125
122
|
// Validates a URL.
|
|
@@ -179,6 +176,8 @@ const isValidAct = exports.isValidAct = act => {
|
|
|
179
176
|
return false;
|
|
180
177
|
}
|
|
181
178
|
};
|
|
179
|
+
// Returns whether a device ID is valid.
|
|
180
|
+
const isDeviceID = deviceID => deviceID === 'default' || !! devices[deviceID];
|
|
182
181
|
// Returns blank if a job is valid, or an error message.
|
|
183
182
|
exports.isValidJob = job => {
|
|
184
183
|
// If any job was provided:
|
|
@@ -190,9 +189,8 @@ exports.isValidJob = job => {
|
|
|
190
189
|
isolate,
|
|
191
190
|
standard,
|
|
192
191
|
observe,
|
|
193
|
-
|
|
192
|
+
device,
|
|
194
193
|
browserID,
|
|
195
|
-
lowMotion,
|
|
196
194
|
timeLimit,
|
|
197
195
|
creationTimeStamp,
|
|
198
196
|
executionTimeStamp,
|
|
@@ -217,15 +215,12 @@ exports.isValidJob = job => {
|
|
|
217
215
|
if (typeof observe !== 'boolean') {
|
|
218
216
|
return 'Bad job observe';
|
|
219
217
|
}
|
|
220
|
-
if (!
|
|
218
|
+
if (device.id !== 'default' && ! devices[device.id]) {
|
|
221
219
|
return 'Bad job deviceID';
|
|
222
220
|
}
|
|
223
|
-
if (!
|
|
221
|
+
if (! isBrowserID(browserID)) {
|
|
224
222
|
return 'Bad job browserID';
|
|
225
223
|
}
|
|
226
|
-
if (typeof lowMotion !== 'boolean') {
|
|
227
|
-
return 'Bad job lowMotion';
|
|
228
|
-
}
|
|
229
224
|
if (typeof timeLimit !== 'number' || timeLimit < 1) {
|
|
230
225
|
return 'Bad job timeLimit';
|
|
231
226
|
}
|
package/run.js
CHANGED
|
@@ -30,15 +30,13 @@
|
|
|
30
30
|
// Module to keep secrets.
|
|
31
31
|
require('dotenv').config();
|
|
32
32
|
// Module to validate jobs.
|
|
33
|
-
const {isValidJob, tools} = require('./procs/job');
|
|
33
|
+
const {isBrowserID, isValidJob, tools} = require('./procs/job');
|
|
34
34
|
// Module to standardize report formats.
|
|
35
35
|
const {standardize} = require('./procs/standardize');
|
|
36
36
|
// Module to identify element bounding boxes.
|
|
37
37
|
const {identify} = require('./procs/identify');
|
|
38
38
|
// Module to send a notice to an observer.
|
|
39
39
|
const {tellServer} = require('./procs/tellServer');
|
|
40
|
-
// Module to get device options.
|
|
41
|
-
const {getDeviceOptions, isDeviceID} = require('./procs/device');
|
|
42
40
|
|
|
43
41
|
// CONSTANTS
|
|
44
42
|
|
|
@@ -186,16 +184,15 @@ const browserClose = async () => {
|
|
|
186
184
|
}
|
|
187
185
|
};
|
|
188
186
|
// Launches a browser, navigates to a URL, and returns browser data.
|
|
189
|
-
const launch = async (report,
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
lowMotion ??= report.lowMotion;
|
|
187
|
+
const launch = async (report, debug, waits, tempBrowserID, tempTarget) => {
|
|
188
|
+
const {browserID, device, target} = report;
|
|
189
|
+
// Get the default arguments if not overridden.
|
|
190
|
+
browserID ??= browserID;
|
|
191
|
+
const {url} = (tempTarget || target);
|
|
195
192
|
// If the specified browser type exists:
|
|
196
|
-
if (
|
|
193
|
+
if (isBrowserID(browserID)) {
|
|
197
194
|
// Create a browser of the specified or default type.
|
|
198
|
-
const browserType = require('playwright')[
|
|
195
|
+
const browserType = require('playwright')[tempBrowserID || browserID];
|
|
199
196
|
// Close the current browser, if any.
|
|
200
197
|
await browserClose();
|
|
201
198
|
// Define browser options.
|
|
@@ -218,122 +215,106 @@ const launch = async (report, url, debug, waits, deviceID, browserID, lowMotion)
|
|
|
218
215
|
error: 'Browser launch failed'
|
|
219
216
|
};
|
|
220
217
|
});
|
|
221
|
-
//
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
);
|
|
225
|
-
//
|
|
226
|
-
|
|
227
|
-
//
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
parts.push(
|
|
260
|
-
if (
|
|
261
|
-
|
|
262
|
-
if (msgText.length > 300) {
|
|
263
|
-
parts.push('...');
|
|
264
|
-
}
|
|
265
|
-
parts.push(tail.slice(0, 75));
|
|
266
|
-
if (tail.length > 75) {
|
|
267
|
-
parts.push(tail.slice(75));
|
|
268
|
-
}
|
|
218
|
+
// Open a context (i.e. browser tab).
|
|
219
|
+
const browserContext = await browser.newContext(device.windowOptions);
|
|
220
|
+
// Prevent default timeouts.
|
|
221
|
+
browserContext.setDefaultTimeout(0);
|
|
222
|
+
// When a page (i.e. browser tab) is added to the browser context (i.e. browser window):
|
|
223
|
+
browserContext.on('page', async page => {
|
|
224
|
+
// Ensure the report has a jobData property.
|
|
225
|
+
report.jobData ??= {};
|
|
226
|
+
const {jobData} = report;
|
|
227
|
+
jobData.logCount ??= 0;
|
|
228
|
+
jobData.logSize ??= 0;
|
|
229
|
+
jobData.errorLogCount ??= 0;
|
|
230
|
+
// Add any error events to the count of logging errors.
|
|
231
|
+
page.on('crash', () => {
|
|
232
|
+
jobData.errorLogCount++;
|
|
233
|
+
console.log('Page crashed');
|
|
234
|
+
});
|
|
235
|
+
page.on('pageerror', () => {
|
|
236
|
+
jobData.errorLogCount++;
|
|
237
|
+
});
|
|
238
|
+
page.on('requestfailed', () => {
|
|
239
|
+
jobData.errorLogCount++;
|
|
240
|
+
});
|
|
241
|
+
// If the page emits a message:
|
|
242
|
+
page.on('console', msg => {
|
|
243
|
+
const msgText = msg.text();
|
|
244
|
+
let indentedMsg = '';
|
|
245
|
+
// If debugging is on:
|
|
246
|
+
if (debug) {
|
|
247
|
+
// Log a summary of the message on the console.
|
|
248
|
+
const parts = [msgText.slice(0, 75)];
|
|
249
|
+
if (msgText.length > 75) {
|
|
250
|
+
parts.push(msgText.slice(75, 150));
|
|
251
|
+
if (msgText.length > 150) {
|
|
252
|
+
const tail = msgText.slice(150).slice(-150);
|
|
253
|
+
if (msgText.length > 300) {
|
|
254
|
+
parts.push('...');
|
|
255
|
+
}
|
|
256
|
+
parts.push(tail.slice(0, 75));
|
|
257
|
+
if (tail.length > 75) {
|
|
258
|
+
parts.push(tail.slice(75));
|
|
269
259
|
}
|
|
270
260
|
}
|
|
271
|
-
indentedMsg = parts.map(part => ` | ${part}`).join('\n');
|
|
272
|
-
console.log(`\n${indentedMsg}`);
|
|
273
|
-
}
|
|
274
|
-
// Add statistics on the message to the report.
|
|
275
|
-
const msgTextLC = msgText.toLowerCase();
|
|
276
|
-
const msgLength = msgText.length;
|
|
277
|
-
report.jobData.logCount++;
|
|
278
|
-
report.jobData.logSize += msgLength;
|
|
279
|
-
if (errorWords.some(word => msgTextLC.includes(word))) {
|
|
280
|
-
report.jobData.errorLogCount++;
|
|
281
|
-
report.jobData.errorLogSize += msgLength;
|
|
282
261
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
msgText.includes('403') && (msgLC.includes('status')
|
|
286
|
-
|| msgLC.includes('prohibited'))
|
|
287
|
-
) {
|
|
288
|
-
report.jobData.prohibitedCount++;
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
});
|
|
292
|
-
// Open the first page of the context.
|
|
293
|
-
const page = await browserContext.newPage();
|
|
294
|
-
try {
|
|
295
|
-
// Wait until it is stable.
|
|
296
|
-
await page.waitForLoadState('domcontentloaded', {timeout: 5000});
|
|
297
|
-
// Navigate to the specified URL.
|
|
298
|
-
const navResult = await goTo(report, page, url, 15000, 'domcontentloaded');
|
|
299
|
-
// If the navigation succeeded:
|
|
300
|
-
if (navResult.success) {
|
|
301
|
-
// Update the name of the current browser type and store it in the page.
|
|
302
|
-
page.browserTypeName = browserID;
|
|
303
|
-
// Return the response of the target server, the browser context, and the page.
|
|
304
|
-
return {
|
|
305
|
-
success: true,
|
|
306
|
-
response: navResult.response,
|
|
307
|
-
browserContext,
|
|
308
|
-
page
|
|
309
|
-
};
|
|
262
|
+
indentedMsg = parts.map(part => ` | ${part}`).join('\n');
|
|
263
|
+
console.log(`\n${indentedMsg}`);
|
|
310
264
|
}
|
|
311
|
-
//
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
265
|
+
// Add statistics on the message to the report.
|
|
266
|
+
const msgTextLC = msgText.toLowerCase();
|
|
267
|
+
const msgLength = msgText.length;
|
|
268
|
+
jobData.logCount++;
|
|
269
|
+
jobData.logSize += msgLength;
|
|
270
|
+
if (errorWords.some(word => msgTextLC.includes(word))) {
|
|
271
|
+
jobData.errorLogCount++;
|
|
272
|
+
jobData.errorLogSize += msgLength;
|
|
273
|
+
}
|
|
274
|
+
const msgLC = msgText.toLowerCase();
|
|
275
|
+
if (
|
|
276
|
+
msgText.includes('403') && (msgLC.includes('status')
|
|
277
|
+
|| msgLC.includes('prohibited'))
|
|
278
|
+
) {
|
|
279
|
+
jobData.prohibitedCount++;
|
|
318
280
|
}
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
// Open the first page (tab) of the context (window).
|
|
284
|
+
const page = await browserContext.newPage();
|
|
285
|
+
try {
|
|
286
|
+
// Wait until it is stable.
|
|
287
|
+
await page.waitForLoadState('domcontentloaded', {timeout: 5000});
|
|
288
|
+
// Navigate to the specified URL.
|
|
289
|
+
const navResult = await goTo(report, page, url, 15000, 'domcontentloaded');
|
|
290
|
+
// If the navigation succeeded:
|
|
291
|
+
if (navResult.success) {
|
|
292
|
+
// Update the name of the current browser type and store it in the page.
|
|
293
|
+
page.browserID = browserID;
|
|
294
|
+
// Return the response of the target server, the browser context, and the page.
|
|
295
|
+
return {
|
|
296
|
+
success: true,
|
|
297
|
+
response: navResult.response,
|
|
298
|
+
browserContext,
|
|
299
|
+
page
|
|
300
|
+
};
|
|
319
301
|
}
|
|
320
|
-
//
|
|
321
|
-
|
|
322
|
-
// Return
|
|
323
|
-
console.log(`ERROR: Blank page load in new tab timed out (${error.message})`);
|
|
302
|
+
// Otherwise, if the navigation failed:
|
|
303
|
+
else {
|
|
304
|
+
// Return the error.
|
|
324
305
|
return {
|
|
325
306
|
success: false,
|
|
326
|
-
error:
|
|
307
|
+
error: navResult.error
|
|
327
308
|
};
|
|
328
309
|
}
|
|
329
310
|
}
|
|
330
|
-
//
|
|
331
|
-
|
|
311
|
+
// If it fails to become stable after load:
|
|
312
|
+
catch(error) {
|
|
332
313
|
// Return this.
|
|
333
|
-
console.log(`ERROR:
|
|
314
|
+
console.log(`ERROR: Blank page load in new tab timed out (${error.message})`);
|
|
334
315
|
return {
|
|
335
316
|
success: false,
|
|
336
|
-
error:
|
|
317
|
+
error: 'Blank page load in new tab timed out'
|
|
337
318
|
};
|
|
338
319
|
}
|
|
339
320
|
}
|
|
@@ -622,12 +603,10 @@ const doActs = async (report, actIndex, page) => {
|
|
|
622
603
|
// Launch the specified browser on the specified device and navigate to the specified URL.
|
|
623
604
|
const launchResult = await launch(
|
|
624
605
|
report,
|
|
625
|
-
act.url || report.target.url,
|
|
626
606
|
debug,
|
|
627
607
|
waits,
|
|
628
|
-
act.deviceID || report.deviceID,
|
|
629
608
|
act.browserID || report.browserID,
|
|
630
|
-
act.
|
|
609
|
+
act.target || report.target
|
|
631
610
|
);
|
|
632
611
|
// If the launch and navigation succeeded:
|
|
633
612
|
if (launchResult && launchResult.success) {
|
package/testaro/focAll.js
CHANGED
|
@@ -50,7 +50,7 @@ exports.reporter = async page => {
|
|
|
50
50
|
*/
|
|
51
51
|
let tabFocused = 0;
|
|
52
52
|
let refocused = 0;
|
|
53
|
-
const keyName = page.
|
|
53
|
+
const keyName = page.browserID === 'webkit' ? 'Alt+Tab' : 'Tab';
|
|
54
54
|
while (refocused < 100 && tabFocused < 2000) {
|
|
55
55
|
await page.keyboard.press(keyName);
|
|
56
56
|
const isNewFocus = await page.evaluate(() => {
|
package/procs/device.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
© 2024 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
-
|
|
4
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
-
in the Software without restriction, including without limitation the rights
|
|
7
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
-
furnished to do so, subject to the following conditions:
|
|
10
|
-
|
|
11
|
-
The above copyright notice and this permission notice shall be included in all
|
|
12
|
-
copies or substantial portions of the Software.
|
|
13
|
-
|
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
-
SOFTWARE.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
// device
|
|
24
|
-
|
|
25
|
-
// IMPORTS
|
|
26
|
-
|
|
27
|
-
const {devices} = require('playwright');
|
|
28
|
-
|
|
29
|
-
// FUNCTIONS
|
|
30
|
-
|
|
31
|
-
// Returns whether a device ID is valid.
|
|
32
|
-
exports.isDeviceID = deviceID => deviceID === 'default' || !! devices[deviceID];
|
|
33
|
-
|
|
34
|
-
// Returns options for the browser.newContext() function.
|
|
35
|
-
exports.getDeviceOptions = (deviceID, motion) => {
|
|
36
|
-
const options = {
|
|
37
|
-
reduceMotion: motion
|
|
38
|
-
};
|
|
39
|
-
// If a non-default device was specified:
|
|
40
|
-
if (deviceID && deviceID !== 'default') {
|
|
41
|
-
// Get its properties if it exists.
|
|
42
|
-
const deviceProperties = devices[deviceID];
|
|
43
|
-
// Return options or report the device as invalid.
|
|
44
|
-
if (deviceProperties) {
|
|
45
|
-
return {
|
|
46
|
-
... options,
|
|
47
|
-
... deviceProperties
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
return {};
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// Otherwise, i.e. if no non-default device was specified:
|
|
55
|
-
else {
|
|
56
|
-
// Return options.
|
|
57
|
-
return options;
|
|
58
|
-
}
|
|
59
|
-
};
|