How to handle UnhandledPromiseRejectionWarning in simple Mocha Unit Tests - node.js

simple mocha, nodejs unit test problem. I have a simple utilties class reading files from the local fs with fs-extra. The class is called FileUtils, takes a path and tries toi return the context by default ion utf-8. Simple:
async readFileContent(fqFileName, encoding='utf-8'){
return fse.readFile(fqFileName,encoding)
.then(content => content)
.catch(any=>{
throw any
})
}
My unit test simply requires the class FileUtils and invokes the method by calling
it.only('accepts an html template to compile', () => {
let fixture = path.resolve(__dirname, '../_fixtures/100_tplWithDynamicBlocks.html')
fileUtils.readFileContent(fixture)
.then(content => {
console.log(content) /* forget */
content.should.not.be.null
})
})
Working fine, everything is ok. But when I change the path to an invalid/non-existing-one, mocha is not getting aware of the error, only warning me, that unhandled promise rejections will exit the node processs in the future.
So my question is, how can I tell mocha that this test should be marked as failed without implementing any kind of catch signature, or better how should I implement the service method that mocha recognizes the missing file(or whatever) access.
Service implementation has to throw the error of a non-existing path (or any other error), but what is the best way to pass these errors to mocha without writing lines of unneccesary code mocha-framework is already doing?

You can handle the error with catch method after the then. Inside the method you can write the assert.

Related

Can I get Jest test instance id or context

Suppose my test setup has the following pattern:
Build a model for this test
Initialize some application based on this model
Test the functioniality in the application
As part of #3, there are some async functions which can be run.
I have thousands of tests and want to create a safeguard against leaks of async functions into other tests- in other words, developers who forget to await for the result
My idea is as follows - Implement an afterEach in a global context which would check if an applcation instance was created for this test. If it was, I can catch all open async functions from here, and throw an error
To do this, I would need to have a testId instance or test context to which I can register the app instance when creating it for tests.
If we were using jasmine and old ES5 syntax, jasmine has a userContext feature which would make this easy:
it('some test', async function(){
this.appInstance = createAppInstance(model)
...
})
afterEach(function(){
if(this.appInstance){
...
}
})
Is there a way to do something like this in jest?

TestCafe: import tests from another file into the current fixture

I have a file tests.js that contains some test(...) definitions. I want to reuse these tests across multiple fixtures, preferably without making any modifications to the original code.
So I wrote a main.js that defines a fixture and imports tests.js, thereby "assembling" a test suite. (In case that works, I could write different driver files with different fixtures, importing the same tests.js from within each.)
However, I'm getting a test is not defined error when trying to execute main.js:
C:\Windows\Temp\dummy>testcafe chrome main.js --debug-on-fail
ERROR Cannot prepare tests due to an error.
ReferenceError: test is not defined
at Object.<anonymous> (C:\Windows\Temp\dummy\tests.js:1:1)
at Object.<anonymous> (C:\Windows\Temp\dummy\main.js:7:1)
Type "testcafe -h" for help.
Minimal sample:
// tests.js
test('wait', async t => {
await t.wait(1);
});
// main.js
fixture `here goes the name`
.page("http://localhost:3000")
.beforeEach(async t => {
// do stuff
});
import "./tests";
/*
trick testcafe to scan the file;
based on https://github.com/DevExpress/testcafe/issues/2889#issuecomment-423859785
test();
*/
I already tried:
removing the block comment hack (test();) - which gives ERROR No tests to run. Either the test files contain no tests or the filter function is too restrictive.
moving the tests.js import to the top - still gives test is not defined
importing testcafe from within main.js and tests.js - same error
Is there a way to make the test function "visible" to other files imported by the testcafe entrypoint file? Or will I actually need to modify my tests.js file in order to get this working? Maybe by adding the test definitions into a method, and invoking it from within main.js - as in the original code sample of this issue?
TestCafe doesn't allow calling fixture and test functions outside the test scope. You can wrap your tests from the tests.js file in a function and call this function in the main.js file:
// tests.js
export default function () {
test('Test 1', () => {});
test('Test 2', () => {});
test('Test 3', () => {});
}
// main.js
import defineTests from './tests';
defineTests();
See also: Organize Tests
Try to add the option --disable-test-syntax-validation on the TestCafe command-line
(works only in latest TestCafe version).

Making assertions on Jest manual mocks

I'm having some trouble with manual Jest mocks and could use some help.
The file I am testing looks something like this:
import withTranslation from '../utils/withTranslation'
withTranslation('test')
I'm mocking a module in a test file like this.
import withTranslation from '../utils/withTranslation'
jest.mock('../utils/withTranslation')
// tests here
I have the manual mock at ../utils/__mocks__/withTranslation.js with the following code:
const impl = (...args) => {
console.log('in mock', args)
return args
}
export default impl
When the test runs, the mock is used and I can see the console log. So far so good.
However, I want to be able to make assertions on the usage of withTranslation when it is mocked. For example, expect(withTranslation).toHaveBeenCalledWith('test').
So, I change the manual mock to be a Jest mock function with the same implementation as before.
const impl = (...args) => {
console.log('in mock 1', args)
return args
}
// only difference is wrapping in jest.fn()
export default jest.fn(impl)
When the test runs now, a generic Jest mock function is used and I DO NOT see the console log, so my fake implementation is never called. Any ideas?
The code in my question is correct. The reason this was happening is because my test suite had a global beforeEach which was calling jest.resetMocks(). Hopefully this saves someone a few hours.
The function withTranslation in the actual module is already replaced with the mock before the test begins and this replacement is not done via reference. Hence when you assert the mock withTranslation the assertion fails because the mocked function is never called but rather the withTranslation method in the actual module is called.
Your console log still appears because as I said above the "real" module's function has already been replaced with the mock.
So import the actual withTranslation and assert it and it will resolve your problem.
Credit to this answer.

typescript replaceent for require inside a function in nodejs

I trying to convert a nodejs project to TypeScript and while mostly I did not faced really difficult obstacles during this process, the codebase has few gotchas like this, mostly in startup code:
function prepareConfiguration() {
let cloudConfigLoader = require('../utils/cloud-config');
return cloudConfigLoader.ensureForFreshConfig().then(function() {
//do some stuff
});
}
I may be need just an advice on which approach for refactoring this has less code changes to be made to make it work in TypeScript fashion.
In response to comments, more details:
That require loads the node module, not a JSON file. From that module the ensureForFreshConfig function contacts with a cloud service to load a list of values to rebuild a configuration state object.
Problem is that mdule was made in standard node approach of "module is isngleton object" and its independencies include auth component that will be ready only when the shown require call is made. I know it is not best a way to do so..
Typesript does not allow "mport that module later" except with dynamyc import which is problematic as mentiond in comment.
The "good" approach is to refactor that part of startup and make the ensureForFreshConfig and its dependency to initiate its ntenras on demand via cnstructors.. I just hoped ofr some soluiton to reduce things to be remade durng this transition to the TypeScript
import { cloudConfigLoader } from '../utils/cloud-config'
async function prepareConfiguration() {
await cloudConfigLoader.ensureForFreshConfig()
// do some stuff
// return some-stuff
}
The function is to be used as follows.
await prepareConfiguration()

Changing mocha tests to jest tests

I'm having trouble changing my mocha tests to jest tests.
I have three test files with three classes: FirstTestGroup, SecondTestGroup and ThirdTestGroup, each with a static execute method, that contains some tests, like this:
class FirstTestGroup {
execute(params) {
describe('some tests', function tests() {
it('one test', () => {
// uses params
});
...
});
...
}
}
Each of those execute methods use the same parameters. These parameters are created in an async before call, like shown bellow.
describe('My Tests', function testSuite() {
let params;
before('param creation', async function asyncFunc() {
// creates params asynchronously
});
it('should pass all', () => {
FirstTestGroup.execute(params);
SecondTestGroup.execute(params);
ThirdTestGroup.execute(params);
});
});
The it('should pass all', ...) is needed because everything inside a describe is run instantly, so params would be passed as null without it. This works in mocha because "it"s can be nested, but apparently this is not the case for jest.
I could make the beforeAll (equivalent of before in jest) be called each time before a test group is run, but I didn't want to do that as this seems inefficient.
I could also place the code inside the before call before the describe('My Tests', ...) is defined. This seems wrong as this should be part of the describe only.
I couldn't find anything in the jest documentation that could help me with that.
Am I doing something wrong? Is there a way to achieve this using jest, even if I have to restructure the tests? But I'd like to keep the tests in different files.
This is my first question here, so please tell me if more info is needed as I'm not used writting here.
Have you tried Jest-Codemods yet?
Jest-Codemods allows you to convert your Mocha, AVA, Jasmine tests into equivalent Jest tests. It would also help you migrate assertion libraries such as Chai and Expect.
The way you do it:
Install jest-codemods with npm install -g jest-codemods
Go to your project and execute jest-codemods
It will ask you Which test library would you like to migrate from?
Select Mocha by using arrow keys (As you want to migrate from Mocha)
Next, It will ask you Will you be using Jest on Node.js as your test runner?
Select Yes, use the globals provided by Jest (recommended)
Last, You need to provide file name on which you are working to migrate from Mocha to Jest.
And you are done!
It will automatically migrate your code from Mocha to Jest. No need to touch code. That's one of the most powerful feature of Jest which would save your time and you don't need to worry about changing mocha tests to jest tests.

Resources