Unit testing with Mocha+PhantomJS async code - javascript

I'm new to unit testing, so please forrgive me if my question could be silly. I wrote an unit test using Mocha with PhantomJS and Chai as assertion library. The code that I want to test is the following function:
function speakingNotification(audioStream){
var options = {};
var speechEvents = hark(audioStream, options);
speechEvents.on('speaking', function() {
return 'speaking';
});
speechEvents.on('stopped_speaking', function() {
return 'stopped_speaking';
});
}
As you can see it takes an audioStream parameter as input and then use a librabry called hark.js https://github.com/otalk/hark for detecting speaking events. The function should return if the user is speaking or not.
So I wrote the following unit test:
describe('Testing speaking notification', function () {
describe('Sender', function(){
var audio = document.createElement('audio');
audio.src = 'data:audio/mp3;base64,//OkVA...'; //audio file with sound
var noAudio = document.createElement('audio');
noAudio.src = 'data:audio/mp3;base64,...'; //audio file with no sound
it('should have a function named "speakingNotification"', function() {
expect(speakingNotification).to.be.a('function');
});
it('speaking event', function () {
var a = speakingNotification(audio);
this.timeout( 10000 );
expect(a).to.equal('speaking');
});
it('stoppedSpeaking event', function () {
var a = speakingNotification(noAudio);
this.timeout( 10000 );
expect(a).to.equal('stopped_speaking');
});
});
});
The test fails and shows:
AssertionError: expected undefined to equal 'speaking'
AssertionError: expected undefined to equal 'stopped_speaking'
I also tried to use done() insted of the timeout, however the test fails and shows:
ReferenceError: Can't find variable: done
I searched for tutorials, however I can only find simple examples that don't help.
How can I write a correct test?

Related

Mock file upload to test a FileReader

Hello and thank you for your time reading this!
I am very interested to do unit tests while developing. I am new to tests in Javascript.
I have written a function to read files we choose,with an input, however I do not know how to test it.
I have read the documentation of Jasmine, about spies:
https://jasmine.github.io/api/2.6/global.html#spyOn
And:
https://jasmine.github.io/2.0/introduction.html
The code:
function readImage() {
if ( this.files && this.files[0] ) {
var FR= new FileReader();
var img = new Image();
FR.onload = function(e) {
img.src = e.target.result;
img.onload = function() {
ctx.drawImage(img, 0, 0, 512, 512);
};
};
FR.readAsDataURL( this.files[0] );
}
return [this.files, FR, img, ctx];
}
fileUpload.onchange = readImage;
The test I tried:
describe('readImage', function () {
it('should get at least one file ', function () {
spyOn(window, 'readImage');
fileUpload.dispatchEvent(new Event('onchange'));
expect(window.readImage).toHaveBeenCalled();
})
});
Also, fileUpload is:
function createUploadInput() {
body = document.getElementsByTagName("BODY")[0];
upload = document.createElement("input");
upload.setAttribute("type", "file");
upload.setAttribute("id", "fileUpload");
body.appendChild(upload);
return upload;
}
createUploadInput();
The output I get:
Expected spy readImage to have been called.
Error: Expected spy readImage to have been called.
at jasmine.Spec.<anonymous> (test/readImageSpec.js:42:34)
I think it is because of the readImage method has not been called in the test. The reason could be because fileUpload.dispatchEvent(new Event('onchange')); does nothing
Could you help me please?
I have also read:
How to trigger event in JavaScript?
Triggering event for unit testing
Using Jasmine to spy on a function without an object
Thank you for your help!
I have tried:
it('should get at least one file ', function () {
spyOn(window, 'readImage');
fileUpload.dispatchEvent(new Event('change'));
expect(window.readImage).toHaveBeenCalled();
})
But output is:
Expected spy readImage to have been called.
Error: Expected spy readImage to have been called.
at jasmine.Spec.<anonymous> (test/readImageSpec.js:42:34)
Also I tried:
it('should get at least one file ', function () {
spyOn(window, 'readImage');
fileUpload.onchange();
expect(window.readImage).toHaveBeenCalled();
})
And output:
Expected spy readImage to have been called.
Error: Expected spy readImage to have been called.
at jasmine.Spec.<anonymous> (test/readImageSpec.js:42:34)
I have also read: How can I trigger an onchange event manually?

Protractor Test Scripts are executing faster than the page load

I am automating an angular js website which has a login functionality. All I want to Click on sign in link and enter username and password. But Somehow my script are executing really fast than the page load. Please advice me on how I can handle this:
My Login Page object is:
'use strict'
// Normal Login
require('../page-objects/loginPage.js');
var customerPortalHome = function () {
this.clickSignIn = function () {
browser.sleep(5000);
element(by.linkText('Sign In')).click();
browser.waitForAngular();
browser.sleep(2000);
return require('./loginPage.js');
}
}
module.exports = new customerPortalHome();
My Test Spec is;
var co = require('co');
var UI = require('./ui.js');
var ui = new UI();
var CustomerPage = require('../page-objects/customerPortalHome.js')
describe(" Smoke Test Login to the application", function () {
it("test", co.wrap(function* () {
var EC = protractor.ExpectedConditions;
browser.get(ui.createStartLink());
expect(browser.getTitle()).toContain("Portal");
// Verify if user is able to Login into the application
var loginPage = CustomerPage.clickSignIn();
loginPage.switchToFrame('account-sdk');
var reportPage = loginPage.clickLogin('$$$$$#gmail.com', '$$$$$');
expect(browser.getCurrentUrl()).toContain('reports');
reportPage.clickSignOut();
expect(browser.getCurrentUrl()).toContain("?signout");
browser.sleep(800);
}));
});
Whenever I execute the test The browser opens for a sec and then closes.
My Onprepare method looks like this:
beforeLaunch: function () {
return new Promise(function (resolve) {
reporter.beforeLaunch(resolve);
});
},
onPrepare: function () {
browser.manage().timeouts().implicitlyWait(5000);
afterEach(co.wrap(function* () {
var remote = require('protractor/node_modules/selenium-webdriver/remote');
browser.driver.setFileDetector(new remote.FileDetector());
}));
Using browser sleep is never a good idea the best thing to do is to wait for an element and use the then function to do so.
element(by.xpath("xpath")).click().then(function(){
var list = element(by.id('id'));
var until = protractor.ExpectedConditions;
browser.wait(until.presenceOf(list), 80000, 'Message: took too long');
});
browser.wait(protractor.ExpectedConditions.visibilityOf($$('.desk-sidebar > li').get(num-1)), 60000);
Usually,I use this wait.
Are you using an ignoreSynchronisation without putting the false somewhere in your page objects helpers?
Be careful, the login can sometimes break the waitForAngular when there are a lot of redirections. I ended up using a dirty sleep to wait the page to be loaded when logging (no other solution were found, ignoreSync, EC for a change of url and wait for an element were not working solutions).
You should also share the error you get.

JavaScript - testing implementation of NodeJS readline.createInterface using Jasmine

I'm building a command-line application in NodeJS and I want to thoroughly test it using Jasmine.
I've implemented a promptUser() method which uses Node's readline.createInterface method to pose a question and pipe the response into a callback. I want to test that, given a user response of 'q', my module's quit() function is called.
However I'm struggling to test this. I don't really want to test the readline method directly, since I didn't write that code, but I reasoned that if I can create a listener on process.stdout.write then when enter command: is printed to the screen I can respond with process.stdin.write("q\n") and trigger the if/else logic.
I've simplified the code, but should explain what I'm trying to do:
Module source code:
var Cli = function() {
var rl = require('readline');
var self = this;
Cli.prototype.promptUser = function() {
var inputHandler = rl.createInterface(process.stdin, process.stdout);
inputHandler.question('enter command: ', function(answer) {
if (answer === 'q') {
self.quit();
};
});
};
Cli.prototype.quit = function() {
// doSomething
};
};
module.exports = Cli;
Jasmine test:
var Cli = require('Cli');
describe('My application.', function() {
beforeEach(function() {
cli = new Cli();
spyOn(cli, 'quit');
});
describe('Cli #promptUser', function() {
it('input of lower-case q calls cli.quit()', function() {
process.stdout.once('write', function() {
process.stdin.write("q\n");
});
cli.promptUser();
expect(cli.quit).toHaveBeenCalled();
});
});
});
I'm looking to either make this approach work or find a better way to test my code. I suspect there is probably a superior/more direct approach.

Isolation of actions and tests

I try to refactor my code. I know that if I have several expectations they should be isolate in 'it'. I try to understand how I can write instead this:
describe('my scenario should make', function () {
var config = browser.params;
var url = config.listOfReferencesUrl,
grid,
numberField;
it('test1', function () {
browser.get(url);
browser.executeScript("icms.go('WEB_INQ_PROC', 'InquiryList', null, 0)");
grid = psGrid(by.css("table[class='n-grid']"));
numberField = grid.getQuickFilter(1);
numberField.click().sendKeys("Hello!");
since('fail1').expect(numberField.getInputText()).toEqual("");
});
it('test2', function () {
since('fail2').expect(numberField.getInputText()).toEqual("Hello!");
});
});
Something like this:
describe('my scenario should make', function () {
var config = browser.params;
var url = config.listOfReferencesUrl,
grid,
numberField;
*********Make this part of code ONES before all tests in spec ****
browser.get(url);
browser.executeScript("icms.go('WEB_INQ_PROC', 'InquiryList', null, 0)");
grid = psGrid(by.css("table[class='n-grid']"));
numberField = grid.getQuickFilter(1);
numberField.click().sendKeys("Hello!");
*******************************************************************
it('test1', function () {
since('fail1').expect(numberField.getInputText()).toEqual("");
});
it('test2', function () {
since('fail2').expect(numberField.getInputText()).toEqual("Hello!");
});
});
Maybe somebody have an idea how I can do this?
To answer your question, if you want to run your code once before all tests then use beforeAll() function available in Jasmine 2. Here's a sample -
beforeAll(function(){
//Write your code here that you need to run once before all specs
});
You can use beforeEach() function available in Jasmine to run it each time before a test spec. Here's a sample -
beforeEach(function(){
//Write your code here that you need to run everytime before each spec
});
If you are facing issue in getting these functions to work, then update your plugins to latest version and then try running it. Also use the framework: 'jasmine2' in your conf.js file
Hope this helps.

Mocha in the browser: How to get a report using chai.assert

I can't get Mocha to produce output when using chai.assert.
http://jsfiddle.net/web5me/244PT/6/
var assert = chai.assert();
mocha.setup('bdd');
describe('Kata', function() {
it('should return...', function() {
assert.equal(true, true, 'Truthy values should be treated equal.');
});
});
mocha.run();
It works perfectly with chai.should and chai.expect.
http://jsfiddle.net/web5me/244PT/#base
I think you are calling assert wrong, have you tried
var assert = chai.assert;

Categories

Resources