VS code turns 'it' into 'hasUncaughtExceptionCaptureCallback'. How to disable this? - javascript

I am going through a book on Test Driven Development in React. I've never written JavaScript tests before. The author presents the following Jest code in a file titled calc.test.js:
var add = require('./calc.js')
describe('calculator',function() {
it('add two numbers',function() {
expect(add(1,2)).toEqual(3)
})
})
but VS code automatically translates it to:
const { hasUncaughtExceptionCaptureCallback } = require('process')
const { isTypedArray } = require('util/types')
var add = require('./calc.js')
describe('calculator', function () {
isTypedArray('add two numbers', function () {
hasUncaughtExceptionCaptureCallback(add(1, 2).toEqual(3))
})
})
The author states that his version uses syntax "borrowed from" jasmine. Is that why VS Code changed it? How do I turn this feature off? Jest is installed.

Seems like vscode tries to autocomplete it and expect, and auto imports the modules process and utils/types.
Even though manually importing isn't required per the jest documentation:
In your test files, Jest puts each of these methods and objects into
the global environment. You don't have to require or import anything
to use them. However, if you prefer explicit imports, you can do
import {describe, expect, test} from '#jest/globals'.
You can silence vscode warnings by explicitly importing:
import {describe, expect, test} from '#jest/globals'

Related

JavaScript/TypeScript Dynamic Imports and browsers - options

I have a relatively simple requirement to start out with.
I want to be able to load a particular UI component, based on some dynamic context. I was thinking that dynamic imports could be used for this purpose. The dynamic imports should be loaded through the Web browser (no nodeJS).
Details about what is possible with dynamic imports are very sketchy to me - at best, probably also because I'm not an expert in the field of JavaScript/TypeScript (yet).
I'm using vanilla JS at the moment and vitejs as build tool.
Here is what I have so far.
This is my main.ts file:
const getPath = () => {
if (import.meta.env.MODE === 'development') {
return 'http://127.0.0.1:3000/one.js';
} else {
return 'http://127.0.0.1:5000/one.js';
}
};
import(getPath()).then((Module) => {
Module.default();
});
This already makes vitejs barf, complaining that it cannot analyze things - but I'm ignoring that for now. The one.js file looks like this:
const hello = () => {
console.log('Hello from one');
};
export default hello;
Both run dev as run serve work with this setup, as-in, the message is printed on the browser console.
My next thing I want to see working is how one.js would be able to itself import a module and work with that. I've tried this with moment like so:
import moment from "moment";
const hello = () => {
console.log('Hello from one ', moment().format());
};
export default hello;
This errors with:
Uncaught (in promise) TypeError: Error resolving module specifier “moment”. Relative module specifiers must start with “./”, “../” or “/”.
Now I don't know whether what I want to do, is not support or that I'm just not doing it the right way. Any pointers would be appreciated.

How do I manually include "#material/drawer" into my component?

I am trying to manually include the #material/drawer npm package into my Ember app. I tried following this guide but I'm running into some weird errors in my Chrome dev console:
Uncaught SyntaxError: Unexpected token *
Uncaught ReferenceError: define is not defined
The first is from the imported node_modules/#material/drawer/index.js file and the second is from my generated shim.
My component code:
import Component from '#ember/component';
import { MDCTemporaryDrawer, MDCTemporaryDrawerFoundation, util } from '#material/drawer';
export default Component.extend({
init() {
this._super(...arguments);
const drawer = new MDCTemporaryDrawer(document.querySelector('.mdc-drawer--temporary'));
document.querySelector('.menu').addEventListener('click', () => drawer.open = true);
}
});
In my ember-cli-build.js:
app.import('node_modules/#material/drawer/index.js');
app.import('vendor/shims/#material/drawer.js');
My generated shim:
(function() {
function vendorModule() {
'use strict';
return {
'default': self['#material/drawer'],
__esModule: true,
};
}
define('#material/drawer', [], vendorModule);
})();
What exactly am I doing wrong? It almost seems as though raw ES6 code got imported rather than compiled into my JS build output.
I also read this SO post but there are too many answers and I'm not sure which to do. It seems this specific answer is what I'm trying to do but not verbatim enough.
Creating a shim only ensures that ember-cli gets an AMD module, which you then can import in your app files.
If the npm package needs a build or transpiling step beforhand, this won't work.
You need a way to get the package build within the ember-cli build pipeline.
Luckily there are addons which can take care of this for you: ember-auto-import and ember-cli-cjs-transform.
You may have also heard of ember-browserify, which does the same thing, but it's deprectaed in favor of ember-auto-import.
I'd suggest you try ember-auto-import:
ember install ember-auto-import
You then should be able to import as you tried:
import { MDCTemporaryDrawer, MDCTemporaryDrawerFoundation, util } from '#material/drawer';
No shim or app.import needed, as ember-auto-import will take care of this for you.

Jest mocking default exports - require vs import

I have seen questions referring to the mocking of default exports with jest around here, but I don't think this has already been asked:
When mocking the default export of a dependency of a module that is being tested, the tests suite fails to run if the module imports the dependency with the ES6 import statement, stating TypeError: (0 , _dependency.default) is not a function It succeeds, however, if the module uses a require().default call instead.
In my understanding, import module from location directly translates to const module = require(location).default, so I am very confused why this is happening. I'd rather keep my code style consistent and not use the require call in the original module.
Is there a way to do it?
Test file with mock:
import './modules.js';
import dependency from './dependency';
jest.mock('./dependency', () => {
return {
default: jest.fn()
};
});
// This is what I would eventually like to call
it('calls the mocked function', () => {
expect(dependency).toHaveBeenCalled();
});
Dependency.js
export default () => console.log('do something');
module.js (not working)
import dependency from './dependency.js';
dependency();
module.js (working)
const dependency = require('./dependency.js').default;
dependency();
You can use either es6 import or require js to import your js files in your jest tests.
When using es6 import you should know that jest is trying to resolve all the dependencies and also calls the constructor for the class that you are importing. During this step, you cannot mock it. The dependency has to be successfully resolved, and then you can proceed with mocks.
I should also add that as can be seen here jest by default hoists any jest.mocks to the top of the file so the order in which you place your imports does not really matter.
Your problem though is different. Your mock function assumes that you have included your js file using require js.
jest.mock('./dependecy', () => {
return {
default: jest.fn()
};
});
When you import a file using require js, this is the structure it has:
So assuming I have imported my class called "Test" using require js, and it has method called "doSomething" I could call it in my test by doing something like:
const test = require('../Test');
test.default.doSomething();
When importing it using es6 import, you should do it differently though. Using the same example:
import Test from '../Test';
Test.doSomething();
EDIT: If you want to use es6 import change your mock function to:
jest.mock('./dependecy', () => jest.fn());
the short answer for ES module if you want to use
import dependency from 'dependency'
jest.mock('dependency', () => ({
...jest.requireActual('dependency'),
__esModule: true,
default: jest.fn(),
}))
Have you tried something like this? I was dealing with the default export mocking for months until I found this.
jest.mock('./dependency', () => () => jest.fn());
The idea behind this line is that you are exporting a module that is a function. So you need to let Jest knows that it has to mock all your ./dependency file as a function, that returns a jest.fn()

WebAssembly LinkError module="env"

I'm running the tutorial on webassembly.org and now I want to run the hello.wasm from my own page.
I'm compiling the code using Emscripten as per tutorial's instructions.
Following these instructions in my index.html I'm doing:
const instantiate = (bytes, imports = {}) =>
WebAssembly.compile(bytes).then(m =>
new WebAssembly.Instance(m, imports)
)
fetch('hello.wasm')
.then(response => response.arrayBuffer())
.then(bytes => instantiate(bytes, {}))
But I get this error:
So I tried to use WebAssembly.instantiate() from the MDN docs with this code:
const instantiate = (bytes, imports = {}) =>
WebAssembly.compile(bytes).then(m =>
WebAssembly.instantiate(m, imports)
)
And I get a different one:
Any idea how to fix it?
It wasn't clear from your question, but further comments explain that you leave the import object as {}, leading instantiation to fail. WebAssembly uses a double namespace, where the import object fulfills the WebAssembly.Module's imports. Each import is specified as module+field+kind, which the JavaScript import object must fulfill.
Emscripten already generates HTML+JS which loads hello.wasm for you, including the WebAssembly import object. What Emscripten generates is pretty big because it emulates an OS. The import object supplies all the syscalls (to JavaScript). You'd have to pass these in for the example to work... or just use the ones Emscripten already generated.
The code you're using is expecting a module called env. Emscripten contains code such as:
let importObject = {
env: { foo: () => 42, bar: () => 3.14 }
};
That's the double namespace I mentioned earlier: env is a module, and foo / bar are fields. Their type is function. WebAssembly supports other kinds of imports and exports: table, memory, and global.
Missing a single module, or a module's field, or mismatching the kind, leads to instantiation failure as you're getting.
Apparently, your example module wants to import something from a module named "env". However, the imports object you provide is empty. To make instantiation of your module succeed you need to provide an imports object of the form {env: {...}}, where the dots are properties corresponding to every single import made from "env".

Writing tests for javascript module using webpack's require.ensure function

I am running mocha tests on my server, testing source scripts an isolated unit test manner.
One of the scripts I am testing makes a call to Webpack's require.ensure function, which is useful for creating code-splitting points in the application when it gets bundled by Webpack.
The test I have written for this script does not run within a Webpack context, therefore the require.ensure function does not exist, and the test fails.
I have tried to create some sort of polyfill/stub/mock/spy for this function but have had no luck whatsoever.
There is a package, webpack-require, which does allow for the creation of a webpack context. This can work but it is unacceptably slow. I would prefer to have some sort of lightweight polyfill targeting the require.ensure function directly.
Any recommendations? :)
Here is a very basic starting point mocha test.
The mocha test loads a contrived module containing a method which returns true if require.ensure is defined.
foo.js
export default {
requireEnsureExists: () => {
return typeof require.ensure === 'function';
}
};
foo.test.js
import { expect } from 'chai';
describe('When requiring "foo"', () => {
let foo;
before(() => {
foo = require('./foo.js');
});
it('The requireEnsureExists() should be true', () => {
expect(foo.requireEnsureExists()).to.be.true;
});
});
Ok, I finally have an answer for this after much research and deliberation.
I initially thought that I could solve this using some sort of IoC / DI strategy, but then I found the source code for Node JS's Module library which is responsible for loading modules. Looking at the source code you will notice that the 'require' function for modules (i.e. foo.js in my example) get created by the _compile function of NodeJs's module loader. It's internally scoped and I couldn't see an immediate mechanism by which to modify it.
I am not quite sure how or where Webpack is extending the created "require" instance, but I suspect it is with some black magic. I realised that I would need some help to do something of a similar nature, and didn't want to write a massive block of complicated code to do so.
Then I stumbled on rewire...
Dependency injection for node.js applications.
rewire adds a special setter and getter to modules so you can modify their behaviour for better unit testing. You may
inject mocks for other modules
leak private variables
override variables within the module.
rewire does not load the file and eval the contents to emulate node's require mechanism. In fact it uses node's own require to load the module. Thus your module behaves exactly the same in your test environment as under regular circumstances (except your modifications).
Perfect. Access to private variables is all that I need.
After installing rewire, getting my test to work was easy:
foo.js
export default {
requireEnsureExists: () => {
return typeof require.ensure === 'function';
}
};
foo.test.js
import { expect } from 'chai';
import rewire from 'rewire';
describe('When requiring "foo"', () => {
let foo;
before(() => {
foo = rewire('./foo.js');
// Get the existing 'require' instance for our module.
let fooRequire = moduletest.__get__('require');
// Add an 'ensure' property to it.
fooRequire.ensure = (path) => {
// Do mocky/stubby stuff here.
};
// We don't need to set the 'require' again in our module, as the above
// is by reference.
});
it('The requireEnsureExists() should be true', () => {
expect(foo.requireEnsureExists()).to.be.true;
});
});
Aaaaah.... so happy. Fast running test land again.
Oh, in my case it's not needed, but if you are bundling your code via webpack for browser based testing, then you may need the rewire-webpack plugin. I also read somewhere that this may have problems with ES6 syntax.
Another note: for straight up mocking of require(...) statements I would recommend using mockery instead of rewire. It's less powerful than rewire (no private variable access), but this is a bit safer in my opinion. Also, it has a very helpful warning system to help you not do any unintentional mocking.
Update
I've also seen the following strategy being employed. In every module that uses require.ensure check that it exists and polyfill it if not:
// Polyfill webpack require.ensure.
if (typeof require.ensure !== `function`) require.ensure = (d, c) => c(require);

Categories

Resources