diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 0000000..e96a2cd --- /dev/null +++ b/.jscsrc @@ -0,0 +1,49 @@ +{ + "disallowKeywords": ["with"], + "disallowKeywordsOnNewLine": ["else"], + "disallowMixedSpacesAndTabs": true, + "disallowMultipleLineStrings": true, + "disallowNewlineBeforeBlockStatements": true, + "disallowSpaceAfterObjectKeys": true, + "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], + "disallowSpaceBeforeBinaryOperators": [","], + "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], + "requireSpacesInAnonymousFunctionExpression": { + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInCallExpression": true, + "disallowSpacesInFunctionDeclaration": { + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInNamedFunctionExpression": { + "beforeOpeningRoundBrace": true + }, + "requireSpacesInsideArrayBrackets": { + "allExcept": [ "[", "]", "{", "}" ] + }, + "requireSpaceBeforeKeywords": [ + "else", + "while", + "catch" + ], + "disallowSpacesInsideParentheses": true, + "disallowTrailingComma": true, + "disallowTrailingWhitespace": true, + "requireCommaBeforeLineBreak": true, + "requireLineFeedAtFileEnd": true, + "requireSpaceAfterBinaryOperators": ["?", ":", "+", "-", "/", "*", "%", "==", "===", "!=", "!==", ">", ">=", "<", "<=", "&&", "||"], + "requireSpaceBeforeBinaryOperators": ["?", ":", "+", "-", "/", "*", "%", "==", "===", "!=", "!==", ">", ">=", "<", "<=", "&&", "||"], + "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"], + "requireSpaceBeforeBlockStatements": true, + "requireSpacesInConditionalExpression": { + "afterTest": true, + "beforeConsequent": true, + "afterConsequent": true, + "beforeAlternate": true + }, + "requireSpacesInForStatement": true, + "requireSpacesInFunction": { + "beforeOpeningCurlyBrace": true + }, + "validateLineBreaks": "LF" +} diff --git a/Gruntfile.js b/Gruntfile.js index a62b2e1..3397c90 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -24,59 +24,60 @@ module.exports = function (grunt) { version: require('./bower.json').version, app: require('./bower.json').appPath, dist: 'dist', + test: 'test' }, bump: { options: { - files: ['package.json', 'bower.json'], - updateConfigs: ['yeoman'], + files: [ 'package.json', 'bower.json' ], + updateConfigs: [ 'yeoman' ], commit: true, commitMessage: 'chore(release): release v%VERSION%. See CHANGELOG.md', - commitFiles: ['-a'], // '-a' for all files + commitFiles: [ '-a' ], // '-a' for all files createTag: true, tagName: 'v%VERSION%', tagMessage: 'Version %VERSION%', push: true, - pushTo: 'origin', - gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d', // options to use with '$ git describe' - }, + pushTo: 'origin master', + gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d' // options to use with '$ git describe' + } }, conventionalChangelog: { options: { changelogOpts: { - preset: 'angular', - }, + preset: 'angular' + } }, release: { - src: 'CHANGELOG.md', - }, + src: 'CHANGELOG.md' + } }, // Watches files for changes and runs tasks based on the changed files watch: { js: { - files: ['<%= yeoman.app %>/scripts/{,*/}*.js'], - tasks: ['newer:jshint:all', 'karma:default'], + files: [ '<%= yeoman.app %>/scripts/{,*/}*.js' ], + tasks: [ 'newer:jshint:all', 'karma:default' ], options: { - livereload: true, - }, + livereload: true + } }, jsTest: { - files: ['test/spec/{,*/}*.js'], - tasks: ['newer:jshint:test', 'karma:default'], + files: [ 'test/spec/{,*/}*.js' ], + tasks: [ 'newer:jshint:test', 'karma:default' ] }, gruntfile: { - files: ['Gruntfile.js'], + files: [ 'Gruntfile.js' ] }, livereload: { options: { - livereload: '<%= connect.options.livereload %>', + livereload: '<%= connect.options.livereload %>' }, files: [ - '<%= yeoman.app %>/{,*/}*.html', - ], - }, + '<%= yeoman.app %>/{,*/}*.html' + ] + } }, // The actual grunt server settings @@ -85,42 +86,55 @@ module.exports = function (grunt) { port: 0, // Change this to '0.0.0.0' to access the server from outside. hostname: 'localhost', - livereload: 35729, + livereload: 35729 }, test: { options: { port: 0, base: [ 'test', - '<%= yeoman.app %>', - ], - }, + '<%= yeoman.app %>' + ] + } }, livereload: { options: { open: true, base: [ - '<%= yeoman.app %>', - ], - }, - }, + '<%= yeoman.app %>' + ] + } + } }, // Make sure code styles are up to par and there are no obvious mistakes jshint: { options: { jshintrc: '.jshintrc', - reporter: require('jshint-stylish'), + reporter: require('jshint-stylish') }, all: [ 'Gruntfile.js', - '<%= yeoman.app %>/scripts/{,*/}*.js', + '<%= yeoman.app %>/scripts/{,*/}*.js' ], test: { options: { - jshintrc: 'test/.jshintrc', + jshintrc: 'test/.jshintrc' }, - src: ['test/spec/{,*/}*.js'], + src: [ 'test/spec/{,*/}*.js' ] + } + }, + + // Check code style guidelines + jscs: { + src: [ + '<%= yeoman.app %>/scripts/**/*.js', + '<%= yeoman.test %>/spec/**/*.js', + '*.js' + ], + options: { + config: '.jscsrc', + verbose: true } }, @@ -131,53 +145,53 @@ module.exports = function (grunt) { dot: true, src: [ '<%= yeoman.dist %>/*', - '!<%= yeoman.dist %>/.git*', - ], - }], - }, + '!<%= yeoman.dist %>/.git*' + ] + }] + } }, // Allow the use of non-minsafe AngularJS files. Automatically makes it // minsafe compatible so Uglify does not destroy the ng references ngAnnotate: { options: { - singleQuotes: true, + singleQuotes: true }, dist: { - src: ['<%= yeoman.dist %>/angular-apimock.js'], - dest: '<%= yeoman.dist %>/angular-apimock.js', - }, + src: [ '<%= yeoman.dist %>/angular-apimock.js' ], + dest: '<%= yeoman.dist %>/angular-apimock.js' + } }, // Replace Google CDN references cdnify: { dist: { - html: ['<%= yeoman.dist %>/*.html'], - }, + html: [ '<%= yeoman.dist %>/*.html' ] + } }, uglify: { options: { preserveComments: 'some', - report: 'gzip', + report: 'gzip' }, dist: { files: { '<%= yeoman.dist %>/angular-apimock.min.js': [ - '<%= yeoman.dist %>/angular-apimock.js', - ], - }, - }, + '<%= yeoman.dist %>/angular-apimock.js' + ] + } + } }, concat: { options: { - banner: '/*! Angular API Mock v<%= yeoman.version %>\n * Licensed with MIT\n * Made with ♥ from Seriema + Redhorn */\n', + banner: '/*! Angular API Mock v<%= yeoman.version %>\n * Licensed with MIT\n * Made with ♥ from Seriema + Redhorn */\n' }, dist: { src: '<%= yeoman.app %>/scripts/**/*.js', - dest: '<%= yeoman.dist %>/angular-apimock.js', - }, + dest: '<%= yeoman.dist %>/angular-apimock.js' + } }, nugetpack: { @@ -185,28 +199,28 @@ module.exports = function (grunt) { src: 'package.nuspec', dest: 'nuget/', options: { - version: '<%= yeoman.version %>', - }, - }, + version: '<%= yeoman.version %>' + } + } }, nugetpush: { dist: { - src: 'nuget/Angular-ApiMock.<%= yeoman.version %>.nupkg', - }, + src: 'nuget/Angular-ApiMock.<%= yeoman.version %>.nupkg' + } }, // Test settings karma: { options: { configFile: 'karma.conf.js', - singleRun: true, + singleRun: true }, default: { // Default }, sauce: { - browsers: ['SL_Chrome', 'SL_Firefox', 'SL_Safari', 'SL_iOS', 'SL_IE_8', 'SL_IE_9', 'SL_IE_10', 'SL_IE_11'], + browsers: [ 'SL_Chrome', 'SL_Firefox', 'SL_Safari', 'SL_iOS', 'SL_IE_8', 'SL_IE_9', 'SL_IE_10', 'SL_IE_11' ], reporters: [ 'progress', 'saucelabs' ], files: [{ src: [ @@ -214,19 +228,19 @@ module.exports = function (grunt) { 'test/ref/angular-v1.2.js', 'test/ref/angular-mocks-v1.2.js', '<%= watch.js.files %>', - '<%= watch.jsTest.files %>', - ]}, - ], + '<%= watch.jsTest.files %>' + ]} + ] }, coverage: { - browsers: ['PhantomJS'], + browsers: [ 'PhantomJS' ], reporters: [ 'dots', 'coverage' ], coverageReporter: { reporters: [ { type: 'lcov', subdir: 'PhantomJS' }, - { type: 'text' }, - ], - }, + { type: 'text' } + ] + } }, dist: { files: [{ @@ -234,9 +248,9 @@ module.exports = function (grunt) { 'app/bower_components/angular/angular.js', 'app/bower_components/angular-mocks/angular-mocks.js', '<%= yeoman.dist %>/*.min.js', - '<%= watch.jsTest.files %>', - ]}, - ], + '<%= watch.jsTest.files %>' + ]} + ] }, angular12: { files: [{ @@ -244,9 +258,9 @@ module.exports = function (grunt) { 'test/ref/angular-v1.2.js', 'test/ref/angular-mocks-v1.2.js', '<%= watch.js.files %>', - '<%= watch.jsTest.files %>', - ]}, - ], + '<%= watch.jsTest.files %>' + ]} + ] }, angular13: { files: [{ @@ -254,9 +268,9 @@ module.exports = function (grunt) { 'test/ref/angular-v1.3.js', 'test/ref/angular-mocks-v1.3.js', '<%= watch.js.files %>', - '<%= watch.jsTest.files %>', - ]}, - ], + '<%= watch.jsTest.files %>' + ]} + ] }, angular14: { files: [{ @@ -264,34 +278,35 @@ module.exports = function (grunt) { 'test/ref/angular-v1.4.js', 'test/ref/angular-mocks-v1.4.js', '<%= watch.js.files %>', - '<%= watch.jsTest.files %>', - ]}, - ], - }, + '<%= watch.jsTest.files %>' + ]} + ] + } }, // To run locally you need to set `COVERALLS_REPO_TOKEN` as an environment variable. // It's currently being run from Travis-CI (see .travis.yml) coveralls: { options: { - force: true, + force: true }, - src: 'coverage/**/*.info', - }, + src: 'coverage/**/*.info' + } }); grunt.registerTask('serve', [ 'connect', - 'watch:js', + 'watch:js' ]); grunt.registerTask('test', [ 'jshint', + 'jscs', 'connect:test', 'karma:coverage', 'karma:angular12', 'karma:angular13', - 'karma:angular14', + 'karma:angular14' ]); grunt.registerTask('build', [ @@ -299,7 +314,7 @@ module.exports = function (grunt) { 'concat', 'ngAnnotate', 'uglify', - 'karma:dist', + 'karma:dist' ]); grunt.registerTask('_publish', [ @@ -307,15 +322,15 @@ module.exports = function (grunt) { 'nugetpack', 'conventionalChangelog', 'bump-commit', - 'nugetpush', + 'nugetpush' ]); - grunt.registerTask('publish', ['publish:patch']); - grunt.registerTask('publish:patch', ['test', 'karma:sauce', 'bump-only:patch', '_publish']); - grunt.registerTask('publish:minor', ['test', 'karma:sauce', 'bump-only:minor', '_publish']); - grunt.registerTask('publish:major', ['test', 'karma:sauce', 'bump-only:major', '_publish']); + grunt.registerTask('publish', [ 'publish:patch' ]); + grunt.registerTask('publish:patch', [ 'test', 'karma:sauce', 'bump-only:patch', '_publish' ]); + grunt.registerTask('publish:minor', [ 'test', 'karma:sauce', 'bump-only:minor', '_publish' ]); + grunt.registerTask('publish:major', [ 'test', 'karma:sauce', 'bump-only:major', '_publish' ]); grunt.registerTask('default', [ - 'test', + 'test' ]); }; diff --git a/app/scripts/angular-apimock.js b/app/scripts/angular-apimock.js index 4034dd7..a544542 100644 --- a/app/scripts/angular-apimock.js +++ b/app/scripts/angular-apimock.js @@ -47,7 +47,7 @@ angular.module('apiMock', []) apiPath: '/api', disable: false, stripQueries: true, - delay: 0, + delay: 0 }; var fallbacks = []; @@ -109,11 +109,11 @@ angular.module('apiMock', []) } if (angular.isArray(toSerialize)) { - angular.forEach(toSerialize, function(value, index) { + angular.forEach(toSerialize, function (value, index) { serialize(value, prefix + '[' + (angular.isObject(value) ? index : '') + ']'); }); } else if (angular.isObject(toSerialize) && !angular.isDate(toSerialize)) { - forEachSorted(toSerialize, function(value, key) { + forEachSorted(toSerialize, function (value, key) { serialize(value, prefix + (topLevel ? '' : '[') + key + @@ -136,7 +136,7 @@ angular.module('apiMock', []) var paramArray = paramString.split('&'); var result = {}; - angular.forEach(paramArray, function(param) { + angular.forEach(paramArray, function (param) { param = param.split('='); result[param[0]] = param[1] || ''; }); @@ -216,14 +216,14 @@ angular.module('apiMock', []) angular.forEach(apiPath, function (path) { if (match) { return; } // Hack to skip more recursive calls if already matched var found = apiPathMatched(url, path); - if (found) { - match = found; + if (found) { + match = found; } }); } - if (match) { - return match; - } + if (match) { + return match; + } if (apiPath instanceof RegExp) { if (apiPath.test(url)) { return apiPath; @@ -276,7 +276,7 @@ angular.module('apiMock', []) var params = angular.extend(req.params || {}, queryParamsFromUrl); //test if there is already a trailing / - if (newPath[newPath.length-1] !== '/') { + if (newPath[newPath.length - 1] !== '/') { newPath += '/'; } @@ -382,7 +382,7 @@ angular.module('apiMock', []) }; }) - .service('httpInterceptor', function($injector, $q, $timeout, apiMock) { + .service('httpInterceptor', function ($injector, $q, $timeout, apiMock) { /* The main service. Is jacked in as a interceptor on `$http` so it gets called * on every http call. This allows us to do our magic. It uses the provider * `apiMock` to determine if a mock should be done, then do the actual mocking. @@ -398,9 +398,9 @@ angular.module('apiMock', []) var deferred = $q.defer(); $timeout( - function() { + function () { // TODO: Apparently, no tests break regardless what this resolves to. Fix the tests! - deferred.resolve( apiMock.onResponse(res) ); + deferred.resolve(apiMock.onResponse(res)); }, apiMock.getDelay(), true // Trigger a $digest. @@ -422,7 +422,7 @@ angular.module('apiMock', []) deferred.resolve(data); }); } else { - deferred.reject( rej ); + deferred.reject(rej); } }, apiMock.getDelay(), diff --git a/karma-e2e.conf.js b/karma-e2e.conf.js index 42ff851..d097247 100644 --- a/karma-e2e.conf.js +++ b/karma-e2e.conf.js @@ -1,13 +1,13 @@ // Karma configuration // http://karma-runner.github.io/0.10/config/configuration-file.html -module.exports = function(config) { +module.exports = function (config) { config.set({ // base path, that will be used to resolve files and exclude basePath: '', // testing framework to use (jasmine/mocha/qunit/...) - frameworks: ['ng-scenario'], + frameworks: [ 'ng-scenario' ], // list of files / patterns to load in the browser files: [ @@ -37,7 +37,7 @@ module.exports = function(config) { // - Safari (only Mac) // - PhantomJS // - IE (only Windows) - browsers: ['Firefox'], + browsers: [ 'Firefox' ], // Continuous Integration mode diff --git a/karma.conf.js b/karma.conf.js index 22aa62a..63b0762 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,8 +1,8 @@ // Karma configuration // http://karma-runner.github.io/0.10/config/configuration-file.html -module.exports = function(config) { - var sourcePreprocessors = ['coverage']; +module.exports = function (config) { + var sourcePreprocessors = [ 'coverage' ]; function isDebug(argument) { return argument === '--debug'; } @@ -15,7 +15,7 @@ module.exports = function(config) { basePath: '', // testing framework to use (jasmine/mocha/qunit/...) - frameworks: ['jasmine'], + frameworks: [ 'jasmine' ], // reporter style reporters: [ 'progress' ], @@ -58,7 +58,7 @@ module.exports = function(config) { // - Safari (only Mac) // - PhantomJS // - IE (only Windows) - browsers: ['PhantomJS'], + browsers: [ 'PhantomJS' ], // Check out https://saucelabs.com/platforms for all browser/platform combos captureTimeout: 120000, @@ -106,7 +106,7 @@ module.exports = function(config) { // You need to set `SAUCE_USERNAME` and `SAUCE_ACCESS_KEY` as environment variables. sauceLabs: { testName: 'Angular ApiMock', - startConnect: true, + startConnect: true }, // Continuous Integration mode diff --git a/package.json b/package.json index 6071d61..9b0510b 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "grunt-contrib-watch": "^0.6.0", "grunt-conventional-changelog": "^4.1.0", "grunt-coveralls": "^1.0.0", + "grunt-jscs": "^2.1.0", "grunt-karma": "^0.12.0", "grunt-newer": "^1.1.0", "grunt-ng-annotate": "^1.0.1", diff --git a/test/spec/services/angular-apimock.js b/test/spec/services/angular-apimock.js index fda1ddf..4b025c2 100644 --- a/test/spec/services/angular-apimock.js +++ b/test/spec/services/angular-apimock.js @@ -8,7 +8,7 @@ describe('Service: apiMock', function () { // Hack (?) to get the provider so we can call .config() var apiMockProvider; - beforeEach(module(function(_apiMockProvider_){ + beforeEach(module(function (_apiMockProvider_) { apiMockProvider = _apiMockProvider_; })); @@ -138,7 +138,7 @@ describe('Service: apiMock', function () { 'ApiMock' ]; - angular.forEach(keys, function(key) { + angular.forEach(keys, function (key) { // Set location with the query string. $location.search(key, value); @@ -157,7 +157,7 @@ describe('Service: apiMock', function () { // Cannot use $httpBackend.expect() because HTTP status doesn't do a request $http(defaultRequest) .success(fail) - .error(function(data, status) { + .error(function (data, status) { expect(apiMock._countFallbacks()).toEqual(0); expect(status).toEqual(200); }); @@ -172,7 +172,7 @@ describe('Service: apiMock', function () { // Cannot use $httpBackend.expect() because HTTP status doesn't do a request $http(defaultRequest) .success(fail) - .error(function(data, status) { + .error(function (data, status) { expect(apiMock._countFallbacks()).toEqual(0); expect(status).toEqual(200); }); @@ -283,7 +283,7 @@ describe('Service: apiMock', function () { // Cannot use $httpBackend.expect() because HTTP status doesn't do a request $http(defaultRequest) .success(fail) - .error(function(data, status) { + .error(function (data, status) { expect(apiMock._countFallbacks()).toEqual(0); expect(status).toEqual(option); }); @@ -297,7 +297,7 @@ describe('Service: apiMock', function () { // Cannot use $httpBackend.expect() because HTTP status doesn't do a request $http(defaultRequest) .success(fail) - .error(function(data, status, headers) { + .error(function (data, status, headers) { expect(apiMock._countFallbacks()).toEqual(0); expect(headers).toExist; expect(headers['Content-Type']).toEqual('text/html; charset=utf-8'); @@ -370,7 +370,7 @@ describe('Service: apiMock', function () { ]; angular.forEach(verbs, function (verb) { - defaultExpectPath = '/mock_data/pokemon.'+verb.toLowerCase()+'.json'; + defaultExpectPath = '/mock_data/pokemon.' + verb.toLowerCase() + '.json'; defaultRequest.method = verb; expectHttpSuccess(); @@ -410,11 +410,11 @@ describe('Service: apiMock', function () { describe('disable option', function () { - beforeEach(function() { + beforeEach(function () { apiMockProvider.config({disable: true}); }); - afterEach(function() { + afterEach(function () { apiMockProvider.config({disable: false}); }); @@ -442,13 +442,13 @@ describe('Service: apiMock', function () { describe('allow regexp for apiPath option instead of string', function () { - beforeEach(function() { + beforeEach(function () { // apiMockProvider.config({apiPath: [/\/(aPI)/i]}); apiMockProvider.config({apiPath: /\/(aPi|UPI|APU)/i}); setGlobalCommand(true); }); - afterEach(function() { + afterEach(function () { apiMockProvider.config({apiPath: '/api'}); unsetGlobalCommand(); }); @@ -475,12 +475,12 @@ describe('Service: apiMock', function () { describe('allow strings array for apiPath option', function () { - beforeEach(function() { - apiMockProvider.config({apiPath: ['/other/api', '/api', '/v2api']}); + beforeEach(function () { + apiMockProvider.config({apiPath: [ '/other/api', '/api', '/v2api' ]}); setGlobalCommand(true); }); - afterEach(function() { + afterEach(function () { apiMockProvider.config({apiPath: '/api'}); unsetGlobalCommand(); }); @@ -513,12 +513,12 @@ describe('Service: apiMock', function () { describe('allow regexp array for apiPath option', function () { - beforeEach(function() { - apiMockProvider.config({apiPath: [/\/other\/api/i, /\/api/i, /\/v(2|3|4)api/i]}); + beforeEach(function () { + apiMockProvider.config({apiPath: [ /\/other\/api/i, /\/api/i, /\/v(2|3|4)api/i ]}); setGlobalCommand(true); }); - afterEach(function() { + afterEach(function () { apiMockProvider.config({apiPath: '/api'}); unsetGlobalCommand(); }); @@ -558,12 +558,12 @@ describe('Service: apiMock', function () { describe('enable query params', function () { - beforeEach(function() { + beforeEach(function () { apiMockProvider.config({stripQueries: false}); setGlobalCommand(true); }); - afterEach(function() { + afterEach(function () { apiMockProvider.config({stripQueries: true}); unsetGlobalCommand(); }); @@ -574,7 +574,7 @@ describe('Service: apiMock', function () { it('should still ignore config.data', function () { defaultRequest.data = { - 'moves': ['Thunder Shock', 'Volt Tackle'] + 'moves': [ 'Thunder Shock', 'Volt Tackle' ] }; expectHttpSuccess(); @@ -647,7 +647,7 @@ describe('Service: apiMock', function () { it('should serialize nested arrays', function () { defaultRequest.url = '/api/pokemon'; defaultRequest.params = { - 'moves': ['Thunder Shock', 'Volt Tackle'] + 'moves': [ 'Thunder Shock', 'Volt Tackle' ] }; defaultExpectPath = '/mock_data/pokemon/moves%5b%5d=thunder+shock&moves%5b%5d=volt+tackle.get.json'; @@ -658,12 +658,12 @@ describe('Service: apiMock', function () { describe('delay option', function () { var delayMs = 500; - beforeEach(function() { + beforeEach(function () { apiMockProvider.config({delay: delayMs}); setGlobalCommand(true); }); - afterEach(function() { + afterEach(function () { apiMockProvider.config({delay: 0}); unsetGlobalCommand(); }); @@ -681,7 +681,7 @@ describe('Service: apiMock', function () { $httpBackend.flush(); // Don't flush $timeout completely. - $timeout.flush(delayMs-1); + $timeout.flush(delayMs - 1); expect($timeout.verifyNoPendingTasks).toThrow(); $rootScope.$digest(); expect(didRun).toBe(false);