How to write simple Jest preset - javascript

How to write own Jest preset with common beforeAll and afterAll?
I'm quite confused, seems that there is no related documentation.

There is the environment that you can extend this way:
JEST config:
module.exports = {
testEnvironment: './suites/future/jest.myEnv.js',
};
The jest.myEnv.js:
const NodeEnvironment = require('jest-environment-node');
const start = async () => {
console.log('START');
};
const stop = async () => {
console.log('STOP');
};
class TestEnvironment extends NodeEnvironment {
constructor(config) {
super(config);
}
async setup() {
await super.setup();
await start();
}
async teardown() {
await stop();
await super.teardown();
}
runScript(script) {
return super.runScript(script);
}
}
module.exports = TestEnvironment;

Related

Mock import() in jest

I'm struggling to test dynamic imports and I am wondering if there's a way to mock import() so I could simply mock the return value with Promise.resolve(mockComponent)?
The hook I want to test:
useEffect(() => {
async function setup() {
const { default: Player } = await import('#vimeo/player');
playerRef.current = new Player(
playerRef.current,
playerConfig,
);
playerRef.current.on('loaded', () => setIsLoading(false));
}
if (playerRef?.current) {
setup();
}
return () => playerRef.current?.destroy && playerRef.current.destroy();
}, [playerRef]);

How to call an exported typescript function from within javascript

I have a typescript file with imports eg:
util.ts file
import { protractor } from 'protractor'
export const waitForFile = async () => {
protractor.promise....
return await ''
}
Now helper.js file
const getUtilFunction = (func) => {
const { register } = require('ts-node');
const { compilerOptions } = require('./tsconfig.json');
register({ compilerOptions });
const result = require('./utils.ts');
return result[func];
};
const waitTillReportGenerated = async () => {
const waitForFileToDownload = getUtilFunction('waitForFileToDownload');
const file = await waitForFileToDownload('./result/result.js', 60000);
console.log(file);
}
However when we call the helper.js function it throws error that protractor is undefined.
Can someone please help me with this?
You need to convert .ts file to .js.

Keep checking connection if available in Node and clear setTimeout

In node i keep checking if connection is available if it is it will get token and store in variable but if not then catch error will be thrown and it will then execute setTimeout to try again in 2 seconds.
But i think i need a clean way to clear the setTimeout because when i log it i keep getting higher number in Symbol(asyncId) this to me feels like it keeps adding setTimeout more and more to memory?
export const getToken = async () => {
try {
if (!GLOBAL_VARS.authToken) {
await auth(`Getting token`)
}
// Do more stuff
} catch (error: any) {
tokenTimeout()
}
}
getToken()
export const tokenTimeout = () => {
setTimeout(() => {
getToken()
}, 2000)
}
Yest it will add more setTimeouts to the memory.
you can clear it like this:
export const tokenTimeout = setTimeout(() => {
getToken()
}, 2000)
export const getToken = async () => {
try {
if (!GLOBAL_VARS.authToken) {
await auth(`Getting token`)
}
// Do more stuff
} catch (error: any) {
const timeout = tokenTimeout()
}
}
getToken()
/// use it wherever you want
clearTimeout(timeout);
Memory is going to increase because of whatever you are doing with auth() and not because you are creating timeouts.
The issue I see with your code is not really using async await properly. It should look more like
const sleep = (ms) =>
new Promise((resolve) => {
setTimeout(resolve, ms);
});
export const getToken = async (count = 0) => {
try {
if (!GLOBAL_VARS.authToken) {
await auth(`Getting token`);
}
} catch (error: any) {
await sleep(2000);
if (count < 10) await getToken(++count);
else throw new Error('Taking too long to get auth token');
}
}
(async function () {
await getToken();
})();

Custom webpack resolver plugin change #meow to ./meow.js

I am trying to create a webpack resolver that will convert the import for #meow to the import of ./meow.js. I have some basic code below that shows main imports #meow and the resolver should be converting all require statements to be ./meow.js.
meow.js
module.export = 'meow';
main.js
import meow from '#meow';
console.log(meow);
Resolver.js
module.exports = class Resolver {
apply(compiler) {
compiler.hooks.module.tapPromise('Resolver', async (init, resolveContext) => {
return compiler.doResolve(compiler.hooks.module, init, './meow.js', resolveContext, () => {});
});
}
}
Here's an example I got working with webpack 4.
class Example {
constructor() {
this.name = 'Example';
}
apply(compiler) {
compiler.hooks.resolve.tapPromise(this.name, async (init, context) => {
const callback = () => {};
if (init.request.match('#')) {
init.request = './meow.js'
return compiler.doResolve(compiler.hooks.resolve, init, null, context, callback)
} else {
return callback()
}
})
}
}
module.exports = Example;
I think that it is better to utilize NormalModuleReplacementPlugin to replace all the imports that are matched to some rule.
module.exports = function(env) {
return {
plugins: [
new webpack.NormalModuleReplacementPlugin(/(.*)#meow(\.*)/, function(resource) {
// do what ever mapping
resource.request = resource.request.replace(/#meow/, `meow.js`);
})
]
};
};

sinon mock not catching calls

I am having a hard time understanding what I am doing wrong.
I have a JS class as such:
export default class A {
constructor(repository) {
this._repository = repository;
}
async process(date) {
// ...
this._repository.writeToTable(entry);
}
}
and I am attempting to write a test that mocks the repository using sinon.mock
This is what I have so far:
describe('A', () => {
describe('#process(date)', () => {
it('should work', async () => {
const repository = { writeToTable: () => {} };
const mock = sinon.mock(repository);
const a = new A(repository);
await a.process('2017-06-16');
mock.expects('writeToTable').once();
mock.verify();
});
});
});
but it always fails saying that
ExpectationError: Expected writeToTable([...]) once (never called)
I've checked (added a console.log) and it is calling the object I defined on the test.
I ran this locally and read the documentation on sinonjs.org and you seem to be doing everything right.
I tried re-writing your example using a spy and ended up with something like this to get a passing test:
import sinon from "sinon";
import { expect } from "chai";
import A from "./index.js";
describe("A", () => {
describe("#process(date)", () => {
it("should work", async () => {
const repository = { writeToTable: sinon.spy() };
const a = new A(repository);
await a.process("2017-06-16");
expect(repository.writeToTable.calledOnce).to.be.true;
});
});
});

Categories