I'm trying to setup unit testing for my ext js application.
I'm using Jasmine 2.0 and PhantomJS to run the tests from console.
I can successfully init the store in the init method of the controller.
But, if I try to declare it in the stores config, I'm getting the following error :
TypeError: 'null' is not a constructor (evaluating 'new c()') (line 1) (1) ,
What is the cause for the error, and how can it be resolved?
Thank you in advance.
My code is below:
TestApplication.js
Ext.Loader.setConfig({ enabled: true });
Ext.ns('myApp');
// Loading different components like controller, model, view..
Ext.application({
name: 'myApp',
appFolder: '../App',
controllers: [],
autoCreateViewport: false,
init : function() {
myApp.app = this;
},
// Launch Jasmine test environment
launch: function () {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.execute();
}
});
spec.js
describe("myController", function () {
var ctrl= null,
store = null;
beforeEach(function () {
bmTab = Ext.create("myApp.controller.myController");
bmTab.init();
});
});
myController.js
Ext.define('myApp.controller.myController', {
extend: 'Ext.app.Controller',
//stores: [Stores.myStore];
init:function() {
console.log('**** init');
var store = Ext.create(Stores.myStore);
console.log('**** store created' + store);
}
});
The problem was using Jasmine 2.0, when all of the tutorials were using Jasmine 1.3.
In Jasmine 2.0 a file boot.js was introduced.
And it was calling jasmine.getEnv().execute() on window.onload.
Because of that, specs were executing before Ext.launch was called.
Once I removed the call to execute() from the boot.js it all started working.
Below is a final version of my TestApplication.js code
P.S.
Note that, HtmlReporter is also initialized in the boot.js, so there is no need to init it on the Ext.launch function
Ext.Loader.setConfig({ enabled: true });
Ext.application({
name: 'myApp',
appFolder: '../App',
controllers: [],
autoCreateViewport: false,
// Launch Jasmine test environment
launch: function () {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
jasmineEnv.execute();
}
});
Related
I'm trying to implement protractor screenshot reporter for jasmine 2.
But, I'm getting the following error on terminal:
/usr/local/bin/node lib/cli.js example/conf.js
/Users/sadiq/node_modules/protractor/node_modules/q/q.js:155
throw e;
^
TypeError: reporter.beforeLaunch is not a function
at /Users/sadiq/node_modules/protractor/example/conf.js:38:19
at exports.config.beforeLaunch (/Users/sadiq/node_modules/protractor/example/conf.js:37:13)
at Function.promise
(/Users/sadiq/node_modules/protractor/node_modules/q/q.js:682:9)
Process finished with exit code 1
Version Details:
Protractor: v3.1.1;
Jasmine: v2.0.0;
protractor-jasmine2-html-reporter
PFB the conf.js file
// An example configuration file.
var Jasmine2HtmlReporter = require('protractor-jasmine2-html-reporter');
var reporter = new Jasmine2HtmlReporter ({
dest: '/Users/sadiq/node_modules/protractor/test-results',
filename: 'Login.html'
});
exports.config = {
//The address of a running selenium server.
seleniumAddress: 'http://localhost:4444/wd/hub',
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
// Framework to use. Jasmine is recommended.
framework: 'jasmine2',
// Spec patterns are relative to the current working directly when
// protractor is called.
specs: ['login_spec.js'],
// Options to be passed to Jasmine.
jasmineNodeOpts: {
defaultTimeoutInterval: 30000,
showColors: true
},
// Setup the report before any test starts
beforeLaunch: function (){
return new Promise(function(resolve){
reporter.beforeLaunch(resolve);
});
},
onPrepare: function () {
browser.driver.manage().window().setSize(1200, 800);
jasmine.getEnv().addReporter(reporter);
},
// Close the report after all tests finish
afterLaunch: function (exitCode) {
return new Promise(function (resolve) {
reporter.afterLaunch(resolve.bind(this, exitCode));
});
}
};
Usually reporters are set up in onPrepare instead of beforeLaunch:
var Jasmine2HtmlReporter = require('protractor-jasmine2-html-reporter');
onPrepare: function () {
browser.driver.manage().window().setSize(1200, 800);
var reporter = new Jasmine2HtmlReporter ({
dest: '/Users/sadiq/node_modules/protractor/test-results',
filename: 'Login.html'
});
jasmine.getEnv().addReporter(reporter);
},
Being new to JS unit testing and Angular testing in particular, I tried writing my own tests with Jasmine and Karma. After numerous failed attempts at writing my own tests, I decided to step back and check whether everything is working properly, so I copied the example controller and its tests from the Angular Documentation on Unit testing into my project and I am unable to get even that to work.. I feel like a complete idiot that can't even get the copy-pasted code to work..
So here is the controller that I have initialized in the step1Ctrl.js file:
Module is initialized in another file.
var mainApp = angular.module("mainApp");
mainApp.controller('PasswordController', function PasswordController($scope) { $scope.password = ''; $scope.grade = function() {
var size = $scope.password.length;
if (size > 8) {
$scope.strength = 'strong';
} else if (size > 3) {
$scope.strength = 'medium';
} else {
$scope.strength = 'weak';
} }; });
And here's are the tests that live inside step1Ctrl.spec.js:
describe('PasswordController', function() {
beforeEach(module('mainApp'));
var $controller;
beforeEach(inject(function(_$controller_){
// The injector unwraps the underscores (_) from around the parameter names when matching
$controller = _$controller_;
}));
describe('$scope.grade', function() {
var $scope, controller;
beforeEach(function() {
$scope = {};
controller = $controller('PasswordController', { $scope: $scope });
});
it('sets the strength to "strong" if the password length is >8 chars', function() {
$scope.password = 'longerthaneightchars';
$scope.grade();
expect($scope.strength).toEqual('strong');
});
it('sets the strength to "weak" if the password length <3 chars', function() {
$scope.password = 'a';
$scope.grade();
expect($scope.strength).toEqual('weak');
});
});
});
Literally copy-pasted from the documentation.
So the error that I get upon running the tests is:
TypeError: undefined is not a constructor (evaluating '$controller('PasswordController', { $scope: $scope })')
Which tells me that the $controller function in the second beforeEach is failing, as $controller is undefined. So it looks like the first beforeEach doesn't run, or it does but an undefined value gets injected with the inject function.
I am also using browserify, if that matters.
Here is my karma.conf.js, if that helps, as well:
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['browserify', 'jasmine'],
files: [
'https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.1/angular.js',
'https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js',
'https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.1/angular-mocks.js',
'test/unit/**/*.js'
],
exclude: [
],
preprocessors: {
'app/main.js': ['browserify']
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['PhantomJS'],
browserify: {
debug: true,
transform: []
},
plugins: [
'karma-phantomjs-launcher', 'karma-jasmine', 'karma-bro'
],
singleRun: false,
concurrency: Infinity
});
};
I have finally managed to figure out what the problem was. PhantomJS wasn't descriptive with the error messages at all. Apparently, it was failing to instantiate my main Angular module mainApp, because I didn't include some source files for external modules that my main module depends on (like ngAnimate, etc.).
So I switched my testing browser from PhantomJS to Chrome and it actually gave me meaningful errors that quickly pointed in the right direction.
Check whether
The testing framework is installed, The test conditions belongs to the
testing framework you are using.
The "karma.config.js" is configured for the framework you
installed.
Use Browser testing instead of Headless PhantomJS testing to get clear directions.
In most cases above are the errors.
I am running my intern test using the following code
node node_modules/intern/runner.js config=tests/intern
on my local machine. The application is using Dojo.
Basically I am trying to override the window.alert function as one of my test is failing because of unexpected alert.
window.alert = function(msg) {
//override alert function
//...
}
I tried putting this in my intern test and got the error. After some search I learned that window object is not available on node environment. Where can I override the alert?
The intern file looks like
define(['intern/lib/args'], function(args) {
var DEFAULT_PORT = "8080";
var urlInfo = {
PORT: args.port || DEFAULT_PORT,
BASE_URL : "http://localhost:".concat(args.port || DEFAULT_PORT, "/webtest"),
};
var config = {
proxyPort: 9000,
proxyUrl: 'http://localhost:9000',
capabilities: {
'selenium-version': '2.45.0',
},
...
...
};
return config;
});
Intern Test file example
define([
'intern!object',
'intern/chai!assert',
'intern/dojo/node!leadfoot/helpers/pollUntil',
'intern',
'intern/dojo/node!fs'
], function(registerSuite, assert, Pages, intern, fs) {
registerSuite ({
name: 'Tests',
setup: function() {
window.alert = function(msg){
console.log("Unexpected Alert: "+msg);
}
return this.remote.get(require.toUrl( intern.config.functionalInfo.BASE_URL)).maximizeWindow();
},
beforeEach: function() {
return
},
afterEach: function() {
return
},
'Test1' : function() {
this.timeout = 600000;
return this.remote
.setFindTimeout(5000)
....
},
}
window does not exist in node, you have to override its alert from code that runs on the browser (the code being tested), not on node itself. I would do it in the setup code for each test that uses it.
This is error message on a protractor test use protractor http mock:
JavascriptError: javascript error: [$injector:nomod] Module 'httpMock'
is not available! You eit her misspelled the module name or forgot to
load it. If registering a module ensure that you specify the
dependencies as the second argument.
conf.js:
// An example configuration file.
exports.config = {
directConnect: true,
// Selenium server
SeleniumAddress: 'http://localhost:4444/wd/hub',
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
//baseUrl: 'http://develop.garbo.livebranches.com/sv-SE/',
//Framework to use. Jasmine 2 is recommended.
framework: 'jasmine2',
//frameworks: ['mocha', 'jasmine'],
// Spec patterns are relative to the current working directly when
// protractor is called.
//specs: ['testmain.js','testlogin.js'],
//specs: ['testmain.js','testteaPartyList.js','testpositionSearchIndex.js','testpositionList.js'],
specs: ['testlogin.js'],
//Options to be passed to Jasmine.
jasmineNodeOpts: {
defaultTimeoutInterval: 250000
},
mocks: {
dir: '../node_modules/protractor-http-mock',
//dir: 'mocks',
default: []
},
//=====login begin =====
onPrepare: function() {
require("protractor-http-mock").config = {
rootDirectory: '../node_modules/protractor-http-mock/lib',
//rootDirectory: __dirname,
protractorConfig: "conf.js", // name of the config here
};
}
//=====login end========
};
testlogin.js
describe('angularjs homepage', function() {
//browser.ignoreSynchronization = true;
it('should login', function() {
var mock = require('protractor-http-mock');
var todoList;
beforeEach(function() {
var url ='http://dev.etest.com:285/Actor/tbUsers/LoginAndGet';
var req = {Mobile:'14500000006',Password:'123456'};
var rep = {UserId:164,AccountId:328,Token:'328:dc91d536ab424aa0b8d7f1ecaf64c55b',Id:328};
mock([{
request: {
path: url,
method: 'POST',
data:req,
},
response: {
data: rep,
}
}]);
});
afterEach(function() {
mock.teardown();
});
browser.get('http://localhost:2024/daNiuJob/www/ionicWeb/index.html#/login');
console.log('mock='+mock);
element(by.model('data.userName')).sendKeys('14500000006');
element(by.model('data.password')).sendKeys('123456');
var btnlogin = element(by.id('Regist')).element(by.tagName('a'));
expect(browser.getTitle()).toEqual('userlogin');
browser.getTitle().then(function(text){
console.log('title='+text);
});
//cause mock error
expect(mock.requestsMade()).toEqual([
{ url : 'http://dev.etest.com:285/Actor/tbUsers/LoginAndGet', method : 'GET' },
]);
btnlogin.click();
browser.sleep(8000);
});
});
Why can't find httpMock, thank!
note:
C:\Users\HQ-XXX\AppData\Roaming\npm\node_modules\protractor\node_modules\protractor-http-mock
This is path of 'protractor-http-mock'
You should be giving the path of the http-mock module folder and not lib folder inside it. Change your rootDirectory path of protractor-http-mock inside onPrepare() function to -
rootDirectory: 'C:\Users\HQ-XXX\AppData\Roaming\npm\node_modules\protractor\node_modules\protractor-http-mock ',
If at all you need to provide a relative path then change it as below -
rootDirectory: '..\node_modules\protractor-http-mock ',
Hope this helps.
We had the same issue and it was related to the page reloading at the beginning of every spec.
This was caused by a faulty config of html5mode and the browser.get so it did a redirect at the beginning from foo.bar/ to foo.bar/#/ which unloads all injected protractor code.
Am trying to run firsttest.js:
// firsttest.js
describe('angularjs homepage', function() {
var firstNumber = element(by.model('first'));
var secondNumber = element(by.model('second'));
var goButton = element(by.id('gobutton'));
var latestResult = element(by.binding('latest'));
beforeEach(function() {
browser.get('http://juliemr.github.io/protractor-demo/');
});
it('should have a title', function() {
expect(browser.getTitle()).toEqual('Super Calculator');
});
it('should add one and two', function() {
firstNumber.sendKeys(1);
secondNumber.sendKeys(2);
goButton.click();
expect(latestResult.getText()).toEqual('3');
});
it('should add four and six', function() {
// Fill this in.
expect(latestResult.getText()).toEqual('10');
});
it('test1', function() {
// Fill this in.
expect(true).toEqual(true);
});
it('test2', function() {
// Fill this in.
expect(true).toEqual(true);
});
it('test3', function() {
// Fill this in.
expect(true).toEqual(true);
});
});
conf file:
var HtmlReporter = require('protractor-html-screenshot-reporter');
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['firsttest.js'],
multiCapabilities: [{
'browserName': 'chrome'
}],
onPrepare: function() {
// Add a screenshot reporter and store screenshots to `/tmp/screnshots`:
jasmine.getEnv().addReporter(new HtmlReporter({
baseDirectory: './e2e-reports',
takeScreenShotsOnlyForFailedSpecs: true,
docTitle: 'Pytheas Tests'
}));
}
}
Console o/p:
Failures:
1) angularjs homepage should add four and six Message:
Expected '0' to equal '10'. Stacktrace:
Error: Failed expectation
at [object Object]. (/Users/bgowda1/Work/Projects/Demos/protractor-tests/firsttest.js:35:36)
Finished in 6.191 seconds 6 tests, 6 assertions, 1 failure
HTML report shows only 5 tests.
I was able to reproduce it - this is always the latest it block that is missing in the final HTML report. This should be reported to the protractor-html-screenshot-reporter bug tracker.
As a current workaround, downgrade to protractor 1.4.0 (tested, worked for me). Or, add an empty it() block to the end of the file. I'll update the post if I'll come up with a fix, or better workaround.