Comparing version 3.99.0 to 4.6.0
#!/usr/bin/env node | ||
const path = require('path'); | ||
const os = require('os'); | ||
const Command = require('../lib/command'); | ||
const Jasmine = require('../lib/jasmine'); | ||
const jasmine = new Jasmine({ projectBaseDir: path.resolve() }); | ||
let projectBaseDir = path.resolve(); | ||
if (os.platform() === 'win32') { | ||
// Future versions of glob will interpret backslashes as escape sequences on | ||
// all platforms, and Jasmine warns about them. Convert to slashes to avoid | ||
// the warning and future behavior change. | ||
projectBaseDir = projectBaseDir.replace(/\\/g, '/'); | ||
} | ||
const jasmine = new Jasmine({ projectBaseDir }); | ||
const examplesDir = path.join(path.dirname(require.resolve('jasmine-core')), 'jasmine-core', 'example', 'node_example'); | ||
const command = new Command(path.resolve(), examplesDir, console.log); | ||
const command = new Command(path.resolve(), examplesDir, { | ||
print: console.log, | ||
platform: os.platform, | ||
}); | ||
command.run(jasmine, process.argv.slice(2)); |
@@ -27,9 +27,12 @@ const path = require('path'); | ||
function Command(projectBaseDir, examplesDir, print) { | ||
this.projectBaseDir = projectBaseDir; | ||
this.specDir = path.join(projectBaseDir, 'spec'); | ||
function Command(projectBaseDir, examplesDir, deps) { | ||
const {print, platform} = deps; | ||
const isWindows = platform() === 'win32'; | ||
this.projectBaseDir = isWindows ? unWindows(projectBaseDir) : projectBaseDir; | ||
this.specDir = `${this.projectBaseDir}/spec`; | ||
const command = this; | ||
this.run = function(jasmine, commands) { | ||
this.run = async function(jasmine, commands) { | ||
setEnvironmentVariables(commands); | ||
@@ -50,3 +53,3 @@ | ||
} else { | ||
const env = parseOptions(commands); | ||
const env = parseOptions(commands, isWindows); | ||
if (env.unknownOptions.length > 0) { | ||
@@ -58,3 +61,3 @@ process.exitCode = 1; | ||
} else { | ||
runJasmine(jasmine, env, print); | ||
await runJasmine(jasmine, env); | ||
} | ||
@@ -69,3 +72,3 @@ } | ||
function parseOptions(argv) { | ||
function parseOptions(argv, isWindows) { | ||
let files = [], | ||
@@ -79,3 +82,2 @@ helpers = [], | ||
filter, | ||
stopOnFailure, | ||
failFast, | ||
@@ -85,4 +87,3 @@ random, | ||
for (let i in argv) { | ||
const arg = argv[i]; | ||
for (const arg of argv) { | ||
if (arg === '--no-color') { | ||
@@ -98,6 +99,4 @@ color = false; | ||
requires.push(arg.match("^--require=(.*)")[1]); | ||
} else if (arg.match("^--stop-on-failure=")) { | ||
stopOnFailure = arg.match("^--stop-on-failure=(.*)")[1] === 'true'; | ||
} else if (arg.match("^--fail-fast=")) { | ||
failFast = arg.match("^--fail-fast=(.*)")[1] === 'true'; | ||
} else if (arg === '--fail-fast') { | ||
failFast = true; | ||
} else if (arg.match("^--random=")) { | ||
@@ -114,3 +113,3 @@ random = arg.match("^--random=(.*)")[1] === 'true'; | ||
} else if (isFileArg(arg)) { | ||
files.push(arg); | ||
files.push(isWindows ? unWindows(arg) : arg); | ||
} else if (!isEnvironmentVariable(arg)) { | ||
@@ -120,28 +119,89 @@ unknownOptions.push(arg); | ||
} | ||
return { | ||
color: color, | ||
configPath: configPath, | ||
filter: filter, | ||
stopOnFailure: stopOnFailure, | ||
failFast: failFast, | ||
helpers: helpers, | ||
requires: requires, | ||
reporter: reporter, | ||
files: files, | ||
random: random, | ||
seed: seed, | ||
unknownOptions: unknownOptions | ||
color, | ||
configPath, | ||
filter, | ||
failFast, | ||
helpers, | ||
requires, | ||
reporter, | ||
files, | ||
random, | ||
seed, | ||
unknownOptions | ||
}; | ||
} | ||
function runJasmine(jasmine, env, print) { | ||
const loadConfig = require('./loadConfig'); | ||
loadConfig(jasmine, env, print); | ||
jasmine.execute(env.files, env.filter) | ||
.catch(function(error) { | ||
console.error(error); | ||
process.exit(1); | ||
async function runJasmine(jasmine, options) { | ||
await jasmine.loadConfigFile(options.configPath || process.env.JASMINE_CONFIG_PATH); | ||
if (options.failFast !== undefined) { | ||
jasmine.env.configure({ | ||
stopSpecOnExpectationFailure: options.failFast, | ||
stopOnSpecFailure: options.failFast | ||
}); | ||
} | ||
if (options.seed !== undefined) { | ||
jasmine.seed(options.seed); | ||
} | ||
if (options.random !== undefined) { | ||
jasmine.randomizeTests(options.random); | ||
} | ||
if (options.helpers !== undefined && options.helpers.length) { | ||
jasmine.addMatchingHelperFiles(options.helpers); | ||
} | ||
if (options.requires !== undefined && options.requires.length) { | ||
jasmine.addRequires(options.requires); | ||
} | ||
if (options.reporter !== undefined) { | ||
await registerReporter(options.reporter, jasmine); | ||
} | ||
jasmine.showColors(options.color); | ||
try { | ||
await jasmine.execute(options.files, options.filter); | ||
} catch (error) { | ||
console.error(error); | ||
process.exit(1); | ||
} | ||
} | ||
async function registerReporter(reporterModuleName, jasmine) { | ||
let Reporter; | ||
try { | ||
Reporter = await jasmine.loader.load(resolveReporter(reporterModuleName)); | ||
} catch (e) { | ||
throw new Error('Failed to load reporter module '+ reporterModuleName + | ||
'\nUnderlying error: ' + e.stack + '\n(end underlying error)'); | ||
} | ||
let reporter; | ||
try { | ||
reporter = new Reporter(); | ||
} catch (e) { | ||
throw new Error('Failed to instantiate reporter from '+ reporterModuleName + | ||
'\nUnderlying error: ' + e.stack + '\n(end underlying error)'); | ||
} | ||
jasmine.clearReporters(); | ||
jasmine.addReporter(reporter); | ||
} | ||
function resolveReporter(nameOrPath) { | ||
if (nameOrPath.startsWith('./') || nameOrPath.startsWith('../')) { | ||
return path.resolve(nameOrPath); | ||
} else { | ||
return nameOrPath; | ||
} | ||
} | ||
function initJasmine(options) { | ||
@@ -211,4 +271,3 @@ const print = options.print; | ||
print('%s\tload module that match the given string', lPad('--require=', 18)); | ||
print('%s\t[true|false] stop spec execution on expectation failure', lPad('--stop-on-failure=', 18)); | ||
print('%s\t[true|false] stop Jasmine execution on spec failure', lPad('--fail-fast=', 18)); | ||
print('%s\tstop Jasmine execution on spec failure', lPad('--fail-fast', 18)); | ||
print('%s\tpath to your optional jasmine.json', lPad('--config=', 18)); | ||
@@ -272,1 +331,9 @@ print('%s\tpath to reporter to use instead of the default Jasmine reporter', lPad('--reporter=', 18)); | ||
} | ||
// Future versions of glob will interpret backslashes as escape sequences on | ||
// all platforms, and Jasmine warns about them. Convert to slashes to avoid | ||
// the warning and future behavior change. Should only be called when running | ||
// on Windows. | ||
function unWindows(projectBaseDir) { | ||
return projectBaseDir.replace(/\\/g, '/'); | ||
} |
@@ -9,4 +9,6 @@ { | ||
], | ||
"stopSpecOnExpectationFailure": false, | ||
"random": true | ||
"env": { | ||
"stopSpecOnExpectationFailure": false, | ||
"random": true | ||
} | ||
} |
@@ -0,1 +1,2 @@ | ||
const os = require('os'); | ||
const path = require('path'); | ||
@@ -5,8 +6,5 @@ const util = require('util'); | ||
const Loader = require('./loader'); | ||
const CompletionReporter = require('./reporters/completion_reporter'); | ||
const ExitHandler = require('./exit_handler'); | ||
const ConsoleSpecFilter = require('./filters/console_spec_filter'); | ||
module.exports = Jasmine; | ||
module.exports.ConsoleReporter = require('./reporters/console_reporter'); | ||
/** | ||
@@ -24,2 +22,13 @@ * Options for the {@link Jasmine} constructor | ||
*/ | ||
/** | ||
* Whether to create the globals (describe, it, etc) that make up Jasmine's | ||
* spec-writing interface. If it is set to false, the spec-writing interface | ||
* can be accessed via jasmine-core's `noGlobals` method, e.g.: | ||
* | ||
* `const {describe, it, expect, jasmine} = require('jasmine-core').noGlobals();` | ||
* | ||
* @name JasmineOptions#globals | ||
* @type (boolean | undefined) | ||
* @default true | ||
*/ | ||
@@ -35,332 +44,481 @@ /** | ||
*/ | ||
function Jasmine(options) { | ||
options = options || {}; | ||
this.loader = options.loader || new Loader(); | ||
const jasmineCore = options.jasmineCore || require('jasmine-core'); | ||
this.jasmineCorePath = path.join(jasmineCore.files.path, 'jasmine.js'); | ||
this.jasmine = jasmineCore.boot(jasmineCore); | ||
this.projectBaseDir = options.projectBaseDir || path.resolve(); | ||
this.specDir = ''; | ||
this.specFiles = []; | ||
this.helperFiles = []; | ||
this.requires = []; | ||
class Jasmine { | ||
constructor(options) { | ||
options = options || {}; | ||
this.loader = options.loader || new Loader(); | ||
this.isWindows_ = (options.platform || os.platform)() === 'win32'; | ||
const jasmineCore = options.jasmineCore || require('jasmine-core'); | ||
if (options.globals === false) { | ||
this.jasmine = jasmineCore.noGlobals().jasmine; | ||
} else { | ||
this.jasmine = jasmineCore.boot(jasmineCore); | ||
} | ||
if (options.projectBaseDir) { | ||
this.validatePath_(options.projectBaseDir); | ||
this.projectBaseDir = options.projectBaseDir; | ||
} else { | ||
this.projectBaseDir = (options.getcwd || path.resolve)(); | ||
} | ||
this.specDir = ''; | ||
this.specFiles = []; | ||
this.helperFiles = []; | ||
this.requires = []; | ||
/** | ||
* The Jasmine environment. | ||
* @name Jasmine#env | ||
* @readonly | ||
* @see {@link https://jasmine.github.io/api/edge/Env.html|Env} | ||
* @type {Env} | ||
*/ | ||
this.env = this.jasmine.getEnv({suppressLoadErrors: true}); | ||
this.reportersCount = 0; | ||
this.exit = process.exit; | ||
this.showingColors = true; | ||
this.alwaysListPendingSpecs_ = true; | ||
this.reporter = new module.exports.ConsoleReporter(); | ||
this.addReporter(this.reporter); | ||
this.defaultReporterConfigured = false; | ||
/** | ||
* @function | ||
* @name Jasmine#coreVersion | ||
* @return {string} The version of jasmine-core in use | ||
*/ | ||
this.coreVersion = function() { | ||
return jasmineCore.version(); | ||
}; | ||
/** | ||
* Whether to cause the Node process to exit when the suite finishes executing. | ||
* | ||
* @name Jasmine#exitOnCompletion | ||
* @type {boolean} | ||
* @default true | ||
*/ | ||
this.exitOnCompletion = true; | ||
} | ||
/** | ||
* The Jasmine environment. | ||
* @name Jasmine#env | ||
* @readonly | ||
* @see {@link https://jasmine.github.io/api/edge/Env.html|Env} | ||
* @type {Env} | ||
* Sets whether to randomize the order of specs. | ||
* @function | ||
* @name Jasmine#randomizeTests | ||
* @param {boolean} value Whether to randomize | ||
*/ | ||
this.env = this.jasmine.getEnv({suppressLoadErrors: true}); | ||
this.reportersCount = 0; | ||
this.completionReporter = new CompletionReporter(); | ||
this.onCompleteCallbackAdded = false; | ||
this.exit = process.exit; | ||
this.showingColors = true; | ||
this.reporter = new module.exports.ConsoleReporter(); | ||
this.addReporter(this.reporter); | ||
this.defaultReporterConfigured = false; | ||
randomizeTests(value) { | ||
this.env.configure({random: value}); | ||
} | ||
const jasmineRunner = this; | ||
this.completionReporter.onComplete(function(passed) { | ||
jasmineRunner.exitCodeCompletion(passed); | ||
}); | ||
this.checkExit = checkExit(this); | ||
/** | ||
* Sets the random seed. | ||
* @function | ||
* @name Jasmine#seed | ||
* @param {number} seed The random seed | ||
*/ | ||
seed(value) { | ||
this.env.configure({seed: value}); | ||
} | ||
/** | ||
* Sets whether to show colors in the console reporter. | ||
* @function | ||
* @name Jasmine#coreVersion | ||
* @return {string} The version of jasmine-core in use | ||
* @name Jasmine#showColors | ||
* @param {boolean} value Whether to show colors | ||
*/ | ||
this.coreVersion = function() { | ||
return jasmineCore.version(); | ||
}; | ||
showColors(value) { | ||
this.showingColors = value; | ||
} | ||
/** | ||
* Whether to cause the Node process to exit when the suite finishes executing. | ||
* | ||
* _Note_: If {@link Jasmine#onComplete|onComplete} is called, Jasmine will not | ||
* exit when the suite completes even if exitOnCompletion is set to true. | ||
* @name Jasmine#exitOnCompletion | ||
* @type {boolean} | ||
* @default true | ||
* Sets whether the console reporter should list pending specs even when there | ||
* are failures. | ||
* @name Jasmine#alwaysListPendingSpecs | ||
* @param value {boolean} | ||
*/ | ||
this.exitOnCompletion = true; | ||
} | ||
/** | ||
* Sets whether to randomize the order of specs. | ||
* @function | ||
* @name Jasmine#randomizeTests | ||
* @param {boolean} value Whether to randomize | ||
*/ | ||
Jasmine.prototype.randomizeTests = function(value) { | ||
this.env.configure({random: value}); | ||
}; | ||
/** | ||
* Sets the random seed. | ||
* @function | ||
* @name Jasmine#seed | ||
* @param {number} seed The random seed | ||
*/ | ||
Jasmine.prototype.seed = function(value) { | ||
this.env.configure({seed: value}); | ||
}; | ||
/** | ||
* Sets whether to show colors in the console reporter. | ||
* @function | ||
* @name Jasmine#showColors | ||
* @param {boolean} value Whether to show colors | ||
*/ | ||
Jasmine.prototype.showColors = function(value) { | ||
this.showingColors = value; | ||
}; | ||
/** | ||
* Adds a spec file to the list that will be loaded when the suite is executed. | ||
* @function | ||
* @name Jasmine#addSpecFile | ||
* @param {string} filePath The path to the file to be loaded. | ||
*/ | ||
Jasmine.prototype.addSpecFile = function(filePath) { | ||
this.specFiles.push(filePath); | ||
}; | ||
/** | ||
* Adds a helper file to the list that will be loaded when the suite is executed. | ||
* @function | ||
* @name Jasmine#addHelperFile | ||
* @param {string} filePath The path to the file to be loaded. | ||
*/ | ||
Jasmine.prototype.addHelperFile = function(filePath) { | ||
this.helperFiles.push(filePath); | ||
}; | ||
/** | ||
* Add a custom reporter to the Jasmine environment. | ||
* @function | ||
* @name Jasmine#addReporter | ||
* @param {Reporter} reporter The reporter to add | ||
* @see custom_reporter | ||
*/ | ||
Jasmine.prototype.addReporter = function(reporter) { | ||
this.env.addReporter(reporter); | ||
this.reportersCount++; | ||
}; | ||
/** | ||
* Clears all registered reporters. | ||
* @function | ||
* @name Jasmine#clearReporters | ||
*/ | ||
Jasmine.prototype.clearReporters = function() { | ||
this.env.clearReporters(); | ||
this.reportersCount = 0; | ||
}; | ||
/** | ||
* Provide a fallback reporter if no other reporters have been specified. | ||
* @function | ||
* @name Jasmine#provideFallbackReporter | ||
* @param reporter The fallback reporter | ||
* @see custom_reporter | ||
*/ | ||
Jasmine.prototype.provideFallbackReporter = function(reporter) { | ||
this.env.provideFallbackReporter(reporter); | ||
}; | ||
/** | ||
* Configures the default reporter that is installed if no other reporter is | ||
* specified. | ||
* @param {ConsoleReporterOptions} options | ||
*/ | ||
Jasmine.prototype.configureDefaultReporter = function(options) { | ||
options.print = options.print || function() { | ||
process.stdout.write(util.format.apply(this, arguments)); | ||
}; | ||
options.showColors = options.hasOwnProperty('showColors') ? options.showColors : true; | ||
options.jasmineCorePath = options.jasmineCorePath || this.jasmineCorePath; | ||
this.reporter.setOptions(options); | ||
this.defaultReporterConfigured = true; | ||
}; | ||
/** | ||
* Add custom matchers for the current scope of specs. | ||
* | ||
* _Note:_ This is only callable from within a {@link beforeEach}, {@link it}, or {@link beforeAll}. | ||
* @function | ||
* @name Jasmine#addMatchers | ||
* @param {Object} matchers - Keys from this object will be the new matcher names. | ||
* @see custom_matcher | ||
*/ | ||
Jasmine.prototype.addMatchers = function(matchers) { | ||
this.env.addMatchers(matchers); | ||
}; | ||
Jasmine.prototype.loadSpecs = async function() { | ||
await this._loadFiles(this.specFiles); | ||
}; | ||
Jasmine.prototype.loadHelpers = async function() { | ||
await this._loadFiles(this.helperFiles); | ||
}; | ||
Jasmine.prototype._loadFiles = async function(files) { | ||
for (const file of files) { | ||
await this.loader.load(file, this._alwaysImport || false); | ||
alwaysListPendingSpecs(value) { | ||
this.alwaysListPendingSpecs_ = value; | ||
} | ||
}; | ||
Jasmine.prototype.loadRequires = function() { | ||
// TODO: In 4.0, switch to calling _loadFiles | ||
// (requires making this function async) | ||
this.requires.forEach(function(r) { | ||
if (r.startsWith('./') || r.startsWith("../")) { | ||
console.warn('DEPRECATION: requires with relative paths (in this case ' + | ||
`${r}) are currently resolved relative to the jasmine/lib/jasmine ` + | ||
'module but will be relative to the current working directory in ' + | ||
'Jasmine 4.0.'); | ||
} | ||
require(r); | ||
}); | ||
}; | ||
/** | ||
* Loads configuration from the specified file. The file can be a JSON file or | ||
* any JS file that's loadable via require and provides a Jasmine config | ||
* as its default export. | ||
* @param {string} [configFilePath=spec/support/jasmine.json] | ||
*/ | ||
Jasmine.prototype.loadConfigFile = function(configFilePath) { | ||
try { | ||
const absoluteConfigFilePath = path.resolve(this.projectBaseDir, configFilePath || 'spec/support/jasmine.json'); | ||
const config = require(absoluteConfigFilePath); | ||
this.loadConfig(config); | ||
} catch (e) { | ||
if(configFilePath || e.code != 'MODULE_NOT_FOUND') { throw e; } | ||
/** | ||
* Adds a spec file to the list that will be loaded when the suite is executed. | ||
* @function | ||
* @name Jasmine#addSpecFile | ||
* @param {string} filePath The path to the file to be loaded. | ||
*/ | ||
addSpecFile(filePath) { | ||
this.specFiles.push(filePath); | ||
} | ||
}; | ||
/** | ||
* Loads configuration from the specified object. | ||
* @param {Configuration} config | ||
*/ | ||
Jasmine.prototype.loadConfig = function(config) { | ||
/** | ||
* @interface Configuration | ||
* Adds a helper file to the list that will be loaded when the suite is executed. | ||
* @function | ||
* @name Jasmine#addHelperFile | ||
* @param {string} filePath The path to the file to be loaded. | ||
*/ | ||
const envConfig = {...config.env}; | ||
addHelperFile(filePath) { | ||
this.helperFiles.push(filePath); | ||
} | ||
/** | ||
* The directory that spec files are contained in, relative to the project | ||
* base directory. | ||
* @name Configuration#spec_dir | ||
* @type string | undefined | ||
* Add a custom reporter to the Jasmine environment. | ||
* @function | ||
* @name Jasmine#addReporter | ||
* @param {Reporter} reporter The reporter to add | ||
* @see custom_reporter | ||
*/ | ||
this.specDir = config.spec_dir || this.specDir; | ||
addReporter(reporter) { | ||
this.env.addReporter(reporter); | ||
this.reportersCount++; | ||
} | ||
/** | ||
* Whether to fail specs that contain no expectations. | ||
* @name Configuration#failSpecWithNoExpectations | ||
* @type boolean | undefined | ||
* @default false | ||
* Clears all registered reporters. | ||
* @function | ||
* @name Jasmine#clearReporters | ||
*/ | ||
if (config.failSpecWithNoExpectations !== undefined) { | ||
envConfig.failSpecWithNoExpectations = config.failSpecWithNoExpectations; | ||
clearReporters() { | ||
this.env.clearReporters(); | ||
this.reportersCount = 0; | ||
} | ||
/** | ||
* Whether to stop each spec on the first expectation failure. | ||
* @name Configuration#stopSpecOnExpectationFailure | ||
* @type boolean | undefined | ||
* @default false | ||
* Provide a fallback reporter if no other reporters have been specified. | ||
* @function | ||
* @name Jasmine#provideFallbackReporter | ||
* @param reporter The fallback reporter | ||
* @see custom_reporter | ||
*/ | ||
if (config.stopSpecOnExpectationFailure !== undefined) { | ||
envConfig.stopSpecOnExpectationFailure = config.stopSpecOnExpectationFailure; | ||
provideFallbackReporter(reporter) { | ||
this.env.provideFallbackReporter(reporter); | ||
} | ||
/** | ||
* Whether to stop suite execution on the first spec failure. | ||
* @name Configuration#stopOnSpecFailure | ||
* @type boolean | undefined | ||
* @default false | ||
* Configures the default reporter that is installed if no other reporter is | ||
* specified. | ||
* @param {ConsoleReporterOptions} options | ||
*/ | ||
if (config.stopOnSpecFailure !== undefined) { | ||
envConfig.stopOnSpecFailure = config.stopOnSpecFailure; | ||
configureDefaultReporter(options) { | ||
options.print = options.print || function() { | ||
process.stdout.write(util.format.apply(this, arguments)); | ||
}; | ||
options.showColors = options.hasOwnProperty('showColors') ? options.showColors : true; | ||
this.reporter.setOptions(options); | ||
this.defaultReporterConfigured = true; | ||
} | ||
/** | ||
* Whether to run specs in a random order. | ||
* @name Configuration#random | ||
* @type boolean | undefined | ||
* @default true | ||
* Add custom matchers for the current scope of specs. | ||
* | ||
* _Note:_ This is only callable from within a {@link beforeEach}, {@link it}, or {@link beforeAll}. | ||
* @function | ||
* @name Jasmine#addMatchers | ||
* @param {Object} matchers - Keys from this object will be the new matcher names. | ||
* @see custom_matcher | ||
*/ | ||
if (config.random !== undefined) { | ||
envConfig.random = config.random; | ||
addMatchers(matchers) { | ||
this.env.addMatchers(matchers); | ||
} | ||
if (config.verboseDeprecations !== undefined) { | ||
envConfig.verboseDeprecations = config.verboseDeprecations; | ||
async loadSpecs() { | ||
await this._loadFiles(this.specFiles); | ||
} | ||
async loadHelpers() { | ||
await this._loadFiles(this.helperFiles); | ||
} | ||
async _loadFiles(files) { | ||
for (const file of files) { | ||
await this.loader.load(file); | ||
} | ||
} | ||
async loadRequires() { | ||
await this._loadFiles(this.requires); | ||
} | ||
/** | ||
* Specifies how to load files with names ending in .js. Valid values are | ||
* "require" and "import". "import" should be safe in all cases, and is | ||
* required if your project contains ES modules with filenames ending in .js. | ||
* @name Configuration#jsLoader | ||
* @type string | undefined | ||
* @default "require" | ||
* Loads configuration from the specified file. The file can be a JSON file or | ||
* any JS file that's loadable via require and provides a Jasmine config | ||
* as its default export. | ||
* @param {string} [configFilePath=spec/support/jasmine.json] | ||
* @return Promise | ||
*/ | ||
if (config.jsLoader === 'import') { | ||
checkForJsFileImportSupport(); | ||
this._alwaysImport = true; | ||
} else if (config.jsLoader === 'require' || config.jsLoader === undefined) { | ||
this._alwaysImport = false; | ||
} else { | ||
throw new Error(`"${config.jsLoader}" is not a valid value for the ` + | ||
'jsLoader configuration property. Valid values are "import", ' + | ||
'"require", and undefined.'); | ||
async loadConfigFile(configFilePath) { | ||
if (configFilePath) { | ||
await this.loadSpecificConfigFile_(configFilePath); | ||
} else { | ||
for (const ext of ['json', 'js']) { | ||
try { | ||
await this.loadSpecificConfigFile_(`spec/support/jasmine.${ext}`); | ||
} catch (e) { | ||
if (e.code !== 'MODULE_NOT_FOUND' && e.code !== 'ERR_MODULE_NOT_FOUND') { | ||
throw e; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
if (Object.keys(envConfig).length > 0) { | ||
this.env.configure(envConfig); | ||
async loadSpecificConfigFile_(relativePath) { | ||
const absolutePath = path.resolve(this.projectBaseDir, relativePath); | ||
const config = await this.loader.load(absolutePath); | ||
this.loadConfig(config); | ||
} | ||
/** | ||
* An array of helper file paths or {@link https://github.com/isaacs/node-glob#glob-primer|globs} | ||
* that match helper files. Each path or glob will be evaluated relative to | ||
* the spec directory. Helpers are loaded before specs. | ||
* @name Configuration#helpers | ||
* @type string[] | undefined | ||
* Loads configuration from the specified object. | ||
* @param {Configuration} config | ||
*/ | ||
if(config.helpers) { | ||
this.addMatchingHelperFiles(config.helpers); | ||
loadConfig(config) { | ||
/** | ||
* @interface Configuration | ||
*/ | ||
const envConfig = {...config.env}; | ||
/** | ||
* The directory that spec files are contained in, relative to the project | ||
* base directory. | ||
* @name Configuration#spec_dir | ||
* @type string | undefined | ||
*/ | ||
this.specDir = config.spec_dir || this.specDir; | ||
this.validatePath_(this.specDir); | ||
/** | ||
* Whether to fail specs that contain no expectations. | ||
* @name Configuration#failSpecWithNoExpectations | ||
* @type boolean | undefined | ||
* @default false | ||
*/ | ||
if (config.failSpecWithNoExpectations !== undefined) { | ||
envConfig.failSpecWithNoExpectations = config.failSpecWithNoExpectations; | ||
} | ||
/** | ||
* Whether to stop each spec on the first expectation failure. | ||
* @name Configuration#stopSpecOnExpectationFailure | ||
* @type boolean | undefined | ||
* @default false | ||
*/ | ||
if (config.stopSpecOnExpectationFailure !== undefined) { | ||
envConfig.stopSpecOnExpectationFailure = config.stopSpecOnExpectationFailure; | ||
} | ||
/** | ||
* Whether to stop suite execution on the first spec failure. | ||
* @name Configuration#stopOnSpecFailure | ||
* @type boolean | undefined | ||
* @default false | ||
*/ | ||
if (config.stopOnSpecFailure !== undefined) { | ||
envConfig.stopOnSpecFailure = config.stopOnSpecFailure; | ||
} | ||
/** | ||
* Whether the default reporter should list pending specs even if there are | ||
* failures. | ||
* @name Configuration#alwaysListPendingSpecs | ||
* @type boolean | undefined | ||
* @default true | ||
*/ | ||
if (config.alwaysListPendingSpecs !== undefined) { | ||
this.alwaysListPendingSpecs(config.alwaysListPendingSpecs); | ||
} | ||
/** | ||
* Whether to run specs in a random order. | ||
* @name Configuration#random | ||
* @type boolean | undefined | ||
* @default true | ||
*/ | ||
if (config.random !== undefined) { | ||
envConfig.random = config.random; | ||
} | ||
if (config.verboseDeprecations !== undefined) { | ||
envConfig.verboseDeprecations = config.verboseDeprecations; | ||
} | ||
/** | ||
* Specifies how to load files with names ending in .js. Valid values are | ||
* "require" and "import". "import" should be safe in all cases, and is | ||
* required if your project contains ES modules with filenames ending in .js. | ||
* @name Configuration#jsLoader | ||
* @type string | undefined | ||
* @default "require" | ||
*/ | ||
if (config.jsLoader === 'import' || config.jsLoader === undefined) { | ||
this.loader.alwaysImport = true; | ||
} else if (config.jsLoader === 'require') { | ||
this.loader.alwaysImport = false; | ||
} else { | ||
throw new Error(`"${config.jsLoader}" is not a valid value for the ` + | ||
'jsLoader configuration property. Valid values are "import", ' + | ||
'"require", and undefined.'); | ||
} | ||
if (Object.keys(envConfig).length > 0) { | ||
this.env.configure(envConfig); | ||
} | ||
/** | ||
* An array of helper file paths or {@link https://github.com/isaacs/node-glob#glob-primer|globs} | ||
* that match helper files. Each path or glob will be evaluated relative to | ||
* the spec directory. Helpers are loaded before specs. | ||
* @name Configuration#helpers | ||
* @type string[] | undefined | ||
*/ | ||
if(config.helpers) { | ||
this.addMatchingHelperFiles(config.helpers); | ||
} | ||
/** | ||
* An array of module names to load via require() at the start of execution. | ||
* @name Configuration#requires | ||
* @type string[] | undefined | ||
*/ | ||
if(config.requires) { | ||
this.addRequires(config.requires); | ||
} | ||
/** | ||
* An array of spec file paths or {@link https://github.com/isaacs/node-glob#glob-primer|globs} | ||
* that match helper files. Each path or glob will be evaluated relative to | ||
* the spec directory. | ||
* @name Configuration#spec_files | ||
* @type string[] | undefined | ||
*/ | ||
if(config.spec_files) { | ||
this.addMatchingSpecFiles(config.spec_files); | ||
} | ||
/** | ||
* An array of reporters. Each object in the array will be passed to | ||
* {@link Jasmine#addReporter|addReporter}. | ||
* | ||
* This provides a middle ground between the --reporter= CLI option and full | ||
* programmatic usage. Note that because reporters are objects with methods, | ||
* this option can only be used in JavaScript config files | ||
* (e.g `spec/support/jasmine.js`), not JSON. | ||
* @name Configuration#reporters | ||
* @type Reporter[] | undefined | ||
* @see custom_reporter | ||
*/ | ||
if (config.reporters) { | ||
for (const r of config.reporters) { | ||
this.addReporter(r); | ||
} | ||
} | ||
} | ||
addRequires(requires) { | ||
const jasmineRunner = this; | ||
requires.forEach(function(r) { | ||
jasmineRunner.requires.push(r); | ||
}); | ||
} | ||
/** | ||
* An array of module names to load via require() at the start of execution. | ||
* @name Configuration#requires | ||
* @type string[] | undefined | ||
* Sets whether to cause specs to only have one expectation failure. | ||
* @function | ||
* @name Jasmine#stopSpecOnExpectationFailure | ||
* @param {boolean} value Whether to cause specs to only have one expectation | ||
* failure | ||
*/ | ||
if(config.requires) { | ||
this.addRequires(config.requires); | ||
stopSpecOnExpectationFailure(value) { | ||
this.env.configure({stopSpecOnExpectationFailure: value}); | ||
} | ||
/** | ||
* An array of spec file paths or {@link https://github.com/isaacs/node-glob#glob-primer|globs} | ||
* that match helper files. Each path or glob will be evaluated relative to | ||
* the spec directory. | ||
* @name Configuration#spec_files | ||
* @type string[] | undefined | ||
* Sets whether to stop execution of the suite after the first spec failure. | ||
* @function | ||
* @name Jasmine#stopOnSpecFailure | ||
* @param {boolean} value Whether to stop execution of the suite after the | ||
* first spec failure | ||
*/ | ||
if(config.spec_files) { | ||
this.addMatchingSpecFiles(config.spec_files); | ||
stopOnSpecFailure(value) { | ||
this.env.configure({stopOnSpecFailure: value}); | ||
} | ||
}; | ||
async flushOutput() { | ||
// Ensure that all data has been written to stdout and stderr, | ||
// then exit with an appropriate status code. Otherwise, we | ||
// might exit before all previous writes have actually been | ||
// written when Jasmine is piped to another process that isn't | ||
// reading quickly enough. | ||
var streams = [process.stdout, process.stderr]; | ||
var promises = streams.map(stream => { | ||
return new Promise(resolve => stream.write('', null, resolve)); | ||
}); | ||
return Promise.all(promises); | ||
} | ||
/** | ||
* Runs the test suite. | ||
* | ||
* _Note_: Set {@link Jasmine#exitOnCompletion|exitOnCompletion} to false if you | ||
* intend to use the returned promise. Otherwise, the Node process will | ||
* ordinarily exit before the promise is settled. | ||
* @param {Array.<string>} [files] Spec files to run instead of the previously | ||
* configured set | ||
* @param {string} [filterString] Regex used to filter specs. If specified, only | ||
* specs with matching full names will be run. | ||
* @return {Promise<JasmineDoneInfo>} Promise that is resolved when the suite completes. | ||
*/ | ||
async execute(files, filterString) { | ||
await this.loadRequires(); | ||
await this.loadHelpers(); | ||
if (!this.defaultReporterConfigured) { | ||
this.configureDefaultReporter({ | ||
showColors: this.showingColors, | ||
alwaysListPendingSpecs: this.alwaysListPendingSpecs_ | ||
}); | ||
} | ||
if (filterString) { | ||
const specFilter = new ConsoleSpecFilter({ | ||
filterString: filterString | ||
}); | ||
this.env.configure({specFilter: function(spec) { | ||
return specFilter.matches(spec.getFullName()); | ||
}}); | ||
} | ||
if (files && files.length > 0) { | ||
this.specDir = ''; | ||
this.specFiles = []; | ||
this.addMatchingSpecFiles(files); | ||
} | ||
await this.loadSpecs(); | ||
const prematureExitHandler = new ExitHandler(() => this.exit(4)); | ||
prematureExitHandler.install(); | ||
const overallResult = await this.env.execute(); | ||
await this.flushOutput(); | ||
prematureExitHandler.uninstall(); | ||
if (this.exitOnCompletion) { | ||
this.exit(exitCodeForStatus(overallResult.overallStatus)); | ||
} | ||
return overallResult; | ||
} | ||
validatePath_(path) { | ||
if (this.isWindows_ && path.includes('\\')) { | ||
const fixed = path.replace(/\\/g, '/'); | ||
console.warn('Backslashes in ' + | ||
'file paths behave inconsistently between platforms and might not be ' + | ||
'treated as directory separators in a future version. Consider ' + | ||
`changing ${path} to ${fixed}.`); | ||
} | ||
} | ||
} | ||
/** | ||
@@ -385,44 +543,8 @@ * Adds files that match the specified patterns to the list of spec files. | ||
// Deprecated synonyms for the above. These are confusingly named (addSpecFiles | ||
// doesn't just do N of what addSpecFile does) but they've been around a long | ||
// time and there might be quite a bit of code that uses them. | ||
/** | ||
* Synonym for {@link Jasmine#addMatchingSpecFiles} | ||
* @function | ||
* @name Jasmine#addSpecFiles | ||
* @deprecated Use {@link Jasmine#addMatchingSpecFiles|addMatchingSpecFiles}, | ||
* {@link Jasmine#loadConfig|loadConfig}, or {@link Jasmine#loadConfigFile|loadConfigFile} | ||
* instead. | ||
*/ | ||
Jasmine.prototype.addSpecFiles = function(globs) { | ||
this.env.deprecated('jasmine#addSpecFiles is deprecated. Use ' + | ||
'jasmine#addMatchingSpecFiles instead.'); | ||
this.addMatchingSpecFiles(globs); | ||
}; | ||
/** | ||
* Synonym for {@link Jasmine#addMatchingHelperFiles} | ||
* @name Jasmine#addHelperFiles | ||
* @function | ||
* @deprecated Use {@link Jasmine#addMatchingHelperFiles|addMatchingHelperFiles}, | ||
* {@link Jasmine#loadConfig|loadConfig}, or {@link Jasmine#loadConfigFile|loadConfigFile} | ||
* instead. | ||
*/ | ||
Jasmine.prototype.addHelperFiles = function(globs) { | ||
this.env.deprecated('jasmine#addHelperFiles is deprecated. Use ' + | ||
'jasmine#addMatchingHelperFiles instead.'); | ||
this.addMatchingHelperFiles(globs); | ||
}; | ||
Jasmine.prototype.addRequires = function(requires) { | ||
const jasmineRunner = this; | ||
requires.forEach(function(r) { | ||
jasmineRunner.requires.push(r); | ||
}); | ||
}; | ||
function addFiles(kind) { | ||
return function (files) { | ||
for (const f of files) { | ||
this.validatePath_(f); | ||
} | ||
const jasmineRunner = this; | ||
@@ -464,141 +586,17 @@ const fileArr = this[kind]; | ||
/** | ||
* Registers a callback that will be called when execution finishes. | ||
* | ||
* _Note_: Only one callback can be registered. The callback will be called | ||
* after the suite has completed and the results have been finalized, but not | ||
* necessarily before all of Jasmine's cleanup has finished. Calling this | ||
* function will also prevent Jasmine from exiting the Node process at the end | ||
* of suite execution. | ||
* | ||
* @deprecated Set {@link Jasmine#exitOnCompletion|exitOnCompletion} to false | ||
* and use the promise returned from {@link Jasmine#execute|execute} instead. | ||
* @param {function} onCompleteCallback | ||
*/ | ||
Jasmine.prototype.onComplete = function(onCompleteCallback) { | ||
this.env.deprecated( | ||
'Jasmine#onComplete is deprecated. Instead of calling onComplete, set ' + | ||
"the Jasmine instance's exitOnCompletion property to false and use the " + | ||
'promise returned from the execute method.' | ||
); | ||
this.completionReporter.onComplete(onCompleteCallback); | ||
}; | ||
/** | ||
* Sets whether to cause specs to only have one expectation failure. | ||
* @function | ||
* @name Jasmine#stopSpecOnExpectationFailure | ||
* @param {boolean} value Whether to cause specs to only have one expectation | ||
* failure | ||
*/ | ||
Jasmine.prototype.stopSpecOnExpectationFailure = function(value) { | ||
this.env.configure({stopSpecOnExpectationFailure: value}); | ||
}; | ||
/** | ||
* Sets whether to stop execution of the suite after the first spec failure. | ||
* @function | ||
* @name Jasmine#stopOnSpecFailure | ||
* @param {boolean} value Whether to stop execution of the suite after the | ||
* first spec failure | ||
*/ | ||
Jasmine.prototype.stopOnSpecFailure = function(value) { | ||
this.env.configure({stopOnSpecFailure: value}); | ||
}; | ||
Jasmine.prototype.exitCodeCompletion = function(passed) { | ||
// Ensure that all data has been written to stdout and stderr, | ||
// then exit with an appropriate status code. Otherwise, we | ||
// might exit before all previous writes have actually been | ||
// written when Jasmine is piped to another process that isn't | ||
// reading quickly enough. | ||
const jasmineRunner = this; | ||
const streams = [process.stdout, process.stderr]; | ||
let writesToWait = streams.length; | ||
streams.forEach(function(stream) { | ||
stream.write('', null, exitIfAllStreamsCompleted); | ||
}); | ||
function exitIfAllStreamsCompleted() { | ||
writesToWait--; | ||
if (writesToWait === 0 && jasmineRunner.exitOnCompletion) { | ||
if(passed) { | ||
jasmineRunner.exit(0); | ||
} | ||
else { | ||
jasmineRunner.exit(1); | ||
} | ||
} | ||
function exitCodeForStatus(status) { | ||
switch (status) { | ||
case 'passed': | ||
return 0; | ||
case 'incomplete': | ||
return 2; | ||
case 'failed': | ||
return 3; | ||
default: | ||
console.error(`Unrecognized overall status: ${status}`); | ||
return 1; | ||
} | ||
}; | ||
const checkExit = function(jasmineRunner) { | ||
return function() { | ||
if (!jasmineRunner.completionReporter.isComplete()) { | ||
process.exitCode = 4; | ||
} | ||
}; | ||
}; | ||
function checkForJsFileImportSupport() { | ||
const v = process.versions.node | ||
.split('.') | ||
.map(el => parseInt(el, 10)); | ||
if (v[0] < 12 || (v[0] === 12 && v[1] < 17)) { | ||
console.warn('Warning: jsLoader: "import" may not work reliably on Node ' + | ||
'versions before 12.17.'); | ||
} | ||
} | ||
/** | ||
* Runs the test suite. | ||
* | ||
* _Note_: Set {@link Jasmine#exitOnCompletion|exitOnCompletion} to false if you | ||
* intend to use the returned promise. Otherwise, the Node process will | ||
* ordinarily exit before the promise is settled. | ||
* @param {Array.<string>} [files] Spec files to run instead of the previously | ||
* configured set | ||
* @param {string} [filterString] Regex used to filter specs. If specified, only | ||
* specs with matching full names will be run. | ||
* @return {Promise<JasmineDoneInfo>} Promise that is resolved when the suite completes. | ||
*/ | ||
Jasmine.prototype.execute = async function(files, filterString) { | ||
this.completionReporter.exitHandler = this.checkExit; | ||
this.loadRequires(); | ||
await this.loadHelpers(); | ||
if (!this.defaultReporterConfigured) { | ||
this.configureDefaultReporter({ showColors: this.showingColors }); | ||
} | ||
if (filterString) { | ||
const specFilter = new ConsoleSpecFilter({ | ||
filterString: filterString | ||
}); | ||
this.env.configure({specFilter: function(spec) { | ||
return specFilter.matches(spec.getFullName()); | ||
}}); | ||
} | ||
if (files && files.length > 0) { | ||
this.specDir = ''; | ||
this.specFiles = []; | ||
this.addMatchingSpecFiles(files); | ||
} | ||
await this.loadSpecs(); | ||
if (!this.completionReporterInstalled_) { | ||
this.addReporter(this.completionReporter); | ||
this.completionReporterInstalled_ = true; | ||
} | ||
let overallResult; | ||
this.addReporter({ | ||
jasmineDone: r => overallResult = r | ||
}); | ||
await new Promise(resolve => { | ||
this.env.execute(null, resolve); | ||
}); | ||
return overallResult; | ||
}; | ||
module.exports = Jasmine; | ||
module.exports.ConsoleReporter = require('./reporters/console_reporter'); |
@@ -1,31 +0,58 @@ | ||
module.exports = Loader; | ||
const path = require('path'); | ||
function Loader(options) { | ||
options = options || {}; | ||
this.require_ = options.requireShim || requireShim; | ||
this.import_ = options.importShim || importShim; | ||
} | ||
class Loader { | ||
constructor(options) { | ||
options = options || {}; | ||
this.require_ = options.requireShim || requireShim; | ||
this.import_ = options.importShim || importShim; | ||
this.resolvePath_ = options.resolvePath || path.resolve.bind(path); | ||
this.alwaysImport = true; | ||
} | ||
Loader.prototype.load = function(path, alwaysImport) { | ||
if (alwaysImport || path.endsWith('.mjs')) { | ||
// The ES module spec requires import paths to be valid URLs. As of v14, | ||
// Node enforces this on Windows but not on other OSes. | ||
const url = `file://${path}`; | ||
return this.import_(url).catch(function(e) { | ||
return Promise.reject(fixupImportException(e, path)); | ||
}); | ||
} else { | ||
return new Promise(resolve => { | ||
this.require_(path); | ||
resolve(); | ||
}); | ||
load(modulePath) { | ||
if ((this.alwaysImport && !modulePath.endsWith('.json')) || modulePath.endsWith('.mjs')) { | ||
let importSpecifier; | ||
if (modulePath.indexOf(path.sep) === -1 && modulePath.indexOf('/') === -1) { | ||
importSpecifier = modulePath; | ||
} else { | ||
// The ES module spec requires import paths to be valid URLs. As of v14, | ||
// Node enforces this on Windows but not on other OSes. On OS X, import | ||
// paths that are URLs must not contain parent directory references. | ||
importSpecifier = `file://${this.resolvePath_(modulePath)}`; | ||
} | ||
return this.import_(importSpecifier) | ||
.then( | ||
mod => mod.default, | ||
e => { | ||
if (e.code === 'ERR_UNKNOWN_FILE_EXTENSION') { | ||
// Extension isn't supported by import, e.g. .jsx. Fall back to | ||
// require(). This could lead to confusing error messages if someone | ||
// tries to use ES module syntax without transpiling in a file with | ||
// an unsupported extension, but it shouldn't break anything and it | ||
// should work well in the normal case where the file is loadable | ||
// as a CommonJS module, either directly or with the help of a | ||
// loader like `@babel/register`. | ||
return this.require_(modulePath); | ||
} else { | ||
return Promise.reject(fixupImportException(e, modulePath)); | ||
} | ||
} | ||
); | ||
} else { | ||
return new Promise(resolve => { | ||
const result = this.require_(modulePath); | ||
resolve(result); | ||
}); | ||
} | ||
} | ||
}; | ||
} | ||
function requireShim(path) { | ||
require(path); | ||
function requireShim(modulePath) { | ||
return require(modulePath); | ||
} | ||
function importShim(path) { | ||
return import(path); | ||
function importShim(modulePath) { | ||
return import(modulePath); | ||
} | ||
@@ -96,3 +123,3 @@ | ||
// paths (c:\path\to\file.js) or URLs (file:///c:/path/to/file.js). | ||
if (!(e instanceof SyntaxError)) { | ||
@@ -127,1 +154,3 @@ return e; | ||
} | ||
module.exports = Loader; |
@@ -15,3 +15,2 @@ module.exports = exports = ConsoleReporter; | ||
showColors = false, | ||
jasmineCorePath = null, | ||
specCount, | ||
@@ -22,2 +21,3 @@ executableSpecCount, | ||
pendingSpecs = [], | ||
alwaysListPendingSpecs = true, | ||
ansi = { | ||
@@ -30,3 +30,3 @@ green: '\x1B[32m', | ||
failedSuites = [], | ||
stackFilter = defaultStackFilter; | ||
stackFilter = stack => stack; | ||
@@ -54,5 +54,2 @@ /** | ||
showColors = options.showColors || false; | ||
if (options.jasmineCorePath) { | ||
jasmineCorePath = options.jasmineCorePath; | ||
} | ||
if (options.stackFilter) { | ||
@@ -71,2 +68,12 @@ stackFilter = options.stackFilter; | ||
} | ||
/** | ||
* Whether to list pending specs even if there are failures. | ||
* @name ConsoleReporterOptions#alwaysListPendingSpecs | ||
* @type Boolean|undefined | ||
* @default true | ||
*/ | ||
if (options.alwaysListPendingSpecs !== undefined) { | ||
alwaysListPendingSpecs = options.alwaysListPendingSpecs; | ||
} | ||
}; | ||
@@ -87,2 +94,6 @@ | ||
this.jasmineDone = function(result) { | ||
if (result.failedExpectations) { | ||
failureCount += result.failedExpectations.length; | ||
} | ||
printNewline(); | ||
@@ -105,8 +116,10 @@ printNewline(); | ||
if (pendingSpecs.length > 0) { | ||
print("Pending:"); | ||
if (alwaysListPendingSpecs || result.overallStatus === 'passed') { | ||
if (pendingSpecs.length > 0) { | ||
print("Pending:"); | ||
} | ||
for (let i = 0; i < pendingSpecs.length; i++) { | ||
pendingSpecDetails(pendingSpecs[i], i + 1); | ||
} | ||
} | ||
for(i = 0; i < pendingSpecs.length; i++) { | ||
pendingSpecDetails(pendingSpecs[i], i + 1); | ||
} | ||
@@ -215,13 +228,2 @@ if(specCount > 0) { | ||
function defaultStackFilter(stack) { | ||
if (!stack) { | ||
return ''; | ||
} | ||
const filteredStack = stack.split('\n').filter(function(stackLine) { | ||
return stackLine.indexOf(jasmineCorePath) === -1; | ||
}).join('\n'); | ||
return filteredStack; | ||
} | ||
function specFailureDetails(result, failedSpecNumber) { | ||
@@ -233,8 +235,8 @@ printNewline(); | ||
if (result.trace) { | ||
if (result.debugLogs) { | ||
printNewline(); | ||
print(indent('Trace:', 2)); | ||
print(indent('Debug logs:', 2)); | ||
printNewline(); | ||
for (const entry of result.trace) { | ||
for (const entry of result.debugLogs) { | ||
print(indent(`${entry.timestamp}ms: ${entry.message}`, 4)); | ||
@@ -241,0 +243,0 @@ printNewline(); |
@@ -13,3 +13,3 @@ { | ||
"license": "MIT", | ||
"version": "3.99.0", | ||
"version": "4.6.0", | ||
"repository": { | ||
@@ -23,2 +23,3 @@ "type": "git", | ||
}, | ||
"exports": "./lib/jasmine.js", | ||
"files": [ | ||
@@ -33,3 +34,3 @@ "bin", | ||
"glob": "^7.1.6", | ||
"jasmine-core": "~3.99.0" | ||
"jasmine-core": "^4.6.0" | ||
}, | ||
@@ -40,4 +41,2 @@ "bin": "./bin/jasmine.js", | ||
"eslint": "^6.8.0", | ||
"grunt": "^1.0.4", | ||
"grunt-cli": "^1.3.2", | ||
"shelljs": "^0.8.3", | ||
@@ -44,0 +43,0 @@ "slash": "^3.0.0", |
@@ -17,87 +17,40 @@ [![Build Status](https://circleci.com/gh/jasmine/jasmine-npm.svg?style=shield)](https://circleci.com/gh/jasmine/jasmine-npm) | ||
https://jasmine.github.io/edge/node.html | ||
https://jasmine.github.io/setup/nodejs.html | ||
## Installation | ||
## Quick Start | ||
Installation: | ||
```sh | ||
# Local installation: | ||
npm install --save-dev jasmine | ||
# Global installation | ||
npm install -g jasmine | ||
``` | ||
## Initializing | ||
To initialize a project for Jasmine: | ||
To initialize a project for Jasmine | ||
```sh | ||
npx jasmine init | ||
```` | ||
`jasmine init` | ||
To seed your project with some examples: | ||
To initialize a project for Jasmine when being installed locally | ||
```sh | ||
npx jasmine examples | ||
```` | ||
`node_modules/.bin/jasmine init` | ||
To run your test suite: | ||
or | ||
```sh | ||
npx jasmine | ||
```` | ||
`npx jasmine init` | ||
## ES and CommonJS module compatibility | ||
To seed your project with some examples | ||
Jasmine is compatible with both ES modules and CommonJS modules. See the | ||
[setup guide](https://jasmine.github.io/setup/nodejs.html) for more information. | ||
`jasmine examples` | ||
## Usage | ||
## Node version compatibility | ||
To run your test suite | ||
Jasmine supports Node 18, 16, 14, and 12.17-12.22. | ||
`jasmine` | ||
## Configuration | ||
Customize `spec/support/jasmine.json` to enumerate the source and spec files you would like the Jasmine runner to include. | ||
You may use dir glob strings. | ||
More information on the format of `jasmine.json` can be found in [the documentation](http://jasmine.github.io/edge/node.html#section-Configuration) | ||
Alternatively, you may specify the path to your `jasmine.json` by setting an environment variable or an option: | ||
```shell | ||
jasmine JASMINE_CONFIG_PATH=relative/path/to/your/jasmine.json | ||
jasmine --config=relative/path/to/your/jasmine.json | ||
``` | ||
## Using ES modules | ||
If the name of a spec file or helper file ends in `.mjs`, Jasmine will load it | ||
as an [ES module](https://nodejs.org/docs/latest-v13.x/api/esm.html) rather | ||
than a CommonJS module. This allows the spec file or helper to import other | ||
ES modules. No extra configuration is required. | ||
You can also use ES modules with names ending in `.js` by adding | ||
`"jsLoader": "import"` to `jasmine.json`. This should work for CommonJS modules | ||
as well as ES modules. We expect to make it the default in a future release. | ||
Please [log an issue](https://github.com/jasmine/jasmine-npm/issues) if you have | ||
code that doesn't load correctly with `"jsLoader": "import"`. | ||
# Filtering specs | ||
Execute only those specs which filename match given glob: | ||
```shell | ||
jasmine "spec/**/critical/*Spec.js" | ||
``` | ||
Or a single file: | ||
```shell | ||
jasmine spec/currentSpec.js | ||
``` | ||
Or execute only those specs which name matches a particular regex: | ||
```shell | ||
jasmine --filter "adapter21*" | ||
``` | ||
(where the *name* of a spec is the first parameter passed to `describe()`) | ||
## Support | ||
@@ -104,0 +57,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
4
1265
4
48285
11
68
+ Addedjasmine-core@4.6.1(transitive)
- Removedjasmine-core@3.99.1(transitive)
Updatedjasmine-core@^4.6.0