1 | 'use strict'
|
2 |
|
3 | const Writable = require('stream').Writable
|
4 | const os = require('os')
|
5 | const test = require('tap').test
|
6 | const pino = require('pino')
|
7 | const serializers = pino.stdSerializers
|
8 | const prettyFactory = require('../')
|
9 |
|
10 |
|
11 | const epoch = 1522431328992
|
12 | const pid = process.pid
|
13 | const hostname = os.hostname()
|
14 |
|
15 | test('error like objects tests', (t) => {
|
16 | t.beforeEach((done) => {
|
17 | Date.originalNow = Date.now
|
18 | Date.now = () => epoch
|
19 |
|
20 | done()
|
21 | })
|
22 | t.afterEach((done) => {
|
23 | Date.now = Date.originalNow
|
24 | delete Date.originalNow
|
25 |
|
26 | done()
|
27 | })
|
28 |
|
29 | t.test('pino transform prettifies Error', (t) => {
|
30 | t.plan(2)
|
31 | const pretty = prettyFactory()
|
32 | const err = Error('hello world')
|
33 | const expected = err.stack.split('\n')
|
34 | expected.unshift(err.message)
|
35 |
|
36 | const log = pino({}, new Writable({
|
37 | write (chunk, enc, cb) {
|
38 | const formatted = pretty(chunk.toString())
|
39 | const lines = formatted.split('\n')
|
40 | t.is(lines.length, expected.length + 1)
|
41 | t.is(lines[0], `[${epoch}] INFO (${pid} on ${hostname}): hello world`)
|
42 | cb()
|
43 | }
|
44 | }))
|
45 |
|
46 | log.info(err)
|
47 | })
|
48 |
|
49 | t.test('errorProps recognizes user specified properties', (t) => {
|
50 | t.plan(3)
|
51 | const pretty = prettyFactory({ errorProps: 'statusCode,originalStack' })
|
52 | const log = pino({}, new Writable({
|
53 | write (chunk, enc, cb) {
|
54 | const formatted = pretty(chunk.toString())
|
55 | t.match(formatted, /\s{4}error stack/)
|
56 | t.match(formatted, /statusCode: 500/)
|
57 | t.match(formatted, /originalStack: original stack/)
|
58 | cb()
|
59 | }
|
60 | }))
|
61 |
|
62 | const error = Error('error message')
|
63 | error.stack = 'error stack'
|
64 | error.statusCode = 500
|
65 | error.originalStack = 'original stack'
|
66 |
|
67 | log.error(error)
|
68 | })
|
69 |
|
70 | t.test('prettifies ignores undefined errorLikeObject', (t) => {
|
71 | const pretty = prettyFactory()
|
72 | pretty({ err: undefined })
|
73 | pretty({ error: undefined })
|
74 | t.end()
|
75 | })
|
76 |
|
77 | t.test('prettifies Error in property within errorLikeObjectKeys', (t) => {
|
78 | t.plan(8)
|
79 | const pretty = prettyFactory({
|
80 | errorLikeObjectKeys: ['err']
|
81 | })
|
82 |
|
83 | const err = Error('hello world')
|
84 | const expected = err.stack.split('\n')
|
85 | expected.unshift(err.message)
|
86 |
|
87 | const log = pino({ serializers: { err: serializers.err } }, new Writable({
|
88 | write (chunk, enc, cb) {
|
89 | const formatted = pretty(chunk.toString())
|
90 | const lines = formatted.split('\n')
|
91 | t.is(lines.length, expected.length + 6)
|
92 | t.is(lines[0], `[${epoch}] INFO (${pid} on ${hostname}):`)
|
93 | t.match(lines[1], /\s{4}err: {/)
|
94 | t.match(lines[2], /\s{6}"type": "Error",/)
|
95 | t.match(lines[3], /\s{6}"message": "hello world",/)
|
96 | t.match(lines[4], /\s{6}"stack":/)
|
97 | t.match(lines[5], /\s{6}Error: hello world/)
|
98 |
|
99 | t.match(lines[6], /\s{10}(at Test.t.test|at Test.<anonymous>)/)
|
100 | cb()
|
101 | }
|
102 | }))
|
103 |
|
104 | log.info({ err })
|
105 | })
|
106 |
|
107 | t.test('prettifies Error in property within errorLikeObjectKeys when stack has escaped characters', (t) => {
|
108 | t.plan(8)
|
109 | const pretty = prettyFactory({
|
110 | errorLikeObjectKeys: ['err']
|
111 | })
|
112 |
|
113 | const err = Error('hello world')
|
114 | err.stack = 'Error: hello world\n at anonymous (C:\\project\\node_modules\\example\\index.js)'
|
115 | const expected = err.stack.split('\n')
|
116 | expected.unshift(err.message)
|
117 |
|
118 | const log = pino({ serializers: { err: serializers.err } }, new Writable({
|
119 | write (chunk, enc, cb) {
|
120 | const formatted = pretty(chunk.toString())
|
121 | const lines = formatted.split('\n')
|
122 | t.is(lines.length, expected.length + 6)
|
123 | t.is(lines[0], `[${epoch}] INFO (${pid} on ${hostname}):`)
|
124 | t.match(lines[1], /\s{4}err: {$/)
|
125 | t.match(lines[2], /\s{6}"type": "Error",$/)
|
126 | t.match(lines[3], /\s{6}"message": "hello world",$/)
|
127 | t.match(lines[4], /\s{6}"stack":$/)
|
128 | t.match(lines[5], /\s{10}Error: hello world$/)
|
129 | t.match(lines[6], /\s{10}at anonymous \(C:\\project\\node_modules\\example\\index.js\)$/)
|
130 | cb()
|
131 | }
|
132 | }))
|
133 |
|
134 | log.info({ err })
|
135 | })
|
136 |
|
137 | t.test('prettifies Error in property within errorLikeObjectKeys when stack is not the last property', (t) => {
|
138 | t.plan(9)
|
139 | const pretty = prettyFactory({
|
140 | errorLikeObjectKeys: ['err']
|
141 | })
|
142 |
|
143 | const err = Error('hello world')
|
144 | err.anotherField = 'dummy value'
|
145 | const expected = err.stack.split('\n')
|
146 | expected.unshift(err.message)
|
147 |
|
148 | const log = pino({ serializers: { err: serializers.err } }, new Writable({
|
149 | write (chunk, enc, cb) {
|
150 | const formatted = pretty(chunk.toString())
|
151 | const lines = formatted.split('\n')
|
152 | t.is(lines.length, expected.length + 7)
|
153 | t.is(lines[0], `[${epoch}] INFO (${pid} on ${hostname}):`)
|
154 | t.match(lines[1], /\s{4}err: {/)
|
155 | t.match(lines[2], /\s{6}"type": "Error",/)
|
156 | t.match(lines[3], /\s{6}"message": "hello world",/)
|
157 | t.match(lines[4], /\s{6}"stack":/)
|
158 | t.match(lines[5], /\s{6}Error: hello world/)
|
159 |
|
160 | t.match(lines[6], /\s{10}(at Test.t.test|at Test.<anonymous>)/)
|
161 | t.match(lines[lines.length - 3], /\s{6}"anotherField": "dummy value"/)
|
162 | cb()
|
163 | }
|
164 | }))
|
165 |
|
166 | log.info({ err })
|
167 | })
|
168 |
|
169 | t.test('errorProps flag with "*" (print all nested props)', function (t) {
|
170 | t.plan(9)
|
171 | const pretty = prettyFactory({ errorProps: '*' })
|
172 | const expectedLines = [
|
173 | ' error stack',
|
174 | 'statusCode: 500',
|
175 | 'originalStack: original stack',
|
176 | 'dataBaseSpecificError: {',
|
177 | ' erroMessage: "some database error message"',
|
178 | ' evenMoreSpecificStuff: {',
|
179 | ' "someErrorRelatedObject": "error"',
|
180 | ' }',
|
181 | '}'
|
182 | ]
|
183 | const log = pino({}, new Writable({
|
184 | write (chunk, enc, cb) {
|
185 | const formatted = pretty(chunk.toString())
|
186 | const lines = formatted.split('\n')
|
187 | lines.shift(); lines.pop()
|
188 | for (var i = 0; i < lines.length; i += 1) {
|
189 | t.is(lines[i], expectedLines[i])
|
190 | }
|
191 | cb()
|
192 | }
|
193 | }))
|
194 |
|
195 | const error = Error('error message')
|
196 | error.stack = 'error stack'
|
197 | error.statusCode = 500
|
198 | error.originalStack = 'original stack'
|
199 | error.dataBaseSpecificError = {
|
200 | erroMessage: 'some database error message',
|
201 | evenMoreSpecificStuff: {
|
202 | someErrorRelatedObject: 'error'
|
203 | }
|
204 | }
|
205 |
|
206 | log.error(error)
|
207 | })
|
208 |
|
209 | t.test('handles errors with a null stack', (t) => {
|
210 | t.plan(2)
|
211 | const pretty = prettyFactory()
|
212 | const log = pino({}, new Writable({
|
213 | write (chunk, enc, cb) {
|
214 | const formatted = pretty(chunk.toString())
|
215 | t.match(formatted, /\s{4}message: "foo"/)
|
216 | t.match(formatted, /\s{4}stack: null/)
|
217 | cb()
|
218 | }
|
219 | }))
|
220 |
|
221 | const error = { message: 'foo', stack: null }
|
222 | log.error(error)
|
223 | })
|
224 |
|
225 | t.test('handles errors with a null stack for Error object', (t) => {
|
226 | t.plan(3)
|
227 | const pretty = prettyFactory()
|
228 | const expectedLines = [
|
229 | ' some: "property"',
|
230 | ' stack: null',
|
231 | ' type: "Error"'
|
232 | ]
|
233 | const log = pino({}, new Writable({
|
234 | write (chunk, enc, cb) {
|
235 | const formatted = pretty(chunk.toString())
|
236 | const lines = formatted.split('\n')
|
237 | lines.shift(); lines.pop()
|
238 | for (var i = 0; i < lines.length; i += 1) {
|
239 | t.true(expectedLines.includes(lines[i]))
|
240 | }
|
241 | cb()
|
242 | }
|
243 | }))
|
244 |
|
245 | const error = Error('error message')
|
246 | error.stack = null
|
247 | error.some = 'property'
|
248 |
|
249 | log.error(error)
|
250 | })
|
251 |
|
252 | t.end()
|
253 | })
|