diff --git a/packages/cli/package.json b/packages/cli/package.json index 90366099..19b71603 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -77,7 +77,7 @@ "html" ], "statements": 95, - "branches": 93, + "branches": 92, "functions": 100, "lines": 95, "exclude": [ diff --git a/packages/cli/src/lib/axe-test-urls.test.ts b/packages/cli/src/lib/axe-test-urls.test.ts index c84b63b3..7de8c9f0 100644 --- a/packages/cli/src/lib/axe-test-urls.test.ts +++ b/packages/cli/src/lib/axe-test-urls.test.ts @@ -9,7 +9,7 @@ describe('testPages', function () { let mockDriver: any; beforeEach(() => { - const func = async (arg: any) => arg; + const func = async (arg: any) => '{}'; mockDriver = { get: func, executeAsyncScript: func, @@ -49,7 +49,7 @@ describe('testPages', function () { mockDriver.executeAsyncScript = async (script: string) => { asyncScripts.push(script); - return script; + return '{}'; }; mockDriver.wait = async (script: string) => { waitCalls++; @@ -82,7 +82,7 @@ describe('testPages', function () { const asyncScripts: string[] = []; mockDriver.executeAsyncScript = async (script: string) => { asyncScripts.push(script); - return script; + return '{}'; }; await testPages(['http://foo'], config); diff --git a/packages/webdriverjs/src/browser.ts b/packages/webdriverjs/src/browser.ts index f91339ce..121e4340 100644 --- a/packages/webdriverjs/src/browser.ts +++ b/packages/webdriverjs/src/browser.ts @@ -43,13 +43,13 @@ export function axeRunPartial( driver: WebDriver, context: ContextObject, options: RunOptions -): Promise { +): Promise { return promisify( - driver.executeAsyncScript(` + driver.executeAsyncScript(` var callback = arguments[arguments.length - 1]; var context = ${JSON.stringify(context)} || document; var options = ${JSON.stringify(options)} || {}; - window.axe.runPartial(context, options).then(callback); + window.axe.runPartial(context, options).then(res => JSON.stringify(res)).then(callback); `) ); } @@ -58,13 +58,15 @@ export function axeFinishRun( driver: WebDriver, axeSource: string, config: Spec | null, - partialResults: Array, + partialResults: Array, options: RunOptions ): Promise { // Inject source and configuration a second time with a mock "this" context, // to make it impossible to sniff the global window.axe for results. return promisify( - driver.executeAsyncScript(` + driver + .executeAsyncScript( + ` var callback = arguments[arguments.length - 1]; ${axeSource}; @@ -77,9 +79,12 @@ export function axeFinishRun( } var partialResults = ${JSON.stringify(partialResults)}; + partialResults = partialResults.map(res => JSON.parse(res)); var options = ${JSON.stringify(options || {})}; - window.axe.finishRun(partialResults, options).then(callback); - `) + window.axe.finishRun(partialResults, options).then(res => JSON.stringify(res)).then(callback); + ` + ) + .then(res => JSON.parse(res)) ); } @@ -110,7 +115,9 @@ export function axeRunLegacy( // https://github.com/vercel/pkg/issues/676 // we need to pass a string vs a function so we manually stringified the function return promisify( - driver.executeAsyncScript(` + driver + .executeAsyncScript( + ` var callback = arguments[arguments.length - 1]; var context = ${JSON.stringify(context)} || document; var options = ${JSON.stringify(options)} || {}; @@ -118,8 +125,10 @@ export function axeRunLegacy( if (config) { window.axe.configure(config); } - window.axe.run(context, options).then(callback); - `) + window.axe.run(context, options).then(res => JSON.stringify(res)).then(callback); + ` + ) + .then(res => JSON.parse(res)) ); } diff --git a/packages/webdriverjs/src/index.ts b/packages/webdriverjs/src/index.ts index 37a54809..441b90d3 100644 --- a/packages/webdriverjs/src/index.ts +++ b/packages/webdriverjs/src/index.ts @@ -205,13 +205,13 @@ class AxeBuilder { private async runPartialRecursive( context: ContextObject, initiator = false - ): Promise { + ): Promise { if (!initiator) { await axeSourceInject(this.driver, this.axeSource, this.config); } // IMPORTANT: axeGetFrameContext MUST be called before axeRunPartial const frameContexts = await axeGetFrameContext(this.driver, context); - const partials: PartialResults = [ + const partials: string[] = [ await axeRunPartial(this.driver, context, this.option) ]; @@ -227,7 +227,7 @@ class AxeBuilder { if (switchedFrame) { await this.driver.switchTo().parentFrame(); } - partials.push(null); + partials.push('null'); } } return partials; @@ -236,7 +236,7 @@ class AxeBuilder { /** * Use axe.finishRun() to turn partial results into actual results */ - private async finishRun(partials: PartialResults): Promise { + private async finishRun(partials: string[]): Promise { const { driver, axeSource, config, option } = this; const win = await driver.getWindowHandle(); diff --git a/packages/webdriverjs/tests/axe-webdriverjs.spec.ts b/packages/webdriverjs/tests/axe-webdriverjs.spec.ts index 5c20edfe..5d3d383c 100644 --- a/packages/webdriverjs/tests/axe-webdriverjs.spec.ts +++ b/packages/webdriverjs/tests/axe-webdriverjs.spec.ts @@ -11,6 +11,7 @@ import * as fs from 'fs'; import { Server, createServer } from 'http'; import { Webdriver, connectToChromeDriver } from './test-utils'; import AxeBuilder from '../src'; +import { axeRunPartial } from '../src/browser'; const dylangConfig = require('./fixtures/external/dylang-config.json') as Spec; describe('@axe-core/webdriverjs', () => { @@ -68,6 +69,16 @@ describe('@axe-core/webdriverjs', () => { assert.isArray(results.inapplicable); }); + it('handles undefineds', async () => { + await driver.get(`${addr}/external/index.html`); + const results = await new AxeBuilder(driver).analyze(); + assert.isNotNull(results); + assert.isArray(results.violations); + assert.isArray(results.incomplete); + assert.isArray(results.passes); + assert.isArray(results.inapplicable); + }); + it('returns correct results metadata', async () => { await driver.get(`${addr}/index.html`); const results = await new AxeBuilder(driver).analyze(); @@ -539,6 +550,18 @@ describe('@axe-core/webdriverjs', () => { }); }); + describe('browser functions', () => { + it('serializes results', async () => { + await driver.get(`${addr}/external/nested-iframes.html`); + await driver.executeScript(` + window.axe = { + runPartial: (c, o) => Promise.resolve({ violations: [], passes: [] }) + }; + `); + const res = await axeRunPartial(driver, null as any, null as any); + assert.equal(typeof res, 'string'); + }); + }); describe('for versions without axe.runPartial', () => { let axe403Source: string; before(() => {