Using karma and jasmine...
I have a module using a global await:
import ...
const data = await fetch()...
And a test using it:
import ...
describe() ...
It seems that jasmine complain about it:
An error was thrown in afterAll
Error: 'describe' should only be used in 'describe' function in node_modules/jasmine-core/lib/jasmine-core/jasmine.js (line 1811)
Any idea if my analysis is correct?
Any idea on how to configure karma to make that work?
Related
'Using the Playwright Library [1.21.0] with Jest [27.5.1] to run browser automation tests on Node.js [14.18.2].
ESM is the current module format.
// package.json
...
"type": "module",
...
I setup a quick test with the following code:
// playwright-hello.js
import {chromium} from 'playwright';
async function main() {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('http://www.example.com');
await page.screenshot({ path: 'screenshot.png' });
await browser.close();
}
main().catch(console.error);
The above code works via CLI command node playwright-hello with no issues.
However, when I try to run similar code with Jest, I get the following error:
FAIL test/index.test.js
● Test suite failed to run
SyntaxError: The requested module 'playwright' does not provide an export named 'chromium'
at Runtime.linkAndEvaluateModule (node_modules/jest-runtime/build/index.js:779:5)
at TestScheduler.scheduleTests (node_modules/#jest/core/build/TestScheduler.js:333:13)
at runJest (node_modules/#jest/core/build/runJest.js:404:19)
at _run10000 (node_modules/#jest/core/build/cli/index.js:320:7)
at runCLI (node_modules/#jest/core/build/cli/index.js:173:3)
I fixed this by updating the test code to use the default export instead:
// changed to use default export instead of named one
import playwright from 'playwright';
// prepended `playwright.` to initial `chromium.launch()`
const browser = await playwright.chromium.launch();
How come the object destructuring assignment in playwright-hello.js [i.e. import {chromium}...] works with node.js CLI, but not with Jest? In other words, node.js did not complain about playwright library not providing a named export, why?
Note: I'm running Jest as follows for ES6 modules support:
NODE_OPTIONS='--experimental-vm-modules' npx jest ./test/index
I'm using the matchFeature example from NodeJS but when i try to test the following error occurs in the
const cv = require('opencv4nodejs'); line from the example.
test/matchFeature.test.js
● Test suite failed to run
TypeError: Cannot convert undefined or null to object
at Function.keys ()
at Object. (node_modules/opencv4nodejs/lib/cv.js:63:8)
at Object.
(node_modules/opencv4nodejs/lib/opencv4nodejs.js:11:79)
I think is a problem when loading the module, but i cant fix it.
I'm using Jest for testing.
If i run the file with NodeJS, works without problems:
https://prnt.sc/sq41s9
And if i run test with jest, gives the error above:
https://prnt.sc/sq42mb
The images are from the file cv.js running the file and the test
EDIT: Screenshot from jest index.js (Module null)
https://prnt.sc/sq5rxl
I was able to solve it with a global setup script which loads the module.
// setup.js
module.exports = async () => {
const cv = require('opencv4nodejs');
console.log('cv.version', cv.version);
};
And in the jest Config in package.json:
"jest": {
...
"testEnvironment": "node",
"globalSetup": "./setup.js"
}
I'm trying to use Mocha to test a CLI app. The tests are running fine but, when I launch the testing procedure, it also launches the main app:
$ npm run test
> standardize-js#0.2.2 test C:\Users\Gaspard\Documents\Code\standardize-js
> mocha "./source/**/*.spec.js"
? Choose your project language or framework (Use arrow keys) //<-- THIS IS THE PROGRAM
> Javascript
Typescript
AngularJS
Main function //<-- THIS IS THE TEST
ask if the configuration is valid
Configuration is not valid, terminating program.
√ should return false if the configuration is not accepted
1 passing (29ms)
I'm kind of new to the testing world and I'm really struggling to understand what I'm doing wrong.
Here is the NPM script used to launch mocha :
"test": "mocha \"./source/**/*.spec.js\""
Here is my testing method:
/* eslint-disable func-names */
const { expect } = require("chai");
const main = require("./index").test;
describe("Main function", function() {
describe("ask if the configuration is valid", function() {
it("should return false if the configuration is not accepted", function() {
const fakeAnswer = false;
expect(main.validateConfiguration(fakeAnswer)).to.equal(false);
});
});
});
And here is my index.js file:
function validateConfiguration(answer) {
if (answer === false) {
console.log(chalk.red("Configuration is not valid, terminating program."));
return false;
}
return true;
}
const run = async () => {
//MAIN FUNCTION
};
run();
// Export functions and variables to be able to test
exports.test = {
validateConfiguration
};
It's not a problem with mocha. It is simply now node.js modules work.
When you do this:
const main = require("./index").test;
Node.js will execute index.js and then check the value of module.exports. If the module (index.js) sets or modifies module.exports then node will export it for use by require(). But note, in order for node to know that the module has exported anything it must execute the javascript file.
Node.js does not have any ability to parse and analyze javascript syntax (that's V8's job). Unlike other languages such as C or Java, modules in node.js are not implemented at the syntax level. Therefore the javascript language does not need to be modified (eg. ES6 modules) for node.js to support modules. Modules are simply implemented as a design pattern.
In your index.js file you call run:
run();
When require() loads index.js it will therefore also cause run() to be called.
Test libraries, not main
The solution to this is to implement your own logic as modules and test that, not test index.js:
mylib.js:
function validateConfiguration(answer) {
if (answer === false) {
console.log(chalk.red("Configuration is not valid, terminating program."));
return false;
}
return true;
}
// Export functions and variables to be able to test
exports.test = { validateConfiguration };
index.js:
const validateConfiguration = require("./mylib").test;
const run = async () => {
//MAIN FUNCTION
};
run();
You can now use your test script as written.
How can you not test code??
The strategy to keep index.js bug free without testing is to remove all logic from it except for the minimum amount of code to wire all your other code up together to run the app. The code should be as simple as "Hello World". That way, the code in main is so small and so simple that you can test it for bugs using your eyeballs.
Any code in index.js that causes a bug should be refactored into its own library so that it can be tested separately. There are a small handful of corner cases, such as loading environment variables or opening port 80 where you can't really separate into a library because they literally are wiring logic. For such cases you just have to be really careful.
It's calling run because you are telling it to right after defining the method.
I'm currently trying to get some test coverage for a command line tool I built in node with Jest. My code is split up in modles, most of which have asynchronous http requests that I'm trying to mock. I'm wondering if there is a way to mock these requests that exist inside the module functions?
module.exports = function() {
client.apiGet() // How do I mock this?
.then(() => {
// more logic, runs several fs operations
})
.catch((err) => { console.error(err) });
}
You will need to mock the client module. I assume you had require or import it further up. Once you have it mocked you can decide to either stub all of it's methods' implementations or just the apiGet.
https://jestjs.io/docs/en/manual-mocks.
Finally, you will probably use the .resolves and .rejects to have the proper expectation.
https://jestjs.io/docs/en/expect#resolves
#Koen Van Gilst wrote a great blog about mocking API calls with Jest:
https://hackernoon.com/api-testing-with-jest-d1ab74005c0a
Hope this sends you in the right direction
I am trying to test a simple node Module with intern.The module is an AMD module. I am running into a couple of issues
If the module is defined as below, I get the error "moduleName" has
no method 'map' "
define('moduleName',[]function(require){ var r= require('request');
})
If the module is defined as below without a moduleName, I see this
error "undefined is not a function" - I guess its not able to resolve 'require'
define([]function(require){ var r= require('request'); })
Here is how my Test Looks
define([
'intern!object',
'intern/chai!assert',
'/src/api/nameApi'
], function (registerSuite, assert,nameApi) {
registerSuite({
name: 'GetName Test',
getName: function () {
var nameFromApi = nameApi.getName();
assert( nameFromApi!= null,'name is not null');
}
});
});
Providing an explicit module ID as the first argument to define destroys module portability and shouldn’t be done. It is not currently supported by the loader used by the master branch because it is such a bad idea. It is supported by the geezer branch, but again, I strongly advise you to never use this pattern.
The second module definition you have provided is just wrong; you need to put 'require' in your dependencies array if you expect to load the special require function. You also can’t use a variable to pass a module ID to the require function if you are expecting it to be pre-loaded as a dependency. So, it should look like this:
define(['require', 'foo'], function (require) {
var foo = require('foo');
});
or, using the CommonJS compatibility wrapper syntax, where require is implicitly provided:
define(function (require) {
var r = require('foo');
});
EDIT: Also, now that you have added the test module: within your test’s define, '/src/api/nameApi' is not a valid AMD module identifier.