pax_global_header 0000666 0000000 0000000 00000000064 15240143636 0014516 g ustar 00root root 0000000 0000000 52 comment=3c2955c9535d4468e07d37f8ad5e38cf870cf924
jasmine-jasmine-npm-3c2955c/ 0000775 0000000 0000000 00000000000 15240143636 0015717 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/.circleci/ 0000775 0000000 0000000 00000000000 15240143636 0017552 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/.circleci/config.yml 0000664 0000000 0000000 00000005760 15240143636 0021552 0 ustar 00root root 0000000 0000000 # Run tests against supported Node versions
version: 2.1
orbs:
win: circleci/windows@5.0.0
node: circleci/node@5.0.2
executors:
node26:
docker:
- image: cimg/node:26.0.0
working_directory: ~/workspace
node24:
docker:
- image: cimg/node:24.0.0
working_directory: ~/workspace
node22:
docker:
- image: cimg/node:22.0.0
working_directory: ~/workspace
node20:
docker:
- image: cimg/node:20.0.0
working_directory: ~/workspace
jobs:
test:
parameters:
executor:
type: executor
executor: << parameters.executor >>
steps:
- checkout
- run:
name: Update npm or delete .npmrc
command: |
# This project's .npmrc requires NPM 12.. Upgrade NPM if possible,
# or delete .npmrc
#
# Note: this check may cause spurious warnings about invalid npm
# settings. npm 11 validates .npmrc even when you just run --version.
if [ $(npm --version | sed 's/\..*//') -lt 12 ]; then
if [ $(node --version | sed -e 's/\..*//' -e 's/^v//') -ge 26 ]; then
npm install -g npm@latest
else
# We can't reliably install NPM 12 on anything before Node 26:
# * NPM 12 won't run on any Node 20 version, or on older 22 and
# 24 minors.
# * npm install -g fails on cimg/node:24.* due to permissions.
# Removing .npmrc theoretically leaves CI vulnerable to supply
# chain attacks, but CI produces no artifacts and has no access
# to credentials (except for the Saucelabs API key, and that's
# only provided to trusted invocations.)
rm .npmrc
fi
fi
- run:
name: Report Node and NPM versions
command: echo "Using Node $(node --version) and NPM $(npm --version)"
- run:
name: Install dependencies
command: npm install
- run:
name: Run tests
command: npm test
test_win:
executor:
name: win/default
shell: bash.exe
steps:
- checkout
- run:
name: Install Node.js
command: nvm install 20.0.0 && nvm use 20.0.0
- run:
name: Report Node and NPM versions
command: echo "Using Node $(node --version) and NPM $(npm --version)"
- run:
name: Install dependencies
command: npm install
- run:
name: Run tests
command: npm test
workflows:
version: 2
push: &push_workflow
jobs:
- test:
matrix:
parameters:
executor:
- node26
- node24
- node22
- node20
- test_win
cron:
<<: *push_workflow
triggers:
- schedule:
# Times are UTC.
cron: "0 10 * * *"
filters:
branches:
only:
- main
jasmine-jasmine-npm-3c2955c/.editorconfig 0000664 0000000 0000000 00000000173 15240143636 0020375 0 ustar 00root root 0000000 0000000 [*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
[*.{js, json, yml}]
indent_style = space
indent_size = 2
jasmine-jasmine-npm-3c2955c/.github/ 0000775 0000000 0000000 00000000000 15240143636 0017257 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/.github/CONTRIBUTING.md 0000664 0000000 0000000 00000004023 15240143636 0021507 0 ustar 00root root 0000000 0000000 # Contributing to Jasmine
## Bug reports
Bug reports are welcome, but please help us help you by:
* Searching for existing issues (including closed issues) that are similar to
yours
* Reading the [FAQ](https://jasmine.github.io/pages/faq.html)
* Providing enough information for someone else to to understand and reproduce
the problem. In most cases that includes a clear description of what you're
trying to do, the version of each Jasmine package that you're using, the Node
version, and a minimal but complete code sample that demonstrates the problem.
## Contributing documentation
We welcome efforts to improve Jasmine's documentation. The source code for the
documentation site is at .
## Contributing code
Contributions are welcome, but we don't say yes to every idea. We recommend
opening an issue to propose your idea before starting work, to reduce the risk
of getting a "no" at the pull request stage.
Don't have an idea of your own but want to help solve problems for other
people? That's great! Have a look at the list of
[issues tagged "help needed"](https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Ajasmine+sort%3Aupdated-desc).
### The nuts and bolts of preparing a pull request
Jasmine is mature software that's downloaded millions of times a week and
supported by a tiny group of people in their free time. Anything that breaks
things for existing users or makes Jasmine harder to maintain is a tough sell.
Before submitting a PR, please check that:
* You aren't introducing any breaking changes
* `npm test` succeeds: tests pass, there are no eslint or prettier errors,
and the exit status is 0
* Your change is well tested: you're reasonably confident that the tests will
fail if somebody breaks your new functionality in the future
* Your code matches the style of the surrounding code
We use Circle CI to test pull requests against a variety of operating systems
and Node versions. Please check back after submitting your PR and make sure
that the build succeeded.
jasmine-jasmine-npm-3c2955c/.gitignore 0000664 0000000 0000000 00000000223 15240143636 0017704 0 ustar 00root root 0000000 0000000 .idea/
lib-cov
lcov.info
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
*.sw?
pids
logs
results
build
.grunt
node_modules
package-lock.json
.DS_Store
jasmine-jasmine-npm-3c2955c/.npmrc 0000664 0000000 0000000 00000002353 15240143636 0017042 0 ustar 00root root 0000000 0000000 # If you're having problems running npm install, try using NPM 12.
#
# This file assumes NPM 12 or later. If you're using an older version, you
# may see various misbehavior dependiong on which version you're running and
# the current state of Jasmine's dependenies:
#
# * Later 11.x may fail with EALLOWGIT if any dependencies are set to git URLs
# * Later 11.x may fail to install during the first 14 days after a Jasmine
# release, because some required packages are too new.
# (min-release-age-exclude is mentioned in the NPM 11 docs but appearst to
# only be supported by NPM 12.)
# * Anything before 11.1.0 won't enforce min-release-age.
ignore-scripts=true
min-release-age=14
# Exclude Jasmine packages from the cooldown period. This is necessary because
# during and shortly after a release one Jasmine package may depend on very new
# versions of others.
# Requires at least NPM 12.
min-release-age-exclude[]=jasmine
min-release-age-exclude[]=jasmine-core
min-release-age-exclude[]=jasmine-browser-runner
min-release-age-exclude[]=@jasminejs/reporters
# At times, particularly leading up to a major release, we may depend on the
# curent unreleased source of other Jasmine packages. set allow-git=root when
# that's the case.
allow-git=root
jasmine-jasmine-npm-3c2955c/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000006241 15240143636 0020521 0 ustar 00root root 0000000 0000000 # Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at jasmine-maintainers@googlegroups.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
jasmine-jasmine-npm-3c2955c/LICENSE 0000664 0000000 0000000 00000002124 15240143636 0016723 0 ustar 00root root 0000000 0000000 Copyright (c) 2014-2019 Pivotal Labs
Copyright (c) 2014-2026 The Jasmine developers
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
jasmine-jasmine-npm-3c2955c/README.md 0000664 0000000 0000000 00000002640 15240143636 0017200 0 ustar 00root root 0000000 0000000 # The Jasmine Package
The `jasmine` package is a command line interface and supporting code for running
[Jasmine](https://github.com/jasmine/jasmine) specs under Node.
The core of jasmine lives at https://github.com/jasmine/jasmine and is `jasmine-core` in npm.
## Contents
This package allows you to run Jasmine specs for your Node.js code. The output will be displayed in your terminal by default.
## Documentation
https://jasmine.github.io/setup/nodejs.html
## Quick Start
Installation:
```sh
npm install --save-dev jasmine
```
To initialize a project for Jasmine:
```sh
npx jasmine init
````
To seed your project with some examples:
```sh
npx jasmine examples
````
To run your test suite:
```sh
npx jasmine
````
## ES and CommonJS module compatibility
Jasmine is compatible with both ES modules and CommonJS modules. See the
[setup guide](https://jasmine.github.io/setup/nodejs.html) for more information.
## Node version compatibility
Jasmine supports Node 20*, 22, 24, and 26.
\* Environments that are past end of life are supported on a best-effort basis.
They may be dropped in a future minor release of Jasmine if continued support
becomes impractical.
## Support
Documentation: [jasmine.github.io](https://jasmine.github.io)
Please file issues here at GitHub.
Copyright (c) 2014-2019 Pivotal Labs
Copyright (c) 2014-2026 The Jasmine developers
This software is licensed under the MIT License.
jasmine-jasmine-npm-3c2955c/RELEASE.md 0000664 0000000 0000000 00000002003 15240143636 0017314 0 ustar 00root root 0000000 0000000 # How to work on a Jasmine Release
## Prepare the release
When ready to release - specs are all green and the stories are done:
1. If this is a major or minor release, publish the corresponding release of
`jasmine-core` as described in that repo's `RELEASE.md`.
2. Create release notes using the Anchorman gem.
3. In `package.json`, update both the package version and the `jasmine-core`
dependency version. This package should depend on the same major and minor
version of `jasmine-core`. For instance, 4.1.1 should depend on
`"jasmine-core": "~4.1.0"`.
4. Commit and push.
5. Wait for Circle CI to go green again.
## Publish the NPM package
1. Create a tag for the version, e.g. `git tag v4.4.0`.
2. Push the tag: `git push --tags`
3. Publish the NPM package: `npm publish`.
### Publish the GitHub release
1. Visit the GitHub releases page and find the tag just published.
2. Paste in a link to the correct release notes for this release.
3. If it is a pre-release, mark it as such.
4. Publish the release.
jasmine-jasmine-npm-3c2955c/bin/ 0000775 0000000 0000000 00000000000 15240143636 0016467 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/bin/jasmine.js 0000775 0000000 0000000 00000001226 15240143636 0020457 0 ustar 00root root 0000000 0000000 #!/usr/bin/env node
const path = require('path');
const os = require('os');
const process = require('process');
const Command = require('../lib/command');
const Jasmine = require('../lib/jasmine');
const ParallelRunner = require("../lib/parallel_runner");
const examplesDir = path.join(path.dirname(require.resolve('jasmine-core')), 'jasmine-core', 'example', 'node_example');
const command = new Command(path.resolve(), examplesDir, {
Jasmine,
ParallelRunner,
print: console.log,
terminalColumns: process.stdout.columns,
platform: os.platform,
});
command.run(process.argv.slice(2))
.catch(e => {
console.error(e);
process.exit(1);
});
jasmine-jasmine-npm-3c2955c/bin/worker.js 0000664 0000000 0000000 00000000351 15240143636 0020335 0 ustar 00root root 0000000 0000000 const cluster = require('node:cluster');
const ParallelWorker = require('../lib/parallel_worker');
const Loader = require('../lib/loader');
new ParallelWorker({
loader: new Loader(),
process,
clusterWorker: cluster.worker
});
jasmine-jasmine-npm-3c2955c/eslint.config.mjs 0000664 0000000 0000000 00000002246 15240143636 0021200 0 ustar 00root root 0000000 0000000 import { defineConfig, globalIgnores } from "eslint/config";
import jasmine from 'eslint-plugin-jasmine';
import globals from 'globals';
export default defineConfig([globalIgnores([
"spec/fixtures/cjs-syntax-error/syntax_error.js",
"spec/fixtures/esm-importing-commonjs-syntax-error/syntax_error.js",
"spec/fixtures/js-loader-import/*.js",
"spec/fixtures/js-loader-default/*.js",
"spec/fixtures/esm-reporter-packagejson/customReporter.js",
]), {
languageOptions: {
globals: {
...globals.commonjs,
...globals.node,
Atomics: 'readonly',
SharedArrayBuffer: 'readonly',
expectAsync: 'readonly',
},
ecmaVersion: 2022,
sourceType: 'commonjs',
},
plugins: {
jasmine,
},
rules: {
"no-unused-vars": ["error", {
args: "none",
}],
eqeqeq: 'error',
"func-call-spacing": ["error", "never"],
"key-spacing": "error",
"no-tabs": "error",
"no-whitespace-before-property": "error",
semi: ["error", "always"],
"space-before-blocks": "error",
'no-var': 'error',
},
}]);
jasmine-jasmine-npm-3c2955c/lib/ 0000775 0000000 0000000 00000000000 15240143636 0016465 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/lib/command.js 0000664 0000000 0000000 00000032612 15240143636 0020445 0 ustar 00root root 0000000 0000000 const path = require('path');
const fs = require('fs');
const os = require('os');
const unWindows = require('./unWindows');
exports = module.exports = Command;
const subCommands = {
init: {
description: 'initialize jasmine',
action: initJasmine
},
examples: {
description: 'install examples',
action: installExamples
},
help: {
description: 'show help',
action: help,
alias: '-h'
},
version: {
description: 'show jasmine and jasmine-core versions',
action: version,
alias: '-v'
},
enumerate: {
description: 'enumerate suites and specs',
action: enumerate
}
};
function Command(projectBaseDir, examplesDir, deps) {
const {print, platform, terminalColumns, Jasmine, ParallelRunner} = deps;
const isWindows = platform() === 'win32';
this.projectBaseDir = isWindows ? unWindows(projectBaseDir) : projectBaseDir;
this.specDir = `${this.projectBaseDir}/spec`;
const command = this;
this.run = async function(args) {
setEnvironmentVariables(args);
let commandToRun;
Object.keys(subCommands).forEach(function(cmd) {
const commandObject = subCommands[cmd];
if (args.indexOf(cmd) >= 0) {
commandToRun = commandObject;
} else if (commandObject.alias && args.indexOf(commandObject.alias) >= 0) {
commandToRun = commandObject;
}
});
if (commandToRun) {
await commandToRun.action({
Jasmine,
projectBaseDir,
specDir: command.specDir,
examplesDir: examplesDir,
print,
terminalColumns
});
} else {
const options = parseOptions(args, isWindows);
if (options.usageErrors.length > 0) {
process.exitCode = 1;
for (const e of options.usageErrors) {
print(e);
}
print('');
help({print, terminalColumns});
} else {
await runJasmine(Jasmine, ParallelRunner, projectBaseDir, options);
}
}
};
}
function isFileArg(arg) {
return arg.indexOf('--') !== 0 && !isEnvironmentVariable(arg);
}
function parseOptions(argv, isWindows) {
let files = [];
let helpers = [];
let requires = [];
let unknownOptions = [];
let usageErrors = [];
let color = undefined;
let listNotApplicableSpecs = undefined;
let reporter;
let configPath;
let filterRegex;
let filterPath;
let failFast;
let random;
let seed;
let numWorkers = 1;
let verbose = false;
for (const arg of argv) {
if (arg === '--no-color') {
color = false;
} else if (arg === '--color') {
color = true;
} else if (arg === '--list-not-applicable') {
listNotApplicableSpecs = true;
} else if (arg.match("^--filter=")) {
filterRegex = arg.match("^--filter=(.*)")[1];
} else if (arg.match("^--filter-path=(.*)")) {
const json = arg.match("^--filter-path=(.*)")[1];
try {
filterPath = JSON.parse(json);
} catch {
usageErrors.push('Invalid filter path: ' + json);
}
if (!(filterPath instanceof Array)) {
usageErrors.push('Invalid filter path: ' + json);
}
} else if (arg.match("^--helper=")) {
helpers.push(arg.match("^--helper=(.*)")[1]);
} else if (arg.match("^--require=")) {
requires.push(arg.match("^--require=(.*)")[1]);
} else if (arg === '--fail-fast') {
failFast = true;
} else if (arg.match("^--random=")) {
random = arg.match("^--random=(.*)")[1] === 'true';
} else if (arg.match("^--seed=")) {
seed = arg.match("^--seed=(.*)")[1];
} else if (arg.match("^--config=")) {
configPath = arg.match("^--config=(.*)")[1];
} else if (arg.match("^--reporter=")) {
reporter = arg.match("^--reporter=(.*)")[1];
} else if (arg.match("^--parallel=(.*)")) {
const w = arg.match("^--parallel=(.*)")[1];
if (w === 'auto') {
// A reasonable default in most situations
numWorkers = os.cpus().length -1;
} else {
numWorkers = parseFloat(w);
if (isNaN(numWorkers) || numWorkers < 2 || numWorkers !== Math.floor(numWorkers)) {
usageErrors.push('Argument to --parallel= must be an integer greater than 1');
}
}
} else if (arg === '--verbose') {
verbose = true;
} else if (arg === '--') {
break;
} else if (isFileArg(arg)) {
files.push(isWindows ? unWindows(arg) : arg);
} else if (!isEnvironmentVariable(arg)) {
unknownOptions.push(arg);
}
}
if (numWorkers > 1 && filterPath) {
usageErrors.push('--filter-path is not supported in parallel mode.');
}
if (unknownOptions.length > 0) {
usageErrors.push('Unknown options: ' + unknownOptions.join(', '));
}
return {
color,
listNotApplicableSpecs,
configPath,
filterRegex,
filterPath,
failFast,
helpers,
requires,
reporter,
files,
random,
seed,
numWorkers,
verbose,
usageErrors
};
}
async function runJasmine(Jasmine, ParallelRunner, projectBaseDir, options) {
let runner;
if (options.numWorkers > 1) {
runner = new ParallelRunner({
projectBaseDir,
numWorkers: options.numWorkers
});
} else {
runner = new Jasmine({
projectBaseDir
});
}
runner.verbose(options.verbose);
await runner.loadConfigFile(options.configPath || process.env.JASMINE_CONFIG_PATH);
if (options.failFast !== undefined) {
runner.configureEnv({
stopSpecOnExpectationFailure: options.failFast,
stopOnSpecFailure: options.failFast
});
}
if (options.seed !== undefined) {
runner.seed(options.seed);
}
if (options.random !== undefined) {
runner.randomizeTests(options.random);
}
if (options.helpers !== undefined && options.helpers.length) {
runner.addMatchingHelperFiles(options.helpers);
}
if (options.requires !== undefined && options.requires.length) {
runner.addRequires(options.requires);
}
if (options.reporter !== undefined) {
await registerReporter(options.reporter, runner);
}
runner.configureDefaultReporter({
color: options.color,
listNotApplicableSpecs: options.listNotApplicableSpecs,
});
let filter;
if (options.filterRegex) {
filter = options.filterRegex;
} else if (options.filterPath) {
filter = {path: options.filterPath};
}
try {
await runner.execute(options.files, filter);
} catch (error) {
console.error(error);
process.exit(1);
}
}
async function registerReporter(reporterModuleName, runner) {
let Reporter;
try {
Reporter = await runner.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)');
}
runner.clearReporters();
runner.addReporter(reporter);
}
function resolveReporter(nameOrPath) {
if (nameOrPath.startsWith('./') || nameOrPath.startsWith('../')) {
return path.resolve(nameOrPath);
} else {
return nameOrPath;
}
}
function initJasmine(options) {
const print = options.print;
const destDir = path.join(options.specDir, 'support/');
makeDirStructure(destDir);
const destPath = path.join(destDir, 'jasmine.mjs');
if (fs.existsSync(destPath)) {
print('spec/support/jasmine.mjs already exists in your project.');
} else {
const contents = fs.readFileSync(
path.join(__dirname, '../lib/examples/jasmine.mjs'), 'utf-8');
fs.writeFileSync(destPath, contents);
}
}
function installExamples(options) {
const specDir = options.specDir;
const projectBaseDir = options.projectBaseDir;
const examplesDir = options.examplesDir;
makeDirStructure(path.join(specDir, 'support'));
makeDirStructure(path.join(specDir, 'jasmine_examples'));
makeDirStructure(path.join(specDir, 'helpers', 'jasmine_examples'));
makeDirStructure(path.join(projectBaseDir, 'lib', 'jasmine_examples'));
copyFiles(
path.join(examplesDir, 'spec', 'helpers', 'jasmine_examples'),
path.join(specDir, 'helpers', 'jasmine_examples'),
new RegExp(/[Hh]elper\.js/)
);
copyFiles(
path.join(examplesDir, 'lib', 'jasmine_examples'),
path.join(projectBaseDir, 'lib', 'jasmine_examples'),
new RegExp(/\.js/)
);
copyFiles(
path.join(examplesDir, 'spec', 'jasmine_examples'),
path.join(specDir, 'jasmine_examples'),
new RegExp(/[Ss]pec.js/)
);
}
function help(deps) {
const print = deps.print;
let terminalColumns = deps.terminalColumns || 80;
print(wrap(terminalColumns, 'Usage: jasmine [command] [options] [files] [--]'));
print('');
print('Commands:');
Object.keys(subCommands).forEach(function(cmd) {
let commandNameText = cmd;
if(subCommands[cmd].alias) {
commandNameText = commandNameText + ',' + subCommands[cmd].alias;
}
print(wrapWithIndent(terminalColumns, lPad(commandNameText, 10) + ' ', subCommands[cmd].description));
});
print('');
print(wrap(terminalColumns, 'If no command is given, Jasmine specs will be run.'));
print('');
print('');
print('Options:');
const options = [
{ syntax: '--parallel=N', help: 'Run in parallel with N workers' },
{ syntax: '--parallel=auto', help: 'Run in parallel with an automatically chosen number of workers' },
{ syntax: '--no-color', help: 'turn off color in spec output' },
{ syntax: '--list-not-applicable', help: 'list all specs that are marked not applicable' },
{ syntax: '--filter=', help: 'filter specs to run only those that match the given regular expression' },
{ syntax: '--filter-path=', help: 'run only the spec or suite that matches ' +
'the given path, e.g. ' +
'--filter-path=\'["parent suite name","child suite name","spec name"]\'' },
{ syntax: '--helper=', help: 'load helper files that match the given string' },
{ syntax: '--require=', help: 'load module that matches the given string' },
{ syntax: '--fail-fast', help: 'stop Jasmine execution on spec failure' },
{ syntax: '--config=', help: 'path to the Jasmine configuration file' },
{ syntax: '--reporter=', help: 'path to reporter to use instead of the default Jasmine reporter' },
{ syntax: '--verbose', help: 'print information that may be useful for debugging configuration' },
{ syntax: '--', help: 'marker to signal the end of options meant for Jasmine' },
];
for (const o of options) {
print(wrapWithIndent(terminalColumns, lPad(o.syntax, 22) + ' ', o.help));
}
print('');
print(wrap(terminalColumns,
'The given arguments take precedence over options in your jasmine.json.'));
print(wrap(terminalColumns,
'The path to your optional jasmine.json can also be configured by setting the JASMINE_CONFIG_PATH environment variable.'));
}
function wrapWithIndent(cols, prefix, suffix) {
const lines = wrap2(cols - prefix.length, suffix);
const indent = lPad('', prefix.length);
return prefix + lines.join('\n' + indent);
}
function wrap(cols, input) {
return wrap2(cols, input).join('\n');
}
function wrap2(cols, input) {
let lines = [];
let start = 0;
while (start < input.length) {
const splitAt = indexOfLastSpaceInRange(start, start + cols, input);
if (splitAt === -1 || input.length - start <= cols) {
lines.push(input.substring(start));
break;
} else {
lines.push(input.substring(start, splitAt));
start = splitAt + 1;
}
}
return lines;
}
function indexOfLastSpaceInRange(start, end, s) {
for (let i = end; i >= start; i--) {
if (s[i] === ' ') {
return i;
}
}
return -1;
}
function version(options) {
const print = options.print;
print('jasmine v' + require('../package.json').version);
const jasmine = new options.Jasmine();
print('jasmine-core v' + jasmine.coreVersion());
}
async function enumerate(options) {
const runner = new options.Jasmine({projectBaseDir: options.projectBaseDir});
await runner.loadConfigFile(options.configPath || process.env.JASMINE_CONFIG_PATH);
if (options.helpers !== undefined && options.helpers.length) {
runner.addMatchingHelperFiles(options.helpers);
}
if (options.requires !== undefined && options.requires.length) {
runner.addRequires(options.requires);
}
const suites = await runner.enumerate();
options.print(JSON.stringify(suites, null, ' '));
}
function lPad(str, length) {
if (str.length >= length) {
return str;
} else {
return lPad(' ' + str, length);
}
}
function copyFiles(srcDir, destDir, pattern) {
const srcDirFiles = fs.readdirSync(srcDir);
srcDirFiles.forEach(function(file) {
if (file.search(pattern) !== -1) {
fs.writeFileSync(path.join(destDir, file), fs.readFileSync(path.join(srcDir, file)));
}
});
}
function makeDirStructure(absolutePath) {
const splitPath = absolutePath.split(path.sep);
splitPath.forEach(function(dir, index) {
if(index > 1) {
const fullPath = path.join(splitPath.slice(0, index).join('/'), dir);
if (!fs.existsSync(fullPath)) {
fs.mkdirSync(fullPath);
}
}
});
}
function isEnvironmentVariable(arg) {
if (arg.match(/^--/)) {
return false;
}
return arg.match(/(.*)=(.*)/);
}
function setEnvironmentVariables(args) {
args.forEach(function (arg) {
const regExpMatch = isEnvironmentVariable(arg);
if(regExpMatch) {
const key = regExpMatch[1];
const value = regExpMatch[2];
process.env[key] = value;
}
});
}
jasmine-jasmine-npm-3c2955c/lib/examples/ 0000775 0000000 0000000 00000000000 15240143636 0020303 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/lib/examples/jasmine.mjs 0000664 0000000 0000000 00000000350 15240143636 0022442 0 ustar 00root root 0000000 0000000 export default {
spec_dir: "spec",
spec_files: [
"**/*[sS]pec.?(m)js"
],
helpers: [
"helpers/**/*.?(m)js"
],
env: {
stopSpecOnExpectationFailure: false,
random: true,
forbidDuplicateNames: true
}
}
jasmine-jasmine-npm-3c2955c/lib/exit_handler.js 0000664 0000000 0000000 00000000354 15240143636 0021473 0 ustar 00root root 0000000 0000000 class ExitHandler {
constructor(onExit) {
this._onExit = onExit;
}
install() {
process.on('exit', this._onExit);
}
uninstall() {
process.removeListener('exit', this._onExit);
}
}
module.exports = ExitHandler;
jasmine-jasmine-npm-3c2955c/lib/filters/ 0000775 0000000 0000000 00000000000 15240143636 0020135 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/lib/filters/path_spec_filter.js 0000664 0000000 0000000 00000000566 15240143636 0024015 0 ustar 00root root 0000000 0000000 module.exports = exports = pathSpecFilter;
function pathSpecFilter(filterPath) {
return function(spec) {
const specPath = spec.getPath();
if (filterPath.length > specPath.length) {
return false;
}
for (let i = 0; i < filterPath.length; i++) {
if (specPath[i] !== filterPath[i]) {
return false;
}
}
return true;
};
}
jasmine-jasmine-npm-3c2955c/lib/filters/regex_spec_filter.js 0000664 0000000 0000000 00000000335 15240143636 0024165 0 ustar 00root root 0000000 0000000 module.exports = exports = regexSpecFilter;
function regexSpecFilter(filterString) {
const filterPattern = new RegExp(filterString);
return function(spec) {
return filterPattern.test(spec.getFullName());
};
}
jasmine-jasmine-npm-3c2955c/lib/global_setup_or_teardown_runner.js 0000664 0000000 0000000 00000002727 15240143636 0025507 0 ustar 00root root 0000000 0000000 // Functionally similar to wrapping a single fn in a QueueRunner
// (except for the lack of callback support), but considerably simpler
class GlobalSetupOrTeardownRunner {
async run(name, fn, timeoutMs) {
await withTimeout(name, timeoutMs, async function() {
await withGlobalErrorHandling(name, fn);
});
}
}
async function withGlobalErrorHandling(name, fn) {
process.on('uncaughtException', onUncaughtException);
process.on('unhandledRejection', onUnhandledRejection);
let globalError = null;
try {
await fn();
} finally {
process.off('uncaughtException', onUncaughtException);
process.off('unhandledRejection', onUnhandledRejection);
}
if (globalError) {
throw globalError;
}
function onUncaughtException(e) {
globalError = new Error(`Unhandled exception during ${name}`, {
cause: e
});
}
function onUnhandledRejection(e) {
globalError = new Error(`Unhandled promise rejection during ${name}`, {
cause: e
});
}
}
async function withTimeout(name, timeoutMs, fn) {
timeoutMs = timeoutMs || 5000;
const maybePromise = fn();
const timedOut = {};
const timeoutPromise = new Promise(function(res) {
setTimeout(function() {
res(timedOut);
}, timeoutMs);
});
const result = await Promise.race([maybePromise, timeoutPromise]);
if (result === timedOut) {
throw new Error(`${name} timed out after ${timeoutMs} milliseconds`);
}
}
module.exports = GlobalSetupOrTeardownRunner;
jasmine-jasmine-npm-3c2955c/lib/jasmine.js 0000664 0000000 0000000 00000021127 15240143636 0020454 0 ustar 00root root 0000000 0000000 const ExitHandler = require('./exit_handler');
const regexSpecFilter = require('./filters/regex_spec_filter');
const pathSpecFilter = require('./filters/path_spec_filter');
const RunnerBase = require('./runner_base');
/**
* Options for the {@link Jasmine} constructor
* @name JasmineOptions
* @interface
*/
/**
* The path to the project's base directory. This can be absolute or relative
* to the current working directory. If it isn't specified, the current working
* directory will be used.
* @name JasmineOptions#projectBaseDir
* @type (string | undefined)
*/
/**
* 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 imported from jasmine-core in spec files, e.g.:
*
* `const {describe, it, expect, jasmine} = require('jasmine-core');`
*
* @name JasmineOptions#globals
* @type (boolean | undefined)
* @default true
*/
/**
* @classdesc Configures, builds, and executes a Jasmine test suite.
See also {@link ParallelRunner} which provides equivalent functionality for parallel execution.
* @param {(JasmineOptions | undefined)} options
* @constructor
* @name Jasmine
* @extends Runner
* @example
* const Jasmine = require('jasmine');
* const runner = new Jasmine();
*/
class Jasmine extends RunnerBase {
constructor(options) {
options = options || {};
super(options);
const jasmineCore = options.jasmineCore || require('jasmine-core');
if (options.jasmineCore && !options.jasmineCore.installGlobals) {
throw new Error('bad core passed');
}
this.jasmine = jasmineCore.jasmine;
if (options.globals !== false) {
jasmineCore.installGlobals();
}
/**
* 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.addReporter(this.reporter_);
/**
* @function
* @name Jasmine#coreVersion
* @return {string} The version of jasmine-core in use
*/
this.coreVersion = function() {
return jasmineCore.version();
};
// Public. See RunnerBase.
this.exitOnCompletion = true;
this.configureDefaultReporter({
randomSeedReproductionCmd(seed) {
return 'jasmine --random=true --seed=' + seed;
}
});
}
/**
* Sets whether to randomize the order of specs.
* @function
* @name Jasmine#randomizeTests
* @param {boolean} value Whether to randomize
*/
randomizeTests(value) {
this.env.configure({random: value});
}
/**
* Sets the random seed.
* @function
* @name Jasmine#seed
* @param {number} seed The random seed
*/
seed(value) {
this.env.configure({seed: value});
}
// Public. See RunnerBase jsdocs.
addReporter(reporter) {
this.env.addReporter(reporter);
this.reportersCount++;
}
// Public. See RunnerBase jsdocs.
clearReporters() {
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
*/
provideFallbackReporter(reporter) {
this.env.provideFallbackReporter(reporter);
}
/**
* 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
*/
addMatchers(matchers) {
this.env.addMatchers(matchers);
}
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);
}
configureEnv(envConfig) {
this.env.configure(envConfig);
}
/**
* 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
*/
stopSpecOnExpectationFailure(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
*/
stopOnSpecFailure(value) {
this.env.configure({stopOnSpecFailure: value});
}
/**
* 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.} [files] Spec files to run instead of the previously
* configured set
* @param {string|RegExp|object} [filter] Optional specification of what specs to run.
* Can be a RegExp, a string, or an object. If it's a RegExp, it will be matched
* against the full names of specs. If it's a string, it will be converted to
* a RegExp and then handled in the same way. If it's
* an object, it should have a path property whose value is an array of spec
* or suite descriptions.
* Regex used to filter specs. If specified, only
* specs with matching full names will be run.
* @return {Promise} Promise that is resolved when the suite completes.
* @example
* // Run all specs
* await jasmine.execute();
*
* // Run just spec/someSpec.js
* await jasmine.execute(['spec/someSpec.js']);
*
* // Run all specs with full paths starting with "a suite a child suite"
* await jasmine.execute(null, '^a suite a child suite');
*
* // Run all specs that are inside a suite named "a child suite" that is
* // a child of a top-level suite named "a suite"
* await jasmine.execute(null, {path: ['a suite', 'a child suite']});
*/
async execute(files, filter) {
await this.loadRequires();
await this.loadHelpers();
if (filter) {
if (typeof filter === 'string' || filter instanceof RegExp) {
this.env.configure({
specFilter: regexSpecFilter(filter)
});
} else if (filter.path) {
this.env.configure({
specFilter: pathSpecFilter(filter.path)
});
} else {
throw new Error('Unrecognized filter type');
}
}
if (files && files.length > 0) {
if (this.isVerbose_) {
console.log('Overriding previous specDir and specFiles because a list of spec files was provided on the command line or as an argument to Jasmine#execute');
}
this.specDir = '';
this.specFiles = [];
this.addMatchingSpecFiles(files);
}
const prematureExitHandler = new ExitHandler(() => this.exit(4));
prematureExitHandler.install();
let overallResult;
try {
await this.withinGlobalSetup_(async () => {
await this.loadSpecs();
overallResult = await this.env.execute();
});
} finally {
await this.flushOutput();
prematureExitHandler.uninstall();
}
if (this.exitOnCompletion) {
this.exit(RunnerBase.exitCodeForStatus(overallResult.overallStatus));
}
return overallResult;
}
/**
* Returns a tree of suites and specs without actually running the specs.
* @return {Promise}
*/
async enumerate() {
await this.loadRequires();
await this.loadHelpers();
await this.loadSpecs();
return this.env.topSuite().children.map(toEnumerateResult);
}
}
function toEnumerateResult(suiteOrSpecMeta) {
// Omit parent links to avoid JSON serialization failure due to circular
// references. Omit IDs since they aren't stable across executions. Add
// type information to make interpreting the output easier.
/**
* @interface EnumeratedSuiteOrSpec
* @property {string} type - 'suite' or 'spec'
* @property {EnumeratedSuiteOrSpec[]} [children] - Only defined for suites
*/
const result = {
description: suiteOrSpecMeta.description
};
if (suiteOrSpecMeta.children === undefined) {
result.type = 'spec';
} else {
result.type = 'suite';
result.children = suiteOrSpecMeta.children.map(toEnumerateResult);
}
return result;
}
module.exports = Jasmine;
jasmine-jasmine-npm-3c2955c/lib/loader.js 0000664 0000000 0000000 00000015741 15240143636 0020301 0 ustar 00root root 0000000 0000000 const path = require('path');
const url = require('url');
class Loader {
constructor(options) {
options = options || {};
this.require_ = options.requireShim || requireShim;
this.import_ = options.importShim || importShim;
this.resolvePath_ = options.resolvePath || path.resolve.bind(path);
}
load(modulePath) {
if (modulePath.endsWith('.json')) {
return new Promise(resolve => {
const result = this.require_(modulePath);
resolve(result);
});
}
const importSpecifier = this.resolveImportSpecifier_(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));
}
}
);
}
resolveImportSpecifier_(modulePath) {
const isNamespaced = modulePath.startsWith('@');
const isRelative = modulePath.startsWith('.');
const hasExtension = /\.[A-Za-z]+/.test(modulePath);
const resolvedModulePath = hasExtension || isRelative
? this.resolvePath_(modulePath)
: modulePath;
if (isNamespaced || ! hasExtension) {
return resolvedModulePath;
}
// 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.
return url.pathToFileURL(resolvedModulePath).toString();
}
}
function requireShim(modulePath) {
return require(modulePath);
}
function importShim(modulePath) {
return import(modulePath);
}
function fixupImportException(e, importedPath) {
// When an ES module has a syntax error, the resulting exception does not
// include the filename, which the user will need to debug the problem. We
// need to fix those up to include the filename. However, other kinds of load-
// time errors *do* include the filename and usually the line number. We need
// to leave those alone.
//
// Some examples of load-time errors that we need to deal with:
// 1. Syntax error in an ESM spec:
// SyntaxError: missing ) after argument list
// at Loader.moduleStrategy (node:internal/modules/esm/translators:147:18)
// at async link (node:internal/modules/esm/module_job:64:21)
//
// 2. Syntax error in an ES module imported from an ESM spec. This is exactly
// the same as #1: there is no way to tell which file actually has the syntax
// error.
//
// 3. Syntax error in a CommonJS module imported by an ES module:
// /path/to/commonjs_with_syntax_error.js:2
//
//
//
// SyntaxError: Unexpected end of input
// at Object.compileFunction (node:vm:355:18)
// at wrapSafe (node:internal/modules/cjs/loader:1038:15)
// at Module._compile (node:internal/modules/cjs/loader:1072:27)
// at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10)
// at Module.load (node:internal/modules/cjs/loader:988:32)
// at Function.Module._load (node:internal/modules/cjs/loader:828:14)
// at ModuleWrap. (node:internal/modules/esm/translators:201:29)
// at ModuleJob.run (node:internal/modules/esm/module_job:175:25)
// at async Loader.import (node:internal/modules/esm/loader:178:24)
// at async file:///path/to/esm_that_imported_cjs.mjs:2:11
//
// Note: For Jasmine's purposes, case 3 only occurs in Node >= 14.8. Older
// versions don't support top-level await, without which it's not possible to
// load a CommonJS module from an ES module at load-time. The entire content
// above, including the file path and the three blank lines, is part of the
// error's `stack` property. There may or may not be any stack trace after the
// SyntaxError line, and if there's a stack trace it may or may not contain
// any useful information.
//
// 4. Any other kind of exception thrown at load time
//
// Error: nope
// at Object. (/path/to/file_throwing_error.js:1:7)
// at Module._compile (node:internal/modules/cjs/loader:1108:14)
// at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10)
// at Module.load (node:internal/modules/cjs/loader:988:32)
// at Function.Module._load (node:internal/modules/cjs/loader:828:14)
// at ModuleWrap. (node:internal/modules/esm/translators:201:29)
// at ModuleJob.run (node:internal/modules/esm/module_job:175:25)
// at async Loader.import (node:internal/modules/esm/loader:178:24)
// at async file:///path_to_file_importing_broken_file.mjs:1:1
//
// We need to replace the error with a useful one in cases 1 and 2, but not in
// cases 3 and 4. Distinguishing among them can be tricky. Simple heuristics
// like checking the stack trace for the name of the file we imported fail
// because it often shows up even when the error was elsewhere, e.g. at the
// bottom of the stack traces in the examples for cases 3 and 4 above. To add
// to the fun, file paths in errors on Windows can be either Windows style
// paths (c:\path\to\file.js) or URLs (file:///c:/path/to/file.js).
if (!(e instanceof SyntaxError)) {
return e;
}
const escapedWin = escapeStringForRegexp(importedPath.replace(/\//g, '\\'));
const windowsPathRegex = new RegExp('[a-zA-z]:\\\\([^\\s]+\\\\|)' + escapedWin);
const windowsUrlRegex = new RegExp('file:///[a-zA-z]:\\\\([^\\s]+\\\\|)' + escapedWin);
const anyUnixPathFirstLineRegex = /^\/[^\s:]+:\d/;
const anyWindowsPathFirstLineRegex = /^[a-zA-Z]:(\\[^\s\\:]+)+:/;
if (e.message.indexOf(importedPath) !== -1
|| e.stack.indexOf(importedPath) !== -1
|| e.stack.match(windowsPathRegex) || e.stack.match(windowsUrlRegex)
|| e.stack.match(anyUnixPathFirstLineRegex)
|| e.stack.match(anyWindowsPathFirstLineRegex)) {
return e;
} else {
return new Error(
`While loading ${importedPath}: ${e.constructor.name}: ${e.message}`,
{cause: e}
);
}
}
// Adapted from Sindre Sorhus's escape-string-regexp (MIT license)
function escapeStringForRegexp(string) {
// Escape characters with special meaning either inside or outside character sets.
// Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.
return string
.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
.replace(/-/g, '\\x2d');
}
module.exports = Loader;
jasmine-jasmine-npm-3c2955c/lib/parallel_runner.js 0000664 0000000 0000000 00000034140 15240143636 0022212 0 ustar 00root root 0000000 0000000 const path = require('path');
const cluster = require('node:cluster');
const RunnerBase = require('./runner_base');
const randomize = require('./randomize');
/**
* Options for the {@link ParallelRunner} constructor
* @name ParallelRunnerOptions
* @interface
*/
/**
* The path to the project's base directory. This can be absolute or relative
* to the current working directory. If it isn't specified, the current working
* directory will be used.
* @name ParallelRunnerOptions#projectBaseDir
* @type (string | undefined)
*/
/**
* The number of worker processes to use.
* @name ParallelRunnerOptions#numWorkers
* @type (number | undefined)
* @default 2
*/
/**
* 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 imported from jasmine-core in spec files, e.g.: *
* `const {describe, it, expect, jasmine} = require('jasmine-core');` *
* @name ParallelRunnerOptions#globals
* @type (boolean | undefined)
* @default true
*/
/**
* @classdesc Configures, builds, and executes a Jasmine test suite in parallel.
* @param {(ParallelRunnerOptions | undefined)} options
* @constructor
* @name ParallelRunner
* @extends Runner
* @example
* const ParallelRunner = require('jasmine/parallel');
* const runner = new ParallelRunner({numWorkers: 3});
*/
class ParallelRunner extends RunnerBase {
constructor(options) {
super(options);
this.cluster_ = options.cluster || cluster;
this.workerDone_ = {};
this.numWorkers_ = options.numWorkers || 2;
let jasmineCore;
if (options.jasmineCore) {
// Use the provided core in all processes. This is mainly for use by
// jasmine-core's own test suite.
jasmineCore = options.jasmineCore;
this.jasmineCorePath_ = jasmineCore.files.self;
} else {
jasmineCore = require('jasmine-core');
}
const ParallelReportDispatcher = options.ParallelReportDispatcher ||
jasmineCore.jasmine.ParallelReportDispatcher;
this.reportDispatcher_ = new ParallelReportDispatcher(error => {
console.error(error);
this.hasUnhandledErrors_ = true;
});
this.reportDispatcher_.addReporter(this.reporter_);
this.timer_ = new jasmineCore.jasmine.Timer();
// Public. See RunnerBase jsdocs.
this.exitOnCompletion = true;
this.exit = process.exit;
this.reportedFatalErrors_ = [];
}
// Public. See RunnerBase jsdocs.
clearReporters() {
this.reportDispatcher_.clearReporters();
}
randomizeTests(value) {
if (!value) {
throw new Error('Randomization cannot be disabled in parallel mode');
}
}
seed(value) {
throw new Error('Random seed cannot be set in parallel mode');
}
// Public. See RunnerBase jsdocs.
addReporter(reporter, errorContext) {
if (!reporter.reporterCapabilities?.parallel) {
if (!errorContext) {
errorContext = 'this reporter';
}
throw new Error(
`Can't use ${errorContext} because it doesn't support parallel mode. ` +
'(Add reporterCapabilities: {parallel: true} if the reporter meets ' +
'the requirements for parallel mode.)'
);
}
this.reportDispatcher_.addReporter(reporter);
}
/**
* Runs the test suite.
*
* _Note_: Set {@link Runner#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.} [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} Promise that is resolved when the suite completes.
*/
async execute(files, filterString) {
if (this.isVerbose_) {
console.log(`Running in parallel with ${this.numWorkers_} workers`);
}
if (this.startedExecuting_) {
throw new Error('Parallel runner instance can only be executed once');
}
this.startedExecuting_ = true;
const explicitFailPromise = new Promise((res, rej) => {
this.failExecution_ = rej;
});
try {
return await Promise.race([
explicitFailPromise,
this.execute2_(files, filterString)
]);
} finally {
await this.flushOutput();
}
}
async execute2_(files, filterString) {
if (files && files.length > 0) {
if (this.isVerbose_) {
console.log('Overriding previous specDir and specFiles because a list of spec files was provided on the command line or as an argument to ParallelRunner#execute');
}
this.specDir = '';
this.specFiles = [];
this.addMatchingSpecFiles(files);
}
this.executionState_ = {
hasFailures: false,
hasSpecs: false,
failedExpectations: [],
deprecationWarnings: []
};
let jasmineDoneInfo;
await this.withinGlobalSetup_(async () => {
this.timer_.start();
// Prevent Node from exiting if all workers shut down unexpectedly, such as
// if a helper fails to load. The time interval is arbitrary.
const keepalive = setInterval(function () {
}, 100000);
try {
await this.createWorkers_(filterString);
this.reportDispatcher_.installGlobalErrors();
await this.reportDispatcher_.jasmineStarted({
// Omit totalSpecsDefined because we don't know how many there are.
// Omit order because it's not currently something the user can control
// in parallel mode.
parallel: true
});
await this.runSpecFiles_();
await this.shutDownWorkers_();
jasmineDoneInfo = await this.reportJasmineDone_();
this.reportDispatcher_.uninstallGlobalErrors();
} finally {
clearInterval(keepalive);
}
});
if (this.exitOnCompletion) {
if (this.hasUnhandledErrors_) {
this.exit(1);
} else {
this.exit(RunnerBase.exitCodeForStatus(jasmineDoneInfo.overallStatus));
}
}
if (this.hasUnhandledErrors_) {
throw new Error(
'Unhandled exceptions, unhandled promise rejections, or reporter ' +
'errors were encountered during execution'
);
}
return jasmineDoneInfo;
}
async createWorkers_(filterString) {
const workerPath = path.join(__dirname, '../bin/worker.js');
this.cluster_.setupPrimary({exec: workerPath});
const configPromises = [];
const workerConfig = {
spec_dir: this.specDir,
helpers: this.helperFiles,
requires: this.requires,
filter: filterString,
globals: this.globals_,
env: this.envConfig_,
};
if (this.jasmineCorePath_) {
workerConfig.jasmineCorePath = this.jasmineCorePath_;
}
for (let i = 0; i < this.numWorkers_; i++) {
const worker = this.cluster_.fork();
worker.on('exit', () => {
if (!this.workerDone_[worker.id]) {
this.fatalError_('Jasmine worker process unexpectedly exited', undefined, 4);
}
});
configPromises.push(new Promise(resolve => {
let booted = false;
worker.on('message', msg => {
switch (msg.type) {
// If custom ES module loaders are in use, there is a delay between
// when the fork() call above returns and when the worker is
// actually able to receive messages. To prevent the configure
// message from being lost, don't send it until the worker asks for
// it.
case 'readyForConfig':
worker.send({type: 'configure', configuration: workerConfig});
break;
// Wait for the worker to acknowledge that it's booted so that we don't
// tell it to run specs while it's booting.
case 'booted':
booted = true;
resolve();
break;
case 'fatalError':
this.fatalError_(formatErrorFromWorker(msg.error, msg.error.message));
break;
default:
if (!booted) {
console.error('Got unexpected message from Jasmine worker during boot:', msg);
}
break;
}
});
}));
}
await Promise.all(configPromises);
}
shutDownWorkers_() {
return new Promise(resolve => {
this.cluster_.disconnect(resolve);
});
}
async runSpecFiles_() {
this.specFiles = randomize(this.specFiles);
this.nextSpecFileIx_ = 0;
const workerPromises = Object.values(this.cluster_.workers)
.map(worker => this.runWorker_(worker));
await Promise.all(workerPromises);
}
async runWorker_(worker) {
return new Promise(resolve => {
const runNextSpecFile = () => {
if (this.exiting_) {
return;
}
const moreFiles = this.nextSpecFileIx_ < this.specFiles.length;
const stopOnSpecFailure = this.envConfig_ ? this.envConfig_.stopOnSpecFailure : false;
if (moreFiles && !(this.executionState_.hasFailures && stopOnSpecFailure)) {
const filePath = this.specFiles[this.nextSpecFileIx_++];
worker.send({type: 'runSpecFile', filePath});
} else {
this.workerDone_[worker.id] = true;
resolve();
}
};
worker.on('message', msg => {
switch (msg.type) {
case 'specFileDone':
if (msg.incompleteCode !== 'noSpecsFound') {
this.executionState_.hasSpecs = true;
}
if (msg.incompleteCode && msg.incompleteCode !== 'noSpecsFound') {
this.executionState_.incompleteCode = msg.incompleteCode;
this.executionState_.incompleteReason = msg.incompleteReason;
}
this.executionState_.failedExpectations = [
...this.executionState_.failedExpectations,
...msg.failedExpectations
];
this.executionState_.deprecationWarnings = [
...this.executionState_.deprecationWarnings,
...msg.deprecationWarnings
];
runNextSpecFile();
break;
case 'specFileLoadError':
this.addTopLevelError_('load',
`Error loading ${msg.filePath}`, msg.error);
runNextSpecFile();
break;
case 'uncaughtException':
this.addTopLevelError_('lateError',
'Uncaught exception in worker process', msg.error);
break;
case 'unhandledRejection':
this.addTopLevelError_('lateError',
'Unhandled promise rejection in worker process', msg.error);
break;
case 'reporterEvent':
this.handleReporterEvent_(msg.eventName, msg.payload);
break;
case 'fatalError':
// Handled elsewhere
break;
default:
console.error('Got unknown message from Jasmine worker:', msg);
}
});
runNextSpecFile();
});
}
configureEnv(envConfig) {
if (envConfig.specFilter) {
// specFilter is a function and we can't serialize those
throw new Error('The specFilter config property is not supported in ' +
'parallel mode');
}
if (this.startedExecuting_) {
throw new Error("Can't call configureEnv() after execute()");
}
this.envConfig_ = envConfig;
}
handleReporterEvent_(eventName, payload) {
switch (eventName) {
case 'jasmineStarted':
case 'jasmineDone':
break;
case 'specDone':
case 'suiteDone':
if (payload.status === 'failed') {
this.executionState_.hasFailures = true;
}
this.reportDispatcher_[eventName](payload);
break;
default:
this.reportDispatcher_[eventName](payload);
}
}
async reportJasmineDone_() {
const event = {
totalTime: this.timer_.elapsed(),
numWorkers: this.numWorkers_,
failedExpectations: this.executionState_.failedExpectations,
deprecationWarnings: this.executionState_.deprecationWarnings,
};
if (this.executionState_.hasFailures
|| this.executionState_.failedExpectations.length > 0) {
event.overallStatus = 'failed';
} else if (this.executionState_.incompleteCode) {
event.overallStatus = 'incomplete';
event.incompleteCode = this.executionState_.incompleteCode;
event.incompleteReason = this.executionState_.incompleteReason;
} else if (!this.executionState_.hasSpecs) {
event.overallStatus = 'incomplete';
event.incompleteCode = 'noSpecsFound';
event.incompleteReason = 'No specs found';
} else {
event.overallStatus = 'passed';
}
await this.reportDispatcher_.jasmineDone(event);
return event;
}
fatalError_(msg, msgWithoutStack, optionalExitCode) {
if (!msgWithoutStack) {
msgWithoutStack = msg;
}
this.exiting_ = true;
// Some errors may be reported by each worker. Print them only once.
if (!this.reportedFatalErrors_.includes(msg)) {
console.error(msg);
this.reportedFatalErrors_.push(msg);
}
this.cluster_.disconnect(() => {
if (this.exitOnCompletion) {
this.exit(optionalExitCode || 1);
}
this.failExecution_(
new Error('Fatal error in Jasmine worker process: ' + msgWithoutStack)
);
});
}
addTopLevelError_(globalErrorType, msgPrefix, serializedError) {
// Match how jasmine-core reports these in non-parallel situations
this.executionState_.failedExpectations.push({
actual: '',
expected: '',
globalErrorType,
matcherName: '',
message: `${msgPrefix}: ${serializedError.message}`,
passed: false,
stack: serializedError.stack,
});
}
}
function formatErrorFromWorker(error) {
// error isn't an Error instance (those don't survive IPC) so we have
// to do some extra work to make it display nicely.
const lines = ['Fatal error in worker: '+ error.message];
const stack = error.stack.split('\n');
let i = 0;
if (stack[0].indexOf(error.message) !== 0) {
i = 1;
}
for (; i < stack.length; i++) {
lines.push(stack[i]);
}
return lines.join('\n');
}
module.exports = ParallelRunner;
jasmine-jasmine-npm-3c2955c/lib/parallel_worker.js 0000664 0000000 0000000 00000013200 15240143636 0022204 0 ustar 00root root 0000000 0000000 const regexSpecFilter = require("./filters/regex_spec_filter");
class ParallelWorker {
constructor(options) {
this.loader_= options.loader;
this.clusterWorker_ = options.clusterWorker;
this.clusterWorker_.on('message', msg => {
switch (msg.type) {
case 'configure':
this.configure(msg.configuration);
break;
case 'runSpecFile':
this.runSpecFile(msg.filePath);
break;
default:
console.error('Jasmine worker got an unrecognized message:', msg);
}
});
// Install global error handlers now, before jasmine-core is booted.
// That allows jasmine-core to override them with its own more specific
// handling. These handlers will take care of errors that occur in between
// spec files.
for (const errorType of ['uncaughtException', 'unhandledRejection']) {
options.process.on(errorType, error => {
const sent = sendIfConnected(this.clusterWorker_, {
type: errorType,
error: serializeError(error)
});
if (!sent) {
console.error(`${errorType} in Jasmine worker process after disconnect:`,
error);
console.error('This error cannot be reported properly because it ' +
'happened after the worker process was disconnected.'
);
}
});
}
this.clusterWorker_.send({type: 'readyForConfig'});
}
async configure(options) {
if (options.loader) {
this.loader_ = { load: await this.loader_.load(options.loader) };
}
this.envPromise_ = this.loader_.load(options.jasmineCorePath || 'jasmine-core')
.then(core => {
if (options.globals !== false) {
core.installGlobals();
}
const env = core.jasmine.getEnv();
env.addReporter(forwardingReporter(this.clusterWorker_));
env.addReporter({
jasmineDone: event => this.jasmineDoneEvent_ = event
});
if (options.env) {
env.configure(options.env);
}
if (options.filter) {
env.configure({
specFilter: regexSpecFilter(options.filter)
});
}
return this.loadFiles_(options.requires || [])
.then(() => {
env.setParallelLoadingState('helpers');
return this.loadFiles_(options.helpers);
})
.then(() => {
env.setParallelLoadingState('specs');
this.clusterWorker_.send({type: 'booted'});
return env;
});
})
.catch(error => {
this.clusterWorker_.send({
type: 'fatalError',
error: serializeError(error)
});
});
}
async loadFiles_(files) {
for (const file of files) {
await this.loader_.load(file);
}
}
runSpecFile(specFilePath) {
(async () => {
this.jasmineDoneEvent_ = null;
let env = await this.envPromise_;
env.parallelReset();
try {
await this.loader_.load(specFilePath);
} catch (error) {
this.clusterWorker_.send({
type: 'specFileLoadError',
filePath: specFilePath,
error: serializeError(error)
});
return;
}
await env.execute();
if (!this.clusterWorker_.isConnected()) {
return;
}
this.clusterWorker_.send({
type: 'specFileDone',
overallStatus: this.jasmineDoneEvent_.overallStatus,
incompleteCode: this.jasmineDoneEvent_.incompleteCode,
incompleteReason: this.jasmineDoneEvent_.incompleteReason,
failedExpectations: this.jasmineDoneEvent_.failedExpectations,
deprecationWarnings: this.jasmineDoneEvent_.deprecationWarnings,
});
})();
}
}
function serializeError(error) {
return {
message: error.message,
stack: error.stack
};
}
function forwardingReporter(clusterWorker) {
const reporter = {};
const eventNames = ['suiteStarted', 'suiteDone', 'specStarted', 'specDone'];
for (const eventName of eventNames) {
reporter[eventName] = function (payload) {
const msg = {
type: 'reporterEvent',
eventName,
payload: {
...payload,
// IDs we get from -core are only unique within this process.
// Make them globally unique by prepending the worker ID.
id: `${clusterWorker.id}-${payload.id}`
}
};
try {
sendIfConnected(clusterWorker, msg);
} catch (e) {
if (e instanceof TypeError) {
msg.payload = fixNonSerializableReporterEvent(payload);
sendIfConnected(clusterWorker, msg);
} else {
throw e;
}
}
};
}
return reporter;
}
function sendIfConnected(clusterWorker, msg) {
if (clusterWorker.isConnected()) {
try {
clusterWorker.send(msg);
return true;
} catch (e) {
// EPIPE may be thrown if the worker receives a disconnect between
// the calls to isConnected() and send() above.
if (e.code !== 'EPIPE') {
throw e;
}
}
}
return false;
}
function fixNonSerializableReporterEvent(payload) {
payload = {...payload};
for (const ak of ['passedExpectations', 'failedExpectations']) {
if (payload[ak]) {
payload[ak] = payload[ak].map(function(expectation) {
expectation = {...expectation};
for (const vk of ['expected', 'actual']) {
try {
JSON.stringify(expectation[vk]);
// eslint-disable-next-line no-unused-vars
} catch (ex) {
expectation[vk] = '';
}
}
return expectation;
});
}
}
return payload;
}
module.exports = ParallelWorker;
jasmine-jasmine-npm-3c2955c/lib/randomize.js 0000664 0000000 0000000 00000001442 15240143636 0021014 0 ustar 00root root 0000000 0000000 module.exports = function randomOrder(items) {
const seed = generateSeed();
const copy = items.slice();
copy.sort(function (a, b) {
return jenkinsHash(seed + a) - jenkinsHash(seed + b);
});
return copy;
};
function generateSeed() {
return String(Math.random()).slice(-5);
}
// Bob Jenkins One-at-a-Time Hash algorithm is a non-cryptographic hash function
// used to get a different output when the key changes slightly.
// We use your return to sort the children randomly in a consistent way when
// used in conjunction with a seed
function jenkinsHash(key) {
let hash, i;
for (hash = i = 0; i < key.length; ++i) {
hash += key.charCodeAt(i);
hash += hash << 10;
hash ^= hash >> 6;
}
hash += hash << 3;
hash ^= hash >> 11;
hash += hash << 15;
return hash;
}
jasmine-jasmine-npm-3c2955c/lib/runner_base.js 0000664 0000000 0000000 00000036533 15240143636 0021340 0 ustar 00root root 0000000 0000000 const path = require('path');
const glob = require("glob");
const ConsoleReporter = require('@jasminejs/reporters/console');
const Loader = require("./loader");
const GlobalSetupOrTeardownRunner = require('./global_setup_or_teardown_runner');
const unWindows = require('./unWindows');
/**
* @classdesc Defines common methods and properties of {@link Jasmine} and
* {@link ParallelRunner}.
* Note: This should be considered an interface. It's only documented as a class
* due to jsdoc limitations. You can safely assume that these members are
* available on both runner classes, but the inheritance structure itself is an
* implementation detail that may change at any time.
* @constructor
* @hideconstructor
* @name Runner
*/
class RunnerBase {
constructor(options) {
this.loader = options.loader || new Loader();
let baseDir;
if (options.projectBaseDir) {
baseDir = options.projectBaseDir;
} else {
baseDir = (options.getcwd || path.resolve)();
}
this.projectBaseDir = unWindows(baseDir);
this.specFiles = [];
this.helperFiles = [];
this.requires = [];
this.specDir = '';
this.reporter_ = new (options.ConsoleReporter || ConsoleReporter)();
this.globalSetupOrTeardownRunner_ =
options.globalSetupOrTeardownRunner || new GlobalSetupOrTeardownRunner();
this.globals_ = options.globals;
}
/**
* Sets whether to run in verbose mode, which prints information that may
* be useful for debugging configuration problems.
* @function
* @name Runner#verbose
* @param {boolean} value Whether to run in verbose mode
*/
verbose(isVerbose) {
this.isVerbose_ = isVerbose;
}
/**
* Loads configuration from the specified file. The file can be a JSON file or
* any JS file that's loadable as a module and provides a Jasmine config
* as its default export.
*
* The config file will be loaded via dynamic import() unless this Jasmine
* instance has already been configured a custom loader. Dynamic
* import() supports ES modules as well as nearly all CommonJS modules.
* @name Runner#loadConfigFile
* @function
* @param {string} [configFilePath=spec/support/jasmine.json]
* @return Promise
*/
async loadConfigFile(configFilePath) {
if (this.isVerbose_) {
console.log(`Project base dir: ${this.projectBaseDir}`);
}
if (configFilePath) {
if (this.isVerbose_) {
console.log(`Loading config file ${configFilePath} because it was explicitly specified`);
}
await this.loadSpecificConfigFile_(configFilePath);
} else {
let found = false;
for (const ext of ['mjs', 'json', 'js']) {
const candidate = `spec/support/jasmine.${ext}`;
try {
await this.loadSpecificConfigFile_(candidate);
found = true;
break;
} catch (e) {
if (e.code !== 'MODULE_NOT_FOUND' // CommonJS
&& e.code !== 'ERR_MODULE_NOT_FOUND' // ESM
&& e.code !== 'ENOENT') { // Testdouble.js, maybe other ESM loaders too
throw e;
}
if (this.isVerbose_) {
console.log(`Tried to load config file ${candidate} but it does not exist (${e.code})`);
}
}
}
if (!found && this.isVerbose_) {
console.log('Did not find any config files.');
}
}
}
async loadSpecificConfigFile_(relativePath) {
const absolutePath = path.resolve(this.projectBaseDir, relativePath);
const config = await this.loader.load(absolutePath);
if (this.isVerbose_) {
console.log(`Loaded config file ${absolutePath}`);
}
await this.loadConfig(config);
}
/**
* Loads configuration from the specified object.
* @name Runner#loadConfig
* @function
* @async
* @param {Configuration} config
*/
async 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;
// TODO: Set up cross-package @see on the docs site and link this to the
// reporters config reference
/**
* Configuration for the default console reporter. See the documentation for
* the @jasminejs/reporters package for details.
* @name Configuration#defaultReporter
* @type object | undefined
*/
if (config.defaultReporter !== undefined) {
this.configureDefaultReporter(config.defaultReporter);
}
/**
* Whether the default reporter should list specs that are marked not
* applicable rather than merely summarizing them.
* @name Configuration#listNotApplicableSpecs
* @type boolean | undefined
* @default false
*/
if (config.listNotApplicableSpecs !== undefined) {
this.configureDefaultReporter({
listNotApplicableSpecs: config.listNotApplicableSpecs
});
}
/**
* Specifies a module containing a custom loader that will be used to load
* config files, source files, spec files, etc.
*
* If provided, it must refer to a module whose default export is a function
* that loads modules. The function must take a single argument, which will
* be a module import specifier or file path, and return a promise that
* resolves to the corresponding loaded module. The argument will be a
* module import specifier or file path.
*
* @name Configuration#loader
* @type string | undefined
* @default undefined
*/
if (config.loader) {
this.loader = { load: await this.loader.load(config.loader) };
}
if (Object.keys(envConfig).length > 0) {
this.configureEnv(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 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} or {@link ParallelRunner#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 (let i = 0; i < config.reporters.length; i++) {
this.addReporter(
config.reporters[i],
`the reporter in position ${i} of the configuration's reporters array`
);
}
}
/**
* A function that will be called exactly once, even in parallel mode,
* before the test suite runs. This is intended to be used to initialize
* out-of-process state such as starting up an external service.
*
* If the globalSetup function is async or otherwise returns a promise,
* Jasmine will wait up to {@link Configuration#globalSetupTimeout}
* milliseconds for it to finish before running specs. Callbacks are not
* supported.
*
* globalSetup may be run in a different process from the specs. In-process
* side effects that it causes, including changes to the Jasmine
* environment, are not guaranteed to affect any or all specs. Use either
* beforeEach or beforeAll for in-process setup.
*
* @name Configuration#globalSetup
* @type Function | undefined
*/
if (config.globalSetup) {
this.globalSetup_ = config.globalSetup;
}
/**
* The number of milliseconds to wait for an asynchronous
* {@link Configuration#globalSetup} to complete.
*
* @name Configuration#globalSetupTimeout
* @type Number | undefined
* @default 5000
*/
if (config.globalSetupTimeout) {
this.globalSetupTimeout_ = config.globalSetupTimeout;
}
/**
* A function that will be called exactly once, even in parallel mode,
* after the test suite runs. This is intended to be used to clean up
* out-of-process state such as shutting down an external service.
*
* If the globalTeardown function is async or otherwise returns a promise,
* Jasmine will wait up to {@link Configuration#globalTeardownTimeout}
* milliseconds for it to finish. Callbacks are not supported.
*
* globalTeardown may be run in a different process from the specs.
* In-process side effects caused by specs, including changes to the Jasmine
* environment, are not guaranteed to be visible to globalTeardown. Use
* either afterEach or afterAll for in-process cleanup.
*
* @name Configuration#globalTeardown
* @type Function | undefined
*/
if (config.globalTeardown) {
this.globalTeardown_ = config.globalTeardown;
}
/**
* The number of milliseconds to wait for an asynchronous
* {@link Configuration#globalTeardown} to complete.
*
* @name Configuration#globalTeardownTimeout
* @type Number | undefined
* @default 5000
*/
if (config.globalTeardownTimeout) {
this.globalTeardownTimeout_ = config.globalTeardownTimeout;
}
}
/**
* Adds a spec file to the list that will be loaded when the suite is executed.
* @function
* @name Runner#addSpecFile
* @param {string} filePath The path to the file to be loaded.
*/
addSpecFile(filePath) {
this.specFiles.push(filePath);
}
/**
* Adds a helper file to the list that will be loaded when the suite is executed.
* @function
* @name Runner#addHelperFile
* @param {string} filePath The path to the file to be loaded.
*/
addHelperFile(filePath) {
this.helperFiles.push(filePath);
}
addRequires(requires) {
const jasmineRunner = this;
requires.forEach(function(r) {
jasmineRunner.requires.push(r);
});
}
/**
* Configures the default reporter that is installed if no other reporter is
* specified.
* @name Runner#configureDefaultReporter
* @function
* @param {ConsoleReporterOptions} options
*/
configureDefaultReporter(options) {
this.reporter_.configure(options);
}
async withinGlobalSetup_(fn) {
let ok = false;
await this.runGlobalSetup_();
try {
await fn();
ok = true;
} finally {
if (ok) {
await this.runGlobalTeardown_();
} else {
// Allow the error from fn (which executes the suite) to propagate.
// It's probably more important than any error from global teardown.
try {
await this.runGlobalTeardown_();
} catch (e) {
console.error(e);
}
}
}
}
async runGlobalSetup_() {
if (this.globalSetup_) {
await this.globalSetupOrTeardownRunner_.run(
'globalSetup', this.globalSetup_, this.globalSetupTimeout_
);
}
}
async runGlobalTeardown_() {
if (this.globalTeardown_) {
await this.globalSetupOrTeardownRunner_.run(
'globalTeardown', this.globalTeardown_, this.globalTeardownTimeout_
);
}
}
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.
const streams = [process.stdout, process.stderr];
const promises = streams.map(stream => {
return new Promise(resolve => stream.write('', null, resolve));
});
return Promise.all(promises);
}
}
/**
* Adds files that match the specified patterns to the list of spec files.
* @function
* @name Runner#addMatchingSpecFiles
* @param {Array} patterns An array of spec file paths
* or {@link https://github.com/isaacs/node-glob#glob-primer|globs} that match
* spec files. Each path or glob will be evaluated relative to the spec directory.
*/
RunnerBase.prototype.addMatchingSpecFiles = addFiles('specFiles');
/**
* Adds files that match the specified patterns to the list of helper files.
* @function
* @name Runner#addMatchingHelperFiles
* @param {Array} patterns 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.
*/
RunnerBase.prototype.addMatchingHelperFiles = addFiles('helperFiles');
/**
* Whether to cause the Node process to exit when the suite finishes executing.
*
* @name Runner#exitOnCompletion
* @type {boolean}
* @default true
*/
/**
* Add a custom reporter to the Jasmine environment.
* @function
* @name Runner#addReporter
* @param {Reporter} reporter The reporter to add
* @see custom_reporter
*/
/**
* Clears all registered reporters.
* @function
* @name Runner#clearReporters
*/
function addFiles(kind) {
return function (files) {
const fileArr = this[kind];
const {includeFiles, excludeFiles} = files.reduce((ongoing, file) => {
const hasNegation = file.startsWith('!');
if (hasNegation) {
file = file.substring(1);
}
return {
includeFiles: ongoing.includeFiles.concat(!hasNegation ? [file] : []),
excludeFiles: ongoing.excludeFiles.concat(hasNegation ? [file] : [])
};
}, { includeFiles: [], excludeFiles: [] });
const baseDir = `${this.projectBaseDir}/${this.specDir}`;
includeFiles.forEach(function(file) {
const filePaths = glob
.sync(file, { cwd: baseDir, ignore: excludeFiles })
.map(function(f) {
if (path.isAbsolute(f)) {
return f;
} else {
return unWindows(path.join(baseDir, f));
}
})
.filter(function(filePath) {
return fileArr.indexOf(filePath) === -1;
})
// Sort file paths consistently. Glob <9 did this but Glob >= 9 doesn't.
// Jasmine doesn't care about the order, but users might.
.sort();
filePaths.forEach(function(filePath) {
fileArr.push(filePath);
});
});
if (this.isVerbose_) {
console.log(`File glob for ${kind}: ${files}`);
console.log(`Resulting ${kind}: [${fileArr}]`);
}
};
}
RunnerBase.exitCodeForStatus = function(status) {
switch (status) {
case 'passed':
return 0;
case 'incomplete':
return 2;
case 'failed':
return 3;
default:
console.error(`Unrecognized overall status: ${status}`);
return 1;
}
};
module.exports = RunnerBase;
jasmine-jasmine-npm-3c2955c/lib/unWindows.js 0000664 0000000 0000000 00000000350 15240143636 0021016 0 ustar 00root root 0000000 0000000 // glob interprets backslashes as escape sequences, not directory separators.
// Convert them to slashes. Should only be called when running on Windows.
module.exports = function unWindows(dir) {
return dir.replace(/\\/g, '/');
}; jasmine-jasmine-npm-3c2955c/package.json 0000664 0000000 0000000 00000001762 15240143636 0020213 0 ustar 00root root 0000000 0000000 {
"name": "jasmine",
"description": "CLI for Jasmine, a simple JavaScript testing framework for browsers and Node",
"homepage": "http://jasmine.github.io/",
"keywords": [
"test",
"testing",
"jasmine",
"tdd",
"bdd"
],
"license": "MIT",
"version": "7.0.0",
"repository": {
"type": "git",
"url": "https://github.com/jasmine/jasmine-npm"
},
"scripts": {
"test": "node ./bin/jasmine.js && npm run lint",
"lint": "eslint \"bin/**/*.js\" \"lib/**/*.js\" \"spec/**/*.js\""
},
"exports": {
".": "./lib/jasmine.js",
"./parallel": "./lib/parallel_runner.js"
},
"files": [
"bin",
"lib",
"LICENSE",
"package.json",
"README.md"
],
"dependencies": {
"@jasminejs/reporters": "^1.1.0",
"glob": "^10.2.2 || ^11.0.3 || ^12.0.0 || ^13.0.0",
"jasmine-core": "~7.0.0"
},
"bin": "./bin/jasmine.js",
"main": "./lib/jasmine.js",
"devDependencies": {
"eslint": "^9.24.0",
"eslint-plugin-jasmine": "^4.2.2"
}
}
jasmine-jasmine-npm-3c2955c/release_notes/ 0000775 0000000 0000000 00000000000 15240143636 0020547 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/release_notes/2.1.0.md 0000664 0000000 0000000 00000001730 15240143636 0021530 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.1.0 Release Notes
## Summary
This release updates the jasmine-core dependency to 2.1.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/2.1.0.md)
for more information.
## Changes
* Stop using util.print as default print option.
* Make the grunt task that runs the jasmine specs available by moving it to the `tasks` dir
* Add cleaned up ConsoleReporter from jasmine-core to the npm.
## Pull Requests and Issues
- Split paths with path.sep and parse arguments in a more compatible way.
- Merges [#6](http://github.com/pivotal/jasmine-npm/issues/6) from @briandipalma
- Allow the jasmine command to run only a specified set of files.
- Fixes [#2](http://github.com/pivotal/jasmine-npm/issues/2)
- Add ability to load jasmine config from a javascript object
- Merges [#1](http://github.com/pivotal/jasmine-npm/issues/1)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.1.1.md 0000664 0000000 0000000 00000001112 15240143636 0021523 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.1.1 Release Notes
## Summary
This release improves the output of the ConsoleReporter.
## Changes
* ConsoleReporter - Add red color to failure messages, add headings for message and stack, add failed spec number
* Update travis badge
* Add .idea/ to gitignore.
## Pull Requests and Issues
- Improve error formatting
- Fixes stack trace of Issue [#4](https://github.com/jasmine/jasmine-npm/issues/4), Merges [#13](https://github.com/jasmine/jasmine-npm/pull/13) from @wendorf
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_ jasmine-jasmine-npm-3c2955c/release_notes/2.2.0.md 0000664 0000000 0000000 00000000756 15240143636 0021540 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.2.0 Release Notes
## Summary
This release updates the jasmine-core dependency to 2.2.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/2.2.0.md)
for more information.
## Changes
* Show pending specs at the end of the suite
* Don't package node_modules and release_notes directories
* Uses more realistic folder structure for examples
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.2.1.md 0000664 0000000 0000000 00000000434 15240143636 0021532 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.2.1 Release Notes
## Pull Requests & Issues
* Use exit module instead of process.exit for Windows workaround
- Fixes [#20](https://github.com/jasmine/jasmine-npm/issues/20)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.3.0.md 0000664 0000000 0000000 00000004064 15240143636 0021535 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.3.0 Release Notes
## Summary
This release updates the jasmine-core dependency to 2.3.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/2.3.0.md)
for more information.
## Changes
* Move mention of default command up near other commands in help
* Document how to specify path to config file
* Add docs for filter and stop spec execution
* Allows the user to specify stop on execution behavior with a CLI param.
* Gives the user the ability to stop execution on failure.
* Adds version command to show the jasmine and jasmine-core versions.
* Deprecates passing an onComplete to ConsoleReporter and as an option to configureDefaultReporter
* Adds jasmine.onComplete that defines a callback for the exit code reporter to call
## Pull Requests & Issues
* Use the exit module only in Windows with node version below v0.12.0. Use process.exit otherwise
- Fixes [#40](https://github.com/jasmine/jasmine-npm/issues/40)
- Fixes [#36](https://github.com/jasmine/jasmine-npm/issues/36)
* Add -v and -h aliases to the CLI.
- Fixes [#19](https://github.com/jasmine/jasmine-npm/issues/19)
* Add filter by spec name
- Merge [#35](https://github.com/jasmine/jasmine-npm/issues/35) from @just-boris
* Update package.json license
- Merge [#34](https://github.com/jasmine/jasmine-npm/issues/34) from @mikaturunen
* Don't output ANSI escape sequences if stdout is not a terminal
- Merge [#33](https://github.com/jasmine/jasmine-npm/issues/33) from @sgravrock
* jasmine command only adds a default reporter if no other reporter is added.
- Fixes [#28](https://github.com/jasmine/jasmine-npm/issues/28)
* Load helper files even if files are specified on the command line
- Fixes [#21](https://github.com/jasmine/jasmine-npm/issues/21)
- Fixes [#28](https://github.com/jasmine/jasmine-npm/issues/28)
* Allow custom stackFilter function
- Merge [#27](https://github.com/jasmine/jasmine-npm/issues/27) from @hankduan
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.3.1.md 0000664 0000000 0000000 00000000631 15240143636 0021532 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.3.1 Release Notes
## Summary
This patch release fixes a breaking change made in 2.3.0 related to default exiting of the process.
## Changes
## Pull Requests & Issues
* Only use the default exiting if the default reporter is used.
- Fixes [#43](https://github.com/jasmine/jasmine-npm/issues/43)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.3.2.md 0000664 0000000 0000000 00000001072 15240143636 0021533 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.3.2 Release Notes
## Pull Requests & Issues
* Use JASMINE_CONFIG_PATH env in grunt task
- Merges [#50](https://github.com/jasmine/jasmine-npm/issues/50) from @nesQuick
* Add link to docs for jasmine.json
- Fixes [#49](https://github.com/jasmine/jasmine-npm/issues/49)
* Merge pull request #48 from LJWall/count-disabled
Report "Ran X of Y specs" if some are disabled.
- Merges [#48](https://github.com/jasmine/jasmine-npm/issues/48) from @ljwall
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.4.0.md 0000664 0000000 0000000 00000000634 15240143636 0021535 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.4.0 Release Notes
## Summary
This release updates the jasmine-core dependency to 2.4.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/2.4.0.md)
for more information.
## Changes
* Enable the --random and --seed cli flags
- Merges #55 from @marcioj
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.4.1.md 0000664 0000000 0000000 00000000421 15240143636 0021530 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.4.1 Release Notes
## Pull Requests & Issues
* Remove comments and generally fix example json file
- Fixes [#60](https://github.com/jasmine/jasmine-npm/issues/60)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.5.0.md 0000664 0000000 0000000 00000003051 15240143636 0021532 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.5.0 Release Notes
## Summary
This release updates the jasmine-core dependency to 2.5.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/2.5.0.md)
for more information.
## Changes
* Report errors in global afterAlls
* Retrieve the jasmine-core version through the interface
* Run CI against multiple node versions
## Pull Requests & Issues
* Added travis ci support for node 6
- Merges [#79](https://github.com/jasmine/jasmine-npm/issues/79) from @amilajack
* Added better install method to readme
- Merges [#80](https://github.com/jasmine/jasmine-npm/issues/80) from @amilajack
* Use jasmine-core's fallback reporter
- Merges [#67](https://github.com/jasmine/jasmine-npm/issues/67) from @mauricioborges
- Fixes [#66](https://github.com/jasmine/jasmine-npm/issues/66)
* Allow to run without jasmine.json
- Merges [#74](https://github.com/jasmine/jasmine-npm/issues/74) from @m7r
* Default spec_dir if not provided
- Merges [#70](https://github.com/jasmine/jasmine-npm/issues/70) from @dflynn15
- Fixes [#69](https://github.com/jasmine/jasmine-npm/issues/69)
* Proper handling of randomization args in config and command line
- Merges [#65](https://github.com/jasmine/jasmine-npm/issues/65) from @marcioj
* Resolve examples folder dynamically.
- Merges [#64](https://github.com/jasmine/jasmine-npm/issues/64) from @danielsiwiec
- Fixes [#63](https://github.com/jasmine/jasmine-npm/issues/63)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.5.1.md 0000664 0000000 0000000 00000001435 15240143636 0021537 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.5.1 Release Notes
## Summary
This release updates the jasmine-core dependency to 2.5.1. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/2.5.1.md)
for more information.
## Pull Requests & Issues
* Update glob dependency
- Fixes [#78](https://github.com/jasmine/jasmine-npm/issues/78)
- Fixes [jasmine/jasmine#1148](https://github.com/jasmine/jasmine/issues/1148)
* Only use the default exiting if the default reporter is used
- Merges [#89](https://github.com/jasmine/jasmine-npm/issues/89) from @flore77
* Update link to documentation in README.md
- Merges [#87](https://github.com/jasmine/jasmine-npm/issues/87) from @gkalpak
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.5.2.md 0000664 0000000 0000000 00000000622 15240143636 0021535 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.5.2 Release Notes
## Changes
* Register ConsoleReporter immediately upon creation so it can be easily cleared
- Fixes [#88](https://github.com/jasmine/jasmine-npm/issues/88)
* Use default reporter in own tests
- Merges [#88](https://github.com/jasmine/jasmine-npm/issues/88) from bcaudan
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.5.3.md 0000664 0000000 0000000 00000001142 15240143636 0021534 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.5.3 Release Notes
## Pull Requests & Issues
* A bunch of fixes to make the default reporter work better and accept the right configurations
- Merge #98 from @cnishina
- Fixes #95
- Merges #100 from @tomv564
* adding license file
- Merges #101 from @julka
* default console reporter hangs sometimes
- Merge #84 from @ybian
- Fixes #83
* Enable regex filter by omitting automatic escaping
- Merge #76 from @aaalsaleh
* Allow adding a helper with a cli argument
- Merges #75 from @m7r
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.6.0.md 0000664 0000000 0000000 00000001314 15240143636 0021533 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.6.0 Release Notes
## Summary
This release updates the jasmine-core dependency to 2.6.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/2.6.0.md)
for more information.
## Pull Requests & Issues
* Expose `closeReporters` methos in the wrapper
- Merges #114 from @lonelyelk
- Fixes jasmine/jasmine#1228
* Try to detect a `exit` being called inside the suite
- Fixes jasmine/jasmine#1273
* Option to specify path to your jasmine.json
- Merges #107 from @bcaudan
- Fixes #85
* Reject unknown CLI options
- Merges #108 from @bcaudan
- Fixes #53
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.7.0.md 0000664 0000000 0000000 00000001272 15240143636 0021537 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.7.0 Release Notes
## Summary
This release updates the jasmine-core dependency to 2.7.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/2.7.0.md)
for more information.
## Pull Requests & Issues
* Report the random seed at the beginning and end of execution to allow users to reproduce seed-dependent Jasmine crashes.
- Merges [#120](https://github.com/jasmine/jasmine-npm/issues/120) from @sgravrock
* Fix linebreak between jasmine config examples.
- Merges [#122](https://github.com/jasmine/jasmine-npm/issues/122) from @donmccurdy
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.8.0.md 0000664 0000000 0000000 00000000507 15240143636 0021540 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.8.0 Release Notes
## Summary
This release updates the jasmine-core dependency to 2.8.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/2.8.0.md)
for more information.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.9.0.md 0000664 0000000 0000000 00000000507 15240143636 0021541 0 ustar 00root root 0000000 0000000 # Jasmine NPM 2.9.0 Release Notes
## Summary
This release updates the jasmine-core dependency to 2.9.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/2.9.0.md)
for more information.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/2.99.md 0000664 0000000 0000000 00000000556 15240143636 0021500 0 ustar 00root root 0000000 0000000 # Jasmine Npm 2.99 Release Notes
## Summary
This release is part of the upgrade path to Jasmine 3.0. Please see the [release notes for Jasmine-Core](https://github.com/jasmine/jasmine/blob/master/release_notes/2.99.md)
## Changes
* Report deprecation warnings in CI output
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.0.md 0000664 0000000 0000000 00000002104 15240143636 0021366 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.0 Release Notes
## Summary
Jasmine 3.0 is a major release of Jasmine, and as such includes some breaking changes in addition to various new features.
Please see the [release notes for Jasmine-Core](https://github.com/jasmine/jasmine/blob/master/release_notes/3.0.md)
There is also a 2.99 release of Jasmine that will present deprecation warnings for suites that will encounter different behavior in 3.0.
## Changes
* Support stopping jasmine execution on first spec failure via config object or with `--fail-fast` command line arg
- Fixes [#16](https://github.com/jasmine/jasmine-npm/issues/16)
* Add ability to pass `--reporter` on the command line
- Fixes [jasmine/jasmine#1027](https://github.com/jasmine/jasmine/issues/1027)
* Print full details for suite failures
* Report how to re-run Jasmine with the current seed
* Run specs in random order by default
* Treat suites with focused specs as failures
* Removed deprecated completion callback from console reporter
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.1.0.md 0000664 0000000 0000000 00000001030 15240143636 0021522 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.1 Release Notes
## Summary
This release updates the jasmine-core dependency to 3.1.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/3.1.0.md)
for more information.
## Changes
* Tell Jasmine-core not to handle load errors itself
- Fixes [jasmine/jasmine#1519](https://github.com/jasmine/jasmine/issues/1519)
* better error reporting when an invalid --reporter is specified
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.10.0.md 0000664 0000000 0000000 00000003211 15240143636 0021605 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.10 Release Notes
This release updates the jasmine-core dependency to 3.10.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/main/release_notes/3.10.0.md)
for more information.
## New features and bugfixes
* Support for executing the suite multiple times
* See the jasmine-core release notes for details
* Display the top suite name as "top suite", not "undefined" when reporting
suite-level failures
* Fixed reporting of load-time errors from modules imported by specs
* Made the promise returned from `Jasmine#execute` usable
* Added an exitOnCompletion property to directly control whether Jasmine
should make the Node process exit. Previously this could only be done by
calling `Jasmine#onComplete`.
* The promise returned from `Jasmine#execute` is resolved to the overall
status.
* Improved interface for programmatically adding files
* Added Jasmine#addHelperFile
* Added more clearly named synonyms for Jasmine#addSpecFiles and
Jasmine#addHelperFiles, and marked the old ones deprecated
## Documentation improvements
* Added jsdoc for `Jasmine#env`
## Internal updates
* Pass stopOnSpecFailure and stopSpecOnExpectationFailure options to core,
not the deprecated failFast and oneFailurePerSpec options
* Replaced var with const and let
* Test suite improvements
## Supported environments
The jasmine NPM package has been tested on Node 12, 14, and 16. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/3.10.0.md)
for supported browsers.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.2.0.md 0000664 0000000 0000000 00000001712 15240143636 0021532 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.2 Release Notes
## Summary
This release updates the jasmine-core dependency to 3.2.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/3.2.0.md)
for more information.
## Changes
* Unknown command line options produce exit code 1
- Merges [#138](https://github.com/jasmine/jasmine-npm/issues/138) from @enelson
- Fixes [#137](https://github.com/jasmine/jasmine-npm/issues/137)
* Add option "require(s)" to command line and config file
- Merges [#136](https://github.com/jasmine/jasmine-npm/issues/136) from @liuxh0
- Fixes [#135](https://github.com/jasmine/jasmine-npm/issues/135)
* Add --color option
- Merges [#132](https://github.com/jasmine/jasmine-npm/issues/132) from @susisu
* fix --filter in README
- Merges [#131](https://github.com/jasmine/jasmine-npm/issues/131) from @cancerberoSgx
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.3.0.md 0000664 0000000 0000000 00000001344 15240143636 0021534 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.3 Release Notes
## Summary
This release updates the jasmine-core dependency to 3.3.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/3.3.0.md)
for more information.
## Changes
* Wait until streams are completed before exiting to prevent output cropping when jasmine is called form another process
- Merges [#141](https://github.com/jasmine/jasmine-npm/issues/141) from @jkytomak
* Allow excluding spec files and helper files
- Merges [#140](https://github.com/jasmine/jasmine-npm/issues/140) from @liuxh0
- Fixes [#128](https://github.com/jasmine/jasmine-npm/issues/128)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.3.1.md 0000664 0000000 0000000 00000001116 15240143636 0021532 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.3.1 Release Notes
## Summary
This is a bug fix release to clean up the deprecation warning introduced in 3.3.0
## Changes
* Add `null` encoding when writing to streams on close
- Fixes [jasmine/jasmine#1622](https://github.com/jasmine/jasmine/issues/1622)
* Changes to avoid config deprecation warnings (from jasmine-core).
- Merges [#147](https://github.com/jasmine/jasmine-npm/issues/147) from @claudiosdc
- Fixes [#145](https://github.com/jasmine/jasmine-npm/issues/145)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.4.0.md 0000664 0000000 0000000 00000001415 15240143636 0021534 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.4 Release Notes
## Summary
This release updates the jasmine-core dependency to 3.4.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/3.4.0.md)
for more information.
## Changes
* Use `removeListener` instead of `off` since it always exists
* moved exit listener add and removal to completion reporter
- Merges [#149](https://github.com/jasmine/jasmine-npm/issues/149) from @battk
- Fixes [#134](https://github.com/jasmine/jasmine-npm/issues/134)
- Fixes [#125](https://github.com/jasmine/jasmine-npm/issues/125)
* Update README.md
- Merges [#146](https://github.com/jasmine/jasmine-npm/issues/146) from @strama4
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.5.0.md 0000664 0000000 0000000 00000000627 15240143636 0021541 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.5 Release Notes
## Summary
This release updates the jasmine-core dependency to 3.5.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/master/release_notes/3.5.0.md)
for more information.
## Changes
* Use the total time from Jasmine-Core instead of calculating ourself
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.6.0.md 0000664 0000000 0000000 00000001653 15240143636 0021542 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.6 Release Notes
## Summary
This release updates the jasmine-core dependency to 3.6.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/main/release_notes/3.6.0.md)
for more information.
## Changes
* Removed unnecessary check for passedExpectations truthiness
* Support 'failSpecWithNoExpectations' config option and include a message in the default ConsoleReporter when a spec contains no expectations
* Merges [#157](https://github.com/jasmine/jasmine-npm/pull/157) from @coyoteecd
* Fixes [#156](https://github.com/jasmine/jasmine-npm/issues/156)
* Don't parse argv after --
* Merges [#155](https://github.com/jasmine/jasmine-npm/pull/155) from @tharvik
* Added support for running specs in parallel
* Merges [#153](https://github.com/jasmine/jasmine-npm/pull/153) from @wood1986
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.6.1.md 0000664 0000000 0000000 00000000442 15240143636 0021536 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.6.1 Release Notes
## Summary
This release fixes a bug in the multi-threading logic to ensure spec files are only loaded once
## Changes
* Only load spec files once
* Fixes #161
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.6.2.md 0000664 0000000 0000000 00000002077 15240143636 0021545 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.6.2 Release Notes
# Summary
This release fixes an issue with load order of helper files introduced by switching globbing libraries
# Changes
Added support for ES modules
* Fixes [#150](https://github.com/jasmine/jasmine-npm/issues/150).
* Specs and helpers with names ending in .mjs are loaded as ES modules
(`import("foo.mjs")`).
* All other specs and helpers are loaded as CommonJS modules, as before
(`require("foo.js")`).
* If using ES modules with Node 10 or 11, run
`node --experimental-modules /path/to/jasmine` instead of `jasmine`.
Switch back to just plain `glob` for smaller dependency list
* Fixes [#162](https://github.com/jasmine/jasmine-npm/issues/162)
Remove code related to multiple workers as it never worked in the first place
* See [#153](https://github.com/jasmine/jasmine-npm/issues/153)
* Fixes [#163](https://github.com/jasmine/jasmine-npm/issues/163)
* Fixes [#165](https://github.com/jasmine/jasmine-npm/issues/165)
* See also discussion in [#162](https://github.com/jasmine/jasmine-npm/issues/162)
jasmine-jasmine-npm-3c2955c/release_notes/3.6.3.md 0000664 0000000 0000000 00000001362 15240143636 0021542 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.6.3 Release Notes
## Summary
This release fixes several bugs related to module loading.
## Changes
Fixed ES module loading on Windows
* Fixes [#169](https://github.com/jasmine/jasmine-npm/issues/169)
Include the filename in the error when an ES module has syntax errors
* Fixes [#168](https://github.com/jasmine/jasmine-npm/issues/168)
Exit nonzero when a spec fails to load
* Fixes [#167](https://github.com/jasmine/jasmine-npm/issues/167)
Clarify which Node versions are supported
* 10.x, 12.x, and 14.x are supported.
* Odd-numbered major versions are very likely to work, but they aren't supported or tested against.
* See the `engines` field in `package.json` in this and future releases for the current list.
jasmine-jasmine-npm-3c2955c/release_notes/3.6.4.md 0000664 0000000 0000000 00000001050 15240143636 0021535 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.6.4 Release Notes
## Summary
This is a bugfix release that removes the `engines` specification.
## Changes
* Removed `engines` field from package.json
The engines field was added in 3.6.3 in an attempt to better document the set
of Node versions that Jasmine supports, but it's caused more problems than it
solves. In particular, Yarn users receive an error rather than a warning when
using a version of Node that works but isn't supported.
See for a list of supported Node
versions.
jasmine-jasmine-npm-3c2955c/release_notes/3.7.0.md 0000664 0000000 0000000 00000000351 15240143636 0021535 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.7 Release Notes
## Summary
This release updates the jasmine-core dependency to 3.7.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/main/release_notes/3.7.0.md)
for more information.
jasmine-jasmine-npm-3c2955c/release_notes/3.8.0.md 0000664 0000000 0000000 00000003333 15240143636 0021541 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.8 Release Notes
## Summary
This release updates the jasmine-core dependency to 3.8.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/main/release_notes/3.8.0.md)
for more information.
# New features and bug fixes
* Opt-in support for ES modules with .js extension and package type `module`
* All files are loaded using `import` if `"jsLoader": "import"` is set in
the config file.
* Only supported on Node >= 12.17.0. Older versions have missing or broken
support for importing .js files.
* Fixes [#170](https://github.com/jasmine/jasmine-npm/issues/170)
* Allow the random seed reproduction command to be overridden
* Needed by jasmine-browser-runner, which uses the ConsoleReporter but needs
to tell the user to run a different command.
# Documentation updates
* Created an initial set of [API reference documentation](https://jasmine.github.io/api/npm/3.8/index)
# Internal notes
* Specify files to include in the NPM package rather than files to exclude
* CI matrix updates
* Added Node 16.
* Added Node 12.0, 12.16, and 12.17 to ensure coverage of versions that do
and don't have good support for importing .js files.
* Removed Windows. We'll manually run the tests on Windows before each
release, but we no longer have reliable access to a free Windows CI
service.
* Migrated from Travis to Circle CI
## Supported environments
The jasmine NPM package has been tested on Node 12, 14, 16, and 18. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/3.8.0.md)
for supported browsers.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.9.0.md 0000664 0000000 0000000 00000001605 15240143636 0021542 0 ustar 00root root 0000000 0000000 # Jasmine NPM Release Notes
This release updates the jasmine-core dependency to 3.9.0. See the
[jasmine-core release notes](https://github.com/pivotal/jasmine/blob/main/release_notes/3.9.0.md)
for more information.
## New features and bug fixes
* Allow arbitrary env configuration to be specified via the `env` config field
This allows us to automatically support new env config properties in the
future without any code changes.
* Default to including .mjs as well as .js in newly generated config files
* Fixes #176
# Documentation improvements
* Added jsdoc for Jasmine.prototype.configureDefaultReporter
* Fixed copy-paste error in docs
* Merges [#183](https://github.com/jasmine/jasmine-npm/pull/183) from @UziTech
## Internal notes
* Removed vestigal code for old `timer` reporter option
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/3.99.0.md 0000664 0000000 0000000 00000000526 15240143636 0021634 0 ustar 00root root 0000000 0000000 # Jasmine NPM 3.99.0 Release Notes
This release adds deprecation warnings for breaking changes that will be
introduced in Jasmine 4.0. Please see the
[migration guide](https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0)
for more information.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/4.0.0.md 0000664 0000000 0000000 00000010526 15240143636 0021534 0 ustar 00root root 0000000 0000000 # Jasmine NPM 4.0.0 Release Notes
## Summary
This is a major release. In addition to new features and bug fixes it contains
a variety of breaking changes that are intended to improve ES module support,
improve awkward or outdated interfaces, and make Jasmine easier to maintain
and contribute to. If you're upgrading from Jasmine 3.x, we recommend installing
3.99 and fixing any deprecation warnings that it emits before updating to 4.0.
See the [migration guide](https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0)
for more information. Be sure to read the release notes for `jasmine-core` 4.0.0
as well.
## Highlights
* The `jasmine-core` dependency has been updated to 4.0.0
* ES module support is enabled by default.
* Node 10 and 12.0-12.16 are no longer supported.
## Breaking changes
* Node versions older than 12.17 are no longer supported because they have
insufficient support for interop between ES modules and CommonJS modules.
* Beginning with this release, everything not documented in the
[API reference](https://jasmine.github.io/api/npm/4.0/Jasmine) is considered
a private API.
* ES module support is enabled by default, but can still be disabled by
adding `jsLoader: "require"` to the configuration. `jsLoader: "import"` is
now a no-op.
This change breaks loading of files with extensions that aren't supported by
dynamic `import()`, such as `.jsx`, although that has been subsequently fixed
in 4.0.1. If you have specs or source files with such extensions, please
update to at least 4.0.1. Alternately you can either rename the files to
`.js` or add `jsLoader: "require"` to your Jasmine config file.
* Config files can be ES modules. This is a breaking change because it requires
`Jasmine#loadConfigFile` to be async.
* The `--fail-fast` CLI flag now causes Jasmine to stop spec execution on the
first expectation failure as well as stopping suite execution on the first
spec failure.
* The ambiguously named `--stop-on-failure` CLI flag is no longer supported.
* Failure to load or instantiate a reporter is a fatal error, not just a warning.
* Relative reporter paths are resolved based on the working directory rather
than the location of the module inside Jasmine that calls `require()`.
* The `jasmine` command now uses distinct exit codes for various types of non-success:
* 1 for anything unexpected, i.e. Jasmine didn't run to completion
* 2 for incomplete (focused specs/suites but no failures)
* 3 for failed (spec/suite failures)
* Other nonzero exit codes may be used for other purposes. Code that checks
the exit code of the `jasmine` command should not treat any value other than
0 as success.
* Fixes [#154](https://github.com/jasmine/jasmine-npm/issues/154).
* `Jasmine#onComplete` is no longer supported. To run code after execution
finishes, set the Jasmine instance's `exitOnCompletion` to false and use the
promise returned by `Jasmine#execute`. See the
[API reference for `execute`](https://jasmine.github.io/api/npm/4.0/Jasmine.html#execute)
for more information.
## New features and bugfixes
* Files listed in the `requires` config property can be ES modules
* Reporters specified with `--reporter=` can be ES modules.
* Allow use without creating globals.
* See .
* Fixes [jasmine/jasmine#1235](https://github.com/jasmine/jasmine/issues/1235).
* Autodiscover spec/support/jasmine.js as well as spec/support/jasmine.json.
* Moved `stopSpecOnExpectationFailure` and `random` to `env` in the sample
config generated by `jasmine init`.
* Top suite failures are included in the failure count displayed by the default
`ConsoleReporter`.
* Added support for the debug logging feature introduced in `jasmine-core` 4.0.0.
* Fixed handling of module paths containing `..` on OS X.
## Internal improvements
* Use the promise returned from `Env#execute` to determine when suite execution
is finished and obtain the overall result.
* Removed unnecessary code to filter Jasmine's frames from stack traces. The same
filtering has been done in jasmine-core since 3.0.
* Inlined loadConfig.js back into command.js to resolve naming conflicts.
## Supported environments
The jasmine NPM package has been tested on Node 12.17-12.22, 14, and 16.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/4.0.1.md 0000664 0000000 0000000 00000000631 15240143636 0021531 0 ustar 00root root 0000000 0000000 # Jasmine NPM 4.0.1 Release Notes
## Summary
This release fixes loading of files with nonstandard extensions (e.g. .jsx,
.coffee) in the default configuration by falling back to `require()` when
`import()` fails because of an unsupported file extension. See
[#188](https://github.com/jasmine/jasmine-npm/issues/188).
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/4.0.2.md 0000664 0000000 0000000 00000000774 15240143636 0021542 0 ustar 00root root 0000000 0000000 # Jasmine NPM 4.0.2 Release Notes
This release fixes two bugs related to reporter loading.
* Fixed loading of reporters in NPM packages (i.e. not a file path) in the
default configuration
* Fixes [#189](https://github.com/jasmine/jasmine-npm/issues/189)
* The `jsLoader` configuration setting is followed when loading reporters
* Merges [#190](https://github.com/jasmine/jasmine-npm/pull/190) from @ffortier
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/4.1.0.md 0000664 0000000 0000000 00000000467 15240143636 0021540 0 ustar 00root root 0000000 0000000 # Jasmine NPM 4.1.0 Release Notes
This release updates the jasmine-core dependency to 4.1.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/4.1.0.md)
for more information.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/4.2.0.md 0000664 0000000 0000000 00000000640 15240143636 0021532 0 ustar 00root root 0000000 0000000 # Jasmine NPM 4.2.0 Release Notes
This release updates the jasmine-core dependency to 4.2.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/4.2.0.md)
for more information.
## Supported environments
The jasmine NPM package has been tested on Node 12.17-12.22, 14, 16, and 18.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/4.2.1.md 0000664 0000000 0000000 00000000653 15240143636 0021537 0 ustar 00root root 0000000 0000000 # Jasmine NPM 4.2.1 Release Notes
## Bug Fixes
* Fixed the `--helper` option
* Merges [#198](https://github.com/jasmine/jasmine-npm/pull/198) from @lucaswerkmeister
* Fixes [#197](https://github.com/jasmine/jasmine-npm/issues/197)
## Supported environments
The jasmine package has been tested on Node 12.17-12.22, 14, 16, and 18.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/4.3.0.md 0000664 0000000 0000000 00000001656 15240143636 0021543 0 ustar 00root root 0000000 0000000 # Jasmine NPM 4.3.0 Release Notes
This release updates the jasmine-core dependency to 4.3.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/4.3.0.md)
for more information.
# New features
* Added a config option to disable listing pending specs when there are failures
* This can make failure output easier to read when there are also a number of
pending specs. To use this feature, add `alwaysListPendingSpecs: false` to
the config file or call `.alwaysListPendingSpecs(false)` on the `Jasmine`
instance.
## Documentation updates
* Added a contributing guide
* Copied CODE_OF_CONDUCT from core repo
## Internal improvements
* Converted `Jasmine` and `Loader` to ES6 classes
## Supported environments
The jasmine NPM package has been tested on Node 12.17-12.22, 14, 16, and 18.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/4.4.0.md 0000664 0000000 0000000 00000000640 15240143636 0021534 0 ustar 00root root 0000000 0000000 # Jasmine NPM 4.4.0 Release Notes
This release updates the jasmine-core dependency to 4.4.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/4.4.0.md)
for more information.
## Supported environments
The jasmine NPM package has been tested on Node 12.17-12.22, 14, 16, and 18.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/4.5.0.md 0000664 0000000 0000000 00000002121 15240143636 0021531 0 ustar 00root root 0000000 0000000 # Jasmine NPM 4.5.0 Release Notes
This release updates the jasmine-core dependency to 4.5.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/4.5.0.md)
for more information.
## New Features
* Warn when backslashes are used in paths/globs on Windows
* Backslashes behave inconsistently between OSes in the version of glob
that Jasmine currently uses. The next major version of glob will treat
them as escape sequences rather than path separators on all OSes.
* Allow instantiated reporters to be provided in the configuration
* This supports more complex scenarios than the --reporter= CLI flag
(multiple reporters, reporters that need configuration, reporters
that aren't default exports, etc) without requiring a switch to programmatic
usage.
## Documentation Improvements
* Fixed default value of Configuration#alwaysListPendingSpecs
## Supported environments
The jasmine NPM package has been tested on Node 12.17-12.22, 14, 16, and 18.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/4.6.0.md 0000664 0000000 0000000 00000000641 15240143636 0021537 0 ustar 00root root 0000000 0000000 # Jasmine NPM 4.6.0 Release Notes
This release updates the jasmine-core dependency to 4.6.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/4.6.0.md)
for more information.
## Supported environments
The jasmine NPM package has been tested on Node 12.17-12.22, 14, 16, and 18.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.0.0-alpha.0.md 0000664 0000000 0000000 00000002076 15240143636 0022757 0 ustar 00root root 0000000 0000000 # Jasmine 5.0.0-alpha.0 Release Notes
## Summary
This release adds support for parallel execution and updates file glob handling.
See the
[parallel documentation](https://jasmine.github.io/tutorials/running_specs_in_parallel)
for more information about that feature. Please also read the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/5.0/release_notes/5.0.0-alpha.0.md)
for information about changes in that package, including breaking changes.
## Breaking changes
* Node versions older than 16.14 are no longer supported.
* Backslashes in the `specFiles` and `helperFiles` configuration properties are
interpreted as the start of escape sequences on all OSes. Previous versions
of Jasmine used a version of the `glob` package that treated them as directory
separators on Windows and the start of escape sequences on other OSes.
## New features
* Support for parallel execution
## Supported environments
The jasmine package has been tested on 16.14+, and 18.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.0.0-alpha.1.md 0000664 0000000 0000000 00000001142 15240143636 0022751 0 ustar 00root root 0000000 0000000 # Jasmine 5.0.0-alpha.1 Release Notes
## Breaking changes
* Unknown args of the form `--foo=bar` are treated as errors, rather than a request
to set the env variable `--foo` to `bar`.
* `--parallel=1` is an error.
## New features and bug fixes
* Reporter errors are handled in parallel mode
* The underlying exception is included in in ESM import exceptions
## Internal improvements
* Updated to Glob 9
* Updated dev dependencies
## Supported environments
The jasmine package has been tested on 16.14+, and 18.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.0.0-beta.0.md 0000664 0000000 0000000 00000002554 15240143636 0022606 0 ustar 00root root 0000000 0000000 # Jasmine 5.0.0-beta.0 Release Notes
This release adds the final pieces of support for parallel execution. There may
be other changes before the final 5.0 release, but parallel support is now
considered feature-complete. Please
[open an issue](https://github.com/jasmine/jasmine-npm/issues/new) if you think
anything's missing.
## Breaking changes
* Dropped support for Node 16
## New Features
* Added support for Node 20
* Parallel: Report unhandled exceptions/rejections that occur between spec files
* Parallel: `--parallel=auto` runs with an inferred number of workers
The number of workers will be one less than the number of CPUs reported by
Node. This is a reasonable default in most situations but may work poorly
inside containers, since the number of CPUs reported by Node is based on the
host machine's hardware and not the resources actually available in the
container. Inside a container you are likely to get better results by
explicitly specifying a number of workers instead, e.g. `--parallel=4`.
* Parallel: Support use without globals
To use this feature, include `globals: false` in the options passed to the
[ParallelRunner constructor](https://jasmine.github.io/api/npm/5.0.0-beta.0/ParallelRunner.html).
## Internal Improvements
* Updated to Glob 10
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.0.0.md 0000664 0000000 0000000 00000002557 15240143636 0021542 0 ustar 00root root 0000000 0000000 # Jasmine NPM 5.0.0 Release Notes
## Summary
This is a major release that includes breaking changes. It primarily adds
support for parallel execution. Most users should be able to upgrade without
changes, but please read the list of breaking changes below and see the
[migration guide](https://jasmine.github.io/tutorials/upgrading_to_Jasmine_5.0)
for more information. Be sure to read the release notes for `jasmine-core`
5.0.0 as well.
## Breaking changes
* Dropped support for Node 12, 14, and 16
* Unknown CLI args of the form --foo=bar are treated as errors, not env vars
* Backslashes in file globs (e.g. `spec_files`) are treated as escape characters
on all platforms. Previously they were treated as directory separators on
Windows and escape characters elsewhere.
## New features
* Support for parallel execution
See the [parallel guide](https://jasmine.github.io/tutorials/running_specs_in_parallel)
for more information.
* Support for Node 20
* Include the underlying exception in ESM import exceptions
## Bug fixes
* Fixed handling of special Glob syntax in project base dirs
* Fixes [#206](https://github.com/jasmine/jasmine-npm/issues/206)
## Internal improvements
* Updated dev dependencies
## Supported environments
This package has been tested on Node 18 and 20.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.0.1.md 0000664 0000000 0000000 00000000542 15240143636 0021533 0 ustar 00root root 0000000 0000000 # Jasmine 5.0.1 Release Notes
## Changes
* Fixed state leak between multiple Jasmine instances run consecutively
Fixes [#207](https://github.com/jasmine/jasmine-npm/issues/207)
## Supported environments
The jasmine package has been tested on Node 18 and 20.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.0.2.md 0000664 0000000 0000000 00000000522 15240143636 0021532 0 ustar 00root root 0000000 0000000 # Jasmine 5.0.2 Release Notes
## Changes
* Fixed error when using the --require CLI argument
* Fixes [#208](https://github.com/jasmine/jasmine-npm/issues/208)
## Supported environments
The jasmine package has been tested on Node 18 and 20.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.1.0.md 0000664 0000000 0000000 00000001643 15240143636 0021536 0 ustar 00root root 0000000 0000000 # Jasmine 5.1.0 Release Notes
This release updates the jasmine-core dependency to 5.1.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.1.0.md)
for more information.
## Bug Fixes
* Issue a deprecation warning if both jasmine.js and jasmine.json are found
Jasmine incorrectly loads both files if they're both found. This will be
fixed in the next major release.
* Fixed support for importing namespaced modules e.g. @serenity-js/jasmine
Fixes [#199](https://github.com/jasmine/jasmine-npm/issues/199)
Merges [#209](https://github.com/jasmine/jasmine-npm/pull/209) from @jan-molak
* Fixed config file detection when the Testdouble loader and possibly other
custom ES module loaders are used
## Supported environments
The jasmine package has been tested on Node 18 and 20.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.10.0.md 0000664 0000000 0000000 00000001106 15240143636 0021610 0 ustar 00root root 0000000 0000000 # Jasmine 5.10.0 Release Notes
This release updates the jasmine-core dependency to 5.10.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.10.0.md)
for more information.
## Supported environments
This version has been tested on Node 18.20.5*, 20, 22, and 24.
\* Environments that are past end of life are supported on a best-effort basis.
They may be dropped in a future minor release of Jasmine if continued support
becomes impractical.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.11.0.md 0000664 0000000 0000000 00000001106 15240143636 0021611 0 ustar 00root root 0000000 0000000 # Jasmine 5.11.0 Release Notes
This release updates the jasmine-core dependency to 5.11.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.11.0.md)
for more information.
## Supported environments
This version has been tested on Node 18.20.5*, 20, 22, and 24.
\* Environments that are past end of life are supported on a best-effort basis.
They may be dropped in a future minor release of Jasmine if continued support
becomes impractical.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.12.0.md 0000664 0000000 0000000 00000001105 15240143636 0021611 0 ustar 00root root 0000000 0000000 # Jasmine 5.12.0 Release Notes
This release updates the jasmine-core dependency to 5.12.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.12.0.md)
for more information.
## Supported environments
This version has been tested on Node 18.20.5*, 20, 22, and 24.
\* Environments that are past end of life are supported on a best-effort basis.
They may be dropped in a future minor release of Jasmine if continued support
becomes impractical.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.13.0.md 0000664 0000000 0000000 00000001105 15240143636 0021612 0 ustar 00root root 0000000 0000000 # Jasmine 5.13.0 Release Notes
This release updates the jasmine-core dependency to 5.13.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.13.0.md)
for more information.
## Supported environments
This version has been tested on Node 18.20.5*, 20, 22, and 24.
\* Environments that are past end of life are supported on a best-effort basis.
They may be dropped in a future minor release of Jasmine if continued support
becomes impractical.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.2.0.md 0000664 0000000 0000000 00000001570 15240143636 0021536 0 ustar 00root root 0000000 0000000 # Jasmine 5.2.0 Release Notes
This release updates the jasmine-core dependency to 5.2.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.2.0.md)
for more information.
## New Features
* Wrap help text to the terminal width
* --verbose flag to print configuration debugging info
* Fixes [#211](https://github.com/jasmine/jasmine-npm/issues/211).
## Bug Fixes
* Report parallel spec loading errors as suite errors rather than terminating early
* Removed excess logging when parallel execution terminates early
## Documentation Improvements
* Added Node 22 to supported environments
* Fixed API docs for Runner#loadConfigFile
* Removed obsolete bits from README
## Supported environments
This version has been tested on Node 18, 20, and 22.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.3.0.md 0000664 0000000 0000000 00000000454 15240143636 0021537 0 ustar 00root root 0000000 0000000 # Jasmine 5.3.0 Release Notes
This release updates the jasmine-core dependency to 5.3.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.3.0.md)
for more information.
## Supported environments
This version has been tested on Node 18, 20, and 22.
jasmine-jasmine-npm-3c2955c/release_notes/5.3.1.md 0000664 0000000 0000000 00000000445 15240143636 0021540 0 ustar 00root root 0000000 0000000 # Jasmine 5.3.1 Release Notes
This release fixes an error when reporting expectation results involving
non-serializable objects in parallel mode. See
[#212](https://github.com/jasmine/jasmine-npm/issues/212).
## Supported environments
This version has been tested on Node 18, 20, and 22.
jasmine-jasmine-npm-3c2955c/release_notes/5.4.0.md 0000664 0000000 0000000 00000000454 15240143636 0021540 0 ustar 00root root 0000000 0000000 # Jasmine 5.4.0 Release Notes
This release updates the jasmine-core dependency to 5.4.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.4.0.md)
for more information.
## Supported environments
This version has been tested on Node 18, 20, and 22.
jasmine-jasmine-npm-3c2955c/release_notes/5.5.0.md 0000664 0000000 0000000 00000000636 15240143636 0021543 0 ustar 00root root 0000000 0000000 # Jasmine 5.5.0 Release Notes
This release updates the jasmine-core dependency to 5.5.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.5.0.md)
for more information.
## Changes
* Support and generate .mjs config files
* Set forbidDuplicateNames: true in newly generated configs
## Supported environments
This version has been tested on Node 18, 20, and 22.
jasmine-jasmine-npm-3c2955c/release_notes/5.6.0.md 0000664 0000000 0000000 00000000453 15240143636 0021541 0 ustar 00root root 0000000 0000000 # Jasmine 5.6.0 Release Notes
This release updates the jasmine-core dependency to 5.6.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.6.0.md)
for more information.
## Supported environments
This version has been tested on Node 18, 20, and 22.
jasmine-jasmine-npm-3c2955c/release_notes/5.7.0.md 0000664 0000000 0000000 00000001637 15240143636 0021547 0 ustar 00root root 0000000 0000000 # Jasmine 5.7.0 Release Notes
This release updates the jasmine-core dependency to 5.7.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.7.0.md)
for more information.
## New features and bug fixes
* Added `--filter-path=` option to do exact (non-regex) prefix filtering
* Updated help text to clarify that `--filter=` takes a regex
* Added `enumerate` subcommand to list suites and specs
## Internal improvements
* Removed mostly-unmaintained dev dependency 'temp'
* Updated to eslint 9
* Updated dev dependency shelljs
## Supported environments
This version has been tested on Node 18*, 20, and 22.
\* Environments that are past end of life are supported on a best-effort basis.
They may be dropped in a future minor release of Jasmine if continued support
becomes impractical.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.7.1.md 0000664 0000000 0000000 00000000710 15240143636 0021537 0 ustar 00root root 0000000 0000000 # Jasmine 5.7.1 Release Notes
## Bug fixes
* Fixed handling of spec filters that are RegExp instances
## Supported environments
This version has been tested on Node 18*, 20, and 22.
\* Environments that are past end of life are supported on a best-effort basis.
They may be dropped in a future minor release of Jasmine if continued support
becomes impractical.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.8.0.md 0000664 0000000 0000000 00000001263 15240143636 0021543 0 ustar 00root root 0000000 0000000 # Jasmine 5.8.0 Release Notes
This release updates the jasmine-core dependency to 5.8.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.8.0.md)
for more information.
## Documentation improvements
* Added Node 24 to supported environments
* Document that spec filter can be a RegExp
## Supported environments
This version has been tested on Node 18*, 20, 22, and 24.
\* Environments that are past end of life are supported on a best-effort basis.
They may be dropped in a future minor release of Jasmine if continued support
becomes impractical.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/5.9.0.md 0000664 0000000 0000000 00000001762 15240143636 0021550 0 ustar 00root root 0000000 0000000 # Jasmine 5.9.0 Release Notes
This release updates the jasmine-core dependency to 5.9.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/5.9.0.md)
for more information.
## Bug fixes
* Fixed startup hang when using ES module loaders in parallel mode
## Changes to supported platforms
* Node versions before 18.20.5 are no longer supported
Older 18.x versions might still work, but Jasmine is no longer tested in them
prior to release.
## Documentation improvements
* Fixed jsdoc description of Configuration#requires
## Internal improvements
* Removed shelljs and rimraf dev dependencies
## Supported environments
This version has been tested on Node 18.20.5*, 20, 22, and 24.
\* Environments that are past end of life are supported on a best-effort basis.
They may be dropped in a future minor release of Jasmine if continued support
becomes impractical.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/6.0.0-alpha.0.md 0000664 0000000 0000000 00000002612 15240143636 0022754 0 ustar 00root root 0000000 0000000 # Jasmine 6.0.0-alpha.0 Release Notes
This is a pre-release, intended to offer a preview of breaking changes and to
solicit feedback. It updates jasmine-core to 6.0.0-alpha.0. Please see the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/6.0.0-alpha.0.md)
for more information, including a list of breaking changes in that release.
## A Note About Pre-Release Compatibility
There may be additional breaking changes in future 6.0 pre-releases or in the
final 6.0 release. That's allowed by the semver specification, but users are
sometimes unpleasantly surprised by it.
NPM's implementation of carat version ranges assumes that subsequent
pre-releases and final releases are fully compatible with earlier pre-releases.
If your package.json contains `"jasmine": "^6.0.0-alpha.0`, NPM might install
any later 6.x version even though there is no guarantee of compatibility. If
that isn't ok, you should specify an exact pre-release version:
`"jasmine": "6.0.0-alpha.0"`.
## Changes to supported environments
* Node 18 is no longer supported.
## Breaking changes
* Only load one config file even if more than one is present.
# Internal improvements
* Dogfood the new default behavior of core `boot()`.
## Supported environments
This version has been tested on Node 20, 22, and 24.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/6.0.0-alpha.1.md 0000664 0000000 0000000 00000001040 15240143636 0022747 0 ustar 00root root 0000000 0000000 # Jasmine 6.0.0-alpha.1 Release Notes
This is a pre-release, intended to offer a preview of breaking changes and to
solicit feedback. It updates jasmine-core to 6.0.0-alpha.1. Please see the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/6.0.0-alpha.1.md)
for more information, including a list of breaking changes in that release.
## Supported environments
This version has been tested on Node 20, 22, and 24.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/6.0.0-alpha.2.md 0000664 0000000 0000000 00000000752 15240143636 0022761 0 ustar 00root root 0000000 0000000 # Jasmine 6.0.0-alpha.2 Release Notes
This is a pre-release, intended to offer a preview of breaking changes and to
solicit feedback. It updates jasmine-core to 6.0.0-alpha.2. Please see the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/6.0.0-alpha.2.md)
for more information.
## Supported environments
This version has been tested on Node 20, 22, and 24.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/6.0.0-beta.0.md 0000664 0000000 0000000 00000001531 15240143636 0022601 0 ustar 00root root 0000000 0000000 # Jasmine 6.0.0-beta.0 Release Notes
This is a pre-release, intended to offer a preview of breaking changes and to
solicit feedback. It updates jasmine-core to 6.0.0-beta.0. Please see the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/6.0.0-beta.0.md)
for more information.
## Breaking changes
* `ConsoleReporter` is no longer exported by this package. It has been moved to
[@jasminejs/reporters](https://github.com/jasmine/reporters/).
## New features
* Console reporter respects the `NO_COLOR` environment variable.
* Compatibility with glob 12 and 13 as well as 10 and 11. Glob 13 is
considerably smaller than previous versions.
## Supported environments
This version has been tested on Node 20, 22, and 24.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/6.0.0.md 0000664 0000000 0000000 00000002055 15240143636 0021534 0 ustar 00root root 0000000 0000000 # Jasmine NPM 6.0.0 Release Notes
## Summary
This is a major release that includes breaking changes. Please read the list of
breaking changes below and see the
[migration guide](https://jasmine.github.io/upgrade-guides/6.0)
for more information. Be sure to read the
[release notes for `jasmine-core` 6.0.0](https://github.com/jasmine/jasmine/blob/main/release_notes/6.0.0.md)
as well.
## Changes to supported environments
* Node 18 is no longer supported.
## Breaking changes
* Only the first config file is loaded when more than one is present.
* `ConsoleReporter` is no longer exported by this package. It has been moved to
[@jasminejs/reporters](https://github.com/jasmine/reporters/).
## New features
* Console reporter respects the `NO_COLOR` environment variable.
* Compatibility with glob 12 and 13 as well as 10 and 11. Glob 13 is
considerably smaller than previous versions.
## Supported environments
This package has been tested on Node 20, 22, and 24.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/6.1.0.md 0000664 0000000 0000000 00000000604 15240143636 0021533 0 ustar 00root root 0000000 0000000 # Jasmine 6.1.0 Release Notes
This release updates the jasmine-core dependency to 6.1.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/6.1.0.md)
for more information.
## Supported environments
This version has been tested on Node 20, 22, and 24.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/6.2.0.md 0000664 0000000 0000000 00000000604 15240143636 0021534 0 ustar 00root root 0000000 0000000 # Jasmine 6.2.0 Release Notes
This release updates the jasmine-core dependency to 6.2.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/6.2.0.md)
for more information.
## Supported environments
This version has been tested on Node 20, 22, and 24.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/6.3.0.md 0000664 0000000 0000000 00000000717 15240143636 0021542 0 ustar 00root root 0000000 0000000 # Jasmine 6.3.0 Release Notes
This release updates the jasmine-core dependency to 6.3.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/6.3.0.md)
for more information.
## Deprecations
* Deprecate config properties that duplicate env config
## Supported environments
This version has been tested on Node 20, 22, and 24.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/7.0.0-pre.0.md 0000664 0000000 0000000 00000000626 15240143636 0022461 0 ustar 00root root 0000000 0000000 # Jasmine 7.0.0-pre.0 Release Notes
This release updates the jasmine-core dependency to 7.0.0-pre.0. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/7.0.0-pre.0.md)
for more information.
## Supported environments
This version has been tested on Node 20, 22, and 24.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/7.0.0-pre.1.md 0000664 0000000 0000000 00000000626 15240143636 0022462 0 ustar 00root root 0000000 0000000 # Jasmine 7.0.0-pre.1 Release Notes
This release updates the jasmine-core dependency to 7.0.0-pre.1. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/7.0.0-pre.1.md)
for more information.
## Supported environments
This version has been tested on Node 20, 22, and 24.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/7.0.0-pre.2.md 0000664 0000000 0000000 00000002033 15240143636 0022455 0 ustar 00root root 0000000 0000000 # Jasmine 7.0.0-pre.2 Release Notes
This release updates the jasmine-core dependency to 7.0.0-pre.2. See the
[jasmine-core release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/7.0.0-pre.2.md)
for more information.
## Breaking changes
* Redundant configuration properties that were deprecated in 6.3.0 have been
removed. Use the corresponding env config properties instead, e.g.
`env.random` instead of `random`.
* The jsLoader config setting has been removed. The default loader now covers
most use cases for it. If you find that the default loader still doesn't meet
your needs, use a custom loader.
* `Jasmine#loadConfig` and `ParallelRunner#loadConfig` are now async.
## New features
* [Custom loaders](https://jasmine.github.io/api/npm/7.0.0-pre.2/Configuration.html#loader)
allow replacing the built-in module loading logic with your own.
## Supported environments
This version has been tested on Node 20, 22, and 24.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/release_notes/7.0.0.md 0000664 0000000 0000000 00000003661 15240143636 0021541 0 ustar 00root root 0000000 0000000 # Jasmine NPM 7.0.0 Release Notes
## Summary
This is a major release that includes breaking changes. It updates jasmine-core
to 7.0.0. In addition to the list of breaking changes below, be sure to read the
[release notes for `jasmine-core` 7.0.0](https://github.com/jasmine/jasmine/blob/main/release_notes/7.0.0.md).
You may also find the
[upgrade guide](https://jasmine.github.io/upgrade-guides/7.0) helpful.
## Breaking changes
* The `alwaysListPendingSpecs` config option is no longer supported. Set
`defaultReporter: { alwaysListPendingSpecs: ... }` instead. â€
* The redundant `showColor` and `alwaysListPendingSpecs` methods from the
`Jasmine` and `ParallelRunner` classes have been removed. Call
`.configureDefaultReporter()` with the `color` and/or `alwaysListPendingSpecs`
options set instead.â€
* Multiple calls to `Jasmine#alwaysListPendingSpecs` and
`ParallelRunner#alwaysListPendingSpecs` are no longer ignored. â€
* Redundant configuration properties that were deprecated in 6.3.0 have been
removed. Use the corresponding env config properties instead, e.g.
`env.random` instead of `random`.
* The jsLoader config setting has been removed. The default loader now covers
most use cases for it. If you find that the default loader still doesn't meet
your needs, use a custom loader.
* `Jasmine#loadConfig` and `ParallelRunner#loadConfig` are now async.
## New features
* `--list-not-applicable` CLI flag â€
* [Custom loaders](https://jasmine.github.io/api/npm/7.0/Configuration.html#loader)
allow replacing the built-in module loading logic with your own.
†New since 7.0.0-pre.2
## Supported environments
This version has been tested on Node 20*, 22, 24, and 26.
\* Supported on a best-effort basis. Support may be dropped if it becomes
impractical, and bugs affecting only this version may not be treated as release
blockers.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
jasmine-jasmine-npm-3c2955c/spec/ 0000775 0000000 0000000 00000000000 15240143636 0016651 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/command_spec.js 0000664 0000000 0000000 00000057712 15240143636 0021653 0 ustar 00root root 0000000 0000000 const fs = require('fs');
const path = require('path');
const os = require('os');
const Command = require('../lib/command');
const Loader = require("../lib/loader");
const projectBaseDir = 'spec/fixtures/sample_empty_project/';
const spec = path.join(projectBaseDir, 'spec');
function deleteDirectory(dir) {
if (fs.existsSync(dir)) {
const dirFiles = fs.readdirSync(dir);
dirFiles.forEach(function(file) {
const fullPath = path.join(dir, file);
if (fs.statSync(fullPath).isDirectory()) {
deleteDirectory(fullPath);
}
else if (fs.statSync(fullPath).isFile()) {
fs.unlinkSync(fullPath);
}
});
fs.rmdirSync(dir);
}
}
async function withValueForIsTTY(value, func) {
const wasTTY = process.stdout.isTTY;
try {
process.stdout.isTTY = value;
await func();
} finally {
process.stdout.isTTY = wasTTY;
}
}
describe('command', function() {
beforeEach(function() {
const examplesDir = path.resolve(path.join(__dirname, 'fixtures', 'example'));
fs.mkdirSync(projectBaseDir);
this.out = (function() {
let output = "";
return {
print: function(str) {
output += str + '\n';
},
getOutput: function() {
return output;
}
};
}());
const commonMethods = [
'loadConfigFile',
'execute',
'configureDefaultReporter',
'verbose',
'coreVersion',
'clearReporters',
'addReporter',
'addRequires',
'addMatchingHelperFiles'
];
this.fakeJasmine = jasmine.createSpyObj(
'jasmine',
[...commonMethods, 'seed', 'randomizeTests', 'configureEnv', 'enumerate']
);
this.fakeJasmine.loader = new Loader();
this.Jasmine = jasmine.createSpy('Jasmine')
.and.returnValue(this.fakeJasmine);
this.parallelRunner = jasmine.createSpyObj(
'parallelRunner',
commonMethods
);
this.parallelRunner.loader = new Loader();
this.ParallelRunner = jasmine.createSpy('ParallelRunner')
.and.returnValue(this.parallelRunner);
this.fakeJasmine.execute.and.returnValue(Promise.resolve());
this.command = new Command(projectBaseDir, examplesDir, {
print: this.out.print,
Jasmine: this.Jasmine,
ParallelRunner: this.ParallelRunner,
platform: () => 'Oberon'
});
});
afterEach(function() {
deleteDirectory(projectBaseDir);
});
describe('passing in environment variables', function() {
beforeEach(function () {
this.command.run(['node', 'bin/jasmine.js', 'TESTKEY=TESTVALUE']);
});
afterEach(function() {
delete process.env.TESTKEY;
});
it('should run with those environment variables', function() {
expect(process.env.TESTKEY).toBe('TESTVALUE');
});
});
describe('init', function() {
beforeEach(function() {
this.command.run(['node', 'bin/jasmine.js', 'init']);
});
it('creates setup folders and files for specs', function() {
expect(fs.existsSync(path.join(spec, 'support/', 'jasmine.mjs'))).toBe(true);
});
it('writes default settings to jasmine.mjs', function() {
const realJson = fs.readFileSync(path.join(spec, 'support/', 'jasmine.mjs'), 'utf-8');
const fixtureJson = fs.readFileSync(path.join(__dirname, '../', 'lib/', 'examples/', 'jasmine.mjs'), 'utf-8');
expect(realJson).toEqual(fixtureJson);
});
});
describe('version', function() {
beforeEach(function() {
this.fakeJasmine.coreVersion.and.returnValue('fake core version');
this.command.run(['node', 'bin/jasmine.js', 'version']);
});
it('displays the version of jasmine', function() {
const packageVersion = require('../package.json').version;
expect(this.out.getOutput()).toContain('jasmine v' + packageVersion);
});
it('displays the version of jasmine-core', function() {
expect(this.out.getOutput()).toContain('jasmine-core vfake core version');
});
});
describe('-v', function() {
beforeEach(function() {
this.fakeJasmine.coreVersion.and.returnValue('fake core version');
this.command.run(['node', 'bin/jasmine.js', '-v']);
});
it('displays the version of jasmine', function() {
const packageVersion = require('../package.json').version;
expect(this.out.getOutput()).toContain('jasmine v' + packageVersion);
});
it('displays the version of jasmine-core', function() {
expect(this.out.getOutput()).toContain('jasmine-core vfake core version');
});
});
describe('passing unknown options', function() {
beforeEach(function() {
this.exitCode = process.exitCode;
});
afterEach(function() {
process.exitCode = this.exitCode;
});
it('displays unknown options and usage', function() {
this.command.run(['node', 'bin/jasmine.js',
'--some-option', '--no-color', '--another-option', '--another=option'
]);
expect(this.out.getOutput()).toContain(
'Unknown options: --some-option, --another-option, --another=option'
);
expect(this.out.getOutput()).toContain('Usage');
expect(process.exitCode).toBe(1);
});
});
describe('--', function() {
it('skips anything after it', async function() {
await withValueForIsTTY(true, async function () {
await this.command.run(['node', 'bin/jasmine.js', '--', '--no-color']);
expect(this.out.getOutput()).toBe('');
expect(this.fakeJasmine.configureDefaultReporter)
.not.toHaveBeenCalledWith({color: false});
}.bind(this));
});
});
describe('examples', function() {
beforeEach(function() {
this.command.run(['node', 'bin/jasmine.js', 'examples']);
});
it('should create init files if they do not exist', function() {
expect(fs.existsSync(path.join(spec, 'jasmine_examples'))).toBe(true);
expect(fs.existsSync(path.join(projectBaseDir, 'lib', 'jasmine_examples'))).toBe(true);
expect(fs.existsSync(path.join(spec, 'helpers', 'jasmine_examples'))).toBe(true);
});
it('should copy files into the appropriate folder', function() {
expect(fs.existsSync(path.join(projectBaseDir, 'lib', 'jasmine_examples', 'Foo.js'))).toBe(true);
expect(fs.existsSync(path.join(projectBaseDir, 'lib', 'jasmine_examples', 'Bar.js'))).toBe(true);
expect(fs.existsSync(path.join(spec, 'jasmine_examples', 'FooSpec.js'))).toBe(true);
expect(fs.existsSync(path.join(spec, 'helpers', 'jasmine_examples', 'SpecHelper.js'))).toBe(true);
});
});
describe('running specs', function() {
beforeEach(function () {
this.originalConfigPath = process.env.JASMINE_CONFIG_PATH;
});
afterEach(function () {
if (this.originalConfigPath) {
process.env.JASMINE_CONFIG_PATH = this.originalConfigPath;
} else {
delete process.env.JASMINE_CONFIG_PATH;
}
});
function sharedRunBehavior(extraArg) {
beforeEach(function() {
this.run = async function(args) {
if (extraArg) {
args.push(extraArg);
}
await this.command.run(args);
};
});
it('should load the default config file', async function () {
await this.run(['node', 'bin/jasmine.js']);
expect(this.runner.loadConfigFile).toHaveBeenCalledWith(undefined);
});
it('should load a custom config file specified by env variable', async function () {
await this.run(['node', 'bin/jasmine.js', 'JASMINE_CONFIG_PATH=somewhere.json']);
expect(this.runner.loadConfigFile).toHaveBeenCalledWith('somewhere.json');
});
it('should load a custom config file specified by option', async function () {
await this.run(['node', 'bin/jasmine.js', '--config=somewhere.json']);
expect(this.runner.loadConfigFile).toHaveBeenCalledWith('somewhere.json');
});
it('should allow colors to be turned off', async function () {
await this.run(['node', 'bin/jasmine.js', '--no-color']);
expect(this.runner.configureDefaultReporter).toHaveBeenCalledWith({
color: false,
listNotApplicableSpecs: undefined
});
});
it('should be able to force colors to be turned on', async function () {
await withValueForIsTTY(undefined, async function () {
await this.run(['node', 'bin/jasmine.js', '--color']);
expect(this.runner.configureDefaultReporter).toHaveBeenCalledWith({
color: true,
listNotApplicableSpecs: undefined
});
}.bind(this));
});
it('allows listNotApplicableSpecs to be turned on', async function() {
await this.run(['node', 'bin/jasmine.js', '--list-not-applicable']);
expect(this.runner.configureDefaultReporter).toHaveBeenCalledWith({
listNotApplicableSpecs: true,
color: undefined,
});
});
it('does not enable verbose mode by default', async function() {
await this.run(['node', 'bin/jasmine.js']);
expect(this.runner.verbose).toHaveBeenCalledWith(false);
expect(this.runner.verbose).toHaveBeenCalledBefore(this.runner.loadConfigFile);
});
it('can enable verbose mode', async function() {
await this.run(['node', 'bin/jasmine.js', '--verbose']);
expect(this.runner.verbose).toHaveBeenCalledWith(true);
expect(this.runner.verbose).toHaveBeenCalledBefore(this.runner.loadConfigFile);
});
it('should execute the jasmine suite', async function () {
await this.run(['node', 'bin/jasmine.js']);
expect(this.runner.execute).toHaveBeenCalled();
});
it('should be able to run only specified specs', async function () {
await this.run(['spec/some/fileSpec.js', 'SOME_ENV=SOME_VALUE', '--no-color']);
expect(this.runner.execute).toHaveBeenCalledWith(['spec/some/fileSpec.js'], undefined);
});
it('should be able filter by spec name', async function () {
await this.run(['--filter=interesting spec']);
expect(this.runner.execute).toHaveBeenCalledWith(jasmine.any(Array), 'interesting spec');
});
it('should be able to add one helper pattern', async function () {
await this.run(['--helper=helpers/**/*.js']);
expect(this.runner.addMatchingHelperFiles).toHaveBeenCalledWith(['helpers/**/*.js']);
});
it('should be able to add many helper patterns', async function () {
await this.run(['--helper=helpers/**/*.js', '--helper=other.js']);
expect(this.runner.addMatchingHelperFiles).toHaveBeenCalledWith(['helpers/**/*.js', 'other.js']);
});
it('should not modify helper patterns if no argument given', async function () {
await this.run([]);
expect(this.runner.addMatchingHelperFiles).not.toHaveBeenCalled();
});
it('should be able to add one require', async function () {
await this.run(['--require=ts-node/require']);
expect(this.runner.addRequires).toHaveBeenCalledWith(['ts-node/require']);
});
it('should be able to add multiple requires', async function () {
await this.run(['--require=ts-node/require', '--require=@babel/register']);
expect(this.runner.addRequires).toHaveBeenCalledWith(['ts-node/require', '@babel/register']);
});
it('can specify a reporter', async function () {
const reporterPath = path.resolve(path.join(__dirname, 'fixtures', 'customReporter.js'));
const Reporter = require(reporterPath);
await this.run(['--reporter=' + reporterPath]);
expect(this.runner.clearReporters).toHaveBeenCalled();
expect(this.runner.addReporter).toHaveBeenCalledWith(jasmine.any(Reporter));
});
it('uses the provided loader to load reporters', async function () {
const reporterPath = path.resolve(path.join(__dirname, 'fixtures', 'customReporter.js'));
spyOn(this.runner.loader, 'load').and.callThrough();
await this.run(['--reporter=' + reporterPath]);
expect(this.runner.loader.load).toHaveBeenCalledWith(reporterPath);
});
it('can specify a reporter that is an ES module', async function () {
await this.run(['--reporter=./spec/fixtures/customReporter.mjs']);
expect(this.runner.clearReporters).toHaveBeenCalled();
expect(this.runner.addReporter.calls.argsFor(0)[0].isCustomReporterDotMjs).toBe(true);
});
describe('When the reporter path is relative', function () {
beforeEach(function () {
this.originalWd = process.cwd();
});
afterEach(function () {
process.chdir(this.originalWd);
});
it('evaluates the path based on the cwd', async function () {
const Reporter = require('./fixtures/customReporter.js');
process.chdir('spec/fixtures');
await this.run(['--reporter=./customReporter.js']);
expect(this.runner.clearReporters).toHaveBeenCalled();
expect(this.runner.addReporter).toHaveBeenCalledWith(jasmine.any(Reporter));
this.runner.clearReporters.calls.reset();
this.runner.addReporter.calls.reset();
process.chdir('example');
await this.run(['--reporter=../customReporter.js']);
expect(this.runner.clearReporters).toHaveBeenCalled();
expect(this.runner.addReporter).toHaveBeenCalledWith(jasmine.any(Reporter));
});
});
it('throws with context if the file does not export a reporter', async function () {
const reporterPath = path.resolve(path.join(__dirname, 'fixtures', 'badReporter.js'));
await expectAsync(
this.run(['--reporter=' + reporterPath])
).toBeRejectedWithError(new RegExp(
'Failed to instantiate reporter from ' +
escapeStringForRegexp(reporterPath) + '\nUnderlying error: .' +
'*Reporter is not a constructor'
));
expect(this.runner.clearReporters).not.toHaveBeenCalled();
expect(this.runner.addReporter).not.toHaveBeenCalled();
});
it('throws with context if the reporter file does not exist', async function () {
const reporterPath = path.resolve(path.join(__dirname, 'fixtures', 'missingReporter.js'));
await expectAsync(
this.run(['--reporter=' + reporterPath])
).toBeRejectedWithError(new RegExp(
'Failed to load reporter module ' +
escapeStringForRegexp(reporterPath) + '\nUnderlying error: ' +
'.*Cannot find module'
));
expect(this.runner.clearReporters).not.toHaveBeenCalled();
expect(this.runner.addReporter).not.toHaveBeenCalled();
});
}
it('runs in normal mode if --parallel is not specified', async function() {
await this.command.run(['node', 'bin/jasmine.js']);
expect(this.fakeJasmine.execute).toHaveBeenCalled();
expect(this.ParallelRunner).not.toHaveBeenCalled();
});
it('runs in parallel mode if --parallel is >1', async function() {
await this.command.run(['node', 'bin/jasmine.js', '--parallel=2']);
expect(this.fakeJasmine.execute).not.toHaveBeenCalled();
expect(this.ParallelRunner).toHaveBeenCalledWith({
projectBaseDir,
numWorkers: 2
});
expect(this.parallelRunner.execute).toHaveBeenCalled();
});
it('sets the number of workers to 1 less than CPUs if --paralell is auto', async function() {
await this.command.run(['node', 'bin/jasmine.js', '--parallel=auto']);
expect(this.fakeJasmine.execute).not.toHaveBeenCalled();
expect(this.ParallelRunner).toHaveBeenCalledWith({
projectBaseDir,
numWorkers: os.cpus().length - 1
});
expect(this.parallelRunner.execute).toHaveBeenCalled();
});
it('shows usage if --parallel is not a number', async function() {
this.command.run(['node', 'bin/jasmine.js', '--parallel=twelve']);
expect(this.out.getOutput()).toContain(
'Argument to --parallel= must be an integer greater than 1'
);
expect(this.out.getOutput()).toContain('Usage');
expect(process.exitCode).toBe(1);
});
it('shows usage if --parallel is not an integer', async function() {
this.command.run(['node', 'bin/jasmine.js', '--parallel=1.23']);
expect(this.out.getOutput()).toContain(
'Argument to --parallel= must be an integer greater than 1'
);
expect(this.out.getOutput()).toContain('Usage');
expect(process.exitCode).toBe(1);
});
it('shows usage if --parallel is 1', async function() {
await this.command.run(['node', 'bin/jasmine.js', '--parallel=1']);
expect(this.out.getOutput()).toContain(
'Argument to --parallel= must be an integer greater than 1'
);
expect(this.out.getOutput()).toContain('Usage');
expect(process.exitCode).toBe(1);
});
it('shows usage if --parallel is not positive', async function() {
this.command.run(['node', 'bin/jasmine.js', '--parallel=0']);
expect(this.out.getOutput()).toContain(
'Argument to --parallel= must be an integer greater than 1'
);
expect(this.out.getOutput()).toContain('Usage');
expect(process.exitCode).toBe(1);
});
describe('In normal mode', function () {
beforeEach(function() {
this.runner = this.fakeJasmine;
});
sharedRunBehavior();
it('uses jasmine-core defaults if random is unspecified', async function () {
await this.run([]);
expect(this.runner.randomizeTests).not.toHaveBeenCalled();
});
it('should be able to turn on random tests', async function () {
await this.run(['--random=true']);
expect(this.runner.randomizeTests).toHaveBeenCalledWith(true);
});
it('should be able to turn off random tests', async function () {
await this.run(['--random=false']);
expect(this.runner.randomizeTests).toHaveBeenCalledWith(false);
});
it('should not configure seed by default', async function () {
await this.run([]);
expect(this.runner.seed).not.toHaveBeenCalled();
});
it('should be able to set a seed', async function () {
await this.run(['--seed=12345']);
expect(this.runner.seed).toHaveBeenCalledWith('12345');
});
it('should not configure fail fast by default', async function () {
await this.run([]);
expect(this.runner.configureEnv).not.toHaveBeenCalledWith(jasmine.objectContaining({
stopOnSpecFailure: jasmine.anything()
}));
expect(this.runner.configureEnv).not.toHaveBeenCalledWith(jasmine.objectContaining({
stopSpecOnExpectationFailure: jasmine.anything()
}));
});
it('should be able to turn on fail fast', async function () {
await this.run(['--fail-fast']);
expect(this.runner.configureEnv).toHaveBeenCalledWith({
stopOnSpecFailure: true,
stopSpecOnExpectationFailure: true
});
});
describe('Path filtering', function() {
it('should be able to filter by path', async function () {
await this.run(['--filter-path=["a","b","c"]']);
expect(this.runner.execute).toHaveBeenCalledWith(jasmine.any(Array),
{path: ['a', 'b', 'c']});
});
it('rejects invalid JSON', async function() {
await this.run(['--filter-path=not valid JSON']);
const output = this.out.getOutput();
expect(output).toContain('Invalid filter path: not valid JSON');
});
it('rejects non-arrays', async function() {
await this.run(['--filter-path={}}']);
const output = this.out.getOutput();
expect(output).toContain('Invalid filter path: {}}');
});
});
});
describe('In parallel mode', function() {
beforeEach(function() {
this.runner = this.parallelRunner;
});
sharedRunBehavior('--parallel=2');
it('rejects --filter-path', async function() {
await this.run(['--filter-path=[]', '--parallel=2']);
const output = this.out.getOutput();
expect(output).toContain(
'--filter-path is not supported in parallel mode.');
});
});
});
describe('enumerate', function() {
it('outputs the result of enumerating specs', async function() {
const result = [{type: 'spec', description: 'foo'}];
this.fakeJasmine.enumerate.and.returnValue(result);
await this.command.run(['enumerate']);
expect(JSON.parse(this.out.getOutput())).toEqual(result);
});
});
describe('Path handling', function() {
describe('On Windows', function () {
beforeEach(function() {
this.deps = {
print: this.out.print,
platform: () => 'win32',
Jasmine: this.Jasmine,
ParallelRunner: this.ParallelRunner,
};
});
it('replaces backslashes in the project base dir with slashes', function() {
const subject = new Command('foo\\bar', '', this.deps);
expect(subject.projectBaseDir).toEqual('foo/bar');
expect(subject.specDir).toEqual('foo/bar/spec');
});
it('replaces backslashes in spec file paths from the command line', async function() {
const subject = new Command('arbitrary', '', this.deps);
await subject.run(['somedir\\somespec.js']);
expect(this.fakeJasmine.execute).toHaveBeenCalledWith(['somedir/somespec.js'], undefined);
});
});
describe('On non-Windows systems', function () {
beforeEach(function() {
this.deps = {
print: this.out.print,
platform: () => 'BeOS',
Jasmine: this.Jasmine,
ParallelRunner: this.ParallelRunner,
};
});
it('does not replace backslashes in the project base dir', function() {
const subject = new Command('foo\\bar', '', this.deps);
expect(subject.projectBaseDir).toEqual('foo\\bar');
expect(subject.specDir).toEqual('foo\\bar/spec');
});
it('does not replace backslashes in spec file paths from the command line', async function() {
const subject = new Command('arbitrary', '', this.deps);
await subject.run(['somedir\\somespec.js']);
expect(this.fakeJasmine.execute).toHaveBeenCalledWith(['somedir\\somespec.js'], undefined);
});
});
});
describe('help', function() {
it('wraps text to the terminal width', async function() {
this.command = new Command(projectBaseDir, '', {
print: this.out.print,
terminalColumns: 50,
platform() {
return 'arbitrary';
}
});
await this.command.run(['help']);
const output = this.out.getOutput();
expect(output).toContain('version,-v show jasmine and jasmine-core\n' +
' versions\n');
expect(output).toContain(
'\n' +
' --parallel=auto Run in parallel with an\n' +
' automatically chosen\n' +
' number of workers\n'
);
expect(output).toContain('The given arguments take precedence over options\n' +
'in your jasmine.json.\n' +
'The path to your optional jasmine.json can also be\n' +
'configured by setting the JASMINE_CONFIG_PATH\n' +
'environment variable.\n');
});
it('wraps text to 80 columns when the terminal width is unknown', function() {
this.command = new Command(projectBaseDir, '', {
print: this.out.print,
terminalColumns: undefined,
platform() {
return 'arbitrary';
}
});
this.command.run(['help']);
const output = this.out.getOutput();
expect(output).toContain(
'\n' +
' --parallel=auto Run in parallel with an automatically chosen number of\n' +
' workers\n');
});
});
});
// Adapted from Sindre Sorhus's escape-string-regexp (MIT license)
function escapeStringForRegexp(string) {
// Escape characters with special meaning either inside or outside character sets.
// Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.
return string
.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
.replace(/-/g, '\\x2d');
}
jasmine-jasmine-npm-3c2955c/spec/filters/ 0000775 0000000 0000000 00000000000 15240143636 0020321 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/filters/regex_spec_filter_spec.js 0000664 0000000 0000000 00000002360 15240143636 0025363 0 ustar 00root root 0000000 0000000 const regexSpecFilter = require('../../lib/filters/regex_spec_filter');
describe("regexSpecFilter", function() {
it("should match when no string is provided", function() {
const specFilter = regexSpecFilter();
expect(specFilter({ getFullName: () => "foo" })).toBe(true);
expect(specFilter({ getFullName: () => "*bar" })).toBe(true);
});
it("should match the provided string", function() {
const specFilter = regexSpecFilter("foo?");
expect(specFilter({ getFullName: () => "foo"})).toBe(true);
expect(specFilter({ getFullName: () => "fo"})).toBe(true);
expect(specFilter({ getFullName: () => "bar"})).toBe(false);
});
it("should match the provided regex", function() {
const specFilter = regexSpecFilter(/foo?/);
expect(specFilter({ getFullName: () => "foo"})).toBe(true);
expect(specFilter({ getFullName: () => "fo"})).toBe(true);
expect(specFilter({ getFullName: () => "bar"})).toBe(false);
});
it("should match by part of spec name", function() {
const specFilter = regexSpecFilter("ba");
expect(specFilter({ getFullName: () => "foo"})).toBe(false);
expect(specFilter({ getFullName: () => "bar"})).toBe(true);
expect(specFilter({ getFullName: () => "baz"})).toBe(true);
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/ 0000775 0000000 0000000 00000000000 15240143636 0020522 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/badReporter.js 0000664 0000000 0000000 00000000000 15240143636 0023317 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/cjs-load-exception/ 0000775 0000000 0000000 00000000000 15240143636 0024212 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/cjs-load-exception/jasmine.json 0000664 0000000 0000000 00000000126 15240143636 0026532 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": [
"throws_on_load.js"
],
"helpers": []
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/cjs-load-exception/throws_on_load.js 0000664 0000000 0000000 00000000031 15240143636 0027563 0 ustar 00root root 0000000 0000000 throw new Error("nope");
jasmine-jasmine-npm-3c2955c/spec/fixtures/cjs-syntax-error/ 0000775 0000000 0000000 00000000000 15240143636 0023754 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/cjs-syntax-error/jasmine.json 0000664 0000000 0000000 00000000124 15240143636 0026272 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": [
"syntax_error.js"
],
"helpers": []
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/cjs-syntax-error/syntax_error.js 0000664 0000000 0000000 00000000012 15240143636 0027042 0 ustar 00root root 0000000 0000000 function(
jasmine-jasmine-npm-3c2955c/spec/fixtures/custom-loader/ 0000775 0000000 0000000 00000000000 15240143636 0023300 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/custom-loader/aSpec.js 0000664 0000000 0000000 00000000052 15240143636 0024666 0 ustar 00root root 0000000 0000000 throw new Error('wrong file was loaded');
jasmine-jasmine-npm-3c2955c/spec/fixtures/custom-loader/contentsOfASpec.js 0000664 0000000 0000000 00000000137 15240143636 0026675 0 ustar 00root root 0000000 0000000 describe('a spec', function() {
it('fails', function() {
expect(1).toEqual(2);
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/custom-loader/jasmine.json 0000664 0000000 0000000 00000000127 15240143636 0025621 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["aSpec.js"],
"loader": "./myCustomLoader.js"
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/custom-loader/myCustomLoader.js 0000664 0000000 0000000 00000000627 15240143636 0026612 0 ustar 00root root 0000000 0000000 console.log('loaded myCustomLoader.js');
module.exports = async function myCustomLoader(path) {
if (path.endsWith('.json')) {
return new Promise(resolve => resolve(require(path)));
} else if (path.endsWith('/aSpec.js')) {
return await import('./contentsOfASpec.js');
} else {
const e = new Error(`Don't know how to load ${path}`);
e.code = 'ERR_MODULE_NOT_FOUND';
throw e;
}
};
jasmine-jasmine-npm-3c2955c/spec/fixtures/customReporter.js 0000664 0000000 0000000 00000000047 15240143636 0024116 0 ustar 00root root 0000000 0000000 module.exports = function Report() {};
jasmine-jasmine-npm-3c2955c/spec/fixtures/customReporter.mjs 0000664 0000000 0000000 00000000275 15240143636 0024276 0 ustar 00root root 0000000 0000000 export default function Reporter() {}
Reporter.prototype.jasmineDone = function() {
console.log('customReporter.mjs jasmineDone');
};
Reporter.prototype.isCustomReporterDotMjs = true; jasmine-jasmine-npm-3c2955c/spec/fixtures/defaultProgrammaticFail.js 0000664 0000000 0000000 00000000210 15240143636 0025637 0 ustar 00root root 0000000 0000000 const Jasmine = require('../..');
const jasmine = new Jasmine();
it('fails', function() {
expect(1).toBe(2);
});
jasmine.execute();
jasmine-jasmine-npm-3c2955c/spec/fixtures/dontExitOnCompletion.js 0000664 0000000 0000000 00000000362 15240143636 0025206 0 ustar 00root root 0000000 0000000 const Jasmine = require('../..');
const jasmine = new Jasmine();
it('a spec', function() {});
jasmine.exitOnCompletion = false;
jasmine.execute().finally(function() {
setTimeout(function() {
console.log("in setTimeout cb");
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/env-config/ 0000775 0000000 0000000 00000000000 15240143636 0022555 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/env-config/aSpec.js 0000664 0000000 0000000 00000000147 15240143636 0024150 0 ustar 00root root 0000000 0000000 for (let i = 1; i <= 5; i++) {
it('spec ' + i, function() {
console.log('in spec ' + i);
});
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/env-config/jasmine.json 0000664 0000000 0000000 00000000130 15240143636 0025070 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["aSpec.js"],
"env": {
"random": false
}
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-importing-commonjs-syntax-error/ 0000775 0000000 0000000 00000000000 15240143636 0027612 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-importing-commonjs-syntax-error/intermediate.js 0000664 0000000 0000000 00000000033 15240143636 0032616 0 ustar 00root root 0000000 0000000 require('./syntax_error');
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-importing-commonjs-syntax-error/jasmine.json 0000664 0000000 0000000 00000000115 15240143636 0032130 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": [
"spec.mjs"
],
"helpers": []
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-importing-commonjs-syntax-error/spec.mjs 0000664 0000000 0000000 00000000043 15240143636 0031254 0 ustar 00root root 0000000 0000000 await import('./intermediate.js');
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-importing-commonjs-syntax-error/syntax_error.js 0000664 0000000 0000000 00000000002 15240143636 0032677 0 ustar 00root root 0000000 0000000 {
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-indirect-error/ 0000775 0000000 0000000 00000000000 15240143636 0024234 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-indirect-error/jasmine.json 0000664 0000000 0000000 00000000115 15240143636 0026552 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": [
"spec.mjs"
],
"helpers": []
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-indirect-error/spec.mjs 0000664 0000000 0000000 00000000060 15240143636 0025675 0 ustar 00root root 0000000 0000000 import './throws.mjs';
it('a spec', () => {});
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-indirect-error/throws.mjs 0000664 0000000 0000000 00000000031 15240143636 0026267 0 ustar 00root root 0000000 0000000 throw new Error('nope');
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-load-exception/ 0000775 0000000 0000000 00000000000 15240143636 0024217 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-load-exception/jasmine.json 0000664 0000000 0000000 00000000127 15240143636 0026540 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": [
"throws_on_load.mjs"
],
"helpers": []
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-load-exception/throws_on_load.mjs 0000664 0000000 0000000 00000000031 15240143636 0027745 0 ustar 00root root 0000000 0000000 throw new Error("nope");
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-reporter-packagejson/ 0000775 0000000 0000000 00000000000 15240143636 0025431 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-reporter-packagejson/customReporter.js 0000664 0000000 0000000 00000000212 15240143636 0031017 0 ustar 00root root 0000000 0000000 export default function Reporter() {}
Reporter.prototype.jasmineDone = function() {
console.log('customReporter.js jasmineDone');
};
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-reporter-packagejson/jasmine.json 0000664 0000000 0000000 00000000055 15240143636 0027752 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": [
]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-reporter-packagejson/package.json 0000664 0000000 0000000 00000000027 15240143636 0027716 0 ustar 00root root 0000000 0000000 {
"type": "module"
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-syntax-error/ 0000775 0000000 0000000 00000000000 15240143636 0023761 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-syntax-error/jasmine.json 0000664 0000000 0000000 00000000125 15240143636 0026300 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": [
"syntax_error.mjs"
],
"helpers": []
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm-syntax-error/syntax_error.mjs 0000664 0000000 0000000 00000000012 15240143636 0027224 0 ustar 00root root 0000000 0000000 function(
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm/ 0000775 0000000 0000000 00000000000 15240143636 0021306 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/esm/commonjs_helper.js 0000664 0000000 0000000 00000000100 15240143636 0025017 0 ustar 00root root 0000000 0000000 console.log('commonjs_helper');
require('./commonjs_sentinel');
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm/commonjs_sentinel.js 0000664 0000000 0000000 00000000101 15240143636 0025362 0 ustar 00root root 0000000 0000000 // An empty module that we can require, to see if require works.
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm/commonjs_spec.js 0000664 0000000 0000000 00000000227 15240143636 0024504 0 ustar 00root root 0000000 0000000 describe('A spec file ending in .js', function() {
it('is required as a commonjs module', function() {
require('./commonjs_sentinel');
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm/esm_helper.mjs 0000664 0000000 0000000 00000000070 15240143636 0024141 0 ustar 00root root 0000000 0000000 import './esm_sentinel.mjs';
console.log('esm_helper');
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm/esm_sentinel.mjs 0000664 0000000 0000000 00000000120 15240143636 0024477 0 ustar 00root root 0000000 0000000 // An empty module that will fail if loaded via require(), due to its extension
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm/esm_spec.mjs 0000664 0000000 0000000 00000000544 15240143636 0023622 0 ustar 00root root 0000000 0000000 describe('A spec file ending in .mjs', function() {
it('is imported as an es module', function() {
// Node probably threw already if we tried to require this file,
// but check anyway just to be sure.
expect(function() {
require('./commonjs_sentinel');
}).toThrowError(/require is not defined/);
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm/jasmine.mjs 0000664 0000000 0000000 00000000447 15240143636 0023454 0 ustar 00root root 0000000 0000000 const config = {
"spec_dir": ".",
"spec_files": [
"commonjs_spec.js",
"esm_spec.mjs"
],
"helpers": [
"name_reporter.js",
"commonjs_helper.js",
"esm_helper.mjs"
],
"stopSpecOnExpectationFailure": false,
"env": {
"random": false
}
};
export default config;
jasmine-jasmine-npm-3c2955c/spec/fixtures/esm/name_reporter.js 0000664 0000000 0000000 00000000267 15240143636 0024513 0 ustar 00root root 0000000 0000000 console.log('name_reporter');
beforeAll(function() {
jasmine.getEnv().addReporter({
specStarted: function (event) {
console.log('Spec:', event.fullName);
}
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/example/ 0000775 0000000 0000000 00000000000 15240143636 0022155 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/example/lib/ 0000775 0000000 0000000 00000000000 15240143636 0022723 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/example/lib/jasmine_examples/ 0000775 0000000 0000000 00000000000 15240143636 0026247 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/example/lib/jasmine_examples/Bar.js 0000664 0000000 0000000 00000000000 15240143636 0027277 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/example/lib/jasmine_examples/Foo.js 0000664 0000000 0000000 00000000000 15240143636 0027316 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/example/spec/ 0000775 0000000 0000000 00000000000 15240143636 0023107 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/example/spec/helpers/ 0000775 0000000 0000000 00000000000 15240143636 0024551 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/example/spec/helpers/jasmine_examples/ 0000775 0000000 0000000 00000000000 15240143636 0030075 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/example/spec/helpers/jasmine_examples/SpecHelper.js 0000664 0000000 0000000 00000000000 15240143636 0032453 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/example/spec/jasmine_examples/ 0000775 0000000 0000000 00000000000 15240143636 0026433 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/example/spec/jasmine_examples/FooSpec.js 0000664 0000000 0000000 00000000000 15240143636 0030315 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/global_setup_failure/ 0000775 0000000 0000000 00000000000 15240143636 0024711 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/global_setup_failure/jasmine.js 0000664 0000000 0000000 00000000206 15240143636 0026673 0 ustar 00root root 0000000 0000000 module.exports = {
spec_dir: '.',
spec_files: ['spec.js'],
globalSetup() {
return Promise.reject(new Error('oops'));
}
};
jasmine-jasmine-npm-3c2955c/spec/fixtures/global_setup_failure/spec.js 0000664 0000000 0000000 00000000035 15240143636 0026177 0 ustar 00root root 0000000 0000000 it('a spec', function() {});
jasmine-jasmine-npm-3c2955c/spec/fixtures/global_setup_success/ 0000775 0000000 0000000 00000000000 15240143636 0024732 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/global_setup_success/jasmine.js 0000664 0000000 0000000 00000000173 15240143636 0026717 0 ustar 00root root 0000000 0000000 module.exports = {
spec_dir: '.',
spec_files: ['spec.js'],
globalSetup() {
console.log('in globalSetup');
}
};
jasmine-jasmine-npm-3c2955c/spec/fixtures/global_setup_success/spec.js 0000664 0000000 0000000 00000000035 15240143636 0026220 0 ustar 00root root 0000000 0000000 it('a spec', function() {});
jasmine-jasmine-npm-3c2955c/spec/fixtures/global_teardown_failure/ 0000775 0000000 0000000 00000000000 15240143636 0025374 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/global_teardown_failure/jasmine.js 0000664 0000000 0000000 00000000211 15240143636 0027352 0 ustar 00root root 0000000 0000000 module.exports = {
spec_dir: '.',
spec_files: ['spec.js'],
globalTeardown() {
return Promise.reject(new Error('oops'));
}
};
jasmine-jasmine-npm-3c2955c/spec/fixtures/global_teardown_failure/spec.js 0000664 0000000 0000000 00000000035 15240143636 0026662 0 ustar 00root root 0000000 0000000 it('a spec', function() {});
jasmine-jasmine-npm-3c2955c/spec/fixtures/global_teardown_success/ 0000775 0000000 0000000 00000000000 15240143636 0025415 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/global_teardown_success/global_setup_success/ 0000775 0000000 0000000 00000000000 15240143636 0031625 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/global_teardown_success/global_setup_success/jasmine.js 0000664 0000000 0000000 00000000201 15240143636 0033602 0 ustar 00root root 0000000 0000000 module.exports = {
spec_dir: '.',
spec_files: ['spec.js'],
globalTeardown() {
console.log('in globalTeardown');
}
};
jasmine-jasmine-npm-3c2955c/spec/fixtures/global_teardown_success/global_setup_success/spec.js 0000664 0000000 0000000 00000000035 15240143636 0033113 0 ustar 00root root 0000000 0000000 it('a spec', function() {});
jasmine-jasmine-npm-3c2955c/spec/fixtures/global_teardown_success/jasmine.js 0000664 0000000 0000000 00000000201 15240143636 0027372 0 ustar 00root root 0000000 0000000 module.exports = {
spec_dir: '.',
spec_files: ['spec.js'],
globalTeardown() {
console.log('in globalTeardown');
}
};
jasmine-jasmine-npm-3c2955c/spec/fixtures/global_teardown_success/spec.js 0000664 0000000 0000000 00000000035 15240143636 0026703 0 ustar 00root root 0000000 0000000 it('a spec', function() {});
jasmine-jasmine-npm-3c2955c/spec/fixtures/global_teardown_unhandled/ 0000775 0000000 0000000 00000000000 15240143636 0025707 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/global_teardown_unhandled/jasmine.js 0000664 0000000 0000000 00000000326 15240143636 0027674 0 ustar 00root root 0000000 0000000 module.exports = {
spec_dir: '.',
spec_files: ['spec.js'],
globalTeardown() {
setTimeout(function() {
throw new Error('oops');
});
return new Promise(resolve => setTimeout(resolve));
}
};
jasmine-jasmine-npm-3c2955c/spec/fixtures/global_teardown_unhandled/spec.js 0000664 0000000 0000000 00000000035 15240143636 0027175 0 ustar 00root root 0000000 0000000 it('a spec', function() {});
jasmine-jasmine-npm-3c2955c/spec/fixtures/import-jsx/ 0000775 0000000 0000000 00000000000 15240143636 0022636 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/import-jsx/jasmine.json 0000664 0000000 0000000 00000000115 15240143636 0025154 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": [
"spec.jsx"
],
"helpers": []
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/import-jsx/spec.jsx 0000664 0000000 0000000 00000000041 15240143636 0024311 0 ustar 00root root 0000000 0000000 it('is a spec', function() {
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/jasmine_spec/ 0000775 0000000 0000000 00000000000 15240143636 0023162 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/jasmine_spec/c.js 0000664 0000000 0000000 00000000000 15240143636 0023730 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/jasmine_spec/d.js 0000664 0000000 0000000 00000000000 15240143636 0023731 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/jasmine_spec/e.js 0000664 0000000 0000000 00000000000 15240143636 0023732 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/jasmine_spec/f.js 0000664 0000000 0000000 00000000000 15240143636 0023733 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/js-loader-default/ 0000775 0000000 0000000 00000000000 15240143636 0024024 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/js-loader-default/anEsModule.js 0000664 0000000 0000000 00000000047 15240143636 0026417 0 ustar 00root root 0000000 0000000 export function foo() {
return 42;
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/js-loader-default/anEsModuleSpec.js 0000664 0000000 0000000 00000000214 15240143636 0027226 0 ustar 00root root 0000000 0000000 import {foo} from './anEsModule.js';
describe('foo', function() {
it('returns 42', function() {
expect(foo()).toEqual(42);
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/js-loader-default/anEsRequire.js 0000664 0000000 0000000 00000000032 15240143636 0026600 0 ustar 00root root 0000000 0000000 import './anEsModule.js';
jasmine-jasmine-npm-3c2955c/spec/fixtures/js-loader-default/jasmine.json 0000664 0000000 0000000 00000000164 15240143636 0026346 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["anEsModuleSpec.js"],
"requires": ["../js-loader-default/anEsRequire.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/js-loader-default/package.json 0000664 0000000 0000000 00000000027 15240143636 0026311 0 ustar 00root root 0000000 0000000 {
"type": "module"
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/no-globals-parallel/ 0000775 0000000 0000000 00000000000 15240143636 0024351 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/no-globals-parallel/aHelper.js 0000664 0000000 0000000 00000000335 15240143636 0026270 0 ustar 00root root 0000000 0000000 const {jasmine, beforeEach} = require('jasmine-core');
beforeEach(function() {
jasmine.addCustomEqualityTester(function(a, b) {
if ((a === 1 && b === 2) || (a === 2 && b === 1)) {
return true;
}
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/no-globals-parallel/aSpec.js 0000664 0000000 0000000 00000000567 15240143636 0025752 0 ustar 00root root 0000000 0000000 const jasmineInterface = require('jasmine-core');
const {it, expect} = jasmineInterface;
it('can use equality testers defined in a different file', function() {
expect(1).toEqual(2);
});
it('does not add any globals', function() {
const jasmineGlobals = Object.keys(jasmineInterface)
.filter(k => global[k] !== undefined);
expect(jasmineGlobals).toEqual([]);
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/no-globals-parallel/runner.js 0000664 0000000 0000000 00000000347 15240143636 0026224 0 ustar 00root root 0000000 0000000 const ParallelRunner = require('../../../lib/parallel_runner.js');
const runner = new ParallelRunner({
globals: false,
numWorkers: 2
});
runner.addHelperFile('./aHelper.js');
runner.addSpecFile('./aSpec.js');
runner.execute();
jasmine-jasmine-npm-3c2955c/spec/fixtures/no-globals/ 0000775 0000000 0000000 00000000000 15240143636 0022557 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/no-globals/aSpec.js 0000664 0000000 0000000 00000000223 15240143636 0024145 0 ustar 00root root 0000000 0000000 const {it, expect} = require('jasmine-core');
it('can use equality testers defined in a different file', function() {
expect(1).toEqual(2);
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/no-globals/runner.js 0000664 0000000 0000000 00000001256 15240143636 0024432 0 ustar 00root root 0000000 0000000 const initialGlobals = Object.keys(global);
const Jasmine = require('../../../lib/jasmine.js');
const {jasmine, beforeEach} = require('jasmine-core');
beforeEach(function() {
jasmine.addCustomEqualityTester(function(a, b) {
if ((a === 1 && b === 2) || (a === 2 && b === 1)) {
return true;
}
});
});
const runner = new Jasmine({globals: false});
runner.addSpecFile('./aSpec.js');
runner.exitOnCompletion = false;
runner.execute().then(function() {
const extraGlobals = Object.keys(global).filter(k => !initialGlobals.includes(k));
if (extraGlobals.length === 0) {
console.log('Globals OK');
} else {
console.log('Extra globals:', extraGlobals);
}
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/noisy_require.js 0000664 0000000 0000000 00000000051 15240143636 0023751 0 ustar 00root root 0000000 0000000 console.log('noisy require was loaded');
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_before_after/ 0000775 0000000 0000000 00000000000 15240143636 0025021 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_before_after/helper.js 0000664 0000000 0000000 00000000215 15240143636 0026634 0 ustar 00root root 0000000 0000000 beforeEach(function() {
console.log('beforeEach in helper ran');
});
afterEach(function() {
console.log('afterEach in helper ran');
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_before_after/jasmine.json 0000664 0000000 0000000 00000000117 15240143636 0027341 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec.js"],
"helpers": ["helper.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_before_after/spec.js 0000664 0000000 0000000 00000000342 15240143636 0026310 0 ustar 00root root 0000000 0000000 describe('a suite', function() {
beforeEach(function() {
console.log('beforeEach in describe ran');
});
afterEach(function() {
console.log('afterEach in describe ran');
});
it('a spec', function() {});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_custom_loader/ 0000775 0000000 0000000 00000000000 15240143636 0025236 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_custom_loader/a%20spec.js 0000664 0000000 0000000 00000000035 15240143636 0027074 0 ustar 00root root 0000000 0000000 it('a spec', function() {});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_custom_loader/customLoader.js 0000664 0000000 0000000 00000000226 15240143636 0030235 0 ustar 00root root 0000000 0000000 module.exports = async function(modulePath) {
return new Promise(resolve => {
const module = require(modulePath);
resolve(module);
});
};
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_custom_loader/jasmine.json 0000664 0000000 0000000 00000000130 15240143636 0027551 0 ustar 00root root 0000000 0000000 {
"loader": "./customLoader.js",
"spec_dir": ".",
"spec_files": ["a%20spec.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_filter/ 0000775 0000000 0000000 00000000000 15240143636 0023663 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_filter/jasmine.json 0000664 0000000 0000000 00000000064 15240143636 0026204 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec*.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_filter/spec1.js 0000664 0000000 0000000 00000000222 15240143636 0025230 0 ustar 00root root 0000000 0000000 describe('suite 1', function() {
it('foo', function() {
expect(1).toBe(2);
});
it('bar', function() {
expect(1).toBe(2);
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_filter/spec2.js 0000664 0000000 0000000 00000000222 15240143636 0025231 0 ustar 00root root 0000000 0000000 describe('suite 2', function() {
it('foo', function() {
expect(1).toBe(2);
});
it('bar', function() {
expect(1).toBe(2);
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_helper_load_exception/ 0000775 0000000 0000000 00000000000 15240143636 0026732 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_helper_load_exception/helper.js 0000664 0000000 0000000 00000000031 15240143636 0030541 0 ustar 00root root 0000000 0000000 throw new Error('nope');
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_helper_load_exception/jasmine.json 0000664 0000000 0000000 00000000117 15240143636 0031252 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec.js"],
"helpers": ["helper.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_helper_load_exception/spec.js 0000664 0000000 0000000 00000000040 15240143636 0030214 0 ustar 00root root 0000000 0000000 it('is a spec', function() {});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_helpers/ 0000775 0000000 0000000 00000000000 15240143636 0024040 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_helpers/helper1.js 0000664 0000000 0000000 00000000034 15240143636 0025733 0 ustar 00root root 0000000 0000000 global.helperLoaded = true;
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_helpers/jasmine.json 0000664 0000000 0000000 00000000121 15240143636 0026353 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec*.js"],
"helpers": ["helper*.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_helpers/spec1.js 0000664 0000000 0000000 00000000167 15240143636 0025415 0 ustar 00root root 0000000 0000000 describe('Spec file 1', function() {
it('a spec', function() {
expect(global.helperLoaded).toBeTrue();
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_helpers/spec2.js 0000664 0000000 0000000 00000000167 15240143636 0025416 0 ustar 00root root 0000000 0000000 describe('Spec file 2', function() {
it('a spec', function() {
expect(global.helperLoaded).toBeTrue();
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_invalid_afterEach/ 0000775 0000000 0000000 00000000000 15240143636 0025766 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_invalid_afterEach/jasmine.json 0000664 0000000 0000000 00000000063 15240143636 0030306 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_invalid_afterEach/spec.js 0000664 0000000 0000000 00000000160 15240143636 0027253 0 ustar 00root root 0000000 0000000 afterEach(function() {
console.log('top level afterEach in spec file ran');
});
it('a spec', function() {});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_invalid_beforeEach/ 0000775 0000000 0000000 00000000000 15240143636 0026127 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_invalid_beforeEach/jasmine.json 0000664 0000000 0000000 00000000063 15240143636 0030447 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_invalid_beforeEach/spec.js 0000664 0000000 0000000 00000000162 15240143636 0027416 0 ustar 00root root 0000000 0000000 beforeEach(function() {
console.log('top level beforeEach in spec file ran');
});
it('a spec', function() {});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_no_specs/ 0000775 0000000 0000000 00000000000 15240143636 0024207 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_no_specs/jasmine.json 0000664 0000000 0000000 00000000064 15240143636 0026530 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec*.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_no_specs/spec1.js 0000664 0000000 0000000 00000000000 15240143636 0025546 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_pass/ 0000775 0000000 0000000 00000000000 15240143636 0023344 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_pass/jasmine.json 0000664 0000000 0000000 00000000064 15240143636 0025665 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec*.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_pass/spec1.js 0000664 0000000 0000000 00000000155 15240143636 0024716 0 ustar 00root root 0000000 0000000 describe('Spec file 1', function() {
it('a spec', function() {});
it('another spec', function() {});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_pass/spec2.js 0000664 0000000 0000000 00000000122 15240143636 0024711 0 ustar 00root root 0000000 0000000 describe('Spec file 2', function() {
it('yet another spec', function() {});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_requires/ 0000775 0000000 0000000 00000000000 15240143636 0024235 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_requires/jasmine.json 0000664 0000000 0000000 00000000126 15240143636 0026555 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec*.js"],
"requires": ["./requireMe.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_requires/requireMe.js 0000664 0000000 0000000 00000000033 15240143636 0026525 0 ustar 00root root 0000000 0000000 global.wasRequired = true;
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_requires/spec1.js 0000664 0000000 0000000 00000000107 15240143636 0025604 0 ustar 00root root 0000000 0000000 it('spec 1', function() {
expect(global.wasRequired).toBeTrue();
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_requires/spec2.js 0000664 0000000 0000000 00000000107 15240143636 0025605 0 ustar 00root root 0000000 0000000 it('spec 2', function() {
expect(global.wasRequired).toBeTrue();
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_spec_fail/ 0000775 0000000 0000000 00000000000 15240143636 0024323 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_spec_fail/jasmine.json 0000664 0000000 0000000 00000000064 15240143636 0026644 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec*.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_spec_fail/spec1.js 0000664 0000000 0000000 00000000211 15240143636 0025666 0 ustar 00root root 0000000 0000000 describe('Spec file 1', function() {
it('a spec', function() {});
it('a failing spec', function() {
expect(1).toBe(2);
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_spec_fail/spec2.js 0000664 0000000 0000000 00000000122 15240143636 0025670 0 ustar 00root root 0000000 0000000 describe('Spec file 2', function() {
it('yet another spec', function() {});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_spec_load_exception/ 0000775 0000000 0000000 00000000000 15240143636 0026405 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_spec_load_exception/jasmine.json 0000664 0000000 0000000 00000000063 15240143636 0030725 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_spec_load_exception/spec.js 0000664 0000000 0000000 00000000031 15240143636 0027667 0 ustar 00root root 0000000 0000000 throw new Error('nope');
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_suite_fail/ 0000775 0000000 0000000 00000000000 15240143636 0024522 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_suite_fail/jasmine.json 0000664 0000000 0000000 00000000064 15240143636 0027043 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec*.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_suite_fail/spec1.js 0000664 0000000 0000000 00000000176 15240143636 0026077 0 ustar 00root root 0000000 0000000 describe('Spec file 1', function() {
it('a spec', function() {});
afterAll(function() {
expect(1).toBe(2);
});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_suite_fail/spec2.js 0000664 0000000 0000000 00000000122 15240143636 0026067 0 ustar 00root root 0000000 0000000 describe('Spec file 2', function() {
it('yet another spec', function() {});
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_suite_incomplete/ 0000775 0000000 0000000 00000000000 15240143636 0025746 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/parallel_suite_incomplete/jasmine.json 0000664 0000000 0000000 00000000064 15240143636 0030267 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec*.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/premature_exit/ 0000775 0000000 0000000 00000000000 15240143636 0023557 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/premature_exit/jasmine.json 0000664 0000000 0000000 00000000063 15240143636 0026077 0 ustar 00root root 0000000 0000000 {
"spec_dir": ".",
"spec_files": ["spec.js"]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/premature_exit/spec.js 0000664 0000000 0000000 00000000061 15240143636 0025044 0 ustar 00root root 0000000 0000000 it('a spec', function() {
process.exit(0);
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/promiseFailure.js 0000664 0000000 0000000 00000000432 15240143636 0024045 0 ustar 00root root 0000000 0000000 const Jasmine = require('../..');
const jasmine = new Jasmine();
it('a spec', function() {
expect(1).toBe(2);
});
jasmine.exitOnCompletion = false;
jasmine.execute().then(function(result) {
if (result.overallStatus === 'failed') {
console.log("Promise failure!");
}
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/promiseIncomplete.js 0000664 0000000 0000000 00000000460 15240143636 0024556 0 ustar 00root root 0000000 0000000 const Jasmine = require('../..');
const jasmine = new Jasmine();
it('a spec', function() {});
fit('another spec', function() {});
jasmine.exitOnCompletion = false;
jasmine.execute().then(function(result) {
if (result.overallStatus === 'incomplete') {
console.log("Promise incomplete!");
}
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/promiseSuccess.js 0000664 0000000 0000000 00000000404 15240143636 0024065 0 ustar 00root root 0000000 0000000 const Jasmine = require('../..');
const jasmine = new Jasmine();
it('a spec', function() {});
jasmine.exitOnCompletion = false;
jasmine.execute().then(function(result) {
if (result.overallStatus === 'passed') {
console.log("Promise success!");
}
});
jasmine-jasmine-npm-3c2955c/spec/fixtures/require_tester.js 0000664 0000000 0000000 00000000076 15240143636 0024125 0 ustar 00root root 0000000 0000000 global.require_tester_was_loaded = true;
module.exports = {};
jasmine-jasmine-npm-3c2955c/spec/fixtures/sample_project/ 0000775 0000000 0000000 00000000000 15240143636 0023531 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/sample_project/spec/ 0000775 0000000 0000000 00000000000 15240143636 0024463 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/sample_project/spec/fixture_spec.js 0000664 0000000 0000000 00000000000 15240143636 0027507 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/sample_project/spec/helper.js 0000664 0000000 0000000 00000000000 15240143636 0026266 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/sample_project/spec/other_fixture_spec.js 0000664 0000000 0000000 00000000000 15240143636 0030710 0 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/sample_project/spec/support/ 0000775 0000000 0000000 00000000000 15240143636 0026177 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/fixtures/sample_project/spec/support/jasmine.json 0000664 0000000 0000000 00000000106 15240143636 0030515 0 ustar 00root root 0000000 0000000 {
"spec_dir": "spec",
"spec_files": [
"fixture_spec.js"
]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/sample_project/spec/support/jasmine_alternate.cjs 0000664 0000000 0000000 00000000273 15240143636 0032367 0 ustar 00root root 0000000 0000000 module.exports = {
"spec_dir": "spec",
"spec_files": [
"fixture_spec.js",
"**/*spec.js"
],
"helpers": [
"helper.js"
],
"requires": [
"ts-node/register"
]
};
jasmine-jasmine-npm-3c2955c/spec/fixtures/sample_project/spec/support/jasmine_alternate.json 0000664 0000000 0000000 00000000251 15240143636 0032555 0 ustar 00root root 0000000 0000000 {
"spec_dir": "spec",
"spec_files": [
"fixture_spec.js",
"**/*spec.js"
],
"helpers": [
"helper.js"
],
"requires": [
"ts-node/register"
]
}
jasmine-jasmine-npm-3c2955c/spec/fixtures/sample_project/spec/support/jasmine_alternate.mjs 0000664 0000000 0000000 00000000357 15240143636 0032404 0 ustar 00root root 0000000 0000000 const config = {
"spec_dir": "spec",
"spec_files": [
"fixture_spec.js",
"**/*spec.js"
],
"helpers": [
"helper.js"
],
"requires": [
"ts-node/register"
]
};
export default config;
jasmine-jasmine-npm-3c2955c/spec/fixtures/topLevelAwaitSentinel.mjs 0000664 0000000 0000000 00000000031 15240143636 0025511 0 ustar 00root root 0000000 0000000 await Promise.resolve();
jasmine-jasmine-npm-3c2955c/spec/global_setup_or_teardown_runner_spec.js 0000664 0000000 0000000 00000010351 15240143636 0026675 0 ustar 00root root 0000000 0000000 const GlobalSetupOrTeardownRunner = require('../lib/global_setup_or_teardown_runner');
describe('GlobalSetupOrTeardownRunner', function() {
describe('#run', function() {
it('waits for a promise-returning fn to complete', async function () {
const subject = new GlobalSetupOrTeardownRunner();
let resolve;
const runPromise = subject.run('', function() {
return new Promise(res => resolve = res);
});
await expectAsync(runPromise).toBePending();
resolve();
await runPromise;
});
});
it('supports synchronous fns', async function() {
const subject = new GlobalSetupOrTeardownRunner();
await subject.run('', function() {});
});
it('fails if the fn throws synchronously', async function() {
const subject = new GlobalSetupOrTeardownRunner();
const error = new Error('nope');
const runPromise = subject.run('', function() {
throw error;
});
await expectAsync(runPromise).toBeRejectedWith(jasmine.is(error));
});
it('fails if the promise returned by the fn is rejected', async function () {
const subject = new GlobalSetupOrTeardownRunner();
const error = new Error('nope');
const runPromise = subject.run('', function () {
return Promise.reject(error);
});
await expectAsync(runPromise).toBeRejectedWith(jasmine.is(error));
});
it('fails if there is an unhandled exception', async function () {
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
const subject = new GlobalSetupOrTeardownRunner();
const innerError = new Error();
const runPromise = subject.run('foo', function () {
setTimeout(function () {
throw innerError;
});
return new Promise(res => setTimeout(res));
});
await runPromise.then(
() => Promise.reject('Expected promise to be rejected but it was resolved'),
outerError => {
expect(outerError.message).toEqual('Unhandled exception during foo');
expect(outerError.cause).toBe(innerError);
}
);
expect(globalErrorSpy).toHaveBeenCalledOnceWith(innerError);
});
});
it('fails if there is an unhandled promise rejection', async function () {
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
const subject = new GlobalSetupOrTeardownRunner();
const innerError = new Error();
const runPromise = subject.run('bar', function () {
setTimeout(function () {
Promise.reject(innerError);
});
return new Promise(res => setTimeout(res));
});
await runPromise.then(
() => Promise.reject('Expected promise to be rejected but it was resolved'),
outerError => {
expect(outerError.message).toEqual('Unhandled promise rejection during bar');
expect(outerError.cause).toBe(innerError);
}
);
expect(globalErrorSpy).toHaveBeenCalledOnceWith(innerError);
});
});
describe('Timeout handling', function() {
const realSetTimeout = setTimeout;
beforeEach(function() {
jasmine.clock().install();
});
afterEach(function() {
jasmine.clock().uninstall();
});
it('fails if the promise returned by the fn is not resolved within 5 seconds', async function () {
const subject = new GlobalSetupOrTeardownRunner();
const runPromise = subject.run('foo', function() {
return new Promise(() => {});
});
jasmine.clock().tick(4999);
await new Promise(res => realSetTimeout.call(null, res));
await expectAsync(runPromise).toBePending();
jasmine.clock().tick(1);
await expectAsync(runPromise).toBeRejectedWithError(
'foo timed out after 5000 milliseconds'
);
});
it('can use a custom timeout', async function() {
const subject = new GlobalSetupOrTeardownRunner();
const runPromise = subject.run('bar', function() {
return new Promise(() => {});
}, 10);
jasmine.clock().tick(9);
await new Promise(res => realSetTimeout.call(null, res));
await expectAsync(runPromise).toBePending();
jasmine.clock().tick(1);
await expectAsync(runPromise).toBeRejectedWithError(
'bar timed out after 10 milliseconds'
);
});
});
});
jasmine-jasmine-npm-3c2955c/spec/integration_spec.js 0000664 0000000 0000000 00000042771 15240143636 0022557 0 ustar 00root root 0000000 0000000 const child_process = require('child_process');
describe('Integration', function () {
beforeEach(function() {
jasmine.addMatchers({
toBeSuccess: function(matchersUtil) {
return {
compare: function(actual, expected) {
const result = { pass: actual.exitCode === 0 };
if (result.pass) {
result.message = 'Expected process not to succeed but it did.';
} else {
result.message = `Expected process to succeed but it exited ${actual.exitCode}.`;
}
result.message += '\n\nOutput:\n' + actual.output;
return result;
}
};
}
});
});
it('supports ES modules', async function () {
const {exitCode, output} = await runJasmine('spec/fixtures/esm', 'jasmine.mjs');
expect(exitCode).toEqual(0);
expect(output).toContain(
'name_reporter\n' +
'commonjs_helper\n' +
'esm_helper\n' +
'Started\n' +
'Spec: A spec file ending in .js is required as a commonjs module\n' +
'.Spec: A spec file ending in .mjs is imported as an es module\n'
);
});
it('supports ES module reporters that end in .mjs', async function() {
let {output} = await runJasmine(
'spec/fixtures/sample_project',
'spec/support/jasmine.json',
['--reporter=../customReporter.mjs']
);
expect(output).toContain('customReporter.mjs jasmineDone');
});
it('supports ES module reporters that end in .js', async function() {
let {output} = await runJasmine(
'spec/fixtures/esm-reporter-packagejson',
'jasmine.json',
['--reporter=./customReporter.js']
);
expect(output).toContain('customReporter.js jasmineDone');
});
it('loads .js files using import', async function() {
expect(await runJasmine('spec/fixtures/js-loader-default')).toBeSuccess();
});
it('falls back to require when loading extensions that import does not support', async function() {
expect(await runJasmine('spec/fixtures/import-jsx')).toBeSuccess();
});
it('handles load-time exceptions from CommonJS specs properly', async function () {
const {exitCode, output} = await runJasmine('spec/fixtures/cjs-load-exception');
expect(exitCode).toEqual(1);
expect(output).toContain('Error: nope');
expect(output).toMatch(/at .*throws_on_load.js/);
});
it('handles load-time exceptions from ESM specs properly', async function () {
const {exitCode, output} = await runJasmine('spec/fixtures/esm-load-exception');
expect(exitCode).toEqual(1);
expect(output).toContain('Error: nope');
expect(output).toMatch(/at .*throws_on_load.mjs/);
});
it('handles syntax errors in CommonJS specs properly', async function () {
const {exitCode, output} = await runJasmine('spec/fixtures/cjs-syntax-error');
expect(exitCode).toEqual(1);
expect(output).toContain('SyntaxError');
expect(output).toContain('syntax_error.js');
});
it('handles syntax errors in ESM specs properly', async function () {
const {exitCode, output} = await runJasmine('spec/fixtures/esm-syntax-error');
expect(exitCode).toEqual(1);
expect(output).toContain('SyntaxError');
expect(output).toContain('syntax_error.mjs');
});
it('handles syntax errors from a CommonJS module loaded from an ESM spec properly', async function() {
try {
await import('./fixtures/topLevelAwaitSentinel.mjs');
} catch (e) {
if (e instanceof SyntaxError && e.message === 'Unexpected reserved word') {
pending('This Node version does not support top-level await');
} else if (e.message === 'Not supported') {
pending('This Node version does not support dynamic import');
} else {
throw e;
}
}
const {exitCode, output} = await runJasmine('spec/fixtures/esm-importing-commonjs-syntax-error');
expect(exitCode).toEqual(1);
expect(output).toContain('SyntaxError');
expect(output).toContain('syntax_error.js');
});
it('handles exceptions thrown from a module loaded from an ESM spec properly', async function() {
const {exitCode, output} = await runJasmine('spec/fixtures/esm-indirect-error');
expect(exitCode).toEqual(1);
expect(output).toContain('nope');
expect(output).toContain('throws.mjs');
});
it('supports custom loaders', async function() {
const {exitCode, output} = await runJasmine('spec/fixtures/custom-loader');
expect(exitCode).toEqual(3);
expect(output).toContain('1 spec, 1 failure');
});
it('can configure the env via the `env` config property', async function() {
const {exitCode, output} = await runJasmine('spec/fixtures/env-config');
expect(exitCode).toEqual(0);
expect(output).toContain(
'in spec 1\n.in spec 2\n.in spec 3\n.in spec 4\n.in spec 5'
);
});
describe('Programmatic usage', function() {
it('exits on completion by default', async function() {
const {exitCode, output} = await runCommand('node', ['spec/fixtures/defaultProgrammaticFail.js']);
expect(exitCode).toEqual(3);
expect(output).toContain('1 spec, 1 failure');
});
it('does not exit on completion when exitOnCompletion is set to false', async function() {
const {exitCode, output} = await runCommand('node', ['spec/fixtures/dontExitOnCompletion.js']);
expect(exitCode).toEqual(0);
expect(output).toContain('in setTimeout cb');
});
it('resolves the returned promise when the suite passes', async function() {
const {exitCode, output} = await runCommand('node', ['spec/fixtures/promiseSuccess.js']);
expect(exitCode).toEqual(0);
expect(output).toContain('Promise success!');
});
it('resolves the returned promise when the suite fails', async function() {
const {exitCode, output} = await runCommand('node', ['spec/fixtures/promiseFailure.js']);
expect(exitCode).toEqual(0);
expect(output).toContain('Promise failure!');
});
it('resolves the returned promise when the suite is incomplete', async function() {
const {exitCode, output} = await runCommand('node', ['spec/fixtures/promiseIncomplete.js']);
expect(exitCode).toEqual(0);
expect(output).toContain('Promise incomplete!');
});
});
describe('When exit() is called before the suite finishes', function() {
describe('in normal mode', function () {
it('exits with status 4', async function () {
const {exitCode} = await runJasmine(
'spec/fixtures/premature_exit',
'jasmine.json'
);
expect(exitCode).toEqual(4);
});
});
describe('in parallel mode', function () {
it('exits with status 4', async function () {
const {exitCode} = await runJasmine(
'spec/fixtures/premature_exit',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(4);
});
});
});
it('does not create globals when the globals option is false', async function() {
const {exitCode, output} = await runCommand('node', ['runner.js'],
'spec/fixtures/no-globals');
expect(exitCode).toEqual(0);
expect(output).toContain('1 spec, 0 failures');
expect(output).toContain('Globals OK');
});
describe('Parallel execution', function() {
it('runs a passing suite', async function () {
const expectedOutput = 'Started\n' +
'...\n' +
'\n' +
'\n' +
'3 specs, 0 failures\n' +
'Ran in parallel with 2 workers\n' +
'Finished in ';
const {exitCode, output} = await runJasmine(
'spec/fixtures/parallel_pass',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(0);
expect(output).toContain(expectedOutput);
});
it('runs an incomplete suite', async function () {
const {exitCode, output} = await runJasmine(
'spec/fixtures/parallel_suite_incomplete',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(2);
expect(output).toContain('Incomplete: No specs found');
});
it('runs a suite with a spec failure', async function () {
const expectedChunks = [
'Started\n',
'\n' +
'Failures:\n' +
'1) Spec file 1 a failing spec\n' +
' Message:\n' +
' Expected 1 to be 2.\n' +
' Stack:\n' +
' at \n' +
' at UserContext. ',
'3 specs, 1 failure\n' +
'Ran in parallel with 2 workers\n' +
'Finished in '
];
const {exitCode, output} = await runJasmine(
'spec/fixtures/parallel_spec_fail',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(3);
for (const chunk of expectedChunks) {
expect(output).toContain(chunk);
}
expect(output).toMatch(/(F\.\.)|(\.F\.)|(\.\.\F)/);
});
it('runs a suite with a suite failure', async function () {
const expectedChunks = [
'Started\n' +
'..\n' +
'\n' +
'\n' +
'Suite error: Spec file 1\n' +
' Message:\n' +
' Expected 1 to be 2.\n' +
' Stack:\n' +
' at \n' +
' at UserContext. ',
'2 specs, 1 failure\n' +
'Ran in parallel with 2 workers\n' +
'Finished in '
];
const {exitCode, output} = await runJasmine(
'spec/fixtures/parallel_suite_fail',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(3);
for (const chunk of expectedChunks) {
expect(output).toContain(chunk);
}
});
it('runs a suite with no specs', async function () {
const expectedChunks = [
'Started\n' +
'\n' +
'\n' +
'No specs found\n' +
'Ran in parallel with 2 workers\n' +
'Finished in ',
'Incomplete: No specs found\n'
];
const {exitCode, output} = await runJasmine(
'spec/fixtures/parallel_no_specs',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(2);
for (const chunk of expectedChunks) {
expect(output).toContain(chunk);
}
});
it('loads helper files in each worker process', async function () {
const expectedOutput = 'Started\n' +
'..\n' +
'\n' +
'\n' +
'2 specs, 0 failures\n' +
'Ran in parallel with 2 workers\n' +
'Finished in ';
const {exitCode, output} = await runJasmine(
'spec/fixtures/parallel_helpers',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(0);
expect(output).toContain(expectedOutput);
});
it('handles spec file load exceptions in worker processes', async function () {
const {exitCode, output} = await runJasmine(
'spec/fixtures/parallel_spec_load_exception',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(3);
expect(output).toMatch(/Error loading .*\/spec\/fixtures\/parallel_spec_load_exception\/spec.js: nope/);
expect(output).toMatch(/at Object\. .*spec[\\\/]fixtures[\\\/]parallel_spec_load_exception[\\\/]spec\.js/);
});
it('handles helper file load exceptions in worker processes', async function () {
const {exitCode, output} = await runJasmine(
'spec/fixtures/parallel_helper_load_exception',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(1);
const prefix = 'Fatal error in worker: nope\n';
expect(output).toContain(prefix);
expect(output).toMatch(/at Object\. .*spec[\\\/]fixtures[\\\/]parallel_helper_load_exception[\\\/]helper\.js/);
// The error should only be logged once.
const firstIndex = output.indexOf(prefix);
const nextIndex = output.indexOf(prefix, firstIndex + 1);
expect(nextIndex)
.withContext('error was reported more than once')
.toEqual(-1);
});
it('prohibits top level beforeEach in spec files in parallel', async function() {
const {exitCode, output} = await runJasmine(
'spec/fixtures/parallel_invalid_beforeEach',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(3);
expect(output).toContain('In parallel mode, ' +
'beforeEach must be in a describe block or in a helper file');
});
it('prohibits top level afterEach in spec files in parallel', async function() {
const {exitCode, output} = await runJasmine(
'spec/fixtures/parallel_invalid_afterEach',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(3);
expect(output).toMatch(
/Error loading .*\/spec\/fixtures\/parallel_invalid_afterEach\/spec.js: In parallel mode, afterEach must be in a describe block or in a helper file/
);
});
it('allows beforeEach and afterEach in helpers and in describe in parallel', async function() {
const {exitCode, output} = await runJasmine(
'spec/fixtures/parallel_before_after',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(0);
expect(output).toContain('beforeEach in helper ran');
expect(output).toContain('afterEach in helper ran');
expect(output).toContain('beforeEach in describe ran');
expect(output).toContain('afterEach in describe ran');
});
it('loads requires in each worker', async function() {
const {exitCode} = await runJasmine(
'spec/fixtures/parallel_requires',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(0);
});
it('passes, the loader config setting to workers', async function() {
const {exitCode, output} = await runJasmine(
'spec/fixtures/parallel_custom_loader',
'jasmine.json',
['--parallel=2']
);
expect(exitCode).toEqual(0);
expect(output).toContain('1 spec, 0 failures');
});
it('passes the --filter setting to workers', async function() {
const {output} = await runJasmine(
'spec/fixtures/parallel_filter',
'jasmine.json',
['--parallel=2', '--filter=foo']
);
expect(output).toContain('suite 1 foo');
expect(output).toContain('suite 2 foo');
expect(output).toContain('Ran 2 of 4 specs');
expect(output).toContain('2 specs, 2 failures');
});
it('does not create globals when the globals option is false', async function() {
const {exitCode, output} = await runCommand('node', ['runner.js'], 'spec/fixtures/no-globals-parallel');
expect(exitCode).toEqual(0);
expect(output).toContain('2 specs, 0 failures');
});
});
describe('Global setup and teardown', function() {
const scenarios = [['parallel', ['--parallel=2']], ['non-parallel', []]];
for (const [description, extraArgs] of scenarios) {
describe(description, function() {
it('runs globalSetup', async function() {
const {exitCode, output} = await runJasmine(
'spec/fixtures/global_setup_success',
'jasmine.js',
extraArgs
);
expect(exitCode).toEqual(0);
expect(output).toContain('in globalSetup');
});
it('runs globalTeardown', async function() {
const {exitCode, output} = await runJasmine(
'spec/fixtures/global_teardown_success',
'jasmine.js',
extraArgs
);
expect(exitCode).toEqual(0);
expect(output).toContain('in globalTeardown');
});
it('fails if globalSetup fails', async function() {
const {exitCode, output} = await runJasmine(
'spec/fixtures/global_setup_failure',
'jasmine.js',
extraArgs
);
expect(exitCode).toEqual(1);
expect(output).toContain('oops');
});
it('fails if globalTeardown fails', async function() {
const {exitCode, output} = await runJasmine(
'spec/fixtures/global_teardown_failure',
'jasmine.js',
extraArgs
);
expect(exitCode).toEqual(1);
expect(output).toContain('oops');
});
it('fails if there is an unhandled exception during globalTeardown', async function() {
const {exitCode, output} = await runJasmine(
'spec/fixtures/global_teardown_unhandled',
'jasmine.js',
extraArgs
);
expect(exitCode).toEqual(1);
expect(output).toContain('Unhandled exception during globalTeardown');
expect(output).toContain('oops');
});
});
}
});
it('supports --require', async function() {
const {exitCode, output} = await runJasmine(
'spec/fixtures/sample_project',
'spec/support/jasmine.json',
['--require=../noisy_require.js']
);
expect(exitCode).toEqual(2); // because no specs
expect(output).toContain('noisy require was loaded');
});
});
async function runJasmine(cwd, config="jasmine.json", extraArgs = []) {
const args = ['../../../bin/jasmine.js', '--config=' + config].concat(extraArgs);
return runCommand('node', args, cwd);
}
async function runCommand(cmd, args, cwd = '.') {
return new Promise(function(resolve) {
const child = child_process.spawn(
cmd,
args,
{
cwd,
shell: false
}
);
let output = '';
child.stdout.on('data', function (data) {
output += data;
});
child.stderr.on('data', function (data) {
output += data;
});
child.on('close', function (exitCode) {
resolve({exitCode, output});
});
});
}
jasmine-jasmine-npm-3c2955c/spec/jasmine_spec.js 0000664 0000000 0000000 00000043125 15240143636 0021654 0 ustar 00root root 0000000 0000000 const path = require('path');
const ConsoleReporter = require('@jasminejs/reporters/console');
const Jasmine = require('../lib/jasmine');
const {sharedRunnerBehaviors} = require('./shared_runner_behaviors');
const {poll, shortPoll} = require('./poll');
describe('Jasmine', function() {
beforeEach(function () {
this.fakeJasmineCore = {
jasmine: {
getEnv: jasmine.createSpy('getEnv').and.returnValue({
addReporter: jasmine.createSpy('addReporter'),
clearReporters: jasmine.createSpy('clearReporters'),
addMatchers: jasmine.createSpy('addMatchers'),
provideFallbackReporter: jasmine.createSpy('provideFallbackReporter'),
execute: jasmine.createSpy('execute')
.and.callFake(function () {
return Promise.reject(new Error('Unconfigured call to Env#execute'));
}),
configure: jasmine.createSpy('configure'),
topSuite: jasmine.createSpy('topSuite'),
}),
Timer: jasmine.createSpy('Timer'),
},
installGlobals() {},
files: {
path: 'fake/jasmine/path'
}
};
this.globalSetupOrTeardownRunner = jasmine.createSpyObj(
'globalSetupOrTeardownRunner', ['run']
);
this.testJasmine = new Jasmine({
jasmineCore: this.fakeJasmineCore,
globalSetupOrTeardownRunner: this.globalSetupOrTeardownRunner,
});
this.testJasmine.exit = function () {
// Don't actually exit the node process
};
this.execute = execute;
this.finishExecution = async () => {
};
});
sharedRunnerBehaviors(function (options) {
return new Jasmine({
jasmineCore: this.fakeJasmineCore,
...options,
});
});
it('delegates #coreVersion to jasmine-core', function () {
this.fakeJasmineCore.version = () => 'a version';
expect(this.testJasmine.coreVersion()).toEqual('a version');
});
it('registers a console reporter upon construction', function () {
const testJasmine = new Jasmine({jasmineCore: this.fakeJasmineCore});
expect(testJasmine.env.addReporter).toHaveBeenCalledWith(jasmine.any(ConsoleReporter));
});
it('reports how to reproduce the random seed', function() {
const testJasmine = new Jasmine({jasmineCore: this.fakeJasmineCore});
const print = jasmine.createSpy('print');
testJasmine.configureDefaultReporter({print});
const reporter = testJasmine.env.addReporter.calls.mostRecent().args[0];
reporter.jasmineDone({order: {random: true, seed: 12345}});
expect(print).toHaveBeenCalledWith(jasmine.stringContaining(
'(jasmine --random=true --seed=12345)'));
});
it('can add and clear reporters', function () {
const testJasmine = new Jasmine({jasmineCore: this.fakeJasmineCore});
expect(testJasmine.reportersCount).toEqual(1);
testJasmine.clearReporters();
expect(testJasmine.reportersCount).toEqual(0);
expect(testJasmine.env.clearReporters).toHaveBeenCalled();
testJasmine.addReporter({someProperty: 'some value'});
expect(testJasmine.reportersCount).toEqual(1);
expect(testJasmine.env.addReporter).toHaveBeenCalledWith({someProperty: 'some value'});
});
it('adds matchers to the jasmine env', function () {
this.testJasmine.addMatchers(['fake matcher 1', 'fake matcher 2']);
expect(this.testJasmine.env.addMatchers).toHaveBeenCalledWith(['fake matcher 1', 'fake matcher 2']);
});
describe('loading configurations', function () {
beforeEach(function () {
this.fixtureJasmine = new Jasmine({
jasmineCore: this.fakeJasmineCore,
projectBaseDir: 'spec/fixtures/sample_project'
});
});
describe('from an object', function () {
beforeEach(function () {
this.loader = this.fixtureJasmine.loader = jasmine.createSpyObj('loader', ['load']);
this.configObject = {
spec_dir: "spec",
spec_files: [
"fixture_spec.js",
"**/*spec.js"
],
helpers: [
"helper.js"
],
requires: [
"ts-node/register"
]
};
});
it('uses jasmine-core defaults if no config options specified', async function () {
await this.fixtureJasmine.loadConfig({});
expect(this.fixtureJasmine.env.configure).not.toHaveBeenCalled();
});
it('can configure the env with arbitrary properties', async function () {
const envConfig = {someProp: 'someVal'};
await this.fixtureJasmine.loadConfig({env: envConfig});
expect(this.fixtureJasmine.env.configure).toHaveBeenCalledWith(envConfig);
});
it('adds specified reporters', async function () {
const reporter1 = {id: 'reporter1'};
const reporter2 = {id: 'reporter2'};
this.configObject.reporters = [reporter1, reporter2];
await this.fixtureJasmine.loadConfig(this.configObject);
expect(this.fixtureJasmine.env.addReporter).toHaveBeenCalledWith(reporter1);
expect(this.fixtureJasmine.env.addReporter).toHaveBeenCalledWith(reporter2);
});
});
});
describe('#stopSpecOnExpectationFailure', function () {
it('sets the stopSpecOnExpectationFailure value on the jasmine-core env', function () {
this.testJasmine.stopSpecOnExpectationFailure('foobar');
expect(this.testJasmine.env.configure).toHaveBeenCalledWith({stopSpecOnExpectationFailure: 'foobar'});
});
});
describe('#stopOnSpecFailure', function () {
it('sets the stopOnSpecFailure value on the jasmine-core env', function () {
spyOn(console, 'warn');
this.testJasmine.stopOnSpecFailure('blah');
expect(this.testJasmine.env.configure).toHaveBeenCalledWith({stopOnSpecFailure: 'blah'});
});
});
describe('#randomizeTests', function () {
it('sets the randomizeTests value on the jasmine-core env', function () {
this.testJasmine.randomizeTests('foobar');
expect(this.testJasmine.env.configure).toHaveBeenCalledWith({random: 'foobar'});
});
});
describe('#execute', function () {
it('executes the env', async function () {
await this.execute();
expect(this.testJasmine.env.execute).toHaveBeenCalled();
});
it('loads helper files', async function () {
spyOn(this.testJasmine, 'loadHelpers');
await this.execute();
expect(this.testJasmine.loadHelpers).toHaveBeenCalled();
});
describe('Filtering', function() {
let specFilter;
beforeEach(function() {
this.testJasmine.env.configure.and.callFake(function (config) {
if (config.specFilter) {
specFilter = config.specFilter;
}
});
});
describe('When a filter string is provided', function () {
it('installs a matching spec filter', async function () {
await this.execute({
executeArgs: [['spec/fixtures/example/*spec.js'], 'interesting spec']
});
expect(specFilter).toBeTruthy();
const matchingSpec = {
getFullName() {
return 'this is an interesting spec that should match';
}
};
const nonMatchingSpec = {
getFullName() {
return 'but this one is not';
}
};
expect(specFilter(matchingSpec)).toBeTrue();
expect(specFilter(nonMatchingSpec)).toBeFalse();
});
});
describe('When a filter regex is provided', function () {
it('installs a matching spec filter', async function () {
await this.execute({
executeArgs: [['spec/fixtures/example/*spec.js'], /interesting spec/]
});
expect(specFilter).toBeTruthy();
const matchingSpec = {
getFullName() {
return 'this is an interesting spec that should match';
}
};
const nonMatchingSpec = {
getFullName() {
return 'but this one is not';
}
};
expect(specFilter(matchingSpec)).toBeTrue();
expect(specFilter(nonMatchingSpec)).toBeFalse();
});
});
describe('When a path filter specification is provided', function () {
it('installs a matching spec filter', async function () {
await this.execute({
executeArgs: [['spec/fixtures/example/*spec.js'], {
path: ['parent', 'child', 'spec']
}]
});
function stubSpec(path) {
return {
getPath() { return path; },
// getFullName is required, but plays no role in filtering
getFullName() { return ""; }
};
}
expect(specFilter).toBeTruthy();
expect(specFilter(stubSpec(['parent', 'child', 'spec'])))
.toBeTrue();
expect(specFilter(stubSpec(['parent', 'other child', 'spec'])))
.toBeFalse();
});
});
});
it('loads specs', async function () {
spyOn(this.testJasmine, 'loadSpecs');
await this.execute();
expect(this.testJasmine.loadSpecs).toHaveBeenCalled();
});
describe('The returned promise', function () {
it('is resolved with the overall suite status', async function () {
await expectAsync(this.execute({overallStatus: 'failed'}))
.toBeResolvedTo(jasmine.objectContaining({overallStatus: 'failed'}));
});
it('is resolved with the overall suite status even if clearReporters was called', async function () {
this.testJasmine.clearReporters();
await expectAsync(this.execute({overallStatus: 'incomplete'}))
.toBeResolvedTo(jasmine.objectContaining({overallStatus: 'incomplete'}));
});
});
it('can run only specified files', async function () {
await this.execute({
executeArgs: [['spec/fixtures/sample_project/**/*spec.js']]
});
const relativePaths = this.testJasmine.specFiles.map(function (filePath) {
return path.relative(__dirname, filePath).replace(/\\/g, '/');
});
expect(relativePaths).toEqual([
'fixtures/sample_project/spec/fixture_spec.js',
'fixtures/sample_project/spec/other_fixture_spec.js'
]);
});
describe('when a globalSetup is configured', function () {
beforeEach(function () {
this.fakeJasmineCore.jasmine.getEnv().execute.and.returnValue(
new Promise(() => {
})
);
});
it('waits for globalSetup to complete before running specs', async function () {
let resolve;
this.globalSetupOrTeardownRunner.run.and.returnValue(
new Promise(res => resolve = res)
);
function globalSetup() {
}
await this.testJasmine.loadConfig({globalSetup});
this.testJasmine.execute();
await shortPoll(
() => this.globalSetupOrTeardownRunner.run.calls.any(),
'globalSetupOrTeardownRunner.run to be called'
);
expect(this.fakeJasmineCore.jasmine.getEnv().execute).not.toHaveBeenCalled();
resolve();
await poll(() => this.fakeJasmineCore.jasmine.getEnv().execute());
});
it('fails if globalSetup fails', async function () {
this.globalSetupOrTeardownRunner.run.and.rejectWith(new Error('nope'));
await this.testJasmine.loadConfig({
globalSetup() {
}
});
await expectAsync(this.testJasmine.execute()).toBeRejectedWithError('nope');
});
it('uses a configured timeout', async function () {
this.globalSetupOrTeardownRunner.run.and.returnValue(
new Promise(() => {
})
);
function globalSetup() {
}
await this.testJasmine.loadConfig({
globalSetup,
globalSetupTimeout: 17
});
this.testJasmine.execute();
await shortPoll(
() => this.globalSetupOrTeardownRunner.run.calls.any(),
'globalSetupOrTeardownRunner.run to be called'
);
expect(this.globalSetupOrTeardownRunner.run).toHaveBeenCalledWith(
'globalSetup', globalSetup, 17
);
});
});
describe('when a globalTeardown is configured', function () {
let resolveEnvExecute;
let arbitraryOverallResult;
beforeEach(function () {
const promise = new Promise(res => resolveEnvExecute = res);
this.fakeJasmineCore.jasmine.getEnv().execute.and.returnValue(promise);
arbitraryOverallResult = {overallStatus: 'passed'};
});
it('waits for globalTeardown to complete after execution finishes', async function () {
let resolveTeardown;
this.globalSetupOrTeardownRunner.run.and.returnValue(
new Promise(res => resolveTeardown = res)
);
function globalTeardown() {
}
await this.testJasmine.loadConfig({globalTeardown});
const runnerExecutePromise = this.testJasmine.execute();
await new Promise(res => setTimeout(res));
expect(this.globalSetupOrTeardownRunner.run).not.toHaveBeenCalled();
resolveEnvExecute(arbitraryOverallResult);
await new Promise(res => setTimeout(res));
await expectAsync(runnerExecutePromise).toBePending();
resolveTeardown();
await runnerExecutePromise;
expect(this.globalSetupOrTeardownRunner.run).toHaveBeenCalledWith(
'globalTeardown', globalTeardown, undefined
);
});
it('fails if globalTeardown fails', async function () {
this.globalSetupOrTeardownRunner.run.and.rejectWith(new Error('nope'));
await this.testJasmine.loadConfig({
globalTeardown() {
}
});
const executePromise = this.testJasmine.execute();
resolveEnvExecute(arbitraryOverallResult);
await expectAsync(executePromise).toBeRejectedWithError('nope');
});
it('runs globalTeardown even if env execution fails', async function () {
this.fakeJasmineCore.jasmine.getEnv().execute
.and.rejectWith(new Error('env execute failure'));
this.globalSetupOrTeardownRunner.run.and.resolveTo();
await this.testJasmine.loadConfig({
globalTeardown() {
}
});
await expectAsync(this.testJasmine.execute())
.toBeRejectedWithError('env execute failure');
expect(this.globalSetupOrTeardownRunner.run).toHaveBeenCalled();
});
it('uses a configured timeout', async function () {
this.globalSetupOrTeardownRunner.run.and.returnValue(
new Promise(() => {
})
);
function globalTeardown() {
}
await this.testJasmine.loadConfig({
globalTeardown,
globalTeardownTimeout: 17
});
this.testJasmine.execute();
resolveEnvExecute();
await shortPoll(
() => this.globalSetupOrTeardownRunner.run.calls.any(),
'globalTeardown to have been run'
);
expect(this.globalSetupOrTeardownRunner.run).toHaveBeenCalledWith(
'globalTeardown', globalTeardown, 17
);
});
});
});
describe('#enumerate', function() {
it('loads requires, helpers, and specs', async function() {
const loadRequires = spyOn(this.testJasmine, 'loadRequires');
const loadHelpers = spyOn(this.testJasmine, 'loadHelpers');
const loadSpecs = spyOn(this.testJasmine, 'loadSpecs');
this.fakeJasmineCore.jasmine.getEnv().topSuite
.and.returnValue({children: []});
await this.testJasmine.enumerate();
expect(loadRequires).toHaveBeenCalledBefore(loadHelpers);
expect(loadHelpers).toHaveBeenCalledBefore(loadSpecs);
expect(loadSpecs).toHaveBeenCalledBefore(
this.fakeJasmineCore.jasmine.getEnv().topSuite);
});
it('returns a serializable, id-less suite tree', async function() {
const topSuite = {
id: 'a',
description: 'Jasmine__TopLevel__Suite',
children: [{
id: 'b',
description: 'parent',
children: [{
id: 'c',
description: 'nested',
children: [{
id: 'd',
description: 'a spec'
}]
}]
}]
};
topSuite.children[0].parentSuite = topSuite;
topSuite.children[0].children[0].parentSuite = topSuite.children[0];
this.fakeJasmineCore.jasmine.getEnv().topSuite.and.returnValue(topSuite);
const result = await this.testJasmine.enumerate();
expect(JSON.parse(JSON.stringify(result))).toEqual([{
type: 'suite',
description: 'parent',
children: [{
type: 'suite',
description: 'nested',
children: [{
type: 'spec',
description: 'a spec'
}]
}]
}]);
});
});
describe('When running on Windows', function () {
function windows() {
return 'win32';
}
it('converts backslashes in the project base dir to slashes, for compatibility with glob', function () {
const subject = new Jasmine({
projectBaseDir: 'c:\\foo\\bar',
platform: windows,
jasmineCore: this.fakeJasmineCore,
});
expect(subject.projectBaseDir).toEqual('c:/foo/bar');
});
});
});
async function execute(options = {}) {
const overallStatus = options.overallStatus || 'passed';
const executeArgs = options.executeArgs || [];
let executePromise;
let resolveEnvExecutePromise;
const envExecutePromise = new Promise(resolve => {
resolveEnvExecutePromise = resolve;
});
await new Promise(resolve => {
this.testJasmine.env.execute.and.callFake(function () {
resolve();
return envExecutePromise;
});
executePromise = this.testJasmine.execute.apply(this.testJasmine, executeArgs);
});
resolveEnvExecutePromise({overallStatus});
return executePromise;
}
jasmine-jasmine-npm-3c2955c/spec/loader_spec.js 0000664 0000000 0000000 00000017263 15240143636 0021500 0 ustar 00root root 0000000 0000000 const path = require('path');
const url = require('url');
const Loader = require('../lib/loader');
describe('loader', function() {
afterEach(function() {
delete global.require_tester_was_loaded;
});
describe('#load', function() {
describe('When the path ends in .mjs', function () {
esModuleSharedExamples('mjs', true);
});
describe('When the path does not end in .mjs', function () {
esModuleSharedExamples('js', true);
});
describe('When the extension is not supported by import()', function() {
it('falls back to require()', async function() {
const error = new TypeError();
error.code = 'ERR_UNKNOWN_FILE_EXTENSION';
const payload = {};
const requireShim = jasmine.createSpy('requireShim')
.and.returnValue(Promise.resolve(payload));
const importShim = jasmine.createSpy('importShim')
.and.returnValue(Promise.reject(error));
const loader = new Loader({requireShim, importShim});
const result = await loader.load('./spec.jsx');
expect(result).toBe(payload);
expect(requireShim).toHaveBeenCalled();
expect(importShim).toHaveBeenCalled();
});
});
it('imports non-local modules', async function() {
const payload = {default: {}};
const requireShim = jasmine.createSpy('requireShim');
const importShim = jasmine.createSpy('importShim')
.and.returnValue(Promise.resolve(payload));
const loader = new Loader({requireShim, importShim});
const result = await loader.load('some-module');
expect(result).toBe(payload.default);
expect(requireShim).not.toHaveBeenCalled();
expect(importShim).toHaveBeenCalledWith('some-module');
});
it('imports namespaced modules', async function() {
const payload = {default: {}};
const requireShim = jasmine.createSpy('requireShim');
const importShim = jasmine.createSpy('importShim')
.and.returnValue(Promise.resolve(payload));
const loader = new Loader({requireShim, importShim});
const result = await loader.load('@namespace/some-module');
expect(result).toBe(payload.default);
expect(requireShim).not.toHaveBeenCalled();
expect(importShim).toHaveBeenCalledWith('@namespace/some-module');
});
it('uses require to load JSON files', async function() {
const requireShim = jasmine.createSpy('requireShim')
.and.returnValue(Promise.resolve());
const importShim = jasmine.createSpy('importShim');
const loader = new Loader({requireShim, importShim});
await expectAsync(loader.load('./jasmine.json')).toBeResolved();
expect(requireShim).toHaveBeenCalledWith('./jasmine.json');
expect(importShim).not.toHaveBeenCalled();
});
});
});
function esModuleSharedExamples(extension) {
async function testBasicEsModuleLoading(separator) {
const requireShim = jasmine.createSpy('requireShim');
let resolve;
const importPromise = new Promise(function (res) {
resolve = res;
});
const importShim = jasmine.createSpy('importShim')
.and.returnValue(importPromise);
const resolvePath = jasmine.createSpy('resolvePath')
.and.returnValue('/the/path/to/the/module');
const loader = new Loader({requireShim, importShim, resolvePath});
const requestedPath = ['foo', 'bar', `baz.${extension}`].join(separator);
const loaderPromise = loader.load(requestedPath);
expect(requireShim).not.toHaveBeenCalled();
expect(resolvePath).toHaveBeenCalledWith(requestedPath);
expect(importShim).toHaveBeenCalledWith(url.pathToFileURL('/the/path/to/the/module').toString());
await expectAsync(loaderPromise).toBePending();
resolve({});
await expectAsync(loaderPromise).toBeResolved();
}
it('loads the file as an es module', async function () {
await testBasicEsModuleLoading(path.sep);
});
it('supports /-separated paths', async function() {
await testBasicEsModuleLoading('/');
});
it("adds the filename to ES module syntax errors", async function() {
const underlyingError = new SyntaxError('some details but no filename, not even in the stack trace');
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
try {
await loader.load(`foo.${extension}`);
fail('Expected loader to throw but it did not');
} catch (thrown) {
expect(thrown.message).toEqual(
`While loading foo.${extension}: SyntaxError: some details but no filename, not even in the stack trace`
);
expect(thrown.cause).toBe(underlyingError);
}
});
it('does not modify errors that are not SyntaxError instances', async function() {
const underlyingError = new Error('nope');
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
await expectAsync(loader.load(`foo.${extension}`)).toBeRejectedWith(underlyingError);
});
it('does not modify SyntaxErrors that mention the imported filename as a Unix-style path', async function() {
const underlyingError = new SyntaxError('nope');
underlyingError.stack = `/the/absolute/path/to/foo.${extension}:1\n` +
'\n' +
'\n' +
'\n' +
'maybe some more stack\n';
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
await expectAsync(loader.load(`path/to/foo.${extension}`))
.toBeRejectedWith(underlyingError);
});
it('does not modify SyntaxErrors that mention the imported filename as a Unix-style file URL', async function() {
const underlyingError = new SyntaxError('nope');
underlyingError.stack += `\n at async file:///the/absolute/path/to/foo.${extension}:1:1`;
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
await expectAsync(loader.load(`path/to/foo.${extension}`))
.toBeRejectedWith(underlyingError);
});
it('does not modify SyntaxErrors that mention the imported filename as a Windows-style path', async function() {
const underlyingError = new SyntaxError('nope');
underlyingError.stack = `c:\\the\\absolute\\path\\to\\foo.${extension}:1\n` +
'\n' +
'\n' +
'\n' +
'maybe some more stack\n';
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
await expectAsync(loader.load(`path/to/foo.${extension}`))
.toBeRejectedWith(underlyingError);
});
it('does not modify SyntaxErrors that mention the imported filename as a Windows-style file URL', async function() {
const underlyingError = new SyntaxError('nope');
underlyingError.stack += `\n at async file:///c:/the/absolute/path/to/foo.${extension}:1:1`;
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
await expectAsync(loader.load(`path/to/foo.${extension}`))
.toBeRejectedWith(underlyingError);
});
it('does not modify SyntaxErrors when the stack trace starts with any Unix-style path', async function() {
const underlyingError = new SyntaxError('nope');
underlyingError.stack = '/some/path/to/a/file.js:1\n\n\n\n' + underlyingError.stack;
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
await expectAsync(loader.load(`path/to/some/other/file.${extension}`))
.toBeRejectedWith(underlyingError);
});
it('does not modify SyntaxErrors when the stack trace starts with any Windows-style path', async function() {
const underlyingError = new SyntaxError('nope');
underlyingError.stack = 'c:\\some\\path\\to\\a\\file.js:1\n\n\n\n' + underlyingError.stack;
const loader = new Loader({importShim: () => Promise.reject(underlyingError)});
await expectAsync(loader.load(`path/to/some/other/file.${extension}`))
.toBeRejectedWith(underlyingError);
});
}
jasmine-jasmine-npm-3c2955c/spec/npm_package_spec.js 0000664 0000000 0000000 00000003266 15240143636 0022475 0 ustar 00root root 0000000 0000000 const path = require('path');
const fs = require('fs');
const os = require('os');
const child_process = require('child_process');
describe('npm package', function() {
beforeAll(function() {
const prefix = path.join(os.tmpdir(), 'jasmine-npm-package');
this.tmpDir = fs.mkdtempSync(prefix);
const packOutput = child_process.execSync('npm pack', {
encoding: 'utf8',
stdio: ['pipe', 'pipe', 'pipe']
});
this.tarball = packOutput.split('\n')[0];
child_process.execSync(`tar -xzf ${this.tarball} -C ${this.tmpDir}`, {
encoding: 'utf8'
});
});
beforeEach(function() {
jasmine.addMatchers({
toExistInPath: function() {
return {
compare: function(actual, expected) {
const fullPath = path.resolve(expected, actual);
return {
pass: fs.existsSync(fullPath)
};
}
};
}
});
});
afterAll(function() {
fs.unlinkSync(this.tarball);
fs.rmSync(this.tmpDir, {recursive: true});
});
it('has a jasmine script', function() {
expect('package/bin/jasmine.js').toExistInPath(this.tmpDir);
});
it('has a jasmine module', function() {
expect('package/lib/jasmine.js').toExistInPath(this.tmpDir);
});
it('contains only the expected root entries', function() {
const files = fs.readdirSync(this.tmpDir);
expect(files).toEqual(['package']);
});
it('contains only the expected entries in the package dir', function() {
const files = fs.readdirSync(path.resolve(this.tmpDir, 'package'));
files.sort();
expect(files).toEqual([
'LICENSE',
'README.md',
'bin',
'lib',
'package.json',
]);
});
});
jasmine-jasmine-npm-3c2955c/spec/parallel_runner_spec.js 0000664 0000000 0000000 00000133434 15240143636 0023416 0 ustar 00root root 0000000 0000000 const path = require('path');
const EventEmitter = require('node:events');
const ConsoleReporter = require('@jasminejs/reporters/console');
const {sharedRunnerBehaviors, pathEndingWith} = require('./shared_runner_behaviors');
const ParallelRunner = require("../lib/parallel_runner");
const {poll, shortPoll} = require('./poll');
const realJasmineCore = require('jasmine-core');
describe('ParallelRunner', function() {
const forwardedReporterEvents = ['suiteStarted', 'suiteDone', 'specStarted', 'specDone'];
const nonForwardedReporterEvents = ['jasmineStarted', 'jasmineDone'];
beforeEach(function () {
this.cluster = jasmine.createSpyObj(
'cluster',
['fork', 'setupPrimary', 'disconnect']
);
this.cluster.workers = {};
this.cluster.disconnect.and.callFake(function (cb) {
cb();
});
let nextWorkerId = 0;
this.cluster.fork.and.callFake(() => {
const worker = new EventEmitter();
worker.id = nextWorkerId++;
worker.send = jasmine.createSpy('worker.send');
this.cluster.workers[worker.id] = worker;
return worker;
});
this.consoleReporter = jasmine.createSpyObj(
'consoleReporter',
[
'configure',
...forwardedReporterEvents,
...nonForwardedReporterEvents
]
);
const consoleReporter = this.consoleReporter;
this.ConsoleReporter = function() {
return consoleReporter;
};
this.globalSetupOrTeardownRunner = jasmine.createSpyObj(
'globalSetupOrTeardownRunner', ['run']
);
// Use the real ParallelReportDispatcher but prevent it from overriding
// global error handling so that we don't accidentally ignore errors in
// the specs
function ParallelReportDispatcher(onError) {
return new realJasmineCore.jasmine.ParallelReportDispatcher(
onError,
{globalErrors: new StubGlobalErrors()}
);
}
this.testJasmine = new ParallelRunner({
jasmineCore: stubCore(),
cluster: this.cluster,
ConsoleReporter: this.ConsoleReporter,
ParallelReportDispatcher,
globalSetupOrTeardownRunner: this.globalSetupOrTeardownRunner
});
this.testJasmine.exit = dontExit;
this.execute = execute;
this.emitBooted = worker => worker.emit('message', {type: 'booted'});
this.emitReadyForConfig = worker => worker.emit('message', {type: 'readyForConfig'});
this.emitAllBooted = async () => {
await shortPoll(
() => Object.values(this.cluster.workers).length > 0,
'workers to be created'
);
for (const worker of Object.values(this.cluster.workers)) {
this.emitBooted(worker);
}
};
this.emitSpecDone = (worker, payload) => {
worker.emit(
'message',
{type: 'reporterEvent', eventName: 'specDone', payload}
);
};
this.emitSuiteDone = (worker, payload) => {
worker.emit(
'message',
{type: 'reporterEvent', eventName: 'suiteDone', payload}
);
};
this.emitFileDone = (worker, payload) => {
worker.emit('message', {
type: 'specFileDone',
failedExpectations: [],
deprecationWarnings: [],
...payload
});
};
this.disconnect = async () => {
await new Promise(resolve => setTimeout(resolve));
expect(this.cluster.disconnect).toHaveBeenCalled();
this.cluster.disconnect.calls.argsFor(0)[0]();
};
});
sharedRunnerBehaviors(function (options) {
return new ParallelRunner({
...options,
jasmineCore: stubCore(),
});
});
it('registers a console reporter upon construction', function() {
this.testJasmine.reportDispatcher_.specStarted('payload');
expect(this.consoleReporter.specStarted).toHaveBeenCalledWith('payload');
});
it('can add and clear reporters', function() {
const reporter = {
someProperty: 'some value',
reporterCapabilities: {parallel: true},
jasmineStarted: jasmine.createSpy('reporter.jasmineStarted')
};
this.testJasmine.addReporter(reporter);
this.testJasmine.reportDispatcher_.jasmineStarted({});
expect(reporter.jasmineStarted).toHaveBeenCalled();
reporter.jasmineStarted.calls.reset();
this.testJasmine.clearReporters();
this.testJasmine.reportDispatcher_.jasmineStarted({});
expect(reporter.jasmineStarted).not.toHaveBeenCalled();
});
describe('Reporter validation', function() {
it('rejects reporters that do not declare parallel support', function () {
const expectedMsg = "Can't use this reporter because it doesn't support " +
'parallel mode. (Add reporterCapabilities: {parallel: true} if ' +
'the reporter meets the requirements for parallel mode.)';
const reporter = jasmine.createSpyObj('reporter', ['jasmineStarted']);
expect(() => this.testJasmine.addReporter(reporter))
.withContext('no reporterCapabilities')
.toThrowError(expectedMsg);
reporter.reporterCapabilities = {};
expect(() => this.testJasmine.addReporter(reporter))
.withContext('no reporterCapabilities.parallel')
.toThrowError(expectedMsg);
reporter.reporterCapabilities.parallel = false;
expect(() => this.testJasmine.addReporter(reporter))
.withContext('reporterCapabilities.parallel = false')
.toThrowError(expectedMsg);
this.testJasmine.reportDispatcher_.jasmineStarted({});
expect(reporter.jasmineStarted).not.toHaveBeenCalled();
});
it('provides additional context when the reporter is in the config file', async function() {
const promise = this.testJasmine.loadConfig({
reporters: [
{reporterCapabilities: {parallel: true}},
{}
]
});
await expectAsync(promise).toBeRejectedWithError(
"Can't use the reporter in position 1 of " +
"the configuration's reporters array because it doesn't support " +
'parallel mode. (Add reporterCapabilities: {parallel: true} if ' +
'the reporter meets the requirements for parallel mode.)'
);
});
it('accepts the built-in console reporter', function() {
this.testJasmine.addReporter(new ConsoleReporter());
});
});
it('can use a caller-specified jasmine-core', async function() {
const jasmineCorePath = 'my-custom-jasmine-core.js';
const callerSpecifiedCore = {
jasmine: jasmine.createSpyObj('callerSpecifiedCore.jasmine', [
'ParallelReportDispatcher',
'Timer',
]),
files: {
self: jasmineCorePath
}
};
callerSpecifiedCore.jasmine.ParallelReportDispatcher.and.returnValue({
addReporter() {}
});
callerSpecifiedCore.jasmine.Timer.and.returnValue({
start() {}
});
this.testJasmine = new ParallelRunner({
jasmineCore: callerSpecifiedCore,
cluster: this.cluster,
ConsoleReporter: this.ConsoleReporter,
});
this.testJasmine.exit = dontExit;
expect(callerSpecifiedCore.jasmine.ParallelReportDispatcher).toHaveBeenCalled();
expect(callerSpecifiedCore.jasmine.Timer).toHaveBeenCalled();
this.testJasmine.execute();
await poll(() => Object.values(this.cluster.workers).length > 0);
for (const worker of Object.values(this.cluster.workers)) {
this.emitReadyForConfig(worker);
expect(worker.send).toHaveBeenCalledWith(
{
type: 'configure',
configuration: jasmine.objectContaining({jasmineCorePath}),
}
);
}
});
describe('#execute', function() {
it('creates the configured number of worker processes', async function () {
this.testJasmine = new ParallelRunner({
jasmineCore: stubCore(),
cluster: this.cluster,
numWorkers: 17,
ConsoleReporter: this.ConsoleReporter,
});
this.testJasmine.exit = dontExit;
this.testJasmine.execute();
await shortPoll(
() => this.cluster.fork.calls.any(),
'cluster.fork to have been called'
);
const expectedPath = path.join(__dirname, '../bin/worker.js');
expect(this.cluster.setupPrimary).toHaveBeenCalledWith({
exec: expectedPath,
});
expect(this.cluster.fork).toHaveBeenCalledTimes(17);
});
it('configures the workers and waits for them to acknowledge', async function () {
this.testJasmine = new ParallelRunner({
jasmineCore: stubCore(),
cluster: this.cluster,
ConsoleReporter: this.ConsoleReporter,
numWorkers: 2,
globals: false,
});
const envConfig = {
stopSpecOnExpectationFailure: true,
};
await this.testJasmine.loadConfig({
spec_dir: 'spec/fixtures/parallel_helpers',
helpers: ['helper*.js'],
requires: ['require1', 'require2'],
env: envConfig,
});
this.testJasmine.addSpecFile('aSpec.js');
spyOn(this.testJasmine, 'runSpecFiles_')
.and.returnValue(new Promise(() => {
}));
this.testJasmine.execute(null, 'myFilterString');
await shortPoll(
() => this.cluster.fork.calls.any(),
'cluster.fork to have been called'
);
const workers = this.cluster.fork.calls.all().map(c => c.returnValue);
expect(workers[0].send).not.toHaveBeenCalled();
expect(workers[1].send).not.toHaveBeenCalled();
const expectedConfig = {
filter: 'myFilterString',
spec_dir: 'spec/fixtures/parallel_helpers',
helpers: [
pathEndingWith('spec/fixtures/parallel_helpers/helper1.js')
],
requires: ['require1', 'require2'],
globals: false,
env: envConfig,
};
this.emitReadyForConfig(workers[0]);
expect(workers[0].send).toHaveBeenCalledWith(
{type: 'configure', configuration: expectedConfig}
);
expect(workers[1].send).not.toHaveBeenCalled();
this.emitReadyForConfig(workers[1]);
expect(workers[1].send).toHaveBeenCalledWith(
{type: 'configure', configuration: expectedConfig}
);
this.emitBooted(workers[0]);
await new Promise(resolve => setTimeout(resolve));
expect(this.testJasmine.runSpecFiles_).not.toHaveBeenCalled();
this.emitBooted(workers[1]);
await new Promise(resolve => setTimeout(resolve));
expect(this.testJasmine.runSpecFiles_).toHaveBeenCalled();
});
it('initially assigns one spec file to each process', async function () {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
const specFiles = ['spec1.js', 'spec2.js', 'spec3.js'];
for (const f of specFiles) {
this.testJasmine.addSpecFile(f);
}
this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => {
this.cluster.workers[0].send
.withArgs(jasmine.objectContaining({type: 'runSpecFile'}))
.and.callFake(() => resolve());
});
expect(this.cluster.workers[0].send).toHaveBeenCalledWith(
{type: 'runSpecFile', filePath: jasmine.any(String)}
);
expect(this.cluster.workers[1].send).toHaveBeenCalledWith(
{type: 'runSpecFile', filePath: jasmine.any(String)}
);
const specFilesRan = new Set(getSpecFilesRan(this.cluster.workers));
expect(specFilesRan.size).toEqual(2);
for (const f of specFilesRan) {
expect(specFiles).toContain(f);
}
});
describe('When a worker finishes processing a spec file', function () {
it('assigns another spec file', async function () {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
const specFiles = ['spec1.js', 'spec2,js', 'spec3.js'];
for (const f of specFiles) {
this.testJasmine.addSpecFile(f);
}
this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
const alreadyRanSpecs = getSpecFilesRan(this.cluster.workers);
expect(alreadyRanSpecs.length).withContext('number of spec files initially ran').toEqual(2);
const remainingSpec = specFiles.filter(f => !alreadyRanSpecs.includes(f))[0];
this.emitFileDone(this.cluster.workers[0]);
expect(this.cluster.workers[0].send).toHaveBeenCalledWith(
{type: 'runSpecFile', filePath: remainingSpec}
);
});
it('finishes when all workers are idle', async function () {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
this.testJasmine.addSpecFile('spec3.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.emitFileDone(this.cluster.workers[0]);
this.emitFileDone(this.cluster.workers[1]);
await expectAsync(executePromise).toBePending();
this.emitFileDone(this.cluster.workers[0]);
await new Promise(resolve => setTimeout(resolve));
await this.disconnect();
await expectAsync(executePromise).toBeResolved();
});
});
it('dispatches a jasmineStarted event at the start of execution', async function () {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
expect(this.consoleReporter.jasmineStarted).toHaveBeenCalledWith({
parallel: true
});
});
describe('When all workers are idle', function () {
beforeEach(async function () {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
this.testJasmine.addSpecFile('spec3.js');
this.executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.emitSpecDone(this.cluster.workers[0], {status: 'passed'});
this.emitFileDone(this.cluster.workers[0]);
this.emitSpecDone(this.cluster.workers[1], {status: 'passed'});
this.emitFileDone(this.cluster.workers[1]);
this.emitSpecDone(this.cluster.workers[0], {status: 'passed'});
this.emitFileDone(this.cluster.workers[0]);
await this.disconnect();
this.expectedJasmineDoneEvent = {
overallStatus: 'passed',
totalTime: jasmine.any(Number),
numWorkers: 2,
failedExpectations: [],
deprecationWarnings: []
};
});
it('dispatches a jasmineDone event', async function () {
await this.executePromise;
expect(this.consoleReporter.jasmineDone).toHaveBeenCalledWith(
this.expectedJasmineDoneEvent);
});
it('resolves the returned promise to the jasmineDone event', async function () {
await expectAsync(this.executePromise).toBeResolvedTo(
this.expectedJasmineDoneEvent
);
});
});
it('sets the jasmineDone event status to failed when there are spec failures', async function () {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.emitSpecDone(this.cluster.workers[0], {status: 'passed'});
this.emitFileDone(this.cluster.workers[0]);
this.emitSpecDone(this.cluster.workers[1], {status: 'passed'});
this.emitSpecDone(this.cluster.workers[1], {status: 'failed'});
this.emitFileDone(this.cluster.workers[1]);
await this.disconnect();
await executePromise;
expect(this.consoleReporter.jasmineDone).toHaveBeenCalledWith(
jasmine.objectContaining({
overallStatus: 'failed'
})
);
});
it('sets the jasmineDone event status to failed when there are suite failures', async function () {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.emitSuiteDone(this.cluster.workers[0], {status: 'passed'});
this.emitFileDone(this.cluster.workers[0]);
this.emitSuiteDone(this.cluster.workers[1], {status: 'passed'});
this.emitSuiteDone(this.cluster.workers[1], {status: 'failed'});
this.emitFileDone(this.cluster.workers[1]);
await this.disconnect();
await executePromise;
expect(this.consoleReporter.jasmineDone).toHaveBeenCalledWith(
jasmine.objectContaining({
overallStatus: 'failed'
})
);
});
it('sets the jasmineDone event status to incomplete when there are focused runables', async function () {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.emitFileDone(this.cluster.workers[0], {
overallStatus: 'incomplete',
incompleteCode: 'focused',
incompleteReason: 'fit() or fdescribe() was found'
});
this.emitFileDone(this.cluster.workers[1]);
await this.disconnect();
await executePromise;
expect(this.consoleReporter.jasmineDone).toHaveBeenCalledWith(
jasmine.objectContaining({
overallStatus: 'incomplete',
incompleteCode: 'focused',
incompleteReason: 'fit() or fdescribe() was found'
})
);
});
it('sets the jasmineDone event status to incomplete when there are no specs', async function () {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.emitFileDone(this.cluster.workers[0], {
overallStatus: 'incomplete',
incompleteCode: 'noSpecsFound',
});
this.emitFileDone(this.cluster.workers[1], {
overallStatus: 'incomplete',
incompleteCode: 'noSpecsFound',
});
await this.disconnect();
await executePromise;
expect(this.consoleReporter.jasmineDone).toHaveBeenCalledWith(
jasmine.objectContaining({
overallStatus: 'incomplete',
incompleteCode: 'noSpecsFound',
incompleteReason: 'No specs found'
})
);
});
it('does not set the jasmineDone event status to incomplete when one file has no specs', async function () {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.emitFileDone(this.cluster.workers[0], {
overallStatus: 'incomplete',
incompleteCode: 'noSpecsFound',
});
this.emitFileDone(this.cluster.workers[1]);
await this.disconnect();
await executePromise;
expect(this.consoleReporter.jasmineDone).toHaveBeenCalledWith(
jasmine.objectContaining({
overallStatus: 'passed',
})
);
});
it('merges top level failedExpectations and deprecationWarnings from workers', async function () {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
this.testJasmine.addSpecFile('spec3.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.emitFileDone(this.cluster.workers[0], {
failedExpectations: ['failed expectation 1'],
deprecationWarnings: ['deprecation 1'],
});
this.emitFileDone(this.cluster.workers[1], {
failedExpectations: ['failed expectation 2'],
deprecationWarnings: ['deprecation 2'],
});
this.emitFileDone(this.cluster.workers[0], {
failedExpectations: ['failed expectation 3'],
deprecationWarnings: ['deprecation 3'],
});
await this.disconnect();
await executePromise;
expect(this.consoleReporter.jasmineDone).toHaveBeenCalledWith(
jasmine.objectContaining({
overallStatus: 'failed',
failedExpectations: [
'failed expectation 1',
'failed expectation 2',
'failed expectation 3',
],
deprecationWarnings: [
'deprecation 1',
'deprecation 2',
'deprecation 3',
]
})
);
});
describe('Handling reporter events from workers', function () {
beforeEach(async function () {
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.execute();
await this.emitAllBooted();
await poll(() => {
return this.cluster.workers[0].listeners('message').length > 0;
});
});
for (const eventName of forwardedReporterEvents) {
it(`forwards the ${eventName} event to reporters`, async function () {
const reporter = jasmine.createSpyObj('reporter', [eventName]);
reporter.reporterCapabilities = {parallel: true};
this.testJasmine.addReporter(reporter);
const payload = 'arbitrary event payload';
this.cluster.workers[0].emit(
'message', {type: 'reporterEvent', eventName, payload}
);
expect(reporter[eventName]).toHaveBeenCalledWith(payload);
});
}
for (const eventName of nonForwardedReporterEvents) {
it(`does not forward the ${eventName} event to reporters`, async function () {
const reporter = jasmine.createSpyObj('reporter', [eventName]);
reporter.reporterCapabilities = {parallel: true};
this.testJasmine.addReporter(reporter);
this.cluster.workers[0].emit(
'message',
{type: 'reporterEvent', eventName, payload: 'arbitrary event payload'}
);
expect(reporter[eventName]).not.toHaveBeenCalled();
});
}
});
it('reports unhandled exceptions and promise rejections from workers', async function() {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.emitFileDone(this.cluster.workers[0], {
failedExpectations: ['failed expectation 1'],
deprecationWarnings: [],
});
this.cluster.workers[0].emit('message', {
type: 'uncaughtException',
error: {
message: 'not caught',
stack: 'it happened here'
},
});
this.cluster.workers[0].emit('message', {
type: 'unhandledRejection',
error: {
message: 'not handled',
stack: 'it happened there'
},
});
this.emitFileDone(this.cluster.workers[1], {
failedExpectations: ['failed expectation 2'],
deprecationWarnings: [''],
});
await this.disconnect();
await executePromise;
expect(this.consoleReporter.jasmineDone).toHaveBeenCalledWith(
jasmine.objectContaining({
overallStatus: 'failed',
failedExpectations: [
'failed expectation 1',
// We don't just pass these through from jasmine-core,
// so verify the actual output format.
{
actual: '',
expected: '',
globalErrorType: 'lateError',
matcherName: '',
message: 'Uncaught exception in worker process: not caught',
passed: false,
stack: 'it happened here',
},
{
actual: '',
expected: '',
globalErrorType: 'lateError',
matcherName: '',
message: 'Unhandled promise rejection in worker process: not handled',
passed: false,
stack: 'it happened there',
},
'failed expectation 2',
],
})
);
});
describe('When a spec file fails to load', function() {
function captor(valueCb) {
return {
asymmetricMatch(v) {
valueCb(v);
return true;
},
jasmineToString() {
return '';
}
};
}
it('moves on to the next file', async function() {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
const specFiles = ['spec1.js', 'spec2.js', 'spec3.js'];
for (const f of specFiles) {
this.testJasmine.addSpecFile(f);
}
this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
let worker0SpecFile, worker1SpecFile;
expect(this.cluster.workers[0].send).toHaveBeenCalledWith(
jasmine.objectContaining({
type: 'runSpecFile',
filePath: captor(v => worker0SpecFile = v)
})
);
expect(this.cluster.workers[1].send).toHaveBeenCalledWith(
jasmine.objectContaining({
type: 'runSpecFile',
filePath: captor(v => worker1SpecFile = v)
})
);
this.cluster.workers[0].send.calls.reset();
const remainingSpecFile = specFiles
.filter(f => f !== worker0SpecFile && f !== worker1SpecFile)[0];
this.cluster.workers[0].emit('message',
{
type: 'specFileLoadError',
filePath: worker0SpecFile,
error: {
message: 'not caught',
stack: 'it happened here'
},
}
);
expect(this.cluster.workers[0].send).toHaveBeenCalledWith(
{type: 'runSpecFile', filePath: remainingSpecFile}
);
});
it('reports the error', async function () {
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
let worker1SpecFile;
expect(this.cluster.workers[1].send).toHaveBeenCalledWith(
jasmine.objectContaining({
type: 'runSpecFile',
filePath: captor(v => worker1SpecFile = v)
})
);
this.emitFileDone(this.cluster.workers[0], {
failedExpectations: ['failed expectation 1'],
deprecationWarnings: [],
});
this.cluster.workers[1].emit('message',
{
type: 'specFileLoadError',
filePath: worker1SpecFile,
error: {
message: 'not caught',
stack: 'it happened here'
},
}
);
await this.disconnect();
await executePromise;
expect(this.consoleReporter.jasmineDone).toHaveBeenCalledWith(
jasmine.objectContaining({
overallStatus: 'failed',
failedExpectations: [
'failed expectation 1',
// We don't just pass this through from jasmine-core,
// so verify the actual output format.
{
actual: '',
expected: '',
globalErrorType: 'load',
matcherName: '',
message: `Error loading ${worker1SpecFile}: not caught`,
passed: false,
stack: 'it happened here',
}
],
})
);
});
});
it('handles errors from reporters', async function() {
const reportDispatcher = new StubParallelReportDispatcher();
spyOn(reportDispatcher, 'installGlobalErrors');
spyOn(reportDispatcher, 'uninstallGlobalErrors');
let reportDispatcherOnError;
this.testJasmine = new ParallelRunner({
jasmineCore: stubCore(),
cluster: this.cluster,
ParallelReportDispatcher: function(onError) {
reportDispatcherOnError = onError;
return reportDispatcher;
}
});
spyOn(this.testJasmine, 'exit');
spyOn(this.testJasmine, 'runSpecFiles_').and.callFake(function() {
expect(reportDispatcher.installGlobalErrors).toHaveBeenCalled();
expect(reportDispatcher.uninstallGlobalErrors).not.toHaveBeenCalled();
reportDispatcherOnError(new Error('nope'));
return Promise.resolve();
});
spyOn(console, 'error');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await expectAsync(executePromise).toBeRejectedWithError(
'Unhandled exceptions, unhandled promise rejections, or reporter ' +
'errors were encountered during execution'
);
expect(console.error).toHaveBeenCalledWith(new Error('nope'));
expect(this.testJasmine.exit).toHaveBeenCalledWith(1);
expect(reportDispatcher.uninstallGlobalErrors).toHaveBeenCalled();
});
describe('When stopSpecOnExpectationFailure is true', function () {
beforeEach(async function () {
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir',
env: { stopOnSpecFailure: true },
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
this.testJasmine.addSpecFile('spec3.js');
this.testJasmine.addSpecFile('spec4.js');
this.executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await poll(() => {
return numRunSpecFileCalls(this.cluster.workers[0]) === 1
&& numRunSpecFileCalls(this.cluster.workers[1]) === 1;
});
});
it('makes a best effort to stop after a spec failure', async function () {
this.emitSpecDone(this.cluster.workers[0], {status: 'failed'});
this.emitFileDone(this.cluster.workers[0]);
this.emitFileDone(this.cluster.workers[1]);
await this.executePromise;
expect(numRunSpecFileCalls(this.cluster.workers[0])).toEqual(1);
expect(numRunSpecFileCalls(this.cluster.workers[1])).toEqual(1);
});
it('makes a best effort to stop after a suite failure', async function () {
this.emitSuiteDone(this.cluster.workers[0], {status: 'failed'});
this.emitFileDone(this.cluster.workers[0]);
this.emitFileDone(this.cluster.workers[1]);
await this.executePromise;
expect(numRunSpecFileCalls(this.cluster.workers[0])).toEqual(1);
expect(numRunSpecFileCalls(this.cluster.workers[1])).toEqual(1);
});
function numRunSpecFileCalls(worker) {
return worker.send.calls.all()
.filter(call => call.args[0].type === 'runSpecFile')
.length;
}
});
describe('When a worker reports a fatal error', function () {
describe('When exitOnCompletion is true', function() {
it('exits', async function () {
spyOn(console, 'error');
spyOn(this.testJasmine, 'exit');
expect(this.testJasmine.exitOnCompletion).toBeTrue();
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.cluster.workers[0].emit('message', {
type: 'fatalError',
error: new Error('nope'),
});
await expectAsync(executePromise).toBeRejectedWithError(
/Fatal error in Jasmine worker process/
);
expect(this.testJasmine.exit).toHaveBeenCalledWith(1);
});
});
describe('When exitOnCompletion is false', function() {
it('fails without exiting', async function () {
spyOn(console, 'error');
spyOn(this.testJasmine, 'exit');
this.testJasmine.exitOnCompletion = false;
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.cluster.workers[0].emit('message', {
type: 'fatalError',
error: new Error('nope'),
});
await expectAsync(executePromise).toBeRejectedWithError(
/Fatal error in Jasmine worker process/
);
expect(this.testJasmine.exit).not.toHaveBeenCalled();
});
});
it('does not send additional runSpecFile messages after a fatal error', async function () {
spyOn(console, 'error');
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
this.testJasmine.addSpecFile('spec3.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.cluster.workers[0].emit('message', {
type: 'fatalError',
error: new Error('nope'),
});
this.cluster.workers[0].send.calls.reset();
this.cluster.workers[1].send.calls.reset();
this.emitFileDone(this.cluster.workers[1]);
await expectAsync(executePromise).toBeRejectedWithError(
/Fatal error in Jasmine worker process/
);
expect(this.cluster.workers[0].send).not.toHaveBeenCalled();
expect(this.cluster.workers[1].send).not.toHaveBeenCalled();
});
});
describe('Handling worker exit', function () {
it('fails if the worker exits before the suite is finished', async function () {
spyOn(console, 'error');
spyOn(this.testJasmine, 'exit');
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.cluster.workers[0].emit('exit', {});
await expectAsync(executePromise).toBeRejectedWithError(
/Fatal error in Jasmine worker process/
);
expect(this.testJasmine.exit).toHaveBeenCalledWith(4);
});
it('does not fail when the worker exits after the suite is finished', async function () {
spyOn(console, 'error');
spyOn(this.testJasmine, 'exit');
this.testJasmine.numWorkers = 2;
await this.testJasmine.loadConfig({
spec_dir: 'some/spec/dir'
});
this.testJasmine.addSpecFile('spec1.js');
this.testJasmine.addSpecFile('spec2.js');
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await new Promise(resolve => setTimeout(resolve));
this.emitFileDone(this.cluster.workers[0]);
this.emitFileDone(this.cluster.workers[1]);
this.cluster.workers[0].emit('exit', {});
await executePromise;
expect(this.testJasmine.exit).toHaveBeenCalledWith(0);
expect(console.error).not.toHaveBeenCalled();
});
});
it('rejects if called more than once', async function () {
this.testJasmine.execute();
await expectAsync(this.testJasmine.execute()).toBeRejectedWithError(
'Parallel runner instance can only be executed once'
);
});
describe('when a globalSetup is configured', function () {
it('waits for globalSetup to complete before creating workers', async function () {
let resolve;
this.globalSetupOrTeardownRunner.run.and.returnValue(
new Promise(res => resolve = res)
);
function globalSetup() {}
await this.testJasmine.loadConfig({globalSetup});
this.testJasmine.execute();
await new Promise(res => setTimeout(res));
expect(this.cluster.fork).not.toHaveBeenCalled();
expect(this.globalSetupOrTeardownRunner.run).toHaveBeenCalledWith(
'globalSetup', globalSetup, undefined
);
resolve();
await poll(() => this.cluster.fork.calls.any());
});
it('fails if globalSetup fails', async function() {
this.globalSetupOrTeardownRunner.run.and.rejectWith(new Error('nope'));
await this.testJasmine.loadConfig({
globalSetup() {}
});
await expectAsync(this.testJasmine.execute()).toBeRejectedWithError('nope');
});
it('uses a configured timeout', async function() {
this.globalSetupOrTeardownRunner.run.and.returnValue(
new Promise(() => {})
);
function globalSetup() {}
await this.testJasmine.loadConfig({
globalSetup,
globalSetupTimeout: 17
});
this.testJasmine.execute();
expect(this.globalSetupOrTeardownRunner.run).toHaveBeenCalledWith(
'globalSetup', globalSetup, 17
);
});
});
describe('when a globalTeardown is configured', function () {
it('waits for globalTeardown to complete after execution finishes', async function () {
let reportedDone = false;
let resolveTeardown;
this.globalSetupOrTeardownRunner.run.and.callFake(function() {
return new Promise(function(res) {
resolveTeardown = res;
expect(reportedDone).toBeTrue();
});
});
function globalTeardown() {}
await this.testJasmine.loadConfig({
globalTeardown,
reporters: [{
jasmineDone() {
reportedDone = true;
},
reporterCapabilities: {parallel: true}
}]
});
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
expect(this.globalSetupOrTeardownRunner.run).not.toHaveBeenCalled();
await new Promise(res => setTimeout(res));
expect(this.globalSetupOrTeardownRunner.run).toHaveBeenCalledWith(
'globalTeardown', globalTeardown, undefined
);
await new Promise(res => setTimeout(res));
await expectAsync(executePromise).toBePending();
resolveTeardown();
await executePromise;
});
it('fails if globalTeardown fails', async function() {
this.globalSetupOrTeardownRunner.run.and.rejectWith(new Error('nope'));
await this.testJasmine.loadConfig({
globalTeardown() {}
});
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await expectAsync(executePromise).toBeRejectedWithError('nope');
});
it('runs globalTeardown even if execution fails', async function() {
spyOn(this.testJasmine, 'runSpecFiles_')
.and.rejectWith(new Error('spec running failed'));
this.globalSetupOrTeardownRunner.run.and.resolveTo();
await this.testJasmine.loadConfig({
globalTeardown() {}
});
const executePromise = this.testJasmine.execute();
await this.emitAllBooted();
await expectAsync(executePromise)
.toBeRejectedWithError('spec running failed');
expect(this.globalSetupOrTeardownRunner.run).toHaveBeenCalled();
});
it('uses a configured timeout', async function() {
this.globalSetupOrTeardownRunner.run.and.returnValue(
new Promise(() => {})
);
function globalTeardown() {}
await this.testJasmine.loadConfig({
globalTeardown,
globalTeardownTimeout: 17
});
this.testJasmine.execute();
await this.emitAllBooted();
await shortPoll(
() => this.globalSetupOrTeardownRunner.run.calls.any(),
'globalTeardown to have been run'
);
expect(this.globalSetupOrTeardownRunner.run).toHaveBeenCalledWith(
'globalTeardown', globalTeardown, 17
);
});
});
});
describe('#configureEnv', function() {
it('throws if called after execution starts', function() {
this.testJasmine.execute();
expect(() => this.testJasmine.configureEnv({}))
.toThrowError("Can't call configureEnv() after execute()");
});
it('throws if specFilter is set', function() {
const config = {
specFilter: function() {}
};
expect(() => this.testJasmine.configureEnv(config))
.toThrowError('The specFilter config property is not supported in ' +
'parallel mode');
});
});
describe('Loading configuration', function() {
it('adds specified reporters', async function () {
const reporters = [
{id: 'reporter1', reporterCapabilities: {parallel: true},
jasmineStarted: jasmine.createSpy('reporter1.jasmineStarted')},
{id: 'reporter2', reporterCapabilities: {parallel: true},
jasmineStarted: jasmine.createSpy('reporter2.jasmineStarted')},
];
await this.testJasmine.loadConfig({reporters});
this.testJasmine.reportDispatcher_.jasmineStarted({});
expect(reporters[0].jasmineStarted).toHaveBeenCalled();
expect(reporters[1].jasmineStarted).toHaveBeenCalled();
});
});
it('does not allow randomization to be disabled', function() {
expect(() => this.testJasmine.randomizeTests(false))
.toThrowError('Randomization cannot be disabled in parallel mode');
expect(() => this.testJasmine.randomizeTests(true))
.not.toThrow();
});
it('does not allow random seed to be set', function() {
expect(() => this.testJasmine.seed(1234))
.toThrowError('Random seed cannot be set in parallel mode');
});
describe('When running on Windows', function () {
function windows() {
return 'win32';
}
it('converts backslashes in the project base dir to slashes, for compatibility with glob', function () {
const subject = new ParallelRunner({
jasmineCore: stubCore(),
projectBaseDir: 'c:\\foo\\bar',
platform: windows,
cluster: this.cluster,
});
expect(subject.projectBaseDir).toEqual('c:/foo/bar');
});
});
});
async function execute(options = {}) {
if (this.testJasmine.specFiles.length === 0) {
this.testJasmine.addSpecFile('aSpec.js');
} else if (this.testJasmine.specFiles.length > 1) {
// The code below could be adapted to work with an arbitrary nonzero number
// of spec files, but so far there's been no need.
throw new Error('Need exactly one spec file');
}
const executeArgs = options.executeArgs || [];
const promise = this.testJasmine.execute.apply(this.testJasmine, executeArgs);
await this.emitAllBooted();
await shortPoll(
() => getSpecFilesRan(this.cluster.workers).length === 1,
'spec file to have been started'
);
const msg = {};
switch (options.overallStatus) {
case undefined:
case 'passed':
break;
case 'failed':
msg.failedExpectations = ['a failed expectation 1'];
break;
case 'incomplete':
msg.incompleteCode = 'focused';
msg.incompleteReason = 'fit() or fdescribe() was found';
break;
default:
throw new Error(`Unsupported overallStatus ${overallStatus}`);
}
this.emitFileDone(this.cluster.workers[0], msg);
await this.disconnect();
const result = await promise;
if (options.overallStatus) {
expect(this.consoleReporter.jasmineDone).toHaveBeenCalledWith(
jasmine.objectContaining({overallStatus: options.overallStatus})
);
}
return result;
}
function dontExit() {
}
function getSpecFilesRan(workers) {
return Object.values(workers)
.flatMap(worker => worker.send.calls.allArgs())
.map(args => args[0])
.filter(msg => msg.type === 'runSpecFile')
.map(msg => msg.filePath);
}
function stubCore() {
return {
jasmine: {
Timer,
ParallelReportDispatcher: StubParallelReportDispatcher
},
files: []
};
}
class Timer {
start() {}
elapsed() {
return 0;
}
}
class StubParallelReportDispatcher {
installGlobalErrors() {}
uninstallGlobalErrors() {}
addReporter() {}
clearReporters() {}
jasmineStarted() {}
jasmineDone() {}
suiteStarted() {}
suiteDone() {}
specStarted() {}
specDone() {}
}
class StubGlobalErrors {
install() {
this.uninstall = function() {};
}
pushListener() {}
popListener() {}
}
jasmine-jasmine-npm-3c2955c/spec/parallel_worker_spec.js 0000664 0000000 0000000 00000062141 15240143636 0023412 0 ustar 00root root 0000000 0000000 const EventEmitter = require('node:events');
const ParallelWorker = require('../lib/parallel_worker');
describe('ParallelWorker', function() {
beforeEach(function() {
this.clusterWorker = new EventEmitter();
this.clusterWorker.send = jasmine.createSpy('clusterWorker.send');
this.clusterWorker.isConnected = jasmine.createSpy(
'clusterWorker.isConnected'
).and.returnValue(true);
});
describe('When a configure event is received', function() {
it('can use a caller-supplied jasmine-core', async function () {
const loader = jasmine.createSpyObj('loader', ['load']);
const core = dummyCore();
loader.load.and.returnValue(Promise.resolve(core));
new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
jasmineCorePath: './path/to/jasmine-core.js',
helpers: [],
}
});
await Promise.resolve();
expect(loader.load).toHaveBeenCalledWith('./path/to/jasmine-core.js');
expect(loader.load).not.toHaveBeenCalledWith('jasmine-core');
});
it('installs globals globals is undefined', async function () {
const loader = jasmine.createSpyObj('loader', ['load']);
const core = dummyCore();
spyOn(core, 'installGlobals');
loader.load.and.returnValue(Promise.resolve(core));
const jasmineWorker = new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
helpers: [],
}
});
await waitForEnvPromise(jasmineWorker);
expect(loader.load).toHaveBeenCalledWith('jasmine-core');
expect(core.installGlobals).toHaveBeenCalled();
});
it('does not install globals if globals is false', async function() {
const loader = jasmine.createSpyObj('loader', ['load']);
const core = dummyCore();
spyOn(core, 'installGlobals');
loader.load.and.returnValue(Promise.resolve(core));
const jasmineWorker = new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
globals: false,
helpers: [],
}
});
await waitForEnvPromise(jasmineWorker);
expect(loader.load).toHaveBeenCalledWith('jasmine-core');
expect(core.installGlobals).not.toHaveBeenCalled();
});
it('boots jasmine-core normally if globals is true', async function() {
const loader = jasmine.createSpyObj('loader', ['load']);
const core = dummyCore();
spyOn(core, 'installGlobals');
loader.load.and.returnValue(Promise.resolve(core));
const jasmineWorker = new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
globals: true,
helpers: [],
}
});
await waitForEnvPromise(jasmineWorker);
expect(loader.load).toHaveBeenCalledWith('jasmine-core');
expect(core.installGlobals).toHaveBeenCalled();
});
it('sends a fatalError message when the core module fails to load', async function() {
const error = new Error('core loading failed');
const loader = {
load() {
return Promise.reject(error);
}
};
new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {}
});
await new Promise(res => setTimeout(res));
expect(this.clusterWorker.send).toHaveBeenCalledWith(
{
type: 'fatalError',
error: {
message: error.message,
stack: error.stack
},
}
);
});
it('creates and configures an env', async function() {
const env = jasmine.createSpyObj('env', [
'configure', 'addReporter', 'setParallelLoadingState'
]);
const loader = {
load() {
return Promise.resolve(dummyCore(env));
}
};
new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
const envConfig = {
stopSpecOnExpectationFailure: true,
};
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
helpers: [],
env: envConfig,
}
});
await new Promise(res => setTimeout(res));
expect(env.configure).toHaveBeenCalledWith(envConfig);
});
it('supports custom loaders', async function() {
function customLoader(path) {
return new Promise((resolve, reject) => {
if (path === 'jasmine-core') {
resolve(dummyCore());
} else {
reject(new Error(`Unexpected path: ${path}`));
}
});
}
const initialLoader = {
load(path) {
return new Promise((resolve, reject) => {
if (path === 'some/loader/module') {
resolve(customLoader);
} else {
reject(new Error(`Unexpected path: ${path}`));
}
});
}
};
const jasmineWorker = new ParallelWorker({
loader: initialLoader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
loader: 'some/loader/module',
}
});
await new Promise(res => setTimeout(res));
expect(jasmineWorker.loader_).toEqual({load: customLoader});
});
it('applies a spec filter if specified', async function() {
const env = jasmine.createSpyObj('env', [
'addReporter', 'setParallelLoadingState'
]);
let envConfig = {};
env.configure = function(config) {
envConfig = {
...envConfig,
...config
};
};
const loader = {
load() {
return Promise.resolve(dummyCore(env));
}
};
new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
filter: '^foo',
}
});
await new Promise(res => setTimeout(res));
expect(envConfig.specFilter).toEqual(jasmine.any(Function));
expect(envConfig.specFilter({getFullName: () => 'foobar'})).toEqual(true);
expect(envConfig.specFilter({getFullName: () => ' foo'})).toEqual(false);
});
it('loads helper files', async function() {
const loader = jasmine.createSpyObj('loader', ['load']);
const core = dummyCore();
const helperPromises = [], resolveHelperPromises = [];
for (let i = 0; i < 2; i++) {
helperPromises[i] = new Promise(function(resolve) {
resolveHelperPromises[i] = resolve;
});
}
loader.load.withArgs('jasmine-core')
.and.returnValue(Promise.resolve(core));
loader.load.withArgs('/some/dir/helper0.js')
.and.returnValue(helperPromises[0]);
loader.load.withArgs('/some/dir/helper1.js')
.and.returnValue(helperPromises[1]);
new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
helpers: [
'/some/dir/helper0.js',
'/some/dir/helper1.js',
]
}
});
await poll(() => loader.load.calls.count() === 2);
expect(loader.load).toHaveBeenCalledWith('/some/dir/helper0.js');
resolveHelperPromises[0]();
await poll(() => loader.load.calls.count() === 3);
expect(loader.load).toHaveBeenCalledWith('/some/dir/helper1.js');
expect(this.clusterWorker.send).not.toHaveBeenCalledWith({type: 'booted'});
resolveHelperPromises[1]();
await poll(() => this.clusterWorker.send.calls.any());
expect(this.clusterWorker.send).toHaveBeenCalledWith({type: 'booted'});
});
it('loads requires before helpers', async function() {
const loader = jasmine.createSpyObj('loader', ['load']);
const core = dummyCore();
const requirePromises = [], resolveRequirePromises = [];
for (let i = 0; i < 2; i++) {
requirePromises[i] = new Promise(function(resolve) {
resolveRequirePromises[i] = resolve;
});
}
loader.load.withArgs('jasmine-core')
.and.returnValue(Promise.resolve(core));
loader.load.withArgs('/some/dir/require0.js')
.and.returnValue(requirePromises[0]);
loader.load.withArgs('/some/dir/require1.js')
.and.returnValue(requirePromises[1]);
loader.load.withArgs('/some/dir/helper.js')
.and.returnValue(new Promise(() => {}));
new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
helpers: [
'/some/dir/helper.js',
],
requires: [
'/some/dir/require0.js',
'/some/dir/require1.js',
]
}
});
await poll(() => loader.load.calls.count() === 2);
expect(loader.load).toHaveBeenCalledWith('/some/dir/require0.js');
resolveRequirePromises[0]();
await poll(() => loader.load.calls.count() === 3);
expect(loader.load).toHaveBeenCalledWith('/some/dir/require1.js');
expect(loader.load).not.toHaveBeenCalledWith('/some/dir/helper.js');
resolveRequirePromises[1]();
await poll(() => loader.load.calls.count() === 4);
expect(loader.load).toHaveBeenCalledWith('/some/dir/helper.js');
});
});
describe('When a runSpecFile message is received', function() {
beforeEach(async function() {
this.loader = jasmine.createSpyObj('loader', ['load']);
this.env = jasmine.createSpyObj(
'env', ['execute', 'parallelReset', 'addReporter', 'setParallelLoadingState']
);
this.core = dummyCore(this.env);
this.loader.load.withArgs('jasmine-core')
.and.returnValue(Promise.resolve(this.core));
this.jasmineWorker = new ParallelWorker({
loader: this.loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.configure = async () => {
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
helpers: [],
}
});
await waitForEnvPromise(this.jasmineWorker);
this.loader.load.calls.reset();
};
});
it('waits for configuration to finish', async function() {
let resolveLoader;
await this.configure();
this.loader.load.withArgs('aSpec.js').and.returnValue(
new Promise(resolve => {
resolveLoader = resolve;
}
));
this.env.execute.and.returnValue(new Promise(() => {}));
this.clusterWorker.emit('message', {
type: 'runSpecFile',
filePath: 'aSpec.js'
});
await Promise.resolve();
expect(this.env.execute).not.toHaveBeenCalled();
resolveLoader();
await Promise.resolve();
await Promise.resolve();
expect(this.env.execute).toHaveBeenCalledWith();
});
it('loads and runs the spec file', async function() {
this.loader.load.withArgs('jasmine-core')
.and.returnValue(Promise.resolve(dummyCore(this.env)));
await this.configure();
this.loader.load.withArgs('aSpec.js').and.returnValue(Promise.resolve());
this.env.execute.and.returnValue(new Promise(() => {}));
this.clusterWorker.emit('message', {type: 'runSpecFile', filePath: 'aSpec.js'});
await new Promise(resolve => setTimeout(resolve));
expect(this.loader.load).toHaveBeenCalledWith('aSpec.js');
expect(this.env.execute).toHaveBeenCalledWith();
});
describe('When the spec file fails to load', function() {
it('reports the failure', async function() {
this.loader.load.withArgs('jasmine-core')
.and.returnValue(Promise.resolve(dummyCore(this.env)));
await this.configure();
const error = new Error('nope');
this.loader.load.withArgs('aSpec.js')
.and.returnValue(Promise.reject(error));
this.clusterWorker.emit('message', {type: 'runSpecFile', filePath: 'aSpec.js'});
await Promise.resolve();
await Promise.resolve();
expect(this.clusterWorker.send).toHaveBeenCalledWith(
{
type: 'specFileLoadError',
filePath: 'aSpec.js',
error: {
message: error.message,
stack: error.stack
},
}
);
expect(this.env.execute).not.toHaveBeenCalled();
});
});
it('resets state from previous spec files', async function() {
this.loader.load.withArgs('jasmine-core')
.and.returnValue(Promise.resolve(dummyCore(this.env)));
await this.configure();
this.loader.load.and.returnValue(Promise.resolve());
let resolveExecute;
this.env.execute.and.callFake(function() {
return new Promise(function(res) {
resolveExecute = res;
});
});
let doneCalls = 0;
this.clusterWorker.send.and.callFake(function(event) {
if (event.type === 'specFileDone') {
doneCalls++;
}
});
this.jasmineWorker.runSpecFile('aSpec.js');
await poll(() => !!resolveExecute);
dispatchRepoterEvent(this.env, 'jasmineDone', {});
resolveExecute();
await poll(() => doneCalls === 1);
this.env.parallelReset.calls.reset();
resolveExecute = null;
this.jasmineWorker.runSpecFile('bSpec.js');
await poll(() => !!resolveExecute);
expect(this.env.parallelReset).toHaveBeenCalled();
});
it('reports completion', async function() {
this.loader.load.withArgs('jasmine-core')
.and.returnValue(Promise.resolve(dummyCore(this.env)));
await this.configure();
this.loader.load.withArgs('aSpec.js').and.returnValue(Promise.resolve());
let resolveExecute;
this.env.execute
.and.returnValue(new Promise(res => resolveExecute = res));
this.clusterWorker.emit('message', {type: 'runSpecFile', filePath: 'aSpec.js'});
await Promise.resolve();
expect(this.clusterWorker.send).not.toHaveBeenCalledWith(
{type: 'specFileDone'}
);
dispatchRepoterEvent(this.env, 'jasmineDone', {
overallStatus: 'incomplete',
incompleteCode: 'focused',
incompleteReason: 'fit',
order: 'should be ignored',
failedExpectations: ['failed expectations'],
deprecationWarnings: ['deprecations'],
});
resolveExecute();
await Promise.resolve();
await Promise.resolve();
expect(this.clusterWorker.send).toHaveBeenCalledWith({
type: 'specFileDone',
overallStatus: 'incomplete',
incompleteCode: 'focused',
incompleteReason: 'fit',
failedExpectations: ['failed expectations'],
deprecationWarnings: ['deprecations'],
});
});
it('does not try to report completion if disconnected', async function() {
this.loader.load.withArgs('jasmine-core')
.and.returnValue(Promise.resolve(dummyCore(this.env)));
await this.configure();
this.loader.load.withArgs('aSpec.js').and.returnValue(Promise.resolve());
let resolveExecute;
this.env.execute
.and.returnValue(new Promise(res => resolveExecute = res));
this.clusterWorker.emit('message', {type: 'runSpecFile', filePath: 'aSpec.js'});
await Promise.resolve();
expect(this.clusterWorker.send).not.toHaveBeenCalledWith(
{type: 'specFileDone'}
);
dispatchRepoterEvent(this.env, 'jasmineDone', {
overallStatus: 'incomplete',
incompleteCode: 'focused',
incompleteReason: 'fit',
order: 'should be ignored',
failedExpectations: ['failed expectations'],
deprecationWarnings: ['deprecations'],
});
this.clusterWorker.isConnected.and.returnValue(false);
spyOn(console, 'error');
resolveExecute();
await Promise.resolve();
await Promise.resolve();
// No other messages should have been sent
expect(this.clusterWorker.send.calls.argsFor(0)[0]).toEqual(
{type: 'readyForConfig'});
expect(this.clusterWorker.send.calls.argsFor(1)[0]).toEqual({type: 'booted'});
expect(this.clusterWorker.send).toHaveBeenCalledTimes(2);
});
});
describe('Handling reporter events', function() {
const forwardedEvents = ['suiteStarted', 'suiteDone', 'specStarted', 'specDone'];
const nonForwardedEvents = ['jasmineStarted', 'jasmineDone'];
for (const eventName of forwardedEvents) {
it(`forwards ${eventName} to the primary if connected`, async function() {
const env = jasmine.createSpyObj(
'env', ['execute', 'parallelReset', 'addReporter']
);
const loader = jasmine.createSpyObj('loader', ['load']);
loader.load.withArgs('jasmine-core')
.and.returnValue(Promise.resolve(dummyCore(env)));
this.clusterWorker.id = 17;
const jasmineWorker = new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
helpers: [],
}
});
await waitForEnvPromise(jasmineWorker);
const payload = {
id: 'foo',
description: 'a spec or suite'
};
dispatchRepoterEvent(env, eventName, payload);
expect(this.clusterWorker.send).toHaveBeenCalledWith({
type: 'reporterEvent',
eventName,
payload: {
id: '17-foo',
description: 'a spec or suite'
}
});
this.clusterWorker.send.calls.reset();
this.clusterWorker.isConnected.and.returnValue(false);
spyOn(console, 'error');
dispatchRepoterEvent(env, eventName, payload);
expect(this.clusterWorker.send).not.toHaveBeenCalled();
});
}
for (const eventName of nonForwardedEvents) {
it(`does not forward ${eventName}`, async function () {
const env = jasmine.createSpyObj(
'env', ['execute', 'parallelReset', 'addReporter', 'setParallelLoadingState']
);
const loader = jasmine.createSpyObj('loader', ['load']);
loader.load.withArgs('jasmine-core')
.and.returnValue(Promise.resolve(dummyCore(env)));
const jasmineWorker = new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
helpers: [],
}
});
await waitForEnvPromise(jasmineWorker);
dispatchRepoterEvent(env, eventName, {});
// No other messages should have been sent
expect(this.clusterWorker.send.calls.argsFor(0)[0]).toEqual(
{type: 'readyForConfig'});
expect(this.clusterWorker.send.calls.argsFor(1)[0]).toEqual({type: 'booted'});
expect(this.clusterWorker.send).toHaveBeenCalledTimes(2);
});
}
for (const eventName of ['specDone', 'suiteDone']) {
it(`handles non-serializable expected values in ${eventName}`, async function() {
const env = jasmine.createSpyObj(
'env', ['execute', 'parallelReset', 'addReporter']
);
const loader = jasmine.createSpyObj('loader', ['load']);
loader.load.withArgs('jasmine-core')
.and.returnValue(Promise.resolve(dummyCore(env)));
const jasmineWorker = new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});
this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
helpers: [],
}
});
await waitForEnvPromise(jasmineWorker);
this.clusterWorker.send.calls.reset();
this.clusterWorker.send.and.callFake(function(msg) {
// Throw if msg is not serializable
JSON.stringify(msg);
});
const notSerializable = BigInt(0);
dispatchRepoterEvent(env, eventName, {
failedExpectations: [{expected: 'ok', actual: notSerializable}],
passedExpectations: [{expected: notSerializable, actual: 'ok'}],
});
expect(this.clusterWorker.send).toHaveBeenCalledWith({
type: 'reporterEvent',
eventName,
payload: jasmine.objectContaining({
failedExpectations: [{expected: 'ok', actual: ''}],
passedExpectations: [{expected: '', actual: 'ok'}],
})
});
});
}
});
it('reports unhandled exceptions that occur between batches', async function() {
const process = jasmine.createSpyObj('process', ['on']);
new ParallelWorker({
process,
loader: { load() {} },
clusterWorker: this.clusterWorker
});
expect(process.on).toHaveBeenCalledWith(
'uncaughtException',
jasmine.any(Function)
);
const onCall = process.on.calls.all()
.filter(c => c.args[0] === 'uncaughtException')
[0];
const error = new Error('nope');
onCall.args[1](error);
expect(this.clusterWorker.send).toHaveBeenCalledWith({
type: 'uncaughtException',
error: {
message: error.message,
stack: error.stack
}
});
});
it('reports unhandled promise rejections that occur between batches', async function() {
const process = jasmine.createSpyObj('process', ['on']);
new ParallelWorker({
process,
loader: { load() {} },
clusterWorker: this.clusterWorker
});
expect(process.on).toHaveBeenCalledWith(
'unhandledRejection',
jasmine.any(Function)
);
const onCall = process.on.calls.all()
.filter(c => c.args[0] === 'unhandledRejection')
[0];
const error = new Error('nope');
onCall.args[1](error);
expect(this.clusterWorker.send).toHaveBeenCalledWith({
type: 'unhandledRejection',
error: {
message: error.message,
stack: error.stack
}
});
});
it('does not try to report unhandled exceptions if disconnected', async function() {
const process = jasmine.createSpyObj('process', ['on']);
new ParallelWorker({
process,
loader: { load() {} },
clusterWorker: this.clusterWorker
});
expect(process.on).toHaveBeenCalledWith(
'uncaughtException',
jasmine.any(Function)
);
const onCall = process.on.calls.all()
.filter(c => c.args[0] === 'uncaughtException')
[0];
this.clusterWorker.isConnected.and.returnValue(false);
spyOn(console, 'error');
this.clusterWorker.send.calls.reset();
const error = new Error('nope');
onCall.args[1](error);
expect(this.clusterWorker.send).not.toHaveBeenCalled();
});
it('does not try to report unhandled rejections if disconnected', async function() {
const process = jasmine.createSpyObj('process', ['on']);
new ParallelWorker({
process,
loader: { load() {} },
clusterWorker: this.clusterWorker
});
expect(process.on).toHaveBeenCalledWith(
'unhandledRejection',
jasmine.any(Function)
);
const onCall = process.on.calls.all()
.filter(c => c.args[0] === 'unhandledRejection')
[0];
this.clusterWorker.isConnected.and.returnValue(false);
spyOn(console, 'error');
this.clusterWorker.send.calls.reset();
const error = new Error('nope');
onCall.args[1](error);
expect(this.clusterWorker.send).not.toHaveBeenCalled();
});
});
async function waitForEnvPromise(jasmineWorker) {
await poll(() => !!jasmineWorker.envPromise_);
await(jasmineWorker.envPromise_);
}
function dispatchRepoterEvent(env, eventName, payload) {
expect(env.addReporter).toHaveBeenCalled();
for (const [reporter] of env.addReporter.calls.allArgs()) {
if (reporter[eventName]) {
reporter[eventName](payload);
dispatched = true;
}
}
}
function dummyCore(env) {
function getEnv() {
return env || {
addReporter() {},
parallelReset() {},
setParallelLoadingState() {},
};
}
return {
jasmine: {getEnv},
installGlobals() {}
};
}
async function poll(predicate) {
return new Promise(function(resolve, reject) {
function check() {
try {
if (predicate()) {
resolve();
} else {
setTimeout(check);
}
} catch (e) {
reject(e);
}
}
check();
});
}
function stubProcess() {
return {
on() {
}
};
}
jasmine-jasmine-npm-3c2955c/spec/path_spec_filter_spec.js 0000664 0000000 0000000 00000001552 15240143636 0023537 0 ustar 00root root 0000000 0000000 const pathSpecFilter = require('../lib/filters/path_spec_filter');
describe("pathSpecFilter", function() {
it("matches a spec with the exact same path", function() {
const specFilter = pathSpecFilter(["a", "b", "c"]);
expect(specFilter(stubSpec(['a', 'b', 'c']))).toBeTrue();
});
it('matches a spec whose path has the filter path as a prefix', function() {
const specFilter = pathSpecFilter(["a", "b"]);
expect(specFilter(stubSpec(['a', 'b', 'c']))).toBeTrue();
});
it('does not match a spec with a different path', function() {
const specFilter = pathSpecFilter(["a", "b", "c"]);
expect(specFilter(stubSpec(['a', 'd', 'c']))).toBeFalse();
});
function stubSpec(path) {
return {
getPath() { return path; },
// getFullName is required, but plays no role in filtering
getFullName() { return ""; }
};
}
});
jasmine-jasmine-npm-3c2955c/spec/poll.js 0000664 0000000 0000000 00000001454 15240143636 0020161 0 ustar 00root root 0000000 0000000 // Make sure we can still work if the mock clock is installed
const realSetTimeout = setTimeout;
async function poll(predicate) {
return new Promise(function(resolve, reject) {
function check() {
try {
if (predicate()) {
resolve();
} else {
realSetTimeout(check);
}
} catch (e) {
reject(e);
}
}
check();
});
}
async function shortPoll(predicate, description) {
const timedOut = {};
const timeoutPromise = new Promise(function(resolve) {
realSetTimeout(function() {
resolve(timedOut);
}, 250);
});
const result = await Promise.race([timeoutPromise, poll(predicate)]);
if (result === timedOut) {
throw new Error(`Timed out waiting for ${description}`);
}
}
module.exports = {poll, shortPoll};
jasmine-jasmine-npm-3c2955c/spec/shared_runner_behaviors.js 0000664 0000000 0000000 00000035774 15240143636 0024130 0 ustar 00root root 0000000 0000000 const path = require('path');
const Loader = require("../lib/loader");
/*
Preconditions that a beforeEach in the containing suite should provide:
- this.testJasmine is the subject
- this.testJasmine.exit is a spy
- this.execute is a function that executes the env and returns a promise
that resolves when it's done
Not all shared behaviors are tested here. Many are separately tested in
jasmine_spec.js and parallel_runner_spec.js because the code resulting
from de-duplication would be excessively complex.
*/
function sharedRunnerBehaviors(makeRunner) {
describe('Shared runner behaviors', function () {
it('sets projectBaseDir to the cwd by default', function () {
expect(this.testJasmine.projectBaseDir).toEqual(
path.resolve().replace(/\\/g, '/')
);
});
describe('#addSpecFile', function () {
it('adds the provided path to the list of spec files', function () {
expect(this.testJasmine.specFiles).toEqual([]);
this.testJasmine.addSpecFile('some/file/path.js');
expect(this.testJasmine.specFiles).toEqual(['some/file/path.js']);
});
});
describe('#addHelperFile', function () {
it('adds the provided path to the list of helper files', function () {
expect(this.testJasmine.helperFiles).toEqual([]);
this.testJasmine.addHelperFile('some/file/path.js');
expect(this.testJasmine.helperFiles).toEqual(['some/file/path.js']);
});
});
describe('Methods that specify files via globs', function () {
describe('#addMatchingSpecFiles', function () {
hasCommonFileGlobBehavior('addMatchingSpecFiles', 'specFiles');
});
describe('#addMatchingHelperFiles', function () {
hasCommonFileGlobBehavior('addMatchingHelperFiles', 'helperFiles');
});
function hasCommonFileGlobBehavior(method, destProp) {
it('adds a file with an absolute path', function () {
const aFile = path.join(this.testJasmine.projectBaseDir, this.testJasmine.specDir, 'spec/command_spec.js')
.replace(/\\/g, '/');
expect(this.testJasmine[destProp]).toEqual([]);
this.testJasmine[method]([aFile]);
const expectedPath = aFile.replace(/\\/g, '/');
expect(this.testJasmine[destProp]).toEqual([
pathEndingWith(expectedPath)
]);
});
it('adds files that match a glob pattern', function () {
expect(this.testJasmine[destProp]).toEqual([]);
this.testJasmine[method](['spec/fixtures/jasmine_spec/*.js']);
expect(this.testJasmine[destProp].map(basename)).toEqual([
'c.js',
'd.js',
'e.js',
'f.js',
]);
});
it('can exclude files that match another glob', function () {
expect(this.testJasmine[destProp]).toEqual([]);
this.testJasmine[method]([
'spec/fixtures/jasmine_spec/*.js',
'!spec/fixtures/jasmine_spec/c*'
]);
expect(this.testJasmine[destProp].map(basename)).toEqual([
'd.js',
'e.js',
'f.js',
]);
});
it('adds new files to existing files', function () {
// Don't use path.join because glob needs forward slashes
// even on Windows
const aFile = [
this.testJasmine.projectBaseDir,
this.testJasmine.specDir,
'spec/command_spec.js',
].join('/');
this.testJasmine[destProp] = [aFile, 'b'];
this.testJasmine[method](['spec/fixtures/jasmine_spec/*.js']);
expect(this.testJasmine[destProp].map(basename)).toEqual([
'command_spec.js',
'b',
'c.js',
'd.js',
'e.js',
'f.js',
]);
});
}
function basename(name) {
return path.basename(name);
}
});
describe('#configureDefaultReporter', function () {
beforeEach(function () {
if (!jasmine.isSpy(this.testJasmine.reporter_.configure)) {
spyOn(this.testJasmine.reporter_, 'configure');
}
});
it('sets the options on the console reporter', function () {
const reporterOptions = {color: true};
this.testJasmine.configureDefaultReporter(reporterOptions);
expect(this.testJasmine.reporter_.configure).toHaveBeenCalledWith(
reporterOptions);
});
});
describe('loading configurations', function () {
beforeEach(function() {
this.fixtureJasmine = makeRunner.call(this, {
projectBaseDir: 'spec/fixtures/sample_project'
});
});
describe('from an object', function () {
it('adds unique spec and helper files', async function() {
await this.fixtureJasmine.loadConfig({
spec_dir: 'spec',
spec_files: [
'fixture_spec.js',
'**/*spec.js'
],
helpers: ["helper.js"]
});
expect(this.fixtureJasmine.specFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/fixture_spec.js'),
pathEndingWith('spec/fixtures/sample_project/spec/other_fixture_spec.js')
]);
expect(this.fixtureJasmine.helperFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/helper.js'
)]);
});
it('sets the spec dir to the provided value', function() {
this.fixtureJasmine.loadConfig({spec_dir: 'spec'});
expect(this.fixtureJasmine.specDir).toEqual('spec');
});
it('sets the spec dir to the empty string when unspecified', async function() {
await this.fixtureJasmine.loadConfig({});
expect(this.fixtureJasmine.specDir).toEqual('');
});
it('can configure the default reporter with arbitrary properties', async function () {
const reporterConfig = {someProp: 'someValue'};
spyOn(this.fixtureJasmine.reporter_, 'configure');
await this.fixtureJasmine.loadConfig({defaultReporter: reporterConfig});
expect(this.fixtureJasmine.reporter_.configure).toHaveBeenCalledWith(
reporterConfig);
});
describe('with loader set', function() {
it('uses the custom loader exported by the specified module', async function() {
function customLoader() {}
spyOn(this.fixtureJasmine.loader, 'load')
.withArgs('some/loader/module')
.and.returnValue(Promise.resolve(customLoader));
await this.fixtureJasmine.loadConfig({loader: 'some/loader/module'});
expect(this.fixtureJasmine.loader).toEqual({load: customLoader});
});
});
it('adds requires', async function() {
await this.fixtureJasmine.loadConfig({
spec_dir: 'spec',
requires: ['ts-node/register']
});
expect(this.fixtureJasmine.requires).toEqual(['ts-node/register']);
});
});
describe('from a file', function () {
it('adds unique spec files', async function() {
await this.fixtureJasmine.loadConfigFile('spec/support/jasmine_alternate.json');
expect(this.fixtureJasmine.helperFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/helper.js')
]);
expect(this.fixtureJasmine.requires).toEqual(['ts-node/register']);
expect(this.fixtureJasmine.specFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/fixture_spec.js'),
pathEndingWith('spec/fixtures/sample_project/spec/other_fixture_spec.js')
]);
});
it('can use an ES module', async function() {
await this.fixtureJasmine.loadConfigFile('spec/support/jasmine_alternate.mjs');
expect(this.fixtureJasmine.helperFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/helper.js')
]);
expect(this.fixtureJasmine.requires).toEqual(['ts-node/register']);
expect(this.fixtureJasmine.specFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/fixture_spec.js'),
pathEndingWith('spec/fixtures/sample_project/spec/other_fixture_spec.js')
]);
});
it('can use a CommonJS module', async function() {
await this.fixtureJasmine.loadConfigFile('spec/support/jasmine_alternate.cjs');
expect(this.fixtureJasmine.helperFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/helper.js')
]);
expect(this.fixtureJasmine.requires).toEqual(['ts-node/register']);
expect(this.fixtureJasmine.specFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/fixture_spec.js'),
pathEndingWith('spec/fixtures/sample_project/spec/other_fixture_spec.js')
]);
});
it('loads the specified configuration file from an absolute path', async function() {
const absoluteConfigPath = path.join(__dirname, 'fixtures/sample_project/spec/support/jasmine_alternate.json');
await this.fixtureJasmine.loadConfigFile(absoluteConfigPath);
expect(this.fixtureJasmine.helperFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/helper.js')
]);
expect(this.fixtureJasmine.requires).toEqual(['ts-node/register']);
expect(this.fixtureJasmine.specFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/fixture_spec.js'),
pathEndingWith('spec/fixtures/sample_project/spec/other_fixture_spec.js')
]);
});
it("throws an error if the specified configuration file doesn't exist", async function() {
await expectAsync(this.fixtureJasmine.loadConfigFile('missing.json')).toBeRejected();
});
it("does not throw if the default configuration files don't exist", async function() {
this.fixtureJasmine.projectBaseDir += '/missing';
await expectAsync(this.fixtureJasmine.loadConfigFile()).toBeResolved();
});
describe('When the default .mjs configuration file exists', function() {
it('loads the default .mjs configuration file', async function() {
const config = require('./fixtures/sample_project/spec/support/jasmine.json');
spyOn(Loader.prototype, 'load')
.withArgs(jasmine.stringMatching(/jasmine\.mjs$/))
.and.returnValue(Promise.resolve(config));
await this.fixtureJasmine.loadConfigFile();
expect(Loader.prototype.load).toHaveBeenCalledWith(jasmine.stringMatching(
'jasmine\.mjs$'
));
expect(this.fixtureJasmine.specFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/fixture_spec.js')
]);
});
it('does not also load the default .js or .json configuration files', async function() {
spyOn(Loader.prototype, 'load')
.withArgs(jasmine.stringMatching(/jasmine\.mjs$/))
.and.returnValue(Promise.resolve({}));
await this.fixtureJasmine.loadConfigFile();
expect(Loader.prototype.load).not.toHaveBeenCalledWith(jasmine.stringMatching(
'jasmine\.js$'
));
expect(Loader.prototype.load).not.toHaveBeenCalledWith(jasmine.stringMatching(
'jasmine\.json$'
));
});
});
describe('When the default .mjs configuration file does not exist', function() {
it('loads the default .json configuration file', async function () {
await this.fixtureJasmine.loadConfigFile();
expect(this.fixtureJasmine.specFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/fixture_spec.js')
]);
});
it('loads the default .js configuration file', async function () {
const config = require('./fixtures/sample_project/spec/support/jasmine.json');
spyOn(Loader.prototype, 'load').and.callFake(function (path) {
if (path.endsWith('jasmine.js')) {
return Promise.resolve(config);
} else {
const e = new Error(`Module not found: ${path}`);
e.code = 'MODULE_NOT_FOUND';
return Promise.reject(e);
}
});
await this.fixtureJasmine.loadConfigFile();
expect(Loader.prototype.load).toHaveBeenCalledWith(jasmine.stringMatching(
'jasmine\.js$'
));
expect(this.fixtureJasmine.specFiles).toEqual([
pathEndingWith('spec/fixtures/sample_project/spec/fixture_spec.js')
]);
});
it('does not load jasmine.js config if jasmine.json config file is found', async function () {
spyOn(Loader.prototype, 'load').and.callFake(function (path) {
if (path.endsWith('jasmine.json')) {
return Promise.resolve({});
} else {
const e = new Error(`Module not found: ${path}`);
e.code = 'MODULE_NOT_FOUND';
return Promise.reject(e);
}
});
await this.fixtureJasmine.loadConfigFile();
expect(Loader.prototype.load)
.toHaveBeenCalledWith(jasmine.stringMatching(/jasmine\.json$/));
expect(Loader.prototype.load)
.not.toHaveBeenCalledWith(jasmine.stringMatching(/jasmine\.js$/));
});
});
});
});
describe('#execute', function() {
describe('completion behavior', function() {
beforeEach(function() {
spyOn(this.testJasmine, 'exit');
});
describe('default', function() {
it('exits successfully when the whole suite is green', async function () {
await this.execute({overallStatus: 'passed'});
expect(this.testJasmine.exit).toHaveBeenCalledWith(0);
});
it('exits with a distinct status code when anything in the suite is not green', async function () {
await this.execute({overallStatus: 'failed'});
expect(this.testJasmine.exit).toHaveBeenCalledWith(3);
});
it('exits with a distinct status code when anything in the suite is focused', async function() {
await this.execute({overallStatus: 'incomplete'});
expect(this.testJasmine.exit).toHaveBeenCalledWith(2);
});
});
describe('When exitOnCompletion is set to false', function() {
it('does not exit', async function() {
this.testJasmine.exitOnCompletion = false;
await this.execute();
expect(this.testJasmine.exit).not.toHaveBeenCalled();
});
});
});
});
});
}
function pathEndingWith(suffix) {
// Match glob output from either Windows or other OSes.
const pattern = '(^|[\\/\\\\])' + suffix.replace(/\//g, '[\\/\\\\]') + '$';
return jasmine.stringMatching(new RegExp(pattern));
}
module.exports = {sharedRunnerBehaviors, pathEndingWith};
jasmine-jasmine-npm-3c2955c/spec/support/ 0000775 0000000 0000000 00000000000 15240143636 0020365 5 ustar 00root root 0000000 0000000 jasmine-jasmine-npm-3c2955c/spec/support/jasmine.json 0000664 0000000 0000000 00000000315 15240143636 0022705 0 ustar 00root root 0000000 0000000 {
"spec_dir": "spec",
"spec_files": [
"*[sS]pec.js",
"reporters/**/*[sS]pec.js",
"filters/**/*[sS]pec.js"
],
"helpers": [
"helpers/**/*.js"
],
"alwaysListPendingSpecs": false
}