Tomasz Szewców
describe('A suite', function() {
it('contains spec with an expectation', function() {
expect(true).toBe(true);
});
});
// install Karma
npm install karma
// install plugins
npm install karma-jasmine
npm install karma-phantomjs-launcher
npm install karma-chrome-launcher
// run Karma
./node_modules/karma/bin/karma start / init / run
// alternative
npm install -g karma-cli
karma start / init / run
// can be created with karma init command
module.exports = function (config) {
config.set({
basePath: '',
frameworks: [],
files: [],
hostname: 'localhost',
port: 9876,
autoWatch: false,
browsers: [],
singleRun: false,
})
};
// for debugging in a browser:
// - set single run to true
// - select other browser
http://karma-runner.github.io/0.8/config/configuration-file.html
describe('SampleCntl tests', function() {
'use strict';
var $scope;
beforeEach(module('someModule'));
beforeEach(inject(function($controller, $rootScope){
$scope = $rootScope.$new();
$controller('SampleCntl', {$scope: $scope});
}));
describe('some suite', function() {
it('some spec', function() {
// given
// when
$scope.someFunction();
// then
});
});
});
describe('SampleCntl tests', function() {
'use strict';
var cntl;
beforeEach(module('someModule'));
beforeEach(inject(function($controller){
cntl = $controller('SampleCntl', {});
}));
describe('some suite', function() {
it('some spec', function() {
// given
// when
cntl.someFunction();
// then
});
});
});
// 1. create a sample angular module
angular.module('sampleModule', []);
// 2. create a calculator controller with 2 functions
angular.module('sampleModule').controller('CalculatorCntl', function(){
'use strict';
this.factorial = function(n){};
this.divide = function(a, b){};
});
// 3. specify appropriate files in the karma config file
// 4. implement controller's functionality using TDD
// sample controller code
angular.module('someModule').controller('SomeCntl', function($location){
'use strict';
this.goToDialog = function(path){
$location.path(path);
};
});
// test code
var cntl, locationMock = {
path: angular.noop
};
beforeEach(inject(function($controller){
// injection of mocked $location service
cntl = $controller('SomeCntl', {$location: locationMock});
}));
describe('data service tests', function () {
'use strict';
var someDataService;
beforeEach(module('app'));
beforeEach(inject(function (_someDataService_) {
someDataService = _someDataService_;
}));
describe('get data method', function () {
it('should return data', function () {
// given
var data = [];
// when
data = someDataService.getData();
// then
expect(data.length).toEqual(10);
});
});
});
// sample service code
angular.module('someModule').factory('serviceUnderTests', function('otherService'){
'use strict';
var data = [];
return {
getData: function(){
angular.copy(otherService.getData(), data);
},
getCurrent: function(){
return data;
}
};
});
// test code
var otherServiceMock = {getData: function(){return [1,2,3]}};
var serviceUnderTests;
beforeEach(function(){
module('someModule');
module(function($provide){
// injecting other service with $provide service
$provide.value('otherService', otherServiceMock);
);
});
beforeEach(function(_serviceUnderTests_){
serviceUnderTests = _serviceUnderTests_;
});
var booksData, $httpBackend;
beforeEach(inject(function (_booksData_, _$httpBackend_) {
booksData = _booksData_;
$httpBackend = _$httpBackend_;
}));
afterEach(function () {
// then
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('should load books', function () {
// given
var searchParams = {title: 'title', author: 'author'}, books = [], response = [
{id: 0, title: 'title1'},
{id: 1, title: 'title2'}
];
$httpBackend.expectGET('/books-management/books-list/books.json?author=author&title=title').respond(response);
// when
booksData.getBooks(searchParams).then(function (response) {
books = response.data;
});
$httpBackend.flush();
// then
expect(books).toEqual(response);
});
describe('testing directive', function() {
'use strict';
var $compile, $rootScope;
beforeEach(module('moduleName'));
beforeEach(inject(function(_$compile_, _$rootScope_){
$compile = _$compile_;
$rootScope = _$rootScope_;
}));
it('should replace the directive with an appropriate content', function() {
// given when
var element = $compile(' ')($rootScope);
$rootScope.$digest();
// then
expect(element.html()).toContain('expected content');
});
});
// install protractor globally with the node package manager
npm install -g protractor
// download webdriver
webdriver-manager update
// start selenium server
webdriver-manager start
// prepare the configuration file
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['todo-spec.js']
};
// run e2e tests
protractor [name-of-config-file]
// running tests in other browsers
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['spec.js'],
capabilities: {
browserName: 'firefox'
}
}
// running tests in many browsers
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['spec.js'],
multiCapabilities: [{
browserName: 'firefox'
}, {
browserName: 'chrome'
}]
}
https://github.com/angular/protractor/blob/master/docs/referenceConf.js
// by binding
element(by.binding('item.name'));
// by model
element(by.model('item.name'));
// by css
element(by.css('some-css'));
// shorthand for css selectors
$('my-css') // the same as element(by.css('my-css'))
// by button text
element(by.buttonText('buttonText'));
// by tag name
element(by.tagName('tag-name'));
// by repeater
element.all(by.repeater('repeater'));
https://angular.github.io/protractor/#/api?view=ProtractorBy
var el = element(locator);
// click on the element
el.click();
// send keys to the element (usually an input)
el.sendKeys('my text');
// clear the text in an element (usually an input)
el.clear();
// get the value of an attribute, for example, get the value of an input
el.getAttribute('value');
https://angular.github.io/protractor/#/api?view=ElementFinder
// set breakpoint
browser.pause();
// continue to the next step
c
// enter interactive mode
repl
// exit debugging
ctrl + C
// 1. create a page object for tables list dialog
// - page object should have nextPage and getNumOfTables function
// - nextPage has to click on the next page button (use for example by.css selector)
// - getNumOfTables has to retrieve number of rows (use for example by.repeater selector)
// 2. use page object in a test together with signIn page object
// - sign in to table management
// - assert number of rows on the first page
// - move to the second page
// - assert number of tables on the second page