Jasmine avoid beforeEach for certain tests - jasmine

Is there a way to NOT execute beforeEach function only for certain tests ('it' blocks). Lets say I have 10 it blocks, I do not want beforeEach to be executed for two of the blocks. Is it possible?

You can group specs which you want to run with beforeEach into a separate describe:
it('should 1...', function () {});
it('should 2...', function () {});
describe('group', function () {
beforeEach(function () {
// ...
});
it('should 3...', function () {});
it('should 4...', function () {});
// ...
});

I currently managed this with a work around as follows:
var executeBeforeEach = true;
function beforeEach() {
if(!executeBeforeEach) return;
//your before each code here.
}
describe('some test case 1', function(){
it('Start', function(){
//this is a dummy block to disable beforeeach for next test
})
it('The test that does not need beforeEach', function(){
//this test does not need before each.
})
it('Start', function(){
//this is a dummy block to enable beforeeach for next test
})
})
But, I am wondering if there is a more elegant way!?!

Related

How to skip a cypress test in beforeeach hook?

I want to skip and allow tests in the before each hook as follows
beforeEach(() =>{
if(Cypress.mocha.getRunner().suite.ctx.currentTest.title === `Skip this`){
// skip the first test case only but run the second one [How?]
}
});
it(`Skip this`, () => {
});
it(`Don't skip this`, () => {
});
In the place of [How?] I tried using the following:
cy.skipOn(true) from the cypress skip-test plugin but apparently it skips the beforeEach hook not the test itself.
this.skip() but apparently this is not a valid function. Also, if I changed the beforeEach from an arrow function expression, the skip function works but it skips the whole suite and not just the desired test case.
Any ideas?
Change the function type from arrow function to regular function, then you can use the built-in Mocha skip() method.
beforeEach(function() {
if (condition) {
this.skip()
}
})
Your code sample will look like this:
beforeEach(function() { // NOTE regular function
if (Cypress.mocha.getRunner().suite.ctx.currentTest.title === 'Skip this') {
this.skip()
}
});
it(`Skip this`, () => {
});
it(`Don't skip this`, () => {
});
Or use the Mocha context you already use for test title
beforeEach(() => { // NOTE arrow function is allowed
const ctx = Cypress.mocha.getRunner().suite.ctx
if (ctx.currentTest.title === 'Skip this') {
ctx.skip()
}
});
afterEach()
If you have an afterEach() hook, the this.skip() call does not stop it running for the skipped test.
You should check the condition inside that hook also,
afterEach(function() {
if (condition) return;
... // code that should not run for skipped tests.
})

Mocha .then(done) doesn't work as expected

This question is not about a problem which I can't solve, it is just a curiosity. I'm not very experienced with Mocha, but there's something interesting I've stumbled upon already.
What I want is to use done() to tell Mocha the promise has been resolved.
The following code DOESN'T work:
beforeEach((done) => {
user = new User({ name: 'Dummy' })
user.save()
.then(done)
})
I know I'm passing the result of the user.save() promise to done, but I think it shouldn't be a problem.
Instead this other code works:
beforeEach((done) => {
user = new User({ name: 'Dummy' })
user.save()
.then(() => done())
})
It seems to me that Mocha done() has some kind of control flow which leads to: Error: done() invoked with non-Error: {"_id":"5b65b9d2669f7b2ec0a3d503","name":"Dummy","__v":0}
Is it because done() wants strictly an error as its argument?
Why done() does even care about what I pass to it?
Can you make some example showing why done() argument to be an Error is useful?
Thanks in advance ;)
It is because done() in Mocha only accepts Error argument. In your case, your save() method returns json object not an Error ie new Error('failed save').
If we take a look at mocha test file, we can see that it won't accept other type of arguments.
// https://github.com/mochajs/mocha/blob/master/test/unit/runnable.spec.js#L358
describe('when done() is invoked with a string', function () {
it('should invoke the callback', function (done) {
var test = new Runnable('foo', function (done) {
done('Test error'); // specify done with string/text argument
});
test.run(function (err) {
assert(err.message === 'done() invoked with non-Error: Test error');
done();
});
});
});
But if we see the test when the argument is Error, it works
// https://github.com/mochajs/mocha/blob/master/test/unit/runnable.spec.js#L345
describe('when an error is passed', function () {
it('should invoke the callback', function (done) {
var test = new Runnable('foo', function (done) {
done(new Error('fail'));
});
test.run(function (err) {
assert(err.message === 'fail');
done();
});
});
});
Btw, I suggest that you avoid using done since mocha supports promise by specifying return statement. So, we change the code into
beforeEach(() => {
user = new User({ name: 'Dummy' })
return user.save().then(user => {
// antyhing todo with user
});
});
Hope it helps.

Moving a promise from it() function to beforeEach()

I am writing some BDD unit tests for the first time and I'd like to eliminate some repeated code for one of my test suites. The following async unit test code works fine, but I'd like to set up the Promise in the beforeEach() block somehow, since I will be writing many more it() tests, and each one will need to run the db.find(...) call. Thanks
describe('DB retrieve row', function() {
beforeEach(function () {
// i'd like to set up the promise in this block
});
it("returns a least one result", function () {
function success(orderData) {
// keep the following line in this it() block
expect(orderData.length).to.be.ok;
}
function fail(error) {
new Error(error);
}
return db.find('P9GV8CIL').then(success).catch(fail);
});
});
Simply something like this would work
describe('DB retrieve row', function() {
var promise;
beforeEach(function () {
promise = db.find('P9GV8CIL')
});
it("returns a least one result", function () {
function success(orderData) {
// keep the following line in this it() block
expect(orderData.length).to.be.ok;
}
function fail(error) {
new Error(error);
}
return promise.then(success).catch(fail);
});
});

How to send the success of a test to testingBot from a Protractor project?

Following the testingBot example for protractor-based projects I got this code
var TestingBot = require('testingbot-api');
describe('Protractor Demo App', function () {
var tb;
beforeEach(function () {
tb = new TestingBot({
api_key: "master_key",
api_secret: "secret_007"
});
});
afterEach(function () {
browser.getSession().then(function (session) {
tb.updateTest({
'test[success]': true/*where do I get this 'test[success]' attribute? */
}, session.getId(), function () {
console.log("Hi! :D");
});
})
});
it('should have a title', function () {
browser.get('http://juliemr.github.io/protractor-demo/');
expect(browser.getTitle()).toEqual('Super Calculator');
});
});
I need to send the success of the test back through the tb.updateTest() but I don't know where I get the value of a passed or failed test. For now the value is a static true. I'd appreciate a jasmine approach too.
You can use a custom reporter with Jasmine.
There you can hook into specDone or suiteDone which has a result parameter, containing the test's success state.
You can then use this state to write a custom report or send it to somewhere else.

Using jasmine to test amplifyjs request call backs

I'm using amplifyjs for AJAX requests. That's working fine. I'm using jasmine to test the code. I'm wondering what the best method is to test the success and error call backs. The current unit test I've written doesn't work because the call back is executed after the jasmine expect. Here's my code under test:
function logout() {
ns.busy.show();
amplify.request({
resourceId: 'logout',
success: _logoutSuccess
});
};
function _logoutSuccess(response) {
ns.busy.hide();
};
Here's the unit test, where I want to validate that a function is called when the request is returned:
it('should hide busy when successful', function () {
// arrange
ns.busy = { show: function () { }, hide: function () { } };
spyOn(ns.busy, 'hide');
amplify.request.define('logout', function (settings) {
settings.success({});
});
// act
ns.accountLogoutViewModel.logout();
// assert
expect(ns.busy.hide).toHaveBeenCalled();
});
Note: ns is just a variable holding the application namespace. If I place break points on the expect and on the ns.busy.hide() in the _logoutSuccess function, jasmine hits the expect and then hits the _logoutSuccess, hence the spyOn fails.
As I say, the code is working, I just want to know how to write a test for it. I've looked into the jasmine done() function, but I'm not sure how to use it in this circumstance (or even if it is a solution).
Thanks
Isn't it always the way, when I finally get round to posting a question, I then immediately find the answer. Here's the test that passes, using the jasmine done() function:
it('should hide busy when successful', function (done) {
// arrange
ns.busy = { show: function () { }, hide: function () { } };
spyOn(ns.busy, 'hide');
amplify.request.define('logout', function (settings) {
settings.success({});
done();
});
// act
ns.accountLogoutViewModel.logout();
// assert
expect(ns.busy.hide).toHaveBeenCalled();
});

Resources