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

Dotenv module doesn't work with cypress #1358

Closed
Gennadiii opened this issue Feb 21, 2018 · 10 comments
Closed

Dotenv module doesn't work with cypress #1358

Gennadiii opened this issue Feb 21, 2018 · 10 comments

Comments

@Gennadiii
Copy link

  • Operating System: Windows 10
  • Cypress Version: 1.4.2
  • Browser Version: Chrome 63

Bug

Current behavior:

https://www.npmjs.com/package/dotenv
In order to use this module to have to require('dotenv').
If I do this anywhere in code it fails:

./node_modules/dotenv/lib/main.js
Module not found: Error: Can't resolve 'fs' in '<project dir>\node_modules\dotenv\lib'
resolve 'fs' in '<project dir>\node_modules\dotenv\lib'
Parsed request is a module
using description file: <project dir>\node_modules\dotenv\package.json (relative path: ./lib)
Field 'browser' doesn't contain a valid alias configuration
after using description file: <project dir>\node_modules\dotenv\package.json (relative path: ./lib)
resolve as module
<project dir>\node_modules\dotenv\lib\node_modules doesn't exist or is not a directory
<project dir>\node_modules\dotenv\node_modules doesn't exist or is not a directory
<project dir>\node_modules\node_modules doesn't exist or is not a directory
<project dir>\node_modules doesn't exist or is not a directory
<user dir>repo\node_modules doesn't exist or is not a directory
<user dir>repo\node_modules doesn't exist or is not a directory
C:\Users\node_modules doesn't exist or is not a directory
C:\node_modules doesn't exist or is not a directory
looking for modules in <project dir>\node_modules
using description file: <project dir>\package.json (relative path: ./node_modules)
Field 'browser' doesn't contain a valid alias configuration
after using description file: <project dir>\package.json (relative path: ./node_modules)
using description file: <project dir>\package.json (relative path: ./node_modules/fs)
no extension
Field 'browser' doesn't contain a valid alias configuration
<project dir>\node_modules\fs doesn't exist
  .ts
Field 'browser' doesn't contain a valid alias configuration
<project dir>\node_modules\fs.ts doesn't exist
  .js
Field 'browser' doesn't contain a valid alias configuration
<project dir>\node_modules\fs.js doesn't exist
as directory
<project dir>\node_modules\fs doesn't exist
looking for modules in <user dir>node_modules
No description file found
Field 'browser' doesn't contain a valid alias configuration
No description file found
no extension
Field 'browser' doesn't contain a valid alias configuration
<user dir>node_modules\fs doesn't exist
  .ts
Field 'browser' doesn't contain a valid alias configuration
<user dir>node_modules\fs.ts doesn't exist
  .js
Field 'browser' doesn't contain a valid alias configuration
<user dir>node_modules\fs.js doesn't exist
as directory
<user dir>node_modules\fs doesn't exist
  [<project dir>\node_modules\dotenv\lib\node_modules]
[<project dir>\node_modules\dotenv\node_modules]
[<project dir>\node_modules\node_modules]
[<project dir>\node_modules]
[<user dir>repo\node_modules]
[<user dir>repos\node_modules]
[C:\Users\node_modules]
[C:\node_modules]
[<user dir>node_modules\package.json]
[<project dir>\node_modules\fs]
[<project dir>\node_modules\fs.ts]
[<user dir>node_modules\fs\package.json]
[<project dir>\node_modules\fs.js]
[<user dir>node_modules\fs]
[<project dir>\node_modules\fs]
[<user dir>node_modules\fs.ts]
[<user dir>node_modules\fs.js]
[<user dir>node_modules\fs]
@ ./node_modules/dotenv/lib/main.js 3:11-24
@ ./dist/specs/menu.spec.js
@brian-mann
Copy link
Member

brian-mann commented Feb 21, 2018

You cannot require npm modules which use native node libs like fs. Cypress serves your JS spec files to the browser - the usage of fs makes no sense there.

If you want to read in config files and then set env vars into Cypress you can use the Configuration Plugin API to do just that.

Files you write in the plugins folder are evaluated by node, not the browser - which is just the place to use them.

https://docs.cypress.io/api/plugins/configuration-api.html#

@Gennadiii
Copy link
Author

Gennadiii commented Feb 22, 2018

Thanks. That makes perfect sense. But if I do what you suggest then types don't work from this module: add-typescript-to-cypress
What I did for now looks ugly so if you have a solution I`d be thankful.

@dandv
Copy link

dandv commented Jun 26, 2020

There's a plugin that claims to put env vars from .env into Cypress.env(), but I couldn't get it to work.

dotenv files are extremely popular (8,000,000+ downloads / week for dotenv on npm). It would be really nice if Cypress supported them.

@alex-popov-tech
Copy link

alex-popov-tech commented Aug 4, 2020

for someone who will be looking for working examples:

// cypress/plugins/index.js
module.exports = (on, config) => {
  const configWithDotenv = require('dotenv').config();
  if (configWithDotenv.error) {
    throw configWithDotenv.error;
  }
  const env = { ...config.env, ...configWithDotenv.parsed };
  const result = { ...config, env };
  return result;
  // `on` is used to hook into various events Cypress emits
  // `config` is the resolved Cypress config
}
// cypress/integration/example.spec.js
...js
Cypress.env('ENV_NAME')
...

@iDVB
Copy link

iDVB commented May 4, 2021

@alex-popov-tech Can't seem to get this to work?

My .env is in the root. I use it with dotenv in Gatsby as well so I know its valid.
I've even added console logging to the plugin code you provided above and I'm unable to see where this is gettings written out. Even turned on DEBUG=* yarn run cypress open.

@bahmutov
Copy link
Contributor

bahmutov commented May 4, 2021

@Norfeldt
Copy link

I have been trying like a mad man to figure out how to do this with my NextJS project. Want to inject my environment variables into process.env like @bahmutov recipe

import injectDevServer from '@cypress/react/plugins/next'

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

  const configWithDotenv = require('dotenv').config({ path: '.env.test' })
  if (configWithDotenv.error) {
    throw configWithDotenv.error
  }
  const env = { ...config.env, ...configWithDotenv.parsed }
  process.env = env

  return { ...config, env }
}

This only gives me access to Cypress.env('SOME_ENV_VAR') but not process.env.SOME_ENV_VAR ???

@jennifer-shehane
Copy link
Member

@Norfeldt I think the example is for reading process.env variables and setting them as Cypress.env so you can read them in Cypress test files. You won't be able to read process.env from test files. Could you explain where you code above is erroring?

@Norfeldt
Copy link

Norfeldt commented Jun 16, 2021

@jennifer-shehane it took me some time to understand this https://stackoverflow.com/questions/67700529/programmatically-declare-typescript-types-for-environment-keys-in-my-env

In order for me to not care about if it is running in node (with process) or not I have made this helper that also gives me type (autosuggestions in vscode)

template:

utils/env.ts

export default function env(key: TEnvKey): string {
  try {
    // have to try catch because of Cypress reference error
    return Cypress.env(key);
  } catch {
    switch (key) {
      // START OF AUTO GENERATED CASES -- DO NOT REMOVE OR EDIT THIS COMMENT

// this part will be replaced

      // END OF AUTO GENERATED CASES -- DO NOT REMOVE OR EDIT THIS COMMENT
      default:
        return undefined;
    }
  }
}

// START OF AUTO GENERATED TYPES -- DO NOT REMOVE OR EDIT THIS COMMENT
// this will be replaced

envTypesWriter.ts

import { config } from 'dotenv'
import { writeFileSync, readFileSync } from 'fs'

const envLocal = config({ path: '.env.local' }).parsed // NOTE: Script has to be executed from the project root
const typeText = `type TEnvKey =\n  | "${Object.keys(envLocal).join('"\n  | "')}"`

const casesText = Object.keys(envLocal).reduce((acc, key) => {
  acc += `      case '${key}':\n`
  acc += `        return process.env.${key}\n`
  return acc
}, '')

const filePath = 'utils/env.ts'
let text = readFileSync(filePath, { encoding: 'utf8' })
console.log(`reading ${filePath}`)

if (!text) throw 'nothing read'


const casesStartLineMarker =
  '// START OF AUTO GENERATED CASES -- DO NOT REMOVE OR EDIT THIS COMMENT\n'
const casesEndLineMarker =
  '      // END OF AUTO GENERATED CASES -- DO NOT REMOVE OR EDIT THIS COMMENT\n'

text = `${
  text.split(casesStartLineMarker)[0]
}${casesStartLineMarker}${casesText}${casesEndLineMarker}${
  text.split(casesStartLineMarker)[1].split(casesEndLineMarker)[1]
}`

const typesLineMarker = '// START OF AUTO GENERATED TYPES -- DO NOT REMOVE OR EDIT THIS COMMENT\n'
const [untouchedCode, _types] = text.split(typesLineMarker)
const updatedText = `${untouchedCode}${typesLineMarker}${typeText}`

writeFileSync(filePath, updatedText, 'utf8')

so now I can just do env('STRIPE_SECRET_KEY') instead of process.env.STRIPE_SECRET_KEY or Cypress.env('STRIPE_SECRET_KEY')

@rakeshnambiar
Copy link

rakeshnambiar commented Dec 19, 2022

@alex-popov-tech I am using cucumber-preprocessor along with cypress and the file extension is mjx. Please could you help me to add the dotenv to the config file?

export async function setupNodeEvents(on, config) {
  // This is required for the preprocessor to be able to generate JSON reports after each run, and more,
  await preprocessor.addCucumberPreprocessorPlugin(on, config);

  on("file:preprocessor", browserify.default(config));

  // Make sure to return the config object as it might have been modified by the plugin.
  return config;
}

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

9 participants