bahmutov / cypress-extends

Cypress plugin that adds "extends" support to the configuration file
34 stars 6 forks source link

Extending configuration file with Cypress 10 #87

Open Deop opened 2 years ago

Deop commented 2 years ago

More of a question rather than a bug. With changes in Cypress 10 (switching from .json to .js or .ts configs) could you please explain/update on how do we extend configs now?

Deop commented 2 years ago

Ok, it seems I've figured out how to do it (not sure if it's the best way though). This solution does not require cypress-extends plugin to be used at all. I'll leave my solution for reference if someone else might need it. First, you need to import your base config into your current config const baseConfig = require('../config/base.config.js') Then you can either assign it's properties to be used in your current config by doing: env: baseConfig.env, or combine properties from both base and current config files by creating two objects and merging them:


let baseE2e = baseConfig.e2e;
let currentE2e = {
    baseUrl: "https://google.com",
}

module.exports = defineConfig({
  e2e: {
      ...baseE2e,
      ...currentE2e
  }
})
mmitchell3590 commented 2 years ago

Nice idea. In my case, I needed to do a deep merge between configs, so I ended up using lodash.merge for this.

Here is a quick sample of a config file, in case it could be helpful for anyone:

const {defineConfig} = require('cypress');
const baseConfig = require('../cypress.config.js').e2e;
const _ = require('lodash.merge');

const currentConfig = {
  projectId: 'someValue',
  env: {
    someProperty: 'someValue'
  }
};

module.exports = defineConfig({
  e2e: _(baseConfig, currentConfig)
});
jrockefeller commented 2 years ago

Did this an easy way in v10

your config files are straight json with what you want to overwrite

//cypress/config/myConfig.json
{
baseUrl: "myUrl",
env: { 
   myKey: "myValue"
  }
}

then to specify what override file you would like:

//cypress.config.js
  e2e: {
    setupNodeEvents(on, config) {
      config.extends = `./cypress/config/${config.env.envName}.json`
      return  require('@bahmutov/cypress-extends')(config.configFile)
    },
}

npx cypress open --env envName=myConfig

kamil220 commented 2 years ago

Excellent solutions, but unfortunately, none of them met my expectations.

I needed to create a solution that would allow me to switch between environments quickly, and from cypress.config.ts I could not retrieve environment variables to add the appropriate config. The following solution works for me, but I don’t know how about performance.

Cypress: 10.3.0 System: MacOS Monterey

package.json

"scripts": {
    "cypress:alpha": "npx cypress run --env ENV=alpha",
  },

cypress.env.json

{
    "projectId": "xxxxxxx",
    "baseUrl": "https://example.com/",
    "viewports": {
      "desktop": {
        "name": "Desktop",
        "width": 1920,
        "height": 1080
      },
      "desktop-small": {
        "name": "Small desktop",
        "width": 1366,
        "height": 768
      },
      "tablet": {
        "name": "Tablet",
        "width": 768,
        "height": 1024
      },
      "mobile": {
        "name": "Mobile",
        "width": 414,
        "height": 896
      },
      "mobile-small": {
        "name": "Small mobile",
        "width": 360,
        "height": 640
      }
    }
}

cypress/support/e2e.js

Cypress.env( {
    ...Cypress.env(),
    ...require( '../../config/' + Cypress.env( 'ENV' ) + '.json' )
} );

config/alpha.json

{
  "baseUrl": "https://alpha-example.com/",
  "credentials": {
    "d2c": {
      "username": "user",
      "password": "password"
    }
  }
}
kamil220 commented 2 years ago

Did this an easy way in v10

your config files are straight json with what you want to overwrite

//cypress/config/myConfig.json
{
baseUrl: "myUrl",
env: { 
   myKey: "myValue"
  }
}

then to specify what override file you would like:

//cypress.config.js
  e2e: {
    setupNodeEvents(on, config) {
      config.extends = `./cypress/config/${config.env.envName}.json`
      return  require('@bahmutov/cypress-extends')(config.configFile)
    },
}

npx cypress open --env envName=myConfig

Are you sure? On my side, extending config via this way is impossible.

nerrante commented 2 years ago

Question for all of you that did this, it seems like all of these assumes you are extending everything under "e2e" section of the configuration (which is new with Cypress10). Does that mean you have moved everything into that section now? Meaning I have somethings outside of e2e that these solutions won't extend. A brief example:

module.exports = defineConfig({
  chromeWebSecurity: false,
  experimentalInteractiveRunEvents: true,
  retries: {
    runMode: 1,
  },

  //more stuff here

  e2e: {
    baseUrl: 'https://myurl.place.com',
    experimentalSessionAndOrigin: true,
    setupNodeEvents(on, config) {
      on('before:browser:launch', (browser, launchOptions) => {
        if (browser.name === 'chrome' && browser.isHeadless) {
          launchOptions.args.push('--disable-gpu');
          launchOptions.args.push('--disable-gpu-sandbox');
          launchOptions.args.push("--incognito");
        }
        return launchOptions
      });

     //more stuff under setupNodeEvents
    }
  }
})

The solutions above only seem to deal with merging the e2e sections...also I assume that means each of your files has to have its own "setUpNodeEvents" section (which could have duplicates between files) because the e2e extension/merge is going to overwrite the entire e2e section (even a deep merge didn't see to work for that section). Any tips or tricks? Right now I've just gone to individual config files and that seems like a silly amount of duplication! Hope this rambling makes sense.

damosull commented 1 year ago

Question for all of you that did this, it seems like all of these assumes you are extending everything under "e2e" section of the configuration (which is new with Cypress10). Does that mean you have moved everything into that section now? Meaning I have somethings outside of e2e that these solutions won't extend. A brief example:

module.exports = defineConfig({
  chromeWebSecurity: false,
  experimentalInteractiveRunEvents: true,
  retries: {
    runMode: 1,
  },

  //more stuff here

  e2e: {
    baseUrl: 'https://myurl.place.com',
    experimentalSessionAndOrigin: true,
    setupNodeEvents(on, config) {
      on('before:browser:launch', (browser, launchOptions) => {
        if (browser.name === 'chrome' && browser.isHeadless) {
          launchOptions.args.push('--disable-gpu');
          launchOptions.args.push('--disable-gpu-sandbox');
          launchOptions.args.push("--incognito");
        }
        return launchOptions
      });

     //more stuff under setupNodeEvents
    }
  }
})

The solutions above only seem to deal with merging the e2e sections...also I assume that means each of your files has to have its own "setUpNodeEvents" section (which could have duplicates between files) because the e2e extension/merge is going to overwrite the entire e2e section (even a deep merge didn't see to work for that section). Any tips or tricks? Right now I've just gone to individual config files and that seems like a silly amount of duplication! Hope this rambling makes sense.

I'm in the same situation as you. I want to extend everything in the config file.

Any help would be appreciated

luqy commented 1 year ago

Excellent solutions, but unfortunately, none of them met my expectations.

I needed to create a solution that would allow me to switch between environments quickly, and from cypress.config.ts I could not retrieve environment variables to add the appropriate config. The following solution works for me, but I don’t know how about performance.

Cypress: 10.3.0 System: MacOS Monterey

package.json

"scripts": {
    "cypress:alpha": "npx cypress run --env ENV=alpha",
  },

cypress.env.json

{
    "projectId": "xxxxxxx",
    "baseUrl": "https://example.com/",
    "viewports": {
      "desktop": {
        "name": "Desktop",
        "width": 1920,
        "height": 1080
      },
      "desktop-small": {
        "name": "Small desktop",
        "width": 1366,
        "height": 768
      },
      "tablet": {
        "name": "Tablet",
        "width": 768,
        "height": 1024
      },
      "mobile": {
        "name": "Mobile",
        "width": 414,
        "height": 896
      },
      "mobile-small": {
        "name": "Small mobile",
        "width": 360,
        "height": 640
      }
    }
}

cypress/support/e2e.js

Cypress.env( {
    ...Cypress.env(),
    ...require( '../../config/' + Cypress.env( 'ENV' ) + '.json' )
} );

config/alpha.json

{
  "baseUrl": "https://alpha-example.com/",
  "credentials": {
    "d2c": {
      "username": "user",
      "password": "password"
    }
  }
}

image I tried your method, but the configuration doesn't seem to take effect,Are there any other treatments?