Since we've switched to generators I haven't been able to find a coverage tool to support this.
We use generators both in our code and in the mocha tests themselves.
We have enabled generators within the mocha tests by using co-mocha.
The only option I have in mind would be to transpile the tests instead of running them in their harmony mode.
Unit-coverage have basic harmony support.
Details here.
But, I can't use this tool correctly: I have error, when use class.
Awhile back co-mocha worked nicely for me. Later on in a new codebase it didn't. After some digging I found that mocha simply isn't handling promises properly anymore and it's probably related to node 5; I've logged a ticket.
With promise handling working properly, you theoretically shouldn't need to monkeypatch mocha to use generators. Simply using co.wrap() like so should work:
it('should yield in the generator', co.wrap(function*() {
yield aPromiseReturningFunction();
yield aGeneratorFunction();
}));
In the meantime, I've written a lil utility function that wraps a generator using co.wrap() and passes done as the then and catch handlers to the promise it returns:
function done(gen) {
const wrapper = co.wrap(gen);
return function(done) {
return wrapper.call(this, done).then(done).catch(done);
};
}
Then I do this:
it('should yield in the generator', done(function*() {
yield aPromiseReturningFunction();
yield aGeneratorFunction();
}));
Related
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?
I'm used to do mocking (actually, faking, but, whatever) with Sinon.js by using withArgs extensively to conditionally return the fake value. And now I'm trying to migrate to Jest and I'm can't find anything similar in the mock API.
What I want:
const t = sinon.stub();
t.withArgs('foo').returns('bar');
console.log(t('foo')); // 'bar'
console.log(t('qux')); // undefined
It seems that the only way to do that in Jest is by using mockImplementation, which means that I must write the arg matcher by hand.
Is there a better way of doing this in Jest?
So far, there isn't any Jest builtin method.
There is an issue opened here and a feature proposal here.
Based on this question, there is a third party library that does something similar: https://github.com/timkindberg/jest-when
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()
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.
I'm working with selenium to write a test suite. The project is in node. I want to refactor the code into a BDD/cucumber model. It looks like using cucumber-js, asynchronous code inside step definitions is not being executed when I run a feature.
Currently I'm using Mocha to manage all the Promises returned from the selenium library and ensure all the asynch operations are run. There is an alternate Cucumber library (gherkin-mocha) that is much older and less maintained that might work.
How can I run asynch operations inside Cucumber steps? Is it possible to use Mocha alongside this?
I figured out the problem.
Step definition methods take a regex and a function. The function parameter can take a callback which it needs to call at the end of its execution. My previous code looked like this
this.Given(/I click something/, function(done) {
// do stuff
done();
}
To use promise and asynch behavior, omit the "done" parameter:
this.Given(/I click something/, function() {
// do stuff
return Promise.resolve();
}