@axe-core/webdriverjs 4.3.3-alpha.221 → 4.3.3-alpha.225

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axe-core/webdriverjs",
3
- "version": "4.3.3-alpha.221+23b848c",
3
+ "version": "4.3.3-alpha.225+82a84c8",
4
4
  "description": "Provides a method to inject and analyze web pages using axe",
5
5
  "contributors": [
6
6
  {
@@ -27,6 +27,9 @@
27
27
  "name": "Michael Siek (me@michaelsiek.com)"
28
28
  }
29
29
  ],
30
+ "files": [
31
+ "/dist"
32
+ ],
30
33
  "repository": {
31
34
  "type": "git",
32
35
  "url": "https://github.com/dequelabs/axe-core-npm.git"
@@ -105,5 +108,5 @@
105
108
  "functions": 85,
106
109
  "lines": 85
107
110
  },
108
- "gitHead": "23b848c8959046014d9620a46f18088d5cfa8f3b"
111
+ "gitHead": "82a84c8acf7a3e20aa89c119bc6439700a631fdb"
109
112
  }
package/.eslintrc.js DELETED
@@ -1,13 +0,0 @@
1
- module.exports = {
2
- overrides: [
3
- {
4
- files: 'src/test/**/*.ts',
5
- env: {
6
- mocha: true
7
- },
8
- rules: {
9
- '@typescript-eslint/no-var-requires': 'off'
10
- }
11
- }
12
- ]
13
- };
package/error-handling.md DELETED
@@ -1,52 +0,0 @@
1
- # Error Handling
2
-
3
- ## Table of Content
4
-
5
- 1. [Having an Out-of-date Driver](#having-an-out-of-date-driver)
6
- 2. [Having Popup blockers enabled](#having-popup-blockers-enabled)
7
- 3. [AxeBuilder.setLegacyMode(legacy: boolean)](#axebuildersetlegacymodelegacy-boolean)
8
-
9
- Version 4.3.0 and above of the axe-core integrations use a new technique when calling `AxeBuilder.analyze()` which opens a new window at the end of a run. Many of the issues outlined in this document address common problems with this technique and their potential solutions.
10
-
11
- ### Having an Out-of-date Driver
12
-
13
- A common problem is having an out-of-date driver. To fix this issue make sure that your local install of [geckodriver](https://github.com/mozilla/geckodriver/releases) or [chromedriver](https://chromedriver.chromium.org/downloads) is up-to-date.
14
-
15
- An example error message for this problem will include a message about `switchToWindow`.
16
-
17
- Example:
18
-
19
- ```console
20
- (node:17566) UnhandledPromiseRejectionWarning: Error: Malformed type for "handle" parameter of command switchToWindow
21
- Expected: string
22
- Actual: undefined
23
- ```
24
-
25
- ### Having Popup blockers enabled
26
-
27
- Popup blockers prevent us from opening the new window when calling `AxeBuilder.analyze()`. The default configuration for most automation testing libraries should allow popups. Please make sure that you do not explicitly enable popup blockers which may cause an issue while running the tests.
28
-
29
- ### AxeBuilder.setLegacyMode(legacy: boolean)
30
-
31
- If for some reason you are unable to run the new `AxeBuilder.analyze` technique without errors, axe provides a new chainable method that allows you to run the legacy version of `AxeBuilder.analyze`. When using this method axe excludes accessibility issues that may occur in cross-domain frames and iframes.
32
-
33
- **Please Note:** `AxeBuilder.setLegacyMode` is deprecated and will be removed in v5.0. Please report any errors you may have while running `AxeBuilder.analyze` so that they can be fixed before the legacy version is removed.
34
-
35
- #### Example:
36
-
37
- ```js
38
- const AxeBuilder = require('@axe-core/webdriverjs');
39
- const WebDriver = require('selenium-webdriver');
40
- (async () => {
41
- const driver = new WebDriver.Builder().forBrowser('chrome').build();
42
- await driver.get('https://dequeuniversity.com/demo/mars/');
43
- const results = await new AxeBuilder(driver, null, {
44
- noSandbox: true
45
- })
46
- // enables legacy mode
47
- .setLegacyMode()
48
- .analyze();
49
- console.log(results);
50
- await driver.quit();
51
- })();
52
- ```
@@ -1,15 +0,0 @@
1
- const AxeBuilder = require('@axe-core/webdriverjs');
2
- const WebDriver = require('selenium-webdriver');
3
-
4
- const driver = new WebDriver.Builder().forBrowser('chrome').build();
5
-
6
- driver.get('https://html5-sandbox.glitch.me/').then(() => {
7
- const axe = new AxeBuilder(driver, null, { noSandbox: true });
8
- axe.analyze(async (err, results) => {
9
- if (err) {
10
- // Handle error somehow
11
- }
12
- console.log(results);
13
- await driver.quit();
14
- });
15
- });
package/example.js DELETED
@@ -1,13 +0,0 @@
1
- const AxeBuilder = require('@axe-core/webdriverjs');
2
- const WebDriver = require('selenium-webdriver');
3
-
4
- // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
5
- (async () => {
6
- const driver = new WebDriver.Builder().forBrowser('chrome').build();
7
- await driver.get('https://html5-sandbox.glitch.me/');
8
- const results = await new AxeBuilder(driver, null, {
9
- noSandbox: true
10
- }).analyze();
11
- console.log(results);
12
- await driver.quit();
13
- })();
@@ -1,191 +0,0 @@
1
- import type { WebDriver, WebElement } from 'selenium-webdriver';
2
- import { error } from 'selenium-webdriver';
3
- import { source } from 'axe-core';
4
- import type { AxeInjectorParams, BuilderOptions } from './types';
5
- const { StaleElementReferenceError } = error;
6
-
7
- export default class AxeInjectorLegacy {
8
- private driver: WebDriver;
9
- private axeSource: string;
10
- private options: BuilderOptions;
11
- private config: string;
12
- private didLogError: boolean;
13
- constructor({
14
- driver,
15
- axeSource,
16
- builderOptions,
17
- config
18
- }: AxeInjectorParams) {
19
- this.driver = driver;
20
- this.axeSource = axeSource || source;
21
- this.config = config ? JSON.stringify(config) : '';
22
- this.options = builderOptions || {};
23
- this.didLogError = false;
24
-
25
- this.options.noSandbox =
26
- typeof this.options.noSandbox === 'boolean'
27
- ? this.options.noSandbox
28
- : false;
29
-
30
- this.options.logIframeErrors =
31
- typeof this.options.logIframeErrors === 'boolean'
32
- ? this.options.logIframeErrors
33
- : false;
34
- }
35
-
36
- /**
37
- * Checks to make sure that the error thrown was not a stale iframe
38
- * @param {Error} error
39
- * @returns {void}
40
- */
41
-
42
- private errorHandler(err: Error): void {
43
- // We've already "warned" the user. No need to do it again (mostly for backwards compatibility)
44
- if (this.didLogError) {
45
- return;
46
- }
47
-
48
- this.didLogError = true;
49
- let msg;
50
- if (err instanceof StaleElementReferenceError) {
51
- msg =
52
- '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.';
53
- } else {
54
- msg = 'Failed to inject axe-core into one of the iframes!';
55
- }
56
-
57
- if (this.options.logIframeErrors) {
58
- console.error(msg);
59
- return;
60
- }
61
-
62
- throw new Error(msg);
63
- }
64
-
65
- /**
66
- * Get axe-core source and configurations
67
- * @returns {String}
68
- */
69
-
70
- private get script(): string {
71
- return `
72
- ${this.axeSource}
73
- ${this.config ? `axe.configure(${this.config})` : ''}
74
- axe.configure({
75
- branding: { application: 'webdriverjs' }
76
- })
77
- `;
78
- }
79
-
80
- /**
81
- * Removes the `sandbox` attribute from iFrames
82
- * @returns {Promise<void>}
83
- */
84
-
85
- private async sandboxBuster(): Promise<void> {
86
- // outer promise needed because `executeAsyncScript`
87
- // does not return a "real promise" (ManagedPromise)
88
- // and we want to await it.
89
- return new Promise((resolve, reject) => {
90
- /* eslint-disable no-undef */
91
- this.driver
92
- // https://github.com/vercel/pkg/issues/676
93
- // we need to pass a string vs a function so we manually stringified the function
94
- .executeAsyncScript(
95
- `
96
- var callback = arguments[arguments.length - 1];
97
- var iframes = Array.from(
98
- document.querySelectorAll('iframe[sandbox]')
99
- );
100
- var removeSandboxAttr = clone => attr => {
101
- if (attr.name === 'sandbox') return;
102
- clone.setAttribute(attr.name, attr.value);
103
- };
104
- var replaceSandboxedIframe = iframe => {
105
- var clone = document.createElement('iframe');
106
- var promise = new Promise(
107
- iframeLoaded => (clone.onload = iframeLoaded)
108
- );
109
- Array.from(iframe.attributes).forEach(removeSandboxAttr(clone));
110
- iframe.parentElement.replaceChild(clone, iframe);
111
- return promise;
112
- };
113
- Promise.all(iframes.map(replaceSandboxedIframe)).then(callback);
114
- `
115
- )
116
- // resolve the outer promise
117
- .then(() => resolve())
118
- .catch(e => reject(e));
119
- });
120
- }
121
-
122
- /**
123
- * Injects into the provided `frame` and its child `frames`
124
- * @param {WebElement[]} framePath
125
- * @returns {Promise<void>}
126
- */
127
-
128
- private async handleFrame(framePath: WebElement[]): Promise<void> {
129
- await this.driver.switchTo().defaultContent();
130
-
131
- for (const frame of framePath) {
132
- await this.driver.switchTo().frame(frame);
133
- }
134
- if (this.options.noSandbox) {
135
- await this.sandboxBuster();
136
- }
137
-
138
- await this.driver.executeScript(this.script);
139
-
140
- const ifs = await this.driver.findElements({ tagName: 'iframe' });
141
- const fs = await this.driver.findElements({ tagName: 'frame' });
142
- const frames = ifs.concat(fs);
143
-
144
- for (const childFrames of frames) {
145
- framePath.push(childFrames);
146
- try {
147
- await this.handleFrame(framePath);
148
- } catch (error) {
149
- this.errorHandler(error as Error);
150
- } finally {
151
- framePath.pop();
152
- }
153
- }
154
- }
155
-
156
- /**
157
- * Injects into all frames
158
- * @returns {Promise<void>}
159
- */
160
- public async injectIntoAllFrames(): Promise<void> {
161
- // Ensure we're "starting" our loop at the top-most frame
162
- await this.driver.switchTo().defaultContent();
163
-
164
- // By default we do not remove the sandbox attr from iframe unless user specifies
165
- if (this.options.noSandbox) {
166
- // reinject any sandboxed iframes without the sandbox attribute so we can scan
167
- await this.sandboxBuster();
168
- }
169
-
170
- // Inject the script into the top-level
171
- // XXX: if this `executeScript` fails, we *want* to error, as we cannot run axe-core.
172
- await this.driver.executeScript(this.script);
173
-
174
- // Get all of <iframe>s and <frame>s at this level
175
- const ifs = await this.driver.findElements({ tagName: 'iframe' });
176
- const fs = await this.driver.findElements({ tagName: 'frame' });
177
- const frames = ifs.concat(fs);
178
-
179
- // Inject the script into all child frames. Handle errors to ensure we don't stop execution if we fail to inject.
180
- for (const childFrame of frames) {
181
- try {
182
- await this.handleFrame([childFrame]);
183
- } catch (err) {
184
- this.errorHandler(err as Error);
185
- }
186
- }
187
-
188
- // Move back to the top-most frame
189
- return this.driver.switchTo().defaultContent();
190
- }
191
- }
package/src/browser.ts DELETED
@@ -1,142 +0,0 @@
1
- import {
2
- AxeResults,
3
- ContextObject,
4
- FrameContext,
5
- RunOptions,
6
- Spec,
7
- PartialResult
8
- } from 'axe-core';
9
- import { WebDriver, WebElement } from 'selenium-webdriver';
10
-
11
- type FrameContextWeb = FrameContext & {
12
- frame: WebElement;
13
- href: string;
14
- };
15
-
16
- // https://github.com/vercel/pkg/issues/676
17
- // we need to pass a string vs a function so we manually stringified the function
18
- // There are no try/catch blocks needed in these scripts. If an error occurs
19
- // Selenium pass them onto the catch block.
20
-
21
- export function axeSourceInject(
22
- driver: WebDriver,
23
- axeSource: string,
24
- config: Spec | null
25
- ): Promise<{ runPartialSupported: boolean }> {
26
- return promisify(
27
- driver.executeScript<{ runPartialSupported: boolean }>(`
28
- ${axeSource};
29
- window.axe.configure({
30
- branding: { application: 'webdriverjs' }
31
- });
32
- var config = ${JSON.stringify(config)};
33
- if (config) {
34
- window.axe.configure(config);
35
- }
36
- var runPartial = typeof window.axe.runPartial === 'function';
37
- return { runPartialSupported: runPartial };
38
- `)
39
- );
40
- }
41
-
42
- export function axeRunPartial(
43
- driver: WebDriver,
44
- context: ContextObject,
45
- options: RunOptions
46
- ): Promise<string> {
47
- return promisify(
48
- driver.executeAsyncScript<string>(`
49
- var callback = arguments[arguments.length - 1];
50
- var context = ${JSON.stringify(context)} || document;
51
- var options = ${JSON.stringify(options)} || {};
52
- window.axe.runPartial(context, options).then(res => JSON.stringify(res)).then(callback);
53
- `)
54
- );
55
- }
56
-
57
- export function axeFinishRun(
58
- driver: WebDriver,
59
- axeSource: string,
60
- config: Spec | null,
61
- partialResults: Array<string>,
62
- options: RunOptions
63
- ): Promise<AxeResults> {
64
- // Inject source and configuration a second time with a mock "this" context,
65
- // to make it impossible to sniff the global window.axe for results.
66
- return promisify(
67
- driver
68
- .executeAsyncScript<string>(
69
- `
70
- var callback = arguments[arguments.length - 1];
71
-
72
- ${axeSource};
73
- window.axe.configure({
74
- branding: { application: 'webdriverjs' }
75
- });
76
- var config = ${JSON.stringify(config)};
77
- if (config) {
78
- window.axe.configure(config);
79
- }
80
-
81
- var partialResults = ${JSON.stringify(partialResults)};
82
- partialResults = partialResults.map(res => JSON.parse(res));
83
- var options = ${JSON.stringify(options || {})};
84
- window.axe.finishRun(partialResults, options).then(res => JSON.stringify(res)).then(callback);
85
- `
86
- )
87
- .then(res => JSON.parse(res))
88
- );
89
- }
90
-
91
- export function axeGetFrameContext(
92
- driver: WebDriver,
93
- context: ContextObject
94
- ): Promise<FrameContextWeb[]> {
95
- return promisify(
96
- driver.executeScript<FrameContextWeb[]>(`
97
- var context = ${JSON.stringify(context)}
98
- var frameContexts = window.axe.utils.getFrameContexts(context);
99
- return frameContexts.map(function (frameContext) {
100
- return Object.assign(frameContext, {
101
- href: window.location.href, // For debugging
102
- frame: axe.utils.shadowSelect(frameContext.frameSelector)
103
- });
104
- });
105
- `)
106
- );
107
- }
108
-
109
- export function axeRunLegacy(
110
- driver: WebDriver,
111
- context: ContextObject,
112
- options: RunOptions,
113
- config: Spec | null
114
- ): Promise<AxeResults> {
115
- // https://github.com/vercel/pkg/issues/676
116
- // we need to pass a string vs a function so we manually stringified the function
117
- return promisify(
118
- driver
119
- .executeAsyncScript<string>(
120
- `
121
- var callback = arguments[arguments.length - 1];
122
- var context = ${JSON.stringify(context)} || document;
123
- var options = ${JSON.stringify(options)} || {};
124
- var config = ${JSON.stringify(config)} || null;
125
- if (config) {
126
- window.axe.configure(config);
127
- }
128
- window.axe.run(context, options).then(res => JSON.stringify(res)).then(callback);
129
- `
130
- )
131
- .then(res => JSON.parse(res))
132
- );
133
- }
134
-
135
- /**
136
- * Selenium-webdriver thenable aren't chainable. This fixes it.
137
- */
138
- function promisify<T>(thenable: Promise<T>): Promise<T> {
139
- return new Promise((resolve, reject) => {
140
- thenable.then(resolve, reject);
141
- });
142
- }