JQuery Unit Testing tooltips (jasmine, qunit, etc..) - javascript

I was wondering if anyone could provide me information, perhaps some example code, on how to unit test tooltips?
The framework is no issue, I am free to use any kind of Javascript/JQuery framework there is available (Jasmine, Qunit etc).
The hard part is that I can not really find a good example of how tooltips (which their scripts is called asynchronously) are tested.
So any example regarding unit testing JQuery UI tooltip or other external libraries (qtip etc) would be really helpfull.

The jQuery team uses Qunit for their testing. When I work on jQuery plugins, I tend to use the same tools. Here is an example test in Qunit:
//In your JS
function myTestFunction() {
//code here
}
//In test.js
QUnit.test( 'My Tests: ', function( assert ) {
'use strict';
var $el = $('#my-tooltip');
assert.strictEqual( typeof myFunction, 'function', 'It is a function.' );
assert.notEqual( $el.css('display'), 'none', 'It is visible.' );
});

Jasmine supports asynchronous tests in general. You can make your assertions in a callback and call done() to signify that your test successfully completed.
For example
it("should work with async", function(done) {
doSomethingAsync().success(function() {
// make assertions in callback
done(); // done with test
});
})

Related

Sinon alert stub: "Attempted to wrap alert which is already wrapped"

I'm using Sinon 1.14. I would like to suppress all javascript alerts using Sinon's stubs.
Using the latest Chrome version: 42.0.2311.135 m, I get an exception: "Attempted to wrap alert which is already wrapped"
The code below works fine in latest Firefox. I will update with a fiddle.
var hooks = {
beforeEach: function(assert){
this.sandbox = sinon.sandbox.create();
this.sandbox.stub(window, 'alert', function (msg) { return false; });
},
afterEach: function(){
this.sandbox.restore();
}
};
module('example', hooks);
test('example', function(assert){
ok(true, 'does not throw an exception');
});
Updating Sinon from 1.14 to 1.14.1 seems to do the trick. I assume this was a bug?
As a side note, the code runs fine in 1.12 as well.
window.alert is a global function. Every time beforeEach runs it will replace that function with a wrapped function. I guess Sinon prevents you from wrapping a function twice.
You can either make sure to have a setup function that runs only once.
Or modify your code so that you don't have global dependencies (ie. pass in a reference to alert or a delegating window object). This can impact your code architecture a lot. This also shows why it is important to think about testing when designing your architecture.

Javascript Unit testing and refactoring (using Angular js framework)

I (as a js/ng newbie) wanna know how do I start on my unit-test journey for the following angular code (Controller with some functions) and mocking necessary? Basically, I want to test extracted() function. Would appreciate beautiful suggestions. Thanks
angular.module('HelloWorld')
.controller('myCtrl', function ($scope, firstService, secondService, messageService) {
'use strict';
function goWhereTheWindBlows() { // some implementation }
$scope.mainFun = function(var1) {
firstService.showSomething(var1, function() {
var result = secondService.read(var1);
// result is the result of http get (200 or 400)
extracted(result);
}, goWhereTheWindBlows);
function extracted(result) {
result.then(function () {
messageService.addMessage({ message: 'Success', type: 'standard' });
}, function () {
messageService.addMessage({ message: 'Failure', type: 'error' });
});
}
};
});
Use grunt-karma to perform unit tests.
You should have tests folder in your structure.
Write unit test for this code in jasmine syntax.
use beforeEach to use module in which your controller is.
create variable and assign controller to it using $controller function.
Take variable with controller and run expect on your method in it function.
Thats it, run grunt test and see the results.
Some explantation about writing in jasmine syntax.
For mocking http data - that one used with $http service, use $httpBackend service in angular-mocks.js.
This is fake backend in which you write for example get requests, and specify answers from this using whenGET() and expect. There are also other requests like POST, PUT. Basically after defining result expectation you use $httpBackend.flush() method to flush changes, so your would retrieve data.
There are also end to end tests, which you can perform with protractor using selenium webdriver, but these are hard to integrate with grunt test, so you may run all tests as two commands.
Note that end to end tests are not in jasmine syntax, so you write them different.

How can I have a beforeAll function in Jasmine ? (Not coffeeScript)

I need to know if there is a way to include or use a beforeAll function, or something similar, so I can login to my application and then start testing.
Right now I'm putting my login operations in the first test case ( it ). Which is not a good practice.
If there is a better way to store my login code other then using a beforeAll function please tell me about it.
I'm using pure Jasmine not related to any other framework like coffee-script or others.
Thank you
This is now much easier. As of Jasmine 2.1 (released 14 Nov 2014), there is a beforeAll function built into the framework.
Here are the release notes with everything that was added in 2.1. And here is the documentation explaining beforeAll and afterAll
You can nest as many describe functions as you want. So you can do something like...
describe("General Test", function () {
function login(){
//This code will run once at he beginning of your script
};
login();
beforeEach(function () {
//anything in here will apply to everything in each nested describe
});
describe("Specific Test", function () {
//Applied here
});
describe("Another Specific Test", function () {
//And here
});
});
please use below code and configure your setting in beforeAll statement.
describe("Top", function() {
beforeAll(function() {
console.log("Example 1 Setup");
});
it('xyz',function(){
console.log('Hi!')
});
});
You can add this package that adds a beforeAll() and afterAll() to Jasmine.
https://github.com/nonplus/jasmine-beforeAll

Use of conditional statements in Jasmine tests

I have two functions I want to test; one that runs only in "modern browsers" the other that runs only in "older" browsers.
I am using Jasmine as my testing framework and Karma to run my tests. Karma will launch many browsers in which all the tests are run.
My problem is that testing ALL my functions in ALL browsers will lead some tests to fail. For example, testing a function that should run only in modern browsers will fail in when tested in IE8.
Code to test:
function getStuffFromSmartBrowser() {
return 'foo';
}
function getStuffFromNotSoSmartBrowser() {
return 'bar';
}
if ('intelligence' in browser) {
getStuffFromSmartBrowser();
} else {
getStuffFromNotSoSmartBrowser();
}
Original test code:
describe("A suite", function () {
it("for smart browsers", function () {
expect(getStuffFromSmartBrowser()).toEqual('foo');
});
});
describe("A suite", function () {
it("for not so smart browsers", function () {
expect(getStuffFromNotSoSmartBrowser()).toEqual('bar');
});
});
In these test cases, one test will fail in one type of browsers while the other test will fail in the other type of browsers.
Alternative test code:
describe("A suite", function () {
if ('intelligence' in browser) {
it("for smart browsers", function () {
expect(getStuffFromSmartBrowser()).toEqual('foo');
});
} else {
it("for not so smart browsers", function () {
expect(getStuffFromNotSoSmartBrowser()).toEqual('bar');
});
}
});
The alternative test code run perfectly well in all tested browsers.
Questions:
A - Is it good practice to use conditional statements in tests?
B - If not, what would be a better approach?
It's generally considered bad practice to have conditionals inside the test code. Outside of the test code is slightly more acceptable and, in the absence of a built-in mechanism to select test specs by browser, your solution is probably the simplest. However, you are coupling your unit tests to the browser-specific implementations.
A "better" approach would be to hide your browser-specific code behind a single function and use feature detection to perform multiple dispatch.
function getStuff() {
if (browserIsSmart()) {
return getStuffFromSmartBrowser();
}
else {
return getStuffFromNotSoSmartBrowser();
}
}
function browserIsSmart() {
return ('intelligence' in browser); // Or whatever
}
Here's where it gets messy. Your two functions have different return values. Ideally you'll want the same return value for all related functions, but this isn't always simple. For example, textarea selection in IE8 uses completely different objects than textarea selection in modern browsers. Sometimes you can hide the details (e.g. using the Strategy Pattern), sometimes you can't.
If you can't make it clean, make it obvious.

unit testing in javascript: how do you mock? - a (hard for me) example

I just rewrote backbone-mongodb to be really compatible with backbone. The original solution had nice vows for testing, and I would like my code to get tested as well, but simply have no idea how to do it.
Here is an example, I would like to test:
update: function(callback) {
var model = this.model;
this._withCollection(function(err, collection) {
if (err) callback(err);
else {
var attributes = _.clone(model.attributes);
delete attributes['_id'];
collection.update({ _id: new ObjectID(model.id) }, {$set: attributes}, {safe:true, upsert:false}, function(err) {
model.fetch();
callback(null, model.toJSON());
});
}
});
},
This code has nothing special in it. It uses the node-mongodb-native driver, and updates a record in the database. AFAIK, proper testing would mean to at least check that (1) collection.update was called with the given arguments, (2) callback is called when and how it should be, (3) model contains the new data.
With vows I can check (2), but have no idea at all how to check (1). Actually, the same holds for every unit testing framework I know about, qUnit, Jasmine. I'm sure that this can be done somehow, and I'm decided to learn at least one of them, but it's hard to make a choice when you got stuck at the beginning. :)
I know about sinon.js and think that everyting can be tested using mocking all the objects I have until I end up having the collection mocked as well, but this seems to be extremely clumsy. Could someone help me in writing the above tests please, and I'll happy to write out a tutorial of it?
I will use Jasmine for that purpose; I don't how familiar are you using that library, but they have a plugin to use jQuery for writing spec tests, you can load fixtures/templates and run tests on it.
for your particular case, assuming that function is part of MyObj "class", I will write something like:
describe("My object tests", function() {
it("Should update my obj", function () {
var noError, flag = false;
MyObj.update(function (err, model){
flag=true;
noError= err==null;
// or you can do other checks on the result
})
// we wait for 5 sec until get a response (flag==true)
waitsFor(function (){ return flag}, "Timeout on update", 5000);
// check if there are no errors
expect(noError).toBeTruthy();
});
});

Categories