How to use process.env variables in browser running by Cypress - reactjs

In the source code of my application (React based on create-react-app) I'm using env variables like so: process.env.REACT_APP_API_URL which are stored in my .env.* files.
But when I run the same application under the Cypress the process.env object is empty. How can I provide these variables to be used in React application when it's running under Cypress?
I know that I have a possibility to set Cypress env variables but it is not what I want - this is a different scope.

You can use the configuration API and do something like this on your plugins file. Set config.env = process.env which will set your entire node env for Cypress.
// cypress/plugins/index.js
module.exports = (on, config) => {
// modify env value
config.env = process.env
// return config
return config
}
You can also selectively assign the values that you want with config.env.YOUR_VAR = process.env.YOUR_VAR.

Updated in Cypress version 10.3.0 and above
In Cypress, environment variables (accessible via Cypress.env) doesn't share the same scope as OS-level environment variables. In order to make process.env variables available in Cypress, you should use a third party library, such as dotenv package, which is very popular.
npm install dotenv
Make sure this line of code sitting on top of your cypress.config.js
require('dotenv').config()
Now you're good to go using process.env, but only under that cypress.config.js file. As mentioned in another answer, you should leverage the Cypress.env() command by passing all process.env properties to Cypress environment variables, so that you can access those variables globally in Cypress
// cypress.config.js
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
config.env = {
...process.env,
...config.env
}
return config
}
}
})
Note that in Cypress version 10.0.0 and above, setupNodeEvents was added to replace the deprecated plugins file.
Now you can retrieve those variables by:
Cypress.env("your_proccess_env_property")

Create cypress.env.json file that contains your environment variables:
{
"api_url": "http://localhost:8080"
}
Then set process.env in your cypress/support/index.js:
...
before(() => {
process.env. REACT_APP_API_URL = Cypress.env("api_url");
})

For my use case, I was simply able to do the following.
// cypress.config.js
require('dotenv').config();
const { defineConfig } = require('cypress');
module.exports = defineConfig({
...,
env: {
...process.env,
},
});
Hopefully this helps anyone else in the future!

If you want to use the same variables, the same way as react app, while running only Cypress without an app (this is the reason why process.env is empty). You could add this in cypress.config.js
const dotenvOutput = require('dotenv').config()
then access the variables as
module.exports = defineConfig({
e2e: {
env: {
api_url: dotenvOutput.parsed.REACT_APP_API_URL,
},
You also need to make sure that the .env file is available where the cypress is ran.

Related

How can I pass environment variables by using dotenv in react app ? I get undefined

This is my react fontend app. to pass data from node.js backend, I need to successfully pass API's url. currently im setting the address to my localhost.
I am struggling to path process.env.API_URL to my config file.
my files structure is
.src
- config
* config.js
- .env
.webpack.config.js
my .env file is
API_URL=http://localhost:3006
my config file is below but im getting "undefined" as my console result here. clearly variable is not passing successfully.
console.log(process.env.API_URL)
const config = {
host: process.env.API_URL
};
export default config;
I have installed both "npm install dotenv --save" and "npm i dotenv-webpack"
Inside my Webpack.config.js is below. I feel like I am just so close to be working but I just cannot figure it out what's the problem here.
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const webpack = require("webpack");
const dotenv = require('dotenv');
dotenv.config({ path: './.env' });
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.API_URL': JSON.stringify(process.env.API_URL),
}),
],
};
any suggestions is appreciated. thank you.
Well you have .env in src folder and you are trying to access it on same level as webpackConfig. So move the .env file on the same level as config or fix your import.

process.env empty object in Cypress

I am working on a React app bootstraped from create-react-app few years ago.
The app has a .env.dev file with many variables.
The start script is "start": "env-cmd -f .env.dev --use-shell \"react-scripts start\"",
React script version: "react-scripts": "^4.0.1",
When I console.log("gggg", process.env); I get all the variables.
When I:
describe('Login via API', () => {
it('Test login', () => {
console.log('teeest', process.env)
cy.login()
})
})
instead I get an empty object.
I tried to read the question How to use process.env variables in browser running by Cypress
however this question does not answer my question on how to make the process.env variables available to Cypress test files.
Also this question says to install dotenv. Dotenv comes with react-scripts, so no need to install it if the app was create by create-react-app.
I also tried this:
in cypress.config.js I added:
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
config.env = process.env
return config
}
}
})
And in the spec I try to get the variable defined in .env.dev file:
it('Test login', () => {
console.log('new', Cypress.env('REACT_APP_USERNAME'))
cy.login()
})
Still getting undefined.
Can anyone please help me to understand what's wrong? How can I make it work?
Edit:
According to an answer here I tried to install dotenv:
npm install dotenv --save
imported in the test:
import 'dotenv/config'
describe('Login via API', () => {
it('Test login', () => {
console.log('newwwww', Cypress.env('REACT_APP_USERNAME'))
console.log('teeest', process.env)
cy.login()
})
})
Npm start
npm run cypress:open
Result:
newwwww undefined
login-test.cy.js:7 teeest {}
Thanks
When you use "start": "env-cmd -f .env.dev --use-shell \"react-scripts start\"", the env-cmd command is specific to the process for the react app.
You would need the same to run before cypress opens it's process
package.json
{
...
"dependencies": {
...
},
"scripts": {
"cy:open": "env-cmd -f .env.dev cypress open",
...
}
}
Avoiding conflict with other env setting
I also recommend using the spread operator as shown below, otherwise you would lose any env var added in other ways, e.g command line additions.
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
config.env = {
...process.env, // add all process env var here
...config.env // plus any command line overrides
}
return config // return the altered config
},
},
env: {
login_url: '/login', // define some specific env var here
products_url: '/products'
}
});
Avoiding pollution of Cypress settings
If you take a look at Settings/Project Settings in the Cypress runner, you'll see a huge number of unnecessary settings which come from the general machine env var.
To pick just those with prefix REACT_,
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
const reactEnv = Object.keys(process.env).reduce((obj, key) => {
if (key.startsWith('REACT_')) {
obj[key] = process.env[key];
}
return obj;
}, {});
config.env = {
...reactEnv, // add REACT_ process env var here
...config.env // plus any command line overrides
}
return config // return the altered config
},
},
env: {
login_url: '/login', // define some specific env var here
products_url: '/products'
}
});
You're right about dotenv being included with react-scripts, but to access it in your test files you'll have to explicitly import it.
npm install dotenv
then at the top of your cypress code
import 'dotenv/config'
See usage instructions here
https://www.npmjs.com/package/dotenv

React Environmental Variables are undefined with Dotenv

I am using dotenv to create an environment variable to insert a base url into my API call using react, dotenv, and webpack.
When I call the variables in the code, I don't get any error other than them printing as undefined. What am I doing wrong?
Here is my webpack file
const webpack = require("webpack");
const Dotenv = require("dotenv");
dotenv.config();
module.exports = (env) => {
return {
plugins: [
new Dotenv(),
new webpack.ProvidePlugin({
process: "process/browser",
}),
new webpack.DefinePlugin({
'process.env': JSON.stringify(process.env)
})
],
};
};
Here are what the variables look like in the .env file in the root of my project
API_URL=http://localhost:8000
BASE_URL=https://my-url.com
And here is how I am accessing it in the code (with axios for auth)
axiosAuth: axios.create({
baseURL: `${process.env.BASE_URL}`,
timeout: 5000,
})
Like Shah already explain, the only thing that you need is add the prefix "REACT_APP" to your current variables..
Change this:
API_URL=http://localhost:8000
BASE_URL=https://my-url.com
To this:
REACT_APP_API_URL=http://localhost:8000
REACT_APP_BASE_URL=https://my-url.com
Set the values explicitly to be defined instead of the whole process.env. Try:
new webpack.DefinePlugin({
'process.env': {
API_URL: JSON.stringify(process.env.API_URL),
BASE_URL: JSON.stringify(process.env.BASE_URL),
}
})
And if you're using create-react-app, prefixing REACT_APP_ will also work and you could remove the define plugin and Dotenv.
example:
API_URL -> REACT_APP_API_URL // .env
usage: `process.env.REACT_APP_API_URL

Why should we use next js configuration file in React project? What's the main purpose using it?

I need to know about the configuration file. Why we use it to react project.
with next.js, you can write your environment variables in ".env.local" but those environment variables will be for server-side. if you want to add environment variables for your client, you add it to next.config.js
If you want to add a new webpack plugin
If you want to convert your app to progresive web app
module.exports = {
webpack: (config) => {
// adding a webpack pugin
config.plugins.push(new MonacoWebpackPlugin());
return config;
},
// this will pass the env variable to the client side
env: {
AUTH0_NAMESPACE: process.env.AUTH0_NAMESPACE,
BASE_URL: process.env.BASE_URL,
EMAILJS_SERVICE_ID: process.env.EMAILJS_SERVICE_ID,
EMAILJS_TEMPLATE_ID: process.env.EMAILJS_TEMPLATE_ID,
EMAILJS_USER_ID: process.env.EMAILJS_USER_ID,
BASE_URL: process.env.BASE_URL,
},
// set up for progressive app
pwa: {
dest: "public",
// runtimeCaching,
swSrc: "service-worker.js",
},
};
You need to add configuration file in next js project for custom advanced behavior of Next.js. The file next.config.js is a regular Node.js module, not a JSON file. It gets used by the Next.js server and build phases, and it's not included in the browser build

http-proxy-middleware not proxying to index page of other server?

I have two servers running on Docker. One is the react frontend at localhost:3000 while the backend runs at localhost:9000. When I go to localhost:3000/api, I want to get to the index page of the backend, which is localhost:9000.
Created a setupProxy.js file in the myApp folder created through create-react-app:
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
app.use(proxy('/api', { target: 'http://backend:9000' }));
};
When I go to localhost:3000/api, I get sent to localhost:9000/api instead of localhost:9000.
http-proxy-middleware has a pathRewrite option, see the documentation.
In your particular case:
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
app.use(proxy('/api', {
target: 'http://backend:9000',
pathRewrite: {'^/api' : ''}
}));
};
this should normally rewrite localhost:3000/api/endpoint to localhost:9000/endpoint.
Note that there is also a router option for more tailored behavior.

Resources