UNPKG

intern

Version:

Intern. A next-generation code testing stack for JavaScript.

815 lines 33.1 kB
(function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "tslib", "@theintern/common", "./path"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.errorToJSON = exports.stringify = exports.splitConfigPath = exports.setOption = exports.pullFromArray = exports.processOption = exports.prefix = exports.parseValue = exports.parseJson = exports.parseArgs = exports.loadConfig = exports.getConfigDescription = exports.getBasePath = exports.evalProperty = void 0; var tslib_1 = require("tslib"); var common_1 = require("@theintern/common"); var path_1 = require("./path"); function evalProperty(key) { var strKey = key; var addToExisting = strKey[strKey.length - 1] === '+'; var name = ((addToExisting ? strKey.slice(0, strKey.length - 1) : key)); return { name: name, addToExisting: addToExisting }; } exports.evalProperty = evalProperty; function getBasePath(configFile, basePath, isAbsolute, pathSep) { pathSep = pathSep || path_1.getPathSep(configFile, basePath); var configPathParts = configFile.replace(/\\/g, '/').split('/'); var initialBasePath; if (configFile[0] === '/' && configPathParts.length === 2) { initialBasePath = '/'; } else { initialBasePath = configPathParts.slice(0, -1).join('/'); } var finalBasePath; if (basePath) { basePath = path_1.normalize(basePath); if (isAbsolute(basePath)) { finalBasePath = basePath; } else { finalBasePath = path_1.join(initialBasePath, basePath); } } else { finalBasePath = initialBasePath; } return finalBasePath.split('/').join(pathSep); } exports.getBasePath = getBasePath; function getConfigDescription(config, prefix) { if (prefix === void 0) { prefix = ''; } var description = ''; if (config.description) { description += "" + prefix + config.description + "\n\n"; } if (config.configs) { description += prefix + "Configs:\n"; var width_1 = Object.keys(config.configs).reduce(function (width, name) { return Math.max(width, name.length); }, 0); var lines = Object.keys(config.configs).map(function (name) { var child = config.configs[name]; while (name.length < width_1) { name += ' '; } var line = " " + name; if (child.description) { line += " (" + child.description + ")"; } return "" + prefix + line; }); description += lines.join('\n'); } return description; } exports.getConfigDescription = getConfigDescription; function loadConfig(configPath, loadText, args, childConfig) { return _loadConfig(configPath, loadText, args, childConfig).then(function (config) { delete config.config; delete config.extends; if (!(args && (args.showConfigs || args.help))) { delete config.configs; } return config; }); } exports.loadConfig = loadConfig; function parseArgs(rawArgs) { var parsedArgs = {}; for (var _i = 0, rawArgs_1 = rawArgs; _i < rawArgs_1.length; _i++) { var arg = rawArgs_1[_i]; var name_1 = arg; var value = void 0; var args = parsedArgs; var eq = arg.indexOf('='); if (eq !== -1) { name_1 = arg.slice(0, eq); value = arg.slice(eq + 1); } if (name_1.indexOf('.') !== -1) { var parts = name_1.split('.'); var head = parts.slice(0, parts.length - 1); name_1 = parts[parts.length - 1]; for (var _a = 0, head_1 = head; _a < head_1.length; _a++) { var part = head_1[_a]; if (!args[part]) { args[part] = {}; } args = args[part]; } } if (typeof value === 'undefined') { args[name_1] = true; } else { if (!(name_1 in args)) { args[name_1] = value; } else if (!Array.isArray(args[name_1])) { args[name_1] = [args[name_1], value]; } else { args[name_1].push(value); } } } return parsedArgs; } exports.parseArgs = parseArgs; function parseJson(json) { return JSON.parse(removeComments(json)); } exports.parseJson = parseJson; function parseValue(name, value, parser, requiredProperty) { var _a; switch (parser) { case 'boolean': if (typeof value === 'boolean') { return value; } if (value === 'true') { return true; } if (value === 'false') { return false; } throw new Error("Non-boolean value \"" + value + "\" for " + name); case 'number': var numValue = Number(value); if (!isNaN(numValue)) { return numValue; } throw new Error("Non-numeric value \"" + value + "\" for " + name); case 'regexp': if (typeof value === 'string') { return new RegExp(value); } if (value instanceof RegExp) { return value; } throw new Error("Non-regexp value \"" + value + "\" for " + name); case 'object': if (typeof value === 'string') { try { value = value ? JSON.parse(value) : {}; } catch (error) { if (!requiredProperty) { throw new Error("Non-object value \"" + value + "\" for " + name); } value = (_a = {}, _a[requiredProperty] = value, _a); } } if (Object.prototype.toString.call(value) === '[object Object]') { if (requiredProperty && !value[requiredProperty]) { throw new Error("Invalid value \"" + JSON.stringify(value) + "\" for " + name + ": missing '" + requiredProperty + "' property"); } return value; } throw new Error("Non-object value \"" + value + "\" for " + name); case 'object[]': if (!value) { value = []; } if (!Array.isArray(value)) { value = [value]; } return value.map(function (item) { return parseValue(name, item, 'object', requiredProperty); }); case 'string': if (typeof value === 'string') { return value; } throw new Error("Non-string value \"" + value + "\" for " + name); case 'string[]': if (!value) { value = []; } if (typeof value === 'string') { value = [value]; } if (Array.isArray(value) && value.every(function (v) { return typeof v === 'string'; })) { return value; } throw new Error("Non-string[] value \"" + value + "\" for " + name); default: if (typeof parser === 'function') { return parser(value); } else { throw new Error('Parser must be a valid type name'); } } } exports.parseValue = parseValue; function prefix(message, prefix) { return message .split('\n') .map(function (line) { return prefix + line; }) .join('\n'); } exports.prefix = prefix; function processOption(key, value, config, executor) { var _a = evalProperty(key), name = _a.name, addToExisting = _a.addToExisting; var emit = executor ? function (eventName, data) { executor.emit(eventName, data); } : function () { var _args = []; for (var _i = 0; _i < arguments.length; _i++) { _args[_i] = arguments[_i]; } }; switch (name) { case 'loader': { setOption(config, name, parseValue(name, value, 'object', 'script')); break; } case 'bail': case 'baseline': case 'benchmark': case 'debug': case 'filterErrorStack': case 'showConfig': { setOption(config, name, parseValue(name, value, 'boolean')); break; } case 'basePath': case 'coverageVariable': case 'description': case 'internPath': case 'name': case 'sessionId': { setOption(config, name, parseValue(name, value, 'string')); break; } case 'defaultTimeout': { setOption(config, name, parseValue(name, value, 'number')); break; } case 'grep': { setOption(config, name, parseValue(name, value, 'regexp')); break; } case 'reporters': { setOption(config, name, parseValue(name, value, 'object[]', 'name'), addToExisting); break; } case 'plugins': case 'requires': case 'require': case 'scripts': { var useLoader = false; var _name = name; switch (name) { case 'scripts': emit('deprecated', { original: 'scripts', replacement: 'plugins', }); _name = 'plugins'; break; case 'require': emit('deprecated', { original: 'require', replacement: 'plugins', }); _name = 'plugins'; break; case 'requires': emit('deprecated', { original: 'require', replacement: 'plugins', message: 'Set `useLoader: true`', }); _name = 'plugins'; useLoader = true; break; } var parsed = parseValue(_name, value, 'object[]', 'script'); if (useLoader) { parsed.forEach(function (entry) { entry.useLoader = true; }); } setOption(config, _name, parsed, addToExisting); break; } case 'suites': { setOption(config, name, parseValue(name, value, 'string[]'), addToExisting); break; } case 'node': case 'browser': { var envConfig_1 = config[name] || {}; if (!config[name]) { config[name] = envConfig_1; } var envName_1 = name; var _value_1 = parseValue(name, value, 'object'); if (_value_1) { Object.keys(_value_1).forEach(function (valueKey) { var key = valueKey; var resource = _value_1[key]; var _a = evalProperty(key), name = _a.name, addToExisting = _a.addToExisting; switch (name) { case 'loader': { resource = parseValue(name, resource, 'object', 'script'); setOption(envConfig_1, name, resource, false); break; } case 'reporters': { resource = parseValue('reporters', resource, 'object[]', 'name'); setOption(envConfig_1, name, resource, addToExisting); break; } case 'plugins': case 'require': case 'requires': case 'scripts': { var useLoader = false; switch (name) { case 'scripts': { emit('deprecated', { original: 'scripts', replacement: 'plugins', }); name = 'plugins'; break; } case 'require': { emit('deprecated', { original: 'require', replacement: 'plugins', }); name = 'plugins'; break; } case 'requires': { emit('deprecated', { original: 'requires', replacement: 'plugins', message: 'Set `useLoader: true`', }); name = 'plugins'; useLoader = true; break; } } resource = parseValue(name, resource, 'object[]', 'script'); if (useLoader) { resource.forEach(function (entry) { entry.useLoader = true; }); } setOption(envConfig_1, name, resource, addToExisting); break; } case 'suites': { resource = parseValue(name, resource, 'string[]'); setOption(envConfig_1, name, resource, addToExisting); break; } case 'tsconfig': { resource = parseValue(name, resource, function (tsconfig) { var value; if (tsconfig === false || tsconfig === 'false') { value = false; } else if (typeof tsconfig === 'string') { value = tsconfig; } if (typeof value === 'undefined') { throw new Error('"tsconfig" must be a string or `false`'); } return value; }); setOption(envConfig_1, name, resource); break; } default: { throw new Error("Invalid property " + key + " in " + envName_1 + " config"); } } }); } break; } case 'functionalBaseUrl': case 'serverUrl': { setOption(config, name, parseValue(name, value, 'string')); break; } case 'proxy': { if (value == null) { setOption(config, name, undefined); } else { setOption(config, name, parseValue(name, value, 'string')); } break; } case 'capabilities': case 'instrumenterOptions': case 'tunnelOptions': { setOption(config, name, parseValue(name, value, 'object'), addToExisting); break; } case 'environments': { var _value = value; if (!_value) { _value = []; } else if (!Array.isArray(_value)) { _value = [_value]; } _value = _value.map(function (val) { if (typeof val === 'object') { if (val.browserName == null && typeof val.browser !== 'undefined') { val.browserName = val.browser; } delete val.browser; } if (typeof val === 'object' && val.version == null) { val.version = val.browserVersion; } return val; }); setOption(config, name, parseValue(name, _value, 'object[]', 'browserName'), addToExisting); break; } case 'remoteOptions': { setOption(config, name, parseValue(name, value, 'object')); break; } case 'excludeInstrumentation': { emit('deprecated', { original: 'excludeInstrumentation', replacement: 'coverage', }); break; } case 'tunnel': { setOption(config, name, parseValue(name, value, 'string')); break; } case 'functionalCoverage': case 'serveOnly': case 'runInSync': { setOption(config, name, parseValue(name, value, 'boolean')); break; } case 'leaveRemoteOpen': { var parsed = void 0; try { parsed = parseValue(name, value, 'boolean'); } catch (error) { parsed = parseValue(name, value, 'string'); if (parsed !== 'fail') { throw new Error("Invalid value '" + parsed + "' for leaveRemoteOpen"); } } setOption(config, name, parsed); break; } case 'coverage': { var parsed = void 0; try { parsed = parseValue(name, value, 'boolean'); } catch (error) { parsed = parseValue(name, value, 'string[]'); } if (typeof parsed === 'boolean' && parsed !== false) { throw new Error("Non-false boolean for 'coverage'"); } setOption(config, name, parsed); break; } case 'functionalSuites': { setOption(config, name, parseValue(name, value, 'string[]'), addToExisting); break; } case 'functionalTimeouts': { if (!config.functionalTimeouts) { config.functionalTimeouts = {}; } var parsedTimeout_1 = parseValue(name, value, 'object'); if (parsedTimeout_1) { Object.keys(parsedTimeout_1).forEach(function (timeoutKey) { var key = timeoutKey; if (key === 'connectTimeout') { emit('deprecated', { original: 'functionalTimeouts.connectTimeout', replacement: 'connectTimeout', }); setOption(config, key, parseValue(key, parsedTimeout_1[key], 'number')); } else { config.functionalTimeouts[key] = parseValue("functionalTimeouts." + key, parsedTimeout_1[key], 'number'); } }); } else { setOption(config, name, {}); } break; } case 'connectTimeout': case 'heartbeatInterval': case 'maxConcurrency': case 'serverPort': case 'socketPort': case 'socketTimeout': { setOption(config, name, parseValue(name, value, 'number')); break; } case 'warnOnUncaughtException': case 'warnOnUnhandledRejection': { var parsed = void 0; try { parsed = parseValue(name, value, 'boolean'); } catch (error) { parsed = parseValue(name, value, 'regexp'); } setOption(config, name, parsed); break; } default: { emit('log', "Config has unknown option \"" + name + "\""); setOption(config, name, value); } } } exports.processOption = processOption; function pullFromArray(haystack, needle) { var removed = []; var i = 0; while ((i = haystack.indexOf(needle, i)) > -1) { removed.push(haystack.splice(i, 1)[0]); } return removed; } exports.pullFromArray = pullFromArray; function removeComments(text) { var state = 'default'; var i = 0; var chars = text.split(''); while (i < chars.length) { switch (state) { case 'block-comment': if (chars[i] === '*' && chars[i + 1] === '/') { chars[i] = ' '; chars[i + 1] = ' '; state = 'default'; i += 2; } else if (chars[i] !== '\n') { chars[i] = ' '; i += 1; } else { i += 1; } break; case 'line-comment': if (chars[i] === '\n') { state = 'default'; } else { chars[i] = ' '; } i += 1; break; case 'string': if (chars[i] === '"') { state = 'default'; i += 1; } else if (chars[i] === '\\' && chars[i + 1] === '\\') { i += 2; } else if (chars[i] === '\\' && chars[i + 1] === '"') { i += 2; } else { i += 1; } break; default: if (chars[i] === '"') { state = 'string'; i += 1; } else if (chars[i] === '/' && chars[i + 1] === '*') { chars[i] = ' '; chars[i + 1] = ' '; state = 'block-comment'; i += 2; } else if (chars[i] === '/' && chars[i + 1] === '/') { chars[i] = ' '; chars[i + 1] = ' '; state = 'line-comment'; i += 2; } else { i += 1; } } } return chars.join(''); } function setOption(config, name, value, addToExisting) { if (addToExisting === void 0) { addToExisting = false; } if (addToExisting) { var currentValue = config[name]; if (currentValue == null) { config[name] = value; } else if (Array.isArray(currentValue)) { currentValue.push.apply(currentValue, value); } else if (typeof config[name] === 'object') { config[name] = common_1.deepMixin({}, config[name], value); } else { throw new Error('Only array or object options may be added'); } } else { config[name] = value; } } exports.setOption = setOption; function splitConfigPath(path, separator) { if (separator === void 0) { separator = '/'; } var lastSep = path.lastIndexOf(configPathSeparator); if (lastSep === 0) { return { configFile: '', childConfig: path.slice(1) }; } if (lastSep === -1 || path[lastSep - 1] === separator) { return { configFile: path }; } return { configFile: path.slice(0, lastSep), childConfig: path.slice(lastSep + 1), }; } exports.splitConfigPath = splitConfigPath; function stringify(object, indent) { return JSON.stringify(object, getSerializeReplacer(), indent); } exports.stringify = stringify; function _loadConfig(configPath, loadText, args, childConfig) { return loadText(configPath) .then(function (text) { var preConfig; try { preConfig = parseJson(text); } catch (error) { throw new Error("Invalid JSON in " + configPath); } if (preConfig.extends) { var parts = configPath.split('/'); var _a = splitConfigPath(preConfig.extends), configFile = _a.configFile, childConfig_1 = _a.childConfig; var extensionPath = parts .slice(0, parts.length - 1) .concat(configFile) .join('/'); return _loadConfig(extensionPath, loadText, undefined, childConfig_1).then(function (extension) { Object.keys(preConfig) .filter(function (key) { return key !== 'configs'; }) .forEach(function (key) { processOption(key, preConfig[key], extension); }); if (preConfig.configs) { if (extension.configs == null) { extension.configs = {}; } Object.keys(preConfig.configs).forEach(function (key) { extension.configs[key] = preConfig.configs[key]; }); } return extension; }); } else { var config_1 = {}; Object.keys(preConfig).forEach(function (key) { processOption(key, preConfig[key], config_1); }); return config_1; } }) .then(function (config) { if (args && (args.showConfigs || args.help)) { return config; } if (childConfig) { var mixinConfig_1 = function (childConfig) { var configs = Array.isArray(childConfig) ? childConfig : [childConfig]; configs.forEach(function (childConfig) { var child = config.configs[childConfig]; if (!child) { throw new Error("Unknown child config \"" + childConfig + "\""); } if (child.extends) { mixinConfig_1(child.extends); } Object.keys(child) .filter(function (key) { return key !== 'node' && key !== 'browser'; }) .forEach(function (key) { processOption(key, child[key], config); }); ['node', 'browser'].forEach(function (key) { if (child[key]) { if (config[key]) { var envConfig = {}; processOption(key, child[key], envConfig); Object.assign(config[key], envConfig[key]); } else { processOption(key, child[key], config); } } }); }); }; mixinConfig_1(childConfig); } return config; }) .then(function (config) { if (args) { var resources = [ 'plugins', 'reporters', 'suites', ]; resources .filter(function (resource) { return resource in args; }) .forEach(function (resource) { var environments = ['node', 'browser']; environments .filter(function (environment) { return config[environment]; }) .forEach(function (environment) { delete config[environment][resource]; }); }); Object.keys(args).forEach(function (key) { processOption(key, args[key], config); }); } return config; }); } var configPathSeparator = '@'; function getSerializeReplacer() { var seen = new WeakSet(); return function (_key, value) { if (!value) { return value; } if (value instanceof RegExp) { return value.source; } if (typeof value === 'function') { return value.toString(); } if (typeof value === 'object') { if (seen.has(value)) { return; } seen.add(value); } return value; }; } function errorToJSON(error) { if (!error) { return undefined; } var name = error.name, message = error.message, stack = error.stack, lifecycleMethod = error.lifecycleMethod, showDiff = error.showDiff, actual = error.actual, expected = error.expected; return tslib_1.__assign(tslib_1.__assign(tslib_1.__assign({ name: name, message: message, stack: stack }, (lifecycleMethod ? { lifecycleMethod: lifecycleMethod } : {})), { showDiff: Boolean(showDiff) }), (showDiff ? { actual: actual, expected: expected } : {})); } exports.errorToJSON = errorToJSON; }); //# sourceMappingURL=util.js.map