intern
Version:
Intern. A next-generation code testing stack for JavaScript.
725 lines • 28.4 kB
JavaScript
(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", "@dojo/core/lang", "./path"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var lang_1 = require("@dojo/core/lang");
var path_1 = require("./path");
function evalProperty(key) {
var addToExisting = key[key.length - 1] === '+';
var name = (addToExisting
? key.slice(0, key.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 isTask(value) {
if (!value || typeof value !== 'object') {
return false;
}
for (var _i = 0, _a = ['then', 'catch', 'finally', 'cancel']; _i < _a.length; _i++) {
var name_1 = _a[_i];
if (!(name_1 in value) || typeof value[name_1] !== 'function') {
return false;
}
}
return true;
}
exports.isTask = isTask;
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_2 = arg;
var value = void 0;
var args = parsedArgs;
var eq = arg.indexOf('=');
if (eq !== -1) {
name_2 = arg.slice(0, eq);
value = arg.slice(eq + 1);
}
if (name_2.indexOf('.') !== -1) {
var parts = name_2.split('.');
var head = parts.slice(0, parts.length - 1);
name_2 = 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_2] = true;
}
else {
if (!(name_2 in args)) {
args[name_2] = value;
}
else if (!Array.isArray(args[name_2])) {
args[name_2] = [args[name_2], value];
}
else {
args[name_2].push(value);
}
}
}
return parsedArgs;
}
exports.parseArgs = parseArgs;
function parseJson(json) {
return JSON.parse(removeComments(json));
}
exports.parseJson = parseJson;
function parseValue(name, value, parser, requiredProperty) {
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');
}
}
var _a;
}
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];
}
};
if (name === 'loader') {
setOption(config, name, parseValue(name, value, 'object', 'script'));
}
else if (name === 'bail' ||
name === 'baseline' ||
name === 'benchmark' ||
name === 'debug' ||
name === 'filterErrorStack' ||
name === 'showConfig') {
setOption(config, name, parseValue(name, value, 'boolean'));
}
else if (name === 'basePath' ||
name === 'coverageVariable' ||
name === 'description' ||
name === 'internPath' ||
name === 'name' ||
name === 'sessionId') {
setOption(config, name, parseValue(name, value, 'string'));
}
else if (name === 'defaultTimeout') {
setOption(config, name, parseValue(name, value, 'number'));
}
else if (name === 'grep') {
setOption(config, name, parseValue(name, value, 'regexp'));
}
else if (name === 'reporters') {
setOption(config, name, parseValue(name, value, 'object[]', 'name'), addToExisting);
}
else if (name === 'plugins' ||
name === 'requires' ||
name === 'require' ||
name === 'scripts') {
var useLoader = false;
var _name = name;
if (name === 'scripts') {
emit('deprecated', {
original: 'scripts',
replacement: 'plugins'
});
_name = 'plugins';
}
else if (name === 'require') {
emit('deprecated', {
original: 'require',
replacement: 'plugins'
});
_name = 'plugins';
}
else if (name === 'requires') {
emit('deprecated', {
original: 'require',
replacement: 'plugins',
message: 'Set `useLoader: true`'
});
_name = 'plugins';
useLoader = true;
}
var parsed = parseValue(_name, value, 'object[]', 'script');
if (useLoader) {
parsed.forEach(function (entry) {
entry.useLoader = true;
});
}
setOption(config, _name, parsed, addToExisting);
}
else if (name === 'suites') {
setOption(config, name, parseValue(name, value, 'string[]'), addToExisting);
}
else if (name === 'node' || name === '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;
if (name === 'scripts') {
emit('deprecated', {
original: 'scripts',
replacement: 'plugins'
});
name = 'plugins';
}
else if (name === 'require') {
emit('deprecated', {
original: 'require',
replacement: 'plugins'
});
name = 'plugins';
}
else if (name === 'requires') {
emit('deprecated', {
original: 'requires',
replacement: 'plugins',
message: 'Set `useLoader: true`'
});
name = 'plugins';
useLoader = true;
}
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;
default:
throw new Error("Invalid property " + key + " in " + envName_1 + " config");
}
});
}
}
else if (name === 'functionalBaseUrl' || name === 'serverUrl') {
setOption(config, name, parseValue(name, value, 'string'));
}
else if (name === 'proxy') {
if (value == null) {
setOption(config, name, undefined);
}
else {
setOption(config, name, parseValue(name, value, 'string'));
}
}
else if (name === 'capabilities' ||
name === 'instrumenterOptions' ||
name === 'tunnelOptions') {
setOption(config, name, parseValue(name, value, 'object'), addToExisting);
}
else if (name === 'environments') {
var _value = value;
if (!_value) {
_value = [];
}
else if (!Array.isArray(_value)) {
_value = [_value];
}
_value = _value.map(function (val) {
if (typeof val === 'object' && val.browserName == null) {
val.browserName = val.browser;
}
return val;
});
setOption(config, name, parseValue(name, _value, 'object[]', 'browserName'), addToExisting);
}
else if (name === 'excludeInstrumentation') {
emit('deprecated', {
original: 'excludeInstrumentation',
replacement: 'coverage'
});
}
else if (name === 'tunnel') {
setOption(config, name, parseValue(name, value, 'string'));
}
else if (name === 'functionalCoverage' ||
name === 'leaveRemoteOpen' ||
name === 'serveOnly' ||
name === 'runInSync') {
setOption(config, name, parseValue(name, value, 'boolean'));
}
else if (name === '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);
}
else if (name === 'functionalSuites') {
setOption(config, name, parseValue(name, value, 'string[]'), addToExisting);
}
else if (name === '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, {});
}
}
else if (name === 'connectTimeout' ||
name === 'heartbeatInterval' ||
name === 'maxConcurrency' ||
name === 'serverPort' ||
name === 'socketPort') {
setOption(config, name, parseValue(name, value, 'number'));
}
else {
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] = lang_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, serializeReplacer, 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);
lang_1.mixin(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 serializeReplacer(_key, value) {
if (!value) {
return value;
}
if (value instanceof RegExp) {
return value.source;
}
if (typeof value === 'function') {
return value.toString();
}
return value;
}
});
//# sourceMappingURL=util.js.map