I found that running Ext.application
usually opens views that you typically don't want during a unit test - otherwise you're venturing into integration testing so I avoid use of the Sencha development loader. Instead I use Karma to load the unit tests and application class files. You configure these files inside the karma.conf.js
file (example below).
I've adapted the examples from the excellent unit test tutorials from Pivotal Labs. Since Karma has a built in web server you don't need Rails, Rake or pow as their 1st tutorial describes. Using Karma means you can easily integrate your unit tests with Javascript tools like IntelliJ IDEA or WebStorm as well as CI systems and cloud testing like https://saucelabs.com/ . You can also configure it to watch your code files and auto rerun unit tests when you update them. You can also use karma-istanbul
to perform code coverage analysis.
Using a trick I learned here, I run a setup.js
file that is configured in my karma.conf.js
file to load before the unit tests. It creates a fake application object so that controllers can assign themselves to an application instance and it intentionally does not have a launch()
method. It also include the SpecHelper.js code from the Pivotal Labs example.
// Create (but don't launch) the app
Ext.application({name: 'MyAppName' });
For the view unit test question, you can create a fake Ext.Viewport
object and add a spyOn().andReturn() to fake the Ext.Viewport.getOrientation()
method required by the view during testing. This then means your unit tests can easily cover both orientation cases. You also add a renderTo:
property during testing to inspect the rendered view:
describe("when portrait orientation", function() {
var view;
beforeEach(function () {
if (!Ext.Viewport) Ext.Viewport = {};
spyOn(Ext.Viewport, 'getOrientation').andReturn('portrait');
view = Ext.create('MyAppName.view.LoginView', {
renderTo: 'jasmine_content'
}
}
it("should render large image", function() {
expect(Ext.DomQuery.select('...')).toContain('img/login.png');
});
it("should render 80px style", function() {
expect(Ext.DomQuery.select('...')).toContain('80px');
});
});
View unit tests (explains how to use the renderTo
property).
My setup.js
file show below, includes code from SpecHelper.js
shown here.
You'll need this to use the renderTo
property.
Controller unit tests covers how to connect a controller to your fake application instance.
setup.js
This code steals a Karma loading trick from here but unlike their example it avoids use of the development loader.
Ext.Loader.setConfig({
enabled: true, // Turn on Ext.Loader
disableCaching: false // Turn OFF cache BUSTING
});
// 'base' is set by Karma to be __dirname of karm.conf.js file
Ext.Loader.setPath({
'Ext': 'base/touch/src',
'MyAppName': 'base/app'
});
// Create (but don't launch) the app
Ext.application({name: 'MyAppName' });
Ext.require('Ext.data.Model');
afterEach(function () {
Ext.data.Model.cache = {}; // Clear any cached models
});
var domEl;
beforeEach(function () { // Reset the div with a new one.
domEl = document.createElement('div');
domEl.setAttribute('id', 'jasmine_content');
var oldEl = document.getElementById('jasmine_content');
if (oldEl) oldEl.parentNode.replaceChild(domEl, oldEl);
});
afterEach(function () { // Make the test runner look pretty
domEl.setAttribute('style', 'display:none;');
});
// Karma normally starts the tests right after all files specified in 'karma.config.js' have been loaded
// We only want the tests to start after Sencha Touch/ExtJS has bootstrapped the application.
// 1. We temporary override the '__karma__.loaded' function
// 2. When Ext is ready we call the '__karma__.loaded' function manually
var karmaLoadedFunction = window.__karma__.loaded;
window.__karma__.loaded = function () {};
Ext.onReady( function () {
console.info("Starting Tests ...");
window.__karma__.loaded = karmaLoadedFunction;
window.__karma__.loaded();
});
karma.conf.js:
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// Don't use Sencha Touch dynamic loading
files: [
'touch/sencha-touch-all-debug.js',
'spec/Setup.js', // Load stubbed app - does not call app.launch()
{ pattern: 'spec/**/*.js', watched: true, served: true, included: true },
{ pattern: 'app/**/*.js', watched: true, served: true, included: false},
// Some class are not loaded by sencha-touch-all-debug.js
// this tell Karma web server that it's ok to serve them.
{ pattern: 'touch/src/**/*.*', watched: false, served: true, included: false}
],
// // Use Sencha Touch static 'testing' app.js
// files: [
// './build/testing/PT/app.js',
// './spec/SetUp.js',
// './spec/**/*.js'
// ],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE/.LOG_ERROR/.LOG_WARN/.LOG_INFO/.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera (has to be installed with `npm install karma-opera-launcher`)
// - Safari (only Mac; has to be installed with `npm install
// karma-safari-launcher`)
// - PhantomJS
// - IE (only Windows; has to be installed with `npm install
// karma-ie-launcher`)
//browsers: [ 'PhantomJS' ],
browsers: ['Chrome'],
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};