@axe-core/webdriverjs 4.6.2-alpha.379 → 4.7.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/dist/index.js CHANGED
@@ -1,356 +1,520 @@
1
1
  "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
- return new (P || (P = Promise))(function (resolve, reject) {
16
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
- step((generator = generator.apply(thisArg, _arguments || [])).next());
20
- });
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
21
11
  };
22
- var __generator = (this && this.__generator) || function (thisArg, body) {
23
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
- function verb(n) { return function (v) { return step([n, v]); }; }
26
- function step(op) {
27
- if (f) throw new TypeError("Generator is already executing.");
28
- while (_) try {
29
- 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;
30
- if (y = 0, t) op = [op[0] & 2, t.value];
31
- switch (op[0]) {
32
- case 0: case 1: t = op; break;
33
- case 4: _.label++; return { value: op[1], done: false };
34
- case 5: _.label++; y = op[1]; op = [0]; continue;
35
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
- default:
37
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
- if (t[2]) _.ops.pop();
42
- _.trys.pop(); continue;
43
- }
44
- op = body.call(thisArg, _);
45
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
- }
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
48
19
  };
49
- var __importDefault = (this && this.__importDefault) || function (mod) {
50
- return (mod && mod.__esModule) ? mod : { "default": mod };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ default: () => src_default
34
+ });
35
+ module.exports = __toCommonJS(src_exports);
36
+ var import_axe_core2 = __toESM(require("axe-core"));
37
+
38
+ // src/utils/index.ts
39
+ var normalizeContext = (include, exclude) => {
40
+ const base = {
41
+ exclude: []
42
+ };
43
+ if (exclude.length && Array.isArray(base.exclude)) {
44
+ base.exclude.push(...exclude);
45
+ }
46
+ if (include.length) {
47
+ base.include = include;
48
+ }
49
+ return base;
51
50
  };
52
- Object.defineProperty(exports, "__esModule", { value: true });
53
- var axe_core_1 = require("axe-core");
54
- var index_1 = require("./utils/index");
55
- var axe_injector_1 = __importDefault(require("./axe-injector"));
56
- var browser_1 = require("./browser");
57
- var assert_1 = __importDefault(require("assert"));
58
- var AxeBuilder = /** @class */ (function () {
59
- function AxeBuilder(driver, axeSource, builderOptions) {
60
- this.legacyMode = false;
61
- this.driver = driver;
62
- this.axeSource = axeSource || axe_core_1.source;
63
- this.includes = [];
64
- this.excludes = [];
65
- this.option = {};
66
- this.config = null;
67
- this.builderOptions = builderOptions || {};
68
- this.errorUrl =
69
- 'https://github.com/dequelabs/axe-core-npm/blob/develop/packages/webdriverjs/error-handling.md';
51
+
52
+ // src/axe-injector.ts
53
+ var import_selenium_webdriver = require("selenium-webdriver");
54
+ var import_axe_core = __toESM(require("axe-core"));
55
+ var { source } = import_axe_core.default;
56
+ var { StaleElementReferenceError } = import_selenium_webdriver.error;
57
+ var AxeInjectorLegacy = class {
58
+ driver;
59
+ axeSource;
60
+ options;
61
+ config;
62
+ didLogError;
63
+ constructor({
64
+ driver,
65
+ axeSource,
66
+ builderOptions,
67
+ config
68
+ }) {
69
+ this.driver = driver;
70
+ this.axeSource = axeSource || source;
71
+ this.config = config ? JSON.stringify(config) : "";
72
+ this.options = builderOptions || {};
73
+ this.didLogError = false;
74
+ this.options.noSandbox = typeof this.options.noSandbox === "boolean" ? this.options.noSandbox : false;
75
+ this.options.logIframeErrors = typeof this.options.logIframeErrors === "boolean" ? this.options.logIframeErrors : false;
76
+ }
77
+ /**
78
+ * Checks to make sure that the error thrown was not a stale iframe
79
+ * @param {Error} error
80
+ * @returns {void}
81
+ */
82
+ errorHandler(err) {
83
+ if (this.didLogError) {
84
+ return;
70
85
  }
71
- /**
72
- * Selector to include in analysis.
73
- * This may be called any number of times.
74
- */
75
- AxeBuilder.prototype.include = function (selector) {
76
- this.includes.push(selector);
77
- return this;
78
- };
79
- /**
80
- * Selector to exclude in analysis.
81
- * This may be called any number of times.
82
- */
83
- AxeBuilder.prototype.exclude = function (selector) {
84
- this.excludes.push(selector);
85
- return this;
86
- };
87
- /**
88
- * Set options to be passed into axe-core
89
- */
90
- AxeBuilder.prototype.options = function (options) {
91
- this.option = options;
92
- return this;
93
- };
94
- /**
95
- * Limit analysis to only the specified rules.
96
- * Cannot be used with `AxeBuilder#withTags`
97
- */
98
- AxeBuilder.prototype.withRules = function (rules) {
99
- rules = Array.isArray(rules) ? rules : [rules];
100
- this.option.runOnly = {
101
- type: 'rule',
102
- values: rules
103
- };
104
- return this;
86
+ this.didLogError = true;
87
+ let msg;
88
+ if (err instanceof StaleElementReferenceError) {
89
+ msg = "Tried to inject into a removed iframe. This will not affect the analysis of the rest of the page but you might want to ensure the page has finished updating before starting the analysis.";
90
+ } else {
91
+ msg = "Failed to inject axe-core into one of the iframes!";
92
+ }
93
+ if (this.options.logIframeErrors) {
94
+ console.error(msg);
95
+ return;
96
+ }
97
+ throw new Error(msg);
98
+ }
99
+ /**
100
+ * Get axe-core source and configurations
101
+ * @returns {String}
102
+ */
103
+ get script() {
104
+ return `
105
+ ${this.axeSource}
106
+ ${this.config ? `axe.configure(${this.config})` : ""}
107
+ axe.configure({
108
+ branding: { application: 'webdriverjs' }
109
+ })
110
+ `;
111
+ }
112
+ /**
113
+ * Removes the `sandbox` attribute from iFrames
114
+ * @returns {Promise<void>}
115
+ */
116
+ async sandboxBuster() {
117
+ return new Promise((resolve, reject) => {
118
+ this.driver.executeAsyncScript(
119
+ `
120
+ var callback = arguments[arguments.length - 1];
121
+ var iframes = Array.from(
122
+ document.querySelectorAll('iframe[sandbox]')
123
+ );
124
+ var removeSandboxAttr = clone => attr => {
125
+ if (attr.name === 'sandbox') return;
126
+ clone.setAttribute(attr.name, attr.value);
127
+ };
128
+ var replaceSandboxedIframe = iframe => {
129
+ var clone = document.createElement('iframe');
130
+ var promise = new Promise(
131
+ iframeLoaded => (clone.onload = iframeLoaded)
132
+ );
133
+ Array.from(iframe.attributes).forEach(removeSandboxAttr(clone));
134
+ iframe.parentElement.replaceChild(clone, iframe);
135
+ return promise;
136
+ };
137
+ Promise.all(iframes.map(replaceSandboxedIframe)).then(callback);
138
+ `
139
+ ).then(() => resolve()).catch((e) => reject(e));
140
+ });
141
+ }
142
+ /**
143
+ * Injects into the provided `frame` and its child `frames`
144
+ * @param {WebElement[]} framePath
145
+ * @returns {Promise<void>}
146
+ */
147
+ async handleFrame(framePath) {
148
+ await this.driver.switchTo().defaultContent();
149
+ for (const frame of framePath) {
150
+ await this.driver.switchTo().frame(frame);
151
+ }
152
+ if (this.options.noSandbox) {
153
+ await this.sandboxBuster();
154
+ }
155
+ await this.driver.executeScript(this.script);
156
+ const ifs = await this.driver.findElements({ tagName: "iframe" });
157
+ const fs = await this.driver.findElements({ tagName: "frame" });
158
+ const frames = ifs.concat(fs);
159
+ for (const childFrames of frames) {
160
+ framePath.push(childFrames);
161
+ try {
162
+ await this.handleFrame(framePath);
163
+ } catch (error2) {
164
+ this.errorHandler(error2);
165
+ } finally {
166
+ framePath.pop();
167
+ }
168
+ }
169
+ }
170
+ /**
171
+ * Injects into all frames
172
+ * @returns {Promise<void>}
173
+ */
174
+ async injectIntoAllFrames() {
175
+ await this.driver.switchTo().defaultContent();
176
+ if (this.options.noSandbox) {
177
+ await this.sandboxBuster();
178
+ }
179
+ await this.driver.executeScript(this.script);
180
+ const ifs = await this.driver.findElements({ tagName: "iframe" });
181
+ const fs = await this.driver.findElements({ tagName: "frame" });
182
+ const frames = ifs.concat(fs);
183
+ for (const childFrame of frames) {
184
+ try {
185
+ await this.handleFrame([childFrame]);
186
+ } catch (err) {
187
+ this.errorHandler(err);
188
+ }
189
+ }
190
+ return this.driver.switchTo().defaultContent();
191
+ }
192
+ };
193
+
194
+ // src/browser.ts
195
+ function axeSourceInject(driver, axeSource, config) {
196
+ return promisify(
197
+ driver.executeScript(`
198
+ ${axeSource};
199
+ window.axe.configure({
200
+ branding: { application: 'webdriverjs' }
201
+ });
202
+ var config = ${JSON.stringify(config)};
203
+ if (config) {
204
+ window.axe.configure(config);
205
+ }
206
+ var runPartial = typeof window.axe.runPartial === 'function';
207
+ return { runPartialSupported: runPartial };
208
+ `)
209
+ );
210
+ }
211
+ function axeRunPartial(driver, context, options) {
212
+ return promisify(
213
+ driver.executeAsyncScript(`
214
+ var callback = arguments[arguments.length - 1];
215
+ var context = ${JSON.stringify(context)} || document;
216
+ var options = ${JSON.stringify(options)} || {};
217
+ window.axe.runPartial(context, options).then(res => JSON.stringify(res)).then(callback);
218
+ `)
219
+ );
220
+ }
221
+ function axeFinishRun(driver, axeSource, config, partialResults, options) {
222
+ const sizeLimit = 15e6;
223
+ const partialString = JSON.stringify(partialResults);
224
+ function chunkResults(result) {
225
+ const chunk = JSON.stringify(result.substring(0, sizeLimit));
226
+ return promisify(
227
+ driver.executeScript(
228
+ `
229
+ window.partialResults ??= '';
230
+ window.partialResults += ${chunk};
231
+ `
232
+ )
233
+ ).then(() => {
234
+ if (result.length > sizeLimit) {
235
+ return chunkResults(result.substr(sizeLimit));
236
+ }
237
+ });
238
+ }
239
+ return chunkResults(partialString).then(() => {
240
+ return promisify(
241
+ driver.executeAsyncScript(
242
+ `
243
+ var callback = arguments[arguments.length - 1];
244
+
245
+ ${axeSource};
246
+ window.axe.configure({
247
+ branding: { application: 'webdriverjs' }
248
+ });
249
+ var config = ${JSON.stringify(config)};
250
+ if (config) {
251
+ window.axe.configure(config);
252
+ }
253
+
254
+ var partialResults = JSON.parse(window.partialResults).map(res => JSON.parse(res));
255
+ var options = ${JSON.stringify(options || {})};
256
+ window.axe.finishRun(partialResults, options).then(res => JSON.stringify(res)).then(callback);
257
+ `
258
+ )
259
+ );
260
+ }).then((res) => JSON.parse(res));
261
+ }
262
+ function axeGetFrameContext(driver, context) {
263
+ return promisify(
264
+ driver.executeScript(`
265
+ var context = ${JSON.stringify(context)}
266
+ var frameContexts = window.axe.utils.getFrameContexts(context);
267
+ return frameContexts.map(function (frameContext) {
268
+ return Object.assign(frameContext, {
269
+ href: window.location.href, // For debugging
270
+ frame: axe.utils.shadowSelect(frameContext.frameSelector)
271
+ });
272
+ });
273
+ `)
274
+ );
275
+ }
276
+ function axeRunLegacy(driver, context, options, config) {
277
+ return promisify(
278
+ driver.executeAsyncScript(
279
+ `
280
+ var callback = arguments[arguments.length - 1];
281
+ var context = ${JSON.stringify(context)} || document;
282
+ var options = ${JSON.stringify(options)} || {};
283
+ var config = ${JSON.stringify(config)} || null;
284
+ if (config) {
285
+ window.axe.configure(config);
286
+ }
287
+ window.axe.run(context, options).then(res => JSON.stringify(res)).then(callback);
288
+ `
289
+ ).then((res) => JSON.parse(res))
290
+ );
291
+ }
292
+ function promisify(thenable) {
293
+ return new Promise((resolve, reject) => {
294
+ thenable.then(resolve, reject);
295
+ });
296
+ }
297
+
298
+ // src/index.ts
299
+ var import_assert = __toESM(require("assert"));
300
+ var { source: source2 } = import_axe_core2.default;
301
+ var AxeBuilder = class {
302
+ driver;
303
+ axeSource;
304
+ includes;
305
+ excludes;
306
+ option;
307
+ config;
308
+ builderOptions;
309
+ legacyMode = false;
310
+ errorUrl;
311
+ constructor(driver, axeSource, builderOptions) {
312
+ this.driver = driver;
313
+ this.axeSource = axeSource || source2;
314
+ this.includes = [];
315
+ this.excludes = [];
316
+ this.option = {};
317
+ this.config = null;
318
+ this.builderOptions = builderOptions || {};
319
+ this.errorUrl = "https://github.com/dequelabs/axe-core-npm/blob/develop/packages/webdriverjs/error-handling.md";
320
+ }
321
+ /**
322
+ * Selector to include in analysis.
323
+ * This may be called any number of times.
324
+ */
325
+ include(selector) {
326
+ this.includes.push(selector);
327
+ return this;
328
+ }
329
+ /**
330
+ * Selector to exclude in analysis.
331
+ * This may be called any number of times.
332
+ */
333
+ exclude(selector) {
334
+ this.excludes.push(selector);
335
+ return this;
336
+ }
337
+ /**
338
+ * Set options to be passed into axe-core
339
+ */
340
+ options(options) {
341
+ this.option = options;
342
+ return this;
343
+ }
344
+ /**
345
+ * Limit analysis to only the specified rules.
346
+ * Cannot be used with `AxeBuilder#withTags`
347
+ */
348
+ withRules(rules) {
349
+ rules = Array.isArray(rules) ? rules : [rules];
350
+ this.option.runOnly = {
351
+ type: "rule",
352
+ values: rules
105
353
  };
106
- /**
107
- * Limit analysis to only specified tags.
108
- * Cannot be used with `AxeBuilder#withRules`
109
- */
110
- AxeBuilder.prototype.withTags = function (tags) {
111
- tags = Array.isArray(tags) ? tags : [tags];
112
- this.option.runOnly = {
113
- type: 'tag',
114
- values: tags
115
- };
116
- return this;
354
+ return this;
355
+ }
356
+ /**
357
+ * Limit analysis to only specified tags.
358
+ * Cannot be used with `AxeBuilder#withRules`
359
+ */
360
+ withTags(tags) {
361
+ tags = Array.isArray(tags) ? tags : [tags];
362
+ this.option.runOnly = {
363
+ type: "tag",
364
+ values: tags
117
365
  };
118
- /**
119
- * Set the list of rules to skip when running an analysis.
120
- */
121
- AxeBuilder.prototype.disableRules = function (rules) {
122
- rules = Array.isArray(rules) ? rules : [rules];
123
- this.option.rules = {};
124
- for (var _i = 0, rules_1 = rules; _i < rules_1.length; _i++) {
125
- var rule = rules_1[_i];
126
- this.option.rules[rule] = { enabled: false };
366
+ return this;
367
+ }
368
+ /**
369
+ * Set the list of rules to skip when running an analysis.
370
+ */
371
+ disableRules(rules) {
372
+ rules = Array.isArray(rules) ? rules : [rules];
373
+ this.option.rules = {};
374
+ for (const rule of rules) {
375
+ this.option.rules[rule] = { enabled: false };
376
+ }
377
+ return this;
378
+ }
379
+ /**
380
+ * Set configuration for `axe-core`.
381
+ * This value is passed directly to `axe.configure()`
382
+ */
383
+ configure(config) {
384
+ if (typeof config !== "object") {
385
+ throw new Error(
386
+ "AxeBuilder needs an object to configure. See axe-core configure API."
387
+ );
388
+ }
389
+ this.config = config;
390
+ return this;
391
+ }
392
+ /**
393
+ * Performs an analysis and retrieves results.
394
+ */
395
+ async analyze(callback) {
396
+ return new Promise((resolve, reject) => {
397
+ return this.analyzePromise().then((results) => {
398
+ callback?.(null, results);
399
+ resolve(results);
400
+ }).catch((err) => {
401
+ if (callback) {
402
+ callback(err, null);
403
+ } else {
404
+ reject(err);
127
405
  }
128
- return this;
129
- };
130
- /**
131
- * Set configuration for `axe-core`.
132
- * This value is passed directly to `axe.configure()`
133
- */
134
- AxeBuilder.prototype.configure = function (config) {
135
- if (typeof config !== 'object') {
136
- throw new Error('AxeBuilder needs an object to configure. See axe-core configure API.');
406
+ });
407
+ });
408
+ }
409
+ /**
410
+ * Use frameMessenger with <same_origin_only>
411
+ *
412
+ * This disables use of axe.runPartial() which is called in each frame, and
413
+ * axe.finishRun() which is called in a blank page. This uses axe.run() instead,
414
+ * but with the restriction that cross-origin frames will not be tested.
415
+ */
416
+ setLegacyMode(legacyMode = true) {
417
+ this.legacyMode = legacyMode;
418
+ return this;
419
+ }
420
+ /**
421
+ * Analyzes the page, returning a promise
422
+ */
423
+ async analyzePromise() {
424
+ const context = normalizeContext(this.includes, this.excludes);
425
+ await this.driver.switchTo().defaultContent();
426
+ const { runPartialSupported } = await axeSourceInject(
427
+ this.driver,
428
+ this.axeSource,
429
+ this.config
430
+ );
431
+ if (runPartialSupported !== true || this.legacyMode) {
432
+ return this.runLegacy(context);
433
+ }
434
+ const partials = await this.runPartialRecursive(context, true);
435
+ try {
436
+ return await this.finishRun(partials);
437
+ } catch (error2) {
438
+ throw new Error(
439
+ `${error2.message}
440
+ Please check out ${this.errorUrl}`
441
+ );
442
+ }
443
+ }
444
+ /**
445
+ * Use axe.run() to get results from the page
446
+ */
447
+ async runLegacy(context) {
448
+ const { driver, axeSource, builderOptions } = this;
449
+ let config = this.config;
450
+ if (!this.legacyMode) {
451
+ config = {
452
+ ...config || {},
453
+ allowedOrigins: ["<unsafe_all_origins>"]
454
+ };
455
+ }
456
+ const injector = new AxeInjectorLegacy({
457
+ driver,
458
+ axeSource,
459
+ config,
460
+ builderOptions
461
+ });
462
+ await injector.injectIntoAllFrames();
463
+ return axeRunLegacy(this.driver, context, this.option, this.config);
464
+ }
465
+ /**
466
+ * Get partial results from the current context and its child frames
467
+ */
468
+ async runPartialRecursive(context, initiator = false) {
469
+ if (!initiator) {
470
+ await axeSourceInject(this.driver, this.axeSource, this.config);
471
+ }
472
+ const frameContexts = await axeGetFrameContext(this.driver, context);
473
+ const partials = [
474
+ await axeRunPartial(this.driver, context, this.option)
475
+ ];
476
+ for (const { frameContext, frameSelector, frame } of frameContexts) {
477
+ let switchedFrame = false;
478
+ try {
479
+ (0, import_assert.default)(frame, `Expect frame of "${frameSelector}" to be defined`);
480
+ await this.driver.switchTo().frame(frame);
481
+ switchedFrame = true;
482
+ partials.push(...await this.runPartialRecursive(frameContext));
483
+ await this.driver.switchTo().parentFrame();
484
+ } catch {
485
+ if (switchedFrame) {
486
+ await this.driver.switchTo().parentFrame();
137
487
  }
138
- this.config = config;
139
- return this;
140
- };
141
- /**
142
- * Performs an analysis and retrieves results.
143
- */
144
- AxeBuilder.prototype.analyze = function (callback) {
145
- return __awaiter(this, void 0, void 0, function () {
146
- var _this = this;
147
- return __generator(this, function (_a) {
148
- return [2 /*return*/, new Promise(function (resolve, reject) {
149
- return _this.analyzePromise()
150
- .then(function (results) {
151
- callback === null || callback === void 0 ? void 0 : callback(null, results);
152
- resolve(results);
153
- })
154
- .catch(function (err) {
155
- // When using a callback, do *not* reject the wrapping Promise. This prevents having to handle the same error twice.
156
- if (callback) {
157
- callback(err, null);
158
- }
159
- else {
160
- reject(err);
161
- }
162
- });
163
- })];
164
- });
165
- });
166
- };
167
- /**
168
- * Use frameMessenger with <same_origin_only>
169
- *
170
- * This disables use of axe.runPartial() which is called in each frame, and
171
- * axe.finishRun() which is called in a blank page. This uses axe.run() instead,
172
- * but with the restriction that cross-origin frames will not be tested.
173
- */
174
- AxeBuilder.prototype.setLegacyMode = function (legacyMode) {
175
- if (legacyMode === void 0) { legacyMode = true; }
176
- this.legacyMode = legacyMode;
177
- return this;
178
- };
179
- /**
180
- * Analyzes the page, returning a promise
181
- */
182
- AxeBuilder.prototype.analyzePromise = function () {
183
- return __awaiter(this, void 0, void 0, function () {
184
- var context, runPartialSupported, partials, error_1;
185
- return __generator(this, function (_a) {
186
- switch (_a.label) {
187
- case 0:
188
- context = (0, index_1.normalizeContext)(this.includes, this.excludes);
189
- return [4 /*yield*/, this.driver.switchTo().defaultContent()];
190
- case 1:
191
- _a.sent();
192
- return [4 /*yield*/, (0, browser_1.axeSourceInject)(this.driver, this.axeSource, this.config)];
193
- case 2:
194
- runPartialSupported = (_a.sent()).runPartialSupported;
195
- if (runPartialSupported !== true || this.legacyMode) {
196
- return [2 /*return*/, this.runLegacy(context)];
197
- }
198
- return [4 /*yield*/, this.runPartialRecursive(context, true)];
199
- case 3:
200
- partials = _a.sent();
201
- _a.label = 4;
202
- case 4:
203
- _a.trys.push([4, 6, , 7]);
204
- return [4 /*yield*/, this.finishRun(partials)];
205
- case 5: return [2 /*return*/, _a.sent()];
206
- case 6:
207
- error_1 = _a.sent();
208
- throw new Error("".concat(error_1.message, "\n Please check out ").concat(this.errorUrl));
209
- case 7: return [2 /*return*/];
210
- }
211
- });
212
- });
213
- };
214
- /**
215
- * Use axe.run() to get results from the page
216
- */
217
- AxeBuilder.prototype.runLegacy = function (context) {
218
- return __awaiter(this, void 0, void 0, function () {
219
- var _a, driver, axeSource, builderOptions, config, injector;
220
- return __generator(this, function (_b) {
221
- switch (_b.label) {
222
- case 0:
223
- _a = this, driver = _a.driver, axeSource = _a.axeSource, builderOptions = _a.builderOptions;
224
- config = this.config;
225
- if (!this.legacyMode) {
226
- config = __assign(__assign({}, (config || {})), { allowedOrigins: ['<unsafe_all_origins>'] });
227
- }
228
- injector = new axe_injector_1.default({
229
- driver: driver,
230
- axeSource: axeSource,
231
- config: config,
232
- builderOptions: builderOptions
233
- });
234
- return [4 /*yield*/, injector.injectIntoAllFrames()];
235
- case 1:
236
- _b.sent();
237
- return [2 /*return*/, (0, browser_1.axeRunLegacy)(this.driver, context, this.option, this.config)];
238
- }
239
- });
240
- });
241
- };
242
- /**
243
- * Get partial results from the current context and its child frames
244
- */
245
- AxeBuilder.prototype.runPartialRecursive = function (context, initiator) {
246
- if (initiator === void 0) { initiator = false; }
247
- return __awaiter(this, void 0, void 0, function () {
248
- var frameContexts, partials, _i, frameContexts_1, _a, frameContext, frameSelector, frame, switchedFrame, _b, _c, _d, _e;
249
- return __generator(this, function (_f) {
250
- switch (_f.label) {
251
- case 0:
252
- if (!!initiator) return [3 /*break*/, 2];
253
- return [4 /*yield*/, (0, browser_1.axeSourceInject)(this.driver, this.axeSource, this.config)];
254
- case 1:
255
- _f.sent();
256
- _f.label = 2;
257
- case 2: return [4 /*yield*/, (0, browser_1.axeGetFrameContext)(this.driver, context)];
258
- case 3:
259
- frameContexts = _f.sent();
260
- return [4 /*yield*/, (0, browser_1.axeRunPartial)(this.driver, context, this.option)];
261
- case 4:
262
- partials = [
263
- _f.sent()
264
- ];
265
- _i = 0, frameContexts_1 = frameContexts;
266
- _f.label = 5;
267
- case 5:
268
- if (!(_i < frameContexts_1.length)) return [3 /*break*/, 14];
269
- _a = frameContexts_1[_i], frameContext = _a.frameContext, frameSelector = _a.frameSelector, frame = _a.frame;
270
- switchedFrame = false;
271
- _f.label = 6;
272
- case 6:
273
- _f.trys.push([6, 10, , 13]);
274
- (0, assert_1.default)(frame, "Expect frame of \"".concat(frameSelector, "\" to be defined"));
275
- return [4 /*yield*/, this.driver.switchTo().frame(frame)];
276
- case 7:
277
- _f.sent();
278
- switchedFrame = true;
279
- _c = (_b = partials.push).apply;
280
- _d = [partials];
281
- return [4 /*yield*/, this.runPartialRecursive(frameContext)];
282
- case 8:
283
- _c.apply(_b, _d.concat([(_f.sent())]));
284
- return [4 /*yield*/, this.driver.switchTo().parentFrame()];
285
- case 9:
286
- _f.sent();
287
- return [3 /*break*/, 13];
288
- case 10:
289
- _e = _f.sent();
290
- if (!switchedFrame) return [3 /*break*/, 12];
291
- return [4 /*yield*/, this.driver.switchTo().parentFrame()];
292
- case 11:
293
- _f.sent();
294
- _f.label = 12;
295
- case 12:
296
- partials.push('null');
297
- return [3 /*break*/, 13];
298
- case 13:
299
- _i++;
300
- return [3 /*break*/, 5];
301
- case 14: return [2 /*return*/, partials];
302
- }
303
- });
304
- });
305
- };
306
- /**
307
- * Use axe.finishRun() to turn partial results into actual results
308
- */
309
- AxeBuilder.prototype.finishRun = function (partials) {
310
- return __awaiter(this, void 0, void 0, function () {
311
- var _a, driver, axeSource, config, option, win, handlers, error_2, res;
312
- return __generator(this, function (_b) {
313
- switch (_b.label) {
314
- case 0:
315
- _a = this, driver = _a.driver, axeSource = _a.axeSource, config = _a.config, option = _a.option;
316
- return [4 /*yield*/, driver.getWindowHandle()];
317
- case 1:
318
- win = _b.sent();
319
- _b.label = 2;
320
- case 2:
321
- _b.trys.push([2, 7, , 8]);
322
- return [4 /*yield*/, driver.executeScript("window.open('about:blank')")];
323
- case 3:
324
- _b.sent();
325
- return [4 /*yield*/, driver.getAllWindowHandles()];
326
- case 4:
327
- handlers = _b.sent();
328
- return [4 /*yield*/, driver.switchTo().window(handlers[handlers.length - 1])];
329
- case 5:
330
- _b.sent();
331
- return [4 /*yield*/, driver.get('about:blank')];
332
- case 6:
333
- _b.sent();
334
- return [3 /*break*/, 8];
335
- case 7:
336
- error_2 = _b.sent();
337
- throw new Error("switchTo failed. Are you using updated browser drivers? \nDriver reported:\n".concat(error_2));
338
- case 8: return [4 /*yield*/, (0, browser_1.axeFinishRun)(driver, axeSource, config, partials, option)];
339
- case 9:
340
- res = _b.sent();
341
- return [4 /*yield*/, driver.close()];
342
- case 10:
343
- _b.sent();
344
- return [4 /*yield*/, driver.switchTo().window(win)];
345
- case 11:
346
- _b.sent();
347
- return [2 /*return*/, res];
348
- }
349
- });
350
- });
351
- };
352
- return AxeBuilder;
353
- }());
354
- exports = module.exports = AxeBuilder;
355
- exports.default = AxeBuilder;
356
- //# sourceMappingURL=index.js.map
488
+ partials.push("null");
489
+ }
490
+ }
491
+ return partials;
492
+ }
493
+ /**
494
+ * Use axe.finishRun() to turn partial results into actual results
495
+ */
496
+ async finishRun(partials) {
497
+ const { driver, axeSource, config, option } = this;
498
+ const win = await driver.getWindowHandle();
499
+ try {
500
+ await driver.executeScript(`window.open('about:blank')`);
501
+ const handlers = await driver.getAllWindowHandles();
502
+ await driver.switchTo().window(handlers[handlers.length - 1]);
503
+ await driver.get("about:blank");
504
+ } catch (error2) {
505
+ throw new Error(
506
+ `switchTo failed. Are you using updated browser drivers?
507
+ Driver reported:
508
+ ${error2}`
509
+ );
510
+ }
511
+ const res = await axeFinishRun(driver, axeSource, config, partials, option);
512
+ await driver.close();
513
+ await driver.switchTo().window(win);
514
+ return res;
515
+ }
516
+ };
517
+ if (typeof module === "object") {
518
+ exports = module.exports = AxeBuilder;
519
+ }
520
+ var src_default = AxeBuilder;