3 var gulp
= require('gulp');
4 var gutil
= require('gulp-util');
5 var runSequence
= require('run-sequence');
6 var using
= require('gulp-using');
7 var codecov
= require('gulp-codecov');
8 var lcovMerger
= require('lcov-result-merger');
9 var path
= require('path');
10 var mkdirp
= require('mkdirp');
11 var glob
= require('glob');
12 var childProcessPromise
= require('./child-process-promise');
13 var del
= require('del');
14 var Promise
= require('bluebird');
16 var argv
= require('yargs')
17 .option('test-suite', {
18 describe
: 'test-suite to run',
19 choices
: ['local', 'mocha', 'docker'],
22 .option('test-fast', {
23 describe
: 'only run fast tests',
27 .option('test-parallel', {
28 describe
: 'run tests in parallel',
32 .option('test-coverage', {
33 describe
: 'generate coverage on tests',
37 .option('test-bail', {
38 describe
: 'bail on first failure',
42 .option('test-xunit-reports', {
43 describe
: 'generate xunit reports',
47 .option('test-grep', {
49 describe
: 'grep tests',
52 .option('test-critical-only', {
53 describe
: 'only test critical tests',
57 .help('test-help').argv
;
59 /* Don't do clean in gulp, use make */
60 var RUN_TESTS_IN_PARALLEL
= argv
['test-parallel'];
61 var generateCoverage
= argv
['test-coverage'];
62 var generateXUnitReports
= argv
['test-xunit-reports'];
63 var bail
= argv
['test-bail'];
64 var testSuite
= argv
['test-suite'];
65 var fast
= argv
['test-fast'];
66 var grep
= argv
['test-grep'];
67 var criticalOnly
= argv
['test-critical-only'];
68 const disableGitHubTests
=
69 process
.env
.DISABLE_GITHUB_TESTS
&& JSON
.parse(process
.env
.DISABLE_GITHUB_TESTS
);
73 var modulesWithTest
= glob
.sync('./modules/*/test');
75 modulesWithTest
.forEach(function(testDir
) {
76 var moduleDir
= path
.dirname(testDir
);
77 var moduleName
= path
.basename(moduleDir
);
78 testModules
[moduleName
] = {
79 files
: [path
.join('modules', moduleName
, 'test')],
84 testModules
['request-tests'] = {
86 './test/request-api-tests/'
87 // XXX: Skipped because Gitter login is now disabled (#gitter-sunset)
88 //'./test/request-web-tests/'
91 // These tests load the entire app, so mocha will sometimes timeout before it even runs the tests
97 testModules
.integration
= {
98 files
: ['./test/integration/'],
102 // eslint-disable-next-line max-statements, complexity
103 function spawnMochaProcess(moduleName
, options
, files
) {
107 var argReporter
= 'spec';
108 var argTimeout
= (options
&& options
.timeout
) || 10000;
112 SKIP_BADGER_TESTS
: 1,
119 if (generateCoverage
) {
120 executable
= './node_modules/.bin/nyc';
124 'output/coverage-reports/' + moduleName
,
127 './node_modules/.bin/mocha'
130 mkdirp
.sync('output/coverage-reports/' + moduleName
);
132 executable
= './node_modules/.bin/mocha';
136 // This is needed because Mocha no longer force exits, https://boneskull.com/mocha-v4-nears-release/#mochawontforceexit
139 if (testSuite
=== 'docker') {
140 env
.HOME
= '/tmp'; // Needs to be writeable inside docker for `nyc`
141 env
.NODE_ENV
= 'test-docker';
145 var argInvert
= false;
150 } else if (disableGitHubTests
) {
155 if (generateXUnitReports
) {
156 mkdirp
.sync('output/test-reports/');
158 argReporter
= 'mocha-multi';
159 env
.multi
= 'spec=- xunit=output/test-reports/' + moduleName
+ '.xml';
160 gutil
.log('Will write xunit reports to', 'output/test-reports/' + moduleName
+ '.xml');
163 args
.push('--recursive');
166 args
.push(argReporter
);
178 args
.push('--invert');
181 args
.push('--timeout');
182 args
.push(argTimeout
);
184 args
= args
.concat(files
);
185 gutil
.log('Running tests with', executable
, args
.join(' '));
187 return childProcessPromise
.spawn(executable
, args
, env
);
191 var testingErrors
= [];
193 Object
.keys(testModules
).forEach(function(moduleName
) {
194 var definition
= testModules
[moduleName
];
196 if (criticalOnly
&& !definition
.isCritical
) {
200 var testTaskName
= 'test:test:' + moduleName
;
201 subTasks
.push(testTaskName
);
203 gulp
.task(testTaskName
, function() {
204 return spawnMochaProcess(moduleName
, definition
.options
, definition
.files
).catch(function(err
) {
206 throw new Error('Test module ' + moduleName
+ ' failed. ' + err
);
209 testingErrors
.push(err
);
214 subTasks
.push('test:test:jest');
215 gulp
.task('test:test:jest', function() {
216 return childProcessPromise
.spawn('npm', ['run', 'jest']);
219 gulp
.task('test:pre-test', function() {
222 if (testSuite
=== 'docker') {
223 env
.NODE_ENV
= 'test-docker';
226 return childProcessPromise
.spawn('./scripts/utils/ensure-mongodb-indexes.js', [], env
);
229 if (RUN_TESTS_IN_PARALLEL
) {
230 // Run tests in parallel
231 gulp
.task('test:test', subTasks
, function() {
232 if (testingErrors
.length
) {
233 return Promise
.reject(testingErrors
[0]);
237 // Run tests in sequence
238 gulp
.task('test:test', function(callback
) {
239 gutil
.log('Run sequence for test:test', subTasks
.join(','));
241 var args
= subTasks
.concat(function(err
) {
242 if (err
) return callback(err
);
244 if (testingErrors
.length
) {
245 return callback(testingErrors
[0]);
251 runSequence
.apply(null, args
);
256 * Hook into post test
258 if (generateCoverage
) {
259 gulp
.task('test:post-test', ['test:post-test:merge-lcov', 'test:post-test:submit-codecov']);
262 gulp
.task('test:post-test:merge-lcov', function() {
264 .src('output/coverage-reports/**/lcov.info')
267 .pipe(gulp
.dest('output/coverage-reports/merged/'));
270 gulp
.task('test:post-test:submit-codecov', ['test:post-test:merge-lcov'], function() {
271 process
.env
.CODECOV_TOKEN
= '4d30a5c7-3839-4396-a2fd-d8f9a68a5c3a';
274 .src('output/coverage-reports/merged/lcov.info')
280 .on('error', function(err
) {
287 * Hook into the clean stage
289 gulp
.task('test:clean', function(cb
) {
290 del(['.nyc_output/'], cb
);