Jest global variables that persist - jestjs

I see that global variables can be specified across Jest tests but that:
mutation will not be persisted across test runs for other test files.
Is there way to make changes to global variables that persist across all test files?

You can use Environment Variables to carry those variables across tests, even if you have multiple test files. Official docs states below that any global variable cannot be accessed through tests:
Note: Any global variables that are defined through globalSetup can only be read in globalTeardown. You cannot retrieve globals defined here in your test suites.
But the tests use the same environment so you can set and change variables accordingly.
Create globalSetup in config with following file:
// setup.js
module.exports = async () => {
process.env.TEST_VAR = "my-test-var";
};
You can use this variable in your tests:
// my-test.js
// ...
it("should read the test var from environment", async (done) => {
expect(process.env.TEST_VAR).toEqual("my-test-var");
process.env.TEST_VAR = "new-var";
expect(process.env.TEST_VAR).toEqual("new-var");
done();
});
// ...
You can unset this variable ones the test are complete with globalTeardown config with the following file:
// teardown.js
module.exports = async () => {
delete process.env.TEST_VAR;
};
Remember that setting and not properly using environment variables are risky that may alter your test results. I use it to pass around a persistent variable.

I do not think there is a way to do that. I also do not think there should be a way to do this. Test cases should be able to run independently from one another. Allowing some mutation to a global variable to be persisted across all test files might create a situation in which a test case will only succeed if it is run after another test case has mutated some variable. This situation might result in very fragile tests and should be avoided.
If you need a global variable (or any other variable for that matter) to be in a certain state for a test to succeed. You should look into the setup and teardown methods of Jest.

Related

Run code before NestJs Decorators initialization

Are there ways to get data and save from another microservice before decorator initialization? As I understand decorators initialize even before bootstrap function is called
Decorators evaluate to regular JS code that is evaluated when the file is required. The only way to run something before the decorator, is to have that something higher in the file, or before that file is even required in another script. It'd be like having
export const foo = () => {
console.log('foo');
}
console.log('Here we are exporting foo');
And wanting to run something before the console.log('Here we are exporting foo'). The only way is to have what you want to run higher up in the file, or before this file is every required

Global beforeAll in Jest?

I need to simulate different window sizes in my tests using React Testing Library and Jest.
Currently I'm having to have this beforeAll in every test file:
import matchMediaPolyfill from 'mq-polyfill';
beforeAll(() => {
matchMediaPolyfill(window)
window.resizeTo = function resizeTo(width, height) {
Object.assign(this, {
innerWidth: width,
innerHeight: height,
outerWidth: width,
outerHeight: height,
}).dispatchEvent(new this.Event('resize'))
}
})
Which I use like so:
it('does something at small screen sizes', async () => {
window.resizeTo(320, 800);
// actual test here
Can I have a global beforeAll that will apply to every test file in my project?
The docs mention globalsetup:
https://jestjs.io/docs/en/configuration#globalsetup-string
However it errors as it doenst recognise the beforeAll function. I seemed to me that that option is meant for setting up an environment but not adding something to the test files?
globalSetup runs in another process and cannot access beforeAll or other variables from test scope. It's meant for initializations made before any test is started, e.g. setting up a server, like the documentation shows.
It's setupFiles that runs in test process. beforeAll should be executed after Jest environment is initialized, so it should be moved to setupFilesAfterEnv.

Proper use of artifacts.require?

I am trying to understand how artifacts.require should be used. I've seen the standard paragraph describing it as being for migrations and testing. From this I infer that the globally scoped artifacts with its method require are automatically defined by the truffle executable tool when doing migrations or running tests. However, I am working with some code that uses artifacts.require outside the context of any migrations or tests, rather, this code just needs to do the usual at and new. However, in this context, the object artifacts is not defined.
Do I have the right picture here? Is this an appropriate use of artifacts.require? If so, what must be done to make it be defined outside of migrations and testing?
Thanks for any suggestions!
artifacts.require really isn't meant to be used outside of a test. this is where it is defined: https://github.com/trufflesuite/truffle-core/blob/3e96337c32aaae6885105661fd1a6792ab4494bf/lib/test.js#L240
when in production code you should load the compiled contract into your application using truffle-contract https://github.com/trufflesuite/truffle-contract
here is a short example (from http://truffleframework.com/docs/getting_started/packages-npm#within-javascript-code and see
http://truffleframework.com/docs/getting_started/contracts#making-a-transaction )
var contract = require("truffle-contract");
var contractJson = require("example-truffle-library/build/contracts/SimpleNameRegistry.json");
var SimpleNameRegistry = contract(contractJson);
SimpleNameRegistry
.deployed()
.then(function(instance) {
return instance.setRegistry(address);
})
.then(function(result) {
// If this callback is called, the transaction was successfully processed.
alert("Transaction successful!")
})
.catch(function(e) {
// There was an error! Handle it.
});

Global function in express.js?

How can I define a global function in express.js, that without require I can call it
"How" is simple enough:
global.fnName = function(){ return "hi"; }; // Andreas Hultgren's answer
But you don't need the global prefix; the thing about the global object is ...
fnName = function(){ return "hi"; }; // i.e. don't do: var name = function(){ ... };
console.log(fnName()); // this prints "hi"
console.log(global.fnName()); // this also prints "hi" - it was assigned to global.
"Without require" is a separate consideration: if you don't use require there is no guarantee your "globals" will have been declared by the time you need them. It enforces loading order of dependencies, among other things.
"Why am I" and "Is it correct to" are now hidden questions you should consider. It is accepted in javascript that Global Variables ...
... should be reserved for objects that have system-wide relevance and they should be named to avoid ambiguity and minimize the risk of naming collisions - Angus Croll, Namespacing in Javascript
i.e. global truly is Global: it is used by every author of every plugin or library you pull in to your application, not just you. Naming collisions between global variables break your application. This applies equally in node.js.
Global variables are also thought of as a code smell. In the detail sections below here you will see you can quickly get into trouble by using global variables, and they should really be treated as something that pushes you towards dependency injection and/or namespaces and modules.
Node.js and express - global vars and functions
Here's a good rule: if you upload it to a web server, or share it with other people, don't use global variables.
global is permissible in tiny "Saturday afternoon" apps in node.js with express.js, but tend to cause problems later if they get adopted into production. Therefore:
Modules and exports is best practice.
Injection should also be used to reduce coupling between javascript files. But in all cases you will usually need require to ensure they exist by the time you need them:
You should really consider app.locals data, and/or middleware functions, for anything that is view data related.
// call this as a function with an input object to merge
// the new properties with any existing ones in app.locals
app.locals.({
sayHello: function() { return "hi"; }
});
// now you can also use this in a template, like a jade template
=sayHello()
If you are creating global vars/functions for configuration settings purposes the below comments about namespaces still apply, and there are conventions emerging such as config.json files (still using require) for settings that are globally accessed.
Global variables - simple case
It is simple enough to declare a global variable in javascript, and for a function the process is no different. Simply omit the var keyword which would normally force a local scope on the declaration:
// app.js
blah = "boo";
sayHello = function(string toWho) { return "hello " + toWho; }
getVersion = function() { return "0.0.0.1"; }
// routes/main.js
console.log(blah); // logs: "boo"
console.log(global.blah); // logs: "boo"
console.log(sayHello("World")); // logs: "hello World"
console.log(global.sayHello("World")); // logs: "hello World"
console.log(getVersion()); // logs: "0.0.0.1"
But what if two separate plugins in your project use a global getVersion function - how do you get the right version number? Also, how do you ensure that getVersion exists before you need it, or exists at all?
Why do we need require?
To quote the nodejitsu docs the built in require function ...
... is the easiest way to include modules that exist in separate files. The basic functionality of require is that it reads a javascript file, executes the file, and then proceeds to return the exports object
"So", you may ask, "require just makes sure that a module from another file is included? Why bother?" It's better than that: you can make a whole folder a module, making your code easier to organise and test test test, it will recognise various extensions for file modules, not just .js, and it will look in various folders as well. Of course, it caches as well.
So, now that require has found your module, it ensures the code inside it is executed, and puts the objects your created into a "namespace":
// module file ./myModule.js
exports.blah = "boo";
exports.sayHello = function(string toWho) { return "hello " + toWho; }
// routes/main.js
var demoModuleReference = require('./myModule.js');
console.log(demoModuleReference.blah); // logs: "boo"
console.log(demoModuleReference.sayHello("World")); // logs: "hello World"
In that sample, demoModuleReference is an object that looks like:
{
blah: "foo",
sayHello: [Function]
}
Why modules and not global variables (a.k.a namespacing and "Global is the new private")?
Seems complicated now? Surely global variables are easier? requires ensures the following:
It ensures ordered loading of dependencies
It prevents variable name conflicts within global through the exports object.
This application at mankz.com (chrome or firefox only) is fascinating. Depending on how you use your js code, you are very likely to have variable name conflicts within the global scope. Name conflicts come from everywhere. In a browser, for instance, they can come from extensions. node.js is slightly different, but it is becoming more and more extended by compatible plugins as time goes on (you can load jquery in right now, for example). As the versions go on frameworks will get added, and name collisions in global will become more likely. My last run of that app in chrome showed over 1200 global namespace variables.
Namespaces - why?
This global namespace pollution was publicised early on by Douglas Crockford through Eric Miraglia in the article "A JavaScript Module Pattern". In summary:
All objects that need to be used between js files are really global
So, create a namespace object that will be unique
Assign the return value an anonymous function
Add private methods and variables inside that function
Do something useful with the pattern
Example:
ANDYBROWNSONICSUITE.BoomBox.SoundModule = function () {
var privateField = "can't touch this";
return {
play: function() {
console.log(privateField);
}
}
}
Why is this good?
Now you have only increased the global namespace members in the world by one, but this member contains as many items as you like.
Your application is far less likely to clash with other namespaces
It's a pattern, other frameworks expect you to use it to interact with them properly. In that reference, jQuery is a browser plugin, but you can use it with node and therefore your app, so the library interactivity policy statement is a perfect example.
It's a pattern, if we all follow it we our programs are all more likely to get along
When you read the Crockford reference along with the Croll reference (Direct Assignment section) I mentioned at the start, you see why it looks this complicated rather than just doing: sound.play = function() { ... } - ease of maintenance, refactoring the namespace etc. being just one reason.
Summary
In summary:
Can I create globals? Yes, it's simple, omit the var keyword before the declaration.
Should I create globals? You should use the module pattern, which is implicitly supported by node, and by express
Why am I creating globals? If it's for configuration, use a config namespace (e.g. How to store Node.js deployment settings/configuration files?)
You can:
global.name = function(){};
But you really should avoid using globals, even if it's possible to use them.

How to stub "global" module variables in node.js with Coffeescript without --bare?

I have some environment variables from Heroku and for readability, I tend to assign them to global variables for readability:
ACCESS_TOKEN = process.env.ACCESS_TOKEN
Now I'd like change value for that in tests. I have tried rewire and sandboxed-module. However, they are both setting global variables directly, whereas coffeescript variables are wrapped in anonymous function.
Is there any way around this, or do I really have to use --bare if I want to test my code?
I'm not familiar with node, but the approach I'd use, and that I've used in other technologies is wrap up globals or external dependencies in an object which can be swapped out for a stub or mock object when needed in test.
Say rather than storing the value in ACCESS_TOKEN you made a herokuEnvironment object and gave it the method accessToken(). Wherever you need to use the properties you inject the object. Then in production that method calls process.env.ACCESS_TOKEN. If you need a safe version to inject into a test situation, you just supply { accessToken: function () {return 'foo';}}

Resources