I am trying to run tests with async/await using mocha. The project architecture was setup before I started working on it and I have been trying to update it's node version to 8.9.4. The project is an isomorphic application and uses babel, gulp and webpack to run.
To run the tests we run a gulp task. There are two .bablerc files in the project. One in the root folder of the project and another in the test fodler.
Both have the same configuration:
{
"presets": [
["env", {"exclude": ["transform-regenerator"]}],
"react",
"stage-1"
],
"plugins": [
"babel-plugin-root-import"
]
}
When I run the app locally there is no error returned anymore. However when I run the tests with gulp test:api I constantly get the error: ReferenceError: regeneratorRuntime is not defined
This is my gulp file in the test folder:
var gulp = require('gulp')
var gutil = require('gulp-util')
var gulpLoadPlugins = require('gulp-load-plugins')
var plugins = gulpLoadPlugins()
var babel = require('gulp-babel')
require('babel-register')({
presets:["es2015", "react", "stage-1"]
});
// This is a cheap way of getting 'test:browser' to run fully before 'test:api' kicks in.
gulp.task('test', ['test:browser'], function(){
return gulp.start('test:api')
});
gulp.task('test:api', function () {
global.env = 'test'
gulp.src(['test/unit-tests/server/**/*.spec.js'], {read: false})
.pipe(plugins.mocha({reporter: 'spec'}))
.once('error', function (error) {
console.log(error)
process.exit(1);
})
.once('end', function () {
process.exit(0);
})
});
gulp.task('default', ['test']);
Any help on why this is happening wouldd be much appreciated.
Node version 8 already has support for async/await so you do not need Babel to transform it; indeed, your root .babelrc includes this preset to exclude the regenerator that would transform async/await (and introduce a dependency on regeneratorRuntime):
["env", {"exclude": ["transform-regenerator"]}]
However, in your test file, the configuration does not specify this preset. Instead, it specifies the preset "es2015", which does include the unwanted transform-regenerator (as you can see at https://babeljs.io/docs/plugins/preset-es2015/). If you change this to match the presets in the root .babelrc, you'll get more consistent results.
Strangely i ran into this issue after i upgraded to Node v8.10.0 from v8.6.x . I had used babel-require like so in my test-setup.js
require('babel-register')();
and the testing tools are Mocha,chai,enzyme + JSDOM . I was getting the same issue when i was making a async call to a API, also while using generator functions via sagas. Adding babel-polyfill seemed to have solved the issue.
require('babel-register')();
require('babel-polyfill');
i guess even babel docs themselves advocate using polyfill for generators and such
Polyfill not included
You must include a polyfill separately when using features that require it, like generators.
Ran into the same issue when running mocha tests from within Visual Studio Code.
The solution was to add the necessary babel plugins in the Visual Studio Code settings.json :
"mocha.requires": [
"babel-register",
"babel-polyfill"
],
I've run into this error before myself when using async/await, mocha, nyc, and when attempting to run coverage. There's never an issue when leveraging mocha for running tests, just with mocha tests while leveraging nyc for running coverage.
11) Filesystem:removeDirectory
Filesystem.removeDirectory()
Should delete the directory "./tmp".:
ReferenceError: regeneratorRuntime is not defined
at Context.<anonymous> (build/tests/filesystem.js:153:67)
at processImmediate (internal/timers.js:461:21)
You can fix the issue a couple of different ways.
Method 1 - NPM's package.json:
...
"nyc": {
"require": [
"#babel/register",
"#babel/polyfill"
],
...
},
...
It really depends which polyfill package you're using. It's recommended to use the scoped (#babel) variant: #babel/pollyfill. However, if you're using babel-polyfill then ensure that's what you reference.
Method 2 - Direct Import
your-test-file.js (es6/7):
...
import '#babel/polyfill';
...
OR
your-test-file.js (CommonJS):
...
require("#babel/polyfill");
...
Don't assign it to a variable, just import or require the package. Again, using the package name for the variant you've sourced. It includes the polyfill and resolves the error.
HTH
Related
I am trying to use Jasmine, via NodeJs and Chutzpah to test the javascript in my project. This is in Visual Studio
The Jasmine test looks like
/// <reference path ='../../net5.Ui/wwwroot/Shared/Javascript/helpers.js' />
describe('Helpers test', function () {
it('Test contains', function () {
const result = helpers.isMatch();
expect(result).toBe(true);
});
});
My javascript files all have a similar structure (a singleton approach)
const helpers = new function(){
this.isMatch = function(){ return true; }
}
Visual Studio is able to detect the tests.
Node version 14.15.4
UPDATE
(I have stripped some of my original post as it's no longer valuable)
I have even removed the <reference path> and replaced it with chutzpah.json at the root of the project with
{
"Framework": "jasmine",
"References": [
{
"Path": "../../net5.Ui/wwwroot/Shared/Javascript/",
"Include": "*.js",
"Exclude": "*app.js"
}
],
"Tests": [
{
"Path": "Tests/",
"Includes": [ "*Spec.js" ]
}
]
}
ES6 features are only partially implemented in IE 11, that is why you get those errors about Invalid character. Template literals $ that you refer to are not implemented. Check more about the compatibility here https://kangax.github.io/compat-table/es6/#ie11
Depending on how you have set up your testing environment, you can change the browser that runs those tests to a different one, like Chrome or Firefox. For example if you use Karma as your test runner, you need to install the npm plugin karma-chrome-launcher and configure karma.conf.js so it uses Chrome.
You haven't given details about your testing environment, but it looks like you are still setting it up, so you could continue using Jasmine as your testing framework and additionally use Karma as your test runner and the free Visual Studio plugin Chutzpah Test Adapter, which enables you to run JavaScript unit tests from the command line and from inside of Visual Studio.
This will require a bit of effort for setting it up from your side, however I there is a very detailed guide about how to integrate all these here.
I try to import a node module inside an Angular 8 web worker, but get an compile error 'Cannot find module'. Anyone know how to solve this?
I created a new worker inside my electron project with ng generate web-worker app, like described in the above mentioned ng documentation.
All works fine until i add some import like path or fs-extra e.g.:
/// <reference lib="webworker" />
import * as path from 'path';
addEventListener('message', ({ data }) => {
console.log(path.resolve('/'))
const response = `worker response to ${data}`;
postMessage(response);
});
This import works fine in any other ts component but inside the web worker i get a compile error with this message e.g.
Error: app/app.worker.ts:3:23 - error TS2307: Cannot find module 'path'.
How can i fix this? Maybe i need some additional parameter in the generated tsconfig.worker.json?
To reproduce the error, run:
$ git clone https://github.com/hoefling/stackoverflow-57774039
$ cd stackoverflow-57774039
$ yarn build
Or check out the project's build log on Travis.
Note:
1) I only found this as a similar problem, but the answer handles only custom modules.
2) I tested the same import with a minimal electron seed which uses web workers and it worked, but this example uses plain java script without angular.
1. TypeScript error
As you've noticed the first error is a TypeScript error. Looking at the tsconfig.worker.json I've found that it sets types to an empty array:
{
"compilerOptions": {
"types": [],
// ...
}
// ...
}
Specifying types turns off the automatic inclusion of #types packages. Which is a problem in this case because path has its type definitions in #types/node.
So let's fix that by explicitly adding node to the types array:
{
"compilerOptions": {
"types": [
"node"
],
// ...
}
// ...
}
This fixes the TypeScript error, however trying to build again we're greeted with a very similar error. This time from Webpack directly.
2. Webpack error
ERROR in ./src/app/app.worker.ts (./node_modules/worker-plugin/dist/loader.js!./src/app/app.worker.ts)
Module build failed (from ./node_modules/worker-plugin/dist/loader.js):
ModuleNotFoundError: Module not found: Error: Can't resolve 'path' in './src/app'
To figure this one out we need to dig quite a lot deeper...
Why it works everywhere else
First it's important to understand why importing path works in all the other modules. Webpack has the concept of targets (web, node, etc). Webpack uses this target to decide which default options and plugins to use.
Ordinarily the target of a Angular application using #angular-devkit/build-angular:browser would be web. However in your case, the postinstall:electron script actually patches node_modules to change that:
postinstall.js (parts omitted for brevity)
const f_angular = 'node_modules/#angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js';
fs.readFile(f_angular, 'utf8', function (err, data) {
var result = data.replace(/target: "electron-renderer",/g, '');
var result = result.replace(/target: "web",/g, '');
var result = result.replace(/return \{/g, 'return {target: "electron-renderer",');
fs.writeFile(f_angular, result, 'utf8');
});
The target electron-renderer is treated by Webpack similarily to node. Especially interesting for us: It adds the NodeTargetPlugin by default.
What does that plugin do, you wonder? It adds all known built in Node.js modules as externals. When building the application, Webpack will not attempt to bundle externals. Instead they are resolved using require at runtime. This is what makes importing path work, even though it's not installed as a module known to Webpack.
Why it doesn't work for the worker
The worker is compiled separately using the WorkerPlugin. In their documentation they state:
By default, WorkerPlugin doesn't run any of your configured Webpack plugins when bundling worker code - this avoids running things like html-webpack-plugin twice. For cases where it's necessary to apply a plugin to Worker code, use the plugins option.
Looking at the usage of WorkerPlugin deep within #angular-devkit we see the following:
#angular-devkit/src/angular-cli-files/models/webpack-configs/worker.js (simplified)
new WorkerPlugin({
globalObject: false,
plugins: [
getTypescriptWorkerPlugin(wco, workerTsConfigPath)
],
})
As we can see it uses the plugins option, but only for a single plugin which is responsible for the TypeScript compilation. This way the default plugins, configured by Webpack, including NodeTargetPlugin get lost and are not used for the worker.
Solution
To fix this we have to modify the Webpack config. And to do that we'll use #angular-builders/custom-webpack. Go ahead and install that package.
Next, open angular.json and update projects > angular-electron > architect > build:
"build": {
"builder": "#angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./extra-webpack.config.js"
}
// existing options
}
}
Repeat the same for serve.
Now, create extra-webpack.config.js in the same directory as angular.json:
const WorkerPlugin = require('worker-plugin');
const NodeTargetPlugin = require('webpack/lib/node/NodeTargetPlugin');
module.exports = (config, options) => {
let workerPlugin = config.plugins.find(p => p instanceof WorkerPlugin);
if (workerPlugin) {
workerPlugin.options.plugins.push(new NodeTargetPlugin());
}
return config;
};
The file exports a function which will be called by #angular-builders/custom-webpack with the existing Webpack config object. We can then search all plugins for an instance of the WorkerPlugin and patch its options adding the NodeTargetPlugin.
I'm attempting to set up some tests for my react app with enzyme, mocha and chai. (I'm also using webpack). I have Karma set up for my in-browser tests but i'd like to run these tests with just node.
I'm currently getting a syntax error when it tries to run the test. I'm not sure how to resolve it.
Update: I am running my tests with es6 mocha 'components/**/*.test.js' --recursive --compilers js:babel-register
The error I get is:
8 | describe('<button />', () => {
9 | it('renders something', () => {
> 10 | const wrapper = shallow(<button />)
11 | expect(wrapper).to.be.present
12 | })
You need to set up Babel before it can handle JSX syntax.
There are two options: add the configuration to your package.json, or create a file called .babelrc that contains the configuration.
First, install babel-preset-react:
$ npm i babel-preset-react --save
Next, add the following to your package.json:
"babel": {
"presets": [ "react" ]
}
(or add that object, without the "babel" key, to .babelrc)
Another preset that you may likely want to use is babel-preset-es2015, which you can add in a similar fashion (just add it to the presets array).
More documentation on Babel configuration here and here (specifically for es2015).
I'm having quite the time trying to set up node/npm with Mocha and RequireJS. Here's what I've done.
I've created a testing/ directory, with this structure:
testing/
|
+-- package.json
|
+-- README.md
|
+-- test/
|
+-- mocha.opts
|
+-- widgets/
|
+--mywidget/
|
+-- test.js
Here is what each relevant file contains:
package.json:
{
"name":"testing-project",
"version":"2.5.0",
"description":"Testing Project",
"keywords":["test"],
"engines": { "node": ">= 0.7.0 < 0.11.0" },
"scripts" : {
"test": "./node_modules/.bin/mocha"
},
"devDependencies": {
"mocha": ">= 1.18.2",
"requirejs": ">= 2.1.11",
"should": ">= 3.2.0",
"expect.js": ">= 0.3.1"
}
}
test/mocha.opts:
--require expect.js
--require should
--require requirejs
--require mocha
--reporter spec
--ui tdd
--recursive
--growl
test/widgets/mywidget/test.js
'use strict';
var requirejs = require('requirejs');
// Also tried with: require('../../../r.js') which I downloaded from RequireJS' site
requirejs.config({
baseUrl: '../../../../',
nodeRequire: require
});
console.log('before require');
requirejs(['mywidget/trunk/src/mywidgetfile.js'], function(myObj){
console.log('after require');
var expect = require('expect.js');
// Instead of the above "requirejs['mywidget..." line, I've also tried:
// var myObj = requirejs('mywidget/trunk/src/mywidgetfile.js'); AND:
// var myObj = requirejs('../../../../mywidget/trunk/src/mywidgetfile.js');
describe('My Widget', function(){
describe('my-widget#getInfo', function(){
it('should pass this test', function(done){
expect( myObj.returnString('test') ).to.equal( 'test' );
done();
})
})
});
});
console.log('done');
It will output the console lines "before require" and "done", but as long as I have the requirejs(['mywidget... line in, it will not hit the after require. If I remove the requirejs line (and the corresponding closing brace/paren line), and instead use the direct "var myObj =" line, I get "cannot find module", and if I use the second "var myObj" line, I get "Reference Error: define is not defined".
I'm trying to package this all, for convenience for other developers, with npm, such that I'm running the command "npm test" from within the top "testing/" directory.
I've been scouring for answers and trying so many things, but I can't seem to require a file using RequireJS and have "define()" defined. I can execute tests, that's not a problem... it's just trying to insert RequireJS into the mix that is when I start having the issues.
Any help would be tremendous!
Thank you!
There are multiple problems going on in what you are showing us. You are incorrectly using both RequireJS and Mocha.
RequireJS
I am pretty sure your baseUrl is incorrect. You seem to think that Mocha's current working directory will be set to test/widgets/mywidget/ when it executes the tests in test/widgets/mywidget/test.js. That's not the case. The working directory is wherever you happen to be when you run npm test. According to your description you are in testing/ when you run it. It is not clear to me what value your baseUrl should be because you do not provide enough information in your question but I trust that from the explanation I just gave you can figure it out.
Now you may think "surely, my baseUrl is correct because when I execute requirejs(['mywidget/trunk/src/mywidgetfile.js'], function(myObj){ I don't get an error". This would be an incorrect inference. While this requirejs invocation schedules the loading of your module, RequireJS does not get the opportunity to try loading it because Mocha exits before RequireJS tries to load it. You can check this by replacing your module path with complete garbage and you won't get an error.
Once you fix this baseUrl issue, using var myObj = requirejs('mywidget/trunk/src/mywidgetfile.js') will work as you expect. So you'll be able to avoid using the asynchronous form of require (this is the form that uses an array of dependencies as the first argument). (The requirejs function you use is just an alias for the function normally called require in RequireJS' documentation.)
Mocha
Your tests are not running because Mocha does not see them. The way Mocha works is by reading all of the test files it finds and then executing them. The callbacks to each describe calls are executed right away, and the callbacks to each it calls are recorded as tests to be run. Once Mocha is done figuring out what tests exist, it runs them.
What happens with your test file is that Mocha executes it, as usual. However, there is no call to describe or it in the top scope of your test file. There are calls in your callback to requirejs but remember what I said above: RequireJS does not get the opportunity to load the module so it does not get the opportunity to run the callback. (And even if it did run it, it would be too late.) So Mocha does not see any tests and exits right away.
The Way Forward
Figure out the baseUrl you need, and then this should work:
'use strict';
var requirejs = require('requirejs');
requirejs.config({
baseUrl: <whatever value is needed here>,
nodeRequire: require
});
var myObj = requirejs('mywidget/trunk/src/mywidgetfile.js');
describe('My Widget', function() {
// etc...
You might also consider dropping RequireJS entirely from your test suite. I've written a library that works just as well in Node as in the browser. It is composed of AMD modules and is loaded by RequireJS in the browser, but I don't use RequireJS in the test suite. This is the loader I use to load my modules in Node. There's also amdefine which I've not used but should give similar capabilities.
How can I properly run jasmine tests using jasmine-node and RequireJS?
I already tried something like this, but doesnt work (CoffeeScript):
requirejs = require 'requirejs'
requirejs.config { baseUrl: __dirname + '/../' }
requirejs ['MyClasses', 'FooClass'], (MyClasses, FooClass) ->
describe "someProp", ->
it "should be true", ->
expect(MyClasses.FooClass.someProp).toEqual true
Finished in 0 seconds 0 tests, 0 assertions, 0 failures
My goal is to write modular classes using RequireJS, CoffeeScript and classes must be testable with jasmine-node (CI server).
How can I do that please?
Thank you!
EDIT:
I executing tests with command (at directory with tests):
jasmine-node ./
Jonathan Tran is right, it's the spec in the file name for me.
I have this:
"scripts": {
"install": "cake install",
"test": "node_modules/jasmine-node/bin/jasmine-node --verbose --coffee --runWithRequireJs --captureExceptions spec"
},
in my package.json and I installed jasmine-node from inside the project npm install jasmine-node
Minimal test file called RingBuffer.spec.coffee
require ["disrasher"], (mod) ->
describe "A test", ->
it "should fail", ->
expect(1).toEqual 0
It doesn't actually work at the moment because I haven't got the project hooked up with require properly I don't think. I'll post back here when it does.
If anyone is running into this, much has changed since this question was asked. The first thing to check is still that you're naming your files like thing.spec.coffee.
But if you're running the tests and still seeing the output "0 tests", you need to make a JavaScript file with your requirejs config. This must be JavaScript, not CoffeeScript.
// requirejs-setup.js
requirejs = require('requirejs');
requirejs.config({ baseUrl: __dirname + '/../' });
Then tell jasmine to use this setup file:
jasmine-node --coffee --requireJsSetup requirejs-setup.js ./
One nice thing about this is that you don't need to include the requirejs config in every spec file.
I've tested this on node v12.16, jasmine-node v3.0.0, and requirejs v2.3.6.
It seems that jasmine-node and require.js are completely incompatible. That said, it is possible to run jasmine tests on require.js modules in node using a bit of extra code. Take a look at https://github.com/geddski/amd-testing to see how.