How to initialise a global variable in unit test runs? - javascript

I understand that global variables are bad but I want to use one.
excerpt from package.json:
"scripts": {
"start": "nodemon jobsServer.js",
"test": "cross-env NODE_ENV=test ./node_modules/.bin/istanbul cover -x \"**/*.spec.js\" ./node_modules/mocha/bin/_mocha -- jobs js --recursive -R spec"
},
jobsServer.js:
global.appPath = require('app-root-path');
// more code here
Now I want to be able to access appPath anywhere in the app.
When I run npm start it picks up the global variable and I am happy.
But when I run npm test it does not load the global (since the global is defined in the server file) and therefore all references to appPath break.
I DO NOT want to do:
const appPath = require('app-root-path');
In every single .spec.js test file.
How can I load the global variable for every spec file?

You just need to add a setup file in test/mocha.opts that will be loaded before to start any test, then you will be available to access those global variables, for example:
test/mocha.opts
--require should
--require ./test/setup
--ui bdd
--globals global
--timeout 200
test/setup.js
global.app = require('some-library')
global.window = {}
global.window.document = {}
docs:
http://unitjs.com/guide/mocha.html#mocha-opts

You could probably write a module to hold your globals and import it in your test:
import getGlobals from './whatever.globals.spec.mjs';
...
describe('Whatever', () => {
it('test global', () => {
const globals = getGlobals();
...
});
Where whatever.globals.spec.mjs is just :
export default function getGlobals() {
return ...; // your global info
}

Related

Reading enviromental variable problem in node.js

Here is my excel.js:
let test = async () => {
console.log(process.env.DATABASE_HOST);
.......
}
test();
Here is my package.json fragment:
"scripts": {
.............
"excel": "cross-env NODE_ENV=development node ./server/excel.js",
"test": "react-scripts test"
}
My .env.development is stored in the application root folder.
Here is my .env.development:
DATABASE_HOST=dbServer
When I execute the following command line in the application root folder:
npm run excel
It should return "dbServer", unfortunately, it returns undefined.
How can I fix it?
Install dotenv package, and require it require('dotenv').config()

Is it possible to set system environment variables from a node script?

I have an npm script like this that executes two node files:
package.json
{
"scripts": {
"my-target": "node setup.js && node run.js"
}
}
Ideally, I can set environment variables in setup.js that can then be accessed in run.js.
setup.js
process.env.HELLO_WORLD=1
run.js
// Ideally prints `1`, instead prints undefined.
console.log(process.env.HELLO_WORLD);
Is something like this possible? Ideally the result of setting the environment variables in setup.js would be persistent, so that if I run
$ echo $HELLO_WORLD
from bash, that reference would still be there.
You can set env vars when you run the main program:
HELLO_WORLD=hello npm run my-target
package.json:
"scripts": {
"my-target": "node setup.js && node run.js"
},
setup.js:
console.info('setup', process.env.HELLO_WORLD);
run.js:
console.info('run', process.env.HELLO_WORLD);
Output will be
setup hello
run hello

node programmatically set process environment variables not available to imported modules

I'm new, hopefully this question is properly formatted and formulated. Can't wait to see your answers on this question. Let's get to it..
Context
Past weekend I was trying to implement es2015 syntax support in my create-react-app configuration files, which was straight forward. All I had to do was use babel-register and babel-preset-env to get it working. So far so good you could say, however it wasn't all good. After some hours of searching I found that process.env variables are not passed through to imported modules. The code below will demonstrate my issue.
The code
package.json
{
...
"scripts": [
"good": "NODE_ENV=development BABEL_ENV=development node -r babel-register scripts/start.js",
"bad": "node -r babel-register scripts/start.js"
],
"devDependencies": {
"babel-core": "^6.26.3",
"babel-preset-env": "^1.7.0",
"babel-register": "^6.26.0"
}
...
}
.babelrc
{
"presets": [ "env" ]
}
scripts/start.js
'use strict'
process.env.NODE_ENV = 'development';
process.env.BABEL_ENV = 'development';
// Always works
const a = require('../src/a');
// Only when environment variables are passed in via the CLI
import b from '../src/b';
console.log('Bye bye..');
src/a.js
'use strict'
console.log('Module A:', process.env.NODE_ENV);
const a = { name: "Module A" };
export default a;
src/b.js
'use strict'
console.log('Module B:', process.env.NODE_ENV);
const b = { name: "Module B" };
export default b;
Running the code
Below you will see the output of both npm scripts:
npm run good
# Outputs:
Module B: development
Module A: development
Bye bye..
npm run bad
# Outputs:
Module B: undefined
Module A: development
Bye bye..
My question(s)
Why aren't programmatically set environment variables passed through to imported modules?
Can this be fixed while keeping es2015 syntax? (e.g. using a babel plugin?)
More info
Just moving my process.env.NODE_PATH over to the CLI won't work, create-react-app programmatically sets environment variables at multiple places in their configuration/script files. I have listed a few links below, pointing to the create-react-app repo and some of the files that are giving me troubles.
create-react-app A link to the create-react-app repo.
scripts/start.js This script sets both process.env.NODE_ENV and process.env.BABEL_ENV.
config/env.js This config file sets process.env.NODE_PATH.
Note(s)
From my current understanding, create-react-app has little to none to do with the problem I'm having. I'm interested in why programmatically set environment variables are not passed through to imported modules.
My setup
OS: Ubuntu 16.04
Node: v8.11.2
Npm: 6.3
ES6 imports are hoisted. This means they will run before the rest of the code regardless of where they are in the source. The result is that b.js will run before you have set process.env.NODE_ENV = 'development'.
Babel's output will be consistent with this and will simulate hoisted imports by moving b's require statement to the top of the file. Babel will create a start file that looks like:
'use strict';
var _b = require('../src/b');
var _b2 = _interopRequireDefault(_b);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
process.env.NODE_ENV = 'development';
process.env.BABEL_ENV = 'development';
// Always works
var a = require('../src/a');
// Only when environment variables are passed in via the CLI
It should be clear looking at that why this isn't working.
[ As a side note, many people strongly recommend that you don't set NODE_ENV at runtime ]
Answer to my second question
Thanks to the insights provided by #Mark Meyer I was able to get it to work.
scripts/start.js
'use strict'
import '../config/devEnv';
config/devEnv.js
'use strict'
process.env.NODE_ENV = 'development';
process.env.BABEL_ENV = 'development';
Now the environment variable setters are hoisted as well, making them available to all imported modules.

How to load config json as environment variable nodejs

I am a newbie to node js. I have different configs for different environments viz dev, prod etc. Currently while creating my app package I copy .json to config.json and then export config.json as config variable (global) and use it throughout the app.
config = require(__dirname + '/config/config');
(config.httpProxy && config.httpProxy.enabled);
I want to load specific env.json as part of environment variable (for dev dev.json's all keys are exported as global variable in app) instead of copying it into app's config.json, so that same app can be used in different env. How to do that.
PS: for application packaging support and dependency management I use gulp and npm.
Please help.
you can name your files like this:
config.development.json
config.production.json
config.test.json
Then load files as:
config = require(__dirname + '/config/config.' + process.env.NODE_ENV);
where process.env.NODE_ENV value can be development/production/test
you have to start your application as
NODE_ENV=development node app.js
for this to work.
I suggest you use this module called config it handles all your env config files.
https://www.npmjs.com/package/config
Just make a folder named config and makes files in it as :
1. development.json
2. qa.json
3. production.json
While starting server provide relevant environment as others mentioned.
Then you can use any property mentioned in your config files.
If you are running your project from your script then set NODE_ENV into your package.json file.
{
...
"scripts": {
"nodemon:server": "NODE_ENV=dev NODE_PATH=. nodemon --exec \"babel-node --stage 1\" server.js",
"prod:server": "NODE_ENV=prod NODE_PATH=. nodemon --exec \"babel-node --stage 1\" server.js"
},
"author": "'Shubham Batra'",
"license": "MIT",
....
}
"prod:server": "**NODE_ENV=prod** NODE_PATH=. nodemon --exec \"babel-node --stage 1\" server.js"
than use in config,js file e.g.
if (process.env.NODE_ENV === 'test' ) {
url = 'http://abc:3000';
dbUrl= 'xyz';
password = '***';
} else if (process.env.NODE_ENV === 'prod') {
url = 'http://def:3000';
...
}
export default {
conf: {
url,
dbUrl,
...
}
}
after that, you can import this config file anywhere in your project and use conf

Adding Vue.js To Rails 5.1 and Unit Tests in Mocha don't work

Repo is available here: https://github.com/systemnate/vuetesting
I created a rails app by running the command rails _5.1.2_ new vuetesting --webpack=vue
And then added mocha and chai yarn add mocha chai --save-dev
And then created a test directory by running mkdir test/javascript
Then I created a spec file to run... touch app/javascript/App.spec.js
And pasted in the following code:
const chai = require('chai')
const expect = chai.expect
describe('first test', () => {
it('is true', () => {
expect(true).to.equal(true)
})
})
And added the following to package.json
"scripts": {
"test": "mocha test/**/*.spec.js --recursive"
}
Now previous yarn test passes. Let's try to implement a Vue specific test.
I run the command yarn add avoriaz mocha-webpack --save-dev
And then modified package.json to use mocha-webpack:
"scripts": {
"test": "mocha-webpack test/**/*.spec.js --recursive"
}
yarn test still passes.
Now I want to test the single file component. To start with, I added to the top of my test so it looks like this:
import Vue from 'vue';
import App from '../../app/javascript/packs/App.vue';
const chai = require('chai')
const expect = chai.expect
describe('first test', () => {
it('is true', () => {
expect(true).to.equal(true)
})
})
And then run yarn test and get the following output
yarn test v0.27.5
$ mocha-webpack test/**/*.spec.js --recursive
ERROR in ./app/javascript/packs/App.vue
Module parse failed: /Users/natedalo/Ruby/vuetesting/app/javascript/packs/App.vue Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
| <template>
| <div id="app">
| <p>{{ message }}</p>
# ./test/javascript/App.spec.js 2:0-53
error Command failed with exit code 1.
Any thoughts on what could be going wrong?
Using Unit Test Vue Components for Beginners as a guide, and copying the webpack.config.js and .setup files from the link above and then changing the test run to read like this inside the package.json:
"test": "mocha-webpack --webpack-config test/javascript/webpack.test.config.js test/**/*.spec.js --recursive --require test/javascript/.setup"

Categories