Skip to content

Commit

Permalink
feat!: improve automatic checks coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
navateja-alagam committed Oct 25, 2023
1 parent b40931f commit ffd9d71
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 30 deletions.
5 changes: 0 additions & 5 deletions packages/jest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ Accessibility matcher for [Jest](https://jestjs.io)
- [JSON result transformation](#json-result-transformation)
- [Limitations](#limitations)
- [Disabled Checks](#disabled-checks)
- [Jest toMatchSnapshot() API Wrapper](#jest-tomatchsnapshot-api-wrapper)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Expand Down Expand Up @@ -279,7 +278,3 @@ Automatic checks currently has the following limitations.
### Disabled Checks

- @sa11y/jest automatic checks also disabled rules which were disabled in `toBeAccessible` Jest API ([disabled-checks](https://github.com/salesforce/sa11y/tree/master/packages/jest#disabled-checks))

### Jest toMatchSnapshot() API Wrapper

- When Snapshot testing is done, jest's `toMatchSnapshot()` API is altering the document.body element attributes as needed to generate snapshots thereby the a11y checks which happen later on `document.body` isn't running on actual elements. To solve this, a wrapper has been introduced to restore the document.body DOM before jest's `toMatchSnapshot` is invoked and use the restored version of document.body for a11y checks.
1 change: 0 additions & 1 deletion packages/jest/__tests__/setup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ describe('jest setup', () => {
registerSa11yMatcher();
it('should define matcher on expect object', () => {
expect(expect['toBeAccessible']).toBeDefined();
expect(expect['toMatchSnapshot']).toBeDefined();
});

it.each([extended, base])('should customize %s preset-rule as expected', (config) => {
Expand Down
4 changes: 1 addition & 3 deletions packages/jest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@
"devDependencies": {
"@jest/globals": "28.1.3",
"@sa11y/common": "5.1.0",
"@sa11y/test-utils": "5.1.0",
"expect": "28.1.3",
"jest-snapshot": "28.1.3"
"@sa11y/test-utils": "5.1.0"
},
"publishConfig": {
"access": "public"
Expand Down
8 changes: 7 additions & 1 deletion packages/jest/src/automatic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export const setOriginalDocumentBodyHtml = (bodyHtml: string | null) => {
originalDocumentBodyHtml = bodyHtml ?? null;
};

export const getOriginalDocumentBodyHtml = () => {
return originalDocumentBodyHtml;
};

/**
* Check if current test file needs to be skipped based on any provided filter
*/
Expand Down Expand Up @@ -107,6 +111,8 @@ export function registerSa11yAutomaticChecks(opts: AutoCheckOpts = defaultAutoCh
if (opts.runAfterEach) {
// TODO (fix): Make registration idempotent
log('Registering sa11y checks to be run automatically after each test');
afterEach(async () => await automaticCheck(opts));
afterEach(async () => {
await automaticCheck(opts);

Check warning on line 115 in packages/jest/src/automatic.ts

View check run for this annotation

Codecov / codecov/patch

packages/jest/src/automatic.ts#L115

Added line #L115 was not covered by tests
});
}
}
43 changes: 25 additions & 18 deletions packages/jest/src/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@

import { toBeAccessible } from './matcher';
import { A11yConfig } from '@sa11y/common';
import { AutoCheckOpts, registerSa11yAutomaticChecks, setOriginalDocumentBodyHtml } from './automatic';
import {
AutoCheckOpts,
registerSa11yAutomaticChecks,
getOriginalDocumentBodyHtml,
setOriginalDocumentBodyHtml,
} from './automatic';
import { expect } from '@jest/globals';
import { toMatchSnapshot, SnapshotState } from 'jest-snapshot';
import type { MatcherFunctionWithState, MatcherState } from 'expect';

interface Context extends MatcherState {
snapshotState: SnapshotState;
}

export const disabledRules = [
// Descendancy checks that would fail at unit/component level, but pass at page level
Expand All @@ -35,15 +34,6 @@ export const disabledRules = [
'video-caption',
];

function wrapperSnapshotMatcher(originalMatcher: MatcherFunctionWithState<Context>) {
return function (...args: Context[]) {
setOriginalDocumentBodyHtml(document?.body?.innerHTML ?? '');
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return originalMatcher.call(expect.getState(), ...args);
};
}

/**
* Options to be passed on to {@link setup}
*/
Expand All @@ -66,11 +56,29 @@ const defaultSa11yOpts: Sa11yOpts = {
},
};

function registerRemoveChild() {
// eslint-disable-next-line @typescript-eslint/unbound-method
const originalRemoveChild = Element.prototype.removeChild;

Check warning on line 61 in packages/jest/src/setup.ts

View check run for this annotation

Codecov / codecov/patch

packages/jest/src/setup.ts#L61

Added line #L61 was not covered by tests

// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
(Element.prototype as any).removeChild = function (oldChild: Node): Node {

Check warning on line 64 in packages/jest/src/setup.ts

View check run for this annotation

Codecov / codecov/patch

packages/jest/src/setup.ts#L64

Added line #L64 was not covered by tests
if (oldChild.parentNode === this) {
// Your custom implementation here
if (!getOriginalDocumentBodyHtml()) {
setOriginalDocumentBodyHtml(document?.body?.innerHTML ?? '');
}
}

return originalRemoveChild.call(this, oldChild);
};
}

/**
* Register Sa11y Jest API and automatic checks depending on {@link Sa11yOpts}
* @param opts - {@link Sa11yOpts} to opt-in to automatic checks
*/
export function setup(opts: Sa11yOpts = defaultSa11yOpts): void {
registerRemoveChild();
registerSa11yMatcher();
// Set defaults from env vars
const autoCheckOpts = opts.autoCheckOpts;
Expand All @@ -87,9 +95,8 @@ export function setup(opts: Sa11yOpts = defaultSa11yOpts): void {
* Register accessibility helpers toBeAccessible as jest matchers
*/
export function registerSa11yMatcher(): void {
const wrapper = wrapperSnapshotMatcher(toMatchSnapshot);
if (expect !== undefined) {
expect.extend({ toBeAccessible, toMatchSnapshot: wrapper });
expect.extend({ toBeAccessible });
} else {
throw new Error(
"Unable to find Jest's expect function." +
Expand Down
4 changes: 2 additions & 2 deletions yarn.lock

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

0 comments on commit ffd9d71

Please sign in to comment.