1'use strict'; 2 3require('../common'); 4const assert = require('assert'); 5const { spawnSync } = require('child_process'); 6const { join } = require('path'); 7const { readdirSync } = require('fs'); 8const fixtures = require('../common/fixtures'); 9const testFixtures = fixtures.path('test-runner'); 10 11{ 12 // File not found. 13 const args = ['--test', 'a-random-file-that-does-not-exist.js']; 14 const child = spawnSync(process.execPath, args); 15 16 assert.strictEqual(child.status, 1); 17 assert.strictEqual(child.signal, null); 18 assert.strictEqual(child.stdout.toString(), ''); 19 assert.match(child.stderr.toString(), /^Could not find/); 20} 21 22{ 23 // Default behavior. node_modules is ignored. Files that don't match the 24 // pattern are ignored except in test/ directories. 25 const args = ['--test']; 26 const child = spawnSync(process.execPath, args, { cwd: join(testFixtures, 'default-behavior') }); 27 28 assert.strictEqual(child.status, 1); 29 assert.strictEqual(child.signal, null); 30 assert.strictEqual(child.stderr.toString(), ''); 31 const stdout = child.stdout.toString(); 32 assert.match(stdout, /ok 1 - this should pass/); 33 assert.match(stdout, /not ok 2 - this should fail/); 34 assert.match(stdout, /ok 3 - .+subdir.+subdir_test\.js/); 35 assert.match(stdout, /ok 4 - this should pass/); 36 assert.match(stdout, /ok 5 - this should be skipped/); 37 assert.match(stdout, /ok 6 - this should be executed/); 38} 39 40{ 41 // Same but with a prototype mutation in require scripts. 42 const args = ['--require', join(testFixtures, 'protoMutation.js'), '--test']; 43 const child = spawnSync(process.execPath, args, { cwd: join(testFixtures, 'default-behavior') }); 44 45 const stdout = child.stdout.toString(); 46 assert.match(stdout, /ok 1 - this should pass/); 47 assert.match(stdout, /not ok 2 - this should fail/); 48 assert.match(stdout, /ok 3 - .+subdir.+subdir_test\.js/); 49 assert.match(stdout, /ok 4 - this should pass/); 50 assert.match(stdout, /ok 5 - this should be skipped/); 51 assert.match(stdout, /ok 6 - this should be executed/); 52 assert.strictEqual(child.status, 1); 53 assert.strictEqual(child.signal, null); 54 assert.strictEqual(child.stderr.toString(), ''); 55} 56 57{ 58 // User specified files that don't match the pattern are still run. 59 const args = ['--test', join(testFixtures, 'index.js')]; 60 const child = spawnSync(process.execPath, args, { cwd: testFixtures }); 61 62 assert.strictEqual(child.status, 1); 63 assert.strictEqual(child.signal, null); 64 assert.strictEqual(child.stderr.toString(), ''); 65 const stdout = child.stdout.toString(); 66 assert.match(stdout, /not ok 1 - .+index\.js/); 67} 68 69{ 70 // Searches node_modules if specified. 71 const args = ['--test', join(testFixtures, 'default-behavior/node_modules')]; 72 const child = spawnSync(process.execPath, args); 73 74 assert.strictEqual(child.status, 1); 75 assert.strictEqual(child.signal, null); 76 assert.strictEqual(child.stderr.toString(), ''); 77 const stdout = child.stdout.toString(); 78 assert.match(stdout, /not ok 1 - .+test-nm\.js/); 79} 80 81{ 82 // The current directory is used by default. 83 const args = ['--test']; 84 const options = { cwd: join(testFixtures, 'default-behavior') }; 85 const child = spawnSync(process.execPath, args, options); 86 87 assert.strictEqual(child.status, 1); 88 assert.strictEqual(child.signal, null); 89 assert.strictEqual(child.stderr.toString(), ''); 90 const stdout = child.stdout.toString(); 91 assert.match(stdout, /ok 1 - this should pass/); 92 assert.match(stdout, /not ok 2 - this should fail/); 93 assert.match(stdout, /ok 3 - .+subdir.+subdir_test\.js/); 94 assert.match(stdout, /ok 4 - this should pass/); 95 assert.match(stdout, /ok 5 - this should be skipped/); 96 assert.match(stdout, /ok 6 - this should be executed/); 97} 98 99{ 100 // Flags that cannot be combined with --test. 101 const flags = [ 102 ['--check', '--test'], 103 ['--interactive', '--test'], 104 ['--eval', 'console.log("should not print")', '--test'], 105 ['--print', 'console.log("should not print")', '--test'], 106 ]; 107 108 flags.forEach((args) => { 109 const child = spawnSync(process.execPath, args); 110 111 assert.notStrictEqual(child.status, 0); 112 assert.strictEqual(child.signal, null); 113 assert.strictEqual(child.stdout.toString(), ''); 114 const stderr = child.stderr.toString(); 115 assert.match(stderr, /--test/); 116 }); 117} 118 119{ 120 // Test combined stream outputs 121 const args = [ 122 '--test', 123 'test/fixtures/test-runner/default-behavior/index.test.js', 124 'test/fixtures/test-runner/nested.js', 125 'test/fixtures/test-runner/invalid-tap.js', 126 ]; 127 const child = spawnSync(process.execPath, args); 128 129 130 assert.strictEqual(child.status, 1); 131 assert.strictEqual(child.signal, null); 132 assert.strictEqual(child.stderr.toString(), ''); 133 const stdout = child.stdout.toString(); 134 assert.match(stdout, /# Subtest: this should pass/); 135 assert.match(stdout, /ok 1 - this should pass/); 136 assert.match(stdout, / {2}---/); 137 assert.match(stdout, / {2}duration_ms: .*/); 138 assert.match(stdout, / {2}\.\.\./); 139 140 assert.match(stdout, /# Subtest: .+invalid-tap\.js/); 141 assert.match(stdout, /# invalid tap output/); 142 assert.match(stdout, /ok 2 - .+invalid-tap\.js/); 143 144 assert.match(stdout, /# Subtest: level 0a/); 145 assert.match(stdout, / {4}# Subtest: level 1a/); 146 assert.match(stdout, / {4}ok 1 - level 1a/); 147 assert.match(stdout, / {4}# Subtest: level 1b/); 148 assert.match(stdout, / {4}not ok 2 - level 1b/); 149 assert.match(stdout, / {6}code: 'ERR_TEST_FAILURE'/); 150 assert.match(stdout, / {6}stack: |-'/); 151 assert.match(stdout, / {8}TestContext\.<anonymous> .*/); 152 assert.match(stdout, / {4}# Subtest: level 1c/); 153 assert.match(stdout, / {4}ok 3 - level 1c # SKIP aaa/); 154 assert.match(stdout, / {4}# Subtest: level 1d/); 155 assert.match(stdout, / {4}ok 4 - level 1d/); 156 assert.match(stdout, /not ok 3 - level 0a/); 157 assert.match(stdout, / {2}error: '1 subtest failed'/); 158 assert.match(stdout, /# Subtest: level 0b/); 159 assert.match(stdout, /not ok 4 - level 0b/); 160 assert.match(stdout, / {2}error: 'level 0b error'/); 161 assert.match(stdout, /# tests 8/); 162 assert.match(stdout, /# suites 0/); 163 assert.match(stdout, /# pass 4/); 164 assert.match(stdout, /# fail 3/); 165 assert.match(stdout, /# cancelled 0/); 166 assert.match(stdout, /# skipped 1/); 167 assert.match(stdout, /# todo 0/); 168} 169 170{ 171 // Test user logging in tests. 172 const args = [ 173 '--test', 174 'test/fixtures/test-runner/user-logs.js', 175 ]; 176 const child = spawnSync(process.execPath, args); 177 178 assert.strictEqual(child.status, 0); 179 assert.strictEqual(child.signal, null); 180 assert.strictEqual(child.stderr.toString(), ''); 181 const stdout = child.stdout.toString(); 182 assert.match(stdout, /# stderr 1/); 183 assert.match(stdout, /# stderr 2/); 184 assert.match(stdout, /# stdout 3/); 185 assert.match(stdout, /# stderr 6/); 186 assert.match(stdout, /# not ok 1 - fake test/); 187 assert.match(stdout, /# stderr 5/); 188 assert.match(stdout, /# stdout 4/); 189 assert.match(stdout, /# Subtest: a test/); 190 assert.match(stdout, /ok 1 - a test/); 191 assert.match(stdout, /# tests 1/); 192 assert.match(stdout, /# pass 1/); 193} 194 195{ 196 // Use test with --loader and --require. 197 // This case is common since vscode uses --require to load the debugger. 198 const args = ['--no-warnings', 199 '--experimental-loader', 'data:text/javascript,', 200 '--require', fixtures.path('empty.js'), 201 '--test', join(testFixtures, 'default-behavior', 'index.test.js')]; 202 const child = spawnSync(process.execPath, args); 203 204 assert.strictEqual(child.stderr.toString(), ''); 205 assert.strictEqual(child.status, 0); 206 assert.strictEqual(child.signal, null); 207 const stdout = child.stdout.toString(); 208 assert.match(stdout, /ok 1 - this should pass/); 209} 210 211{ 212 // --test-shard option validation 213 const args = ['--test', '--test-shard=1', join(testFixtures, 'index.js')]; 214 const child = spawnSync(process.execPath, args, { cwd: testFixtures }); 215 216 assert.strictEqual(child.status, 1); 217 assert.strictEqual(child.signal, null); 218 assert.match(child.stderr.toString(), /The argument '--test-shard' must be in the form of <index>\/<total>\. Received '1'/); 219 const stdout = child.stdout.toString(); 220 assert.strictEqual(stdout, ''); 221} 222 223{ 224 // --test-shard option validation 225 const args = ['--test', '--test-shard=1/2/3', join(testFixtures, 'index.js')]; 226 const child = spawnSync(process.execPath, args, { cwd: testFixtures }); 227 228 assert.strictEqual(child.status, 1); 229 assert.strictEqual(child.signal, null); 230 assert.match(child.stderr.toString(), /The argument '--test-shard' must be in the form of <index>\/<total>\. Received '1\/2\/3'/); 231 const stdout = child.stdout.toString(); 232 assert.strictEqual(stdout, ''); 233} 234 235{ 236 // --test-shard option validation 237 const args = ['--test', '--test-shard=0/3', join(testFixtures, 'index.js')]; 238 const child = spawnSync(process.execPath, args, { cwd: testFixtures }); 239 240 assert.strictEqual(child.status, 1); 241 assert.strictEqual(child.signal, null); 242 assert.match(child.stderr.toString(), /The value of "options\.shard\.index" is out of range\. It must be >= 1 && <= 3 \("options\.shard\.total"\)\. Received 0/); 243 const stdout = child.stdout.toString(); 244 assert.strictEqual(stdout, ''); 245} 246 247{ 248 // --test-shard option validation 249 const args = ['--test', '--test-shard=0xf/20abcd', join(testFixtures, 'index.js')]; 250 const child = spawnSync(process.execPath, args, { cwd: testFixtures }); 251 252 assert.strictEqual(child.status, 1); 253 assert.strictEqual(child.signal, null); 254 assert.match(child.stderr.toString(), /The argument '--test-shard' must be in the form of <index>\/<total>\. Received '0xf\/20abcd'/); 255 const stdout = child.stdout.toString(); 256 assert.strictEqual(stdout, ''); 257} 258 259{ 260 // --test-shard option validation 261 const args = ['--test', '--test-shard=hello', join(testFixtures, 'index.js')]; 262 const child = spawnSync(process.execPath, args, { cwd: testFixtures }); 263 264 assert.strictEqual(child.status, 1); 265 assert.strictEqual(child.signal, null); 266 assert.match(child.stderr.toString(), /The argument '--test-shard' must be in the form of <index>\/<total>\. Received 'hello'/); 267 const stdout = child.stdout.toString(); 268 assert.strictEqual(stdout, ''); 269} 270 271{ 272 // --test-shard option, first shard 273 const shardsTestPath = join(testFixtures, 'shards'); 274 const allShardsTestsFiles = readdirSync(shardsTestPath).map((file) => join(shardsTestPath, file)); 275 const args = [ 276 '--test', 277 '--test-shard=1/2', 278 ...allShardsTestsFiles, 279 ]; 280 const child = spawnSync(process.execPath, args); 281 282 assert.strictEqual(child.status, 0); 283 assert.strictEqual(child.signal, null); 284 assert.strictEqual(child.stderr.toString(), ''); 285 const stdout = child.stdout.toString(); 286 assert.match(stdout, /# Subtest: a\.cjs this should pass/); 287 assert.match(stdout, /ok 1 - a\.cjs this should pass/); 288 289 assert.match(stdout, /# Subtest: c\.cjs this should pass/); 290 assert.match(stdout, /ok 2 - c\.cjs this should pass/); 291 292 assert.match(stdout, /# Subtest: e\.cjs this should pass/); 293 assert.match(stdout, /ok 3 - e\.cjs this should pass/); 294 295 assert.match(stdout, /# Subtest: g\.cjs this should pass/); 296 assert.match(stdout, /ok 4 - g\.cjs this should pass/); 297 298 assert.match(stdout, /# Subtest: i\.cjs this should pass/); 299 assert.match(stdout, /ok 5 - i\.cjs this should pass/); 300 301 assert.match(stdout, /# tests 5/); 302 assert.match(stdout, /# pass 5/); 303 assert.match(stdout, /# fail 0/); 304 assert.match(stdout, /# skipped 0/); 305} 306 307{ 308 // --test-shard option, last shard 309 const shardsTestPath = join(testFixtures, 'shards'); 310 const allShardsTestsFiles = readdirSync(shardsTestPath).map((file) => join(shardsTestPath, file)); 311 const args = [ 312 '--test', 313 '--test-shard=2/2', 314 ...allShardsTestsFiles, 315 ]; 316 const child = spawnSync(process.execPath, args); 317 318 assert.strictEqual(child.status, 0); 319 assert.strictEqual(child.signal, null); 320 assert.strictEqual(child.stderr.toString(), ''); 321 const stdout = child.stdout.toString(); 322 assert.match(stdout, /# Subtest: b\.cjs this should pass/); 323 assert.match(stdout, /ok 1 - b\.cjs this should pass/); 324 325 assert.match(stdout, /# Subtest: d\.cjs this should pass/); 326 assert.match(stdout, /ok 2 - d\.cjs this should pass/); 327 328 assert.match(stdout, /# Subtest: f\.cjs this should pass/); 329 assert.match(stdout, /ok 3 - f\.cjs this should pass/); 330 331 assert.match(stdout, /# Subtest: h\.cjs this should pass/); 332 assert.match(stdout, /ok 4 - h\.cjs this should pass/); 333 334 assert.match(stdout, /# Subtest: j\.cjs this should pass/); 335 assert.match(stdout, /ok 5 - j\.cjs this should pass/); 336 337 assert.match(stdout, /# tests 5/); 338 assert.match(stdout, /# pass 5/); 339 assert.match(stdout, /# fail 0/); 340 assert.match(stdout, /# skipped 0/); 341} 342