mock module which does not exist? - node.js

When i run my mocha tests in my meteor app by:
node_modules/.bin/mocha --compilers js:babel-core/register //..opts
i get a problem when my module under test wants to import:
import { Meteor } from 'meteor/meteor';
So i tried to mock it with mockery:
mockery.enable();
moduleUnderTest = '../moduleUnderTest';
mockery.registerAllowable(moduleUnderTest);
meteorMock = {};
mockery.registerMock('Meteor', meteorMock);
Unfortunately the module cannot be found
Error: Cannot find module 'meteor/meteor'
So the mocking of Meteor cannot be done.
Is there a way how i can fake the location meteor/meteor?
(Alternate Solution: If i can get access to the Meteor Environment in my mocha test)

If you look at the documentation, you'll see that .registerAllowable takes a string, not a module. You also need to give the exact module name that you are mocking, and provide a fake module with the values you want.
So:
var mockery = require("mockery");
mockery.enable();
mockery.registerAllowable("./moduleUnderTest");
// We want Meteor to have the value "foo". You probably want something
// different.
var meteorMock = { Meteor: "foo" };
// We mock 'meteor/meteor' because that's what's imported.
mockery.registerMock('meteor/meteor', meteorMock);
If you think about it, what you were doing cannot work. You were requiring the module before Mockery is configured for mocking 'Meteor', so Node loads your module, and then tries to load Meteor before the mock is available, and you get a failure.
Moreover, Meteor mocks modules so when you register a mock, you have to give a module name, not the name of a variable.

Related

jest test with xmljs GLOBAL not defined

currently I am writing an App using
NodeJS v13.12.0
Jest 25.4.0
xmljs 0.3.2
typescript 3.8.3
ts-jest 25.4.0
This App should mimic a CalDAV Server. For this reason, I rely on the module xmljs, which is (after my research) the only module giving me a direct path method for finding properties in the XML.
In the node Container, the App runs fine without any errors. But When I start a test with Jest, the test fails with the error
ReferenceError: GLOBAL is not defined
at node_modules/xmljs/core.js:46:2
at Object.<anonymous> (node_modules/xmljs/core.js:176:3)
at node_modules/xmljs/XmlParser.js:3:11
at Object.<anonymous> (node_modules/xmljs/XmlParser.js:204:3)
I now know, that this error originates from the xmljs module trying to set the GLOBAL variable, which in NodeJS resolved to global. But this does not happen in jest.
My code works like following:
import XmlParser = require("xmljs");
/*
* data is the body of a PROPFIND request
*/
new XmlParser({ strict: true }).parseString(data, (err, xmlNode) => {
// omit err
xmlNode.path(["propfind", "prop"], true);
const propertiesObj: XmlNode[] = childs[0].children;
const properties: string[] = [];
Object.keys(propertiesObj).forEach(n => {
properties.push(n);
});
logger.silly("Returning properties: %O", properties);
});
Can anyone
Show me a module to use instead without requiring huge modifications of my code
Which supports a pure js implementation without using node-gyp (since it may be used on windows server)
Show me how to make a workaround in jest to spoof this GLOBAL variable being set in xmljs
I appreciate your help
You can set the value of GLOBAL in the setup of your tests. It seems that the GLOBAL variable is the deprecated form of the global in node.
In your jest.config.js file you can add a setup file through the setupFiles option:
module.exports = {
[...] // Other configurations
setupFiles: ['<rootDir>/define-deprecated-global.js']
};
And in the file define-deprecated-global you can define the GLOBAL variable as:
global.GLOBAL = global;

Writing WebSocket client with TypeScript running both on browser and Node.JS

I am writing a typescript code that would run in a web-browser and would be tested with Node.JS.
My client code looks like below.
import * as WebSocket from 'ws';
export class SomeClient {
constructor(url) {
this.ws = new WebSocket(url);
}
send(data: any) {
this.ws.send(data);
}
}
I had no problem in writing a unit test code using mocha/chai.
However, trying to bundle this code, browserify includes all the 'ws' node module and the size of the output file is almost 100kb. If I remove the import 'ws' statement, the bundle file size shrinks less than 1kb. But, in this case, the Node.JS test complains with 'WebSocket is not defined' error.
I think, this is because WebSocket is natively supported in web browsers but not supported in Node.JS and the external 'ws' module is required to run properly.
How can I make a bundle with the minimum size for web browsers yet can use in Node.JS???
Try isomorphic-ws:
npm i isomorphic-ws -s
or universal-websocket-client:
npm install --save universal-websocket-client
I struggled with the same problem, best solution I could find was to use isomorphic-ws create a decs.d.ts in my typescript rootDir with the following content
declare module "isomorphic-ws";
and then use it inside typescript like that:
import { IsoWebSocket } from "isomorphic-ws";
var ws = new IsoWebSocket("wss://echo.websocket.org") as WebSocket;

how to use node module with es6 import syntax in typescript

I have a typescript project which has uses one of our node modules which normally runs in our front-end. We are now looking to use this module in node on our server.
The module uses es6 import syntax import { props } from 'module/file'
When I include a ref in typescript using either of the following methods
import { props } from 'module/file';
var props = require('module/file');
I get the following error from typescript
unexpected token 'import'
(function (exports, require, module, __filename, __dirname) { import
It's a big job to re-write the module, and I've tried using babel with babel-plugin-dynamic-import-node, as well as SystemJS.
The problem with these systems is that they are all asynchronous, so I can't import the module in the standard fashion, so I would need to do a whole bunch of re-write when we get to the point that I can use import natively in node.js.
I can't be the first person to have this issue, but I can't seem to find a working solution.
--------------- update with set-up -------------
In response to #DanielKhoroshko's response. The original module I am trying to import is normally packaged by webpack in order to use on the front-end. I am now trying to use this same module both server-side and in the front-end (via webpack on the front-end) without re-writing the imports to use require and without running webpack to bundle the js to use on the server.
To be clear, the original module is written in JS, our service which is trying to use this module is written in typescript and transpiled. When the typescript tries to require the old module which uses import, it is at this point that we are running into the issue.
------------------ some progress ---------------------------
I've made some progress by creating a file in my imported module which uses babel in node.js to transpile the es6 code into commonJS modules.
I've done this via
var babel = require("babel-core")
var store = babel.transformFileSync(__dirname + '/store.js', {
plugins: ["transform-es2015-modules-commonjs"]
});
module.exports = {
store: store.code
}
I can now get the store in my new node.js project. However, the submodules within the store.js file are not included in the export.
So where in my module, it says
import activities from './reducers/activities';
I now get an error
Cannot find module './reducers/activities'
How can I get babel to do a deep traversal to include the sub-directories?
unexpected token 'import' means you are running es-modules code in environment that doesn't support import/export commands. If you are writing you code in TypeScript it's important to transpile it first before building for the browser or use ts-node to run it server-side.
If you are using webpack there are loaders ts-loader and awesome-typescript-loader
What is your setup?
To describe the module you would need to create an activities.d.ts file in the same folder where the js-version (I understood it is called activities.js and containers a reducer) resides with the following (approx.):
import { Reducer } from 'redux';
export const activities: Reducer<any>;
#Daniel Khoroshko was right in many ways, I ended up finding #std/esm which lets you import es6 modules and worked find for fetching the included imports as well.
var babel = require('babel-register')({
presets: ["env"]
});
require = require('#std/esm')(module);
var store = require('ayvri-viewer/src/store');
exports.default = {
store: store
}
I had to run babel to get a consistent build from es6 to node compatible es5

How to test Angular2 pipe in nodejs with mocha without karma

I'd like to be able to test an Angular2 pipe purely in nodejs environment without including karma etc.
It is possible to use typescript files as test suites for mocha
https://templecoding.com/blog/2016/05/05/unit-testing-with-typescript-and-mocha/
But when I have a import {Pipe} from '#angular/core' it gives me
/Users/foo/node_modules/#angular/core/src/util/decorators.js:173
throw 'reflect-metadata shim is required when using class decorators';
^
reflect-metadata shim is required when using class decorators
Even if I write require('reflect-metadata') in my test file it still breaks with the same error.
Angular internally has this check:
(function checkReflect() {
if (!(Reflect && Reflect.getMetadata)) {
throw 'reflect-metadata shim is required when using class decorators';
}
})();
And after requireing reflect-matadata I indeed have Reflect on the global object, however it still doesn't work...
Anyway is there a way to test an Angular pipe purley in nodejs with mocha?
I'm using webpack to bundle the app so the file I'm requring in my test file looks like this:
import {Pipe} from '#angular/core';
#Pipe({
name: 'filterBy'
})
export class FilterByPipe {
transform(items = [], prop, val) {
return items.filter(someFilteringAlgorithm(prop, val));
}
}
I didn't test pipes yet, but here a post that explain how to test Angular 2 application in Node with Mocha. But It use Webpack instead of ts-node : Here
Hope It can help.

Declare test dependency using Npm.depends

I would like to know how to declare a dependency on an Npm module in Meteor only in test.
While testing a package, I can easily declare a Npm dependency in package.js like this:
Npm.depends({
...
'sinon': '1.15.3'
...
});
But I am only using sinon in test, and I want to make it explicit.
I tried the following with no success.
Package.onTest(function(api) {
// # 1
// can't do this because it is not a meteor module
api.use('sinon');
// # 2
// can't because I have other production Npm dependencies
// and Meteor only allows one `Npm.depends` call per `package.js`.
// Also, not sure if nesting Npm.depends() is allowed at all.
Npm.depends({
'sinon': '1.15.3'
});
});
Any suggestions?
The only way to do this is to wrap sinon into a package and api.use it. You can do the following:
$ meteor create --package sinon
Replace the contents of packages/sinon with the following:
package.js
Package.describe({
summary: 'Standalone test spies, stubs and mocks for JavaScript.'
});
Package.onUse(function(api) {
api.versionsFrom('1.0.4');
api.export('sinon', 'server');
api.addFiles('sinon.js');
api.addFiles('post.js');
});
post.js
sinon = this.sinon;
sinon.js
Download the latest version from here.
Finally in the package you are testing, you can add api.use('sinon'); in your Package.onTest.
As an alternative to making your own package, you can just use one of the community versions available here.

Resources