diff --git a/.eslintrc.json b/.eslintrc.json index 7610d2b2..81b8f889 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -25,10 +25,6 @@ 2, "single" ], - "linebreak-style": [ - 2, - "unix" - ], "semi": [ 2, "always" diff --git a/bower.json b/bower.json index 411e0c5e..0f2dd8cb 100644 --- a/bower.json +++ b/bower.json @@ -15,5 +15,7 @@ "clipboard": "~1.5.3", "wsevent.js": "~0.0.4" }, - "devDependencies": {} + "devDependencies": { + "angular-mocks": "~1.4.7" + } } diff --git a/circle.yml b/circle.yml index 0be1a8e2..8af05dc3 100644 --- a/circle.yml +++ b/circle.yml @@ -10,6 +10,7 @@ dependencies: test: override: - gulp lint + - gulp test deployment: master: branch: master diff --git a/gulp/build.js b/gulp/build.js index a4e6a42b..04ffc4db 100644 --- a/gulp/build.js +++ b/gulp/build.js @@ -1,6 +1,10 @@ 'use strict'; +var fs = require('fs'); +var glob = require('glob'); var path = require('path'); +var _ = require('lodash'); +var runSequence = require('run-sequence'); var gulp = require('gulp'); var conf = require('./conf'); @@ -109,8 +113,24 @@ gulp.task('clean', function (done) { $.del([path.join(conf.paths.dist, '/'), path.join(conf.paths.tmp, '/')], done); }); -gulp.task('build-after-cleaned', ['html', 'fonts', 'other']); +// Return only base file name without dir +function getMostRecentMtimeSync(dir) { + var files = glob.sync(path.join(dir, '**/*')); -gulp.task('build', ['clean'], function () { - gulp.start('build-after-cleaned'); + return _.max(_.map(files, function (f) { + return fs.statSync(f).mtime; + })); +} + +gulp.task('rebuild', function (cb) { + runSequence('clean', ['html', 'fonts', 'other'], cb); +}); + +gulp.task('build', function (cb) { + if (getMostRecentMtimeSync(conf.paths.src) <= getMostRecentMtimeSync(conf.paths.dist)) { + $.util.log('No modified files: not building'); + cb(); + } else { + runSequence('rebuild', cb); + } }); diff --git a/gulp/conf.js b/gulp/conf.js index c4639f1b..94312a8a 100644 --- a/gulp/conf.js +++ b/gulp/conf.js @@ -14,6 +14,7 @@ var gutil = require('gulp-util'); exports.paths = { src: 'src', dist: 'dist', + test: 'test', tmp: '.tmp', e2e: 'e2e' }; diff --git a/gulp/test.js b/gulp/test.js new file mode 100644 index 00000000..68519eb5 --- /dev/null +++ b/gulp/test.js @@ -0,0 +1,35 @@ +'use strict'; + +var path = require('path'); +var runSequence = require('run-sequence'); +var mainBowerFiles = require('main-bower-files'); +var gulp = require('gulp'); +var conf = require('./conf'); +var karma = require('karma'); + +var $ = require('gulp-load-plugins')(); + +gulp.task('test:unit', function (done) { + var server = new karma.Server({ + browsers: ['PhantomJS'], + frameworks: ['mocha', 'chai-sinon'], + files: mainBowerFiles({ includeDev: true }).concat([ + 'dist/scripts/app-*.js', + 'test/karma/**/*.js' + ]), + logLevel: 'DEBUG', + singleRun: true + }); + + server.on('run_complete', function (browsers, results) { + // NB If the argument of done() is not null or not undefined, + // e.g. a string, the next task in a series won't run. + done(results.error ? 'There are test failures' : null); + }); + + server.start(); +}); + +gulp.task('test', function (cb) { + runSequence('build', 'test:unit', cb); +}); diff --git a/package.json b/package.json index 41337645..bb7e10c8 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "license": "GPL-3.0", "repository": "https://github.com/TF2Stadium/Frontend", "readme": "readme.md", - "version": "0.3.1", + "version": "0.3.2", "dependencies": { "del": "~1.2.0", "uglify-save-license": "~0.4.1", @@ -36,18 +36,32 @@ "devDependencies": { "browser-sync": "~2.7.12", "browser-sync-spa": "~1.0.2", + "chai": "^3.4.1", + "chai-as-promised": "^5.1.0", "chalk": "^1.1.1", "concat-stream": "~1.5.0", "connect-history-api-fallback": "^1.1.0", "eslint": "^1.10.1", "eslint-plugin-angular": "^0.14.0", + "glob": "^6.0.1", "gulp-eslint": "^1.1.1", + "gulp-karma": "0.0.5", + "gulp-mocha": "^2.2.0", "gulp-protractor": "~1.0.0", "gulp-rename": "~1.2.2", "gulp-replace": "~0.5.3", "http-proxy-middleware": "~0.0.5", + "karma": "^0.13.15", + "karma-chai-sinon": "^0.1.5", + "karma-mocha": "^0.2.1", + "karma-phantomjs-launcher": "^0.2.1", "merge-stream": "~0.1.7", - "require-dir": "~0.3.0" + "mocha": "^2.3.4", + "phantomjs": "^1.9.19", + "require-dir": "~0.3.0", + "run-sequence": "^1.1.5", + "selenium-webdriver": "^2.48.2", + "sinon": "^1.17.2" }, "engines": { "node": ">=0.10.0" diff --git a/src/app/app.run.js b/src/app/app.run.js index 3561b140..c8694ef9 100644 --- a/src/app/app.run.js +++ b/src/app/app.run.js @@ -38,6 +38,7 @@ $rootScope.config = Config; Settings.getSettings(function (settings) { $rootScope.currentTheme = settings.currentTheme; + $rootScope.currentTimestampsOption = settings.timestamps; $rootScope.themeLoaded = true; }); diff --git a/src/app/app.settings.js b/src/app/app.settings.js index d4f8c283..aef30b4c 100644 --- a/src/app/app.settings.js +++ b/src/app/app.settings.js @@ -53,12 +53,19 @@ dark: {name: 'TF2Stadium Dark', selector: 'dark-theme'} }; + SettingsProvider.constants.timestampOptions = { + hours12: {name: '12-hour'}, + hours24: {name: '24-hour'}, + none: {name: 'None'} + }; + SettingsProvider.constants.sound = { soundVolume: {name: 'Notifications volume'} }; function setDefaultValues() { SettingsProvider.settings.currentTheme = 'default-theme'; + SettingsProvider.settings.timestamps = 'hours12'; /* Defaults every value found in the filters to true. diff --git a/src/app/pages/settings/section-theme.html b/src/app/pages/settings/section-theme.html index 8d8f7186..c7215968 100644 --- a/src/app/pages/settings/section-theme.html +++ b/src/app/pages/settings/section-theme.html @@ -1,11 +1,22 @@