--- a
+++ b/Gruntfile.js
@@ -0,0 +1,80 @@
+'use strict';
+
+module.exports = function(grunt) {
+ grunt.initConfig({
+ jshint: {
+ options: {
+ jshintrc: '.jshintrc',
+ ignores: []
+ },
+ all: {
+ src: [
+ 'Gruntfile.js',
+ 'tasks/**/*.js',
+ 'test/**/**/*.js',
+ 'backend/**/*.js',
+ 'frontend/js/**/*.js'
+ ]
+ }
+ },
+ jscs: {
+ options: {
+ config: '.jscsrc'
+ },
+ all: {
+ src: ['<%= jshint.all.src %>']
+ }
+ },
+ lint_pattern: {
+ options: {
+ rules: [
+ { pattern: /(describe|it)\.only/, message: 'Must not use .only in tests' }
+ ]
+ },
+ all: {
+ src: ['<%= jshint.all.src %>']
+ },
+ css: {
+ options: {
+ rules: [
+ { pattern: /important;(\s*$|(?=\s+[^\/]))/, message: 'CSS important rules only allowed with explanatory comment' }
+ ]
+ },
+ src: [
+ 'frontend/css/**/*.less'
+ ]
+ }
+ },
+
+ mochacli: {
+ options: {
+ require: ['chai', 'mockery'],
+ reporter: 'spec',
+ timeout: process.env.TEST_TIMEOUT || 20000
+ },
+ backend: {
+ options: {
+ files: ['test/unit-backend/all.js', grunt.option('test') || 'test/unit-backend/**/*.js']
+ }
+ }
+ },
+ karma: {
+ unit: {
+ configFile: './test/config/karma.conf.js',
+ browsers: ['PhantomJS']
+ }
+ }
+ });
+
+ grunt.loadNpmTasks('grunt-contrib-jshint');
+ grunt.loadNpmTasks('grunt-lint-pattern');
+ grunt.loadNpmTasks('grunt-jscs');
+ grunt.loadNpmTasks('grunt-mocha-cli');
+ grunt.loadNpmTasks('grunt-karma');
+
+ grunt.registerTask('linters', 'Check code for lint', ['jshint:all', 'jscs:all', 'lint_pattern']);
+ grunt.registerTask('test-unit-backend', 'Test backend code', ['mochacli:backend']);
+ grunt.registerTask('test-unit-frontend', 'Test frontend code', ['karma:unit']);
+ grunt.registerTask('test', ['linters', 'test-unit-frontend', 'test-unit-backend']);
+ grunt.registerTask('default', ['test']);
+};