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

Cypress and Yarn 2 PNP support #8008

Closed
kirill-konshin opened this issue Jul 16, 2020 · 29 comments · Fixed by #17335
Closed

Cypress and Yarn 2 PNP support #8008

kirill-konshin opened this issue Jul 16, 2020 · 29 comments · Fixed by #17335
Assignees
Labels
package manager: yarn Issues relating to yarn

Comments

@kirill-konshin
Copy link

kirill-konshin commented Jul 16, 2020

Current behavior:

In Yarn 2 monorepo I have a package a and tests in package b.

When I do

// b/cypress/plugins/index
module.exports = require('a/src/cypress/plugins');

It works as expected.

But

// a/cypress/commands/index
require('a/src/cypress/commands');

Fails with error:

Oops...we found an error preparing this test file:

  /Users/xxx/b/cypress/support/index.js

The error was:

Error: Cannot find module 'a/src/cypress/support' from '/Users/xxx/b/cypress/support'

Looks like Yarn's Plug'n'play file .pnp.js is not present in second (commands) context.

Desired behavior:

Require of monorepo packages should work.

@jennifer-shehane jennifer-shehane added the package manager: yarn Issues relating to yarn label Jul 17, 2020
@cypress-bot cypress-bot bot added the stage: needs investigating Someone from Cypress needs to look at this label Jul 17, 2020
@kirill-konshin
Copy link
Author

@bahmutov @jennifer-shehane please take a look at this issue, this is a huge blocker since there's no known workaround... Yarn 2.1.1 has been recently released, which means it's time to support it. Is there anything I can help?

@arcanis I was trying to find a way to import .pnp.js to enable proper resolution mechanics, but it did not help. Also I've tried https://yarnpkg.com/advanced/pnpify but seems that Cypress is launching some other context (for the browser?) which is not connected to main one, which is aware of PNP.

@bahmutov
Copy link
Contributor

@kirill-konshin you can open a PR with at least some work showing what is going on in CLI when Yarn v2 is used to install Cypress

@kirill-konshin
Copy link
Author

@bahmutov here you go https://github.com/kirill-konshin/cypress-test-tiny-yarn-pnp/pull/1/files (branch bug), monorepo is actually not needed, since none of PNP resolutions work.

Just run

$ yarn install
$ yarn test

And get an error:

Error: Cannot find module 'cypress-plugin-snapshots/commands' from '/Users/xxx/cypress-test-tiny-yarn-pnp/cypress/support'

@kirill-konshin
Copy link
Author

@bahmutov Any updates? We're completely blocked for almost a month, are there any workarounds or hacks?

@bahmutov
Copy link
Contributor

We did not work on this issue, since it has low priority overall. If you know how to make Cypress NPM module play nicely with Yarn 2, you can open a PR into Cypress with the fix.

PS: The error above seems to indicate a problem not with the Cypress itself, but with another plugin, no?

@kirill-konshin
Copy link
Author

kirill-konshin commented Aug 13, 2020

@bahmutov I wish I could make a PR, but I am not familiar with Cypress codebase at all.

I know that Yarn 2 is shipped with a set of tools https://next.yarnpkg.com/advanced/pnpapi and https://next.yarnpkg.com/advanced/pnpify that can be used to resolve packages. Superficially it looks like Cypress is creating a new Node (or Browser) context, which is not aware of PNP resolution (unlike the main process).

The error above is a Cypress problem because it would happen with ANY plugin, since it is related to resolution algorithm in general.

Given that this issue has ben linked from another issue, there is some traction, and Yarn 2 is already public, so please consider raising the priority.

@kirill-konshin
Copy link
Author

@bahmutov any updates?

@bahmutov
Copy link
Contributor

bahmutov commented Sep 1, 2020 via email

@kirill-konshin
Copy link
Author

@bahmutov is there anything else that I can do to speed it up? Do you have any ETA?

@bahmutov
Copy link
Contributor

bahmutov commented Sep 1, 2020 via email

@kirill-konshin
Copy link
Author

Like I said before, I’m not familiar with Cypress architecture and this bug seems to be buried quite deep, in the code where cypress resolves dependencies. Pnp has to be injected there, or their resolution has to be used. If you can point out the direction or provide a fix - it would be much better.

@bahmutov
Copy link
Contributor

bahmutov commented Sep 1, 2020 via email

@kirill-konshin
Copy link
Author

It is definitely not part of CLI, it is the part that involves browser, because it all works in CLI. Please take a closer look at bug description: it works for plugins and does not work for commands.

mateus-f-torres added a commit to mateus-f-torres/barefoot that referenced this issue Sep 19, 2020
@marcneander
Copy link

Adding the pnp-webpack-plugin is needed until cypress is using webpack 5.

const webpackPreprocessor = require('@cypress/webpack-preprocessor');
const PnpWebpackPlugin = require('pnp-webpack-plugin');

module.exports = (on) => {
    const options = {
        webpackOptions: {
            resolve: {
                plugins: [
                    PnpWebpackPlugin
                ]
            },
            resolveLoader: {
                plugins: [
                    PnpWebpackPlugin.moduleLoader(module)
                ]
            }
        },
        watchOptions: {}
    };

    on('file:preprocessor', webpackPreprocessor(options));
};

@kirill-konshin
Copy link
Author

@marcneander it did work, thanks a lot! Totally makes sense why.

@masihjahangiri
Copy link

Cypress should support built-in yarn 2 (PNP algorithm) and it's really important.
We use yarn 2 for the zero-install feature to improve our CI build time, and If we use nodeLinker, we miss that feature.

@benwainwright
Copy link

+1 for this please. I'm currently completely unable to write my integration tests or any code related to it in TypeScript in my otherwise entirely TypeScript based yarn2/pnp project.

@kleingtm
Copy link

kleingtm commented Feb 15, 2021

The pnp-webpack-plugin did not work for me, however...

I had luck in a TypeScript + Cypress project doing the following in the Cypress plugins/index.js file:

const deepmerge = require("deepmerge");
const path = require("path");

module.exports = (on, config) => {

        // deep-merge config with the actual reporter 
        config =  deepmerge(config, {
            reporter: require(
                require(path.join(config.projectRoot, ".pnp.js")).resolveToUnqualified("cypress-multi-reporters", __filename)
            ),
            reporterOptions: {
                ... // put reporter options here
            }
        })
        ... // other plugin config
      

The key being yarn pnp API's resolveToUnqualified function which will spit out the pnp-ed module location.
https://next.yarnpkg.com/advanced/pnpapi#resolvetounqualified

@jennifer-shehane jennifer-shehane changed the title Cypress and Yarn 2 PNP in a monorepo Cypress and Yarn 2 PNP support Feb 26, 2021
@johnwiseheart
Copy link

johnwiseheart commented Feb 26, 2021

As per #15241, this is also broken for resolving typescript cypress config:

plugins/index.ts:

/// <reference types="cypress" />

const config: Cypress.PluginConfig = (on, config) => {
  // plugin config
};

export default config;

Fails with various errors due to it being run without transpilation.

This is not in a monorepo configuration.

@ysozer
Copy link

ysozer commented Mar 1, 2021

Has anyone succeeded with using PnpWebpackPlugin? I am also blocked with yarn 2 implementation

@missing1984
Copy link
Contributor

Webpack 5 has built in pnp support. does Cypress have plan to switch default webpack preprocessor to webpack 5?

@cypress-bot cypress-bot bot added stage: work in progress and removed stage: needs investigating Someone from Cypress needs to look at this labels Mar 22, 2021
@AaronBuxbaum
Copy link

Is there any movement on this PR? It's pretty annoying that this is the only package that forces us to use nodeLinker: node-modules

@jennifer-shehane
Copy link
Member

@AaronBuxbaum You can track the currently opened PR here: #15623 Although this PR will not address all of the issues preventing Cypress from fully working with Yarn 2.

@jpulec
Copy link

jpulec commented May 13, 2021

If anyone else comes across this, managed to get this to work by just making sure that the PnP plugin gets added to the webpack config that Cypress uses. This works with cypress@7.3.0 using PnP with yarn workspaces. The following just needs to get added to you cypress/plugins/index.js.

module.exports = (on) => {
    // You need to use your PnP file to resolve files. The following is just the path that traverses up to where my PnP file is in our repo root.
    const pnp = require('../../../../.pnp.js');
    // I couldn't find this documented, but this appears to monkey-patch require and do all the other necessary things to get PnP working
    pnp.setup();

    // This is where we'll be resolving packages from. In this case, it is a workspace package we have named, but using a relative path here should work as well to resolve from a specific folder.
    const targetModule = '@mypackages/package';

    // We need to patch the webpack config that cypress uses (which is v4 which needs a plugin for PnP support)
    const webpackPreprocessor = require(pnp.resolveToUnqualified('@cypress/webpack-preprocessor', targetModule));
    const PnpWebpackPlugin = require(pnp.resolveToUnqualified('pnp-webpack-plugin', targetModule));

    const options = {
        webpackOptions: {
            resolve: {
                plugins: [
                    PnpWebpackPlugin
                ]
            },
            resolveLoader: {
                plugins: [
                    PnpWebpackPlugin.moduleLoader(module)
                ]
            }
        },
        watchOptions: {}
    };

    on('file:preprocessor', webpackPreprocessor(options));
};

You also may need to add webpack@^4 as a dependency if you're using strict PnP mode, since it's peerDependency of @cypress/webpack-preprocessor.

@ottoo
Copy link

ottoo commented May 13, 2021

If anyone else comes across this, managed to get this to work by just making sure that the PnP plugin gets added to the webpack config that Cypress uses. This works with cypress@7.3.0 using PnP with yarn workspaces. The following just needs to get added to you cypress/plugins/index.js.

module.exports = (on) => {
    // You need to use your PnP file to resolve files. The following is just the path that traverses up to where my PnP file is in our repo root.
    const pnp = require('../../../../.pnp.js');
    // I couldn't find this documented, but this appears to monkey-patch require and do all the other necessary things to get PnP working
    pnp.setup();

    // This is where we'll be resolving packages from. In this case, it is a workspace package we have named, but using a relative path here should work as well to resolve from a specific folder.
    const targetModule = '@mypackages/package';

    // We need to patch the webpack config that cypress uses (which is v4 which needs a plugin for PnP support)
    const webpackPreprocessor = require(pnp.resolveToUnqualified('@cypress/webpack-preprocessor', targetModule));
    const PnpWebpackPlugin = require(pnp.resolveToUnqualified('pnp-webpack-plugin', targetModule));

    const options = {
        webpackOptions: {
            resolve: {
                plugins: [
                    PnpWebpackPlugin
                ]
            },
            resolveLoader: {
                plugins: [
                    PnpWebpackPlugin.moduleLoader(module)
                ]
            }
        },
        watchOptions: {}
    };

    on('file:preprocessor', webpackPreprocessor(options));
};

You also may need to add webpack@^4 as a dependency if you're using strict PnP mode, since it's peerDependency of @cypress/webpack-preprocessor.

Thanks! I've been looking for a solution for this for a while, I got it working with this example.

@kleingtm
Copy link

kleingtm commented Jun 30, 2021 via email

@missing1984
Copy link
Contributor

missing1984 commented Jun 30, 2021

cc @merceyz this is the cypress issue i was talking about. Cypress is using a forked process (from its electron app) to do compilation through webpack.

I think in order to make cypress compatible with yarn pnp natively . We need to either:

  1. Fix pnp-webpack-plugin cannot work outside of pnp runtime. arcanis/pnp-webpack-plugin#32 and make it part of the default webpack config.
  2. Fix the webpack 5 enhanced-resolve so it can load the correct pnpapi bases on source file(Do we have an issue opened?). and wait for Cypress switch to use webpack 5.

@cypress-bot cypress-bot bot added stage: needs review The PR code is done & tested, needs review stage: work in progress and removed stage: icebox stage: needs review The PR code is done & tested, needs review labels Jul 14, 2021
@cypress-bot cypress-bot bot added stage: pending release and removed stage: needs review The PR code is done & tested, needs review labels Jul 21, 2021
@cypress-bot
Copy link
Contributor

cypress-bot bot commented Jul 21, 2021

The code for this is done in cypress-io/cypress#17335, but has yet to be released.
We'll update this issue and reference the changelog when it's released.

@cypress-bot
Copy link
Contributor

cypress-bot bot commented Jul 29, 2021

Released in 8.1.0.

This comment thread has been locked. If you are still experiencing this issue after upgrading to
Cypress v8.1.0, please open a new issue.

@cypress-bot cypress-bot bot locked as resolved and limited conversation to collaborators Jul 29, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
package manager: yarn Issues relating to yarn
Projects
None yet
Development

Successfully merging a pull request may close this issue.