1 | 'use strict'
|
2 | const path = require('path')
|
3 | const Module = require('module')
|
4 | const fs = require('fs')
|
5 | const binpath = path.resolve(__dirname, '../bin')
|
6 | const stack = require('./stack.js')
|
7 | const diff = require('diff')
|
8 | const yaml = require('tap-yaml')
|
9 |
|
10 | const hasOwn = (obj, key) =>
|
11 | Object.prototype.hasOwnProperty.call(obj, key)
|
12 |
|
13 | const tapDir = path.resolve(__dirname, '..')
|
14 | const 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 |
|
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 |
|
53 |
|
54 |
|
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 |
|
100 | module.exports = cleanDiag
|