pino-testkit 10.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/.nojekyll +0 -0
  2. package/.prettierignore +1 -0
  3. package/CNAME +1 -0
  4. package/CONTRIBUTING.md +30 -0
  5. package/LICENSE +21 -0
  6. package/README.md +175 -0
  7. package/SECURITY.md +87 -0
  8. package/benchmarks/basic.bench.js +95 -0
  9. package/benchmarks/child-child.bench.js +52 -0
  10. package/benchmarks/child-creation.bench.js +73 -0
  11. package/benchmarks/child.bench.js +62 -0
  12. package/benchmarks/deep-object.bench.js +88 -0
  13. package/benchmarks/formatters.bench.js +50 -0
  14. package/benchmarks/internal/custom-levels.js +67 -0
  15. package/benchmarks/internal/just-pino-heavy.bench.js +76 -0
  16. package/benchmarks/internal/just-pino.bench.js +182 -0
  17. package/benchmarks/internal/parent-vs-child.bench.js +75 -0
  18. package/benchmarks/internal/redact.bench.js +86 -0
  19. package/benchmarks/long-string.bench.js +81 -0
  20. package/benchmarks/multi-arg.bench.js +193 -0
  21. package/benchmarks/multistream.js +98 -0
  22. package/benchmarks/object.bench.js +82 -0
  23. package/benchmarks/utils/generate-benchmark-doc.js +36 -0
  24. package/benchmarks/utils/runbench.js +138 -0
  25. package/benchmarks/utils/wrap-log-level.js +55 -0
  26. package/bin.js +6 -0
  27. package/browser.js +547 -0
  28. package/build/sync-version.js +25 -0
  29. package/docs/api.md +1593 -0
  30. package/docs/asynchronous.md +40 -0
  31. package/docs/benchmarks.md +55 -0
  32. package/docs/browser.md +278 -0
  33. package/docs/bundling.md +40 -0
  34. package/docs/child-loggers.md +95 -0
  35. package/docs/diagnostics.md +16 -0
  36. package/docs/ecosystem.md +86 -0
  37. package/docs/help.md +345 -0
  38. package/docs/lts.md +64 -0
  39. package/docs/pretty.md +35 -0
  40. package/docs/redaction.md +135 -0
  41. package/docs/transports.md +1376 -0
  42. package/docs/web.md +309 -0
  43. package/eslint.config.js +28 -0
  44. package/examples/basic.js +43 -0
  45. package/examples/transport.js +68 -0
  46. package/favicon.ico +0 -0
  47. package/file.js +12 -0
  48. package/inc-version.sh +42 -0
  49. package/index.html +55 -0
  50. package/lib/caller.js +30 -0
  51. package/lib/constants.js +28 -0
  52. package/lib/contract.js +8 -0
  53. package/lib/deprecations.js +8 -0
  54. package/lib/levels.js +241 -0
  55. package/lib/meta.js +3 -0
  56. package/lib/multistream.js +203 -0
  57. package/lib/proto.js +256 -0
  58. package/lib/redaction.js +114 -0
  59. package/lib/symbols.js +74 -0
  60. package/lib/time.js +39 -0
  61. package/lib/tools.js +427 -0
  62. package/lib/transport-stream.js +56 -0
  63. package/lib/transport.js +289 -0
  64. package/lib/worker.js +194 -0
  65. package/package.json +119 -0
  66. package/pino.d.ts +908 -0
  67. package/pino.js +240 -0
  68. package/test/basic.test.js +886 -0
  69. package/test/broken-pipe.test.js +59 -0
  70. package/test/browser-child.test.js +132 -0
  71. package/test/browser-disabled.test.js +87 -0
  72. package/test/browser-early-console-freeze.test.js +12 -0
  73. package/test/browser-is-level-enabled.test.js +101 -0
  74. package/test/browser-levels.test.js +241 -0
  75. package/test/browser-serializers.test.js +352 -0
  76. package/test/browser-timestamp.test.js +88 -0
  77. package/test/browser-transmit.test.js +417 -0
  78. package/test/browser.test.js +698 -0
  79. package/test/complex-objects.test.js +36 -0
  80. package/test/crlf.test.js +34 -0
  81. package/test/custom-levels.test.js +267 -0
  82. package/test/diagnostics.test.js +107 -0
  83. package/test/error-key.test.js +37 -0
  84. package/test/error.test.js +403 -0
  85. package/test/escaping.test.js +93 -0
  86. package/test/esm/esm.mjs +14 -0
  87. package/test/esm/index.test.js +21 -0
  88. package/test/esm/named-exports.mjs +29 -0
  89. package/test/exit.test.js +79 -0
  90. package/test/fixtures/broken-pipe/basic.js +9 -0
  91. package/test/fixtures/broken-pipe/destination.js +10 -0
  92. package/test/fixtures/broken-pipe/syncfalse.js +12 -0
  93. package/test/fixtures/console-transport.js +13 -0
  94. package/test/fixtures/crashing-transport.js +13 -0
  95. package/test/fixtures/default-exit.js +8 -0
  96. package/test/fixtures/destination-exit.js +8 -0
  97. package/test/fixtures/eval/index.js +13 -0
  98. package/test/fixtures/eval/node_modules/14-files.js +3 -0
  99. package/test/fixtures/eval/node_modules/2-files.js +3 -0
  100. package/test/fixtures/eval/node_modules/file1.js +5 -0
  101. package/test/fixtures/eval/node_modules/file10.js +5 -0
  102. package/test/fixtures/eval/node_modules/file11.js +5 -0
  103. package/test/fixtures/eval/node_modules/file12.js +5 -0
  104. package/test/fixtures/eval/node_modules/file13.js +5 -0
  105. package/test/fixtures/eval/node_modules/file14.js +11 -0
  106. package/test/fixtures/eval/node_modules/file2.js +5 -0
  107. package/test/fixtures/eval/node_modules/file3.js +5 -0
  108. package/test/fixtures/eval/node_modules/file4.js +5 -0
  109. package/test/fixtures/eval/node_modules/file5.js +5 -0
  110. package/test/fixtures/eval/node_modules/file6.js +5 -0
  111. package/test/fixtures/eval/node_modules/file7.js +5 -0
  112. package/test/fixtures/eval/node_modules/file8.js +5 -0
  113. package/test/fixtures/eval/node_modules/file9.js +5 -0
  114. package/test/fixtures/noop-transport.js +10 -0
  115. package/test/fixtures/pretty/null-prototype.js +8 -0
  116. package/test/fixtures/stdout-hack-protection.js +11 -0
  117. package/test/fixtures/syncfalse-child.js +6 -0
  118. package/test/fixtures/syncfalse-exit.js +9 -0
  119. package/test/fixtures/syncfalse-flush-exit.js +10 -0
  120. package/test/fixtures/syncfalse.js +6 -0
  121. package/test/fixtures/syntax-error-esm.mjs +2 -0
  122. package/test/fixtures/to-file-transport-with-transform.js +20 -0
  123. package/test/fixtures/to-file-transport.js +13 -0
  124. package/test/fixtures/to-file-transport.mjs +8 -0
  125. package/test/fixtures/transport/index.js +12 -0
  126. package/test/fixtures/transport/package.json +5 -0
  127. package/test/fixtures/transport-exit-immediately-with-async-dest.js +16 -0
  128. package/test/fixtures/transport-exit-immediately.js +11 -0
  129. package/test/fixtures/transport-exit-on-ready.js +12 -0
  130. package/test/fixtures/transport-invalid-node-options.js +26 -0
  131. package/test/fixtures/transport-main.js +9 -0
  132. package/test/fixtures/transport-many-lines.js +29 -0
  133. package/test/fixtures/transport-preload-main.mjs +13 -0
  134. package/test/fixtures/transport-preload.mjs +13 -0
  135. package/test/fixtures/transport-string-stdout.js +9 -0
  136. package/test/fixtures/transport-transform.js +21 -0
  137. package/test/fixtures/transport-uses-pino-config.js +33 -0
  138. package/test/fixtures/transport-with-on-exit.js +12 -0
  139. package/test/fixtures/transport-worker-data.js +19 -0
  140. package/test/fixtures/transport-worker-name.js +24 -0
  141. package/test/fixtures/transport-worker.js +15 -0
  142. package/test/fixtures/transport-wrong-export-type.js +3 -0
  143. package/test/fixtures/ts/to-file-transport-native.mts +15 -0
  144. package/test/fixtures/ts/to-file-transport-with-transform.ts +18 -0
  145. package/test/fixtures/ts/to-file-transport.ts +11 -0
  146. package/test/fixtures/ts/transpile.cjs +36 -0
  147. package/test/fixtures/ts/transport-exit-immediately-with-async-dest.ts +15 -0
  148. package/test/fixtures/ts/transport-exit-immediately.ts +10 -0
  149. package/test/fixtures/ts/transport-exit-on-ready.ts +11 -0
  150. package/test/fixtures/ts/transport-main.ts +8 -0
  151. package/test/fixtures/ts/transport-string-stdout.ts +8 -0
  152. package/test/fixtures/ts/transport-worker.ts +14 -0
  153. package/test/formatters.test.js +364 -0
  154. package/test/helper.d.ts +4 -0
  155. package/test/helper.js +155 -0
  156. package/test/hooks.test.js +114 -0
  157. package/test/http.test.js +214 -0
  158. package/test/internals/version.test.js +17 -0
  159. package/test/is-level-enabled.test.js +179 -0
  160. package/test/jest/basic.spec.js +10 -0
  161. package/test/levels.test.js +810 -0
  162. package/test/metadata.test.js +120 -0
  163. package/test/mixin-merge-strategy.test.js +57 -0
  164. package/test/mixin.test.js +241 -0
  165. package/test/multistream.test.js +729 -0
  166. package/test/redact.test.js +893 -0
  167. package/test/serializers.test.js +257 -0
  168. package/test/stdout-protection.test.js +41 -0
  169. package/test/syncfalse.test.js +186 -0
  170. package/test/timestamp-nano.test.js +37 -0
  171. package/test/timestamp.test.js +124 -0
  172. package/test/transport/big.test.js +42 -0
  173. package/test/transport/bundlers-support.test.js +99 -0
  174. package/test/transport/caller.test.js +24 -0
  175. package/test/transport/core.test.js +733 -0
  176. package/test/transport/core.transpiled.test.ts +114 -0
  177. package/test/transport/crash.test.js +36 -0
  178. package/test/transport/module-link.test.js +241 -0
  179. package/test/transport/native-type-stripping.test.mjs +151 -0
  180. package/test/transport/node-options.test.js +116 -0
  181. package/test/transport/pipeline.test.js +137 -0
  182. package/test/transport/preload.test.js +54 -0
  183. package/test/transport/repl.test.js +15 -0
  184. package/test/transport/sync-false.test.js +67 -0
  185. package/test/transport/sync-true.test.js +57 -0
  186. package/test/transport/targets.test.js +48 -0
  187. package/test/transport/uses-pino-config.test.js +166 -0
  188. package/test/transport-stream.test.js +40 -0
  189. package/test/types/pino-import.test-d.cts +30 -0
  190. package/test/types/pino-multistream.test-d.ts +28 -0
  191. package/test/types/pino-top-export.test-d.ts +34 -0
  192. package/test/types/pino-transport.test-d.ts +156 -0
  193. package/test/types/pino-type-only.test-d.ts +75 -0
  194. package/test/types/pino.test-d.ts +683 -0
  195. package/test/types/pino.ts +91 -0
  196. package/tsconfig.json +14 -0
@@ -0,0 +1,886 @@
1
+ 'use strict'
2
+
3
+ const os = require('node:os')
4
+ const { readFileSync } = require('node:fs')
5
+ const test = require('node:test')
6
+ const assert = require('node:assert')
7
+
8
+ const { sink, check, match, once, watchFileCreated, file } = require('./helper')
9
+ const pino = require('../')
10
+ const { version } = require('../package.json')
11
+ const { pid } = process
12
+ const hostname = os.hostname()
13
+
14
+ test('pino version is exposed on export', () => {
15
+ assert.equal(pino.version, version)
16
+ })
17
+
18
+ test('pino version is exposed on instance', () => {
19
+ const instance = pino()
20
+ assert.equal(instance.version, version)
21
+ })
22
+
23
+ test('child instance exposes pino version', () => {
24
+ const child = pino().child({ foo: 'bar' })
25
+ assert.equal(child.version, version)
26
+ })
27
+
28
+ test('bindings are exposed on every instance', () => {
29
+ const instance = pino()
30
+ assert.deepEqual(instance.bindings(), {})
31
+ })
32
+
33
+ test('bindings contain the name and the child bindings', () => {
34
+ const instance = pino({ name: 'basicTest', level: 'info' }).child({ foo: 'bar' }).child({ a: 2 })
35
+ assert.deepEqual(instance.bindings(), { name: 'basicTest', foo: 'bar', a: 2 })
36
+ })
37
+
38
+ test('set bindings on instance', () => {
39
+ const instance = pino({ name: 'basicTest', level: 'info' })
40
+ instance.setBindings({ foo: 'bar' })
41
+ assert.deepEqual(instance.bindings(), { name: 'basicTest', foo: 'bar' })
42
+ })
43
+
44
+ test('newly set bindings overwrite old bindings', () => {
45
+ const instance = pino({ name: 'basicTest', level: 'info', base: { foo: 'bar' } })
46
+ instance.setBindings({ foo: 'baz' })
47
+ assert.deepEqual(instance.bindings(), { name: 'basicTest', foo: 'baz' })
48
+ })
49
+
50
+ test('set bindings on child instance', () => {
51
+ const child = pino({ name: 'basicTest', level: 'info' }).child({})
52
+ child.setBindings({ foo: 'bar' })
53
+ assert.deepEqual(child.bindings(), { name: 'basicTest', foo: 'bar' })
54
+ })
55
+
56
+ test('child should have bindings set by parent', () => {
57
+ const instance = pino({ name: 'basicTest', level: 'info' })
58
+ instance.setBindings({ foo: 'bar' })
59
+ const child = instance.child({})
60
+ assert.deepEqual(child.bindings(), { name: 'basicTest', foo: 'bar' })
61
+ })
62
+
63
+ test('child should not share bindings of parent set after child creation', () => {
64
+ const instance = pino({ name: 'basicTest', level: 'info' })
65
+ const child = instance.child({})
66
+ instance.setBindings({ foo: 'bar' })
67
+ assert.deepEqual(instance.bindings(), { name: 'basicTest', foo: 'bar' })
68
+ assert.deepEqual(child.bindings(), { name: 'basicTest' })
69
+ })
70
+
71
+ function levelTest (name, level) {
72
+ test(`${name} logs as ${level}`, async () => {
73
+ const stream = sink()
74
+ const instance = pino(stream)
75
+ instance.level = name
76
+ instance[name]('hello world')
77
+ check(assert.equal, await once(stream, 'data'), level, 'hello world')
78
+ })
79
+
80
+ test(`passing objects at level ${name}`, async () => {
81
+ const stream = sink()
82
+ const instance = pino(stream)
83
+ instance.level = name
84
+ const obj = { hello: 'world' }
85
+ instance[name](obj)
86
+
87
+ const result = await once(stream, 'data')
88
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
89
+ assert.equal(result.pid, pid)
90
+ assert.equal(result.hostname, hostname)
91
+ assert.equal(result.level, level)
92
+ assert.equal(result.hello, 'world')
93
+ assert.deepEqual(Object.keys(obj), ['hello'])
94
+ })
95
+
96
+ test(`passing an object and a string at level ${name}`, async () => {
97
+ const stream = sink()
98
+ const instance = pino(stream)
99
+ instance.level = name
100
+ const obj = { hello: 'world' }
101
+ instance[name](obj, 'a string')
102
+ const result = await once(stream, 'data')
103
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
104
+ delete result.time
105
+ assert.deepEqual(result, {
106
+ pid,
107
+ hostname,
108
+ level,
109
+ msg: 'a string',
110
+ hello: 'world'
111
+ })
112
+ assert.deepEqual(Object.keys(obj), ['hello'])
113
+ })
114
+
115
+ test(`passing a undefined and a string at level ${name}`, async () => {
116
+ const stream = sink()
117
+ const instance = pino(stream)
118
+ instance.level = name
119
+ instance[name](undefined, 'a string')
120
+ const result = await once(stream, 'data')
121
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
122
+ delete result.time
123
+ assert.deepEqual(result, {
124
+ pid,
125
+ hostname,
126
+ level,
127
+ msg: 'a string'
128
+ })
129
+ })
130
+
131
+ test(`overriding object key by string at level ${name}`, async () => {
132
+ const stream = sink()
133
+ const instance = pino(stream)
134
+ instance.level = name
135
+ instance[name]({ hello: 'world', msg: 'object' }, 'string')
136
+ const result = await once(stream, 'data')
137
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
138
+ delete result.time
139
+ assert.deepEqual(result, {
140
+ pid,
141
+ hostname,
142
+ level,
143
+ msg: 'string',
144
+ hello: 'world'
145
+ })
146
+ })
147
+
148
+ test(`formatting logs as ${name}`, async () => {
149
+ const stream = sink()
150
+ const instance = pino(stream)
151
+ instance.level = name
152
+ instance[name]('hello %d', 42)
153
+ const result = await once(stream, 'data')
154
+ check(assert.equal, result, level, 'hello 42')
155
+ })
156
+
157
+ test(`formatting a symbol at level ${name}`, async () => {
158
+ const stream = sink()
159
+ const instance = pino(stream)
160
+ instance.level = name
161
+
162
+ const sym = Symbol('foo')
163
+ instance[name]('hello %s', sym)
164
+
165
+ const result = await once(stream, 'data')
166
+
167
+ check(assert.equal, result, level, 'hello Symbol(foo)')
168
+ })
169
+
170
+ test(`passing error with a serializer at level ${name}`, async () => {
171
+ const stream = sink()
172
+ const err = new Error('myerror')
173
+ const instance = pino({
174
+ serializers: {
175
+ err: pino.stdSerializers.err
176
+ }
177
+ }, stream)
178
+ instance.level = name
179
+ instance[name]({ err })
180
+ const result = await once(stream, 'data')
181
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
182
+ delete result.time
183
+ assert.deepEqual(result, {
184
+ pid,
185
+ hostname,
186
+ level,
187
+ err: {
188
+ type: 'Error',
189
+ message: err.message,
190
+ stack: err.stack
191
+ },
192
+ msg: err.message
193
+ })
194
+ })
195
+
196
+ test(`child logger for level ${name}`, async () => {
197
+ const stream = sink()
198
+ const instance = pino(stream)
199
+ instance.level = name
200
+ const child = instance.child({ hello: 'world' })
201
+ child[name]('hello world')
202
+ const result = await once(stream, 'data')
203
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
204
+ delete result.time
205
+ assert.deepEqual(result, {
206
+ pid,
207
+ hostname,
208
+ level,
209
+ msg: 'hello world',
210
+ hello: 'world'
211
+ })
212
+ })
213
+ }
214
+
215
+ levelTest('fatal', 60)
216
+ levelTest('error', 50)
217
+ levelTest('warn', 40)
218
+ levelTest('info', 30)
219
+ levelTest('debug', 20)
220
+ levelTest('trace', 10)
221
+
222
+ test('serializers can return undefined to strip field', async () => {
223
+ const stream = sink()
224
+ const instance = pino({
225
+ serializers: {
226
+ test () { return undefined }
227
+ }
228
+ }, stream)
229
+
230
+ instance.info({ test: 'sensitive info' })
231
+ const result = await once(stream, 'data')
232
+ assert.equal('test' in result, false)
233
+ })
234
+
235
+ test('streams receive a message event with PINO_CONFIG', (t, end) => {
236
+ const stream = sink()
237
+ stream.once('message', (message) => {
238
+ match(message, {
239
+ code: 'PINO_CONFIG',
240
+ config: {
241
+ errorKey: 'err',
242
+ levels: {
243
+ labels: {
244
+ 10: 'trace',
245
+ 20: 'debug',
246
+ 30: 'info',
247
+ 40: 'warn',
248
+ 50: 'error',
249
+ 60: 'fatal'
250
+ },
251
+ values: {
252
+ debug: 20,
253
+ error: 50,
254
+ fatal: 60,
255
+ info: 30,
256
+ trace: 10,
257
+ warn: 40
258
+ }
259
+ },
260
+ messageKey: 'msg'
261
+ }
262
+ })
263
+ end()
264
+ })
265
+ pino(stream)
266
+ })
267
+
268
+ test('does not explode with a circular ref', () => {
269
+ const stream = sink()
270
+ const instance = pino(stream)
271
+ const b = {}
272
+ const a = {
273
+ hello: b
274
+ }
275
+ b.a = a // circular ref
276
+ assert.doesNotThrow(() => instance.info(a))
277
+ })
278
+
279
+ test('set the name', async () => {
280
+ const stream = sink()
281
+ const instance = pino({
282
+ name: 'hello'
283
+ }, stream)
284
+ instance.fatal('this is fatal')
285
+ const result = await once(stream, 'data')
286
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
287
+ delete result.time
288
+ assert.deepEqual(result, {
289
+ pid,
290
+ hostname,
291
+ level: 60,
292
+ name: 'hello',
293
+ msg: 'this is fatal'
294
+ })
295
+ })
296
+
297
+ test('set the messageKey', async () => {
298
+ const stream = sink()
299
+ const message = 'hello world'
300
+ const messageKey = 'fooMessage'
301
+ const instance = pino({
302
+ messageKey
303
+ }, stream)
304
+ instance.info(message)
305
+ const result = await once(stream, 'data')
306
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
307
+ delete result.time
308
+ assert.deepEqual(result, {
309
+ pid,
310
+ hostname,
311
+ level: 30,
312
+ fooMessage: message
313
+ })
314
+ })
315
+
316
+ test('set the nestedKey', async () => {
317
+ const stream = sink()
318
+ const object = { hello: 'world' }
319
+ const nestedKey = 'stuff'
320
+ const instance = pino({
321
+ nestedKey
322
+ }, stream)
323
+ instance.info(object)
324
+ const result = await once(stream, 'data')
325
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
326
+ delete result.time
327
+ assert.deepEqual(result, {
328
+ pid,
329
+ hostname,
330
+ level: 30,
331
+ stuff: object
332
+ })
333
+ })
334
+
335
+ test('set undefined properties', async () => {
336
+ const stream = sink()
337
+ const instance = pino(stream)
338
+ instance.info({ hello: 'world', property: undefined })
339
+ const result = await once(stream, 'data')
340
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
341
+ delete result.time
342
+ assert.deepEqual(result, {
343
+ pid,
344
+ hostname,
345
+ level: 30,
346
+ hello: 'world'
347
+ })
348
+ })
349
+
350
+ test('prototype properties are not logged', async () => {
351
+ const stream = sink()
352
+ const instance = pino(stream)
353
+ instance.info(Object.create({ hello: 'world' }))
354
+ const { hello } = await once(stream, 'data')
355
+ assert.equal(hello, undefined)
356
+ })
357
+
358
+ test('set the base', async () => {
359
+ const stream = sink()
360
+ const instance = pino({
361
+ base: {
362
+ a: 'b'
363
+ }
364
+ }, stream)
365
+
366
+ instance.fatal('this is fatal')
367
+ const result = await once(stream, 'data')
368
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
369
+ delete result.time
370
+ assert.deepEqual(result, {
371
+ a: 'b',
372
+ level: 60,
373
+ msg: 'this is fatal'
374
+ })
375
+ })
376
+
377
+ test('set the base to null', async () => {
378
+ const stream = sink()
379
+ const instance = pino({
380
+ base: null
381
+ }, stream)
382
+ instance.fatal('this is fatal')
383
+ const result = await once(stream, 'data')
384
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
385
+ delete result.time
386
+ assert.deepEqual(result, {
387
+ level: 60,
388
+ msg: 'this is fatal'
389
+ })
390
+ })
391
+
392
+ test('set the base to null and use a formatter', async () => {
393
+ const stream = sink()
394
+ const instance = pino({
395
+ base: null,
396
+ formatters: {
397
+ log (input) {
398
+ return Object.assign({}, input, { additionalMessage: 'using pino' })
399
+ }
400
+ }
401
+ }, stream)
402
+ instance.fatal('this is fatal too')
403
+ const result = await once(stream, 'data')
404
+ assert.equal(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
405
+ delete result.time
406
+ assert.deepEqual(result, {
407
+ level: 60,
408
+ msg: 'this is fatal too',
409
+ additionalMessage: 'using pino'
410
+ })
411
+ })
412
+
413
+ test('throw if creating child without bindings', () => {
414
+ const stream = sink()
415
+ const instance = pino(stream)
416
+ try {
417
+ instance.child()
418
+ assert.fail('it should throw')
419
+ } catch (err) {
420
+ assert.equal(err.message, 'missing bindings for child Pino')
421
+ }
422
+ })
423
+
424
+ test('correctly escapes msg strings with stray double quote at end', async () => {
425
+ const stream = sink()
426
+ const instance = pino({
427
+ name: 'hello'
428
+ }, stream)
429
+
430
+ instance.fatal('this contains "')
431
+ const result = await once(stream, 'data')
432
+ delete result.time
433
+ assert.deepEqual(result, {
434
+ pid,
435
+ hostname,
436
+ level: 60,
437
+ name: 'hello',
438
+ msg: 'this contains "'
439
+ })
440
+ })
441
+
442
+ test('correctly escape msg strings with unclosed double quote', async () => {
443
+ const stream = sink()
444
+ const instance = pino({
445
+ name: 'hello'
446
+ }, stream)
447
+ instance.fatal('" this contains')
448
+ const result = await once(stream, 'data')
449
+ delete result.time
450
+ assert.deepEqual(result, {
451
+ pid,
452
+ hostname,
453
+ level: 60,
454
+ name: 'hello',
455
+ msg: '" this contains'
456
+ })
457
+ })
458
+
459
+ test('correctly escape quote in a key', async () => {
460
+ const stream = sink()
461
+ const instance = pino(stream)
462
+ const obj = { 'some"obj': 'world' }
463
+ instance.info(obj, 'a string')
464
+ const result = await once(stream, 'data')
465
+ delete result.time
466
+ assert.deepEqual(result, {
467
+ level: 30,
468
+ pid,
469
+ hostname,
470
+ msg: 'a string',
471
+ 'some"obj': 'world'
472
+ })
473
+ assert.deepEqual(Object.keys(obj), ['some"obj'])
474
+ })
475
+
476
+ // https://github.com/pinojs/pino/issues/139
477
+ test('object and format string', async () => {
478
+ const stream = sink()
479
+ const instance = pino(stream)
480
+ instance.info({}, 'foo %s', 'bar')
481
+
482
+ const result = await once(stream, 'data')
483
+ delete result.time
484
+ assert.deepEqual(result, {
485
+ pid,
486
+ hostname,
487
+ level: 30,
488
+ msg: 'foo bar'
489
+ })
490
+ })
491
+
492
+ test('object and format string property', async () => {
493
+ const stream = sink()
494
+ const instance = pino(stream)
495
+ instance.info({ answer: 42 }, 'foo %s', 'bar')
496
+ const result = await once(stream, 'data')
497
+ delete result.time
498
+ assert.deepEqual(result, {
499
+ pid,
500
+ hostname,
501
+ level: 30,
502
+ msg: 'foo bar',
503
+ answer: 42
504
+ })
505
+ })
506
+
507
+ test('correctly strip undefined when returned from toJSON', async () => {
508
+ const stream = sink()
509
+ const instance = pino({
510
+ test: 'this'
511
+ }, stream)
512
+ instance.fatal({ test: { toJSON () { return undefined } } })
513
+ const result = await once(stream, 'data')
514
+ assert.equal('test' in result, false)
515
+ })
516
+
517
+ test('correctly supports stderr', (t, end) => {
518
+ // stderr inherits from Stream, rather than Writable
519
+ const dest = {
520
+ writable: true,
521
+ write (result) {
522
+ result = JSON.parse(result)
523
+ delete result.time
524
+ assert.deepEqual(result, {
525
+ pid,
526
+ hostname,
527
+ level: 60,
528
+ msg: 'a message'
529
+ })
530
+ end()
531
+ }
532
+ }
533
+ const instance = pino(dest)
534
+ instance.fatal('a message')
535
+ })
536
+
537
+ test('normalize number to string', async () => {
538
+ const stream = sink()
539
+ const instance = pino(stream)
540
+ instance.info(1)
541
+ const result = await once(stream, 'data')
542
+ delete result.time
543
+ assert.deepEqual(result, {
544
+ pid,
545
+ hostname,
546
+ level: 30,
547
+ msg: '1'
548
+ })
549
+ })
550
+
551
+ test('normalize number to string with an object', async () => {
552
+ const stream = sink()
553
+ const instance = pino(stream)
554
+ instance.info({ answer: 42 }, 1)
555
+ const result = await once(stream, 'data')
556
+ delete result.time
557
+ assert.deepEqual(result, {
558
+ pid,
559
+ hostname,
560
+ level: 30,
561
+ msg: '1',
562
+ answer: 42
563
+ })
564
+ })
565
+
566
+ test('handles objects with null prototype', async () => {
567
+ const stream = sink()
568
+ const instance = pino(stream)
569
+ const o = Object.create(null)
570
+ o.test = 'test'
571
+ instance.info(o)
572
+ const result = await once(stream, 'data')
573
+ delete result.time
574
+ assert.deepEqual(result, {
575
+ pid,
576
+ hostname,
577
+ level: 30,
578
+ test: 'test'
579
+ })
580
+ })
581
+
582
+ test('pino.destination', async () => {
583
+ const tmp = file()
584
+ const instance = pino(pino.destination(tmp))
585
+ instance.info('hello')
586
+ await watchFileCreated(tmp)
587
+ const result = JSON.parse(readFileSync(tmp).toString())
588
+ delete result.time
589
+ assert.deepEqual(result, {
590
+ pid,
591
+ hostname,
592
+ level: 30,
593
+ msg: 'hello'
594
+ })
595
+ })
596
+
597
+ test('auto pino.destination with a string', async () => {
598
+ const tmp = file()
599
+ const instance = pino(tmp)
600
+ instance.info('hello')
601
+ await watchFileCreated(tmp)
602
+ const result = JSON.parse(readFileSync(tmp).toString())
603
+ delete result.time
604
+ assert.deepEqual(result, {
605
+ pid,
606
+ hostname,
607
+ level: 30,
608
+ msg: 'hello'
609
+ })
610
+ })
611
+
612
+ test('auto pino.destination with a string as second argument', async () => {
613
+ const tmp = file()
614
+ const instance = pino(null, tmp)
615
+ instance.info('hello')
616
+ await watchFileCreated(tmp)
617
+ const result = JSON.parse(readFileSync(tmp).toString())
618
+ delete result.time
619
+ assert.deepEqual(result, {
620
+ pid,
621
+ hostname,
622
+ level: 30,
623
+ msg: 'hello'
624
+ })
625
+ })
626
+
627
+ test('does not override opts with a string as second argument', async () => {
628
+ const tmp = file()
629
+ const instance = pino({
630
+ timestamp: () => ',"time":"none"'
631
+ }, tmp)
632
+ instance.info('hello')
633
+ await watchFileCreated(tmp)
634
+ const result = JSON.parse(readFileSync(tmp).toString())
635
+ assert.deepEqual(result, {
636
+ pid,
637
+ hostname,
638
+ level: 30,
639
+ time: 'none',
640
+ msg: 'hello'
641
+ })
642
+ })
643
+
644
+ // https://github.com/pinojs/pino/issues/222
645
+ test('children with same names render in correct order', async () => {
646
+ const stream = sink()
647
+ const root = pino(stream)
648
+ root.child({ a: 1 }).child({ a: 2 }).info({ a: 3 })
649
+ const { a } = await once(stream, 'data')
650
+ assert.equal(a, 3, 'last logged object takes precedence')
651
+ })
652
+
653
+ test('use `safe-stable-stringify` to avoid circular dependencies', async () => {
654
+ const stream = sink()
655
+ const root = pino(stream)
656
+ // circular depth
657
+ const obj = {}
658
+ obj.a = obj
659
+ root.info(obj)
660
+ const { a } = await once(stream, 'data')
661
+ assert.deepEqual(a, { a: '[Circular]' })
662
+ })
663
+
664
+ test('correctly log non circular objects', async () => {
665
+ const stream = sink()
666
+ const root = pino(stream)
667
+ const obj = {}
668
+ let parent = obj
669
+ for (let i = 0; i < 10; i++) {
670
+ parent.node = {}
671
+ parent = parent.node
672
+ }
673
+ root.info(obj)
674
+ const { node } = await once(stream, 'data')
675
+ assert.deepEqual(node, { node: { node: { node: { node: { node: { node: { node: { node: { node: {} } } } } } } } } })
676
+ })
677
+
678
+ test('safe-stable-stringify must be used when interpolating', async () => {
679
+ const stream = sink()
680
+ const instance = pino(stream)
681
+
682
+ const o = { a: { b: {} } }
683
+ o.a.b.c = o.a.b
684
+ instance.info('test %j', o)
685
+
686
+ const { msg } = await once(stream, 'data')
687
+ assert.equal(msg, 'test {"a":{"b":{"c":"[Circular]"}}}')
688
+ })
689
+
690
+ test('throws when setting useOnlyCustomLevels without customLevels', () => {
691
+ assert.throws(
692
+ () => {
693
+ pino({
694
+ useOnlyCustomLevels: true
695
+ })
696
+ },
697
+ /customLevels is required if useOnlyCustomLevels is set true/
698
+ )
699
+ })
700
+
701
+ test('correctly log Infinity', async () => {
702
+ const stream = sink()
703
+ const instance = pino(stream)
704
+
705
+ const o = { num: Infinity }
706
+ instance.info(o)
707
+
708
+ const { num } = await once(stream, 'data')
709
+ assert.equal(num, null)
710
+ })
711
+
712
+ test('correctly log -Infinity', async () => {
713
+ const stream = sink()
714
+ const instance = pino(stream)
715
+
716
+ const o = { num: -Infinity }
717
+ instance.info(o)
718
+
719
+ const { num } = await once(stream, 'data')
720
+ assert.equal(num, null)
721
+ })
722
+
723
+ test('correctly log NaN', async () => {
724
+ const stream = sink()
725
+ const instance = pino(stream)
726
+
727
+ const o = { num: NaN }
728
+ instance.info(o)
729
+
730
+ const { num } = await once(stream, 'data')
731
+ assert.equal(num, null)
732
+ })
733
+
734
+ test('offers a .default() method to please typescript', async () => {
735
+ assert.equal(pino.default, pino)
736
+
737
+ const stream = sink()
738
+ const instance = pino.default(stream)
739
+ instance.info('hello world')
740
+ check(assert.equal, await once(stream, 'data'), 30, 'hello world')
741
+ })
742
+
743
+ test('correctly skip function', async () => {
744
+ const stream = sink()
745
+ const instance = pino(stream)
746
+
747
+ const o = { num: NaN }
748
+ instance.info(o, () => {})
749
+
750
+ const { msg } = await once(stream, 'data')
751
+ assert.equal(msg, undefined)
752
+ })
753
+
754
+ test('correctly skip Infinity', async () => {
755
+ const stream = sink()
756
+ const instance = pino(stream)
757
+
758
+ const o = { num: NaN }
759
+ instance.info(o, Infinity)
760
+
761
+ const { msg } = await once(stream, 'data')
762
+ assert.equal(msg, null)
763
+ })
764
+
765
+ test('correctly log number', async () => {
766
+ const stream = sink()
767
+ const instance = pino(stream)
768
+
769
+ const o = { num: NaN }
770
+ instance.info(o, 42)
771
+
772
+ const { msg } = await once(stream, 'data')
773
+ assert.equal(msg, 42)
774
+ })
775
+
776
+ test('nestedKey should not be used for non-objects', async () => {
777
+ const stream = sink()
778
+ const message = 'hello'
779
+ const nestedKey = 'stuff'
780
+ const instance = pino({
781
+ nestedKey
782
+ }, stream)
783
+ instance.info(message)
784
+ const result = await once(stream, 'data')
785
+ delete result.time
786
+ assert.deepStrictEqual(result, {
787
+ pid,
788
+ hostname,
789
+ level: 30,
790
+ msg: message
791
+ })
792
+ })
793
+
794
+ test('throws if prettyPrint is passed in as an option', async () => {
795
+ assert.throws(
796
+ () => {
797
+ pino({
798
+ prettyPrint: true
799
+ })
800
+ },
801
+ Error('prettyPrint option is no longer supported, see the pino-pretty package (https://github.com/pinojs/pino-pretty)')
802
+ )
803
+ })
804
+
805
+ test('Should invoke `onChild` with the newly created child', () => {
806
+ let innerChild
807
+ const child = pino({
808
+ onChild: (instance) => {
809
+ innerChild = instance
810
+ }
811
+ }).child({ foo: 'bar' })
812
+ assert.equal(child, innerChild)
813
+ })
814
+
815
+ test('logger message should have the prefix message that defined in the logger creation', async () => {
816
+ const stream = sink()
817
+ const logger = pino({
818
+ msgPrefix: 'My name is Bond '
819
+ }, stream)
820
+ assert.equal(logger.msgPrefix, 'My name is Bond ')
821
+ logger.info('James Bond')
822
+ const { msg } = await once(stream, 'data')
823
+ assert.equal(msg, 'My name is Bond James Bond')
824
+ })
825
+
826
+ test('child message should have the prefix message that defined in the child creation', async () => {
827
+ const stream = sink()
828
+ const instance = pino(stream)
829
+ const child = instance.child({}, { msgPrefix: 'My name is Bond ' })
830
+ child.info('James Bond')
831
+ const { msg } = await once(stream, 'data')
832
+ assert.equal(msg, 'My name is Bond James Bond')
833
+ })
834
+
835
+ test('child message should have the prefix message that defined in the child creation when logging with log meta', async () => {
836
+ const stream = sink()
837
+ const instance = pino(stream)
838
+ const child = instance.child({}, { msgPrefix: 'My name is Bond ' })
839
+ child.info({ hello: 'world' }, 'James Bond')
840
+ const { msg, hello } = await once(stream, 'data')
841
+ assert.equal(hello, 'world')
842
+ assert.equal(msg, 'My name is Bond James Bond')
843
+ })
844
+
845
+ test('logged message should not have the prefix when not providing any message', async () => {
846
+ const stream = sink()
847
+ const instance = pino(stream)
848
+ const child = instance.child({}, { msgPrefix: 'This should not be shown ' })
849
+ child.info({ hello: 'world' })
850
+ const { msg, hello } = await once(stream, 'data')
851
+ assert.equal(hello, 'world')
852
+ assert.equal(msg, undefined)
853
+ })
854
+
855
+ test('child message should append parent prefix to current prefix that defined in the child creation', async () => {
856
+ const stream = sink()
857
+ const instance = pino({
858
+ msgPrefix: 'My name is Bond '
859
+ }, stream)
860
+ const child = instance.child({}, { msgPrefix: 'James ' })
861
+ child.info('Bond')
862
+ assert.equal(child.msgPrefix, 'My name is Bond James ')
863
+ const { msg } = await once(stream, 'data')
864
+ assert.equal(msg, 'My name is Bond James Bond')
865
+ })
866
+
867
+ test('child message should inherent parent prefix', async () => {
868
+ const stream = sink()
869
+ const instance = pino({
870
+ msgPrefix: 'My name is Bond '
871
+ }, stream)
872
+ const child = instance.child({})
873
+ child.info('James Bond')
874
+ const { msg } = await once(stream, 'data')
875
+ assert.equal(msg, 'My name is Bond James Bond')
876
+ })
877
+
878
+ test('grandchild message should inherent parent prefix', async () => {
879
+ const stream = sink()
880
+ const instance = pino(stream)
881
+ const child = instance.child({}, { msgPrefix: 'My name is Bond ' })
882
+ const grandchild = child.child({})
883
+ grandchild.info('James Bond')
884
+ const { msg } = await once(stream, 'data')
885
+ assert.equal(msg, 'My name is Bond James Bond')
886
+ })