Browse Source

Add karma, Jasmine, deps and karma.conf.js. Fixes #1291 (#1293)

* 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`.
master
André Jaenisch 7 years ago committed by Igor Zhukov
parent
commit
6f8676dd74
  1. 5
      .gitignore
  2. 31
      gulpfile.js
  3. 111
      karma.conf.js
  4. 9
      package.json
  5. 50
      test/unit/AppLangSelectControllerSpec.js
  6. 50
      test/unit/AppWelcomeControllerSpec.js
  7. 56
      test/unit/PhonebookContactsServiceSpec.js
  8. 31
      test/unit/chatTitleFilterSpec.js
  9. 23
      test/unit/myHeadDirective.js
  10. 30
      test/unit/myLangFooterDirective.js
  11. 42
      test/unit/userFirstNameFilterSpec.js
  12. 42
      test/unit/userNameFilterSpec.js

5
.gitignore vendored

@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
.idea
.publish
*.sublime-workspace
*.*~
*.swp
# Node.js package manager
node_modules
@ -12,4 +14,5 @@ releases @@ -12,4 +14,5 @@ releases
webogram*.zip
app/js/templates.js
app/css
cldr
cldr
coverage/

31
gulpfile.js

@ -8,6 +8,7 @@ var st = require('st') @@ -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 () { @@ -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 () @@ -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

@ -0,0 +1,111 @@ @@ -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,
})
}

9
package.json

@ -19,7 +19,8 @@ @@ -19,7 +19,8 @@
"show": true
},
"scripts": {
"start": "node server.js"
"start": "gulp watch",
"test": "gulp test"
},
"repository": {
"type": "git",
@ -65,6 +66,12 @@ @@ -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

@ -0,0 +1,50 @@ @@ -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

@ -0,0 +1,50 @@ @@ -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

@ -0,0 +1,56 @@ @@ -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

@ -0,0 +1,31 @@ @@ -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

@ -0,0 +1,23 @@ @@ -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

@ -0,0 +1,30 @@ @@ -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

@ -0,0 +1,42 @@ @@ -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

@ -0,0 +1,42 @@ @@ -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…
Cancel
Save