Set custom Jest environment in docblock - jestjs

Is it possible to set a custom environment via the docblock syntax, or does it just work with node and jsdom envs?
Eg:
/**
* #jest-environment my-custom-env
*/

Yes, you can set a custom environment for a single Jest test using the docblock syntax.
If your custom environment is installed as a package in node_modules you can just use the module name.
Alternatively, if your custom environment is defined in a file within your project you can use the path to that file (in this case my-custom-env.js in the root directory of the project):
/**
* #jest-environment ./my-custom-env
*/

Related

.env variables not available in jest testing environment

When I run my code normally I can access my .env file with const newVar = process.env.MY_DOTENV_VARIABLE, but when I run jest everything becomes undefined. Is this normal for jest? If so, what is the best practice for storing variables?
Is it simply to create a set up file, eg:
// jest.config.ts
setupFiles: [
"<rootDir>/.jest/setEnvVars.ts",
],
# .env
MY_DOTENV_VARIABLE=exampleString
I just needed to install dotenv. I think I got confused where process.env was working previously without the dotenv packaging. This was either due to me setting the env variables with scripts in my package.json file, eg "scripts":"NODE_ENV=test ..." and/or some packages were making changes. (I'm using various aws packages, and I've read that they can change environment variables)

I can't access my environment variable in file.js

I define REACT_APP_ADMIN_URL in my .envrc file, i want to use it as a component link, but i get only empty or undefined
This my environment variable, in file .envrc
REACT_APP_ADMIN_URL="http://127.0.0.1:8000/admin"
in file consts.js i make
export const ADMIN_URL = process.env.REACT_APP_ADMIN_URL;
and in my page i make this
import { ADMIN_URL } from './Consts';
<Menu href={ADMIN_URL}>Admin</Menu>
but doesnt work, in my inspector console i get this
Admin
I think that you have to load the environment variables from the .env file on runtime, you can use dotenv package to do so.
Install the package using npm i dotenv
Create a .env file in the root directory of your project. Add environment-specific variables on new lines in the form of NAME=VALUE.
Put this line require('dotenv').config() before using the environment variables on your code.
process.env now has the keys and values you defined in your .env file

How to set environment variables using Node?

I am trying to automatically set three AWS environment variables (AWS_ACCESS_KEY, AWS_ACCESS_ID and AWS_SESSION_TOKEN) which are derived from the JSON returned by aws sts assume-role.
Normally if I wanted to automatically set environment variables I would write a Bash script, say setvars.sh:
export AWS_ACCESS_KEY=something
and then
source setvars.sh
I know that if you do process.env.AWS_ACCESS_KEY = 'something' in a Node script, it won't affect the parent process.
Is there a workaround to be able to use a Node script (rather than Bash, which will be tricky to manipulate JSON with) to set environment variables this way?
When you set environment variables using a bash script and run in a shell, they are accessible just to the processes which are run in the same shell. So you will need to run the Node app in the same shell to access those variables.
Now another approach is to add them in process.env object, so you can write a config script just to load all the config variables and require it at top of your Node app. You need to design the application in such a way that you can use all the configuration in same file.
For Example:
config.js:
process.env.AWS_ACCESS_KEY = 'something'
app.js:
// Starting point of your app
require('./config');
const app = require('express')();
// Use the config
// AWS_API(process.env.AWS_ACCESS_KEY);
// Other App Logic
This approach is mostly used in development environment, in production you might want to use the first approach or you can add the configuration globally using /etc/profile or /etc/environment. Refer how-to-set-global-environment-variable
You can read the JSON file and set your environment variables in process.env:
process.env['environment_variable_name'] = 'environment_variable_value';
NB: This will be available only for that particular node process and its children, not globally available.
As an expansion to the accepted answer,
You can also define your ENV in a file, and import a specific env config based on a release.
This way you can set ENV files for your staging, development or production environments in static configs if required.
From dotenv repository/docs
As early as possible in your application, require and configure dotenv.
require('dotenv').config()
Create a .env file in the root directory of your project. Add
environment-specific variables on new lines in the form of NAME=VALUE.
For example:
DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3
process.env now has the keys and values you defined in your .env file.
const db = require('db')
db.connect({
host: process.env.DB_HOST,
username: process.env.DB_USER,
password: process.env.DB_PASS
})
So for you, you may want to do an async call from AWS to get those ENV variables, or perhaps save them within a .env file
https://github.com/motdotla/dotenv

REACT_APP_* vs NODE_PATH Environment Variables

What is the difference between a regular CRA environment variable (that MUST begin with REACT_APP_) and the NODE_PATH variable (that is used to avoid having to use relative paths for imports, ../../../foo etc.)
From my testing, no variables can be used unless they begin with REACT_APP, so how is the NODE_PATH variable not ignored like other variables that do not begin with REACT_APP?
NODE_PATH is accessible because it's added in the Webpack configuration in react-scripts.
You can see the code that adds it here:
https://github.com/facebook/create-react-app/blob/25184c4e91ebabd16fe1cde3d8630830e4a36a01/packages/react-scripts/config/env.js#L61
You'll see in that file that you can also set NODE_ENV which sets which environment you are running in (e.g. development, staging, etc.) as well as PUBLIC_URL
To answer your question on the differences:
NODE_PATH allows you to use absolute paths for imports. For example, you can set your NODE_PATH to the following:NODE_PATH=src:src/components:src/containers and then in your React code you could write something like this: import Button from 'button' instead of import Button from '../../../button' as long as you have that module in one of the folders src, src/components, or src/containers because create-react app will look for the button module those folders. You wouldn't actually use the NODE_PATH variable in your React code that same way that you use REACT_APP_* variables. Basically, it tells your app where to look for modules.
REACT_APP_* variables are injected into your application at build time using the Webpack configuration from the file I linked to.
This: const GRAPHQL_URI = REACT_APP_GRAPHQL_URI
becomes this: const GRAPHQL_URI = https://example.com
if you have this in your .env file: REACT_APP_GRAPHQL_URI = https://example.com

Will env. vars affect imports from node_modules?

I'm extracting some utility functions from my project into npm modules so I can use them in other projects.
Some of these functions rely on API Keys, and use different API Keys for DEV and PROD environments.
In the main project, this isn't a problem, as my build process sets the environment vars correctly, and my webpack build process results in the correct keys in the source code.
If I include the API Keys in the npm modules with the same DEV | PROD ternaries, will the environment vars of the main project work the same for the modules as they did for the code when it was in the main project?
// mymodule/index.js
export default function() {
return __PROD__ === true ? "abc" : "123"
// ....
}
// project/index.js in __DEV__ environment
import getKey from 'my-module'
getKey() // should return "123"
I may be misunderstanding your question, but what you're using aren't environment variables. They're probably variables you're filling in with Webpack's DefinePlugin, such as
new webpack.DefinePlugin({
__PROD__: true
})
When Webpack compiles your code, the plugin automatically replaces these magic global variables with the value in the configuration file.
The correct way to use an environment variable in node is process.env, as in process.env.__PROD__, and run your program with something like __PROD__=true node index.js, or by the more common convention NODE_ENV=production node index.js.
If you're publishing the compiled Webpack code to npm, then it should work with whatever DefinePlugin value you've set for the npm compile Webpack configuration.

Resources