ES6 imports are not called - javascript

I got problem with this code:
/* src/app.js */
import axios from 'axios'
export const run = async () => {
console.log(axios)
}
/* test/app.js */
import {run} from ../src/app
describe('#run', () => {
it('should work', function () {
run()
})
})
When I run the code I get this error:
ReferenceError: axios is not defined
I'm also using Babel, but I don't think it's relevant.
I really don't get why axios is not defined there. With old-style require syntax it works correctly, why it doesn't with ES6?
Code is run with Node.js.

Related

Why are dynamic imports unexpectedly coupled between tests when using mock-fs?

I'm trying to use mock-fs to unit test code which uses ES6 dynamic imports.
There seems to be an unexpected coupling between tests when I'm using dynamic imports, even though I call restore() after each test. It appears as though fs.readFile() behaves as expected between tests (no coupling), but await import() has coupling (it returns the result from the previous test).
I've created a minimal Jest test case that reproduces the issue. The tests pass individually, but not when run together. I notice that if I change the directory value so it's different between each test, then they pass together.
Can you help me understand why this doesn't work, whether it's a bug, and what I should do here?
import path from 'path';
import { promises as fs } from 'fs';
import mockFs from 'mock-fs';
const fsMockModules = {
node_modules: mockFs.load(path.resolve(__dirname, '../node_modules')),
};
describe('Reproduce dynamic import coupling between tests', () => {
afterEach(() => {
mockFs.restore();
});
it('first test', async () => {
const directory = 'some/path';
mockFs({
...fsMockModules,
[directory]: {
'index.js': ``,
},
});
await import(path.resolve(`${directory}/index.js`));
//not testing anything here, just illustrating the coupling for next test
});
it('second tests works in isolation but not together with first test', async () => {
const directory = 'some/path';
mockFs({
...fsMockModules,
[directory]: {
'index.js': `export {default as migrator} from './migrator.js';`,
'migrator.js':
'export default (payload) => ({...payload, xyz: 123});',
},
});
const indexFile = await fs.readFile(`${directory}/index.js`, 'utf-8');
expect(indexFile.includes('export {default as migrator}')).toBe(true);
const migrations = await import(path.resolve(`${directory}/index.js`));
expect(typeof migrations.migrator).toBe('function');
});
});

Node v12: module is not defined when exporting

I export a function in my index.js
module.exports = {
myFunc
};
and I run node index.js I got error of
module.exports = {
^
ReferenceError: module is not defined
Is there any new way to exports something in node version 12?
Looks like your app is using es-modules which means you need to use export/import instead of module.exports/require. Here's how you could fix it:
const myFunc = () => {
console.log("test");
}
export {myFunc};
You can then import the function using:
import {myFunc} from './index.js'
myFunc();

Mock Service Worker / Node isn't working and I can't see why

If anyone can spot whatever's wrong with this code, I'd really appreciate. Not seeing an issue myself, but it's failing.
import React from "react"
import {setupServer} from "msw/node"
import {rest} from "msw"
describe("mocking apis", () => {
const testCall = jest.fn()
const server = setupServer(
...[
rest.get("/test", (req, res, ctx) => {
console.log('This line is never run')
testCall()
return res(ctx.json({message: "success"}))
}),
]
)
test("test", async () => {
server.listen()
fetch("/test", {method: "GET"})
expect(testCall).toHaveBeenCalled()
server.close();
})
})
I also had this problem. After a while I realized the cause. In my src/setupTests.js file I had:
import { enableFetchMocks } from 'jest-fetch-mock';
...
enableFetchMocks();
So, fetch() was not being called at all.
I made 3 changes to the posted code to get it to work:
Import and call disableFetchMocks().
Add await before fetch(....
Change the URL to http://localhost/test, to address a test error that said I needed to use an absolute URL.
Here is the working code (cleaned up to AirB&B style by PyCharm):
import { setupServer } from 'msw/node';
import { rest } from 'msw';
import { disableFetchMocks } from 'jest-fetch-mock';
describe('mocking apis', () => {
const testCall = jest.fn();
const server = setupServer(
...[
rest.get('http://localhost/test', (req, res, ctx) => {
console.log('This line is run');
testCall();
return res(ctx.json({ message: 'success' }));
}),
],
);
test('test', async () => {
disableFetchMocks();
server.listen();
await fetch('http://localhost/test', { method: 'GET' });
expect(testCall).toHaveBeenCalled();
server.close();
});
});
When you run your tests these run in a node environment, in this fetch function does not exist (it means: global.fetch) for that reason you need to make a polyfill.
I recommend installing the npm package 'whatwg-fetch'
npm install whatwg-fetch
and use it like this:
import 'whatwg-fetch';
This video could help

Proxyquire shows error "Cannot find module"

I'm trying to use proxyquire to replace a private function for testing in my Meteor app.
Meteor 1.6.1
meteortesting:mocha#1.1.2
In my parentFunction.js:
import { some function } from 'anotherFile';
function childFunction() {
...
return someValue;
}
export default function parentFunction() {
return childFunction()
}
In my test file:
const proxyquire = require('proxyquire');
if (Meteor.isServer) {
...
describe('parentFunction', () => {
it('uses the mocked child function', () => {
const testThing = proxyquire('./parentFunction', {
'childFunction': () => ({ 'name': 'bob' }),
});
});
}
parentFunction.js is in the same folder as my test file, and just to double check the path, I made sure this works:
import parentFunction from './parentFunction';
But when I run the test, I'm seeing an error:
Error: Cannot find module './parentFunction.js'
What am I doing wrong? I've tried an absolute path, that didn't work. And as far as I can see from the documentation a relative path in the file where proxiquire is required, should be fine.
Thanks for any help!

Require not behaving as expected

I'm using the proxyquire library, which mocks packages on import.
I'm creating my own proxyquire function, which stubs a variety of packages I use regularly and want to stub regularly (meteor packages, which have a special import syntax):
// myProxyquire.js
import proxyquire from 'proxyquire';
const importsToStub = {
'meteor/meteor': { Meteor: { defer: () => {} } },
};
const myProxyquire = filePath => proxyquire(filePath, importsToStub);
export default myProxyquire;
Now I want to write a test of a file which uses one of these packages:
// src/foo.js
import { Meteor } from 'meteor/meteor'; // This import should be stubbed
export const foo = () => {
Meteor.defer(() => console.log('hi')); // This call should be stubbed
return 'bar';
};
And finally I test it like this:
// src/foo.test.js
import myProxyquire from '../myProxyquire';
// This should be looking in the `src` folder
const { foo } = myProxyquire('./foo'); // error: ENOENT: no such file
describe('foo', () => {
it("should return 'bar'", () => {
expect(foo()).to.equal('bar');
});
});
Note that my last 2 files are nested inside a subfolder src. So when I try to run this test, I get an error saying that the module ./foo couldn't be found, as it is being looked for in the "root" directory, where the myProxyquire.js file is, not the src directory as expected.
You might be able to work around that (expected) behaviour by using a module like caller-path to determine from which file myProxyquire was called, and resolving the passed path relative to that file:
'use strict'; // this line is important and should not be removed
const callerPath = require('caller-path');
const { dirname, resolve } = require('path');
module.exports.default = path => require(resolve(dirname(callerPath()), path));
However, I have no idea of this works with import (and, presumably, transpilers).

Categories

Resources