I am attempting to test an AngularJS controller with a Jasmine unit test spec file. My approach is to use $httpBacked, in the following test:
describe('SubmissionsController', function() {
var minimal_mock_response = [ { id: 1 } ];
var scope, routeParams, $httpBackend;
beforeEach(module('submissionServices'));
beforeEach(inject(function($_httpBackend_, $rootScope) {
scope = $rootScope.$new();
$httpBackend = $_httpBackend_;
$httpBackend.expectGET('/submissions').respond(minimal_mock_response);
routeParams = {};
}));
it('passes a trivial test', function() {
expect(true).toBe(true);
});
});
I inserted the expect(true).toBe(true) just to get the test to execute and fail, even though it does not touch the angular controller. When I I attempt to run the test with jasmine-headless-webkit, I receive the following error:
jasmine-headless-webkit spec/javascripts/SubmissionsControllerSpec.js
Running Jasmine specs...
F
FAIL: 1 test, 1 failure, 0.011 secs.
Submissions controllers SubmissionsController passes a trivial test. (XXX/spec/javascripts/SubmissionsControllerSpec.js:18)
Error: Unknown provider: $_httpBackend_Provider <- $_httpBackend_
Test ordering seed: --seed 9254
Are there any hints on how I can correct this error and make the trivial test execute?
Enclosing service names with underscores has some benefit.
From your code, I can see that you probably wanted to save the reference to $httpBackend. This is how you wanted to do. The placement of underscore was one off.
beforeEach(inject(function(_$httpBackend_, $rootScope) {
scope = $rootScope.$new();
$httpBackend = _$httpBackend_;
...
Angular is smart enough to remove underscores and returns $httpBackend back to you, and you can save it to your own $httpBackend.
I believe this is because you're injecting the wrong service. It doesn't know what $_httpBackend_ is. You should be able to just do this:
beforeEach(inject(function($httpBackend, $rootScope) {
scope = $rootScope.$new();
$httpBackend.expectGET('/submissions').respond(minimal_mock_response);
routeParams = {};
}));
If you want to get a reference to the $httpBackend service once and store that as $httpBackend, ghiden's answer is the way to go.
Related
I need to pass the Randomly generated string data in all my Test Cases but it is only working when i put this below code in all it() block
but i need to set this code somewhere i can access these values in all my it() block or in all my TestCases
FYI-beforeAll() and beforeEach() also not able to do this
so how can i make these thing global form where in can read in all my TestCases??
`const Rs = new RandomString();
var UserEmaill = Rs.getRandomUserEmail();
cy.log(UserEmaill);
var UserData = Rs.getRandomUser();
cy.log(UserData)`
You can do in multiple ways. If you want to generate random strings in your tests, you can use faker npm module and you can do it easily... So you can do this in as many as tests possible....
npm install faker
let faker = require('faker');
cy.log(faker.internet.email());
But as you are saying that you want to use globally across multiple tests, So I suggest you to do below stuff in before hooks of support/index.js. and call those variable wherever you want.
Do as below in index.js and it will be done at before your tests execution..
let faker = require('faker');
before(() => {
global.EMAIL1 = getRandomEmail();
global.EMAIL2 = getRandomEmail();
global.EMAIL3 = getRandomEmail();
global.EMAIL4 = getRandomEmail();
function getRandomEmail() {
return faker.internet.email();
}
})
In your test you can access as below
cy.log(global.EMAIL1);
It will work like charm, please use it and like the answer to reach to more people...
Then it is super easy, all you have to do is generate the random email per test case. So that it would not be impacted by any other test and it will not impact others too. I still suggest you to use test data per test so that other test do not get effected... I think below snippet is enough for you.
let faker = require('faker');
describe('test suite', () => {
it('test1', () => {
var email1 = faker.internet.email().split('#')[0]+'#mailinator.com';
cy.log(`test1 email is ${email1}`);
});
it('test2', () => {
var email2 = faker.internet.email().split('#')[0]+'#mailinator.com';
cy.log(`test2 email is ${email2}`);
})
})
I'm working on some Jasmine end-to-end testing, using Protractor test runner. The application I am testing is a simple webpage. I already have a test scenario that works fine.
Now I'd like to improve my code so that I can use the same script to run the testing scenario twice.
The first time: the test would be performed on the English version of the page
The second time: on a translated version of the same page.
Here is my code:
var RandomSentenceInThePage = ["Sentence in English", "Phrase en Francais"];
var i;
var signInButton;
var TranslationButton;
var RandomSentenceInThePageBis;
i = 0;
//Runs the testing scenario twice
while (i < 2) {
describe('TC1 - The registration Page', function() {
//the translation is done on the second iteration
if (i != 0) {
beforeEach(function() {
browser.ignoreSynchronization = true;
browser.get('https://Mywebsite.url.us/');
//we get the translation button then click on it
TranslationButton = element(by.css('.TranslationButtonClass'));
TranslationButton.click();
});
}
//On the first iteration, we run the test on the not translated pageā¦
Else {
beforeEach(function() {
browser.ignoreSynchronization = true; //Necessary for the browser.get() method to work inside the it statements.
browser.get('https://Mywebsite.url.us/');
});
}
it('should display the log in page', function() {
//Accessing the browser is done in the before each section
signInButton = element(by.css('.SignInButtonClass'));
signInButton.click();
RandomSentenceInThePageBis = element(by.css('.mt-4.text-center.signin-header')).getText();
/*******************[HERE IS WHERE THE PROBLEM IS]*******************/
expect(RandomSentenceInThePageBis.getText()).toEqual(RandomSentenceInThePage[i]);
});
/*******************************************************************/
});
}
I have highlighted the problematic section. The code keeps running even before the comparison between RandomSentenceInThePage[i] and RandomSentenceInThePageBis are compared. And when they are finally compared, the loop is already done.
According to what I have seen on the other related topics, because of the use of expect statements and getText() methods, I am dealing with promises and I have to wait for them to be resolved. After trying for the whole day, I think I could use a hint on how to deal with this promise resolution. Let me know if you need more information.
Change while loop to for loop and declare the variable: i by let, rather than var
let can declare variable at code block scope like for, if block etc. But var can't.
Because protractor api execute async, thus when the expect()... execute for the second time. the value of i has become 2, not 1
for(let i=0;i<2;i++) {
describe('TC1 - The registration Page', function() {
....
})
}
I am currently writing some tests in a legacy system and am confused about a test result here.
I have one test here which fails as expected but mocha shows as a result 1 passing and 1 failing.
I am using Bluebird Promises, mocha, chai-as-promised and sinon with sinon-chai for spies and stubs. This is the test (I have removed stuff not needed for understanding my problem):
describe("with a triggerable activity (selection)", function () {
beforeEach(function stubData() {
stubbedTriggerFunction = sinon.stub(trigger, "newParticipation");
activityLibStub = ... // stub
selectionLibStub = ... // stub
fakeActivities = ... // simple data with just ONE element
fakeSelection = ... // simple data with just ONE element
// stub methods to return synthetic data
activityLibStub.returns(new Promise(function (resolve) {
resolve(fakeActivities);
}));
selectionLibStub.withArgs(1).returns(new Promise(function (resolve) {
resolve(fakeSelection);
}));
});
afterEach(function releaseStubs() {
// restore stubs...
});
it("should call the newParticipation function", function () {
var member = memberBuilder.buildCorrect();
trigger.allActivities(member)
.then(function () {
return expect(stubbedTriggerFunction).to.not.have.been.called;
})
.done();
})
});
This test fails as expected, because the function is actually invoked. However, mocha tells me that one test passed and one test failed. This is the only test I have implemented in this module.
I am pretty sure this has something to do with the promises but I don't seem to figure out what it is. Also if I add
.catch(function(){
chai.assert.fail();
})
after the then-block, mocha still claims that one test passed. The method is also just invoked one time and I have only one synthetic dataset which I am working with. So I don't see what it is which tells mocha that this has passed while failed...
Any ideas?
Regards, Vegaaaa
Return your promise, return your promise, return your promise. Let's chant it all together now "Return, yoooooooour promise!"
it("should call the newParticipation function", function () {
var member = memberBuilder.buildCorrect();
return trigger.allActivities(member)
.then(function () {
return expect(stubbedTriggerFunction).to.not.have.been.called;
});
})
});
I've also removed .done() because that's not generally useful with Bluebird and would be downright harmful here. Mocha still needs to use your promise.
(It's use is generally discouraged, see here.) If you do not return your promise, then Mocha treats you test as synchronous and most likely that's going to be successful because your test is not really testing anything synchronously. Then if you get an asychronous failure, Mocha has to decide what failed exactly and will do its best to record the failure but it can lead to funny things like having an incorrect number of tests or the same test being reported as failed and successful!
I'am using chakram + mocha.
How can I use shared variables for all test?
For example, I would like to use variable API_PATH="http://example.com/v1/" in tests. And this variable could be changed during running test. So, my test looks like this.
var response = chakram.get(API_PATH + "products");
expect(response).to.have.status(200);
As example, protractor has conf.js with parameter baseUrl. Running test looks like protractor conf.js --baseUrl http://example.com/
what have you tried so far? Have you tried using beforeEach to reinitialize the object that you are using? You could just make the the shared variables declared outside of your tests.
EDIT: Adding details from what Jerry said:
If you want all variable to be reused within the same test, you must make them global variables. See example below
///include dependencies
var assert = require('assert'),
chai = require('chai'),
expect = chai.expect,
chakram = require('chakram');
//INIT GLOBAL VARAIBLES FOR within the same test
var testObj,
dummyData = {
user: 'John Kim',
lastSeenOnline: 'Wed August 11 12:05 2017'
};
describe ('#User', function () {
beforeEach(function () {
//init what the object contains
testObj = new DataStore(data, ContainerStore);
});
it ('#Should return the name of the user', function () {
assert.equal(testObj.get('user'), dummyData.user);
});
it("should offer simple HTTP request capabilities", function () {
return chakram.get("http://httpbin.org/get");
});
});
Note: I work with react but this is an example. We assume that the ContainerStore contains a method that has a method for get() which just gets the value of our JSON object. You can use testObj many time in different describe blocks since it is declared outside of your tests. But you should remember to always reinitialize your tesObj in a beforeEach(); otherwise, you risk populating your individual tests. There are cases were you do not have to initialize the beforeEach() and it is optional.
For Example in config.js
module.exports = {
"baseUrl": "http://example.com/",
"googleUrl": "http://www.google.com.tr/"
};
And use in javascript code:
let config = require('/config');
describle("test describle", () => {
it("test", () => {
chakram.get(config.baseUrl + "products"); //for example use
})
})
I'm using Sinon with Mocha to test some expiration date values. I used the same code a few months ago and it worked fine, but somewhere between v1.12.x and v1.17.x, something has changed and I can't seem to find the right path.
let sinon = require('sinon');
describe('USER & AUTHENTICATION ENDPOINTS', function(done) {
beforeEach(function() {
this.clock = sinon.useFakeTimers(new Date().getTime());
return fixtures.load(data);
});
afterEach(function() {
this.clock.restore();
return fixtures.clear(data);
});
context('POST /users', function() { ... }
});
I've tried with and without the new Date().getTime() argument.
I've tried passing in and explicitly calling done().
I've tried removing my fixture load/clear processes.
The end result is always the same:
Error: timeout of 5000ms exceeded. Ensure the done() callback is being called in this test.
Has something changed that I just haven't noticed in the documentation? Do I have some kind of error in there that I can't see?
Any thoughts would be appreciated.
UPDATE
So a little more info here. This clearly has something to do with my code, but I'm at a loss.
If I comment every actual test, the tests run and give me a green "0 passing".
If I run an actual test, even one that just this:
context('POST /users', function() {
it('should create a new user', function(done) {
done();
})
});
I'm right back to the timeout. What am I missing?
Mystery solved. It appears to be a conflict between Sinon and versions of Knex > 0.7.6.
Seems to be because pool2 relies on behavior of setTimeout. Using sinon.useFakeTimers(...) replaces several methods including setTimeout with synchronous versions which breaks it. Can fix by replacing with: clock = sinon.useFakeTimers(Number(date), 'Date');
My original code was written in a world where Knex v0.7.6 was the latest version. Now that it's not everything failed even though the code itself was the same. I used the fix mentioned and things look to be fine.
You are passing done to your describe callback in line 2:
describe('USER & AUTHENTICATION ENDPOINTS', function(done) {
Mocha expects you to invoke it... To get rid of the timeout error, just remove the done parameter from the callback.