'use strict'; const apidoc = require('gulp-apidoc'), documentation = require('gulp-documentation'), eslint = require('gulp-eslint'), gulp = require('gulp'), istanbul = require('gulp-istanbul'), jscs = require('gulp-jscs'), mocha = require('gulp-mocha'), pipe = require('gulp-pipe'), nsp = require('gulp-nsp'); /* * Path(s) to all source files */ const SRC_FILES = [ 'app/base/**/*.js', 'app/config/**/*.js', 'app/controllers/**/*.js', 'app/helpers/**/*.js', 'app/models/**/*.js', 'app/*.js', ]; /* * Path to unit test files */ const UNIT_TEST_FILES = ['test/unit/**/*_test.js']; /* * Path to integration test files */ const INTEGRATION_TEST_FILES = ['test/integration/**/*_test.js']; /* * Path(s) to all test files */ const TEST_FILES = ['test/**/*_test.js']; /* * Configuration values for eslint */ const ESLINT_SETTINGS = { env: { node: true, es6: true, }, // Each rule has an error level (0-2), and some have extra parameters // 0 turns a rule off // 1 makes a rule give a warning // 2 makes a rule fail linting rules: { 'linebreak-style': [2, 'unix'], // Only unix line endings 'arrow-parens': [2, 'always'], // No parens on arrow functions with one param 'no-console': [1], // Avoid using console methods 'no-constant-condition': [1], 'no-extra-semi': [1], // Enliminate extra semicolons 'no-func-assign': [1], 'no-obj-calls': [2], 'no-unexpected-multiline': [2], // Catch syntax errors due to automatic semicolon insertion 'no-unneeded-ternary': [2], // Avoid redundant ternary expressions radix: [2], // Require radix parameter on parseInt 'no-with': [2], // No use of with construct 'no-eval': [2], // No use of eval 'no-unreachable': [1], // Avoid code that is not reachable 'no-irregular-whitespace': [1], // Highlight whitespace that isn't a tab or space 'no-new-wrappers': [2], // Avoid using primitive constructors 'no-new-func': [2], // Avoid Function constructor eval curly: [2, 'multi-line'], // Require braces for if,for,while,do contructs that are not on the same line 'no-implied-eval': [2], // Avoid camoflauged eval 'no-invalid-this': [2], 'constructor-super': [2], 'no-dupe-args': [2], // Disallow functions to have more than one parameter with the same name 'no-dupe-keys': [2], // Disaalow objects to have more than one property with the same name 'no-dupe-class-members': [2], // Disallow classes to have more than one method/memeber with the same name 'no-this-before-super': [2], 'prefer-arrow-callback': [1], // Prefer arrow functions for callbacks 'no-var': [2], // Use let or const instead of var 'valid-jsdoc': [1], semi: [2, 'always'], // Require use of semicolons strict: [2, 'global'], // have a global 'use strict' in every code file 'callback-return': [1], // return when invoking a callback 'object-shorthand': [1, 'methods'], // Prefer shorthand for functions in object literals/classes, but avoid property shorthand 'prefer-template': [1], // Prefer template strings eg. `Hello ${name}`, to string concatenation 'no-case-declarations': [2], // Don't define variables in switch labels 'no-const-assign': [2], // Highlight instances where assigning to const declaration 'no-new-symbol': [2], // Symbol is not a constructor, don't use the new keyword 'no-unused-labels': [2], // Error on labels in code that aren't used }, }; /* * Configuration values for mocha */ const MOCHA_SETTINGS = { ui: 'tdd', bail: true, slow: 1000, timeout: 5000, }; /* * Check syntax and style of test/miscellaneous files */ gulp.task('lint-tests', () => { const LINT_TESTS_FILES = TEST_FILES.concat([ 'gulpfile.js', 'server.js', ]); // eslint pipe(gulp.src(LINT_TESTS_FILES), [ eslint(ESLINT_SETTINGS), eslint.format(), eslint.failAfterError(), ]); // JSCS rules are defined in /.jscsrc pipe(gulp.src(['test/**/*.js', 'gulpfile.js']), [ jscs(), jscs.reporter(), ]); }); /* * Check syntax and style of source files */ gulp.task('lint-src', () => { // eslint pipe(gulp.src(SRC_FILES), [ eslint(ESLINT_SETTINGS), eslint.format(), eslint.failAfterError(), ]); // JSCS // JSCS rules are defined in /.jscsrc pipe(gulp.src(SRC_FILES), [ jscs(), jscs.reporter(), ]); }); /* * Run all lint tasks */ gulp.task('lint', ['lint-src', 'lint-tests']); /* * Create internal method documentation of source files */ gulp.task('src-docs', () => { pipe(gulp.src(SRC_FILES), [ documentation({ format: 'html', }), gulp.dest('public/docs'), ]); }); /* * Create api documentation from source files */ gulp.task('api-docs', (done) => { apidoc({ src: 'app/', dest: 'public/api-docs/', }, done); }); /* * Run all documentation generation tasks */ gulp.task('docs', ['src-docs', 'api-docs']); /* * Run integration tests */ gulp.task('integration-test', ['lint'], () => { return gulp.src(INTEGRATION_TEST_FILES) .pipe(mocha(MOCHA_SETTINGS)); }); /* * Run unit tests */ gulp.task('unit-test', ['lint'], () => { return gulp.src(UNIT_TEST_FILES) .pipe(mocha(MOCHA_SETTINGS)); }); /* * Run all tests */ gulp.task('test', ['lint'], () => { return gulp.src(TEST_FILES) .pipe(mocha(MOCHA_SETTINGS)); }); /* * Run hooks for istanbul coverage generation */ gulp.task('pre-coverage', () => { return pipe(gulp.src(SRC_FILES), [ istanbul(), istanbul.hookRequire(), ]); }); /* * Run unit tests and generate code coverage * * Does not run integration tests */ gulp.task('coverage', ['lint', 'pre-coverage'], () => { return pipe(gulp.src(UNIT_TEST_FILES), [ mocha(MOCHA_SETTINGS), istanbul.writeReports({ dir: 'public/coverage', reporters:['lcov', 'lcovonly', 'html', 'text'], }), ]); }); /* * Check dependencies for known security vulnerabilites */ gulp.task('audit', (cb) => { nsp({ package: `${__dirname}/package.json`, }, cb); }); /* * Run all tasks */ gulp.task('default', [ 'audit', 'lint', 'docs', 'coverage', ]); // End of gulpfile.js