why does jest have problems executing node module code? - javascript

I have two modules.
One of them, "A", is ES5 with no babel. Its unit tests use mocha and chai and they complete successfully. The unit tests require a module, "M", during the testing. At this point, the code in the module is run. If it is not, the test fails. If i debug the execution, the "require('M')" jumps straight into the module.js require(path) and it loads/executes the code at the top module scope.
The other is ES6. It uses jest 19.0.2 and babel-jest 19.0.0, both currently the latest versions. It requires the same module but, unfortunately, the code is not run and the test fails. I've set "automock" to false explicitly. When I debug it, the "require('M')" stack is:
jest-runtime/build/index.js:requireModuleOrMock(from, moduleName)
jest-runtime/build/index.js:requireModule(from, moduleName, options)
jest-runtime/build/index.js:_execModule(localModule, options)
at this point it returns without running the module's code. The block is:
// If the environment was disposed, prevent this module from being executed.
if (!this._environment.global) {
return;
}
Apparently the environment was disposed. Then requireModule() returns moduleRegistry[modulePath].exports. As a result, the top-level, module-scope code does not run and the test fails.
I should add that the failing code is run within a promise so it seems possible that the environment is released before the promise resolves. I have tried using:
let promise = ...
expect(promise).resolves.toBe(true);
but the execution path is unchanged.
If someone knows why this is occurring and how to ensure that the module code runs it would be appreciated.

Related

mocha global `before` that executes only 1 time

I'm using mocha for node.js functional testing.
There are several files in my test.
How can I run a piece of code for only one time before all tests start?
For example, I may have to set up a docker container before all tests start.
Is it possible to do this with mocha?
The before hook runs 1 time for every test file. This doesn't meet my needs.
You can have 'root' level hooks, if you put them outside of any describe blocks. So you can put your relevant code in any files inside of the test folder.
before(function() {
console.log('before any tests started');
});
See the docs: http://mochajs.org/#root-level-hooks
Mocha 8 introduces the concept of root hook plugins. In your case, the relevant ones are beforeAll and afterAll, which will run once before/after all tests, so long you tests run in serial.
You can write:
exports.mochaHooks = {
beforeAll(done) {
// do something before all tests run
done();
},
};
And you'll have to add this file using the --require flag.
See docs for more info.
There is a very clean solution for this. Use --file as parameter in your mocha command. It works like a global hook for your tests.
xargs mocha -R spec --file <path-to-setup-file>
A setup file can look like this:
'use strict';
const mongoHelper = require('./mongoHelper.js');
console.log("[INFO]: Starting tests ...");
// connect to database
mongoHelper.connect()
.then(function(connection){
console.log("[INFO]: Connected to database ...");
console.log(connection);
})
.catch(function(err){
console.error("[WARN]: Connection to database failed ...");
console.log(err);
});
Unfortunately I have not found a way to use async/await in this setup files. So I think you may have to be conent with using "old" promise and callback code.

jest - error with watch mode

I am using Jest 21.2.1 to run my tests for a react application. Strangely when I run jest --watch (as mentioned here) to watch test cases for any change, I get an error as below
Determining test suites to run...Error: This promise must be present when running with -o.
I tried to check the Jest-CLI and found that the function is expecting two parameters and one of them is promise which is not passed in this case (Not sure how can I pass that). Maybe some missing config?
Any suggestion will be helpful to fix this.
getTestPaths(
globalConfig,
changedFilesPromise)
{var _this2 = this;return _asyncToGenerator(function* () {
const paths = globalConfig.nonFlagArgs;
if (globalConfig.onlyChanged) {
if (!changedFilesPromise) {
throw new Error('This promise must be present when running with -o.');
}
return _this2.findTestRelatedToChangedFiles(changedFilesPromise);
}
Note: It might be related to issue reported here.
Make sure you're running it in a Git repo (initialised with git init). Otherwise it doesn't know how to get only the changed files.
If you don't want to run tests only on changed files, you can use --watchAll, which runs all the tests.

Jasmine asynchronous boot in SystemJS+Typescript environment

I'm running Jasmine tests in SystemJS+Typescript environment (basically a plunk that is supposed to be Angular 2 test rig).
Jasmine is intentionally used as global library, not via TypeScript import.
This results in
No specs found
There are no errors in console, the specs just don't run:
main.ts
describe('test', () => {
it('test', () => {
console.log('test');
expect(1).toBe(1);
});
});
I'm positive this is due to the fact that main.ts is loaded asynchronously with SystemJS, so Jasmine boot procedure should be additionally triggered in order to make it pick on the specs.
The manual describes what is default boot configuration in Jasmine, but it doesn't explain well how it can boot be executed manually.
What is the way to run the tests with SystemJS and global Jasmine in this case?
The reason is that your specs are loaded after jasmine has done attempts to search and execute them.
To overcome this issue you can call window.onload again after your specs are loaded by system.js:
<script>
System.import('app').then(window.onload).catch(console.error.bind(console));
</script>

How to run the v8 Promise tests against my own implementation?

I have implemented a module that should look exactly like a regular ES6 Promise; and I want to test it as such.
The files that test promises in the node tests are here:
https://github.com/nodejs/node/blob/master/deps/v8/test/mjsunit/es6/promises.js
However I cannot work out how to run these files. After putting in the requisite require for my own module the files fail with syntax errors of missing functions. I seem to be missing some kind of testing suite but can't work out which it is.
The syntax errors are for missing function: eg. describe
I have inserted a line at the top of the file like so:
var Promise = require('my-promise-module');
this module should appear no different to:
module.exports = Promise;
I am attempting to run the file like node ./promise.js (where promise.js is the linked test file).
This is obviously not the right way to run it as many of the functions called in the test file are not available (e.g. %abortJS), though I cannot work out what the test file needs to run.

How to run JavaScript test script in multiple environments (terminal and browser)?

Let's say I have some tests that require jQuery. Well, we don't have to make believe, I actually have the tests. The test themselves are not important, but the fact they depend on jQuery is important.
Disclaimer: this is node.js so you cannot depend on global variables in your solution. Any dependency must be called into the file with require.
On the server we need this API (to mock the window object required by server-side jquery)
// somefile.js
var jsdom = require("jsdom").jsdom;
var window = jsdom().parentWindow();
var $ = require("jquery")(window);
// my tests that depend on $
// ...
On the client we need a slightly different API
// somefile.js
// jsdom is not required obviously
// window is not needed because we don't have to pass it to jquery explicitly
// assume `require` is available
// requiring jquery is different
var $ = require("jquery");
// my tests that depend on $
// ...
This is a huge problem !
The setup for each environment is different, but duplicating each test just to change setup is completely stupid.
I feel like I'm overlooking something simple.
How can I write a single test file that requires jQuery and run it in multiple environments?
in the terminal via npm test
in the browser
Additional information
These informations shouldn't be necessary to solve the fundamental problem here; a general solution is acceptable. However, the tools I'm using might have components that make it easier to solve this.
I'm using mocha for my tests
I'm using webpack
I'm not married to jsdom, if there's something better, let's use it !
I haven't used phantomjs, but if it makes my life easier, let's do it !
Additional thoughts:
Is this jQuery's fault for not adhering to an actual UMD? Why would there be different APIs available based on which env required it?
I'm using karma to run my unit tests from the command line directly (CI too, with gulp).
Karma uses phantomjs to run the tests inside of a headless browser, you can configure it to run in real browsers too.
Example of karma configuration inside of gulp:
// Run karma tests
gulp.task("unit", function (done) {
var parseConfig = require("karma/lib/config").parseConfig,
server = karma.server,
karmaConfig = path.resolve("karma.conf.js"),
config = parseConfig(karmaConfig, {
singleRun: true,
client: {
specRegexp: ".spec.js$"
}
});
server.start(config, done);
});
In case of my tests it takes approx. 10 seconds to run 750 tests, so it's quite fast.

Categories