UNPKG

3.12 kBJavaScriptView Raw
1'use strict'
2const path = require('path')
3const Module = require('module')
4const fs = require('fs')
5const binpath = path.resolve(__dirname, '../bin')
6const stack = require('./stack.js')
7const diff = require('diff')
8const yaml = require('tap-yaml')
9
10const hasOwn = (obj, key) =>
11 Object.prototype.hasOwnProperty.call(obj, key)
12
13const tapDir = path.resolve(__dirname, '..')
14const cleanDiag = object => {
15 const res = { ...object }
16 if (hasOwn(res, 'stack') && !hasOwn(res, 'at'))
17 res.at = stack.parseLine(res.stack.split('\n')[0])
18
19 // don't print locations in tap itself, that's almost never useful
20 const file = res.at && res.at.file && path.resolve(res.at.file)
21 if (file &&
22 (file.indexOf(__dirname) === 0 || file.indexOf(binpath) === 0) &&
23 (process.cwd() !== tapDir || process.env.TAP_DEV_SHORTSTACK === '1') &&
24 process.env.TAP_DEV_LONGSTACK !== '1') {
25 delete res.at
26 }
27
28 if (file && res.at && res.at.file && res.at.line && !res.source) {
29 const content = (() => {
30 try {
31 return fs.readFileSync(file, 'utf8')
32 } catch (er) {
33 }
34 })()
35 if (content) {
36 const lines = content.split('\n')
37 if (res.at.line <= lines.length) {
38 const startLine = Math.max(res.at.line - 2, 0)
39 const endLine = Math.min(res.at.line + 2, lines.length)
40 const caret = res.at.column &&
41 res.at.column <= lines[res.at.line - 1].length
42 ? [new Array(res.at.column).join('-') + '^'] : []
43 const context = lines.slice(startLine, res.at.line).concat(caret)
44 .concat(lines.slice(res.at.line, endLine))
45 const csplit = context.join('\n').trimRight()
46 if (csplit)
47 res.source = csplit + '\n'
48 }
49 }
50 }
51
52 // show a line by line string diff
53 // diff the yaml, to make it more humane, especially
54 // when strings or buffers are very large or multi-line
55 if (res.found && res.wanted && !res.diff) {
56 const f = res.found
57 const w = res.wanted
58 const fy = yaml.stringify(f)
59 const wy = yaml.stringify(w)
60 if (fy !== wy) {
61 res.diff = ['--- wanted', '+++ found'].concat(
62 diff.createPatch('', wy, fy)
63 .split(/\n/).slice(5).join('\n')
64 .replace(/^ (\||>)(\+|-)?\n/, '')
65 ).join('\n')
66 } else if (f !== w) {
67 res.note = 'object identities differ'
68 }
69 }
70
71 for (const [key, value] of Object.entries(res)) {
72 if (key === 'todo' ||
73 key === 'time' ||
74 /^_?tapChild/.test(key) ||
75 key === 'childId' ||
76 /^tapStream/.test(key) ||
77 /^tapMochaTest/.test(key) ||
78 key === 'cb' ||
79 key === 'name' ||
80 key === 'indent' ||
81 key === 'skip' ||
82 key === 'bail' ||
83 key === 'grep' ||
84 key === 'grepInvert' ||
85 key === 'only' ||
86 key === 'diagnostic' ||
87 key === 'buffered' ||
88 key === 'parent' ||
89 key === 'domainEmitter' ||
90 key === 'domainThrew' ||
91 key === 'domain' ||
92 key === 'at' && !value ||
93 key === 'stack' && !value)
94 delete res[key]
95 }
96
97 return res
98}
99
100module.exports = cleanDiag