Add ability to register a11y matcher in jest config once per project
mohanraj-r opened this issue · 5 comments
Motivation
The a11y matcher API has to be registered before its used. Currently this needs to be done in each test module as part of test setup as shown below.
import { registerA11yMatchers } from '@sa11y/jest';
beforeAll(() => {
registerA11yMatchers();
});
describe('integration test @sa11y/jest', () => {
it('should have a11y matchers working', () => {
expect(expect.toBeAccessible).toBeDefined();
expect(document).toBeAccessible();
});
});
This could be made less tedious by registering the a11y matchers once in the jest config of the consuming project and then all the tests in the project can use the a11y API without any additional setup.
For example a consuming project should be able to register a11y matchers by extending the config as below in the jest.config.js
at the project root:
const { jestConfig } = require('@sa11y/jest');
module.exports = {
...jestConfig,
// Rest of the Project's Jest config ..
};
Resources
Similar setup can be found in
I am running into errors related to modules primarily because I think jest uses the CJS module system whereas the rest of the sa11y packages are using the ES modules. Not sure if it would help if I split the integration tests from the mono-repo into its own project.
In the integration tests package:
Baseline
- Using the
toBeAccessible()
API after explicitly invoking theregisterA11yMatchers()
in the test module works as illustrated in this issue above.
extending jest.config.js
directly with setup from sa11y
- When I create a
jest.config.js
with
const { jestConfig } = require('@sa11y/jest');
module.exports = {
...jestConfig,
}
I run into the following error: SyntaxError: Unexpected token 'export'
$ /Users/mrajamanickam/src/sa11y/foundation/node_modules/.bin/jest --no-cache
/Users/mrajamanickam/src/sa11y/foundation/packages/jest/dist/index.js:8
export { toBeAccessible } from './matcher';
^^^^^^
SyntaxError: Unexpected token 'export'
The error means that jest is making use of the extended config, but is not able to understand the ES module syntax.
extending with local setup file
- When I use
setupFilesAfterEnv
injest.config.js
instead
module.exports = {
setupFilesAfterEnv: ['./jestSetup.js'],
}
with a local file jestSetup.js
:
const { registerA11yMatchers } = require('@sa11y/jest');
registerA11yMatchers();
I get no errors when running jest - but the integration test fails because the toBeAccessible
is not defined which probably means that the setup is not working. Also tried with
setupFilesAfterEnv: [require('./jestSetup.js')],
setupFilesAfterEnv: [require('<rootDir>/jestSetup.js')],
● integration test @sa11y/jest › should have a11y matchers working with setup in jest.config.js
expect(received).toBeDefined()
Received: undefined
12 | // registerA11yMatchers();
13 | it('should have a11y matchers working with setup in jest.config.js', () => {
> 14 | expect(expect.toBeAccessible).toBeDefined();
| ^
15 | // TODO(Fix) : Fails with TypeError: expect(...).toBeAccessible is not a function
16 | expect(document).toBeAccessible();
17 | });
Tried out many suggestions from
- Unexpected Token Import for ES6 modules · Issue #2081 · facebook/jest · GitHub
- Dynamic import not working if using .babelrc · Issue #2442 · facebook/jest · GitHub
- babel-jest does not transpile import/export in node_modules when Babel 7 is used · Issue #6229 · facebook/jest · GitHub
including
- adding babel plugins to
babel.config.js
- didn't help
env: {
test: {
plugins: ['transform-es2015-modules-commonjs', 'dynamic-import-node', 'babel-plugin-transform-dynamic-import'],
},
},
- adding
"type": "module"
to the @sa11y/jest package.json- got
Error: Jest: Your version of Node does not support dynamic import - please enable it or use a .cjs file extension
- got
@trevor-bliss If you have any suggestions please let me know.
Ok I pulled your branch and tried it out. I got it working after making a couple changes.
- Update dist files to be commonjs format
You were on to something when you mentioned the module format. You don't have to update any of your authored source code, but in the root level tsconfig.common.js
file, you can change the module
entry to commonjs
so the dist files you produce are in a more compatible format.
- Fix
packages/jest/package.json
The main
and types
entries are wrong here. Should point to dist/index.js
instead of dist/jest.js
.
- Simplify the Jest setup
This one is broader and more my opinion than a "bug". I think having @sally/jest
export a jest config object is doing too much. Instead, it should export the registerA11yMatchers
function and the consuming projects can call that function themselves in their Jest setup. sfdx-lwc-jest
provides the full config because it's a full test runner. This is more of a "matchers" library being integrated into an existing Jest setup.
So what I would do is remove the registerA11yMatchers()
invocation in setup.ts
and update test-integ/jest.config.js
to:
module.exports = {
setupFilesAfterEnv: ['<rootDir>/jest-setup.js'],
};
where jest-setup.js
is:
const { registerA11yMatchers } = require('@sa11y/jest');
registerA11yMatchers();
I think this is a reasonable thing for consuming projects to do so appropriate for this integration test package.
Finally, if you run the Jest tests from the top level this will still fail because that will use the root level jest config instead of the integration test package config. I'd either create a separate npm script for running tests in this package, or have each sub package extend a base config and then have this package also have the setupFilesAfterEnv
entry to register the matchers.
That is awesome 🎉. Thanks a lot @trevor-bliss
- Updating the common tsconfig to commonjs fixed the issue 🥳
- I had fixed the incorrect
main
entry inpackage.json
in 85609d3 but forgot to push 🤦. Sorry about that. - I get what you are saying and guess am ok with it for now. Cleaned up code as per your suggestions. But sometime in the future would like to offer a simplified 1 step setup process rather than the 2 step process if thats something most consumers of the API would want and could benefit from. But if most of them already have a jest setup and jest config and have no issues with the 2 step process, we could leave it as is.
- Got the integrations tests with a different jest config to run from project root with the help of some config in the root jest config.
Thanks a lot for this!
Fixed by #9
If you came here because you had this error, be aware that the Api has changed from registerA11yMatchers
to setup
while initializing these custom matchers
https://www.npmjs.com/package/@sa11y/jest
const { setup } = require('@sa11y/jest'); // CommonJS
import { setup } from '@sa11y/jest'; // ES6
// Register the sa11y matcher
setup();