diff options
author | Florian Dold <florian.dold@gmail.com> | 2019-03-27 21:01:33 +0100 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2019-03-27 21:01:33 +0100 |
commit | cc97a4dd2a967e1c2273bd5f4c5f49a5bf2e2585 (patch) | |
tree | 92c5d88706a6ffc654d1b133618d357890e7096b /node_modules/ava/lib | |
parent | 3771b4d6b67b34c130f3a9a1a15f42deefdb2eda (diff) |
remove node_modules
Diffstat (limited to 'node_modules/ava/lib')
33 files changed, 0 insertions, 5085 deletions
diff --git a/node_modules/ava/lib/assert.js b/node_modules/ava/lib/assert.js deleted file mode 100644 index 18009b97d..000000000 --- a/node_modules/ava/lib/assert.js +++ /dev/null @@ -1,449 +0,0 @@ -'use strict'; -const concordance = require('concordance'); -const coreAssert = require('core-assert'); -const observableToPromise = require('observable-to-promise'); -const isObservable = require('is-observable'); -const isPromise = require('is-promise'); -const concordanceOptions = require('./concordance-options').default; -const concordanceDiffOptions = require('./concordance-options').diff; -const enhanceAssert = require('./enhance-assert'); -const snapshotManager = require('./snapshot-manager'); - -function formatDescriptorDiff(actualDescriptor, expectedDescriptor, options) { - options = Object.assign({}, options, concordanceDiffOptions); - return { - label: 'Difference:', - formatted: concordance.diffDescriptors(actualDescriptor, expectedDescriptor, options) - }; -} - -function formatDescriptorWithLabel(label, descriptor) { - return { - label, - formatted: concordance.formatDescriptor(descriptor, concordanceOptions) - }; -} - -function formatWithLabel(label, value) { - return formatDescriptorWithLabel(label, concordance.describe(value, concordanceOptions)); -} - -class AssertionError extends Error { - constructor(opts) { - super(opts.message || ''); - this.name = 'AssertionError'; - - this.assertion = opts.assertion; - this.fixedSource = opts.fixedSource; - this.improperUsage = opts.improperUsage || false; - this.operator = opts.operator; - this.values = opts.values || []; - - // Raw expected and actual objects are stored for custom reporters - // (such as wallaby.js), that manage worker processes directly and - // use the values for custom diff views - this.raw = opts.raw; - - // Reserved for power-assert statements - this.statements = []; - - if (opts.stack) { - this.stack = opts.stack; - } - } -} -exports.AssertionError = AssertionError; - -function getStack() { - const obj = {}; - Error.captureStackTrace(obj, getStack); - return obj.stack; -} - -function wrapAssertions(callbacks) { - const pass = callbacks.pass; - const pending = callbacks.pending; - const fail = callbacks.fail; - const log = callbacks.log; - - const noop = () => {}; - const makeRethrow = reason => () => { - throw reason; - }; - - const assertions = { - pass() { - pass(this); - }, - - fail(message) { - fail(this, new AssertionError({ - assertion: 'fail', - message: message || 'Test failed via `t.fail()`' - })); - }, - - is(actual, expected, message) { - if (Object.is(actual, expected)) { - pass(this); - } else { - const result = concordance.compare(actual, expected, concordanceOptions); - const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); - const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); - - if (result.pass) { - fail(this, new AssertionError({ - assertion: 'is', - message, - raw: {actual, expected}, - values: [formatDescriptorWithLabel('Values are deeply equal to each other, but they are not the same:', actualDescriptor)] - })); - } else { - fail(this, new AssertionError({ - assertion: 'is', - message, - raw: {actual, expected}, - values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] - })); - } - } - }, - - not(actual, expected, message) { - if (Object.is(actual, expected)) { - fail(this, new AssertionError({ - assertion: 'not', - message, - raw: {actual, expected}, - values: [formatWithLabel('Value is the same as:', actual)] - })); - } else { - pass(this); - } - }, - - log(text) { - log(this, text); - }, - - deepEqual(actual, expected, message) { - const result = concordance.compare(actual, expected, concordanceOptions); - if (result.pass) { - pass(this); - } else { - const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); - const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); - fail(this, new AssertionError({ - assertion: 'deepEqual', - message, - raw: {actual, expected}, - values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] - })); - } - }, - - notDeepEqual(actual, expected, message) { - const result = concordance.compare(actual, expected, concordanceOptions); - if (result.pass) { - const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); - fail(this, new AssertionError({ - assertion: 'notDeepEqual', - message, - raw: {actual, expected}, - values: [formatDescriptorWithLabel('Value is deeply equal:', actualDescriptor)] - })); - } else { - pass(this); - } - }, - - throws(fn, err, message) { - let promise; - if (isPromise(fn)) { - promise = fn; - } else if (isObservable(fn)) { - promise = observableToPromise(fn); - } else if (typeof fn !== 'function') { - fail(this, new AssertionError({ - assertion: 'throws', - improperUsage: true, - message: '`t.throws()` must be called with a function, Promise, or Observable', - values: [formatWithLabel('Called with:', fn)] - })); - return; - } - - let coreAssertThrowsErrorArg; - if (typeof err === 'string') { - const expectedMessage = err; - coreAssertThrowsErrorArg = error => error.message === expectedMessage; - } else { - // Assume it's a constructor function or regular expression - coreAssertThrowsErrorArg = err; - } - - const test = (fn, stack) => { - let actual; - let threw = false; - try { - coreAssert.throws(() => { - try { - fn(); - } catch (err) { - actual = err; - threw = true; - throw err; - } - }, coreAssertThrowsErrorArg); - return actual; - } catch (err) { - throw new AssertionError({ - assertion: 'throws', - message, - stack, - values: threw ? - [formatWithLabel('Threw unexpected exception:', actual)] : - null - }); - } - }; - - if (promise) { - // Record stack before it gets lost in the promise chain. - const stack = getStack(); - const intermediate = promise.then(value => { - throw new AssertionError({ - assertion: 'throws', - message: 'Expected promise to be rejected, but it was resolved instead', - values: [formatWithLabel('Resolved with:', value)] - }); - }, reason => test(makeRethrow(reason), stack)); - - pending(this, intermediate); - // Don't reject the returned promise, even if the assertion fails. - return intermediate.catch(noop); - } - - try { - const retval = test(fn); - pass(this); - return retval; - } catch (err) { - fail(this, err); - } - }, - - notThrows(fn, message) { - let promise; - if (isPromise(fn)) { - promise = fn; - } else if (isObservable(fn)) { - promise = observableToPromise(fn); - } else if (typeof fn !== 'function') { - fail(this, new AssertionError({ - assertion: 'notThrows', - improperUsage: true, - message: '`t.notThrows()` must be called with a function, Promise, or Observable', - values: [formatWithLabel('Called with:', fn)] - })); - return; - } - - const test = (fn, stack) => { - try { - coreAssert.doesNotThrow(fn); - } catch (err) { - throw new AssertionError({ - assertion: 'notThrows', - message, - stack, - values: [formatWithLabel('Threw:', err.actual)] - }); - } - }; - - if (promise) { - // Record stack before it gets lost in the promise chain. - const stack = getStack(); - const intermediate = promise.then(noop, reason => test(makeRethrow(reason), stack)); - pending(this, intermediate); - // Don't reject the returned promise, even if the assertion fails. - return intermediate.catch(noop); - } - - try { - test(fn); - pass(this); - } catch (err) { - fail(this, err); - } - }, - - ifError(actual, message) { - if (actual) { - fail(this, new AssertionError({ - assertion: 'ifError', - message, - values: [formatWithLabel('Error:', actual)] - })); - } else { - pass(this); - } - }, - - snapshot(expected, optionsOrMessage, message) { - const options = {}; - if (typeof optionsOrMessage === 'string') { - message = optionsOrMessage; - } else if (optionsOrMessage) { - options.id = optionsOrMessage.id; - } - options.expected = expected; - options.message = message; - - let result; - try { - result = this._test.compareWithSnapshot(options); - } catch (err) { - if (!(err instanceof snapshotManager.SnapshotError)) { - throw err; - } - - const improperUsage = {name: err.name, snapPath: err.snapPath}; - if (err instanceof snapshotManager.VersionMismatchError) { - improperUsage.snapVersion = err.snapVersion; - improperUsage.expectedVersion = err.expectedVersion; - } - - fail(this, new AssertionError({ - assertion: 'snapshot', - message: message || 'Could not compare snapshot', - improperUsage - })); - return; - } - - if (result.pass) { - pass(this); - } else if (result.actual) { - fail(this, new AssertionError({ - assertion: 'snapshot', - message: message || 'Did not match snapshot', - values: [formatDescriptorDiff(result.actual, result.expected, {invert: true})] - })); - } else { - fail(this, new AssertionError({ - assertion: 'snapshot', - message: message || 'No snapshot available, run with --update-snapshots' - })); - } - } - }; - - const enhancedAssertions = enhanceAssert(pass, fail, { - truthy(actual, message) { - if (!actual) { - throw new AssertionError({ - assertion: 'truthy', - message, - operator: '!!', - values: [formatWithLabel('Value is not truthy:', actual)] - }); - } - }, - - falsy(actual, message) { - if (actual) { - throw new AssertionError({ - assertion: 'falsy', - message, - operator: '!', - values: [formatWithLabel('Value is not falsy:', actual)] - }); - } - }, - - true(actual, message) { - if (actual !== true) { - throw new AssertionError({ - assertion: 'true', - message, - values: [formatWithLabel('Value is not `true`:', actual)] - }); - } - }, - - false(actual, message) { - if (actual !== false) { - throw new AssertionError({ - assertion: 'false', - message, - values: [formatWithLabel('Value is not `false`:', actual)] - }); - } - }, - - regex(string, regex, message) { - if (typeof string !== 'string') { - throw new AssertionError({ - assertion: 'regex', - improperUsage: true, - message: '`t.regex()` must be called with a string', - values: [formatWithLabel('Called with:', string)] - }); - } - if (!(regex instanceof RegExp)) { - throw new AssertionError({ - assertion: 'regex', - improperUsage: true, - message: '`t.regex()` must be called with a regular expression', - values: [formatWithLabel('Called with:', regex)] - }); - } - - if (!regex.test(string)) { - throw new AssertionError({ - assertion: 'regex', - message, - values: [ - formatWithLabel('Value must match expression:', string), - formatWithLabel('Regular expression:', regex) - ] - }); - } - }, - - notRegex(string, regex, message) { - if (typeof string !== 'string') { - throw new AssertionError({ - assertion: 'notRegex', - improperUsage: true, - message: '`t.notRegex()` must be called with a string', - values: [formatWithLabel('Called with:', string)] - }); - } - if (!(regex instanceof RegExp)) { - throw new AssertionError({ - assertion: 'notRegex', - improperUsage: true, - message: '`t.notRegex()` must be called with a regular expression', - values: [formatWithLabel('Called with:', regex)] - }); - } - - if (regex.test(string)) { - throw new AssertionError({ - assertion: 'notRegex', - message, - values: [ - formatWithLabel('Value must not match expression:', string), - formatWithLabel('Regular expression:', regex) - ] - }); - } - } - }); - - return Object.assign(assertions, enhancedAssertions); -} -exports.wrapAssertions = wrapAssertions; diff --git a/node_modules/ava/lib/ava-error.js b/node_modules/ava/lib/ava-error.js deleted file mode 100644 index 05df6b349..000000000 --- a/node_modules/ava/lib/ava-error.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -class AvaError extends Error { - constructor(message) { - super(message); - this.name = 'AvaError'; - } -} - -module.exports = AvaError; diff --git a/node_modules/ava/lib/ava-files.js b/node_modules/ava/lib/ava-files.js deleted file mode 100644 index b6520da37..000000000 --- a/node_modules/ava/lib/ava-files.js +++ /dev/null @@ -1,287 +0,0 @@ -'use strict'; -const fs = require('fs'); -const path = require('path'); -const Promise = require('bluebird'); -const slash = require('slash'); -const globby = require('globby'); -const flatten = require('lodash.flatten'); -const autoBind = require('auto-bind'); -const defaultIgnore = require('ignore-by-default').directories(); -const multimatch = require('multimatch'); - -function handlePaths(files, excludePatterns, globOptions) { - // Convert Promise to Bluebird - files = Promise.resolve(globby(files.concat(excludePatterns), globOptions)); - - const searchedParents = new Set(); - const foundFiles = new Set(); - - function alreadySearchingParent(dir) { - if (searchedParents.has(dir)) { - return true; - } - - const parentDir = path.dirname(dir); - - if (parentDir === dir) { - // We have reached the root path - return false; - } - - return alreadySearchingParent(parentDir); - } - - return files - .map(file => { - file = path.resolve(globOptions.cwd, file); - - if (fs.statSync(file).isDirectory()) { - if (alreadySearchingParent(file)) { - return null; - } - - searchedParents.add(file); - - let pattern = path.join(file, '**', '*.js'); - - if (process.platform === 'win32') { - // Always use `/` in patterns, harmonizing matching across platforms - pattern = slash(pattern); - } - - return handlePaths([pattern], excludePatterns, globOptions); - } - - // `globby` returns slashes even on Windows. Normalize here so the file - // paths are consistently platform-accurate as tests are run. - return path.normalize(file); - }) - .then(flatten) - .filter(file => file && path.extname(file) === '.js') - .filter(file => { - if (path.basename(file)[0] === '_' && globOptions.includeUnderscoredFiles !== true) { - return false; - } - - return true; - }) - .map(file => path.resolve(file)) - .filter(file => { - const alreadyFound = foundFiles.has(file); - foundFiles.add(file); - return !alreadyFound; - }); -} - -const defaultExcludePatterns = () => [ - '!**/node_modules/**', - '!**/fixtures/**', - '!**/helpers/**' -]; - -const defaultIncludePatterns = () => [ - 'test.js', - 'test-*.js', - 'test', - '**/__tests__', - '**/*.test.js' -]; - -const defaultHelperPatterns = () => [ - '**/__tests__/helpers/**/*.js', - '**/__tests__/**/_*.js', - '**/test/helpers/**/*.js', - '**/test/**/_*.js' -]; - -const getDefaultIgnorePatterns = () => defaultIgnore.map(dir => `${dir}/**/*`); - -// Used on paths before they're passed to multimatch to harmonize matching -// across platforms -const matchable = process.platform === 'win32' ? slash : (path => path); - -class AvaFiles { - constructor(options) { - options = options || {}; - - let files = (options.files || []).map(file => { - // `./` should be removed from the beginning of patterns because - // otherwise they won't match change events from Chokidar - if (file.slice(0, 2) === './') { - return file.slice(2); - } - - return file; - }); - - if (files.length === 0) { - files = defaultIncludePatterns(); - } - - this.excludePatterns = defaultExcludePatterns(); - this.files = files; - this.sources = options.sources || []; - this.cwd = options.cwd || process.cwd(); - - autoBind(this); - } - - findTestFiles() { - return handlePaths(this.files, this.excludePatterns, { - cwd: this.cwd, - cache: Object.create(null), - statCache: Object.create(null), - realpathCache: Object.create(null), - symlinks: Object.create(null) - }); - } - - findTestHelpers() { - return handlePaths(defaultHelperPatterns(), ['!**/node_modules/**'], { - cwd: this.cwd, - includeUnderscoredFiles: true, - cache: Object.create(null), - statCache: Object.create(null), - realpathCache: Object.create(null), - symlinks: Object.create(null) - }); - } - - isSource(filePath) { - let mixedPatterns = []; - const defaultIgnorePatterns = getDefaultIgnorePatterns(); - const overrideDefaultIgnorePatterns = []; - - let hasPositivePattern = false; - this.sources.forEach(pattern => { - mixedPatterns.push(pattern); - - // TODO: Why not just `pattern[0] !== '!'`? - if (!hasPositivePattern && pattern[0] !== '!') { - hasPositivePattern = true; - } - - // Extract patterns that start with an ignored directory. These need to be - // rematched separately. - if (defaultIgnore.indexOf(pattern.split('/')[0]) >= 0) { - overrideDefaultIgnorePatterns.push(pattern); - } - }); - - // Same defaults as used for Chokidar - if (!hasPositivePattern) { - mixedPatterns = ['package.json', '**/*.js'].concat(mixedPatterns); - } - - filePath = matchable(filePath); - - // Ignore paths outside the current working directory. - // They can't be matched to a pattern. - if (/^\.\.\//.test(filePath)) { - return false; - } - - const isSource = multimatch(filePath, mixedPatterns).length === 1; - if (!isSource) { - return false; - } - - const isIgnored = multimatch(filePath, defaultIgnorePatterns).length === 1; - if (!isIgnored) { - return true; - } - - const isErroneouslyIgnored = multimatch(filePath, overrideDefaultIgnorePatterns).length === 1; - if (isErroneouslyIgnored) { - return true; - } - - return false; - } - - isTest(filePath) { - const excludePatterns = this.excludePatterns; - const initialPatterns = this.files.concat(excludePatterns); - - // Like in `api.js`, tests must be `.js` files and not start with `_` - if (path.extname(filePath) !== '.js' || path.basename(filePath)[0] === '_') { - return false; - } - - // Check if the entire path matches a pattern - if (multimatch(matchable(filePath), initialPatterns).length === 1) { - return true; - } - - // Check if the path contains any directory components - const dirname = path.dirname(filePath); - if (dirname === '.') { - return false; - } - - // Compute all possible subpaths. Note that the dirname is assumed to be - // relative to the working directory, without a leading `./`. - const subpaths = dirname.split(/[\\/]/).reduce((subpaths, component) => { - const parent = subpaths[subpaths.length - 1]; - - if (parent) { - // Always use `/`` to makes multimatch consistent across platforms - subpaths.push(`${parent}/${component}`); - } else { - subpaths.push(component); - } - - return subpaths; - }, []); - - // Check if any of the possible subpaths match a pattern. If so, generate a - // new pattern with **/*.js. - const recursivePatterns = subpaths - .filter(subpath => multimatch(subpath, initialPatterns).length === 1) - // Always use `/` to makes multimatch consistent across platforms - .map(subpath => `${subpath}/**/*.js`); - - // See if the entire path matches any of the subpaths patterns, taking the - // excludePatterns into account. This mimicks the behavior in api.js - return multimatch(matchable(filePath), recursivePatterns.concat(excludePatterns)).length === 1; - } - - getChokidarPatterns() { - let paths = []; - let ignored = []; - - this.sources.forEach(pattern => { - if (pattern[0] === '!') { - ignored.push(pattern.slice(1)); - } else { - paths.push(pattern); - } - }); - - // Allow source patterns to override the default ignore patterns. Chokidar - // ignores paths that match the list of ignored patterns. It uses anymatch - // under the hood, which supports negation patterns. For any source pattern - // that starts with an ignored directory, ensure the corresponding negation - // pattern is added to the ignored paths. - const overrideDefaultIgnorePatterns = paths - .filter(pattern => defaultIgnore.indexOf(pattern.split('/')[0]) >= 0) - .map(pattern => `!${pattern}`); - - ignored = getDefaultIgnorePatterns().concat(ignored, overrideDefaultIgnorePatterns); - - if (paths.length === 0) { - paths = ['package.json', '**/*.js', '**/*.snap']; - } - - paths = paths.concat(this.files); - - return { - paths, - ignored - }; - } -} - -module.exports = AvaFiles; -module.exports.defaultIncludePatterns = defaultIncludePatterns; -module.exports.defaultExcludePatterns = defaultExcludePatterns; diff --git a/node_modules/ava/lib/babel-config.js b/node_modules/ava/lib/babel-config.js deleted file mode 100644 index d58b700b8..000000000 --- a/node_modules/ava/lib/babel-config.js +++ /dev/null @@ -1,156 +0,0 @@ -'use strict'; -const fs = require('fs'); -const path = require('path'); -const chalk = require('chalk'); -const figures = require('figures'); -const configManager = require('hullabaloo-config-manager'); -const md5Hex = require('md5-hex'); -const makeDir = require('make-dir'); -const semver = require('semver'); -const colors = require('./colors'); - -function validate(conf) { - if (conf === undefined || conf === null) { - conf = 'default'; - } - - // Check for valid babel config shortcuts (can be either `default` or `inherit`) - const isValidShortcut = conf === 'default' || conf === 'inherit'; - - if (!conf || (typeof conf === 'string' && !isValidShortcut)) { - let message = colors.error(figures.cross); - message += ' Unexpected Babel configuration for AVA. '; - message += 'See ' + chalk.underline('https://github.com/avajs/ava#es2017-support') + ' for allowed values.'; - - throw new Error(message); - } - - return conf; -} - -const SOURCE = '(AVA) Base Babel config'; -const AVA_DIR = path.join(__dirname, '..'); - -function verifyExistingOptions(verifierFile, baseConfig, cache) { - return new Promise((resolve, reject) => { - try { - resolve(fs.readFileSync(verifierFile)); - } catch (err) { - if (err && err.code === 'ENOENT') { - resolve(null); - } else { - reject(err); - } - } - }) - .then(buffer => { - if (!buffer) { - return null; - } - - const verifier = configManager.restoreVerifier(buffer); - const fixedSourceHashes = new Map(); - fixedSourceHashes.set(baseConfig.source, baseConfig.hash); - if (baseConfig.extends) { - fixedSourceHashes.set(baseConfig.extends.source, baseConfig.extends.hash); - } - return verifier.verifyCurrentEnv({sources: fixedSourceHashes}, cache) - .then(result => { - if (!result.cacheKeys) { - return null; - } - - if (result.dependenciesChanged) { - fs.writeFileSync(verifierFile, result.verifier.toBuffer()); - } - - return result.cacheKeys; - }); - }); -} - -function resolveOptions(baseConfig, cache, optionsFile, verifierFile) { - return configManager.fromConfig(baseConfig, {cache}) - .then(result => { - fs.writeFileSync(optionsFile, result.generateModule()); - - return result.createVerifier() - .then(verifier => { - fs.writeFileSync(verifierFile, verifier.toBuffer()); - return verifier.cacheKeysForCurrentEnv(); - }); - }); -} - -function build(projectDir, cacheDir, userOptions, powerAssert) { - // Compute a seed based on the Node.js version and the project directory. - // Dependency hashes may vary based on the Node.js version, e.g. with the - // @ava/stage-4 Babel preset. Sources and dependencies paths are absolute in - // the generated module and verifier state. Those paths wouldn't necessarily - // be valid if the project directory changes. - const seed = md5Hex([process.versions.node, projectDir]); - - // Ensure cacheDir exists - makeDir.sync(cacheDir); - - // The file names predict where valid options may be cached, and thus should - // include the seed. - const optionsFile = path.join(cacheDir, `${seed}.babel-options.js`); - const verifierFile = path.join(cacheDir, `${seed}.verifier.bin`); - - const baseOptions = { - babelrc: false, - plugins: [], - presets: [ - ['@ava/transform-test-files', {powerAssert}] - ] - }; - if (userOptions === 'default') { - baseOptions.presets.unshift('@ava/stage-4'); - } - - // Include object rest spread support for node versions that support it - // natively. - if (userOptions === 'default' && semver.satisfies(process.versions.node, '>= 8.3.0')) { - baseOptions.plugins.push('babel-plugin-syntax-object-rest-spread'); - } - - const baseConfig = configManager.createConfig({ - dir: AVA_DIR, // Presets are resolved relative to this directory - hash: md5Hex(JSON.stringify(baseOptions)), - json5: false, - options: baseOptions, - source: SOURCE - }); - - if (userOptions !== 'default') { - baseConfig.extend(configManager.createConfig({ - dir: projectDir, - options: userOptions === 'inherit' ? - {babelrc: true} : - userOptions, - source: path.join(projectDir, 'package.json') + '#ava.babel', - hash: md5Hex(JSON.stringify(userOptions)) - })); - } - - const cache = configManager.prepareCache(); - return verifyExistingOptions(verifierFile, baseConfig, cache) - .then(cacheKeys => { - if (cacheKeys) { - return cacheKeys; - } - - return resolveOptions(baseConfig, cache, optionsFile, verifierFile); - }) - .then(cacheKeys => ({ - getOptions: require(optionsFile).getOptions, - // Include the seed in the cache keys used to store compilation results. - cacheKeys: Object.assign({seed}, cacheKeys) - })); -} - -module.exports = { - validate, - build -}; diff --git a/node_modules/ava/lib/beautify-stack.js b/node_modules/ava/lib/beautify-stack.js deleted file mode 100644 index 4ae8c04be..000000000 --- a/node_modules/ava/lib/beautify-stack.js +++ /dev/null @@ -1,72 +0,0 @@ -'use strict'; -const StackUtils = require('stack-utils'); -const cleanStack = require('clean-stack'); -const debug = require('debug')('ava'); - -// Ignore unimportant stack trace lines -let ignoreStackLines = []; - -const avaInternals = /\/ava\/(?:lib\/)?[\w-]+\.js:\d+:\d+\)?$/; -const avaDependencies = /\/node_modules\/(?:bluebird|empower-core|(?:ava\/node_modules\/)?(?:babel-runtime|core-js))\//; -const stackFrameLine = /^.+( \(.+:\d+:\d+\)|:\d+:\d+)$/; - -if (!debug.enabled) { - ignoreStackLines = StackUtils.nodeInternals(); - ignoreStackLines.push(avaInternals); - ignoreStackLines.push(avaDependencies); -} - -const stackUtils = new StackUtils({internals: ignoreStackLines}); - -function extractFrames(stack) { - return stack - .split('\n') - .map(line => line.trim()) - .filter(line => stackFrameLine.test(line)) - .join('\n'); -} - -/** - * Given a string value of the format generated for the `stack` property of a - * V8 error object, return a string that contains only stack frame information - * for frames that have relevance to the consumer. - * - * For example, given the following string value: - * - * ``` - * Error - * at inner (/home/ava/ex.js:7:12) - * at /home/ava/ex.js:12:5 - * at outer (/home/ava/ex.js:13:4) - * at Object.<anonymous> (/home/ava/ex.js:14:3) - * at Module._compile (module.js:570:32) - * at Object.Module._extensions..js (module.js:579:10) - * at Module.load (module.js:487:32) - * at tryModuleLoad (module.js:446:12) - * at Function.Module._load (module.js:438:3) - * at Module.runMain (module.js:604:10) - * ``` - * - * ...this function returns the following string value: - * - * ``` - * inner (/home/ava/ex.js:7:12) - * /home/ava/ex.js:12:5 - * outer (/home/ava/ex.js:13:4) - * Object.<anonymous> (/home/ava/ex.js:14:3) - * ``` - */ -module.exports = stack => { - if (!stack) { - return ''; - } - - stack = extractFrames(stack); - // Workaround for https://github.com/tapjs/stack-utils/issues/14 - // TODO: fix it in `stack-utils` - stack = cleanStack(stack); - - return stackUtils.clean(stack) - // Remove the trailing newline inserted by the `stack-utils` module - .trim(); -}; diff --git a/node_modules/ava/lib/caching-precompiler.js b/node_modules/ava/lib/caching-precompiler.js deleted file mode 100644 index f6e5e47c3..000000000 --- a/node_modules/ava/lib/caching-precompiler.js +++ /dev/null @@ -1,108 +0,0 @@ -'use strict'; -const path = require('path'); -const fs = require('fs'); -const convertSourceMap = require('convert-source-map'); -const cachingTransform = require('caching-transform'); -const packageHash = require('package-hash'); -const stripBomBuf = require('strip-bom-buf'); -const autoBind = require('auto-bind'); -const md5Hex = require('md5-hex'); - -function getSourceMap(filePath, code) { - let sourceMap = convertSourceMap.fromSource(code); - - if (!sourceMap) { - const dirPath = path.dirname(filePath); - sourceMap = convertSourceMap.fromMapFileSource(code, dirPath); - } - - if (sourceMap) { - sourceMap = sourceMap.toObject(); - } - - return sourceMap; -} - -class CachingPrecompiler { - constructor(options) { - autoBind(this); - - this.getBabelOptions = options.getBabelOptions; - this.babelCacheKeys = options.babelCacheKeys; - this.cacheDirPath = options.path; - this.fileHashes = {}; - this.transform = this._createTransform(); - } - - precompileFile(filePath) { - if (!this.fileHashes[filePath]) { - const source = stripBomBuf(fs.readFileSync(filePath)); - this.transform(source, filePath); - } - - return this.fileHashes[filePath]; - } - - // Conditionally called by caching-transform when precompiling is required - _init() { - this.babel = require('babel-core'); - return this._transform; - } - - _transform(code, filePath, hash) { - code = code.toString(); - - let result; - const originalBabelDisableCache = process.env.BABEL_DISABLE_CACHE; - try { - // Disable Babel's cache. AVA has good cache management already. - process.env.BABEL_DISABLE_CACHE = '1'; - - result = this.babel.transform(code, Object.assign(this.getBabelOptions(), { - inputSourceMap: getSourceMap(filePath, code), - filename: filePath, - sourceMaps: true, - ast: false - })); - } finally { - // Restore the original value. It is passed to workers, where users may - // not want Babel's cache to be disabled. - process.env.BABEL_DISABLE_CACHE = originalBabelDisableCache; - } - - // Save source map - const mapPath = path.join(this.cacheDirPath, `${hash}.js.map`); - fs.writeFileSync(mapPath, JSON.stringify(result.map)); - - // Append source map comment to transformed code - // So that other libraries (like nyc) can find the source map - const dirPath = path.dirname(filePath); - const relativeMapPath = path.relative(dirPath, mapPath); - const comment = convertSourceMap.generateMapFileComment(relativeMapPath); - - return `${result.code}\n${comment}`; - } - - _createTransform() { - const salt = packageHash.sync([ - require.resolve('../package.json'), - require.resolve('babel-core/package.json') - ], this.babelCacheKeys); - - return cachingTransform({ - factory: this._init, - cacheDir: this.cacheDirPath, - hash: this._generateHash, - salt, - ext: '.js' - }); - } - - _generateHash(code, filePath, salt) { - const hash = md5Hex([code, filePath, salt]); - this.fileHashes[filePath] = hash; - return hash; - } -} - -module.exports = CachingPrecompiler; diff --git a/node_modules/ava/lib/cli.js b/node_modules/ava/lib/cli.js deleted file mode 100644 index 0c2c2f82f..000000000 --- a/node_modules/ava/lib/cli.js +++ /dev/null @@ -1,210 +0,0 @@ -'use strict'; -const path = require('path'); -const updateNotifier = require('update-notifier'); -const figures = require('figures'); -const arrify = require('arrify'); -const meow = require('meow'); -const Promise = require('bluebird'); -const pkgConf = require('pkg-conf'); -const isCi = require('is-ci'); -const hasFlag = require('has-flag'); -const Api = require('../api'); -const colors = require('./colors'); -const VerboseReporter = require('./reporters/verbose'); -const MiniReporter = require('./reporters/mini'); -const TapReporter = require('./reporters/tap'); -const Logger = require('./logger'); -const Watcher = require('./watcher'); -const babelConfigHelper = require('./babel-config'); - -// Bluebird specific -Promise.longStackTraces(); - -exports.run = () => { - const conf = pkgConf.sync('ava'); - - const filepath = pkgConf.filepath(conf); - const projectDir = filepath === null ? process.cwd() : path.dirname(filepath); - - const cli = meow(` - Usage - ava [<file|directory|glob> ...] - - Options - --init Add AVA to your project - --fail-fast Stop after first test failure - --serial, -s Run tests serially - --tap, -t Generate TAP output - --verbose, -v Enable verbose output - --no-cache Disable the transpiler cache - --no-power-assert Disable Power Assert - --color Force color output - --no-color Disable color output - --match, -m Only run tests with matching title (Can be repeated) - --watch, -w Re-run tests when tests and source files change - --timeout, -T Set global timeout - --concurrency, -c Max number of test files running at the same time (Default: CPU cores) - --update-snapshots, -u Update snapshots - - Examples - ava - ava test.js test2.js - ava test-*.js - ava test - ava --init - ava --init foo.js - - Default patterns when no arguments: - test.js test-*.js test/**/*.js **/__tests__/**/*.js **/*.test.js - `, { - string: [ - '_', - 'match', - 'timeout', - 'concurrency' - ], - boolean: [ - 'init', - 'fail-fast', - 'serial', - 'tap', - 'verbose', - 'watch', - 'update-snapshots', - 'color' - ], - default: { - cache: conf.cache, - color: 'color' in conf ? conf.color : require('supports-color').stdout !== false, - concurrency: conf.concurrency, - failFast: conf.failFast, - init: conf.init, - match: conf.match, - powerAssert: conf.powerAssert, - serial: conf.serial, - tap: conf.tap, - timeout: conf.timeout, - updateSnapshots: conf.updateSnapshots, - verbose: conf.verbose, - watch: conf.watch - }, - alias: { - t: 'tap', - v: 'verbose', - s: 'serial', - m: 'match', - w: 'watch', - T: 'timeout', - c: 'concurrency', - u: 'update-snapshots' - } - }); - - updateNotifier({pkg: cli.pkg}).notify(); - - if (cli.flags.init) { - require('ava-init')(); - return; - } - - if ( - ((hasFlag('--watch') || hasFlag('-w')) && (hasFlag('--tap') || hasFlag('-t'))) || - (conf.watch && conf.tap) - ) { - throw new Error(colors.error(figures.cross) + ' The TAP reporter is not available when using watch mode.'); - } - - if ((hasFlag('--watch') || hasFlag('-w')) && isCi) { - throw new Error(colors.error(figures.cross) + ' Watch mode is not available in CI, as it prevents AVA from terminating.'); - } - - if (cli.flags.concurrency === '') { - throw new Error(colors.error(figures.cross) + ' The --concurrency and -c flags must be provided.'); - } - - if (cli.flags.concurrency && - (!Number.isInteger(Number.parseFloat(cli.flags.concurrency)) || parseInt(cli.flags.concurrency, 10) < 0)) { - throw new Error(colors.error(figures.cross) + ' The --concurrency and -c flags must be a nonnegative integer.'); - } - - if (hasFlag('--require') || hasFlag('-r')) { - throw new Error(colors.error(figures.cross) + ' The --require and -r flags are deprecated. Requirements should be configured in package.json - see documentation.'); - } - - // Copy resultant cli.flags into conf for use with Api and elsewhere - Object.assign(conf, cli.flags); - - const api = new Api({ - failFast: conf.failFast, - failWithoutAssertions: conf.failWithoutAssertions !== false, - serial: conf.serial, - require: arrify(conf.require), - cacheEnabled: conf.cache !== false, - powerAssert: conf.powerAssert !== false, - explicitTitles: conf.watch, - match: arrify(conf.match), - babelConfig: babelConfigHelper.validate(conf.babel), - resolveTestsFrom: cli.input.length === 0 ? projectDir : process.cwd(), - projectDir, - timeout: conf.timeout, - concurrency: conf.concurrency ? parseInt(conf.concurrency, 10) : 0, - updateSnapshots: conf.updateSnapshots, - snapshotDir: conf.snapshotDir ? path.resolve(projectDir, conf.snapshotDir) : null, - color: conf.color - }); - - let reporter; - - if (conf.tap && !conf.watch) { - reporter = new TapReporter(); - } else if (conf.verbose || isCi) { - reporter = new VerboseReporter({color: conf.color, watching: conf.watch}); - } else { - reporter = new MiniReporter({color: conf.color, watching: conf.watch}); - } - - reporter.api = api; - const logger = new Logger(reporter); - - logger.start(); - - api.on('test-run', runStatus => { - reporter.api = runStatus; - runStatus.on('test', logger.test); - runStatus.on('error', logger.unhandledError); - - runStatus.on('stdout', logger.stdout); - runStatus.on('stderr', logger.stderr); - }); - - const files = cli.input.length ? cli.input : arrify(conf.files); - - if (conf.watch) { - try { - const watcher = new Watcher(logger, api, files, arrify(conf.source)); - watcher.observeStdin(process.stdin); - } catch (err) { - if (err.name === 'AvaError') { - // An AvaError may be thrown if `chokidar` is not installed. Log it nicely. - console.error(` ${colors.error(figures.cross)} ${err.message}`); - logger.exit(1); - } else { - // Rethrow so it becomes an uncaught exception - throw err; - } - } - } else { - api.run(files) - .then(runStatus => { - logger.finish(runStatus); - logger.exit(runStatus.failCount > 0 || runStatus.rejectionCount > 0 || runStatus.exceptionCount > 0 ? 1 : 0); - }) - .catch(err => { - // Don't swallow exceptions. Note that any expected error should already - // have been logged. - setImmediate(() => { - throw err; - }); - }); - } -}; diff --git a/node_modules/ava/lib/code-excerpt.js b/node_modules/ava/lib/code-excerpt.js deleted file mode 100644 index aa619a0b2..000000000 --- a/node_modules/ava/lib/code-excerpt.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; -const fs = require('fs'); -const equalLength = require('equal-length'); -const codeExcerpt = require('code-excerpt'); -const truncate = require('cli-truncate'); -const chalk = require('chalk'); - -const formatLineNumber = (lineNumber, maxLineNumber) => - ' '.repeat(Math.max(0, String(maxLineNumber).length - String(lineNumber).length)) + lineNumber; - -module.exports = (source, options) => { - if (!source.isWithinProject || source.isDependency) { - return null; - } - - const file = source.file; - const line = source.line; - - options = options || {}; - const maxWidth = options.maxWidth || 80; - - let contents; - try { - contents = fs.readFileSync(file, 'utf8'); - } catch (err) { - return null; - } - - const excerpt = codeExcerpt(contents, line, {around: 1}); - if (!excerpt) { - return null; - } - - const lines = excerpt.map(item => ({ - line: item.line, - value: truncate(item.value, maxWidth - String(line).length - 5) - })); - - const joinedLines = lines.map(line => line.value).join('\n'); - const extendedLines = equalLength(joinedLines).split('\n'); - - return lines - .map((item, index) => ({ - line: item.line, - value: extendedLines[index] - })) - .map(item => { - const isErrorSource = item.line === line; - - const lineNumber = formatLineNumber(item.line, line) + ':'; - const coloredLineNumber = isErrorSource ? lineNumber : chalk.grey(lineNumber); - const result = ` ${coloredLineNumber} ${item.value}`; - - return isErrorSource ? chalk.bgRed(result) : result; - }) - .join('\n'); -}; diff --git a/node_modules/ava/lib/colors.js b/node_modules/ava/lib/colors.js deleted file mode 100644 index 75fb4d8aa..000000000 --- a/node_modules/ava/lib/colors.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; -const chalk = require('chalk'); - -module.exports = { - log: chalk.gray, - title: chalk.bold.white, - error: chalk.red, - skip: chalk.yellow, - todo: chalk.blue, - pass: chalk.green, - duration: chalk.gray.dim, - errorSource: chalk.gray, - errorStack: chalk.gray, - stack: chalk.red, - information: chalk.magenta -}; diff --git a/node_modules/ava/lib/concordance-options.js b/node_modules/ava/lib/concordance-options.js deleted file mode 100644 index 18b4b0c77..000000000 --- a/node_modules/ava/lib/concordance-options.js +++ /dev/null @@ -1,130 +0,0 @@ -'use strict'; -const ansiStyles = require('ansi-styles'); -const chalk = require('chalk'); -const stripAnsi = require('strip-ansi'); -const cloneDeepWith = require('lodash.clonedeepwith'); -const reactPlugin = require('@concordance/react'); -const options = require('./globals').options; - -// Wrap Concordance's React plugin. Change the name to avoid collisions if in -// the future users can register plugins themselves. -const avaReactPlugin = Object.assign({}, reactPlugin, {name: 'ava-plugin-react'}); -const plugins = [avaReactPlugin]; - -const forceColor = new chalk.constructor({enabled: true}); - -const colorTheme = { - boolean: ansiStyles.yellow, - circular: forceColor.grey('[Circular]'), - date: { - invalid: forceColor.red('invalid'), - value: ansiStyles.blue - }, - diffGutters: { - actual: forceColor.red('-') + ' ', - expected: forceColor.green('+') + ' ', - padding: ' ' - }, - error: { - ctor: {open: ansiStyles.grey.open + '(', close: ')' + ansiStyles.grey.close}, - name: ansiStyles.magenta - }, - function: { - name: ansiStyles.blue, - stringTag: ansiStyles.magenta - }, - global: ansiStyles.magenta, - item: {after: forceColor.grey(',')}, - list: {openBracket: forceColor.grey('['), closeBracket: forceColor.grey(']')}, - mapEntry: {after: forceColor.grey(',')}, - maxDepth: forceColor.grey('…'), - null: ansiStyles.yellow, - number: ansiStyles.yellow, - object: { - openBracket: forceColor.grey('{'), - closeBracket: forceColor.grey('}'), - ctor: ansiStyles.magenta, - stringTag: {open: ansiStyles.magenta.open + '@', close: ansiStyles.magenta.close}, - secondaryStringTag: {open: ansiStyles.grey.open + '@', close: ansiStyles.grey.close} - }, - property: { - after: forceColor.grey(','), - keyBracket: {open: forceColor.grey('['), close: forceColor.grey(']')}, - valueFallback: forceColor.grey('…') - }, - react: { - functionType: forceColor.grey('\u235F'), - openTag: { - start: forceColor.grey('<'), - end: forceColor.grey('>'), - selfClose: forceColor.grey('/'), - selfCloseVoid: ' ' + forceColor.grey('/') - }, - closeTag: { - open: forceColor.grey('</'), - close: forceColor.grey('>') - }, - tagName: ansiStyles.magenta, - attribute: { - separator: '=', - value: { - openBracket: forceColor.grey('{'), - closeBracket: forceColor.grey('}'), - string: { - line: {open: forceColor.blue('"'), close: forceColor.blue('"'), escapeQuote: '"'} - } - } - }, - child: { - openBracket: forceColor.grey('{'), - closeBracket: forceColor.grey('}') - } - }, - regexp: { - source: {open: ansiStyles.blue.open + '/', close: '/' + ansiStyles.blue.close}, - flags: ansiStyles.yellow - }, - stats: {separator: forceColor.grey('---')}, - string: { - open: ansiStyles.blue.open, - close: ansiStyles.blue.close, - line: {open: forceColor.blue('\''), close: forceColor.blue('\'')}, - multiline: {start: forceColor.blue('`'), end: forceColor.blue('`')}, - controlPicture: ansiStyles.grey, - diff: { - insert: { - open: ansiStyles.bgGreen.open + ansiStyles.black.open, - close: ansiStyles.black.close + ansiStyles.bgGreen.close - }, - delete: { - open: ansiStyles.bgRed.open + ansiStyles.black.open, - close: ansiStyles.black.close + ansiStyles.bgRed.close - }, - equal: ansiStyles.blue, - insertLine: { - open: ansiStyles.green.open, - close: ansiStyles.green.close - }, - deleteLine: { - open: ansiStyles.red.open, - close: ansiStyles.red.close - } - } - }, - symbol: ansiStyles.yellow, - typedArray: { - bytes: ansiStyles.yellow - }, - undefined: ansiStyles.yellow -}; - -const plainTheme = cloneDeepWith(colorTheme, value => { - if (typeof value === 'string') { - return stripAnsi(value); - } -}); - -const theme = options.color === false ? plainTheme : colorTheme; -exports.default = {maxDepth: 3, plugins, theme}; -exports.diff = {maxDepth: 1, plugins, theme}; -exports.snapshotManager = {plugins, theme: plainTheme}; diff --git a/node_modules/ava/lib/concurrent.js b/node_modules/ava/lib/concurrent.js deleted file mode 100644 index 3cdbb41c3..000000000 --- a/node_modules/ava/lib/concurrent.js +++ /dev/null @@ -1,64 +0,0 @@ -'use strict'; - -class Concurrent { - constructor(runnables, bail) { - if (!Array.isArray(runnables)) { - throw new TypeError('Expected an array of runnables'); - } - - this.runnables = runnables; - this.bail = bail || false; - } - - run() { - let allPassed = true; - - let pending; - let rejectPending; - let resolvePending; - const allPromises = []; - const handlePromise = promise => { - if (!pending) { - pending = new Promise((resolve, reject) => { - rejectPending = reject; - resolvePending = resolve; - }); - } - - allPromises.push(promise.then(passed => { - if (!passed) { - allPassed = false; - - if (this.bail) { - // Stop if the test failed and bail mode is on. - resolvePending(); - } - } - }, rejectPending)); - }; - - for (const runnable of this.runnables) { - const passedOrPromise = runnable.run(); - - if (!passedOrPromise) { - if (this.bail) { - // Stop if the test failed and bail mode is on. - return false; - } - - allPassed = false; - } else if (passedOrPromise !== true) { - handlePromise(passedOrPromise); - } - } - - if (pending) { - Promise.all(allPromises).then(resolvePending); - return pending.then(() => allPassed); - } - - return allPassed; - } -} - -module.exports = Concurrent; diff --git a/node_modules/ava/lib/enhance-assert.js b/node_modules/ava/lib/enhance-assert.js deleted file mode 100644 index 6991caf40..000000000 --- a/node_modules/ava/lib/enhance-assert.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; -const concordance = require('concordance'); -const dotProp = require('dot-prop'); -const generate = require('babel-generator').default; -const concordanceOptions = require('./concordance-options').default; - -// When adding patterns, don't forget to add to -// https://github.com/avajs/babel-preset-transform-test-files/blob/master/espower-patterns.json -// Then release a new version of that preset and bump the SemVer range here. -const PATTERNS = [ - 't.truthy(value, [message])', - 't.falsy(value, [message])', - 't.true(value, [message])', - 't.false(value, [message])', - 't.regex(contents, regex, [message])', - 't.notRegex(contents, regex, [message])' -]; - -const computeStatement = node => generate(node, {quotes: 'single'}).code; -const getNode = (ast, path) => dotProp.get(ast, path.replace(/\//g, '.')); - -const formatter = context => { - const ast = JSON.parse(context.source.ast); - const args = context.args[0].events; - return args - .map(arg => { - const node = getNode(ast, arg.espath); - const statement = computeStatement(node); - const formatted = concordance.format(arg.value, concordanceOptions); - return [statement, formatted]; - }) - .reverse(); -}; - -const enhanceAssert = (pass, fail, assertions) => { - const empower = require('empower-core'); - return empower(assertions, { - destructive: true, - onError(event) { - const error = event.error; - if (event.powerAssertContext) { // Context may be missing in internal tests. - error.statements = formatter(event.powerAssertContext); - } - fail(this, error); - }, - onSuccess() { - pass(this); - }, - patterns: PATTERNS, - bindReceiver: false - }); -}; -module.exports = enhanceAssert; diff --git a/node_modules/ava/lib/fork.js b/node_modules/ava/lib/fork.js deleted file mode 100644 index 0ca0f45a4..000000000 --- a/node_modules/ava/lib/fork.js +++ /dev/null @@ -1,176 +0,0 @@ -'use strict'; -const childProcess = require('child_process'); -const path = require('path'); -const fs = require('fs'); -const Promise = require('bluebird'); -const debug = require('debug')('ava'); -const AvaError = require('./ava-error'); - -if (fs.realpathSync(__filename) !== __filename) { - console.warn('WARNING: `npm link ava` and the `--preserve-symlink` flag are incompatible. We have detected that AVA is linked via `npm link`, and that you are using either an early version of Node 6, or the `--preserve-symlink` flag. This breaks AVA. You should upgrade to Node 6.2.0+, avoid the `--preserve-symlink` flag, or avoid using `npm link ava`.'); -} - -const env = Object.assign({NODE_ENV: 'test'}, process.env); - -// Ensure NODE_PATH paths are absolute -if (env.NODE_PATH) { - env.NODE_PATH = env.NODE_PATH - .split(path.delimiter) - .map(x => path.resolve(x)) - .join(path.delimiter); -} - -// In case the test file imports a different AVA install, -// the presence of this variable allows it to require this one instead -env.AVA_PATH = path.resolve(__dirname, '..'); - -module.exports = (file, opts, execArgv) => { - opts = Object.assign({ - file, - baseDir: process.cwd(), - tty: process.stdout.isTTY ? { - columns: process.stdout.columns, - rows: process.stdout.rows - } : false - }, opts); - - const args = [JSON.stringify(opts), opts.color ? '--color' : '--no-color']; - - const ps = childProcess.fork(path.join(__dirname, 'test-worker.js'), args, { - cwd: opts.projectDir, - silent: true, - env, - execArgv: execArgv || process.execArgv - }); - - const relFile = path.relative('.', file); - - let exiting = false; - const send = (name, data) => { - if (!exiting) { - // This seems to trigger a Node bug which kills the AVA master process, at - // least while running AVA's tests. See - // <https://github.com/novemberborn/_ava-tap-crash> for more details. - ps.send({ - name: `ava-${name}`, - data, - ava: true - }); - } - }; - - const testResults = []; - let results; - - const promise = new Promise((resolve, reject) => { - ps.on('error', reject); - - // Emit `test` and `stats` events - ps.on('message', event => { - if (!event.ava) { - return; - } - - event.name = event.name.replace(/^ava-/, ''); - event.data.file = relFile; - - debug('ipc %s:\n%o', event.name, event.data); - - ps.emit(event.name, event.data); - }); - - ps.on('test', props => { - testResults.push(props); - }); - - ps.on('results', data => { - results = data; - data.tests = testResults; - send('teardown'); - }); - - ps.on('exit', (code, signal) => { - if (code > 0) { - return reject(new AvaError(`${relFile} exited with a non-zero exit code: ${code}`)); - } - - if (code === null && signal) { - return reject(new AvaError(`${relFile} exited due to ${signal}`)); - } - - if (results) { - resolve(results); - } else { - reject(new AvaError(`Test results were not received from ${relFile}`)); - } - }); - - ps.on('no-tests', data => { - send('teardown'); - - let message = `No tests found in ${relFile}`; - - if (!data.avaRequired) { - message += ', make sure to import "ava" at the top of your test file'; - } - - reject(new AvaError(message)); - }); - }); - - // Teardown finished, now exit - ps.on('teardown', () => { - send('exit'); - exiting = true; - }); - - // Uncaught exception in fork, need to exit - ps.on('uncaughtException', () => { - send('teardown'); - }); - - ps.stdout.on('data', data => { - ps.emit('stdout', data); - }); - - ps.stderr.on('data', data => { - ps.emit('stderr', data); - }); - - promise.on = function () { - ps.on.apply(ps, arguments); - return promise; - }; - - promise.send = (name, data) => { - send(name, data); - return promise; - }; - - promise.exit = () => { - send('init-exit'); - return promise; - }; - - // Send 'run' event only when fork is listening for it - let isReady = false; - - ps.on('stats', () => { - isReady = true; - }); - - promise.run = options => { - if (isReady) { - send('run', options); - return promise; - } - - ps.on('stats', () => { - send('run', options); - }); - - return promise; - }; - - return promise; -}; diff --git a/node_modules/ava/lib/globals.js b/node_modules/ava/lib/globals.js deleted file mode 100644 index 51176c113..000000000 --- a/node_modules/ava/lib/globals.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -// Global objects / functions to be bound before requiring test file, so tests do not interfere - -const x = module.exports; -x.now = Date.now; -x.setTimeout = setTimeout; -x.clearTimeout = clearTimeout; -x.setImmediate = setImmediate; -x.options = {}; diff --git a/node_modules/ava/lib/logger.js b/node_modules/ava/lib/logger.js deleted file mode 100644 index e8edb120f..000000000 --- a/node_modules/ava/lib/logger.js +++ /dev/null @@ -1,92 +0,0 @@ -'use strict'; -const autoBind = require('auto-bind'); - -class Logger { - constructor(reporter) { - this.reporter = reporter; - autoBind(this); - } - - start(runStatus) { - if (!this.reporter.start) { - return; - } - - this.write(this.reporter.start(runStatus), runStatus); - } - - reset(runStatus) { - if (!this.reporter.reset) { - return; - } - - this.write(this.reporter.reset(runStatus), runStatus); - } - - test(test, runStatus) { - this.write(this.reporter.test(test, runStatus), runStatus); - } - - unhandledError(err, runStatus) { - if (!this.reporter.unhandledError) { - return; - } - - this.write(this.reporter.unhandledError(err, runStatus), runStatus); - } - - finish(runStatus) { - if (!this.reporter.finish) { - return; - } - - this.write(this.reporter.finish(runStatus), runStatus); - } - - section() { - if (!this.reporter.section) { - return; - } - - this.write(this.reporter.section()); - } - - clear() { - if (!this.reporter.clear) { - return false; - } - - this.write(this.reporter.clear()); - return true; - } - - write(str, runStatus) { - if (typeof str === 'undefined') { - return; - } - - this.reporter.write(str, runStatus); - } - - stdout(data, runStatus) { - if (!this.reporter.stdout) { - return; - } - - this.reporter.stdout(data, runStatus); - } - - stderr(data, runStatus) { - if (!this.reporter.stderr) { - return; - } - - this.reporter.stderr(data, runStatus); - } - - exit(code) { - process.exit(code); // eslint-disable-line unicorn/no-process-exit - } -} - -module.exports = Logger; diff --git a/node_modules/ava/lib/main.js b/node_modules/ava/lib/main.js deleted file mode 100644 index 4c5fdc373..000000000 --- a/node_modules/ava/lib/main.js +++ /dev/null @@ -1,105 +0,0 @@ -'use strict'; -const worker = require('./test-worker'); -const adapter = require('./process-adapter'); -const serializeError = require('./serialize-error'); -const globals = require('./globals'); -const Runner = require('./runner'); - -const opts = globals.options; -const runner = new Runner({ - bail: opts.failFast, - failWithoutAssertions: opts.failWithoutAssertions, - file: opts.file, - match: opts.match, - projectDir: opts.projectDir, - serial: opts.serial, - updateSnapshots: opts.updateSnapshots, - snapshotDir: opts.snapshotDir -}); - -worker.setRunner(runner); - -// If fail-fast is enabled, use this variable to detect -// that no more tests should be logged -let isFailed = false; - -Error.stackTraceLimit = Infinity; - -function test(props) { - if (isFailed) { - return; - } - - const hasError = typeof props.error !== 'undefined'; - - // Don't display anything if it's a passed hook - if (!hasError && props.type !== 'test') { - return; - } - - if (hasError) { - props.error = serializeError(props.error); - } else { - props.error = null; - } - - adapter.send('test', props); - - if (hasError && opts.failFast) { - isFailed = true; - exit(); - } -} - -function exit() { - // Reference the IPC channel now that tests have finished running. - adapter.ipcChannel.ref(); - - const stats = runner.buildStats(); - adapter.send('results', {stats}); -} - -globals.setImmediate(() => { - const hasExclusive = runner.tests.hasExclusive; - const numberOfTests = runner.tests.testCount; - - if (numberOfTests === 0) { - adapter.send('no-tests', {avaRequired: true}); - return; - } - - adapter.send('stats', { - testCount: numberOfTests, - hasExclusive - }); - - runner.on('test', test); - - process.on('ava-run', options => { - // Unreference the IPC channel. This stops it from keeping the event loop - // busy, which means the `beforeExit` event can be used to detect when tests - // stall. - adapter.ipcChannel.unref(); - - runner.run(options) - .then(() => { - runner.saveSnapshotState(); - - return exit(); - }) - .catch(err => { - process.emit('uncaughtException', err); - }); - }); - - process.on('ava-init-exit', () => { - exit(); - }); -}); - -module.exports = runner.chain; - -// TypeScript imports the `default` property for -// an ES2015 default import (`import test from 'ava'`) -// See: https://github.com/Microsoft/TypeScript/issues/2242#issuecomment-83694181 -module.exports.default = runner.chain; diff --git a/node_modules/ava/lib/prefix-title.js b/node_modules/ava/lib/prefix-title.js deleted file mode 100644 index a1c7b4f3b..000000000 --- a/node_modules/ava/lib/prefix-title.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; -const path = require('path'); - -module.exports = (file, base, separator) => { - let prefix = file - // Only replace this.base if it is found at the start of the path - .replace(base, (match, offset) => offset === 0 ? '' : match) - .replace(/\.spec/, '') - .replace(/\.test/, '') - .replace(/test-/g, '') - .replace(/\.js$/, '') - .split(path.sep) - .filter(p => p !== '__tests__') - .join(separator); - - if (prefix.length > 0) { - prefix += separator; - } - - return prefix; -}; diff --git a/node_modules/ava/lib/process-adapter.js b/node_modules/ava/lib/process-adapter.js deleted file mode 100644 index 5f9c0d79d..000000000 --- a/node_modules/ava/lib/process-adapter.js +++ /dev/null @@ -1,103 +0,0 @@ -'use strict'; -const fs = require('fs'); -const path = require('path'); -const debug = require('debug')('ava'); -const sourceMapSupport = require('source-map-support'); -const installPrecompiler = require('require-precompiled'); - -// Parse and re-emit AVA messages -process.on('message', message => { - if (!message.ava) { - return; - } - - process.emit(message.name, message.data); -}); - -exports.send = (name, data) => { - process.send({ - name: `ava-${name}`, - data, - ava: true - }); -}; - -// `process.channel` was added in Node.js 7.1.0, but the channel was available -// through an undocumented API as `process._channel`. -exports.ipcChannel = process.channel || process._channel; - -const opts = JSON.parse(process.argv[2]); -exports.opts = opts; - -// Fake TTY support -if (opts.tty) { - process.stdout.isTTY = true; - process.stdout.columns = opts.tty.columns || 80; - process.stdout.rows = opts.tty.rows; - - const tty = require('tty'); - const isatty = tty.isatty; - - tty.isatty = function (fd) { - if (fd === 1 || fd === process.stdout) { - return true; - } - - return isatty(fd); - }; -} - -if (debug.enabled) { - // Forward the `time-require` `--sorted` flag. - // Intended for internal optimization tests only. - if (opts._sorted) { - process.argv.push('--sorted'); - } - - require('time-require'); // eslint-disable-line import/no-unassigned-import -} - -const sourceMapCache = new Map(); -const cacheDir = opts.cacheDir; - -exports.installSourceMapSupport = () => { - sourceMapSupport.install({ - environment: 'node', - handleUncaughtExceptions: false, - retrieveSourceMap(source) { - if (sourceMapCache.has(source)) { - return { - url: source, - map: fs.readFileSync(sourceMapCache.get(source), 'utf8') - }; - } - } - }); -}; - -exports.installPrecompilerHook = () => { - installPrecompiler(filename => { - const precompiled = opts.precompiled[filename]; - - if (precompiled) { - sourceMapCache.set(filename, path.join(cacheDir, `${precompiled}.js.map`)); - return fs.readFileSync(path.join(cacheDir, `${precompiled}.js`), 'utf8'); - } - - return null; - }); -}; - -exports.installDependencyTracking = (dependencies, testPath) => { - Object.keys(require.extensions).forEach(ext => { - const wrappedHandler = require.extensions[ext]; - - require.extensions[ext] = (module, filename) => { - if (filename !== testPath) { - dependencies.add(filename); - } - - wrappedHandler(module, filename); - }; - }); -}; diff --git a/node_modules/ava/lib/reporters/format-serialized-error.js b/node_modules/ava/lib/reporters/format-serialized-error.js deleted file mode 100644 index 6ab59e47c..000000000 --- a/node_modules/ava/lib/reporters/format-serialized-error.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; -const chalk = require('chalk'); -const trimOffNewlines = require('trim-off-newlines'); - -function formatSerializedError(error) { - const printMessage = error.values.length === 0 ? - Boolean(error.message) : - !error.values[0].label.startsWith(error.message); - - if (error.statements.length === 0 && error.values.length === 0) { - return {formatted: null, printMessage}; - } - - let formatted = ''; - for (const value of error.values) { - formatted += `${value.label}\n\n${trimOffNewlines(value.formatted)}\n\n`; - } - - for (const statement of error.statements) { - formatted += `${statement[0]}\n${chalk.grey('=>')} ${trimOffNewlines(statement[1])}\n\n`; - } - - formatted = trimOffNewlines(formatted); - return {formatted, printMessage}; -} -module.exports = formatSerializedError; diff --git a/node_modules/ava/lib/reporters/improper-usage-messages.js b/node_modules/ava/lib/reporters/improper-usage-messages.js deleted file mode 100644 index 014a4bf0d..000000000 --- a/node_modules/ava/lib/reporters/improper-usage-messages.js +++ /dev/null @@ -1,56 +0,0 @@ -'use strict'; -const chalk = require('chalk'); - -exports.forError = error => { - if (!error.improperUsage) { - return null; - } - - const assertion = error.assertion; - if (assertion === 'throws' || assertion === 'notThrows') { - return `Try wrapping the first argument to \`t.${assertion}()\` in a function: - - ${chalk.cyan(`t.${assertion}(() => { `)}${chalk.grey('/* your code here */')}${chalk.cyan(' })')} - -Visit the following URL for more details: - - ${chalk.blue.underline('https://github.com/avajs/ava#throwsfunctionpromise-error-message')}`; - } - - if (assertion === 'snapshot') { - const name = error.improperUsage.name; - const snapPath = error.improperUsage.snapPath; - - if (name === 'ChecksumError') { - return `The snapshot file is corrupted. - -File path: ${chalk.yellow(snapPath)} - -Please run AVA again with the ${chalk.cyan('--update-snapshots')} flag to recreate it.`; - } - - if (name === 'LegacyError') { - return `The snapshot file was created with AVA 0.19. It's not supported by this AVA version. - -File path: ${chalk.yellow(snapPath)} - -Please run AVA again with the ${chalk.cyan('--update-snapshots')} flag to upgrade.`; - } - - if (name === 'VersionMismatchError') { - const snapVersion = error.improperUsage.snapVersion; - const expectedVersion = error.improperUsage.expectedVersion; - const upgradeMessage = snapVersion < expectedVersion ? - `Please run AVA again with the ${chalk.cyan('--update-snapshots')} flag to upgrade.` : - 'You should upgrade AVA.'; - - return `The snapshot file is v${snapVersion}, but only v${expectedVersion} is supported. - -File path: ${chalk.yellow(snapPath)} - -${upgradeMessage}`; - } - } - - return null; -}; diff --git a/node_modules/ava/lib/reporters/mini.js b/node_modules/ava/lib/reporters/mini.js deleted file mode 100644 index a21d02a6b..000000000 --- a/node_modules/ava/lib/reporters/mini.js +++ /dev/null @@ -1,333 +0,0 @@ -'use strict'; -const StringDecoder = require('string_decoder').StringDecoder; -const cliCursor = require('cli-cursor'); -const lastLineTracker = require('last-line-stream/tracker'); -const plur = require('plur'); -const spinners = require('cli-spinners'); -const chalk = require('chalk'); -const figures = require('figures'); -const cliTruncate = require('cli-truncate'); -const cross = require('figures').cross; -const indentString = require('indent-string'); -const ansiEscapes = require('ansi-escapes'); -const trimOffNewlines = require('trim-off-newlines'); -const codeExcerpt = require('../code-excerpt'); -const colors = require('../colors'); -const formatSerializedError = require('./format-serialized-error'); -const improperUsageMessages = require('./improper-usage-messages'); - -class MiniReporter { - constructor(options) { - this.options = Object.assign({}, options); - - chalk.enabled = this.options.color; - for (const key of Object.keys(colors)) { - colors[key].enabled = this.options.color; - } - - const spinnerDef = spinners[process.platform === 'win32' ? 'line' : 'dots']; - this.spinnerFrames = spinnerDef.frames.map(c => chalk.gray.dim(c)); - this.spinnerInterval = spinnerDef.interval; - - this.reset(); - this.stream = process.stderr; - this.stringDecoder = new StringDecoder(); - } - - start() { - this.interval = setInterval(() => { - this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length; - this.write(this.prefix()); - }, this.spinnerInterval); - - return this.prefix(''); - } - - reset() { - this.clearInterval(); - this.passCount = 0; - this.knownFailureCount = 0; - this.failCount = 0; - this.skipCount = 0; - this.todoCount = 0; - this.rejectionCount = 0; - this.exceptionCount = 0; - this.currentStatus = ''; - this.currentTest = ''; - this.statusLineCount = 0; - this.spinnerIndex = 0; - this.lastLineTracker = lastLineTracker(); - } - - spinnerChar() { - return this.spinnerFrames[this.spinnerIndex]; - } - - clearInterval() { - clearInterval(this.interval); - this.interval = null; - } - - test(test) { - if (test.todo) { - this.todoCount++; - } else if (test.skip) { - this.skipCount++; - } else if (test.error) { - this.failCount++; - } else { - this.passCount++; - if (test.failing) { - this.knownFailureCount++; - } - } - - if (test.todo || test.skip) { - return; - } - - return this.prefix(this._test(test)); - } - - prefix(str) { - str = str || this.currentTest; - this.currentTest = str; - - // The space before the newline is required for proper formatting - // TODO(jamestalmage): Figure out why it's needed and document it here - return ` \n ${this.spinnerChar()} ${str}`; - } - - _test(test) { - const SPINNER_WIDTH = 3; - const PADDING = 1; - let title = cliTruncate(test.title, process.stdout.columns - SPINNER_WIDTH - PADDING); - - if (test.error || test.failing) { - title = colors.error(test.title); - } - - return title + '\n' + this.reportCounts(); - } - - unhandledError(err) { - if (err.type === 'exception') { - this.exceptionCount++; - } else { - this.rejectionCount++; - } - } - - reportCounts(time) { - const lines = [ - this.passCount > 0 ? '\n ' + colors.pass(this.passCount, 'passed') : '', - this.knownFailureCount > 0 ? '\n ' + colors.error(this.knownFailureCount, plur('known failure', this.knownFailureCount)) : '', - this.failCount > 0 ? '\n ' + colors.error(this.failCount, 'failed') : '', - this.skipCount > 0 ? '\n ' + colors.skip(this.skipCount, 'skipped') : '', - this.todoCount > 0 ? '\n ' + colors.todo(this.todoCount, 'todo') : '' - ].filter(Boolean); - - if (time && lines.length > 0) { - lines[0] += ' ' + time; - } - - return lines.join(''); - } - - finish(runStatus) { - this.clearInterval(); - let time; - - if (this.options.watching) { - time = chalk.gray.dim('[' + new Date().toLocaleTimeString('en-US', {hour12: false}) + ']'); - } - - let status = this.reportCounts(time) + '\n'; - - if (this.rejectionCount > 0) { - status += ' ' + colors.error(this.rejectionCount, plur('rejection', this.rejectionCount)) + '\n'; - } - - if (this.exceptionCount > 0) { - status += ' ' + colors.error(this.exceptionCount, plur('exception', this.exceptionCount)) + '\n'; - } - - if (runStatus.previousFailCount > 0) { - status += ' ' + colors.error(runStatus.previousFailCount, 'previous', plur('failure', runStatus.previousFailCount), 'in test files that were not rerun') + '\n'; - } - - if (this.knownFailureCount > 0) { - for (const test of runStatus.knownFailures) { - const title = test.title; - status += '\n ' + colors.title(title) + '\n'; - // TODO: Output description with link - // status += colors.stack(description); - } - } - - status += '\n'; - if (this.failCount > 0) { - runStatus.errors.forEach(test => { - if (!test.error) { - return; - } - - status += ' ' + colors.title(test.title) + '\n'; - - if (test.logs) { - test.logs.forEach(log => { - const logLines = indentString(colors.log(log), 6); - const logLinesWithLeadingFigure = logLines.replace( - /^ {6}/, - ` ${colors.information(figures.info)} ` - ); - - status += logLinesWithLeadingFigure + '\n'; - }); - - status += '\n'; - } - - if (test.error.source) { - status += ' ' + colors.errorSource(test.error.source.file + ':' + test.error.source.line) + '\n'; - - const excerpt = codeExcerpt(test.error.source, {maxWidth: process.stdout.columns}); - if (excerpt) { - status += '\n' + indentString(excerpt, 2) + '\n'; - } - } - - if (test.error.avaAssertionError) { - const result = formatSerializedError(test.error); - if (result.printMessage) { - status += '\n' + indentString(test.error.message, 2) + '\n'; - } - - if (result.formatted) { - status += '\n' + indentString(result.formatted, 2) + '\n'; - } - - const message = improperUsageMessages.forError(test.error); - if (message) { - status += '\n' + indentString(message, 2) + '\n'; - } - } else if (test.error.message) { - status += '\n' + indentString(test.error.message, 2) + '\n'; - } - - if (test.error.stack) { - const stack = test.error.stack; - if (stack.includes('\n')) { - status += '\n' + indentString(colors.errorStack(stack), 2) + '\n'; - } - } - - status += '\n\n\n'; - }); - } - - if (this.rejectionCount > 0 || this.exceptionCount > 0) { - // TODO(sindresorhus): Figure out why this causes a test failure when switched to a for-of loop - runStatus.errors.forEach(err => { - if (err.title) { - return; - } - - if (err.type === 'exception' && err.name === 'AvaError') { - status += ' ' + colors.error(cross + ' ' + err.message) + '\n\n'; - } else { - const title = err.type === 'rejection' ? 'Unhandled Rejection' : 'Uncaught Exception'; - status += ' ' + colors.title(title) + '\n'; - - if (err.name) { - status += ' ' + colors.stack(err.summary) + '\n'; - status += colors.errorStack(err.stack) + '\n\n'; - } else { - status += ' Threw non-error: ' + err.summary + '\n'; - } - } - }); - } - - if (runStatus.failFastEnabled === true && runStatus.remainingCount > 0 && runStatus.failCount > 0) { - const remaining = 'At least ' + runStatus.remainingCount + ' ' + plur('test was', 'tests were', runStatus.remainingCount) + ' skipped.'; - status += ' ' + colors.information('`--fail-fast` is on. ' + remaining) + '\n\n'; - } - - if (runStatus.hasExclusive === true && runStatus.remainingCount > 0) { - status += ' ' + colors.information('The .only() modifier is used in some tests.', runStatus.remainingCount, plur('test', runStatus.remainingCount), plur('was', 'were', runStatus.remainingCount), 'not run'); - } - - return '\n' + trimOffNewlines(status) + '\n'; - } - - section() { - return '\n' + chalk.gray.dim('\u2500'.repeat(process.stdout.columns || 80)); - } - - clear() { - return ''; - } - - write(str) { - cliCursor.hide(); - this.currentStatus = str; - this._update(); - this.statusLineCount = this.currentStatus.split('\n').length; - } - - stdout(data) { - this._update(data); - } - - stderr(data) { - this._update(data); - } - - _update(data) { - let str = ''; - let ct = this.statusLineCount; - const columns = process.stdout.columns; - let lastLine = this.lastLineTracker.lastLine(); - - // Terminals automatically wrap text. We only need the last log line as seen on the screen. - lastLine = lastLine.substring(lastLine.length - (lastLine.length % columns)); - - // Don't delete the last log line if it's completely empty. - if (lastLine.length > 0) { - ct++; - } - - // Erase the existing status message, plus the last log line. - str += ansiEscapes.eraseLines(ct); - - // Rewrite the last log line. - str += lastLine; - - if (str.length > 0) { - this.stream.write(str); - } - - if (data) { - // Send new log data to the terminal, and update the last line status. - this.lastLineTracker.update(this.stringDecoder.write(data)); - this.stream.write(data); - } - - let currentStatus = this.currentStatus; - - if (currentStatus.length > 0) { - lastLine = this.lastLineTracker.lastLine(); - // We need a newline at the end of the last log line, before the status message. - // However, if the last log line is the exact width of the terminal a newline is implied, - // and adding a second will cause problems. - if (lastLine.length % columns) { - currentStatus = '\n' + currentStatus; - } - // Rewrite the status message. - this.stream.write(currentStatus); - } - } -} - -module.exports = MiniReporter; diff --git a/node_modules/ava/lib/reporters/tap.js b/node_modules/ava/lib/reporters/tap.js deleted file mode 100644 index 5ef8a23e3..000000000 --- a/node_modules/ava/lib/reporters/tap.js +++ /dev/null @@ -1,132 +0,0 @@ -'use strict'; -const format = require('util').format; -const indentString = require('indent-string'); -const stripAnsi = require('strip-ansi'); -const yaml = require('js-yaml'); - -function dumpError(error, includeMessage) { - const obj = Object.assign({}, error.object); - if (error.name) { - obj.name = error.name; - } - if (includeMessage && error.message) { - obj.message = error.message; - } - - if (error.avaAssertionError) { - if (error.assertion) { - obj.assertion = error.assertion; - } - if (error.operator) { - obj.operator = error.operator; - } - if (error.values.length > 0) { - obj.values = error.values.reduce((acc, value) => { - acc[value.label] = stripAnsi(value.formatted); - return acc; - }, {}); - } - } - - if (error.stack) { - obj.at = error.stack.split('\n')[0]; - } - - return ` ---\n${indentString(yaml.safeDump(obj).trim(), 4)}\n ...`; -} - -class TapReporter { - constructor() { - this.i = 0; - } - - start() { - return 'TAP version 13'; - } - - test(test) { - const output = []; - - let directive = ''; - const passed = test.todo ? 'not ok' : 'ok'; - - if (test.todo) { - directive = '# TODO'; - } else if (test.skip) { - directive = '# SKIP'; - } - - const title = stripAnsi(test.title); - - const appendLogs = () => { - if (test.logs) { - test.logs.forEach(log => { - const logLines = indentString(log, 4); - const logLinesWithLeadingFigure = logLines.replace( - /^ {4}/, - ' * ' - ); - - output.push(logLinesWithLeadingFigure); - }); - } - }; - - output.push(`# ${title}`); - - if (test.error) { - output.push(format('not ok %d - %s', ++this.i, title)); - appendLogs(); - output.push(dumpError(test.error, true)); - } else { - output.push(format('%s %d - %s %s', passed, ++this.i, title, directive).trim()); - appendLogs(); - } - - return output.join('\n'); - } - - unhandledError(err) { - const output = [ - `# ${err.message}`, - format('not ok %d - %s', ++this.i, err.message) - ]; - // AvaErrors don't have stack traces - if (err.type !== 'exception' || err.name !== 'AvaError') { - output.push(dumpError(err, false)); - } - - return output.join('\n'); - } - - finish(runStatus) { - const output = [ - '', - '1..' + (runStatus.passCount + runStatus.failCount + runStatus.skipCount), - '# tests ' + (runStatus.passCount + runStatus.failCount + runStatus.skipCount), - '# pass ' + runStatus.passCount - ]; - - if (runStatus.skipCount > 0) { - output.push(`# skip ${runStatus.skipCount}`); - } - - output.push('# fail ' + (runStatus.failCount + runStatus.rejectionCount + runStatus.exceptionCount), ''); - - return output.join('\n'); - } - - write(str) { - console.log(str); - } - - stdout(data) { - process.stderr.write(data); - } - - stderr(data) { - this.stdout(data); - } -} - -module.exports = TapReporter; diff --git a/node_modules/ava/lib/reporters/verbose.js b/node_modules/ava/lib/reporters/verbose.js deleted file mode 100644 index c58d8db3b..000000000 --- a/node_modules/ava/lib/reporters/verbose.js +++ /dev/null @@ -1,204 +0,0 @@ -'use strict'; -const indentString = require('indent-string'); -const prettyMs = require('pretty-ms'); -const figures = require('figures'); -const chalk = require('chalk'); -const plur = require('plur'); -const trimOffNewlines = require('trim-off-newlines'); -const codeExcerpt = require('../code-excerpt'); -const colors = require('../colors'); -const formatSerializedError = require('./format-serialized-error'); -const improperUsageMessages = require('./improper-usage-messages'); - -class VerboseReporter { - constructor(options) { - this.options = Object.assign({}, options); - - chalk.enabled = this.options.color; - for (const key of Object.keys(colors)) { - colors[key].enabled = this.options.color; - } - } - - start() { - return ''; - } - - test(test, runStatus) { - const lines = []; - if (test.error) { - lines.push(' ' + colors.error(figures.cross) + ' ' + test.title + ' ' + colors.error(test.error.message)); - } else if (test.todo) { - lines.push(' ' + colors.todo('- ' + test.title)); - } else if (test.skip) { - lines.push(' ' + colors.skip('- ' + test.title)); - } else if (test.failing) { - lines.push(' ' + colors.error(figures.tick) + ' ' + colors.error(test.title)); - } else if (runStatus.fileCount === 1 && runStatus.testCount === 1 && test.title === '[anonymous]') { - // No output - } else { - // Display duration only over a threshold - const threshold = 100; - const duration = test.duration > threshold ? colors.duration(' (' + prettyMs(test.duration) + ')') : ''; - - lines.push(' ' + colors.pass(figures.tick) + ' ' + test.title + duration); - } - - if (test.logs) { - test.logs.forEach(log => { - const logLines = indentString(colors.log(log), 6); - const logLinesWithLeadingFigure = logLines.replace( - /^ {6}/, - ` ${colors.information(figures.info)} ` - ); - - lines.push(logLinesWithLeadingFigure); - }); - } - - return lines.length > 0 ? lines.join('\n') : undefined; - } - - unhandledError(err) { - if (err.type === 'exception' && err.name === 'AvaError') { - return colors.error(' ' + figures.cross + ' ' + err.message); - } - - const types = { - rejection: 'Unhandled Rejection', - exception: 'Uncaught Exception' - }; - - let output = colors.error(types[err.type] + ':', err.file) + '\n'; - - if (err.stack) { - output += ' ' + colors.stack(err.title || err.summary) + '\n'; - output += ' ' + colors.stack(err.stack) + '\n'; - } else { - output += ' ' + colors.stack(JSON.stringify(err)) + '\n'; - } - - output += '\n'; - - return output; - } - - finish(runStatus) { - let output = ''; - - const lines = [ - runStatus.failCount > 0 ? - ' ' + colors.error(runStatus.failCount, plur('test', runStatus.failCount), 'failed') : - ' ' + colors.pass(runStatus.passCount, plur('test', runStatus.passCount), 'passed'), - runStatus.knownFailureCount > 0 ? ' ' + colors.error(runStatus.knownFailureCount, plur('known failure', runStatus.knownFailureCount)) : '', - runStatus.skipCount > 0 ? ' ' + colors.skip(runStatus.skipCount, plur('test', runStatus.skipCount), 'skipped') : '', - runStatus.todoCount > 0 ? ' ' + colors.todo(runStatus.todoCount, plur('test', runStatus.todoCount), 'todo') : '', - runStatus.rejectionCount > 0 ? ' ' + colors.error(runStatus.rejectionCount, 'unhandled', plur('rejection', runStatus.rejectionCount)) : '', - runStatus.exceptionCount > 0 ? ' ' + colors.error(runStatus.exceptionCount, 'uncaught', plur('exception', runStatus.exceptionCount)) : '', - runStatus.previousFailCount > 0 ? ' ' + colors.error(runStatus.previousFailCount, 'previous', plur('failure', runStatus.previousFailCount), 'in test files that were not rerun') : '' - ].filter(Boolean); - - if (lines.length > 0) { - if (this.options.watching) { - lines[0] += ' ' + chalk.gray.dim('[' + new Date().toLocaleTimeString('en-US', {hour12: false}) + ']'); - } - output += lines.join('\n') + '\n'; - } - - if (runStatus.knownFailureCount > 0) { - runStatus.knownFailures.forEach(test => { - output += '\n\n ' + colors.error(test.title) + '\n'; - }); - } - - output += '\n'; - if (runStatus.failCount > 0) { - runStatus.tests.forEach(test => { - if (!test.error) { - return; - } - - output += ' ' + colors.title(test.title) + '\n'; - - if (test.logs) { - test.logs.forEach(log => { - const logLines = indentString(colors.log(log), 6); - const logLinesWithLeadingFigure = logLines.replace( - /^ {6}/, - ` ${colors.information(figures.info)} ` - ); - - output += logLinesWithLeadingFigure + '\n'; - }); - - output += '\n'; - } - - if (test.error.source) { - output += ' ' + colors.errorSource(test.error.source.file + ':' + test.error.source.line) + '\n'; - - const excerpt = codeExcerpt(test.error.source, {maxWidth: process.stdout.columns}); - if (excerpt) { - output += '\n' + indentString(excerpt, 2) + '\n'; - } - } - - if (test.error.avaAssertionError) { - const result = formatSerializedError(test.error); - if (result.printMessage) { - output += '\n' + indentString(test.error.message, 2) + '\n'; - } - - if (result.formatted) { - output += '\n' + indentString(result.formatted, 2) + '\n'; - } - - const message = improperUsageMessages.forError(test.error); - if (message) { - output += '\n' + indentString(message, 2) + '\n'; - } - } else if (test.error.message) { - output += '\n' + indentString(test.error.message, 2) + '\n'; - } - - if (test.error.stack) { - const stack = test.error.stack; - if (stack.includes('\n')) { - output += '\n' + indentString(colors.errorStack(stack), 2) + '\n'; - } - } - - output += '\n\n\n'; - }); - } - - if (runStatus.failFastEnabled === true && runStatus.remainingCount > 0 && runStatus.failCount > 0) { - const remaining = 'At least ' + runStatus.remainingCount + ' ' + plur('test was', 'tests were', runStatus.remainingCount) + ' skipped.'; - output += ' ' + colors.information('`--fail-fast` is on. ' + remaining) + '\n\n'; - } - - if (runStatus.hasExclusive === true && runStatus.remainingCount > 0) { - output += ' ' + colors.information('The .only() modifier is used in some tests.', runStatus.remainingCount, plur('test', runStatus.remainingCount), plur('was', 'were', runStatus.remainingCount), 'not run'); - } - - return '\n' + trimOffNewlines(output) + '\n'; - } - - section() { - return chalk.gray.dim('\u2500'.repeat(process.stdout.columns || 80)); - } - - write(str) { - console.error(str); - } - - stdout(data) { - process.stderr.write(data); - } - - stderr(data) { - process.stderr.write(data); - } -} - -module.exports = VerboseReporter; diff --git a/node_modules/ava/lib/run-status.js b/node_modules/ava/lib/run-status.js deleted file mode 100644 index 461ab8f90..000000000 --- a/node_modules/ava/lib/run-status.js +++ /dev/null @@ -1,136 +0,0 @@ -'use strict'; -const EventEmitter = require('events'); -const chalk = require('chalk'); -const flatten = require('arr-flatten'); -const figures = require('figures'); -const autoBind = require('auto-bind'); -const prefixTitle = require('./prefix-title'); - -function sum(arr, key) { - let result = 0; - - arr.forEach(item => { - result += item[key]; - }); - - return result; -} - -class RunStatus extends EventEmitter { - constructor(opts) { - super(); - - opts = opts || {}; - this.prefixTitles = opts.prefixTitles !== false; - this.hasExclusive = Boolean(opts.runOnlyExclusive); - this.base = opts.base || ''; - this.rejectionCount = 0; - this.exceptionCount = 0; - this.passCount = 0; - this.knownFailureCount = 0; - this.skipCount = 0; - this.todoCount = 0; - this.failCount = 0; - this.fileCount = 0; - this.testCount = 0; - this.remainingCount = 0; - this.previousFailCount = 0; - this.knownFailures = []; - this.errors = []; - this.stats = []; - this.tests = []; - this.failFastEnabled = opts.failFast || false; - this.updateSnapshots = opts.updateSnapshots || false; - - autoBind(this); - } - - observeFork(emitter) { - emitter - .on('teardown', this.handleTeardown) - .on('stats', this.handleStats) - .on('test', this.handleTest) - .on('unhandledRejections', this.handleRejections) - .on('uncaughtException', this.handleExceptions) - .on('stdout', this.handleOutput.bind(this, 'stdout')) - .on('stderr', this.handleOutput.bind(this, 'stderr')); - } - - handleRejections(data) { - this.rejectionCount += data.rejections.length; - - data.rejections.forEach(err => { - err.type = 'rejection'; - err.file = data.file; - this.emit('error', err, this); - this.errors.push(err); - }); - } - - handleExceptions(data) { - this.exceptionCount++; - const err = data.exception; - err.type = 'exception'; - err.file = data.file; - this.emit('error', err, this); - this.errors.push(err); - } - - handleTeardown(data) { - this.emit('dependencies', data.file, data.dependencies, this); - this.emit('touchedFiles', data.touchedFiles); - } - - handleStats(stats) { - this.emit('stats', stats, this); - - if (stats.hasExclusive) { - this.hasExclusive = true; - } - - this.testCount += stats.testCount; - } - - handleTest(test) { - test.title = this.prefixTitle(test.file) + test.title; - - if (test.error) { - this.errors.push(test); - } - - if (test.failing && !test.error) { - this.knownFailures.push(test); - } - - this.emit('test', test, this); - } - - prefixTitle(file) { - if (!this.prefixTitles) { - return ''; - } - - const separator = ' ' + chalk.gray.dim(figures.pointerSmall) + ' '; - - return prefixTitle(file, this.base, separator); - } - - handleOutput(channel, data) { - this.emit(channel, data, this); - } - - processResults(results) { - // Assemble stats from all tests - this.stats = results.map(result => result.stats); - this.tests = results.map(result => result.tests); - this.tests = flatten(this.tests); - this.passCount = sum(this.stats, 'passCount'); - this.knownFailureCount = sum(this.stats, 'knownFailureCount'); - this.skipCount = sum(this.stats, 'skipCount'); - this.todoCount = sum(this.stats, 'todoCount'); - this.failCount = sum(this.stats, 'failCount'); - this.remainingCount = this.testCount - this.passCount - this.failCount - this.skipCount - this.todoCount - this.knownFailureCount; - } -} - -module.exports = RunStatus; diff --git a/node_modules/ava/lib/runner.js b/node_modules/ava/lib/runner.js deleted file mode 100644 index eb02dde45..000000000 --- a/node_modules/ava/lib/runner.js +++ /dev/null @@ -1,232 +0,0 @@ -'use strict'; -const EventEmitter = require('events'); -const path = require('path'); -const Bluebird = require('bluebird'); -const optionChain = require('option-chain'); -const matcher = require('matcher'); -const snapshotManager = require('./snapshot-manager'); -const TestCollection = require('./test-collection'); -const validateTest = require('./validate-test'); - -const chainableMethods = { - defaults: { - type: 'test', - serial: false, - exclusive: false, - skipped: false, - todo: false, - failing: false, - callback: false, - always: false - }, - chainableMethods: { - test: {}, - serial: {serial: true}, - before: {type: 'before'}, - after: {type: 'after'}, - skip: {skipped: true}, - todo: {todo: true}, - failing: {failing: true}, - only: {exclusive: true}, - beforeEach: {type: 'beforeEach'}, - afterEach: {type: 'afterEach'}, - cb: {callback: true}, - always: {always: true} - } -}; - -function wrapFunction(fn, args) { - return function (t) { - return fn.apply(this, [t].concat(args)); - }; -} - -class Runner extends EventEmitter { - constructor(options) { - super(); - - options = options || {}; - - this.file = options.file; - this.match = options.match || []; - this.projectDir = options.projectDir; - this.serial = options.serial; - this.updateSnapshots = options.updateSnapshots; - this.snapshotDir = options.snapshotDir; - - this.hasStarted = false; - this.results = []; - this.snapshots = null; - this.tests = new TestCollection({ - bail: options.bail, - failWithoutAssertions: options.failWithoutAssertions, - compareTestSnapshot: this.compareTestSnapshot.bind(this) - }); - - this.chain = optionChain(chainableMethods, (opts, args) => { - let title; - let fn; - let macroArgIndex; - - if (this.hasStarted) { - throw new Error('All tests and hooks must be declared synchronously in your ' + - 'test file, and cannot be nested within other tests or hooks.'); - } - - if (typeof args[0] === 'string') { - title = args[0]; - fn = args[1]; - macroArgIndex = 2; - } else { - fn = args[0]; - title = null; - macroArgIndex = 1; - } - - if (this.serial) { - opts.serial = true; - } - - if (args.length > macroArgIndex) { - args = args.slice(macroArgIndex); - } else { - args = null; - } - - if (Array.isArray(fn)) { - fn.forEach(fn => { - this.addTest(title, opts, fn, args); - }); - } else { - this.addTest(title, opts, fn, args); - } - }); - } - - addTest(title, metadata, fn, args) { - if (args) { - if (fn.title) { - title = fn.title.apply(fn, [title || ''].concat(args)); - } - - fn = wrapFunction(fn, args); - } - - if (metadata.type === 'test' && this.match.length > 0) { - metadata.exclusive = matcher([title || ''], this.match).length === 1; - } - - const validationError = validateTest(title, fn, metadata); - if (validationError !== null) { - throw new TypeError(validationError); - } - - this.tests.add({ - metadata, - fn, - title - }); - } - - addTestResult(result) { - const test = result.result; - const props = { - logs: test.logs, - duration: test.duration, - title: test.title, - error: result.reason, - type: test.metadata.type, - skip: test.metadata.skipped, - todo: test.metadata.todo, - failing: test.metadata.failing - }; - - this.results.push(result); - this.emit('test', props); - } - - buildStats() { - const stats = { - failCount: 0, - knownFailureCount: 0, - passCount: 0, - skipCount: 0, - testCount: 0, - todoCount: 0 - }; - - for (const result of this.results) { - if (!result.passed) { - // Includes hooks - stats.failCount++; - } - - const metadata = result.result.metadata; - if (metadata.type === 'test') { - stats.testCount++; - - if (metadata.skipped) { - stats.skipCount++; - } else if (metadata.todo) { - stats.todoCount++; - } else if (result.passed) { - if (metadata.failing) { - stats.knownFailureCount++; - } else { - stats.passCount++; - } - } - } - } - - return stats; - } - - compareTestSnapshot(options) { - if (!this.snapshots) { - this.snapshots = snapshotManager.load({ - file: this.file, - fixedLocation: this.snapshotDir, - name: path.basename(this.file), - projectDir: this.projectDir, - relFile: path.relative(this.projectDir, this.file), - testDir: path.dirname(this.file), - updating: this.updateSnapshots - }); - this.emit('dependency', this.snapshots.snapPath); - } - - return this.snapshots.compare(options); - } - - saveSnapshotState() { - if (this.snapshots) { - const files = this.snapshots.save(); - if (files) { - this.emit('touched', files); - } - } else if (this.updateSnapshots) { - // TODO: There may be unused snapshot files if no test caused the - // snapshots to be loaded. Prune them. But not if tests (including hooks!) - // were skipped. Perhaps emit a warning if this occurs? - } - } - - run(options) { - if (options.runOnlyExclusive && !this.tests.hasExclusive) { - return Promise.resolve(null); - } - - this.hasStarted = true; - this.tests.on('test', result => { - this.addTestResult(result); - }); - return Bluebird.try(() => this.tests.build().run()); - } - - attributeLeakedError(err) { - return this.tests.attributeLeakedError(err); - } -} - -module.exports = Runner; diff --git a/node_modules/ava/lib/sequence.js b/node_modules/ava/lib/sequence.js deleted file mode 100644 index 1e5960a98..000000000 --- a/node_modules/ava/lib/sequence.js +++ /dev/null @@ -1,94 +0,0 @@ -'use strict'; - -const beforeExitSubscribers = new Set(); -const beforeExitHandler = () => { - for (const subscriber of beforeExitSubscribers) { - subscriber(); - } -}; -const onBeforeExit = subscriber => { - if (beforeExitSubscribers.size === 0) { - // Only listen for the event once, no matter how many Sequences are run - // concurrently. - process.on('beforeExit', beforeExitHandler); - } - - beforeExitSubscribers.add(subscriber); - return { - dispose() { - beforeExitSubscribers.delete(subscriber); - if (beforeExitSubscribers.size === 0) { - process.removeListener('beforeExit', beforeExitHandler); - } - } - }; -}; - -class Sequence { - constructor(runnables, bail) { - if (!Array.isArray(runnables)) { - throw new TypeError('Expected an array of runnables'); - } - - this.runnables = runnables; - this.bail = bail || false; - } - - run() { - const iterator = this.runnables[Symbol.iterator](); - - let activeRunnable; - const beforeExit = onBeforeExit(() => { - if (activeRunnable.finishDueToInactivity) { - activeRunnable.finishDueToInactivity(); - } - }); - - let allPassed = true; - const finish = () => { - beforeExit.dispose(); - return allPassed; - }; - - const runNext = () => { - let promise; - - for (let next = iterator.next(); !next.done; next = iterator.next()) { - activeRunnable = next.value; - const passedOrPromise = activeRunnable.run(); - if (!passedOrPromise) { - allPassed = false; - - if (this.bail) { - // Stop if the test failed and bail mode is on. - break; - } - } else if (passedOrPromise !== true) { - promise = passedOrPromise; - break; - } - } - - if (!promise) { - return finish(); - } - - return promise.then(passed => { - if (!passed) { - allPassed = false; - - if (this.bail) { - // Stop if the test failed and bail mode is on. - return finish(); - } - } - - return runNext(); - }); - }; - - return runNext(); - } -} - -module.exports = Sequence; diff --git a/node_modules/ava/lib/serialize-error.js b/node_modules/ava/lib/serialize-error.js deleted file mode 100644 index 13146ff42..000000000 --- a/node_modules/ava/lib/serialize-error.js +++ /dev/null @@ -1,99 +0,0 @@ -'use strict'; -const path = require('path'); -const cleanYamlObject = require('clean-yaml-object'); -const StackUtils = require('stack-utils'); -const assert = require('./assert'); -const beautifyStack = require('./beautify-stack'); - -function isAvaAssertionError(source) { - return source instanceof assert.AssertionError; -} - -function filter(propertyName, isRoot) { - return !isRoot || (propertyName !== 'message' && propertyName !== 'name' && propertyName !== 'stack'); -} - -const stackUtils = new StackUtils(); -function extractSource(stack) { - if (!stack) { - return null; - } - - const firstStackLine = stack.split('\n')[0]; - return stackUtils.parseLine(firstStackLine); -} -function buildSource(source) { - if (!source) { - return null; - } - - // Assume the CWD is the project directory. This holds since this function - // is only called in test workers, which are created with their working - // directory set to the project directory. - const projectDir = process.cwd(); - - const file = path.resolve(projectDir, source.file.trim()); - const rel = path.relative(projectDir, file); - - const isWithinProject = rel.split(path.sep)[0] !== '..'; - const isDependency = isWithinProject && path.dirname(rel).split(path.sep).indexOf('node_modules') > -1; - - return { - isDependency, - isWithinProject, - file, - line: source.line - }; -} - -module.exports = error => { - const stack = typeof error.stack === 'string' ? - beautifyStack(error.stack) : - null; - - const retval = { - avaAssertionError: isAvaAssertionError(error), - source: buildSource(extractSource(stack)) - }; - if (stack) { - retval.stack = stack; - } - - if (retval.avaAssertionError) { - retval.improperUsage = error.improperUsage; - retval.message = error.message; - retval.name = error.name; - retval.statements = error.statements; - retval.values = error.values; - - if (error.fixedSource) { - const source = buildSource(error.fixedSource); - if (source) { - retval.source = source; - } - } - - if (error.assertion) { - retval.assertion = error.assertion; - } - if (error.operator) { - retval.operator = error.operator; - } - } else { - retval.object = cleanYamlObject(error, filter); // Cleanly copy non-standard properties - if (typeof error.message === 'string') { - retval.message = error.message; - } - if (typeof error.name === 'string') { - retval.name = error.name; - } - } - - if (typeof error.stack === 'string') { - retval.summary = error.stack.split('\n')[0]; - } else { - retval.summary = JSON.stringify(error); - } - - return retval; -}; diff --git a/node_modules/ava/lib/snapshot-manager.js b/node_modules/ava/lib/snapshot-manager.js deleted file mode 100644 index fcc24922e..000000000 --- a/node_modules/ava/lib/snapshot-manager.js +++ /dev/null @@ -1,418 +0,0 @@ -'use strict'; - -const crypto = require('crypto'); -const fs = require('fs'); -const path = require('path'); -const zlib = require('zlib'); - -const writeFileAtomic = require('@ava/write-file-atomic'); -const concordance = require('concordance'); -const indentString = require('indent-string'); -const makeDir = require('make-dir'); -const md5Hex = require('md5-hex'); -const Buffer = require('safe-buffer').Buffer; -const convertSourceMap = require('convert-source-map'); - -const concordanceOptions = require('./concordance-options').snapshotManager; - -// Increment if encoding layout or Concordance serialization versions change. Previous AVA versions will not be able to -// decode buffers generated by a newer version, so changing this value will require a major version bump of AVA itself. -// The version is encoded as an unsigned 16 bit integer. -const VERSION = 1; - -const VERSION_HEADER = Buffer.alloc(2); -VERSION_HEADER.writeUInt16LE(VERSION); - -// The decoder matches on the trailing newline byte (0x0A). -const READABLE_PREFIX = Buffer.from(`AVA Snapshot v${VERSION}\n`, 'ascii'); -const REPORT_SEPARATOR = Buffer.from('\n\n', 'ascii'); -const REPORT_TRAILING_NEWLINE = Buffer.from('\n', 'ascii'); - -const MD5_HASH_LENGTH = 16; - -class SnapshotError extends Error { - constructor(message, snapPath) { - super(message); - this.name = 'SnapshotError'; - this.snapPath = snapPath; - } -} -exports.SnapshotError = SnapshotError; - -class ChecksumError extends SnapshotError { - constructor(snapPath) { - super('Checksum mismatch', snapPath); - this.name = 'ChecksumError'; - } -} -exports.ChecksumError = ChecksumError; - -class VersionMismatchError extends SnapshotError { - constructor(snapPath, version) { - super('Unexpected snapshot version', snapPath); - this.name = 'VersionMismatchError'; - this.snapVersion = version; - this.expectedVersion = VERSION; - } -} -exports.VersionMismatchError = VersionMismatchError; - -const LEGACY_SNAPSHOT_HEADER = Buffer.from('// Jest Snapshot v1'); -function isLegacySnapshot(buffer) { - return LEGACY_SNAPSHOT_HEADER.equals(buffer.slice(0, LEGACY_SNAPSHOT_HEADER.byteLength)); -} - -class LegacyError extends SnapshotError { - constructor(snapPath) { - super('Legacy snapshot file', snapPath); - this.name = 'LegacyError'; - } -} -exports.LegacyError = LegacyError; - -function tryRead(file) { - try { - return fs.readFileSync(file); - } catch (err) { - if (err.code === 'ENOENT') { - return null; - } - - throw err; - } -} - -function withoutLineEndings(buffer) { - let newLength = buffer.byteLength - 1; - while (buffer[newLength] === 0x0A || buffer[newLength] === 0x0D) { - newLength--; - } - return buffer.slice(0, newLength); -} - -function formatEntry(label, descriptor) { - if (label) { - label = `> ${label}\n\n`; - } - const codeBlock = indentString(concordance.formatDescriptor(descriptor, concordanceOptions), 4); - return Buffer.from(label + codeBlock, 'utf8'); -} - -function combineEntries(entries) { - const buffers = []; - let byteLength = 0; - - const sortedKeys = Array.from(entries.keys()).sort(); - for (const key of sortedKeys) { - const keyBuffer = Buffer.from(`\n\n## ${key}\n\n`, 'utf8'); - buffers.push(keyBuffer); - byteLength += keyBuffer.byteLength; - - const formattedEntries = entries.get(key); - const last = formattedEntries[formattedEntries.length - 1]; - for (const entry of formattedEntries) { - buffers.push(entry); - byteLength += entry.byteLength; - - if (entry !== last) { - buffers.push(REPORT_SEPARATOR); - byteLength += REPORT_SEPARATOR.byteLength; - } - } - } - - return {buffers, byteLength}; -} - -function generateReport(relFile, snapFile, entries) { - const combined = combineEntries(entries); - const buffers = combined.buffers; - let byteLength = combined.byteLength; - - const header = Buffer.from(`# Snapshot report for \`${relFile}\` - -The actual snapshot is saved in \`${snapFile}\`. - -Generated by [AVA](https://ava.li).`, 'utf8'); - buffers.unshift(header); - byteLength += header.byteLength; - - buffers.push(REPORT_TRAILING_NEWLINE); - byteLength += REPORT_TRAILING_NEWLINE.byteLength; - return Buffer.concat(buffers, byteLength); -} - -function appendReportEntries(existingReport, entries) { - const combined = combineEntries(entries); - const buffers = combined.buffers; - let byteLength = combined.byteLength; - - const prepend = withoutLineEndings(existingReport); - buffers.unshift(prepend); - byteLength += prepend.byteLength; - - return Buffer.concat(buffers, byteLength); -} - -function encodeSnapshots(buffersByHash) { - const buffers = []; - let byteOffset = 0; - - // Entry start and end pointers are relative to the header length. This means - // it's possible to append new entries to an existing snapshot file, without - // having to rewrite pointers for existing entries. - const headerLength = Buffer.alloc(4); - buffers.push(headerLength); - byteOffset += 4; - - // Allows 65535 hashes (tests or identified snapshots) per file. - const numHashes = Buffer.alloc(2); - numHashes.writeUInt16LE(buffersByHash.size); - buffers.push(numHashes); - byteOffset += 2; - - const entries = []; - for (const pair of buffersByHash) { - const hash = pair[0]; - const snapshotBuffers = pair[1]; - - buffers.push(Buffer.from(hash, 'hex')); - byteOffset += MD5_HASH_LENGTH; - - // Allows 65535 snapshots per hash. - const numSnapshots = Buffer.alloc(2); - numSnapshots.writeUInt16LE(snapshotBuffers.length, 0); - buffers.push(numSnapshots); - byteOffset += 2; - - for (const value of snapshotBuffers) { - // Each pointer is 32 bits, restricting the total, uncompressed buffer to - // 4 GiB. - const start = Buffer.alloc(4); - const end = Buffer.alloc(4); - entries.push({start, end, value}); - - buffers.push(start, end); - byteOffset += 8; - } - } - - headerLength.writeUInt32LE(byteOffset, 0); - - let bodyOffset = 0; - for (const entry of entries) { - const start = bodyOffset; - const end = bodyOffset + entry.value.byteLength; - entry.start.writeUInt32LE(start, 0); - entry.end.writeUInt32LE(end, 0); - buffers.push(entry.value); - bodyOffset = end; - } - byteOffset += bodyOffset; - - const compressed = zlib.gzipSync(Buffer.concat(buffers, byteOffset)); - const md5sum = crypto.createHash('md5').update(compressed).digest(); - return Buffer.concat([ - READABLE_PREFIX, - VERSION_HEADER, - md5sum, - compressed - ], READABLE_PREFIX.byteLength + VERSION_HEADER.byteLength + MD5_HASH_LENGTH + compressed.byteLength); -} - -function decodeSnapshots(buffer, snapPath) { - if (isLegacySnapshot(buffer)) { - throw new LegacyError(snapPath); - } - - // The version starts after the readable prefix, which is ended by a newline - // byte (0x0A). - const versionOffset = buffer.indexOf(0x0A) + 1; - const version = buffer.readUInt16LE(versionOffset); - if (version !== VERSION) { - throw new VersionMismatchError(snapPath, version); - } - - const md5sumOffset = versionOffset + 2; - const compressedOffset = md5sumOffset + MD5_HASH_LENGTH; - const compressed = buffer.slice(compressedOffset); - - const md5sum = crypto.createHash('md5').update(compressed).digest(); - const expectedSum = buffer.slice(md5sumOffset, compressedOffset); - if (!md5sum.equals(expectedSum)) { - throw new ChecksumError(snapPath); - } - - const decompressed = zlib.gunzipSync(compressed); - let byteOffset = 0; - - const headerLength = decompressed.readUInt32LE(byteOffset); - byteOffset += 4; - - const snapshotsByHash = new Map(); - const numHashes = decompressed.readUInt16LE(byteOffset); - byteOffset += 2; - - for (let count = 0; count < numHashes; count++) { - const hash = decompressed.toString('hex', byteOffset, byteOffset + MD5_HASH_LENGTH); - byteOffset += MD5_HASH_LENGTH; - - const numSnapshots = decompressed.readUInt16LE(byteOffset); - byteOffset += 2; - - const snapshotsBuffers = new Array(numSnapshots); - for (let index = 0; index < numSnapshots; index++) { - const start = decompressed.readUInt32LE(byteOffset) + headerLength; - byteOffset += 4; - const end = decompressed.readUInt32LE(byteOffset) + headerLength; - byteOffset += 4; - snapshotsBuffers[index] = decompressed.slice(start, end); - } - - // Allow for new entries to be appended to an existing header, which could - // lead to the same hash being present multiple times. - if (snapshotsByHash.has(hash)) { - snapshotsByHash.set(hash, snapshotsByHash.get(hash).concat(snapshotsBuffers)); - } else { - snapshotsByHash.set(hash, snapshotsBuffers); - } - } - - return snapshotsByHash; -} - -class Manager { - constructor(options) { - this.appendOnly = options.appendOnly; - this.dir = options.dir; - this.relFile = options.relFile; - this.reportFile = options.reportFile; - this.snapFile = options.snapFile; - this.snapPath = options.snapPath; - this.snapshotsByHash = options.snapshotsByHash; - - this.hasChanges = false; - this.reportEntries = new Map(); - } - - compare(options) { - const hash = md5Hex(options.belongsTo); - const entries = this.snapshotsByHash.get(hash) || []; - if (options.index > entries.length) { - throw new RangeError(`Cannot record snapshot ${options.index} for ${JSON.stringify(options.belongsTo)}, exceeds expected index of ${entries.length}`); - } - if (options.index === entries.length) { - this.record(hash, options); - return {pass: true}; - } - - const snapshotBuffer = entries[options.index]; - const actual = concordance.deserialize(snapshotBuffer, concordanceOptions); - - const expected = concordance.describe(options.expected, concordanceOptions); - const pass = concordance.compareDescriptors(actual, expected); - - return {actual, expected, pass}; - } - - record(hash, options) { - const descriptor = concordance.describe(options.expected, concordanceOptions); - - this.hasChanges = true; - const snapshot = concordance.serialize(descriptor); - if (this.snapshotsByHash.has(hash)) { - this.snapshotsByHash.get(hash).push(snapshot); - } else { - this.snapshotsByHash.set(hash, [snapshot]); - } - - const entry = formatEntry(options.label, descriptor); - if (this.reportEntries.has(options.belongsTo)) { - this.reportEntries.get(options.belongsTo).push(entry); - } else { - this.reportEntries.set(options.belongsTo, [entry]); - } - } - - save() { - if (!this.hasChanges) { - return null; - } - - const snapPath = this.snapPath; - const buffer = encodeSnapshots(this.snapshotsByHash); - - const reportPath = path.join(this.dir, this.reportFile); - const existingReport = this.appendOnly ? tryRead(reportPath) : null; - const reportBuffer = existingReport ? - appendReportEntries(existingReport, this.reportEntries) : - generateReport(this.relFile, this.snapFile, this.reportEntries); - - makeDir.sync(this.dir); - const tmpSnapPath = writeFileAtomic.sync(snapPath, buffer); - const tmpReportPath = writeFileAtomic.sync(reportPath, reportBuffer); - - return [tmpSnapPath, tmpReportPath, snapPath, reportPath]; - } -} - -function determineSnapshotDir(options) { - const testDir = determineSourceMappedDir(options); - if (options.fixedLocation) { - const relativeTestLocation = path.relative(options.projectDir, testDir); - return path.join(options.fixedLocation, relativeTestLocation); - } - - const parts = new Set(path.relative(options.projectDir, testDir).split(path.sep)); - if (parts.has('__tests__')) { - return path.join(testDir, '__snapshots__'); - } - if (parts.has('test') || parts.has('tests')) { // Accept tests, even though it's not in the default test patterns - return path.join(testDir, 'snapshots'); - } - - return testDir; -} - -function determineSourceMappedDir(options) { - const source = tryRead(options.file).toString(); - const converter = convertSourceMap.fromSource(source) || convertSourceMap.fromMapFileSource(source, options.testDir); - if (converter) { - const map = converter.toObject(); - const firstSource = `${map.sourceRoot || ''}${map.sources[0]}`; - const sourceFile = path.resolve(options.testDir, firstSource); - return path.dirname(sourceFile); - } - - return options.testDir; -} - -function load(options) { - const dir = determineSnapshotDir(options); - const reportFile = `${options.name}.md`; - const snapFile = `${options.name}.snap`; - const snapPath = path.join(dir, snapFile); - - let appendOnly = !options.updating; - let snapshotsByHash; - - if (!options.updating) { - const buffer = tryRead(snapPath); - if (buffer) { - snapshotsByHash = decodeSnapshots(buffer, snapPath); - } else { - appendOnly = false; - } - } - - return new Manager({ - appendOnly, - dir, - relFile: options.relFile, - reportFile, - snapFile, - snapPath, - snapshotsByHash: snapshotsByHash || new Map() - }); -} -exports.load = load; diff --git a/node_modules/ava/lib/test-collection.js b/node_modules/ava/lib/test-collection.js deleted file mode 100644 index fd34bc489..000000000 --- a/node_modules/ava/lib/test-collection.js +++ /dev/null @@ -1,230 +0,0 @@ -'use strict'; -const EventEmitter = require('events'); -const fnName = require('fn-name'); -const Concurrent = require('./concurrent'); -const Sequence = require('./sequence'); -const Test = require('./test'); - -class TestCollection extends EventEmitter { - constructor(options) { - super(); - - this.bail = options.bail; - this.failWithoutAssertions = options.failWithoutAssertions; - this.compareTestSnapshot = options.compareTestSnapshot; - this.hasExclusive = false; - this.testCount = 0; - - this.tests = { - concurrent: [], - serial: [] - }; - - this.hooks = { - before: [], - beforeEach: [], - after: [], - afterAlways: [], - afterEach: [], - afterEachAlways: [] - }; - - this.pendingTestInstances = new Set(); - - this._emitTestResult = this._emitTestResult.bind(this); - } - - add(test) { - const metadata = test.metadata; - const type = metadata.type; - - if (!type) { - throw new Error('Test type must be specified'); - } - - if (!test.title && test.fn) { - test.title = fnName(test.fn); - } - - // Workaround for Babel giving anonymous functions a name - if (test.title === 'callee$0$0') { - test.title = null; - } - - if (!test.title) { - if (type === 'test') { - test.title = '[anonymous]'; - } else { - test.title = type; - } - } - - if (metadata.always && type !== 'after' && type !== 'afterEach') { - throw new Error('"always" can only be used with after and afterEach hooks'); - } - - // Add a hook - if (type !== 'test') { - if (metadata.exclusive) { - throw new Error(`"only" cannot be used with a ${type} hook`); - } - - this.hooks[type + (metadata.always ? 'Always' : '')].push(test); - return; - } - - this.testCount++; - - // Add `.only()` tests if `.only()` was used previously - if (this.hasExclusive && !metadata.exclusive) { - return; - } - - if (metadata.exclusive && !this.hasExclusive) { - this.tests.concurrent = []; - this.tests.serial = []; - this.hasExclusive = true; - } - - if (metadata.serial) { - this.tests.serial.push(test); - } else { - this.tests.concurrent.push(test); - } - } - - _skippedTest(test) { - return { - run: () => { - this._emitTestResult({ - passed: true, - result: test - }); - - return true; - } - }; - } - - _emitTestResult(result) { - this.pendingTestInstances.delete(result.result); - this.emit('test', result); - } - - _buildHooks(hooks, testTitle, context) { - return hooks.map(hook => { - const test = this._buildHook(hook, testTitle, context); - - if (hook.metadata.skipped || hook.metadata.todo) { - return this._skippedTest(test); - } - - return test; - }); - } - - _buildHook(hook, testTitle, contextRef) { - let title = hook.title; - - if (testTitle) { - title += ` for ${testTitle}`; - } - - if (!contextRef) { - contextRef = null; - } - - const test = new Test({ - contextRef, - failWithoutAssertions: false, - fn: hook.fn, - compareTestSnapshot: this.compareTestSnapshot, - metadata: hook.metadata, - onResult: this._emitTestResult, - title - }); - this.pendingTestInstances.add(test); - return test; - } - - _buildTest(test, contextRef) { - if (!contextRef) { - contextRef = null; - } - - test = new Test({ - contextRef, - failWithoutAssertions: this.failWithoutAssertions, - fn: test.fn, - compareTestSnapshot: this.compareTestSnapshot, - metadata: test.metadata, - onResult: this._emitTestResult, - title: test.title - }); - this.pendingTestInstances.add(test); - return test; - } - - _buildTestWithHooks(test) { - if (test.metadata.skipped || test.metadata.todo) { - return new Sequence([this._skippedTest(this._buildTest(test))], true); - } - - const context = {context: {}}; - - const beforeHooks = this._buildHooks(this.hooks.beforeEach, test.title, context); - const afterHooks = this._buildHooks(this.hooks.afterEach, test.title, context); - - let sequence = new Sequence([].concat(beforeHooks, this._buildTest(test, context), afterHooks), true); - if (this.hooks.afterEachAlways.length > 0) { - const afterAlwaysHooks = new Sequence(this._buildHooks(this.hooks.afterEachAlways, test.title, context)); - sequence = new Sequence([sequence, afterAlwaysHooks], false); - } - return sequence; - } - - _buildTests(tests) { - return tests.map(test => this._buildTestWithHooks(test)); - } - - _hasUnskippedTests() { - return this.tests.serial.concat(this.tests.concurrent) - .some(test => { - return !(test.metadata && test.metadata.skipped === true); - }); - } - - build() { - const serialTests = new Sequence(this._buildTests(this.tests.serial), this.bail); - const concurrentTests = new Concurrent(this._buildTests(this.tests.concurrent), this.bail); - const allTests = new Sequence([serialTests, concurrentTests]); - - let finalTests; - // Only run before and after hooks when there are unskipped tests - if (this._hasUnskippedTests()) { - const beforeHooks = new Sequence(this._buildHooks(this.hooks.before)); - const afterHooks = new Sequence(this._buildHooks(this.hooks.after)); - finalTests = new Sequence([beforeHooks, allTests, afterHooks], true); - } else { - finalTests = new Sequence([allTests], true); - } - - if (this.hooks.afterAlways.length > 0) { - const afterAlwaysHooks = new Sequence(this._buildHooks(this.hooks.afterAlways)); - finalTests = new Sequence([finalTests, afterAlwaysHooks], false); - } - - return finalTests; - } - - attributeLeakedError(err) { - for (const test of this.pendingTestInstances) { - if (test.attributeLeakedError(err)) { - return true; - } - } - return false; - } -} - -module.exports = TestCollection; diff --git a/node_modules/ava/lib/test-worker.js b/node_modules/ava/lib/test-worker.js deleted file mode 100644 index 84fba364e..000000000 --- a/node_modules/ava/lib/test-worker.js +++ /dev/null @@ -1,141 +0,0 @@ -'use strict'; - -// Check if the test is being run without AVA cli -{ - const path = require('path'); - const chalk = require('chalk'); - - const isForked = typeof process.send === 'function'; - if (!isForked) { - const fp = path.relative('.', process.argv[1]); - - console.log(); - console.error('Test files must be run with the AVA CLI:\n\n ' + chalk.grey.dim('$') + ' ' + chalk.cyan('ava ' + fp) + '\n'); - - process.exit(1); // eslint-disable-line unicorn/no-process-exit - } -} - -const currentlyUnhandled = require('currently-unhandled')(); -const isObj = require('is-obj'); - -const adapter = require('./process-adapter'); -const globals = require('./globals'); - -const opts = adapter.opts; -globals.options = opts; - -const serializeError = require('./serialize-error'); - -(opts.require || []).forEach(x => require(x)); - -adapter.installSourceMapSupport(); -adapter.installPrecompilerHook(); - -const testPath = opts.file; - -const dependencies = new Set(); -adapter.installDependencyTracking(dependencies, testPath); - -const touchedFiles = new Set(); - -// Set when main.js is required (since test files should have `require('ava')`). -let runner = null; -exports.setRunner = newRunner => { - runner = newRunner; - runner.on('dependency', file => { - dependencies.add(file); - }); - runner.on('touched', files => { - for (const file of files) { - touchedFiles.add(file); - } - }); -}; - -require(testPath); - -// If AVA was not required, show an error -if (!runner) { - adapter.send('no-tests', {avaRequired: false}); -} - -function attributeLeakedError(err) { - if (!runner) { - return false; - } - - return runner.attributeLeakedError(err); -} - -const attributedRejections = new Set(); -process.on('unhandledRejection', (reason, promise) => { - if (attributeLeakedError(reason)) { - attributedRejections.add(promise); - } -}); - -process.on('uncaughtException', exception => { - if (attributeLeakedError(exception)) { - return; - } - - let serialized; - try { - serialized = serializeError(exception); - } catch (ignore) { // eslint-disable-line unicorn/catch-error-name - // Avoid using serializeError - const err = new Error('Failed to serialize uncaught exception'); - serialized = { - avaAssertionError: false, - name: err.name, - message: err.message, - stack: err.stack - }; - } - - // Ensure the IPC channel is refereced. The uncaught exception will kick off - // the teardown sequence, for which the messages must be received. - adapter.ipcChannel.ref(); - - adapter.send('uncaughtException', {exception: serialized}); -}); - -let tearingDown = false; -process.on('ava-teardown', () => { - // AVA-teardown can be sent more than once - if (tearingDown) { - return; - } - tearingDown = true; - - let rejections = currentlyUnhandled() - .filter(rejection => !attributedRejections.has(rejection.promise)); - - if (rejections.length > 0) { - rejections = rejections.map(rejection => { - let reason = rejection.reason; - if (!isObj(reason) || typeof reason.message !== 'string') { - reason = { - message: String(reason) - }; - } - return serializeError(reason); - }); - - adapter.send('unhandledRejections', {rejections}); - } - - // Include dependencies in the final teardown message. This ensures the full - // set of dependencies is included no matter how the process exits, unless - // it flat out crashes. Also include any files that AVA touched during the - // test run. This allows the watcher to ignore modifications to those files. - adapter.send('teardown', { - dependencies: Array.from(dependencies), - touchedFiles: Array.from(touchedFiles) - }); -}); - -process.on('ava-exit', () => { - process.exit(0); // eslint-disable-line xo/no-process-exit -}); diff --git a/node_modules/ava/lib/test.js b/node_modules/ava/lib/test.js deleted file mode 100644 index 839101b40..000000000 --- a/node_modules/ava/lib/test.js +++ /dev/null @@ -1,441 +0,0 @@ -'use strict'; -const isGeneratorFn = require('is-generator-fn'); -const co = require('co-with-promise'); -const concordance = require('concordance'); -const observableToPromise = require('observable-to-promise'); -const isPromise = require('is-promise'); -const isObservable = require('is-observable'); -const plur = require('plur'); -const assert = require('./assert'); -const globals = require('./globals'); -const concordanceOptions = require('./concordance-options').default; - -function formatErrorValue(label, error) { - const formatted = concordance.format(error, concordanceOptions); - return {label, formatted}; -} - -class SkipApi { - constructor(test) { - this._test = test; - } -} - -const captureStack = start => { - const limitBefore = Error.stackTraceLimit; - Error.stackTraceLimit = 1; - const obj = {}; - Error.captureStackTrace(obj, start); - Error.stackTraceLimit = limitBefore; - return obj.stack; -}; - -class ExecutionContext { - constructor(test) { - Object.defineProperties(this, { - _test: {value: test}, - skip: {value: new SkipApi(test)} - }); - } - - plan(ct) { - this._test.plan(ct, captureStack(this.plan)); - } - - get end() { - const end = this._test.bindEndCallback(); - const endFn = err => end(err, captureStack(endFn)); - return endFn; - } - - get title() { - return this._test.title; - } - - get context() { - const contextRef = this._test.contextRef; - return contextRef && contextRef.context; - } - - set context(context) { - const contextRef = this._test.contextRef; - - if (!contextRef) { - this._test.saveFirstError(new Error(`\`t.context\` is not available in ${this._test.metadata.type} tests`)); - return; - } - - contextRef.context = context; - } - - _throwsArgStart(assertion, file, line) { - this._test.trackThrows({assertion, file, line}); - } - - _throwsArgEnd() { - this._test.trackThrows(null); - } -} - -{ - const assertions = assert.wrapAssertions({ - log(executionContext, text) { - executionContext._test.addLog(text); - }, - - pass(executionContext) { - executionContext._test.countPassedAssertion(); - }, - - pending(executionContext, promise) { - executionContext._test.addPendingAssertion(promise); - }, - - fail(executionContext, error) { - executionContext._test.addFailedAssertion(error); - } - }); - Object.assign(ExecutionContext.prototype, assertions); - - function skipFn() { - this._test.countPassedAssertion(); - } - Object.keys(assertions).forEach(el => { - SkipApi.prototype[el] = skipFn; - }); -} - -class Test { - constructor(options) { - this.contextRef = options.contextRef; - this.failWithoutAssertions = options.failWithoutAssertions; - this.fn = isGeneratorFn(options.fn) ? co.wrap(options.fn) : options.fn; - this.metadata = options.metadata; - this.onResult = options.onResult; - this.title = options.title; - this.logs = []; - - this.snapshotInvocationCount = 0; - this.compareWithSnapshot = assertionOptions => { - const belongsTo = assertionOptions.id || this.title; - const expected = assertionOptions.expected; - const index = assertionOptions.id ? 0 : this.snapshotInvocationCount++; - const label = assertionOptions.id ? '' : assertionOptions.message || `Snapshot ${this.snapshotInvocationCount}`; - return options.compareTestSnapshot({belongsTo, expected, index, label}); - }; - - this.assertCount = 0; - this.assertError = undefined; - this.calledEnd = false; - this.duration = null; - this.endCallbackFinisher = null; - this.finishDueToAttributedError = null; - this.finishDueToInactivity = null; - this.finishing = false; - this.pendingAssertionCount = 0; - this.pendingThrowsAssertion = null; - this.planCount = null; - this.startedAt = 0; - } - - bindEndCallback() { - if (this.metadata.callback) { - return (err, stack) => { - this.endCallback(err, stack); - }; - } - - throw new Error('`t.end()`` is not supported in this context. To use `t.end()` as a callback, you must use "callback mode" via `test.cb(testName, fn)`'); - } - - endCallback(err, stack) { - if (this.calledEnd) { - this.saveFirstError(new Error('`t.end()` called more than once')); - return; - } - this.calledEnd = true; - - if (err) { - this.saveFirstError(new assert.AssertionError({ - actual: err, - message: 'Callback called with an error', - stack, - values: [formatErrorValue('Callback called with an error:', err)] - })); - } - - if (this.endCallbackFinisher) { - this.endCallbackFinisher(); - } - } - - createExecutionContext() { - return new ExecutionContext(this); - } - - countPassedAssertion() { - if (this.finishing) { - this.saveFirstError(new Error('Assertion passed, but test has already finished')); - } - - this.assertCount++; - } - - addLog(text) { - this.logs.push(text); - } - - addPendingAssertion(promise) { - if (this.finishing) { - this.saveFirstError(new Error('Assertion passed, but test has already finished')); - } - - this.assertCount++; - this.pendingAssertionCount++; - promise - .catch(err => this.saveFirstError(err)) - .then(() => this.pendingAssertionCount--); - } - - addFailedAssertion(error) { - if (this.finishing) { - this.saveFirstError(new Error('Assertion failed, but test has already finished')); - } - - this.assertCount++; - this.saveFirstError(error); - } - - saveFirstError(err) { - if (!this.assertError) { - this.assertError = err; - } - } - - plan(count, planStack) { - if (typeof count !== 'number') { - throw new TypeError('Expected a number'); - } - - this.planCount = count; - - // In case the `planCount` doesn't match `assertCount, we need the stack of - // this function to throw with a useful stack. - this.planStack = planStack; - } - - verifyPlan() { - if (!this.assertError && this.planCount !== null && this.planCount !== this.assertCount) { - this.saveFirstError(new assert.AssertionError({ - assertion: 'plan', - message: `Planned for ${this.planCount} ${plur('assertion', this.planCount)}, but got ${this.assertCount}.`, - operator: '===', - stack: this.planStack - })); - } - } - - verifyAssertions() { - if (!this.assertError) { - if (this.failWithoutAssertions && !this.calledEnd && this.planCount === null && this.assertCount === 0) { - this.saveFirstError(new Error('Test finished without running any assertions')); - } else if (this.pendingAssertionCount > 0) { - this.saveFirstError(new Error('Test finished, but an assertion is still pending')); - } - } - } - - trackThrows(pending) { - this.pendingThrowsAssertion = pending; - } - - detectImproperThrows(err) { - if (!this.pendingThrowsAssertion) { - return false; - } - - const pending = this.pendingThrowsAssertion; - this.pendingThrowsAssertion = null; - - const values = []; - if (err) { - values.push(formatErrorValue(`The following error was thrown, possibly before \`t.${pending.assertion}()\` could be called:`, err)); - } - - this.saveFirstError(new assert.AssertionError({ - assertion: pending.assertion, - fixedSource: {file: pending.file, line: pending.line}, - improperUsage: true, - message: `Improper usage of \`t.${pending.assertion}()\` detected`, - stack: err instanceof Error && err.stack, - values - })); - return true; - } - - waitForPendingThrowsAssertion() { - return new Promise(resolve => { - this.finishDueToAttributedError = () => { - resolve(this.finishPromised()); - }; - - this.finishDueToInactivity = () => { - this.detectImproperThrows(); - resolve(this.finishPromised()); - }; - - // Wait up to a second to see if an error can be attributed to the - // pending assertion. - globals.setTimeout(() => this.finishDueToInactivity(), 1000).unref(); - }); - } - - attributeLeakedError(err) { - if (!this.detectImproperThrows(err)) { - return false; - } - - this.finishDueToAttributedError(); - return true; - } - - callFn() { - try { - return { - ok: true, - retval: this.fn(this.createExecutionContext()) - }; - } catch (err) { - return { - ok: false, - error: err - }; - } - } - - run() { - this.startedAt = globals.now(); - - const result = this.callFn(); - if (!result.ok) { - if (!this.detectImproperThrows(result.error)) { - this.saveFirstError(new assert.AssertionError({ - message: 'Error thrown in test', - stack: result.error instanceof Error && result.error.stack, - values: [formatErrorValue('Error thrown in test:', result.error)] - })); - } - return this.finish(); - } - - const returnedObservable = isObservable(result.retval); - const returnedPromise = isPromise(result.retval); - - let promise; - if (returnedObservable) { - promise = observableToPromise(result.retval); - } else if (returnedPromise) { - // `retval` can be any thenable, so convert to a proper promise. - promise = Promise.resolve(result.retval); - } - - if (this.metadata.callback) { - if (returnedObservable || returnedPromise) { - const asyncType = returnedObservable ? 'observables' : 'promises'; - this.saveFirstError(new Error(`Do not return ${asyncType} from tests declared via \`test.cb(...)\`, if you want to return a promise simply declare the test via \`test(...)\``)); - return this.finish(); - } - - if (this.calledEnd) { - return this.finish(); - } - - return new Promise(resolve => { - this.endCallbackFinisher = () => { - resolve(this.finishPromised()); - }; - - this.finishDueToAttributedError = () => { - resolve(this.finishPromised()); - }; - - this.finishDueToInactivity = () => { - this.saveFirstError(new Error('`t.end()` was never called')); - resolve(this.finishPromised()); - }; - }); - } - - if (promise) { - return new Promise(resolve => { - this.finishDueToAttributedError = () => { - resolve(this.finishPromised()); - }; - - this.finishDueToInactivity = () => { - const err = returnedObservable ? - new Error('Observable returned by test never completed') : - new Error('Promise returned by test never resolved'); - this.saveFirstError(err); - resolve(this.finishPromised()); - }; - - promise - .catch(err => { - if (!this.detectImproperThrows(err)) { - this.saveFirstError(new assert.AssertionError({ - message: 'Rejected promise returned by test', - stack: err instanceof Error && err.stack, - values: [formatErrorValue('Rejected promise returned by test. Reason:', err)] - })); - } - }) - .then(() => resolve(this.finishPromised())); - }); - } - - return this.finish(); - } - - finish() { - this.finishing = true; - - if (!this.assertError && this.pendingThrowsAssertion) { - return this.waitForPendingThrowsAssertion(); - } - - this.verifyPlan(); - this.verifyAssertions(); - - this.duration = globals.now() - this.startedAt; - - let reason = this.assertError; - let passed = !reason; - - if (this.metadata.failing) { - passed = !passed; - - if (passed) { - reason = undefined; - } else { - reason = new Error('Test was expected to fail, but succeeded, you should stop marking the test as failing'); - } - } - - this.onResult({ - passed, - result: this, - reason - }); - - return passed; - } - - finishPromised() { - return new Promise(resolve => { - resolve(this.finish()); - }); - } -} - -module.exports = Test; diff --git a/node_modules/ava/lib/validate-test.js b/node_modules/ava/lib/validate-test.js deleted file mode 100644 index 8258a5990..000000000 --- a/node_modules/ava/lib/validate-test.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -function validate(title, fn, metadata) { - if (metadata.type !== 'test') { - if (metadata.exclusive) { - return '`only` is only for tests and cannot be used with hooks'; - } - - if (metadata.failing) { - return '`failing` is only for tests and cannot be used with hooks'; - } - - if (metadata.todo) { - return '`todo` is only for documentation of future tests and cannot be used with hooks'; - } - } - - if (metadata.todo) { - if (typeof fn === 'function') { - return '`todo` tests are not allowed to have an implementation. Use ' + - '`test.skip()` for tests with an implementation.'; - } - - if (typeof title !== 'string') { - return '`todo` tests require a title'; - } - - if (metadata.skipped || metadata.failing || metadata.exclusive) { - return '`todo` tests are just for documentation and cannot be used with `skip`, `only`, or `failing`'; - } - } else if (typeof fn !== 'function') { - return 'Expected an implementation. Use `test.todo()` for tests without an implementation.'; - } - - if (metadata.always) { - if (!(metadata.type === 'after' || metadata.type === 'afterEach')) { - return '`always` can only be used with `after` and `afterEach`'; - } - } - - if (metadata.skipped && metadata.exclusive) { - return '`only` tests cannot be skipped'; - } - - return null; -} - -module.exports = validate; diff --git a/node_modules/ava/lib/watcher.js b/node_modules/ava/lib/watcher.js deleted file mode 100644 index 3f5ed3ee7..000000000 --- a/node_modules/ava/lib/watcher.js +++ /dev/null @@ -1,376 +0,0 @@ -'use strict'; -const nodePath = require('path'); -const debug = require('debug')('ava:watcher'); -const diff = require('lodash.difference'); -const chokidar = require('chokidar'); -const flatten = require('arr-flatten'); -const union = require('array-union'); -const uniq = require('array-uniq'); -const AvaFiles = require('./ava-files'); - -function rethrowAsync(err) { - // Don't swallow exceptions. Note that any - // expected error should already have been logged - setImmediate(() => { - throw err; - }); -} - -const MIN_DEBOUNCE_DELAY = 10; -const INITIAL_DEBOUNCE_DELAY = 100; - -class Debouncer { - constructor(watcher) { - this.watcher = watcher; - this.timer = null; - this.repeat = false; - } - - debounce(delay) { - if (this.timer) { - this.again = true; - return; - } - - delay = delay ? Math.max(delay, MIN_DEBOUNCE_DELAY) : INITIAL_DEBOUNCE_DELAY; - - const timer = setTimeout(() => { - this.watcher.busy.then(() => { - // Do nothing if debouncing was canceled while waiting for the busy - // promise to fulfil - if (this.timer !== timer) { - return; - } - - if (this.again) { - this.timer = null; - this.again = false; - this.debounce(delay / 2); - } else { - this.watcher.runAfterChanges(); - this.timer = null; - this.again = false; - } - }); - }, delay); - - this.timer = timer; - } - - cancel() { - if (this.timer) { - clearTimeout(this.timer); - this.timer = null; - this.again = false; - } - } -} - -class TestDependency { - constructor(file, sources) { - this.file = file; - this.sources = sources; - } - - contains(source) { - return this.sources.indexOf(source) !== -1; - } -} - -class Watcher { - constructor(logger, api, files, sources) { - this.debouncer = new Debouncer(this); - this.avaFiles = new AvaFiles({ - files, - sources - }); - - this.clearLogOnNextRun = true; - this.runVector = 0; - this.previousFiles = files; - this.run = (specificFiles, updateSnapshots) => { - if (this.runVector > 0) { - const cleared = this.clearLogOnNextRun && logger.clear(); - if (!cleared) { - logger.reset(); - logger.section(); - } - this.clearLogOnNextRun = true; - - logger.reset(); - logger.start(); - } - - this.runVector += 1; - - const currentVector = this.runVector; - - let runOnlyExclusive = false; - - if (specificFiles) { - const exclusiveFiles = specificFiles.filter(file => this.filesWithExclusiveTests.indexOf(file) !== -1); - - runOnlyExclusive = exclusiveFiles.length !== this.filesWithExclusiveTests.length; - - if (runOnlyExclusive) { - // The test files that previously contained exclusive tests are always - // run, together with the remaining specific files. - const remainingFiles = diff(specificFiles, exclusiveFiles); - specificFiles = this.filesWithExclusiveTests.concat(remainingFiles); - } - } - - this.touchedFiles.clear(); - this.previousFiles = specificFiles || files; - this.busy = api.run(this.previousFiles, {runOnlyExclusive, updateSnapshots: updateSnapshots === true}) - .then(runStatus => { - runStatus.previousFailCount = this.sumPreviousFailures(currentVector); - logger.finish(runStatus); - - const badCounts = runStatus.failCount + runStatus.rejectionCount + runStatus.exceptionCount; - this.clearLogOnNextRun = this.clearLogOnNextRun && badCounts === 0; - }) - .catch(rethrowAsync); - }; - - this.testDependencies = []; - this.trackTestDependencies(api, sources); - - this.touchedFiles = new Set(); - this.trackTouchedFiles(api); - - this.filesWithExclusiveTests = []; - this.trackExclusivity(api); - - this.filesWithFailures = []; - this.trackFailures(api); - - this.dirtyStates = {}; - this.watchFiles(); - this.rerunAll(); - } - - watchFiles() { - const patterns = this.avaFiles.getChokidarPatterns(); - - chokidar.watch(patterns.paths, { - ignored: patterns.ignored, - ignoreInitial: true - }).on('all', (event, path) => { - if (event === 'add' || event === 'change' || event === 'unlink') { - debug('Detected %s of %s', event, path); - this.dirtyStates[path] = event; - this.debouncer.debounce(); - } - }); - } - - trackTestDependencies(api) { - const relative = absPath => nodePath.relative(process.cwd(), absPath); - - api.on('test-run', runStatus => { - runStatus.on('dependencies', (file, dependencies) => { - const sourceDeps = dependencies.map(x => relative(x)).filter(this.avaFiles.isSource); - this.updateTestDependencies(file, sourceDeps); - }); - }); - } - - updateTestDependencies(file, sources) { - if (sources.length === 0) { - this.testDependencies = this.testDependencies.filter(dep => dep.file !== file); - return; - } - - const isUpdate = this.testDependencies.some(dep => { - if (dep.file !== file) { - return false; - } - - dep.sources = sources; - - return true; - }); - - if (!isUpdate) { - this.testDependencies.push(new TestDependency(file, sources)); - } - } - - trackTouchedFiles(api) { - api.on('test-run', runStatus => { - runStatus.on('touchedFiles', files => { - for (const file of files) { - this.touchedFiles.add(nodePath.relative(process.cwd(), file)); - } - }); - }); - } - - trackExclusivity(api) { - api.on('stats', stats => { - this.updateExclusivity(stats.file, stats.hasExclusive); - }); - } - - updateExclusivity(file, hasExclusiveTests) { - const index = this.filesWithExclusiveTests.indexOf(file); - - if (hasExclusiveTests && index === -1) { - this.filesWithExclusiveTests.push(file); - } else if (!hasExclusiveTests && index !== -1) { - this.filesWithExclusiveTests.splice(index, 1); - } - } - - trackFailures(api) { - api.on('test-run', (runStatus, files) => { - files.forEach(file => { - this.pruneFailures(nodePath.relative(process.cwd(), file)); - }); - - const currentVector = this.runVector; - runStatus.on('error', err => { - this.countFailure(err.file, currentVector); - }); - runStatus.on('test', result => { - if (result.error) { - this.countFailure(result.file, currentVector); - } - }); - }); - } - - pruneFailures(file) { - this.filesWithFailures = this.filesWithFailures.filter(state => state.file !== file); - } - - countFailure(file, vector) { - const isUpdate = this.filesWithFailures.some(state => { - if (state.file !== file) { - return false; - } - - state.count++; - return true; - }); - - if (!isUpdate) { - this.filesWithFailures.push({ - file, - vector, - count: 1 - }); - } - } - - sumPreviousFailures(beforeVector) { - let total = 0; - - this.filesWithFailures.forEach(state => { - if (state.vector < beforeVector) { - total += state.count; - } - }); - - return total; - } - - cleanUnlinkedTests(unlinkedTests) { - unlinkedTests.forEach(testFile => { - this.updateTestDependencies(testFile, []); - this.updateExclusivity(testFile, false); - this.pruneFailures(testFile); - }); - } - - observeStdin(stdin) { - stdin.resume(); - stdin.setEncoding('utf8'); - - stdin.on('data', data => { - data = data.trim().toLowerCase(); - if (data !== 'r' && data !== 'rs' && data !== 'u') { - return; - } - - // Cancel the debouncer, it might rerun specific tests whereas *all* tests - // need to be rerun - this.debouncer.cancel(); - this.busy.then(() => { - // Cancel the debouncer again, it might have restarted while waiting for - // the busy promise to fulfil - this.debouncer.cancel(); - this.clearLogOnNextRun = false; - if (data === 'u') { - this.updatePreviousSnapshots(); - } else { - this.rerunAll(); - } - }); - }); - } - - rerunAll() { - this.dirtyStates = {}; - this.run(); - } - - updatePreviousSnapshots() { - this.dirtyStates = {}; - this.run(this.previousFiles, true); - } - - runAfterChanges() { - const dirtyStates = this.dirtyStates; - this.dirtyStates = {}; - - const dirtyPaths = Object.keys(dirtyStates).filter(path => { - if (this.touchedFiles.has(path)) { - debug('Ignoring known touched file %s', path); - this.touchedFiles.delete(path); - return false; - } - return true; - }); - const dirtyTests = dirtyPaths.filter(this.avaFiles.isTest); - const dirtySources = diff(dirtyPaths, dirtyTests); - const addedOrChangedTests = dirtyTests.filter(path => dirtyStates[path] !== 'unlink'); - const unlinkedTests = diff(dirtyTests, addedOrChangedTests); - - this.cleanUnlinkedTests(unlinkedTests); - - // No need to rerun tests if the only change is that tests were deleted - if (unlinkedTests.length === dirtyPaths.length) { - return; - } - - if (dirtySources.length === 0) { - // Run any new or changed tests - this.run(addedOrChangedTests); - return; - } - - // Try to find tests that depend on the changed source files - const testsBySource = dirtySources.map(path => { - return this.testDependencies.filter(dep => dep.contains(path)).map(dep => { - debug('%s is a dependency of %s', path, dep.file); - return dep.file; - }); - }, this).filter(tests => tests.length > 0); - - // Rerun all tests if source files were changed that could not be traced to - // specific tests - if (testsBySource.length !== dirtySources.length) { - debug('Sources remain that cannot be traced to specific tests: %O', dirtySources); - debug('Rerunning all tests'); - this.run(); - return; - } - - // Run all affected tests - this.run(union(addedOrChangedTests, uniq(flatten(testsBySource)))); - } -} - -module.exports = Watcher; |