* Add karma, Jasmine, deps and karma.conf.js. Fixes #1291 * Improved service worker code * npm start script executes gulp watch task. * Written a gulp task to compile templates AOT. Get rid of loading deps in unit tests and a preprocessor. * PhantomJS package is deprecated. Use phantomjs-prebuilt instead. * Adjust `npm run test`.
This commit is contained in:
parent
043c76b454
commit
6f8676dd74
5
.gitignore
vendored
5
.gitignore
vendored
@ -2,6 +2,8 @@
|
||||
.idea
|
||||
.publish
|
||||
*.sublime-workspace
|
||||
*.*~
|
||||
*.swp
|
||||
|
||||
# Node.js package manager
|
||||
node_modules
|
||||
@ -12,4 +14,5 @@ releases
|
||||
webogram*.zip
|
||||
app/js/templates.js
|
||||
app/css
|
||||
cldr
|
||||
cldr
|
||||
coverage/
|
||||
|
31
gulpfile.js
31
gulpfile.js
@ -8,6 +8,7 @@ var st = require('st')
|
||||
var del = require('del')
|
||||
var runSequence = require('run-sequence')
|
||||
var swPrecache = require('sw-precache')
|
||||
var Server = require('karma').Server
|
||||
|
||||
|
||||
// The generated file is being created at src
|
||||
@ -21,6 +22,7 @@ gulp.task('templates', function () {
|
||||
}))
|
||||
.pipe(gulp.dest('app/js'))
|
||||
})
|
||||
|
||||
gulp.task('clean-templates', function () {
|
||||
return del(['app/js/templates.js'])
|
||||
})
|
||||
@ -275,6 +277,35 @@ gulp.task('bump', ['bump-version-manifests', 'bump-version-config'], function ()
|
||||
gulp.start('bump-version-comments')
|
||||
})
|
||||
|
||||
// Single run of karma
|
||||
gulp.task('karma-single', function (done) {
|
||||
new Server({
|
||||
configFile: __dirname + '/karma.conf.js',
|
||||
singleRun: true
|
||||
}, done).start();
|
||||
});
|
||||
|
||||
// Continuous testing with karma by watching for changes
|
||||
gulp.task('karma-tdd', function (done) {
|
||||
new Server({
|
||||
configFile: __dirname + '/karma.conf.js',
|
||||
}, done).start();
|
||||
});
|
||||
|
||||
gulp.task('test', function (callback) {
|
||||
runSequence(
|
||||
['templates', 'karma-single'],
|
||||
callback
|
||||
)
|
||||
});
|
||||
|
||||
gulp.task('tdd', function (callback) {
|
||||
runSequence(
|
||||
['templates', 'karma-tdd'],
|
||||
callback
|
||||
)
|
||||
});
|
||||
|
||||
gulp.task('build', ['clean'], function (callback) {
|
||||
runSequence(
|
||||
['less', 'templates'],
|
||||
|
111
karma.conf.js
Normal file
111
karma.conf.js
Normal file
@ -0,0 +1,111 @@
|
||||
// Karma configuration
|
||||
// Generated on Thu Dec 15 2016 21:12:39 GMT+0100 (CET)
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
|
||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||
basePath: 'app',
|
||||
|
||||
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
// Load files to access global variables
|
||||
files: [
|
||||
{pattern: 'js/lib/polyfill.js', watched: false},
|
||||
{pattern: 'vendor/jquery/jquery.min.js', watched: false},
|
||||
{pattern: 'js/lib/config.js', watched: false},
|
||||
{pattern: 'vendor/jquery.nanoscroller/nanoscroller.js', watched: false},
|
||||
{pattern: 'vendor/angular/angular.js', watched: false},
|
||||
{pattern: 'vendor/angular/angular-mocks.js', watched: false},
|
||||
{pattern: 'vendor/angular/angular-route.js', watched: false},
|
||||
{pattern: 'vendor/angular/angular-animate.js', watched: false},
|
||||
{pattern: 'vendor/angular/angular-sanitize.js', watched: false},
|
||||
{pattern: 'vendor/angular/angular-touch.js', watched: false},
|
||||
{pattern: 'vendor/ui-bootstrap/ui-bootstrap-custom-tpls-0.12.0.js', watched: false},
|
||||
{pattern: 'vendor/angular-media-player/angular-media-player.js', watched: false},
|
||||
{pattern: 'vendor/jsbn/jsbn_combined.js', watched: false},
|
||||
{pattern: 'vendor/cryptoJS/crypto.js', watched: false},
|
||||
{pattern: 'vendor/rusha/rusha.js', watched: false},
|
||||
{pattern: 'vendor/zlib/gunzip.min.js', watched: false},
|
||||
{pattern: 'vendor/closure/long.js', watched: false},
|
||||
{pattern: 'vendor/leemon_bigint/bigint.js', watched: false},
|
||||
{pattern: 'vendor/libwebpjs/libwebp-0.2.0.js', watched: false},
|
||||
{pattern: 'vendor/angularjs-toaster/toaster.js', watched: false},
|
||||
{pattern: 'vendor/clipboard/clipboard.js', watched: false},
|
||||
{pattern: 'js/lib/utils.js', watched: false},
|
||||
{pattern: 'js/lib/bin_utils.js', watched: false},
|
||||
{pattern: 'js/lib/tl_utils.js', watched: false},
|
||||
{pattern: 'js/lib/ng_utils.js', watched: false},
|
||||
{pattern: 'js/lib/i18n.js', watched: false},
|
||||
{pattern: 'js/lib/mtproto.js', watched: false},
|
||||
{pattern: 'js/lib/mtproto_wrapper.js', watched: false},
|
||||
'js/templates.js', // Generated by `gulp templates`
|
||||
'js/services.js',
|
||||
'js/filters.js',
|
||||
'js/controllers.js',
|
||||
'js/directives.js',
|
||||
'../test/unit/*.js'
|
||||
],
|
||||
|
||||
|
||||
// list of files to exclude
|
||||
exclude: [
|
||||
'js/background.js'
|
||||
],
|
||||
|
||||
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
preprocessors: {
|
||||
'js/*.js': ['coverage'],
|
||||
},
|
||||
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress'
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: ['progress', 'coverage'],
|
||||
|
||||
|
||||
coverageReporter: {
|
||||
type: 'text',
|
||||
dir: 'coverage/'
|
||||
},
|
||||
|
||||
|
||||
// web server port
|
||||
port: 9876,
|
||||
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.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
|
||||
browsers: ['PhantomJS'],
|
||||
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, Karma captures browsers, runs the tests and exits
|
||||
singleRun: false,
|
||||
|
||||
// Concurrency level
|
||||
// how many browser should be started simultaneous
|
||||
concurrency: Infinity,
|
||||
})
|
||||
}
|
@ -19,7 +19,8 @@
|
||||
"show": true
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node server.js"
|
||||
"start": "gulp watch",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -65,6 +66,12 @@
|
||||
"gulp-util": "^3.0.7",
|
||||
"gulp-zip": "^0.1.2",
|
||||
"http": "0.0.0",
|
||||
"jasmine-core": "^2.5.2",
|
||||
"karma": "^1.3.0",
|
||||
"karma-coverage": "^1.1.1",
|
||||
"karma-jasmine": "^1.1.0",
|
||||
"karma-phantomjs-launcher": "^1.0.2",
|
||||
"phantomjs-prebuilt": "^2.1.14",
|
||||
"run-sequence": "^1.0.2",
|
||||
"st": "^0.5.2",
|
||||
"sw-precache": "^3.2.0"
|
||||
|
50
test/unit/AppLangSelectControllerSpec.js
Normal file
50
test/unit/AppLangSelectControllerSpec.js
Normal file
@ -0,0 +1,50 @@
|
||||
describe('AppLangSelectController', function () {
|
||||
var $controller, $scope;
|
||||
|
||||
beforeEach(module('ui.bootstrap'));
|
||||
beforeEach(module('myApp.services'));
|
||||
beforeEach(module('myApp.controllers'));
|
||||
|
||||
beforeEach(function () {
|
||||
inject(function (_$controller_, _$rootScope_, _, Storage, ErrorService, AppRuntimeManager) {
|
||||
$controller = _$controller_;
|
||||
$scope = _$rootScope_.$new()
|
||||
$controller('AppLangSelectController', {
|
||||
$scope: $scope,
|
||||
_: _,
|
||||
Storage: Storage,
|
||||
ErrorService: ErrorService,
|
||||
AppRuntimeManager: AppRuntimeManager
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('holds the supportedLocales', function () {
|
||||
expect($scope.supportedLocales).toBeDefined();
|
||||
});
|
||||
|
||||
it('holds langNames', function () {
|
||||
expect($scope.langNames).toBeDefined();
|
||||
});
|
||||
|
||||
it('holds the current locale', function () {
|
||||
expect($scope.curLocale).toBeDefined();
|
||||
});
|
||||
|
||||
it('has a locale form', function () {
|
||||
expect($scope.form).toBeDefined();
|
||||
expect($scope.form.locale).toBeDefined();
|
||||
});
|
||||
|
||||
it('allows to select a locale', function () {
|
||||
expect($scope.localeSelect).toBeDefined();
|
||||
});
|
||||
|
||||
describe('when the user switches the locale', function () {
|
||||
describe('and confirms the dialogue', function () {
|
||||
xit('reloads the app', function (done) {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
50
test/unit/AppWelcomeControllerSpec.js
Normal file
50
test/unit/AppWelcomeControllerSpec.js
Normal file
@ -0,0 +1,50 @@
|
||||
describe('AppWelcomeController', function () {
|
||||
var $controller, $rootScope, $scope, $location, MtApiManager, ErrorService,
|
||||
ChangelogNotifyService, LayoutSwitchService;
|
||||
|
||||
beforeEach(module('myApp.controllers'));
|
||||
|
||||
beforeEach(function () {
|
||||
ChangelogNotifyService = {
|
||||
checkUpdate: function () {}
|
||||
};
|
||||
|
||||
LayoutSwitchService = {
|
||||
start: function () {}
|
||||
};
|
||||
|
||||
MtpApiManager = {
|
||||
getUserID: function () {
|
||||
return {
|
||||
then: function () {}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
module(function ($provide) {
|
||||
$provide.value('MtpApiManager', MtpApiManager);
|
||||
});
|
||||
|
||||
inject(function (_$controller_, _$rootScope_, _$location_) {
|
||||
$controller = _$controller_;
|
||||
$rootScope = _$rootScope_;
|
||||
$location = _$location_;
|
||||
|
||||
$scope = $rootScope.$new();
|
||||
$controller('AppWelcomeController', {
|
||||
$scope: $scope,
|
||||
$location: $location,
|
||||
MtpApiManager: MtpApiManager,
|
||||
ErrorService: ErrorService,
|
||||
ChangelogNotifyService: ChangelogNotifyService,
|
||||
LayoutSwitchService: LayoutSwitchService
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// https://stackoverflow.com/a/36460924
|
||||
it('executes a dummy spec', function (done) {
|
||||
expect(true).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
56
test/unit/PhonebookContactsServiceSpec.js
Normal file
56
test/unit/PhonebookContactsServiceSpec.js
Normal file
@ -0,0 +1,56 @@
|
||||
describe('PhonebookContactsService', function () {
|
||||
var PhonebookContactsService;
|
||||
|
||||
beforeEach(module('ui.bootstrap'));
|
||||
beforeEach(module('myApp.services'));
|
||||
|
||||
beforeEach(inject(function (_PhonebookContactsService_) {
|
||||
PhonebookContactsService = _PhonebookContactsService_;
|
||||
}));
|
||||
|
||||
describe('Public API:', function () {
|
||||
it('checks availability', function () {
|
||||
expect(PhonebookContactsService.isAvailable).toBeDefined();
|
||||
});
|
||||
|
||||
it('open the phonebook for import', function () {
|
||||
expect(PhonebookContactsService.openPhonebookImport).toBeDefined();
|
||||
});
|
||||
|
||||
it('get phonebook contacts', function () {
|
||||
expect(PhonebookContactsService.getPhonebookContacts).toBeDefined();
|
||||
});
|
||||
|
||||
describe('usage', function () {
|
||||
describe('of isAvailable()', function () {
|
||||
it('returns false in most cases', function (done) {
|
||||
expect(PhonebookContactsService.isAvailable()).toBe(false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('of openPhonebookImport()', function () {
|
||||
beforeEach(function() {
|
||||
$modal = {
|
||||
open: jasmine.createSpy('open')
|
||||
};
|
||||
});
|
||||
|
||||
xit('opens a modal', function () {
|
||||
PhonebookContactsService.openPhonebookImport();
|
||||
expect($modal.open).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('of getPhonebookContacts()', function () {
|
||||
xit('will get rejected in most cases', function (done) {
|
||||
promise = PhonebookContactsService.getPhonebookContacts();
|
||||
promise.finally(function () {
|
||||
expect(promise.isFullfilled()).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
31
test/unit/chatTitleFilterSpec.js
Normal file
31
test/unit/chatTitleFilterSpec.js
Normal file
@ -0,0 +1,31 @@
|
||||
describe('chatTitle filter', function () {
|
||||
var $filter, _, chatTitleFilter;
|
||||
|
||||
beforeEach(module('myApp.filters'));
|
||||
|
||||
beforeEach(inject(function (_$filter_, ___) {
|
||||
$filter = _$filter_;
|
||||
_ = ___;
|
||||
}));
|
||||
|
||||
beforeEach(function () {
|
||||
chatTitleFilter = $filter('chatTitle');
|
||||
});
|
||||
|
||||
it('displays chat title deleted', function () {
|
||||
var expected = _('chat_title_deleted');
|
||||
var actual = chatTitleFilter(null);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it('displays the chat title', function () {
|
||||
var chat = {
|
||||
title: 'Telegraph is hot!'
|
||||
};
|
||||
var expected = chat.title;
|
||||
var actual = chatTitleFilter(chat);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
23
test/unit/myHeadDirective.js
Normal file
23
test/unit/myHeadDirective.js
Normal file
@ -0,0 +1,23 @@
|
||||
describe('myHead directive', function () {
|
||||
var $compile, $rootScope;
|
||||
|
||||
beforeEach(module('myApp.templates'));
|
||||
beforeEach(module('myApp.directives'));
|
||||
|
||||
beforeEach(inject(function (_$compile_, _$rootScope_) {
|
||||
$compile = _$compile_;
|
||||
$rootScope = _$rootScope_;
|
||||
}));
|
||||
|
||||
it('compiles a my-head attribute', function () {
|
||||
var compiledElement = $compile('<div my-head></div>')($rootScope);
|
||||
$rootScope.$digest(); // Fire watchers
|
||||
expect(compiledElement.html()).toContain('tg_page_head');
|
||||
});
|
||||
|
||||
it('compiles a my-head element', function () {
|
||||
var compiledElement = $compile('<my-head></my-head>')($rootScope);
|
||||
$rootScope.$digest(); // Fire watchers
|
||||
expect(compiledElement.html()).toContain('tg_page_head');
|
||||
});
|
||||
});
|
30
test/unit/myLangFooterDirective.js
Normal file
30
test/unit/myLangFooterDirective.js
Normal file
@ -0,0 +1,30 @@
|
||||
describe('myLangFooter directive', function () {
|
||||
var $compile, $rootScope;
|
||||
|
||||
beforeEach(module('ui.bootstrap'));
|
||||
beforeEach(module('myApp.templates'));
|
||||
// ErrorServiceProvider in myApp.services is needed by
|
||||
// AppLangSelectController in myApp.controllers
|
||||
beforeEach(module('myApp.services'));
|
||||
beforeEach(module('myApp.controllers'));
|
||||
beforeEach(module('myApp.directives'));
|
||||
|
||||
beforeEach(inject(function (_$compile_, _$rootScope_) {
|
||||
$compile = _$compile_;
|
||||
$rootScope = _$rootScope_;
|
||||
}));
|
||||
|
||||
it('compiles a my-lang-footer attribute', function () {
|
||||
var compiledElement = $compile('<div my-lang-footer></div>')($rootScope);
|
||||
$rootScope.$digest(); // Fire watchers
|
||||
expect(compiledElement.html()).toContain('footer_lang_link');
|
||||
expect(compiledElement.html()).toContain('AppLangSelectController');
|
||||
});
|
||||
|
||||
it('compiles a my-lang-footer element', function () {
|
||||
var compiledElement = $compile('<my-lang-footer></my-lang-footer>')($rootScope);
|
||||
$rootScope.$digest(); // Fire watchers
|
||||
expect(compiledElement.html()).toContain('footer_lang_link');
|
||||
expect(compiledElement.html()).toContain('AppLangSelectController');
|
||||
});
|
||||
});
|
42
test/unit/userFirstNameFilterSpec.js
Normal file
42
test/unit/userFirstNameFilterSpec.js
Normal file
@ -0,0 +1,42 @@
|
||||
describe('userFirstName filter', function () {
|
||||
var $filter, _, userFirstNameFilter;
|
||||
|
||||
beforeEach(module('myApp.filters'));
|
||||
|
||||
beforeEach(inject(function (_$filter_, ___) {
|
||||
$filter = _$filter_;
|
||||
_ = ___;
|
||||
}));
|
||||
|
||||
beforeEach(function () {
|
||||
userFirstNameFilter = $filter('userFirstName');
|
||||
});
|
||||
|
||||
it('displays user first name deleted', function () {
|
||||
var expected = _('user_first_name_deleted');
|
||||
var actual = userFirstNameFilter(null);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it('displays the first name', function () {
|
||||
var user = {
|
||||
first_name: 'John'
|
||||
};
|
||||
var expected = user.first_name;
|
||||
var actual = userFirstNameFilter(user);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it('displays the last name alternatively', function () {
|
||||
var user = {
|
||||
last_name: 'Doe'
|
||||
};
|
||||
var expected = user.last_name;
|
||||
var actual = userFirstNameFilter(user);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
});
|
42
test/unit/userNameFilterSpec.js
Normal file
42
test/unit/userNameFilterSpec.js
Normal file
@ -0,0 +1,42 @@
|
||||
describe('userName filter', function () {
|
||||
var $filter, _, userNameFilter;
|
||||
|
||||
beforeEach(module('myApp.filters'));
|
||||
|
||||
beforeEach(inject(function (_$filter_, ___) {
|
||||
$filter = _$filter_;
|
||||
_ = ___;
|
||||
}));
|
||||
|
||||
beforeEach(function () {
|
||||
userNameFilter = $filter('userName');
|
||||
});
|
||||
|
||||
it('displays user name deleted', function () {
|
||||
var expected = _('user_name_deleted');
|
||||
var actual = userNameFilter(null);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it('displays the first name', function () {
|
||||
var user = {
|
||||
first_name: 'John'
|
||||
};
|
||||
var expected = user.first_name;
|
||||
var actual = userNameFilter(user);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it('displays both, the first and the last name', function () {
|
||||
var user = {
|
||||
first_name: 'John',
|
||||
last_name: 'Doe'
|
||||
};
|
||||
var expected = user.first_name + ' ' + user.last_name;
|
||||
var actual = userNameFilter(user);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user