Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: webdriver7 #150

Merged
merged 25 commits into from
Sep 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
365f201
feat(wdio): upgrade to wdio7
jasonschroeder-sfdc Sep 1, 2022
7fd0db0
feat(wdio7): wdio.config.js
jasonschroeder-sfdc Sep 1, 2022
f39b904
feat(wdio7): remove @wdio/sync
jasonschroeder-sfdc Sep 1, 2022
faced84
test(wdio): finish fixing the test failures for the wdio suite
jasonschroeder-sfdc Sep 9, 2022
89e3918
feat: tsconfig package for tsconfig.json
jasonschroeder-sfdc Sep 9, 2022
acb1d7a
refactor(ts-node): add wdio/async to tsconfig types
jasonschroeder-sfdc Sep 9, 2022
70b282e
refactor: mocha to jasmine
jasonschroeder-sfdc Sep 19, 2022
0ab947f
fix(jasmine): add jasmine types to tsc
jasonschroeder-sfdc Sep 21, 2022
7586ada
refactor: import @jest/globals
jasonschroeder-sfdc Sep 19, 2022
56982bd
refactor(common): remove custom typedef WdioBrowser
jasonschroeder-sfdc Sep 20, 2022
30bb8df
refactor: checkA11yError and checkA11yErrorFunc
jasonschroeder-sfdc Sep 21, 2022
32b594a
refactor: checkA11yErrorWdio
jasonschroeder-sfdc Sep 22, 2022
b0a1df8
test: update all Jest snapshots
jasonschroeder-sfdc Sep 21, 2022
73844c2
chore(depcheck): make depcheck happy
jasonschroeder-sfdc Sep 21, 2022
347a3f8
test(jest): disable one test
jasonschroeder-sfdc Sep 22, 2022
99510cb
refactor(jest): async optimization
jasonschroeder-sfdc Sep 22, 2022
db80036
fix(test-integration): add @sally/common to devDependencies
jasonschroeder-sfdc Sep 22, 2022
11e694f
docs: update dependency graph
jasonschroeder-sfdc Sep 21, 2022
6d8ba8a
fix(eslint): eslint cannot see expect().toBeAccessible()
jasonschroeder-sfdc Sep 22, 2022
a792ed6
fix(eslint): fixing eslint complaints
jasonschroeder-sfdc Sep 22, 2022
2acea78
chore(deps): yarn.lock
jasonschroeder-sfdc Sep 22, 2022
0d15735
test(jest): disable a fake timer test
jasonschroeder-sfdc Sep 23, 2022
45d1b35
build(renovate): keep webdriverio and related packages up-to-date
jasonschroeder-sfdc Sep 23, 2022
a83e68a
build(circleci): prepare for matrix jobs
jasonschroeder-sfdc Jul 26, 2022
c5b5f21
build(circleci): add node 14, node 16 for CircleCI
jasonschroeder-sfdc Jul 27, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ orbs:
codecov: codecov/codecov@3.2.3
jobs:
build-and-test:
parameters:
node-version:
type: string
executor:
name: node/default
# TODO: switch back to 'lts'. Temp workaround for issues with lts v16.
# https://github.com/salesforce/sa11y/issues/82
tag: '14.18.1'
tag: << parameters.node-version >>
steps:
- browser-tools/install-chrome
- browser-tools/install-chromedriver
Expand All @@ -23,6 +26,11 @@ jobs:
path: ./reports/
- codecov/upload
workflows:
build-and-test:
matrix-tests:
jobs:
- build-and-test
- build-and-test:
matrix:
parameters:
node-version:
- '14.19.3'
- '16.16.0'
2 changes: 1 addition & 1 deletion docs/sa11y_dependency_graph.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 8 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
"url": "https://github.com/salesforce/sa11y/issues"
},
"homepage": "https://github.com/salesforce/sa11y",
"workspaces": [
"packages/*"
],
"workspaces": ["packages/*"],
"scripts": {
"build": "tsc --build && yarn workspace @sa11y/browser-lib build",
"build:ci": "yarn install --frozen-lockfile && yarn build",
Expand Down Expand Up @@ -64,11 +62,10 @@
"@types/node": "15.14.1",
"@typescript-eslint/eslint-plugin": "5.38.1",
"@typescript-eslint/parser": "5.38.1",
"@wdio/cli": "6.12.1",
"@wdio/local-runner": "6.10.5",
"@wdio/mocha-framework": "6.10.4",
"@wdio/spec-reporter": "6.11.0",
"@wdio/sync": "6.10.4",
"@wdio/cli": "7",
"@wdio/local-runner": "7",
"@wdio/jasmine-framework": "7",
"@wdio/spec-reporter": "7",
"babel-jest": "27.5.1",
"chromedriver": "105.0.1",
"commitizen": "4.2.5",
Expand Down Expand Up @@ -100,10 +97,10 @@
"ts-node": "10.9.1",
"typescript": "4.8.3",
"vertioner": "1.0.6",
"wdio-chromedriver-service": "6.0.4",
"webdriverio": "6.12.1"
"wdio-chromedriver-service": "7",
"webdriverio": "7"
},
"engines": {
"node": "^14"
"node": "^14 || ^16"
}
}
15 changes: 0 additions & 15 deletions packages/assert/__tests__/__snapshots__/assert.test.ts.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 40 additions & 6 deletions packages/assert/__tests__/assert.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ import {
a11yIssuesCount,
audioURL,
beforeEachSetup,
checkA11yError,
checkA11yErrorFunc,
domWithA11yIssues,
domWithNoA11yIssues,
shadowDomID,
videoURL,
} from '@sa11y/test-utils';
import { A11yConfig } from '@sa11y/common';
import { A11yConfig, axeRuntimeExceptionMsgPrefix } from '@sa11y/common';
import { expect } from '@jest/globals';

// Create a11y config with a map of rules with default priority and wcag sc from given
// list of rule ids
Expand All @@ -28,6 +27,35 @@ function getA11yConfigMap(rules: string[]): A11yConfig {
);
}

/**
* Check error thrown by calling given function.
* Preferable to using `checkA11yError` with `expect.assertions(..)` due to
* https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/no-conditional-expect.md
*/
async function checkA11yErrorFunc(
errorThrower: CallableFunction,
expectRuntimeError = false,
expectNoError = false
): Promise<void> {
expect.hasAssertions();
let err = new Error();
try {
await errorThrower();
} catch (e) {
err = e as Error;
} finally {
if (expectNoError) {
expect(err.message).toHaveLength(0);
} else if (expectRuntimeError) {
expect(err.message).toContain(axeRuntimeExceptionMsgPrefix);
} else {
expect(err).toBeTruthy();
expect(err.message).not.toContain(axeRuntimeExceptionMsgPrefix);
expect(err.message).toMatchSnapshot();
}
}
}

beforeEach(() => {
beforeEachSetup();
});
Expand All @@ -47,15 +75,21 @@ describe('assertAccessible API', () => {

it.each([
// DOM to test, expected assertions, expected a11y violations
[domWithNoA11yIssues, 1, 0],
[domWithA11yIssues, 4, a11yIssuesCount - 1],
[domWithNoA11yIssues, 2, 0],
[domWithA11yIssues, 2, a11yIssuesCount - 1],
])(
'should use default document, ruleset, formatter when called with no args - expecting %# assertion',
async (testDOM: string, expectedAssertions: number, expectedViolations: number) => {
document.body.innerHTML = testDOM;
expect.assertions(expectedAssertions);
await expect(getViolationsJSDOM()).resolves.toHaveLength(expectedViolations);
await assertAccessible().catch((e: Error) => checkA11yError(e));
if (expectedViolations > 0) {
// eslint-disable-next-line jest/no-conditional-expect
await expect(assertAccessible()).rejects.toThrow(`${expectedViolations} Accessibility issues found`);
} else {
// eslint-disable-next-line jest/no-conditional-expect
await expect(assertAccessible()).resolves.toBeUndefined();
}
}
);

Expand Down
1 change: 1 addition & 0 deletions packages/assert/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"axe-core": "4.3.3"
},
"devDependencies": {
"@jest/globals": "^27",
"@sa11y/test-utils": "3.1.0"
},
"publishConfig": {
Expand Down
63 changes: 29 additions & 34 deletions packages/browser-lib/__wdio__/browser-lib.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import * as fs from 'fs';
import * as fs from 'fs/promises';
import * as path from 'path';
import { namespace } from '../src';
import { axeVersion } from '@sa11y/common';
Expand Down Expand Up @@ -39,76 +39,71 @@ function isLoaded(objName: string): Promise<string | boolean> {
}, objName);
}

function loadMinJS(filePath = sa11yMinJS): void {
async function loadMinJS(filePath = sa11yMinJS): Promise<void> {
const sa11yMinJsPath = path.resolve(__dirname, filePath);
const sa11yMinJs = fs.readFileSync(sa11yMinJsPath).toString();
const sa11yMinJs = (await fs.readFile(sa11yMinJsPath)).toString();
if (sa11yMinJs.length <= 0) throw new Error('Unable to load min js ' + filePath);
void browser.execute(sa11yMinJs);
return browser.execute(sa11yMinJs);
}

/**
* Test util function to inject given file and verify that sa11y and axe are loaded into browser
*/
function verifySa11yLoaded(filePath: string): void {
void browser.reloadSession();
loadMinJS(filePath);
async function verifySa11yLoaded(filePath: string): Promise<void> {
await browser.reloadSession();
await loadMinJS(filePath);
// After injecting sa11y and axe should be defined
const packageJSON = JSON.parse(
fs.readFileSync(path.resolve(__dirname, '../package.json')).toString()
(await fs.readFile(path.resolve(__dirname, '../package.json'))).toString()
) as ObjectWithVersion;
expect(isLoaded(namespace)).toEqual(packageJSON.version);
expect(isLoaded('axe')).toEqual(axeVersion);
await expectAsync(isLoaded(namespace)).toBeResolvedTo(packageJSON.version);
await expectAsync(isLoaded('axe')).toBeResolvedTo(axeVersion);
}

function checkNumViolations(
async function checkNumViolations(
scope = '',
exceptionList = {},
expectedNumViolations = a11yIssuesCount,
script = ''
): void {
): Promise<void> {
const getViolationsScript =
script ||
`return JSON.parse((await sa11y.checkAccessibility(
'${scope}',
sa11y.base,
${JSON.stringify(exceptionList)}))).length;`;
void browser.url(htmlFileWithNoA11yIssues);
loadMinJS();
expect(browser.execute(getViolationsScript)).toBe(0);
await browser.url(htmlFileWithNoA11yIssues);
await loadMinJS();
await expectAsync(browser.execute(getViolationsScript)).toBeResolvedTo(0);

void browser.url(htmlFileWithA11yIssues);
loadMinJS();
expect(browser.execute(getViolationsScript)).toBe(expectedNumViolations);
await browser.url(htmlFileWithA11yIssues);
await loadMinJS();
await expectAsync(browser.execute(getViolationsScript)).toBeResolvedTo(expectedNumViolations);
}

describe('@sa11y/browser-lib', () => {
it('should not have axe or sa11y loaded to start with', () => {
expect(isLoaded(namespace)).toBe(false);
expect(isLoaded('axe')).toBe(false);
it('should not have axe or sa11y loaded to start with', async () => {
await expectAsync(isLoaded(namespace)).toBeResolvedTo(false);
await expectAsync(isLoaded('axe')).toBeResolvedTo(false);
});

it('should inject minified js', () => verifySa11yLoaded(sa11yMinJS));

it('should inject un-minified js', () => {
verifySa11yLoaded(sa11yJS);
});
it('should inject un-minified js', () => verifySa11yLoaded(sa11yJS));

it('should invoke functions on axe e.g. getRules', () => {
loadMinJS();
expect(browser.execute('return axe.getRules().length')).toEqual(full.runOnly.values.length);
it('should invoke functions on axe e.g. getRules', async () => {
await loadMinJS();
return expectAsync(browser.execute('return axe.getRules().length')).toBeResolvedTo(full.runOnly.values.length);
});

it('should run a11y checks using axe', () => {
checkNumViolations('', {}, a11yIssuesCount, 'return (await axe.run()).violations.length;');
return checkNumViolations('', {}, a11yIssuesCount, 'return (await axe.run()).violations.length;');
});

it('should run a11y checks using sa11y', () => {
checkNumViolations();
});
it('should run a11y checks using sa11y', () => checkNumViolations());

it('should filter a11y violations using sa11y', () => {
checkNumViolations('', exceptionList, a11yIssuesCountFiltered);
});
it('should filter a11y violations using sa11y', () =>
checkNumViolations('', exceptionList, a11yIssuesCountFiltered));

it('should analyze only specified scope using sa11y', () => checkNumViolations('div', {}, 1));
});
2 changes: 1 addition & 1 deletion packages/browser-lib/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"compilerOptions": {
"rootDir": "src",
"outDir": "dist",
"types": ["webdriverio", "jest"],
"types": ["webdriverio/async", "jest"],
"noEmitOnError": false,
"declaration": false,
"declarationMap": false,
Expand Down
2 changes: 2 additions & 0 deletions packages/common/.depcheckrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Ignore webdriverio - we need the types for `WebdriverIO.Browser`
ignores: ['webdriverio']
2 changes: 1 addition & 1 deletion packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"axe-core": "4.3.3"
},
"devDependencies": {
"webdriverio": "6.12.1"
"webdriverio": "7"
},
"publishConfig": {
"access": "public"
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
*/

export { A11yConfig, AxeResults, axeRuntimeExceptionMsgPrefix, axeVersion, getAxeRules, getViolations } from './axe';
export { WdioAssertFunction, WdioOptions, WdioBrowser } from './wdio';
export { WdioAssertFunction, WdioOptions } from './wdio';
export { errMsgHeader, ExceptionList } from './format';
export { log } from './helpers';
16 changes: 5 additions & 11 deletions packages/common/src/wdio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,21 @@
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { BrowserObject, MultiRemoteBrowserObject, Element } from 'webdriverio';
import { A11yConfig } from './axe';
import { ExceptionList } from './format';

// TODO (refactor): The base common pkg depending on wdio feels strange.
// Refactor it out into another package, even a new one (e.g. test-utils-wdio) to
// avoid circular dep.
export type WdioBrowser = BrowserObject | MultiRemoteBrowserObject;

/**
* Optional arguments passed to WDIO APIs
* @param driver - WDIO {@link BrowserObject} instance navigated to the page to be checked. Created automatically by WDIO test runner. Might need to be passed in explicitly when other test runners are used.
* @param driver - WDIO {@link WebdriverIO.Browser} instance navigated to the page to be checked. Created automatically by WDIO test runner. Might need to be passed in explicitly when other test runners are used.
* @param scope - Element to check for accessibility found using [`browser.$(selector)`](https://webdriver.io/docs/selectors), defaults to the entire document.
* @param rules - {@link A11yConfig} to be used for checking accessibility. Defaults to {@link base}
* @param exceptionList - map of rule id to corresponding CSS targets that needs to be filtered from results
*/
export interface WdioOptions {
driver: WdioBrowser;
scope?: Promise<Element> | Element;
export type WdioOptions = {
driver: WebdriverIO.Browser;
scope?: Promise<WebdriverIO.Element> | WebdriverIO.Element;
rules?: A11yConfig;
exceptionList?: ExceptionList;
}
};

export type WdioAssertFunction = (opts: Partial<WdioOptions>) => void | Promise<void>;
4 changes: 3 additions & 1 deletion packages/common/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
"extends": "../../tsconfig.common.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
"outDir": "dist",
"types": ["node", "webdriverio/async"]

},
"include": ["src"],
// "@sa11y/common" is the base package and should not depend on any
Expand Down
1 change: 1 addition & 0 deletions packages/format/__tests__/filter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { exceptionListFilter } from '../src';
import { AxeResults } from '@sa11y/common';
import { getViolations } from './format.test';
import { expect } from '@jest/globals';

let violations: AxeResults = [];
beforeAll(async () => {
Expand Down
1 change: 1 addition & 0 deletions packages/format/__tests__/format.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as axe from 'axe-core';
import { beforeEachSetup, domWithA11yIssues, domWithNoA11yIssues } from '@sa11y/test-utils';
import { AxeResults } from '@sa11y/common';
import { A11yError } from '../src';
import { expect } from '@jest/globals';

// TODO (refactor): Move to common test-utils
// - without creating circular dep due to "A11yError"
Expand Down
1 change: 1 addition & 0 deletions packages/format/__tests__/result.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { A11yResult, A11yResults } from '../src';
import { getViolations } from './format.test';
import { AxeResults } from '@sa11y/common';
import { NodeResult, Result } from 'axe-core';
import { expect } from '@jest/globals';

const a11yIssues = [
{ impact: undefined },
Expand Down
Loading