DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 966,904 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
poponuts
poponuts

Posted on

Using config files for multiple environment variables in Cypress

If you want a readable, easy-to-change, independent, and other superlatives you can think of, in terms of scaling your Cypress framework, then I suggest using configuration files 😎. It is actually not as hard as some other options on environment variables manipulation can do.

First, create a config folder under the project's root directory (a.k.a. outside the cypress folder). Your extreme patience is needed to answer the question why I would like it placed there.

Next, create two env.json files, namely,

local.env.json:

{
 "env": {
  "domain": "localhost:8080",
  "description": "This is my local machine!",
  "protocol": "http://",
  "subDirectory": "helloworld"
 }
}
Enter fullscreen mode Exit fullscreen mode

test1.env.json:

{
 "env": {
  "domain": "test1.domain.com",
  "description": "This is awesome company's stage environment",
  "protocol": "https://",
  "subDirectory": "/helloworld"
 }
}
Enter fullscreen mode Exit fullscreen mode

Then, go to plugins/index.js and insert the following script:

const fs = require('fs-extra');
const path = require('path');

function getConfigurationByFile (file) {
    const pathToConfigFile = path.resolve('config', `${file}.json`);

    return fs.readJson(pathToConfigFile)
}

// plugins file
module.exports = (on, config) => {
    // accept a configFile value or use local by default
    const file = config.env.configFile || 'local';

    return getConfigurationByFile(file)
};
Enter fullscreen mode Exit fullscreen mode

Something I forgot: You may need to install the package fs-extra as a pre-requisite (npm i --save-dev fs-extra)

Lastly, you can just invoke the environment variables on your tests under the integration folder:
CheckTheUrl.js

const helloWorldUrl = Cypress.env('protocol') + Cypress.env('domain') + Cypress.env('subDirectory')
describe('Run this baby!', ()=> {
 it('Run this baby, I said!', ()=> {
  cy.visit(helloWorldUrl);
  cy.log('This is for demo purpose so I am not doing assertion!');
 });
});
Enter fullscreen mode Exit fullscreen mode

And, drop-dead last step is to execute the test via the CLI (whether it's your IDE's terminal or your CI pipeline) with the command below:
npx cypress run --env configFile=local and if you are feeling nerdy πŸ€“, remove the hard-coding and parameterise the value for configFile with something like %envName% where you can always interchange the value on your CI configurations / parameters.

As a bonus, you can also include this script on your package.json with the following line:

"scripts": {
    "cy:run": "node scripts/cypress.js",
    "e2e:ci": "cypress run --env 'configFile=%envName%'"
}
Enter fullscreen mode Exit fullscreen mode

So, why did I place the config sub-folder outside the cypress folder? Sorry for the anti-climax but it is simply due to the fact that I want to re-use these environment variables for my other frameworks such as k6 (since these are just data in json format). I can create something like this:

import http from `k6/http`;
const config = JSON.parse(open('../config/local.env.json'));
import { sleep } from 'k6';

const helloWorldUrl = `${config.env.protocol}${config.env.domain}${config.env.subDirectory}`;

export let options = {
  vus: 50, // no. of virtual users
  duration: '30s',
};

export default function() {
  console.log(`Attacking the Hello World page, baby!`);
  http.get(`${helloWorldUrl}`);
  sleep(1);
}
Enter fullscreen mode Exit fullscreen mode

Putting it outside makes it cleaner, although a lazy engineer can always make a case to still point it to the cypress folder.

Top comments (2)

Collapse
 
minombreeskarla profile image
minombreeskarla

Hey @poponuts , I wonder if you can help me wth my query. I'm also working on that piece where I wanna call different environment files (qa.json, uat.json)
I've followed your steps above as well as other forum but to no avail.
I'm always getting this error

The function exported by the plugins file threw an error.

We invoked the function exported by /Users/xxxxx/Cypress/projectfolder/cypress/plugins/index.js, but it threw an error.

Error: ENOENT: no such file or directory, open '/Users/xxxxx/Cypress/projectfolder/config/uat.json'
Note: my config is outside the Cypress folder as you mentioned above

Looks like I'm having issue with path.resolve() or the readJson() and Im not sure if I'm missing here such as packages, set up, version? Hope to hear from you.
Probably a sample github code might help. Thanks

Collapse
 
poponuts profile image
poponuts Author

I'm not sure if you have resolved this issue and apologies for the late response (I usually check my dev.to account only when I'm about to write something).
It's hard to know the context of your issue but this is my "stab-in-the-dark" solution:
Try changing this line to the following:
`const pathToConfigFile = path.resolve('../../config',${file}.json);

  • Include the ../..

🌚 Browsing with dark mode makes you a better developer.

It's a scientific fact.