Using Qunit module setUp tearDown to test ajax - ajax

I have been finding it quite difficult to get up and running with Qunit for testing jQuery ajax.
In particular I am stumped at trying to use Qunit's module construct with a setUp and tearDown method to reduce repeated code. The following works:
test("ajax request is 200 OK", function () {
var xhr = sinon.useFakeXMLHttpRequest();
var requests = sinon.requests = [];
xhr.onCreate = function (request) {
requests.push(request);
};
var callback_success = sinon.spy();
$.ajax('/course/data', {
success: callback_success,
});
equal(sinon.requests.length, 1);
equal(sinon.requests[0].url, "/course/data");
requests[0].respond(200, { "Content-Type": "application/json" }, '[]');
ok(callback_success.called);
});
I have a JSFiddle which shows a failing test (number 11). (The earlier tests I wrote as I was trying to get my head around everything).
Specifically my question is: why does the test report failure with 'requests is undefined' when I have declared var requests; at global scope on line 115?
Explanation gratefully received! (Edit: For some reason the JSFiddle linked shows problems with sinon.js, not evident when I run the JSFiddle from my fiddle account??)

Found solution to problem with requests being undefined in my JSFiddle. My test module's setup function was never being called. For some reason I was using camelCase to define setup and teardown:
setUp: function () { .....},
tearDown: function() {....}
When of course is should be just plain
setup: function () {...},
teardown: function () {...}
So, basically a case-sensitivity error on my part, compounded with the fact that I'm finding ajax, qunit and sinon quite mind-bending.

Related

Protractor/Jasmine Error : Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL

I am running into this issue where I execute my protractor test only to find out that it has failed. Now the issue is not with the actual functionality failing but with the Default Timeout Interval apparently. The Code runs fine, performs all the operation on the Webpage and just when you expect a green dot it errors out.
Before anyone marks it duplicate, I would just like to tell that I have tried the below approaches going through the answers of other similar question.
Included argument in the "it" block and called the argument after the test.
Changed the default_timeout_interval in conf.js file to 30s.
Tried using Async/await in the last function to wait for the promise to get resolved.
I would not only like to find a answer to this one but also if someone can give me an explanation on what exactly Protractor wants to convey here. To me as a novice in JavaScript and Protractor this looks like a very vague message.
Below is my spec file :
describe("Validating Booking for JetBlue WebApplication", function(){
var firstPage = require("../PageLogic/jetBlueHomePage.js");
it("Validating One Way Booking", function(pleaserun){
firstPage.OneWayTrip();
firstPage.EnterFromCity("California");
firstPage.EnterToCity("New York");
firstPage.SelectDepartureDate();
firstPage.searchFlights();
pleaserun();
});
});
Below is my Page file:
var homePage = function(){
this.OneWayTrip = function(){
element(by.xpath("//label[text()=' One-way ']/parent::jb-radio/div")).click();
}
this.EnterFromCity = function(FromCityName){
element(by.xpath("//input[#placeholder='Where from?']")).clear();
element(by.xpath("//input[#placeholder='Where from?']")).sendKeys(FromCityName);
browser.sleep(3000);
element(by.xpath("//ul[#id='listbox']/li[1]")).click();
}
this.EnterToCity = function(ToCityName){
element(by.xpath("//input[#placeholder='Where to?']")).clear();
element(by.xpath("//input[#placeholder='Where to?']")).sendKeys(ToCityName);
browser.sleep(3000);
element(by.xpath("//ul[#id='listbox']/li[1]")).click();
browser.sleep(3000);
}
this.SelectDepartureDate = function(){
element(by.xpath("//input[#placeholder='Select Date']")).click();
browser.sleep(3000);
element(by.xpath("//span[text()=' 24 ']")).click();
}
this.NumberOfPassengers = function(){
element(by.xpath("//button[#pax='traveler-selector']")).click();
}
this.searchFlights = async function(){
await element(by.buttonText('Search flights')).click();
}
};
module.exports = new homePage();
Below is the Conf.js file :
exports.config = {
directConnect: true,
specs:["TestSpecs/jetBlueBookingTest.js"],
onPrepare: function(){
browser.get("https://www.jetblue.com/");
browser.manage().window().maximize();
},
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
isVerbose: true,
includeStackTrace: true,
}
};
Seeking help from all the protractor pros out there to help me get this solution and hopefully make me understand the concept.
the message means that an async script was run in the browser, and it hasn't returned a result within the expected time limit. it would be useful if you could share the full error stack, the root cause is probably mentioned deeper down in it

How to pass custom data to Jasmine or a Reporter?

I have some Protractor tests using Axe (AxeBuilder) like the following:
var AxeBuilder = require('path_to_the/axe-webdriverjs');
describe('Page under test', function() {
'use strict';
it('should be accessible', function() {
AxeBuilder(browser.driver).analyze(function(results) {
expect(results.violations.length).toBe(0);
});
});
});
How would I go about passing results.violations out to Jasmine so that it can be reported in my Jasmine Reporter?
I am currently looking to use the following Jasmine JSON Reporter:
https://github.com/DrewML/jasmine-json-test-reporter
But I will eventually customise this to output HTML.
I found a fix for this in the end.
It turns out that the solution is to write a custom Jasmine matcher, like this: http://jasmine.github.io/2.4/custom_matcher.html
This allows you to control what information is passed out to the result.message.

Webdriverio Node.js Mocha Chai test skips describe block

I am running this test and it seems that when the test get's to the function portion of my describe block, it skips the whole thing and gives a false positive for passing.
// required libraries
var webdriverio = require('webdriverio');
var describe = require('describe');
var after = require('after');
console.log("Lets begin");
describe('Title Test for google site', function() {
console.log("MARTY!!");
// set timeout to 10 seconds
this.timeout(10000);
var driver = {};
console.log("before we start");
// hook to run before tests
before( function (done) {
// load the driver for browser
console.log("before browser");
driver = webdriverio.remote({ desiredCapabilities: {browserName: 'firefox'} });
driver.init(done);
});
it('should load correct page and title', function () {
// load page, then call function()
return driver
.console.log("before site")
.url('http://www.ggogle.com')
// get title, then pass title to function()
.getTitle().then( function (title) {
// verify title
(title).should.be.equal("google");
// uncomment for console debug
// console.log('Current Page Title: ' + title);
});
});
});
// a "hook" to run after all tests in this block
after(function(done) {
driver.end(done);
});
console.log ("Fin");
This is the output I get
Lets begin
Fin
[Finished in 0.4s]
As you can see it skips everything else.
This is wrong and should be removed:
var describe = require('describe');
var after = require('after');
Mocha's describe and after are added to the global space of your test files by Mocha. You do not need to import them. Look at all the examples on the Mocha site, you won't find anywhere where they tell you to import describe and its siblings.
To get Mocha to add describe and its siblings, you need to be running your test through mocha. Running node directly on a test file won't work. And for mocha to be findable it has to be in your PATH. If you installed it locally, it is (most likely) not in your PATH so you have to give the full path ./node_modules/.bin/mocha.

How to mock an ajax call in mocha using sinon without setting timeout on a ractive component using reflux store

I have a working ractive component test case already with mocha using sinon ans able to mock an ajax call but with the help of setTimeout(function(){}, 100) and I dont like using it.
beforeEach(function () {
this.container = document.createElement('div');
document.body.appendChild(this.container);
this.server = sinon.fakeServer.create();
this.server.respondWith(
"GET",
"/api/url",
[
200,
{ "Content-Type": "application/json" },
'{"data": []}'
]
);
});
afterEach(function () {
document.body.removeChild(this.container);
});
it("should fetch data from server", function (done) {
var server = this.server;
var Component = require('rvc!path/to/component');
var component = new Component({
el: this.container,
});
setTimeout( function() {
server.respond();
expect(component.findAll('.list li').length).to.equal(7);
done();
}, 100);
});
As you can see in the code above, I'm using the setTimeout to make sure that the ajax call (mock) was made before having the actual test of the component.
Is there a way that I can eliminate the setTimeout having the same effect? Thanks!
Assuming that your http request is happening in the component, then it won't get the data until the next tick of the event loop.
One approach is to use setTimeout as you have done, but you probably can lower the timeout (use autoRespondAfter to adjust the sinon response delay).
If your component code supports it, an approach that seems well suited to your use case from the sinon fakeServer docs would be to use the respondImmediately option:
If set, the server will respond to every request immediately and
synchronously. This is ideal for faking the server from within a test
without having to call server.respond() after each request made in
that test. As this is synchronous and immediate, this is not suitable
for simulating actual network latency in tests or mockups.
this.server = sinon.fakeServer.create({ respondImmediately: true })
// now no need to call server.respond() and calls are returned synchronously!

Running spec after promise has been resolved

I came across an issue with running a spec that should be executed after a promise has been resolved. See the commented simplified example below.
I tried using IIFE or calling done() function in the spec but none of these seemed to work.
// getIds() is a simple promise which returns an array of ids
getIds().then(function (ids) {
console.log('IDS: ' + ids); // all good so far
// This test is never run
it('dummy test', function () {
console.log('TEST HAS BEEN RUN');
});
});
You can use browser.wait() to wait until your promise is complete. Or you can put your test inside the then block:
it('should test', function() {
getIds().then(function (ids) {
// some action.
expect()...
});
});
Also, you can put the promise in a beforeEach or a beforeAll (jasmine 2). Assign the ids to a variable declared inside a describe. The value should be available for your test to use.

Resources