i've been trying to figure out how to specify which .env file to use when running Cypress Component tests for a while now but can't seem to figure it out or find any information about it online.
I've noticed when you mount a Component in Cypress and run some Component Tests, the component will pick up process.env variables from the .env file by default. However, I would instead like Cypress to pick up process.env variables from my .env.test file. Does anyone know how to specify which .env file your component should get process.env variables from when running component tests?
I am currently just running the following command from my package.json file "test-e2e": "cypress open". This opens the Cypress test runner where I can select Component Testing and then select a spec file to run tests against. The component in question uses some process.env variables which I can see are being taken from the .env file which seems to be the default. I can't find any flags I can add to my npm command to instead tell Cypress to take them from the .env.test file instead.
Any help would be much appreciated!
You want to do something like this answer How can I get Vite env variables.
Note that the .env section of config is outside of component or e2e sections (common to both).
const { defineConfig } = require("cypress");
const dotenv = require('dotenv')
const env = dotenv.config('./.env.test').parsed
module.exports = defineConfig({
'component': {
// component config here
},
env: {
login_url: '/login',
...env, // merge here with spread operator
},
});
Related
I am having a problem getting .env variables working in my Vue app. After npm install process this was the only syntax that didn't throw an error when trying to import.
import * as process from 'process';
Before this I also had the following error:
Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i --save-dev #types/node`.
I ran this install and added "node" to types in my tsconfig file.
I have a member variable defined like so,
const testVar = process.env.TEST_VAR
and have tried both TEST_VAR=just test and TEST_VAR="just test" inside my .env file.
The .env file itself is placed in the root folder of the project, ie. outside the src folder, but I have tried placing it inside the src folder also.
Despite all that, the var is coming back undefined.
mounted(){
console.log('ENV TEST -> ', this.testVar)
alert(`ENV2 : ${this.testVar}`)
...
}
I'd be very grateful for any help solving this. Thanks!
Only variables that start with VUE_APP_ will be statically embedded into the client bundle. Vue docs
And then it will be accessible in the components
mounted() {
console.log(process.env.VUE_APP_TEST_VAR)
}
I have the following initial situation:
Our tests refer to a store that is available in multiple languages via country dropdown.
Depending on the country, the store has different features and therefore also different tests.
I have two problems here. The first is the folder structure
In order not to have a separate repo for each country, we would like to separate the test specs for the stores by folders.
But since the PageObjects are identical, I would like to define them only once, so that the test specs can access them.
However, it does not work as I imagine it.
Here is my idea of the folder structure in Cypress:
cypress-automation
cypress
fixtures
integration
shops
shop_de
sample-tests.spec.js
shop_en
sample-tests.spec.js
shop_es
sample-tests.spec.js
plugins
index.js
support
pageObjects
samplePageObject.js
index.js
commands.js
node_modules
cypress.json
package-lock.json
package.json
However, it doesn't work because Cypress misses the PageObjects. The following error occurs:
Error: webpack compilation error
./cypress/integration/shops/shop_en/sample-tests.spec.js
Module not found: Error: Unable to resolve '../support/pageObjects/samplePageObject.js' in 'C:\users\users\desktop\cypress-automation\cypress\integration\shops\shop_en'.
The second problem concerns the index.js
there I have to add a country switch in the beforeEach method, because the URLs of the stores are identical and the store can only be changed via dropdown.
Unfortunately I don't know how to integrate the index.js into the store folder, so that the sample-tests.spec.js access a specific index.js instead of a global one. Alternatively, I would have to adjust the beforeEach method in each sample-tests.spec.js but with so many test specs I find that impractical.
is that even possible, the way I imagine it?
EDIT:
#Fody
i did it exactly as you said. However, now I get an error:
PageObjects_homePage__WEBPACK_IMPORTED_MODULE_1_.HomePage is not a constructor
here is an example from my code how i included it:
import { HomePage } from "#PageObjects/homePage";
the constructor looks like this
const homePage = new HomePage();
HomePage Class:
class HomePage {
testMethod() {
testcode()
}
}
export default HomePage;
For part one, set up a webpack alias to make it easy to import from anywhere in the intergration folders, any level nesting.
Add the package Cypress Webpack Preprocessor, following their instructions
npm install --save-dev #cypress/webpack-preprocessor
npm install --save-dev #babel/core #babel/preset-env babel-loader webpack - if not already installed
or with yarn
yarn add -D #cypress/webpack-preprocessor
yarn add -D #babel/core #babel/preset-env babel-loader webpack - if not already installed
cypress/plugins.index.js
/// <reference types="cypress" />
const path = require('path');
const webpack = require('#cypress/webpack-preprocessor');
console.log('__dirname', __dirname) // __dirname is cypress/plugins
module.exports = (on) => {
const options = {
webpackOptions: {
resolve: {
alias: {
'#PageObjects': path.resolve(__dirname, '../../cypress/support/pageObjects')
},
},
},
watchOptions: {},
};
on('file:preprocessor', webpack(options));
};
cypress/integration/shops/shop_de/sample-tests.spec.js
// resolves any level of nesting
import {MyPageObject} from '#PageObjects/samplePageObject.js'
...
cypress/integration/shops/shop_de/bavaria/sample-tests.spec.jbs
// same import after move to sub-folder
import {MyPageObject} from '#PageObjects/samplePageObject.js'
...
I have a react app that sets a bunch of process.env variables using dotenv. Every component when it's source is in the same source code repo and imported via '../component/component_name' can access the process.env variables simply by using process.env.variable_name. We decided to break the components out into separate NPM packages in order to update them independent of the main repo. Now when we import them from our local NPM they intsall to node_modules and run, but cannot access the process.env variables. process.env shows up as an object, but it has nothing in it. We are using webpack to build the package before we publish it.
Inside component, you can do:
import process from "process";
const env = process.env;
export default env;
I am working on this react app and thinking of adding some environment variables inside, this is what I've done:
installed the latest version of react-scripts
added .env file on the root folder (the same location where node_modules folder is)
added REACT_APP_OTHER_OTHER_THING=asdfas just to test the variable
REACT_APP_OTHER_OTHER_THING=asdfas
open index.js and console.log(process.env.REACT_APP_OTHER_OTHER_THING) inside to see the output
import React from 'react';
import Reactdom from 'react-dom';
import App from './App';
console.log(process.env.REACT_APP_OTHER_OTHER_THING, 'DOTENV')
Reactdom.render(<App/>, document.getElementById("app"))
then I rebuilt the app and started the app to see the result
but then it gives out undefined as the output for process.env.REACT_APP_OTHER_OTHER_THING. I then tried to print process.env.NODE_ENV (which is working and prints "development" as output).
note: I have also tried to add temporary variable as the docs said in https://create-react-app.dev/docs/adding-custom-environment-variables >> rebuilt the server and run ($env:REACT_APP_OTHER_OTHER_THING= "abcdef") -and (npm start) << due to me running it on powershell which still gives undefined as output.
is there anything I can do on this?
thank you
Ensure it has correct directory tree
D:\your-react-project \ .env
Here it maybe your-react-project \ .env.development
It should be in the path of where default README.md placed
Alright, the problem I'm having seemed to be from the webpack I made in my React App,
I tried to follow the instruction from this article and it's working well!
after configuring my webpack, I rebuilt it, restart the server, and it works!
edit: for my solution, I added:
const dotenv = require('dotenv');
const env = dotenv.config().parsed;
const envKeys = Object.keys(env).reduce((prev, next) => {
prev[`process.env.${next}`] = JSON.stringify(env[next]);
return prev; }, {});
at the top of webpack.common.js
and also added
plugins: [
new webpack.DefinePlugin(envKeys), //this line
]
in the module.exports
in the plugin. I hope this helps! :)
Can't comment, so i will post an answer, sorry.
Are you sure about ($REACT_APP_OTHER_OTHER_THING= "abcdef") -and (npm start), because docs says ($env:REACT_APP_NOT_SECRET_CODE = "abcdef") -and (npm start)
I just added new env var, and it gave me undefined, but after server restart it worked just fine. Can you try to restart server, but add env variable not in terminal, but inside .env file?
UPD1:
just so you know, NODE_ENV is set by npm start or npm run build commands, they set to development or production, respectively.
As docs says:
You cannot override NODE_ENV manually. This prevents developers from accidentally deploying a slow development build to production.
This worked for me with the same issue. I double-checked everything was connected correctly then killed my server in the terminal after started it back up & it worked fine.
Other causes of undefined environment variables on a much simpler level than the op's Webpack configuration question include:
Leaving out process.env.REACT_APP_SERVER_URL and just writing REACT_APP_SERVER_URL in your code
Forgetting to name the environment variable with REACT_APP as the first part of the string
I am trying to set some environment variables (for making API calls to dev/prod endpoints, keys depending on dev/prod, etc.) and I'm wondering if using dotenv will work.
I've installed dotenv, and I am using webpack.
My webpack entry is main.js, so in this file I've put require('dotenv').config()
Then, in my webpack config, I've put this:
new webpack.EnvironmentPlugin([
'NODE_ENV',
'__DEV_BASE_URL__' //base url for dev api endpoints
])
However, it is still undefined. How can I do this correctly?
Sorry for picking up old question, but
react-scripts actually uses dotenv library under the hood.
With react-scripts#0.2.3 and higher, you can work with environment variables this way:
create .env file in the root of the project
set environment variables starting with REACT_APP_ there
access it by process.env.REACT_APP_... in components
.env
REACT_APP_BASE_URL=http://localhost:3000
App.js
const BASE_URL = process.env.REACT_APP_BASE_URL;
See docs for more details.
The short answer is no. A browser cannot access local or server environment variables so dotenv has nothing to look for. Instead, you specify ordinary variables in your React application, usually in a settings module.
Webpack can be made to take environment variables from the build machine and bake them into your settings files. However, it works be actually replacing strings at build-time, not run-time. So each build of your application will have the values hard-coded into it. These values would then be accessible through the process.env object.
var nodeEnv = process.env.NODE_ENV;
Additionally, you could use the DefinePlugin for webpack which lets you explicitly specify different values depending on your build target (dev, prod, etc.). Note that you have to JSON.stringify all values passed into it.
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
}),
This is fine for any sort of public details but should never be used for any sort of private keys, passwords or API secrets. This is because any values baked in are publicly accessible and could be used maliciously if they contain sensitive details. For those sorts of things, you need to write some server-side code and build a simple API which can authenticate with the 3rd party API using the secrets, then pass the relevant details along to your client-side application. Your server-side API acts as an intermediary, protecting your secrets while still getting the data you need.
Create .env file
API_URL=http://localhost:8000
Install dotenv npm package
$ npm install --save-dev dotenv
Config webpack to add env variables
const webpack = require('webpack');
const dotenv = require('dotenv');
module.exports = () => {
// call dotenv and it will return an Object with a parsed key
const env = dotenv.config().parsed;
// reduce it to a nice object, the same as before
const envKeys = Object.keys(env).reduce((prev, next) => {
prev[`process.env.${next}`] = JSON.stringify(env[next]);
return prev;
}, {});
return {
plugins: [
new webpack.DefinePlugin(envKeys)
]
};
Great job! Enjoy React and dotenv.
Actually, you can use dotenv in your React app with webpack. Moreover, there are several ways of doing it. However, keep in mind that it's still a build-time configuration.
A similar way to the answer above. You import dotenv in your webpack config and use DefinePlugin to pass the variables to your React app. More complete guide on how you can inject your .env files depending on current configuration could be found in this blog.
Using a dotenv-webpack plugin. I personally find it really convenient. Let's say you have environments: dev, staging and prod. You create .env file for each environment (.env.dev, .env.staging, etc). In your webpack configuration you need to pick a correct file for the environment:
const Dotenv = require('dotenv-webpack');
module.exports = (env, argv) => {
const envPath = env.ENVIRONMENT ? `.env.${env.ENVIRONMENT}` : '.env';
const config = {
...
plugins: [
new Dotenv({
path: envPath
})
]
};
return config;
};
When you build the app for a particular environment, just pass the environment name to webpack:
webpack --config webpack.config.js --env.ENVIRONMENT=dev
I Just created a config.json in the source folder:
{
"api_url" : "http://localhost:8080/"
}
then required it in the file I needed it
const config = require('./config.json');
and used config.api_url