Skip to content

Commit d506860

Browse files
committedSep 4, 2021
Merge branch 'main' into 3.99
2 parents a80b18e + da9decc commit d506860

27 files changed

+411
-223
lines changed
 

‎.circleci/config.yml

+23-25
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,18 @@ executors:
1010
docker:
1111
- image: cimg/node:16.1.0
1212
working_directory: ~/workspace
13-
node14:
13+
node14_latest:
1414
docker:
1515
- image: circleci/node:14
1616
working_directory: ~/workspace
17+
node14_8:
18+
docker:
19+
- image: circleci/node:14.8
20+
working_directory: ~/workspace
21+
node14_7:
22+
docker:
23+
- image: circleci/node:14.7
24+
working_directory: ~/workspace
1725
node12_latest:
1826
docker:
1927
- image: circleci/node:12
@@ -36,7 +44,7 @@ executors:
3644
working_directory: ~/workspace
3745

3846
jobs:
39-
build_and_test:
47+
test:
4048
parameters:
4149
executor:
4250
type: executor
@@ -57,29 +65,19 @@ workflows:
5765
version: 2
5866
push: &push_workflow
5967
jobs:
60-
- build_and_test:
61-
executor: node16
62-
name: node_16
63-
- build_and_test:
64-
executor: node14
65-
name: node_14
66-
- build_and_test:
67-
executor: node12_latest
68-
name: node_12_latest
69-
- build_and_test:
70-
executor: node12_0
71-
name: node_12_0
72-
# 12.16 is the last version without good-enough ES module support
73-
- build_and_test:
74-
executor: node12_16
75-
name: node_12_16
76-
# 12.16 is the first version with good-enough ES module support
77-
- build_and_test:
78-
executor: node12_17
79-
name: node_12_17
80-
- build_and_test:
81-
executor: node10
82-
name: node_10
68+
- test:
69+
matrix:
70+
parameters:
71+
executor:
72+
- node16
73+
- node14_latest
74+
- node14_8 # first with top level await in ES modules.
75+
- node14_7
76+
- node12_latest
77+
- node12_17 # first with dynamic import() of commonjs modules
78+
- node12_16
79+
- node12_0
80+
- node10
8381
cron:
8482
<<: *push_workflow
8583
triggers:

‎.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
spec/fixtures/cjs-syntax-error/syntax_error.js
2+
spec/fixtures/esm-importing-commonjs-syntax-error/syntax_error.js
23
spec/fixtures/js-loader-import/*.js

‎bin/jasmine.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#!/usr/bin/env node
22

3-
var path = require('path'),
4-
Command = require('../lib/command'),
5-
Jasmine = require('../lib/jasmine');
3+
const path = require('path');
4+
const Command = require('../lib/command');
5+
const Jasmine = require('../lib/jasmine');
66

7-
var jasmine = new Jasmine({ projectBaseDir: path.resolve() });
8-
var examplesDir = path.join(path.dirname(require.resolve('jasmine-core')), 'jasmine-core', 'example', 'node_example');
9-
var command = new Command(path.resolve(), examplesDir, console.log);
7+
const jasmine = new Jasmine({ projectBaseDir: path.resolve() });
8+
const examplesDir = path.join(path.dirname(require.resolve('jasmine-core')), 'jasmine-core', 'example', 'node_example');
9+
const command = new Command(path.resolve(), examplesDir, console.log);
1010

1111
command.run(jasmine, process.argv.slice(2));

‎lib/command.js

+26-26
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
var path = require('path'),
2-
fs = require('fs');
1+
const path = require('path');
2+
const fs = require('fs');
33

44
exports = module.exports = Command;
55

6-
var subCommands = {
6+
const subCommands = {
77
init: {
88
description: 'initialize jasmine',
99
action: initJasmine
@@ -28,14 +28,14 @@ function Command(projectBaseDir, examplesDir, print) {
2828
this.projectBaseDir = projectBaseDir;
2929
this.specDir = path.join(projectBaseDir, 'spec');
3030

31-
var command = this;
31+
const command = this;
3232

3333
this.run = function(jasmine, commands) {
3434
setEnvironmentVariables(commands);
3535

36-
var commandToRun;
36+
let commandToRun;
3737
Object.keys(subCommands).forEach(function(cmd) {
38-
var commandObject = subCommands[cmd];
38+
const commandObject = subCommands[cmd];
3939
if (commands.indexOf(cmd) >= 0) {
4040
commandToRun = commandObject;
4141
} else if(commandObject.alias && commands.indexOf(commandObject.alias) >= 0) {
@@ -46,7 +46,7 @@ function Command(projectBaseDir, examplesDir, print) {
4646
if (commandToRun) {
4747
commandToRun.action({jasmine: jasmine, projectBaseDir: command.projectBaseDir, specDir: command.specDir, examplesDir: examplesDir, print: print});
4848
} else {
49-
var env = parseOptions(commands);
49+
const env = parseOptions(commands);
5050
if (env.unknownOptions.length > 0) {
5151
process.exitCode = 1;
5252
print('Unknown options: ' + env.unknownOptions.join(', '));
@@ -64,7 +64,7 @@ function isFileArg(arg) {
6464
}
6565

6666
function parseOptions(argv) {
67-
var files = [],
67+
let files = [],
6868
helpers = [],
6969
requires = [],
7070
unknownOptions = [],
@@ -77,8 +77,8 @@ function parseOptions(argv) {
7777
random,
7878
seed;
7979

80-
for (var i in argv) {
81-
var arg = argv[i];
80+
for (let i in argv) {
81+
const arg = argv[i];
8282
if (arg === '--no-color') {
8383
color = false;
8484
} else if (arg === '--color') {
@@ -126,7 +126,7 @@ function parseOptions(argv) {
126126
}
127127

128128
function runJasmine(jasmine, env, print) {
129-
var loadConfig = require('./loadConfig');
129+
const loadConfig = require('./loadConfig');
130130
loadConfig(jasmine, env, print);
131131
jasmine.execute(env.files, env.filter)
132132
.catch(function(error) {
@@ -136,8 +136,8 @@ function runJasmine(jasmine, env, print) {
136136
}
137137

138138
function initJasmine(options) {
139-
var print = options.print;
140-
var specDir = options.specDir;
139+
const print = options.print;
140+
const specDir = options.specDir;
141141
makeDirStructure(path.join(specDir, 'support/'));
142142
if(!fs.existsSync(path.join(specDir, 'support/jasmine.json'))) {
143143
fs.writeFileSync(path.join(specDir, 'support/jasmine.json'), fs.readFileSync(path.join(__dirname, '../lib/examples/jasmine.json'), 'utf-8'));
@@ -148,9 +148,9 @@ function initJasmine(options) {
148148
}
149149

150150
function installExamples(options) {
151-
var specDir = options.specDir;
152-
var projectBaseDir = options.projectBaseDir;
153-
var examplesDir = options.examplesDir;
151+
const specDir = options.specDir;
152+
const projectBaseDir = options.projectBaseDir;
153+
const examplesDir = options.examplesDir;
154154

155155
makeDirStructure(path.join(specDir, 'support'));
156156
makeDirStructure(path.join(specDir, 'jasmine_examples'));
@@ -177,12 +177,12 @@ function installExamples(options) {
177177
}
178178

179179
function help(options) {
180-
var print = options.print;
180+
const print = options.print;
181181
print('Usage: jasmine [command] [options] [files] [--]');
182182
print('');
183183
print('Commands:');
184184
Object.keys(subCommands).forEach(function(cmd) {
185-
var commandNameText = cmd;
185+
let commandNameText = cmd;
186186
if(subCommands[cmd].alias) {
187187
commandNameText = commandNameText + ',' + subCommands[cmd].alias;
188188
}
@@ -210,7 +210,7 @@ function help(options) {
210210
}
211211

212212
function version(options) {
213-
var print = options.print;
213+
const print = options.print;
214214
print('jasmine v' + require('../package.json').version);
215215
print('jasmine-core v' + options.jasmine.coreVersion());
216216
}
@@ -224,7 +224,7 @@ function lPad(str, length) {
224224
}
225225

226226
function copyFiles(srcDir, destDir, pattern) {
227-
var srcDirFiles = fs.readdirSync(srcDir);
227+
const srcDirFiles = fs.readdirSync(srcDir);
228228
srcDirFiles.forEach(function(file) {
229229
if (file.search(pattern) !== -1) {
230230
fs.writeFileSync(path.join(destDir, file), fs.readFileSync(path.join(srcDir, file)));
@@ -233,10 +233,10 @@ function copyFiles(srcDir, destDir, pattern) {
233233
}
234234

235235
function makeDirStructure(absolutePath) {
236-
var splitPath = absolutePath.split(path.sep);
236+
const splitPath = absolutePath.split(path.sep);
237237
splitPath.forEach(function(dir, index) {
238238
if(index > 1) {
239-
var fullPath = path.join(splitPath.slice(0, index).join('/'), dir);
239+
const fullPath = path.join(splitPath.slice(0, index).join('/'), dir);
240240
if (!fs.existsSync(fullPath)) {
241241
fs.mkdirSync(fullPath);
242242
}
@@ -245,16 +245,16 @@ function makeDirStructure(absolutePath) {
245245
}
246246

247247
function isEnvironmentVariable(command) {
248-
var envRegExp = /(.*)=(.*)/;
248+
const envRegExp = /(.*)=(.*)/;
249249
return command.match(envRegExp);
250250
}
251251

252252
function setEnvironmentVariables(commands) {
253253
commands.forEach(function (command) {
254-
var regExpMatch = isEnvironmentVariable(command);
254+
const regExpMatch = isEnvironmentVariable(command);
255255
if(regExpMatch) {
256-
var key = regExpMatch[1];
257-
var value = regExpMatch[2];
256+
const key = regExpMatch[1];
257+
const value = regExpMatch[2];
258258
process.env[key] = value;
259259
}
260260
});

‎lib/filters/console_spec_filter.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
module.exports = exports = ConsoleSpecFilter;
22

33
function ConsoleSpecFilter(options) {
4-
var filterString = options && options.filterString;
5-
var filterPattern = new RegExp(filterString);
4+
const filterString = options && options.filterString;
5+
const filterPattern = new RegExp(filterString);
66

77
this.matches = function(specName) {
88
return filterPattern.test(specName);

‎lib/jasmine.js

+26-26
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
var path = require('path'),
2-
util = require('util'),
3-
glob = require('glob'),
4-
Loader = require('./loader'),
5-
CompletionReporter = require('./reporters/completion_reporter'),
6-
ConsoleSpecFilter = require('./filters/console_spec_filter');
1+
const path = require('path');
2+
const util = require('util');
3+
const glob = require('glob');
4+
const Loader = require('./loader');
5+
const CompletionReporter = require('./reporters/completion_reporter');
6+
const ConsoleSpecFilter = require('./filters/console_spec_filter');
77

88
module.exports = Jasmine;
99
module.exports.ConsoleReporter = require('./reporters/console_reporter');
@@ -33,7 +33,7 @@ module.exports.ConsoleReporter = require('./reporters/console_reporter');
3333
function Jasmine(options) {
3434
options = options || {};
3535
this.loader = options.loader || new Loader();
36-
var jasmineCore = options.jasmineCore || require('jasmine-core');
36+
const jasmineCore = options.jasmineCore || require('jasmine-core');
3737
this.jasmineCorePath = path.join(jasmineCore.files.path, 'jasmine.js');
3838
this.jasmine = jasmineCore.boot(jasmineCore);
3939
this.projectBaseDir = options.projectBaseDir || path.resolve();
@@ -58,7 +58,7 @@ function Jasmine(options) {
5858
this.addReporter(this.reporter);
5959
this.defaultReporterConfigured = false;
6060

61-
var jasmineRunner = this;
61+
const jasmineRunner = this;
6262
this.completionReporter.onComplete(function(passed) {
6363
jasmineRunner.exitCodeCompletion(passed);
6464
});
@@ -234,8 +234,8 @@ Jasmine.prototype.loadRequires = function() {
234234
*/
235235
Jasmine.prototype.loadConfigFile = function(configFilePath) {
236236
try {
237-
var absoluteConfigFilePath = path.resolve(this.projectBaseDir, configFilePath || 'spec/support/jasmine.json');
238-
var config = require(absoluteConfigFilePath);
237+
const absoluteConfigFilePath = path.resolve(this.projectBaseDir, configFilePath || 'spec/support/jasmine.json');
238+
const config = require(absoluteConfigFilePath);
239239
this.loadConfig(config);
240240
} catch (e) {
241241
if(configFilePath || e.code != 'MODULE_NOT_FOUND') { throw e; }
@@ -250,7 +250,7 @@ Jasmine.prototype.loadConfig = function(config) {
250250
/**
251251
* @interface Configuration
252252
*/
253-
var envConfig = {...config.env};
253+
const envConfig = {...config.env};
254254

255255
/**
256256
* The directory that spec files are contained in, relative to the project
@@ -277,7 +277,7 @@ Jasmine.prototype.loadConfig = function(config) {
277277
* @default false
278278
*/
279279
if (config.stopSpecOnExpectationFailure !== undefined) {
280-
envConfig.oneFailurePerSpec = config.stopSpecOnExpectationFailure;
280+
envConfig.stopSpecOnExpectationFailure = config.stopSpecOnExpectationFailure;
281281
}
282282

283283
/**
@@ -287,7 +287,7 @@ Jasmine.prototype.loadConfig = function(config) {
287287
* @default false
288288
*/
289289
if (config.stopOnSpecFailure !== undefined) {
290-
envConfig.failFast = config.stopOnSpecFailure;
290+
envConfig.stopOnSpecFailure = config.stopOnSpecFailure;
291291
}
292292

293293
/**
@@ -404,19 +404,19 @@ Jasmine.prototype.addSpecFiles = Jasmine.prototype.addMatchingSpecFiles;
404404
Jasmine.prototype.addHelperFiles = Jasmine.prototype.addMatchingHelperFiles;
405405

406406
Jasmine.prototype.addRequires = function(requires) {
407-
var jasmineRunner = this;
407+
const jasmineRunner = this;
408408
requires.forEach(function(r) {
409409
jasmineRunner.requires.push(r);
410410
});
411411
};
412412

413413
function addFiles(kind) {
414414
return function (files) {
415-
var jasmineRunner = this;
416-
var fileArr = this[kind];
415+
const jasmineRunner = this;
416+
const fileArr = this[kind];
417417

418-
var {includeFiles, excludeFiles} = files.reduce(function(ongoing, file) {
419-
var hasNegation = file.startsWith('!');
418+
const {includeFiles, excludeFiles} = files.reduce(function(ongoing, file) {
419+
const hasNegation = file.startsWith('!');
420420

421421
if (hasNegation) {
422422
file = file.substring(1);
@@ -433,7 +433,7 @@ function addFiles(kind) {
433433
}, { includeFiles: [], excludeFiles: [] });
434434

435435
includeFiles.forEach(function(file) {
436-
var filePaths = glob
436+
const filePaths = glob
437437
.sync(file, { ignore: excludeFiles })
438438
.filter(function(filePath) {
439439
// glob will always output '/' as a segment separator but the fileArr may use \ on windows
@@ -478,7 +478,7 @@ Jasmine.prototype.onComplete = function(onCompleteCallback) {
478478
* failure
479479
*/
480480
Jasmine.prototype.stopSpecOnExpectationFailure = function(value) {
481-
this.env.configure({oneFailurePerSpec: value});
481+
this.env.configure({stopSpecOnExpectationFailure: value});
482482
};
483483

484484
/**
@@ -489,7 +489,7 @@ Jasmine.prototype.stopSpecOnExpectationFailure = function(value) {
489489
* first spec failure
490490
*/
491491
Jasmine.prototype.stopOnSpecFailure = function(value) {
492-
this.env.configure({failFast: value});
492+
this.env.configure({stopOnSpecFailure: value});
493493
};
494494

495495
Jasmine.prototype.exitCodeCompletion = function(passed) {
@@ -498,9 +498,9 @@ Jasmine.prototype.exitCodeCompletion = function(passed) {
498498
// might exit before all previous writes have actually been
499499
// written when Jasmine is piped to another process that isn't
500500
// reading quickly enough.
501-
var jasmineRunner = this;
502-
var streams = [process.stdout, process.stderr];
503-
var writesToWait = streams.length;
501+
const jasmineRunner = this;
502+
const streams = [process.stdout, process.stderr];
503+
let writesToWait = streams.length;
504504
streams.forEach(function(stream) {
505505
stream.write('', null, exitIfAllStreamsCompleted);
506506
});
@@ -517,7 +517,7 @@ Jasmine.prototype.exitCodeCompletion = function(passed) {
517517
}
518518
};
519519

520-
var checkExit = function(jasmineRunner) {
520+
const checkExit = function(jasmineRunner) {
521521
return function() {
522522
if (!jasmineRunner.completionReporter.isComplete()) {
523523
process.exitCode = 4;
@@ -558,7 +558,7 @@ Jasmine.prototype.execute = async function(files, filterString) {
558558
}
559559

560560
if (filterString) {
561-
var specFilter = new ConsoleSpecFilter({
561+
const specFilter = new ConsoleSpecFilter({
562562
filterString: filterString
563563
});
564564
this.env.configure({specFilter: function(spec) {

‎lib/loadConfig.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ module.exports = exports = function(jasmine, env, print) {
2020
}
2121
if (env.reporter !== undefined) {
2222
try {
23-
var Report = require(env.reporter);
24-
var reporter = new Report();
23+
const Report = require(env.reporter);
24+
const reporter = new Report();
2525
jasmine.clearReporters();
2626
jasmine.addReporter(reporter);
2727
} catch(e) {
@@ -31,4 +31,4 @@ module.exports = exports = function(jasmine, env, print) {
3131
}
3232
}
3333
jasmine.showColors(env.color);
34-
};
34+
};

‎lib/loader.js

+95-10
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,7 @@ Loader.prototype.load = function(path, alwaysImport) {
1212
// Node enforces this on Windows but not on other OSes.
1313
const url = `file://${path}`;
1414
return this.import_(url).catch(function(e) {
15-
if (e.message.indexOf(path) !== -1 || e.stack.indexOf(path) !== -1) {
16-
return Promise.reject(e);
17-
} else {
18-
// When an ES module has a syntax error, the resulting exception does not
19-
// include the filename. Add it. We lose the stack trace in the process,
20-
// but the stack trace is usually not useful since it contains only frames
21-
// from the Node module loader.
22-
const updatedError = new Error(`While loading ${path}: ${e.constructor.name}: ${e.message}`);
23-
return Promise.reject(updatedError);
24-
}
15+
return Promise.reject(fixupImportException(e, path));
2516
});
2617
} else {
2718
return new Promise(resolve => {
@@ -38,3 +29,97 @@ function requireShim(path) {
3829
function importShim(path) {
3930
return import(path);
4031
}
32+
33+
34+
function fixupImportException(e, importedPath) {
35+
// When an ES module has a syntax error, the resulting exception does not
36+
// include the filename, which the user will need to debug the problem. We
37+
// need to fix those up to include the filename. However, other kinds of load-
38+
// time errors *do* include the filename and usually the line number. We need
39+
// to leave those alone.
40+
//
41+
// Some examples of load-time errors that we need to deal with:
42+
// 1. Syntax error in an ESM spec:
43+
// SyntaxError: missing ) after argument list
44+
// at Loader.moduleStrategy (node:internal/modules/esm/translators:147:18)
45+
// at async link (node:internal/modules/esm/module_job:64:21)
46+
//
47+
// 2. Syntax error in an ES module imported from an ESM spec. This is exactly
48+
// the same as #1: there is no way to tell which file actually has the syntax
49+
// error.
50+
//
51+
// 3. Syntax error in a CommonJS module imported by an ES module:
52+
// /path/to/commonjs_with_syntax_error.js:2
53+
//
54+
//
55+
//
56+
// SyntaxError: Unexpected end of input
57+
// at Object.compileFunction (node:vm:355:18)
58+
// at wrapSafe (node:internal/modules/cjs/loader:1038:15)
59+
// at Module._compile (node:internal/modules/cjs/loader:1072:27)
60+
// at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10)
61+
// at Module.load (node:internal/modules/cjs/loader:988:32)
62+
// at Function.Module._load (node:internal/modules/cjs/loader:828:14)
63+
// at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:201:29)
64+
// at ModuleJob.run (node:internal/modules/esm/module_job:175:25)
65+
// at async Loader.import (node:internal/modules/esm/loader:178:24)
66+
// at async file:///path/to/esm_that_imported_cjs.mjs:2:11
67+
//
68+
// Note: For Jasmine's purposes, case 3 only occurs in Node >= 14.8. Older
69+
// versions don't support top-level await, without which it's not possible to
70+
// load a CommonJS module from an ES module at load-time. The entire content
71+
// above, including the file path and the three blank lines, is part of the
72+
// error's `stack` property. There may or may not be any stack trace after the
73+
// SyntaxError line, and if there's a stack trace it may or may not contain
74+
// any useful information.
75+
//
76+
// 4. Any other kind of exception thrown at load time
77+
//
78+
// Error: nope
79+
// at Object.<anonymous> (/path/to/file_throwing_error.js:1:7)
80+
// at Module._compile (node:internal/modules/cjs/loader:1108:14)
81+
// at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10)
82+
// at Module.load (node:internal/modules/cjs/loader:988:32)
83+
// at Function.Module._load (node:internal/modules/cjs/loader:828:14)
84+
// at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:201:29)
85+
// at ModuleJob.run (node:internal/modules/esm/module_job:175:25)
86+
// at async Loader.import (node:internal/modules/esm/loader:178:24)
87+
// at async file:///path_to_file_importing_broken_file.mjs:1:1
88+
//
89+
// We need to replace the error with a useful one in cases 1 and 2, but not in
90+
// cases 3 and 4. Distinguishing among them can be tricky. Simple heuristics
91+
// like checking the stack trace for the name of the file we imported fail
92+
// because it often shows up even when the error was elsewhere, e.g. at the
93+
// bottom of the stack traces in the examples for cases 3 and 4 above. To add
94+
// to the fun, file paths in errors on Windows can be either Windows style
95+
// paths (c:\path\to\file.js) or URLs (file:///c:/path/to/file.js).
96+
97+
if (!(e instanceof SyntaxError)) {
98+
return e;
99+
}
100+
101+
const escapedWin = escapeStringForRegexp(importedPath.replace(/\//g, '\\'));
102+
const windowsPathRegex = new RegExp('[a-zA-z]:\\\\([^\\s]+\\\\|)' + escapedWin);
103+
const windowsUrlRegex = new RegExp('file:///[a-zA-z]:\\\\([^\\s]+\\\\|)' + escapedWin);
104+
const anyUnixPathFirstLineRegex = /^\/[^\s:]+:\d/;
105+
const anyWindowsPathFirstLineRegex = /^[a-zA-Z]:(\\[^\s\\:]+)+:/;
106+
107+
if (e.message.indexOf(importedPath) !== -1
108+
|| e.stack.indexOf(importedPath) !== -1
109+
|| e.stack.match(windowsPathRegex) || e.stack.match(windowsUrlRegex)
110+
|| e.stack.match(anyUnixPathFirstLineRegex)
111+
|| e.stack.match(anyWindowsPathFirstLineRegex)) {
112+
return e;
113+
} else {
114+
return new Error(`While loading ${importedPath}: ${e.constructor.name}: ${e.message}`);
115+
}
116+
}
117+
118+
// Adapted from Sindre Sorhus's escape-string-regexp (MIT license)
119+
function escapeStringForRegexp(string) {
120+
// Escape characters with special meaning either inside or outside character sets.
121+
// Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.
122+
return string
123+
.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
124+
.replace(/-/g, '\\x2d');
125+
}

‎lib/reporters/completion_reporter.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module.exports = function() {
2-
var onCompleteCallback = function() {};
3-
var completed = false;
2+
let onCompleteCallback = function() {};
3+
let completed = false;
44

55
this.onComplete = function(callback) {
66
onCompleteCallback = callback;

‎lib/reporters/console_reporter.js

+15-15
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module.exports = exports = ConsoleReporter;
1010
* const reporter = new ConsoleReporter();
1111
*/
1212
function ConsoleReporter() {
13-
var print = function() {},
13+
let print = function() {},
1414
showColors = false,
1515
jasmineCorePath = null,
1616
specCount,
@@ -81,14 +81,14 @@ function ConsoleReporter() {
8181
this.jasmineDone = function(result) {
8282
printNewline();
8383
printNewline();
84-
if(failedSpecs.length > 0) {
84+
if (failedSpecs.length > 0) {
8585
print('Failures:');
8686
}
87-
for (var i = 0; i < failedSpecs.length; i++) {
87+
for (let i = 0; i < failedSpecs.length; i++) {
8888
specFailureDetails(failedSpecs[i], i + 1);
8989
}
9090

91-
for(i = 0; i < failedSuites.length; i++) {
91+
for(let i = 0; i < failedSuites.length; i++) {
9292
suiteFailureDetails(failedSuites[i]);
9393
}
9494

@@ -110,7 +110,7 @@ function ConsoleReporter() {
110110
print('Ran ' + executableSpecCount + ' of ' + specCount + plural(' spec', specCount));
111111
printNewline();
112112
}
113-
var specCounts = executableSpecCount + ' ' + plural('spec', executableSpecCount) + ', ' +
113+
let specCounts = executableSpecCount + ' ' + plural('spec', executableSpecCount) + ', ' +
114114
failureCount + ' ' + plural('failure', failureCount);
115115

116116
if (pendingSpecs.length) {
@@ -123,7 +123,7 @@ function ConsoleReporter() {
123123
}
124124

125125
printNewline();
126-
var seconds = result ? result.totalTime / 1000 : 0;
126+
const seconds = result ? result.totalTime / 1000 : 0;
127127
print('Finished in ' + seconds + ' ' + plural('second', seconds));
128128
printNewline();
129129

@@ -189,17 +189,17 @@ function ConsoleReporter() {
189189
}
190190

191191
function repeat(thing, times) {
192-
var arr = [];
193-
for (var i = 0; i < times; i++) {
192+
const arr = [];
193+
for (let i = 0; i < times; i++) {
194194
arr.push(thing);
195195
}
196196
return arr;
197197
}
198198

199199
function indent(str, spaces) {
200-
var lines = (str || '').split('\n');
201-
var newArr = [];
202-
for (var i = 0; i < lines.length; i++) {
200+
const lines = (str || '').split('\n');
201+
const newArr = [];
202+
for (let i = 0; i < lines.length; i++) {
203203
newArr.push(repeat(' ', spaces).join('') + lines[i]);
204204
}
205205
return newArr.join('\n');
@@ -210,7 +210,7 @@ function ConsoleReporter() {
210210
return '';
211211
}
212212

213-
var filteredStack = stack.split('\n').filter(function(stackLine) {
213+
const filteredStack = stack.split('\n').filter(function(stackLine) {
214214
return stackLine.indexOf(jasmineCorePath) === -1;
215215
}).join('\n');
216216
return filteredStack;
@@ -230,8 +230,8 @@ function ConsoleReporter() {
230230
}
231231

232232
function printFailedExpectations(result) {
233-
for (var i = 0; i < result.failedExpectations.length; i++) {
234-
var failedExpectation = result.failedExpectations[i];
233+
for (let i = 0; i < result.failedExpectations.length; i++) {
234+
const failedExpectation = result.failedExpectations[i];
235235
printNewline();
236236
print(indent('Message:', 2));
237237
printNewline();
@@ -266,7 +266,7 @@ function ConsoleReporter() {
266266
print(pendingSpecNumber + ') ');
267267
print(result.fullName);
268268
printNewline();
269-
var pendingReason = "No reason given";
269+
let pendingReason = "No reason given";
270270
if (result.pendingReason && result.pendingReason !== '') {
271271
pendingReason = result.pendingReason;
272272
}

‎spec/command_spec.js

+18-19
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
var fs = require('fs'),
2-
path = require('path');
1+
const fs = require('fs');
2+
const path = require('path');
3+
const Command = require('../lib/command');
34

4-
var Command = require('../lib/command');
5-
6-
var projectBaseDir = 'spec/fixtures/sample_empty_project/';
7-
var spec = path.join(projectBaseDir, 'spec');
5+
const projectBaseDir = 'spec/fixtures/sample_empty_project/';
6+
const spec = path.join(projectBaseDir, 'spec');
87

98
function deleteDirectory(dir) {
109
if (fs.existsSync(dir)) {
11-
var dirFiles = fs.readdirSync(dir);
10+
const dirFiles = fs.readdirSync(dir);
1211
dirFiles.forEach(function(file) {
13-
var fullPath = path.join(dir, file);
12+
const fullPath = path.join(dir, file);
1413
if (fs.statSync(fullPath).isDirectory()) {
1514
deleteDirectory(fullPath);
1615
}
@@ -23,7 +22,7 @@ function deleteDirectory(dir) {
2322
}
2423

2524
function withValueForIsTTY(value, func) {
26-
var wasTTY = process.stdout.isTTY;
25+
const wasTTY = process.stdout.isTTY;
2726
try {
2827
process.stdout.isTTY = value;
2928
func();
@@ -35,12 +34,12 @@ function withValueForIsTTY(value, func) {
3534

3635
describe('command', function() {
3736
beforeEach(function() {
38-
var examplesDir = path.resolve(path.join(__dirname, 'fixtures', 'example'));
37+
const examplesDir = path.resolve(path.join(__dirname, 'fixtures', 'example'));
3938

4039
fs.mkdirSync(projectBaseDir);
4140

4241
this.out = (function() {
43-
var output = "";
42+
let output = "";
4443
return {
4544
print: function(str) {
4645
output += str;
@@ -86,8 +85,8 @@ describe('command', function() {
8685
});
8786

8887
it('writes default settings to jasmine.json', function() {
89-
var realJson = fs.readFileSync(path.join(spec, 'support/', 'jasmine.json'), 'utf-8');
90-
var fixtureJson = fs.readFileSync(path.join(__dirname, '../', 'lib/', 'examples/', 'jasmine.json'), 'utf-8');
88+
const realJson = fs.readFileSync(path.join(spec, 'support/', 'jasmine.json'), 'utf-8');
89+
const fixtureJson = fs.readFileSync(path.join(__dirname, '../', 'lib/', 'examples/', 'jasmine.json'), 'utf-8');
9190
expect(realJson).toEqual(fixtureJson);
9291
});
9392
});
@@ -99,7 +98,7 @@ describe('command', function() {
9998
});
10099

101100
it('displays the version of jasmine', function() {
102-
var packageVersion = require('../package.json').version;
101+
const packageVersion = require('../package.json').version;
103102
expect(this.out.getOutput()).toContain('jasmine v' + packageVersion);
104103
});
105104

@@ -115,7 +114,7 @@ describe('command', function() {
115114
});
116115

117116
it('displays the version of jasmine', function() {
118-
var packageVersion = require('../package.json').version;
117+
const packageVersion = require('../package.json').version;
119118
expect(this.out.getOutput()).toContain('jasmine v' + packageVersion);
120119
});
121120

@@ -265,23 +264,23 @@ describe('command', function() {
265264
});
266265

267266
it('can specify a reporter', function() {
268-
var reporterPath = path.resolve(path.join(__dirname, 'fixtures', 'customReporter.js'));
269-
var Reporter = require(reporterPath);
267+
const reporterPath = path.resolve(path.join(__dirname, 'fixtures', 'customReporter.js'));
268+
const Reporter = require(reporterPath);
270269
this.command.run(this.fakeJasmine, ['--reporter=' + reporterPath]);
271270
expect(this.fakeJasmine.clearReporters).toHaveBeenCalled();
272271
expect(this.fakeJasmine.addReporter).toHaveBeenCalledWith(jasmine.any(Reporter));
273272
});
274273

275274
it('prints an error if the file does not export a reporter', function() {
276-
var reporterPath = path.resolve(path.join(__dirname, 'fixtures', 'badReporter.js'));
275+
const reporterPath = path.resolve(path.join(__dirname, 'fixtures', 'badReporter.js'));
277276
this.command.run(this.fakeJasmine, ['--reporter=' + reporterPath]);
278277
expect(this.fakeJasmine.clearReporters).not.toHaveBeenCalled();
279278
expect(this.fakeJasmine.addReporter).not.toHaveBeenCalled();
280279
expect(this.out.getOutput()).toContain('failed to register reporter');
281280
});
282281

283282
it('prints an error if the reporter file does not exist', function() {
284-
var reporterPath = path.resolve(path.join(__dirname, 'fixtures', 'missingReporter.js'));
283+
const reporterPath = path.resolve(path.join(__dirname, 'fixtures', 'missingReporter.js'));
285284
this.command.run(this.fakeJasmine, ['--reporter=' + reporterPath]);
286285
expect(this.fakeJasmine.clearReporters).not.toHaveBeenCalled();
287286
expect(this.fakeJasmine.addReporter).not.toHaveBeenCalled();
+5-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
var ConsoleSpecFilter = require('../../lib/filters/console_spec_filter');
1+
const ConsoleSpecFilter = require('../../lib/filters/console_spec_filter');
22

33
describe("ConsoleSpecFilter", function() {
44

55
it("should match when no string is provided", function() {
6-
var specFilter = new ConsoleSpecFilter();
6+
const specFilter = new ConsoleSpecFilter();
77

88
expect(specFilter.matches("foo")).toBe(true);
99
expect(specFilter.matches("*bar")).toBe(true);
1010
});
1111

1212
it("should match the provided string", function() {
13-
var specFilter = new ConsoleSpecFilter({
13+
const specFilter = new ConsoleSpecFilter({
1414
filterString: "foo"
1515
});
1616

@@ -19,12 +19,12 @@ describe("ConsoleSpecFilter", function() {
1919
});
2020

2121
it("should match by part of spec name", function() {
22-
var specFilter = new ConsoleSpecFilter({
22+
const specFilter = new ConsoleSpecFilter({
2323
filterString: "ba"
2424
});
2525

2626
expect(specFilter.matches("foo")).toBe(false);
2727
expect(specFilter.matches("bar")).toBe(true);
2828
expect(specFilter.matches("baz")).toBe(true);
2929
});
30-
});
30+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require('./syntax_error');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"spec_dir": ".",
3+
"spec_files": [
4+
"spec.mjs"
5+
],
6+
"helpers": []
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
await import('./intermediate.js');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"spec_dir": ".",
3+
"spec_files": [
4+
"spec.mjs"
5+
],
6+
"helpers": []
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import './throws.mjs';
2+
3+
it('a spec', () => {});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
throw new Error('nope');
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
await Promise.resolve();

‎spec/integration_spec.js

+26
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,32 @@ describe('Integration', function () {
8989
expect(output).toContain('syntax_error.mjs');
9090
});
9191

92+
it('handles syntax errors from a CommonJS module loaded from an ESM spec properly', async function() {
93+
try {
94+
await import('./fixtures/topLevelAwaitSentinel.mjs');
95+
} catch (e) {
96+
if (e instanceof SyntaxError && e.message === 'Unexpected reserved word') {
97+
pending('This Node version does not support top-level await');
98+
} else if (e.message === 'Not supported') {
99+
pending('This Node version does not support dynamic import');
100+
} else {
101+
throw e;
102+
}
103+
}
104+
105+
const {exitCode, output} = await runJasmine('spec/fixtures/esm-importing-commonjs-syntax-error', true);
106+
expect(exitCode).toEqual(1);
107+
expect(output).toContain('SyntaxError');
108+
expect(output).toContain('syntax_error.js');
109+
});
110+
111+
it('handles exceptions thrown from a module loaded from an ESM spec properly', async function() {
112+
const {exitCode, output} = await runJasmine('spec/fixtures/esm-indirect-error', true);
113+
expect(exitCode).toEqual(1);
114+
expect(output).toContain('nope');
115+
expect(output).toContain('throws.mjs');
116+
});
117+
92118
it('can configure the env via the `env` config property', async function() {
93119
const {exitCode, output} = await runJasmine('spec/fixtures/env-config');
94120
expect(exitCode).toEqual(0);

‎spec/jasmine_spec.js

+26-26
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
describe('Jasmine', function() {
2-
var path = require('path'),
3-
slash = require('slash'),
4-
Jasmine = require('../lib/jasmine');
1+
const path = require('path');
2+
const slash = require('slash');
3+
const Jasmine = require('../lib/jasmine');
54

5+
describe('Jasmine', function() {
66
beforeEach(function() {
77
this.bootedJasmine = {
88
getEnv: jasmine.createSpy('getEnv').and.returnValue({
@@ -74,7 +74,7 @@ describe('Jasmine', function() {
7474

7575
function hasCommonFileGlobBehavior(method, destProp) {
7676
it('adds a file with an absolute path', function() {
77-
var aFile = path.join(this.testJasmine.projectBaseDir, this.testJasmine.specDir, 'spec/command_spec.js');
77+
const aFile = path.join(this.testJasmine.projectBaseDir, this.testJasmine.specDir, 'spec/command_spec.js');
7878
expect(this.testJasmine[destProp]).toEqual([]);
7979
this.testJasmine[method]([aFile]);
8080
expect(this.testJasmine[destProp]).toEqual([slash(aFile)]);
@@ -105,7 +105,7 @@ describe('Jasmine', function() {
105105
});
106106

107107
it('adds new files to existing files', function() {
108-
var aFile = path.join(this.testJasmine.projectBaseDir, this.testJasmine.specDir, 'spec/command_spec.js');
108+
const aFile = path.join(this.testJasmine.projectBaseDir, this.testJasmine.specDir, 'spec/command_spec.js');
109109
this.testJasmine[destProp] = [aFile, 'b'];
110110
this.testJasmine[method](['spec/fixtures/jasmine_spec/*.js']);
111111
expect(this.testJasmine[destProp].map(basename)).toEqual([
@@ -130,13 +130,13 @@ describe('Jasmine', function() {
130130
it('registers a console reporter upon construction', function() {
131131
spyOn(Jasmine, 'ConsoleReporter').and.returnValue({someProperty: 'some value'});
132132

133-
var testJasmine = new Jasmine({ jasmineCore: this.fakeJasmineCore });
133+
const testJasmine = new Jasmine({ jasmineCore: this.fakeJasmineCore });
134134

135135
expect(testJasmine.env.addReporter).toHaveBeenCalledWith({someProperty: 'some value'});
136136
});
137137

138138
it('exposes #addReporter and #clearReporters', function() {
139-
var testJasmine = new Jasmine({ jasmineCore: this.fakeJasmineCore });
139+
const testJasmine = new Jasmine({ jasmineCore: this.fakeJasmineCore });
140140
expect(testJasmine.reportersCount).toEqual(1);
141141
testJasmine.clearReporters();
142142
expect(testJasmine.reportersCount).toEqual(0);
@@ -152,13 +152,13 @@ describe('Jasmine', function() {
152152
});
153153

154154
it('sets the options on the console reporter', function() {
155-
var reporterOptions = {
155+
const reporterOptions = {
156156
print: 'printer',
157157
showColors: true,
158158
jasmineCorePath: 'path',
159159
};
160160

161-
var expectedReporterOptions = Object.keys(reporterOptions).reduce(function(options, key) {
161+
const expectedReporterOptions = Object.keys(reporterOptions).reduce(function(options, key) {
162162
options[key] = reporterOptions[key];
163163
return options;
164164
}, {});
@@ -169,11 +169,11 @@ describe('Jasmine', function() {
169169
});
170170

171171
it('creates a reporter with a default option if an option is not specified', function() {
172-
var reporterOptions = {};
172+
const reporterOptions = {};
173173

174174
this.testJasmine.configureDefaultReporter(reporterOptions);
175175

176-
var expectedReporterOptions = {
176+
const expectedReporterOptions = {
177177
print: jasmine.any(Function),
178178
showColors: true,
179179
jasmineCorePath: path.normalize('fake/jasmine/path/jasmine.js')
@@ -236,7 +236,7 @@ describe('Jasmine', function() {
236236
this.configObject.stopSpecOnExpectationFailure = true;
237237
this.fixtureJasmine.loadConfig(this.configObject);
238238

239-
expect(this.fixtureJasmine.env.configure).toHaveBeenCalledWith({oneFailurePerSpec: true});
239+
expect(this.fixtureJasmine.env.configure).toHaveBeenCalledWith({stopSpecOnExpectationFailure: true});
240240
});
241241

242242
it('does not configure jasmine-core for stopping spec on expectation failure by default', function() {
@@ -249,7 +249,7 @@ describe('Jasmine', function() {
249249
this.configObject.stopOnSpecFailure = true;
250250
this.fixtureJasmine.loadConfig(this.configObject);
251251

252-
expect(this.fixtureJasmine.env.configure).toHaveBeenCalledWith({failFast: true});
252+
expect(this.fixtureJasmine.env.configure).toHaveBeenCalledWith({stopOnSpecFailure: true});
253253
});
254254

255255
it('does not configure jasmine-core for stopping execution by default', function() {
@@ -288,7 +288,7 @@ describe('Jasmine', function() {
288288

289289
describe('without options', function() {
290290
it('falls back to an empty string with an undefined spec_dir', function() {
291-
var config = this.configObject;
291+
const config = this.configObject;
292292
delete config.spec_dir;
293293

294294
this.fixtureJasmine.loadConfig(config);
@@ -397,7 +397,7 @@ describe('Jasmine', function() {
397397
});
398398

399399
it('loads the specified configuration file from an absolute path', function() {
400-
var absoluteConfigPath = path.join(__dirname, 'fixtures/sample_project/spec/support/jasmine_alternate.json');
400+
const absoluteConfigPath = path.join(__dirname, 'fixtures/sample_project/spec/support/jasmine_alternate.json');
401401
this.fixtureJasmine.loadConfigFile(absoluteConfigPath);
402402
expect(this.fixtureJasmine.helperFiles).toEqual(['spec/fixtures/sample_project/spec/helper.js']);
403403
expect(this.fixtureJasmine.requires).toEqual(['ts-node/register']);
@@ -408,13 +408,13 @@ describe('Jasmine', function() {
408408
});
409409

410410
it('throw error if specified configuration file doesn\'t exist', function() {
411-
var jasmine = this.fixtureJasmine;
411+
const jasmine = this.fixtureJasmine;
412412
function load() { jasmine.loadConfigFile('missing.json'); }
413413
expect(load).toThrow();
414414
});
415415

416416
it('no error if default configuration file doesn\'t exist', function() {
417-
var jasmine = this.fixtureJasmine;
417+
const jasmine = this.fixtureJasmine;
418418
function load() {
419419
jasmine.projectBaseDir += '/missing';
420420
jasmine.loadConfigFile();
@@ -432,16 +432,16 @@ describe('Jasmine', function() {
432432
});
433433

434434
describe('#stopSpecOnExpectationFailure', function() {
435-
it('sets the throwOnExpectationFailure value on the jasmine-core env', function() {
435+
it('sets the stopSpecOnExpectationFailure value on the jasmine-core env', function() {
436436
this.testJasmine.stopSpecOnExpectationFailure('foobar');
437-
expect(this.testJasmine.env.configure).toHaveBeenCalledWith({oneFailurePerSpec: 'foobar'});
437+
expect(this.testJasmine.env.configure).toHaveBeenCalledWith({stopSpecOnExpectationFailure: 'foobar'});
438438
});
439439
});
440440

441441
describe('#stopOnSpecFailure', function() {
442442
it('sets the stopOnSpecFailure value on the jasmine-core env', function() {
443443
this.testJasmine.stopOnSpecFailure('blah');
444-
expect(this.testJasmine.env.configure).toHaveBeenCalledWith({failFast: 'blah'});
444+
expect(this.testJasmine.env.configure).toHaveBeenCalledWith({stopOnSpecFailure: 'blah'});
445445
});
446446
});
447447

@@ -454,7 +454,7 @@ describe('Jasmine', function() {
454454

455455
describe('#onComplete', function() {
456456
it('stores an onComplete function', function() {
457-
var fakeOnCompleteCallback = function() {};
457+
const fakeOnCompleteCallback = function() {};
458458
spyOn(this.testJasmine.completionReporter, 'onComplete');
459459
this.testJasmine.env.deprecated = jasmine.createSpy('env.deprecated');
460460

@@ -513,7 +513,7 @@ describe('Jasmine', function() {
513513
});
514514

515515
it('loads helper files before checking if any reporters were added', async function() {
516-
var loadHelpers = spyOn(this.testJasmine, 'loadHelpers');
516+
const loadHelpers = spyOn(this.testJasmine, 'loadHelpers');
517517
spyOn(this.testJasmine, 'configureDefaultReporter').and.callFake(function() {
518518
expect(loadHelpers).toHaveBeenCalled();
519519
});
@@ -532,7 +532,7 @@ describe('Jasmine', function() {
532532

533533
await this.testJasmine.execute(['spec/fixtures/sample_project/**/*spec.js']);
534534

535-
var relativePaths = this.testJasmine.specFiles.map(function(filePath) {
535+
const relativePaths = this.testJasmine.specFiles.map(function(filePath) {
536536
return slash(path.relative(__dirname, filePath));
537537
});
538538

@@ -547,7 +547,7 @@ describe('Jasmine', function() {
547547
});
548548

549549
it('adds an exit code reporter', async function() {
550-
var completionReporterSpy = jasmine.createSpyObj('reporter', ['onComplete']);
550+
const completionReporterSpy = jasmine.createSpyObj('reporter', ['onComplete']);
551551
this.testJasmine.completionReporter = completionReporterSpy;
552552
spyOn(this.testJasmine, 'addReporter');
553553

@@ -572,7 +572,7 @@ describe('Jasmine', function() {
572572
});
573573

574574
it('leaves it if the suite has completed', function() {
575-
var completionReporterSpy = jasmine.createSpyObj('reporter', ['isComplete']);
575+
const completionReporterSpy = jasmine.createSpyObj('reporter', ['isComplete']);
576576
completionReporterSpy.isComplete.and.returnValue(true);
577577
this.testJasmine.completionReporter = completionReporterSpy;
578578

‎spec/load_config_spec.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
describe('loadConfig', function() {
2-
var path = require('path'),
3-
loadConfig = require('../lib/loadConfig');
1+
const path = require('path');
2+
const loadConfig = require('../lib/loadConfig');
43

4+
describe('loadConfig', function() {
55
it('should configure the jasmine object based on env and call execute', function() {
6-
var fakeJasmine = jasmine.createSpyObj('jasmine', ['loadConfigFile', 'addHelperFiles', 'addRequires', 'showColors', 'execute', 'stopSpecOnExpectationFailure',
6+
const fakeJasmine = jasmine.createSpyObj('jasmine', ['loadConfigFile', 'addHelperFiles', 'addRequires', 'showColors', 'execute', 'stopSpecOnExpectationFailure',
77
'stopOnSpecFailure', 'randomizeTests', 'seed', 'coreVersion', 'clearReporters', 'addReporter']),
88
env = {
99
configPath: 'somewhere.json',
@@ -33,7 +33,7 @@ describe('loadConfig', function() {
3333
});
3434

3535
it('should not configure the jasmine object when env is an empty object and call execute', function() {
36-
var fakeJasmine = jasmine.createSpyObj('jasmine', ['loadConfigFile', 'addHelperFiles', 'addRequires', 'showColors', 'execute', 'stopSpecOnExpectationFailure',
36+
const fakeJasmine = jasmine.createSpyObj('jasmine', ['loadConfigFile', 'addHelperFiles', 'addRequires', 'showColors', 'execute', 'stopSpecOnExpectationFailure',
3737
'stopOnSpecFailure', 'randomizeTests', 'seed', 'coreVersion', 'clearReporters', 'addReporter']),
3838
env = {};
3939
loadConfig(fakeJasmine, env, console.log);

‎spec/loader_spec.js

+66-9
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,81 @@ function esModuleSharedExamples(extension, alwaysImport) {
7070
await expectAsync(loaderPromise).toBeResolved();
7171
});
7272

73-
it("adds the filename to errors that don't include it", async function() {
73+
it("adds the filename to ES module syntax errors", async function() {
7474
const underlyingError = new SyntaxError('some details but no filename, not even in the stack trace');
75-
const importShim = () => Promise.reject(underlyingError);
76-
const loader = new Loader({importShim});
75+
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
7776

7877
await expectAsync(loader.load(`foo.${extension}`, alwaysImport)).toBeRejectedWithError(
7978
`While loading foo.${extension}: SyntaxError: some details but no filename, not even in the stack trace`
8079
);
8180
});
8281

83-
it('propagates errors that already contain the filename without modifying them', async function () {
84-
const requireShim = jasmine.createSpy('requireShim');
82+
it('does not modify errors that are not SyntaxError instances', async function() {
8583
const underlyingError = new Error('nope');
86-
underlyingError.stack = underlyingError.stack.replace('loader_spec.js', `foo.${extension}`);
87-
const importShim = jasmine.createSpy('importShim')
88-
.and.callFake(() => Promise.reject(underlyingError));
89-
const loader = new Loader({requireShim, importShim});
84+
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
9085

9186
await expectAsync(loader.load(`foo.${extension}`, alwaysImport)).toBeRejectedWith(underlyingError);
9287
});
88+
89+
it('does not modify SyntaxErrors that mention the imported filename as a Unix-style path', async function() {
90+
const underlyingError = new SyntaxError('nope');
91+
underlyingError.stack = `/the/absolute/path/to/foo.${extension}:1\n` +
92+
'\n' +
93+
'\n' +
94+
'\n' +
95+
'maybe some more stack\n';
96+
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
97+
98+
await expectAsync(loader.load(`path/to/foo.${extension}`, alwaysImport))
99+
.toBeRejectedWith(underlyingError);
100+
});
101+
102+
it('does not modify SyntaxErrors that mention the imported filename as a Unix-style file URL', async function() {
103+
const underlyingError = new SyntaxError('nope');
104+
underlyingError.stack += `\n at async file:///the/absolute/path/to/foo.${extension}:1:1`;
105+
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
106+
107+
await expectAsync(loader.load(`path/to/foo.${extension}`, alwaysImport))
108+
.toBeRejectedWith(underlyingError);
109+
});
110+
111+
it('does not modify SyntaxErrors that mention the imported filename as a Windows-style path', async function() {
112+
const underlyingError = new SyntaxError('nope');
113+
underlyingError.stack = `c:\\the\\absolute\\path\\to\\foo.${extension}:1\n` +
114+
'\n' +
115+
'\n' +
116+
'\n' +
117+
'maybe some more stack\n';
118+
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
119+
120+
await expectAsync(loader.load(`path/to/foo.${extension}`, alwaysImport))
121+
.toBeRejectedWith(underlyingError);
122+
});
123+
124+
it('does not modify SyntaxErrors that mention the imported filename as a Windows-style file URL', async function() {
125+
const underlyingError = new SyntaxError('nope');
126+
underlyingError.stack += `\n at async file:///c:/the/absolute/path/to/foo.${extension}:1:1`;
127+
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
128+
129+
await expectAsync(loader.load(`path/to/foo.${extension}`, alwaysImport))
130+
.toBeRejectedWith(underlyingError);
131+
});
132+
133+
it('does not modify SyntaxErrors when the stack trace starts with any Unix-style path', async function() {
134+
const underlyingError = new SyntaxError('nope');
135+
underlyingError.stack = '/some/path/to/a/file.js:1\n\n\n\n' + underlyingError.stack;
136+
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
137+
138+
await expectAsync(loader.load(`path/to/some/other/file.${extension}`, alwaysImport))
139+
.toBeRejectedWith(underlyingError);
140+
});
141+
142+
it('does not modify SyntaxErrors when the stack trace starts with any Windows-style path', async function() {
143+
const underlyingError = new SyntaxError('nope');
144+
underlyingError.stack = 'c:\\some\\path\\to\\a\\file.js:1\n\n\n\n' + underlyingError.stack;
145+
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
146+
147+
await expectAsync(loader.load(`path/to/some/other/file.${extension}`, alwaysImport))
148+
.toBeRejectedWith(underlyingError);
149+
});
93150
}

‎spec/npm_package_spec.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
describe('npm package', function() {
2-
var path = require('path'),
3-
temp = require('temp').track(),
4-
fs = require('fs');
1+
const path = require('path');
2+
const temp = require('temp').track();
3+
const fs = require('fs');
54

5+
describe('npm package', function() {
66
beforeAll(function() {
7-
var shell = require('shelljs'),
7+
const shell = require('shelljs'),
88
pack = shell.exec('npm pack', { silent: true });
99

1010
this.tarball = pack.stdout.split('\n')[0];
1111
this.tmpDir = temp.mkdirSync(); // automatically deleted on exit
1212

13-
var untar = shell.exec('tar -xzf ' + this.tarball + ' -C ' + this.tmpDir, {
13+
const untar = shell.exec('tar -xzf ' + this.tarball + ' -C ' + this.tmpDir, {
1414
silent: true
1515
});
1616
expect(untar.code).toBe(0);
@@ -21,7 +21,7 @@ describe('npm package', function() {
2121
toExistInPath: function() {
2222
return {
2323
compare: function(actual, expected) {
24-
var fullPath = path.resolve(expected, actual);
24+
const fullPath = path.resolve(expected, actual);
2525
return {
2626
pass: fs.existsSync(fullPath)
2727
};

‎spec/reporters/completion_reporter_spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
describe('CompletionReporter', function() {
2-
var CompletionReporter = require('../../lib/reporters/completion_reporter');
1+
const CompletionReporter = require('../../lib/reporters/completion_reporter');
32

3+
describe('CompletionReporter', function() {
44
beforeEach(function() {
55
this.reporter = new CompletionReporter();
66
this.onComplete = jasmine.createSpy('onComplete');

‎spec/reporters/console_reporter_spec.js

+35-35
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
describe("ConsoleReporter", function() {
2-
var ConsoleReporter = require('../../lib/reporters/console_reporter'),
3-
jasmineCorePath = 'path/to/jasmine/core/jasmine.js';
1+
const ConsoleReporter = require('../../lib/reporters/console_reporter');
2+
const jasmineCorePath = 'path/to/jasmine/core/jasmine.js';
43

5-
var fakeStack = ['foo' + jasmineCorePath,
4+
describe("ConsoleReporter", function() {
5+
const fakeStack = ['foo' + jasmineCorePath,
66
'bar ' + jasmineCorePath,
77
'line of useful stack trace',
88
'baz ' + jasmineCorePath].join('\n');
99

1010
beforeEach(function() {
1111
this.out = (function() {
12-
var output = "";
12+
let output = "";
1313
return {
1414
print: function(str) {
1515
output += str;
@@ -25,7 +25,7 @@ describe("ConsoleReporter", function() {
2525
});
2626

2727
it("reports that the suite has started to the console", function() {
28-
var reporter = new ConsoleReporter();
28+
const reporter = new ConsoleReporter();
2929

3030
reporter.setOptions({
3131
print: this.out.print
@@ -38,7 +38,7 @@ describe("ConsoleReporter", function() {
3838

3939
describe("When order information is passed to jasmineStarted", function() {
4040
it("reports the seed number when randomized", function() {
41-
var reporter = new ConsoleReporter();
41+
const reporter = new ConsoleReporter();
4242
reporter.setOptions({
4343
print: this.out.print
4444
});
@@ -54,7 +54,7 @@ describe("ConsoleReporter", function() {
5454
});
5555

5656
it("does not report order info when not randomized", function() {
57-
var reporter = new ConsoleReporter();
57+
const reporter = new ConsoleReporter();
5858
reporter.setOptions({
5959
print: this.out.print
6060
});
@@ -70,7 +70,7 @@ describe("ConsoleReporter", function() {
7070
});
7171

7272
it("setOptions should not override existing options if set multiple times", function() {
73-
var reporter = new ConsoleReporter();
73+
const reporter = new ConsoleReporter();
7474

7575
reporter.setOptions({
7676
print: this.out.print,
@@ -94,7 +94,7 @@ describe("ConsoleReporter", function() {
9494
});
9595

9696
it("reports a passing spec as a dot", function() {
97-
var reporter = new ConsoleReporter();
97+
const reporter = new ConsoleReporter();
9898
reporter.setOptions({
9999
print: this.out.print
100100
});
@@ -105,7 +105,7 @@ describe("ConsoleReporter", function() {
105105
});
106106

107107
it("does not report a disabled spec", function() {
108-
var reporter = new ConsoleReporter();
108+
const reporter = new ConsoleReporter();
109109
reporter.setOptions({
110110
print: this.out.print
111111
});
@@ -116,7 +116,7 @@ describe("ConsoleReporter", function() {
116116
});
117117

118118
it("reports a failing spec as an 'F'", function() {
119-
var reporter = new ConsoleReporter();
119+
const reporter = new ConsoleReporter();
120120
reporter.setOptions({
121121
print: this.out.print
122122
});
@@ -127,7 +127,7 @@ describe("ConsoleReporter", function() {
127127
});
128128

129129
it("reports a pending spec as a '*'", function() {
130-
var reporter = new ConsoleReporter();
130+
const reporter = new ConsoleReporter();
131131
reporter.setOptions({
132132
print: this.out.print
133133
});
@@ -138,7 +138,7 @@ describe("ConsoleReporter", function() {
138138
});
139139

140140
it("alerts user if there are no specs", function() {
141-
var reporter = new ConsoleReporter();
141+
const reporter = new ConsoleReporter();
142142
reporter.setOptions({
143143
print: this.out.print
144144
});
@@ -151,7 +151,7 @@ describe("ConsoleReporter", function() {
151151
});
152152

153153
it("reports the seed number when running in random order", function() {
154-
var reporter = new ConsoleReporter();
154+
const reporter = new ConsoleReporter();
155155
reporter.setOptions({
156156
print: this.out.print
157157
});
@@ -167,7 +167,7 @@ describe("ConsoleReporter", function() {
167167
});
168168

169169
it("allows the seed reproduction command to be overridden", function() {
170-
var reporter = new ConsoleReporter("jasmine-some-other-tool");
170+
const reporter = new ConsoleReporter("jasmine-some-other-tool");
171171
reporter.setOptions({
172172
print: this.out.print,
173173
randomSeedReproductionCmd: function(seed) {
@@ -186,7 +186,7 @@ describe("ConsoleReporter", function() {
186186
});
187187

188188
it("reports a summary when done (singular spec and time)", function() {
189-
var reporter = new ConsoleReporter();
189+
const reporter = new ConsoleReporter();
190190
reporter.setOptions({
191191
print: this.out.print,
192192
});
@@ -204,7 +204,7 @@ describe("ConsoleReporter", function() {
204204
});
205205

206206
it("reports a summary when done (pluralized specs and seconds)", function() {
207-
var reporter = new ConsoleReporter();
207+
const reporter = new ConsoleReporter();
208208
reporter.setOptions({
209209
print: this.out.print,
210210
});
@@ -237,7 +237,7 @@ describe("ConsoleReporter", function() {
237237
});
238238

239239
it("reports a summary when done that indicates the number of specs run (when it's less that the full number of specs)", function() {
240-
var reporter = new ConsoleReporter();
240+
const reporter = new ConsoleReporter();
241241
reporter.setOptions({
242242
print: this.out.print,
243243
});
@@ -254,7 +254,7 @@ describe("ConsoleReporter", function() {
254254
});
255255

256256
it("reports a summary when done that includes the failed spec number before the full name of a failing spec", function() {
257-
var reporter = new ConsoleReporter();
257+
const reporter = new ConsoleReporter();
258258
reporter.setOptions({
259259
print: this.out.print,
260260
jasmineCorePath: jasmineCorePath
@@ -286,7 +286,7 @@ describe("ConsoleReporter", function() {
286286
});
287287

288288
it("reports a summary when done that includes stack traces without jasmine internals for a failing suite", function() {
289-
var reporter = new ConsoleReporter();
289+
const reporter = new ConsoleReporter();
290290
reporter.setOptions({
291291
print: this.out.print,
292292
jasmineCorePath: jasmineCorePath
@@ -320,7 +320,7 @@ describe("ConsoleReporter", function() {
320320
});
321321

322322
it("reports a summary when done in case that stack is somehow undefined", function() {
323-
var reporter = new ConsoleReporter();
323+
const reporter = new ConsoleReporter();
324324
reporter.setOptions({
325325
print: this.out.print,
326326
jasmineCorePath: jasmineCorePath
@@ -352,11 +352,11 @@ describe("ConsoleReporter", function() {
352352
});
353353

354354
it("reports a summary when done that includes custom filtered stack traces for a failing suite", function() {
355-
var stackLine = 'custom line of stack';
356-
var customStackFilter = function(stack) {
355+
const stackLine = 'custom line of stack';
356+
const customStackFilter = function(stack) {
357357
return stackLine;
358358
};
359-
var reporter = new ConsoleReporter();
359+
const reporter = new ConsoleReporter();
360360
reporter.setOptions({
361361
print: this.out.print,
362362
stackFilter: customStackFilter
@@ -389,7 +389,7 @@ describe("ConsoleReporter", function() {
389389
});
390390

391391
it("reports a summary when done that includes which specs are pending and their reasons", function() {
392-
var reporter = new ConsoleReporter();
392+
const reporter = new ConsoleReporter();
393393
reporter.setOptions({
394394
print: this.out.print,
395395
jasmineCorePath: jasmineCorePath
@@ -413,7 +413,7 @@ describe("ConsoleReporter", function() {
413413
});
414414

415415
it("reports a summary when done that includes the reason for an incomplete suite", function() {
416-
var reporter = new ConsoleReporter();
416+
const reporter = new ConsoleReporter();
417417
reporter.setOptions({
418418
print: this.out.print,
419419
jasmineCorePath: jasmineCorePath
@@ -432,7 +432,7 @@ describe("ConsoleReporter", function() {
432432
});
433433

434434
it("reports a summary when done that shows info for a failed spec with no expectations", function() {
435-
var reporter = new ConsoleReporter();
435+
const reporter = new ConsoleReporter();
436436
reporter.setOptions({
437437
print: this.out.print,
438438
jasmineCorePath: jasmineCorePath
@@ -456,7 +456,7 @@ describe("ConsoleReporter", function() {
456456
});
457457

458458
it('reports a summary without "no expectations" message for a spec having failed expectations', function () {
459-
var reporter = new ConsoleReporter();
459+
const reporter = new ConsoleReporter();
460460
reporter.setOptions({
461461
print: this.out.print,
462462
jasmineCorePath: jasmineCorePath
@@ -485,7 +485,7 @@ describe("ConsoleReporter", function() {
485485
});
486486

487487
it('reports a summary without a "no expectations" message for a spec having passed expectations', function () {
488-
var reporter = new ConsoleReporter();
488+
const reporter = new ConsoleReporter();
489489
reporter.setOptions({
490490
print: this.out.print,
491491
jasmineCorePath: jasmineCorePath
@@ -524,7 +524,7 @@ describe("ConsoleReporter", function() {
524524
});
525525

526526
it("displays all afterAll exceptions", function() {
527-
var reporter = new ConsoleReporter();
527+
const reporter = new ConsoleReporter();
528528
reporter.setOptions({
529529
print: this.out.print,
530530
showColors: true
@@ -541,7 +541,7 @@ describe("ConsoleReporter", function() {
541541

542542
describe("with color", function() {
543543
it("reports that the suite has started to the console", function() {
544-
var reporter = new ConsoleReporter();
544+
const reporter = new ConsoleReporter();
545545
reporter.setOptions({
546546
print: this.out.print,
547547
showColors: true
@@ -553,7 +553,7 @@ describe("ConsoleReporter", function() {
553553
});
554554

555555
it("reports a passing spec as a dot", function() {
556-
var reporter = new ConsoleReporter();
556+
const reporter = new ConsoleReporter();
557557
reporter.setOptions({
558558
print: this.out.print,
559559
showColors: true
@@ -565,7 +565,7 @@ describe("ConsoleReporter", function() {
565565
});
566566

567567
it("does not report a disabled spec", function() {
568-
var reporter = new ConsoleReporter();
568+
const reporter = new ConsoleReporter();
569569
reporter.setOptions({
570570
print: this.out.print,
571571
showColors: true
@@ -577,7 +577,7 @@ describe("ConsoleReporter", function() {
577577
});
578578

579579
it("reports a failing spec as an 'F'", function() {
580-
var reporter = new ConsoleReporter();
580+
const reporter = new ConsoleReporter();
581581
reporter.setOptions({
582582
print: this.out.print,
583583
showColors: true

0 commit comments

Comments
 (0)
Please sign in to comment.