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

Resolved path for axe-core/axe.min.js is incorrect if the Cypress Config is in a sub-directory when using Cypress v10+ #134

Open
aturingmachine opened this issue Jun 17, 2022 · 17 comments

Comments

@aturingmachine
Copy link

axe-core/axe.min.js cannot be loaded if the Cypress config is contained in a sub directory. The resolved path traverses from the location of the config, but starts at the project root where the command was invoked.

This seems to be due to require.resolve returning the path relative to the configuration file, whereas when running in Cypress Versions <10 require.resolve returns the path relative to the directory the initial command was invoked.

So assuming a project with a directory structure of:

/home/user/dev/project/
- e2e/
  - config/
    - cypress.config.ts
- src/
- node_modules/
- package.json

The path we attempt to require for axe-core/axe.min.js will be /home/user/dev/node_modules/axe-core/axe.min.js.

A minimum reproduction can be found using my fork of this repo.

image

@ldeveber
Copy link

We are also experiencing this issue

@jonkoops
Copy link

This might be a duplicate of #84 and #73 if a preprocessor is configured.

@ldeveber
Copy link

ldeveber commented Jul 26, 2022

Fun fact: it only throws this error with cypress run for us. When using cypress open it seems to work fine, but we can't use that on the build servers :(

This is using the same config file for both commands.

@christianmartinnies
Copy link

Facing the same issue, both when cypress runand cypress open.

Environment:
node 16.16.0
yarn 3.2.2

devDependencies:

"axe-core": "^4.4.3",
"cypress": "^10.5.0",
"cypress-axe": "^1.0.0"

@ldeveber
Copy link

still does not work with cypress 10.6

@rdylanwalker
Copy link

We are experiencing this issue on Cypress 10.3. We have a cypress.config.ts in project root. In <projectRoot>/cypress/configurations we have several custom configurations that extend the main configuration (via import). We override with the Cypress --config-file command line. When running tests with cypress-axe we experience the same error as above.

@ghost
Copy link

ghost commented Sep 16, 2022

I'm experiencing this as well, see CI logs here: https://github.com/ismay/portfolio/actions/runs/3067878096/jobs/4954656842#step:3:266

Looking at the resolved path, it seems like that path is correct relative to my config file (which is in ./.cypress): cy.readFile("../node_modules/axe-core/axe.min.js").

However, judging from the error it seems like cy.readFile("../node_modules/axe-core/axe.min.js") is resolving from the root of the project. So it ends up looking one level too high. It tries to find the file at /home/runner/work/portfolio/node_modules/axe-core/axe.min.js, but it should be looking for /home/runner/work/portfolio/portfolio/node_modules/axe-core/axe.min.js

The cypress docs mention that readFile resolves relative to the config file: https://docs.cypress.io/api/commands/readfile#Arguments, at least that's how I read it: A path to a file within the project root (the directory that contains the Cypress configuration file).. But that seems to be incorrect.

Judging from this issue the base path is actually hardcoded to the project root: cypress-io/cypress#2673 (see the related issues as well). So if that's correct, to fix this I think we have to make sure that we're resolving from the root of the project here: https://github.com/component-driven/cypress-axe/blob/master/src/index.ts#L26. See the docs here: https://nodejs.org/api/modules.html#requireresolverequest-options. Maybe https://github.com/sindresorhus/pkg-dir would be useful to resolve this.

@artvichi
Copy link

artvichi commented Nov 10, 2022

Here is a patch you can use to fix it with the patch-package
Updated just this file node_modules/cypress-axe/dist/index.js

 exports.injectAxe = function () {
-    var fileName = typeof (require === null || require === void 0 ? void 0 : require.resolve) === 'function'
-        ? require.resolve('axe-core/axe.min.js')
-        : 'node_modules/axe-core/axe.min.js';
+    var fileName = 'node_modules/axe-core/axe.min.js';
+
     cy.readFile(fileName).then(function (source) {
         return cy.window({ log: false }).then(function (window) {
             window.eval(source);

@ghost
Copy link

ghost commented Nov 11, 2022

If that fixes it for you it would be good to submit your patch as a PR.

@Szymon-dziewonski
Copy link

Szymon-dziewonski commented Nov 17, 2022

@artvichi this won't work for workspaces when axe-core i installed as dependency of cypress-axe in workspace root, thats how its working on yarn.3

When install using workspace scoping packages:

- project `a` node_modules (here's always will be installed axe-core)
--- workspace `one` node_modules (cypress-axe when install with `yarn workspace @a/one add -D cypress-axe)

if install normally cd workspace; yarn add -D cypress-axe then package will be installed on root node_modules either way resolve of axe-core fail in

exports.injectAxe = function () {
    var fileName = typeof (require === null || require === void 0 ? void 0 : require.resolve) === 'function'
        ? require.resolve('axe-core/axe.min.js')
        : 'node_modules/axe-core/axe.min.js';
    cy.readFile(fileName).then(function (source) {
        return cy.window({ log: false }).then(function (window) {
            window.eval(source);
        });
    });
};

Problem only occurs on vite because webpack resolves properly with require.resolve even if package is installed in different node_modules

EDIT: plugin should be compiled to commonjs AND esm, also should use cypress task to read/reasolve package via createRequire so vite would be able to resolve package same way as webpack.

@AriPerkkio
Copy link

AriPerkkio commented Dec 2, 2022

This seems to be due to require.resolve returning the path relative to the configuration file, whereas when running in Cypress Versions <10 require.resolve returns the path relative to the directory the initial command was invoked.

This all sounds exactly as the upstream issue: cypress-io/cypress#22689.
It makes no sense that all plugins in the ecosystem start patching themselves due to a bug in Cypress. Code coverage plugin is also seeing this: cypress-io/code-coverage#586.

Work-around for now: cypress-io/cypress#22689 (comment)

@dkryaklin
Copy link
Contributor

This PR address this issue as well #150

@pdimova

This comment was marked as spam.

@9j0hn50n
Copy link

Hi,

I'm still seeing issues with this after upgrading cypress-axe version to 1.3.0 and axe-core to 4.6.3.

This is what I see in terminal when running my tests:

AssertionError: Timed out retrying after 2500ms: `cy.readFile("../../../../node_modules/axe-core/axe.min.js")` failed because the file does not exist at the following path:

`/node_modules/axe-core/axe.min.js`

https://on.cypress.io/readfile
      at ../../../node_modules/cypress-axe/dist/index.js.exports.injectAxe (webpack:////Users/blah/blah/blah/node_modules/cypress-axe/dist/index.js:20:0)

The file does exist in /node_modules/axe-core/axe.min.js

I've made the following change in my custom Cypress function that tests a11y (as indicated here):

Cypress.Commands.add('checkAccessibility', () => {
  const terminalLog = (violations) => {
    cy.task(
      'log',
      `${violations.length} accessibility violation${violations.length === 1 ? '' : 's'
      } ${violations.length === 1 ? 'was' : 'were'} detected`,
    );
    const violationData = violations.map(
      ({
        id, impact, description, nodes,
      }) => ({
        id,
        impact,
        description,
        nodes: nodes.length,
      }),
    );
    cy.task('table', violationData);
  };
  cy.injectAxe({ axeCorePath: '../../../../node_modules/axe-core/axe.min.js'})
    .checkA11y(null, null, terminalLog, true, {
      runOnly: {
        values: ['wcag2aa'],
      },
    });
});

My config files are nested as follows:

my-app/
├─ node_modules/
├─ tests/
│  ├─ e2e/
│  │  ├─ configs/
│  │  │  ├─ common.config.js
│  │  │  ├─ ui.config.js
│  │  │  ├─ visual.config.js
│  │  ├─ tests/
│  │  │  ├─ ui/
│  │  │  ├─ visual/
├─ .gitignore
├─ package.json
├─ README.md

Can someone please advise?

Many thanks!

@dkryaklin
Copy link
Contributor

dkryaklin commented Feb 20, 2023

@9j0hn50n Hi,

Not sure why you are using ../../../../node_modules/axe-core/axe.min.js path. I would suggest trying

../../../node_modules/axe-core/axe.min.js
or
./node_modules/axe-core/axe.min.js

@9j0hn50n
Copy link

Lovely, thank you @dkryaklin!

I had tried ../../../node_modules/axe-core/axe.min.js but still got the mentioned error.

But ./node_modules/axe-core/axe.min.js did the trick.

Thanks again.

@AshMcConnell
Copy link

AshMcConnell commented Jan 30, 2024

I have a similar, but slightly bizarre issue. When I try to injectAxe in an afterEach it works fine, however if the beforeEach or test fails it can't fine the file axe-core/axe.min.js. Does anyone know why that would be? Here is my checkAxe custom command: -

Cypress.Commands.add('checkAxe', (wait?: number) => {
    if (wait) {
        cy.wait(wait);
    }
    cy.injectAxe();
    cy.configureAxe({
        rules: exceptions.map(rule => ({id: rule, enabled: false})),
        standards: accessibilityStandards
    });

    cy.window({log: false})
        .then((win: any) => {

            const context = {
                include: [win.document],
                exclude: exclusions,
            };

            const rules = exceptions.reduce((result, exception) => {
                result[exception] = {enabled: false};
                return result;
            }, {});

            return cy.checkA11y(context, <any>{runOnly: accessibilityStandards, rules});
        });
});

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests