var path = require('path'); var yaml = require('js-yaml'); module.exports.getDiag = function (body) { var yamlStart = body.indexOf(' ---'); var yamlEnd = body.indexOf(' ...\n'); var diag = body.slice(yamlStart, yamlEnd).split('\n').map(function (line) { return line.slice(2); }).join('\n'); // The stack trace and at variable will vary depending on where the code // is run, so just strip it out. var withStack = yaml.safeLoad(diag); delete withStack.stack; delete withStack.at; return withStack; }; // There are three challenges associated with checking the stack traces included // in errors: // 1) The base checkout directory of tape might change. Because stack traces // include absolute paths, the stack traces will change depending on the // checkout path. We handle this by replacing the base test directory with a // placeholder $TEST variable and the package root with a placehodler // $TAPE variable. // 2) Line positions within the file might change. We handle this by replacing // line and column markers with placeholder $LINE and $COL "variables" // a) node 0.8 does not provide nested eval line numbers, so we remove them // 3) Stacks themselves change frequently with refactoring. We've even run into // issues with node library refactorings "breaking" stack traces. Most of // these changes are irrelevant to the tests themselves. To counter this, we // strip out all stack frames that aren't directly under our test directory, // and replace them with placeholders. module.exports.stripFullStack = function (output) { var stripped = ' [... stack stripped ...]'; var withDuplicates = output.split('\n').map(function (line) { var m = line.match(/[ ]{8}at .*\((.*)\)/); var stripChangingData = function (line) { var withoutTestDir = line.replace(__dirname, '$TEST'); var withoutPackageDir = withoutTestDir.replace(path.dirname(__dirname), '$TAPE'); var withoutPathSep = withoutPackageDir.replace(new RegExp('\\' + path.sep, 'g'), '/'); var withoutLineNumbers = withoutPathSep.replace(/:\d+:\d+/g, ':$LINE:$COL'); var withoutNestedLineNumbers = withoutLineNumbers.replace(/, \:\$LINE:\$COL\)$/, ')'); return withoutNestedLineNumbers; }; if (m) { if (m[1].slice(0, __dirname.length) === __dirname) { return stripChangingData(line); } return stripped; } return stripChangingData(line); }); var deduped = withDuplicates.filter(function (line, ix) { var hasPrior = line === stripped && withDuplicates[ix - 1] === stripped; return !hasPrior; }); return deduped.join('\n'); };