Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Socket
Sign inDemoInstall

jasmine

Package Overview
Dependencies
Maintainers
4
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jasmine - npm Package Compare versions

Comparing version 3.99.0 to 4.6.0

lib/exit_handler.js

17

bin/jasmine.js
#!/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));

139

lib/command.js

@@ -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 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc