Test Report

0
1
49
121

ID Title Duration (ms)
1 Purdy should print an object without a constructor 24
2 Purdy should indent array correctly 6
3 Purdy allows for removal of array index 1
4 Purdy honors indent level 1
5 Purdy prints arguments function 2
6 Purdy should print plain 1
7 Purdy should handle circular references 3
8 Purdy should print a string 1
9 Purdy should print a date 2
10 Purdy should print a number 1
11 Purdy should print null 1
12 Purdy should print undefined 1
13 Purdy should print a regular expression 1
14 Purdy should print a false boolean 1
15 Purdy should print a true boolean 1
16 Purdy should print an empty array without extra indentation 0
17 Purdy should print an empty object without extra indentation 0
18 Purdy should print a more complex object 4
19 Purdy should not print circular after second use 2
20 Purdy shows circular reference with path 1
21 Purdy will keep a path for an object in Hoek format 3
22 Purdy indents object the way it should 1
23 Purdy aligns object the way it should 1
24 Purdy prints directly to console 5
25 Purdy Promise should print promise with unknown state such as a non-native lib. like bluebird 3
26 Purdy Promise reject a fake promise 1
27 Purdy Promise should pretty print a pending promise 15
28 Purdy Promise should pretty print a fulfilled promise 2
29 Purdy Promise should pretty print a rejected promise 3
30 Purdy Promise should pretty print a rejected promise with properties 1
31 Purdy errors should display an error 1
32 Purdy errors should display an error with no error message and property correctly 1
33 Purdy errors should display an error with properties 1
34 Purdy errors should display an error with detail 1
35 Purdy functions should print constructor name 1
36 Purdy functions should print not print common constructor 1
37 Purdy functions should print a function 1
38 Purdy functions should print an anonymous function 1
39 Purdy functions should print properties for functions 2
40 Purdy functions should print properties for functions with name 1
41 Purdy symbols prints symbols 1
42 Purdy symbols prints only symbols 1
43 Purdy symbols 100% coverage should have coverage for having getOwnPropertySymbols 1
44 Purdy symbols 100% coverage should have coverage for not having getOwnPropertySymbols 0
45 Purdy depth should handle depth printing 1
46 Purdy depth should handle depth printing for array 0
47 Purdy depth should print using zero depth 5
48 Purdy depth should handle depth printing for mixed 2
49 Purdy depth should handle depth printing using null depth 1

Code Coverage Report

100%
266
266
0

lib/index.js

100%
266
266
0
Line Lint Hits Source
1 'use strict';
2
3
4 // Load modules
5
6 1 const Chalk = require('chalk');
7 1 const Hoek = require('hoek');
8 1 const Joi = require('joi');
9 1 const Util = require('util');
10
11
12 // declare internals
13
14 1 const internals = {
15 colors: {
16 BoolFalse: 'red.bold',
17 BoolTrue: 'green.bold',
18 Circular: 'grey.bold',
19 Date: 'green',
20 Key: 'white.bold',
21 Null: 'red.bold',
22 Number: 'blue.bold',
23 RegExp: 'magenta',
24 String: 'yellow',
25 Symbol: 'magenta.bold',
26 Undefined: 'red.inverse',
27 depth: 'grey',
28 error: 'red',
29 function: 'cyan',
30 prefix: 'green',
31 fulfilledPromise: 'green',
32 pendingPromise: 'cyan',
33 unknownPromise: 'cyan',
34 rejectedPromise: 'red',
35 path: 'blue'
36 },
37 defaults: {
38 depth: Joi.number().min(0).allow(null).default(2),
39 plain: Joi.boolean().default(false),
40 path: Joi.boolean().default(false),
41 indent: Joi.number().default(4),
42 align: Joi.string().valid(['left', 'right']).default('left'),
43 arrayIndex: Joi.boolean().default(true),
44 pathPrefix: Joi.string().default('// ')
45 }
46 };
47
48 1 internals.purdy = function (object, options) {
49
50 51 this.indentLevel = 0;
51 51 this.seen = [];
52 51 this.path = [];
53 51 this.object = object;
54
55 51 this.settings = Joi.attempt(options || {}, internals.defaults);
56 };
57
58
59 1 module.exports = function (object, options) {
60
61 1 const Purdy = new internals.purdy(object, options);
62 1 return console.log(Purdy.stringify());
63 };
64
65 1 module.exports.stringify = function (object, options) {
66
67 50 const Purdy = new internals.purdy(object, options);
68 50 return Purdy.stringify();
69 };
70
71
72 1 internals.purdy.prototype.stringify = function (object, options) {
73
74 51 return this.travel(this.object, '', 0);
75 };
76
77
78 1 internals.isPromise = function (obj) {
79
80 42 if (!(typeof (obj.then) === 'function') || !(typeof (obj.catch) === 'function')) {
81 40 return false;
82 }
83
84 2 if (obj.constructor.name !== 'Promise') {
85 1 return false;
86 }
87
88 1 return !Util.inspect(obj, { depth: 0, customInspect: false }).indexOf('Promise');
89 };
90
91
92 1 internals.purdy.prototype.travel = function (object, path, depth) {
93
94 160 let type = toString.call(object).split(' ')[1].slice(0, -1);
95
96 160 if (type === 'Object' && internals.isPromise(object)) {
97 1 type = 'Promise';
98 }
99
100 160 let format = '';
101
102 160 if (this[type]) {
103 98 format = this[type](object, path, depth);
104 }
105 else {
106 62 format = String(object);
107 }
108
109 160 return this.colorize(format, type);
110 };
111
112
113 1 internals.purdy.prototype.colorize = function (string, type) {
114
115 284 if (this.settings.plain) {
116 133 return string;
117 }
118
119 151 const colors = internals.colors[type];
120 151 if (!colors) {
121 46 return string;
122 }
123
124 105 const colorArr = colors.split('.');
125
126 105 for (let i = 0; i < colorArr.length; ++i) {
127 175 const color = colorArr[i];
128 175 string = Chalk[color](string);
129 }
130
131 105 return string;
132 };
133
134
135 1 internals.lengthCompare = function (a, b) {
136
137 82 return a.length - b.length;
138 };
139
140
141 1 internals.promiseType = function (promise) {
142
143 5 const opts = { depth: 0, customInspect: false };
144
145 5 const isRejected = Util.inspect(promise, opts).indexOf('rejected') !== -1;
146 5 if (isRejected) {
147 2 return 'rejected';
148 }
149 3 const isPending = Util.inspect(promise, opts).indexOf('pending') !== -1;
150 3 if (isPending) {
151 1 return 'pending';
152 }
153
154 2 const isFulfilled = !Util.inspect(promise, opts).indexOf('Promise { undefined');
155 2 if (isFulfilled) {
156 1 return 'fulfilled';
157 }
158
159 1 return 'unknown';
160 };
161
162
163 1 internals.purdy.prototype.Promise = function (promise) {
164
165 5 const promiseType = internals.promiseType(promise);
166 5 const color = promiseType + 'Promise';
167
168 5 if (Object.keys(promise).length === 0) {
169 3 return this.colorize('[Promise: ' + promiseType + ']', color);
170 }
171
172 2 const props = this.Object(promise, '', null);
173 2 return props.replace(/^{/, '{ ' + this.colorize('[Promise: ' + promiseType + ']', color) );
174 };
175
176
177 1 internals.purdy.prototype.tidyPath = function (path) {
178
179 4 return this.colorize(path.slice(1, path.size), 'path');
180 };
181
182
183 1 internals.purdy.prototype.Object = internals.purdy.prototype.process = internals.purdy.prototype.global = function (object, path, depth) {
184
185 48 let keys = Object.keys(object);
186
187 48 if (Object.getOwnPropertySymbols) {
188 47 keys = keys.concat(Object.getOwnPropertySymbols(object));
189 }
190
191 48 let prefix = '';
192 48 if (object.constructor) {
193 47 prefix = ['Object', 'Function', 'Error', 'Promise', ''].indexOf(object.constructor.name) !== -1 ? '' : this.colorize(object.constructor.name, 'prefix') + ' ';
194 }
195
196 48 if (keys.length === 0) {
197 1 return prefix + '{}';
198 }
199
200 47 ++depth;
201 47 const index = this.seen.indexOf(object);
202 47 if (index !== -1) {
203 3 return this.showCircular(index);
204 }
205 44 this.seen.push(object);
206 44 this.path.push(path);
207
208 44 const keyLengths = Hoek.clone(keys);
209 44 this.indentLevel = this.indentLevel + 1;
210 44 let out = prefix + '{\n';
211
212 44 for (let i = 0; i < keys.length; ++i) {
213 66 const key = keys[i];
214 66 const item = object[key];
215 66 if (this.settings.path && path.length > 0) {
216 3 keyLengths.push(this.settings.pathPrefix);
217 3 out = out + this.indent() +
218 this.colorize(this.settings.pathPrefix, 'path') +
219 this.tidyPath(path + '.' + key) + '\n';
220 }
221 66 const longest = keyLengths.sort(internals.lengthCompare)[keyLengths.length - 1];
222 66 const keyStr = key.toString();
223
224 66 if (this.settings.depth === null || this.settings.depth + 1 >= depth) {
225 64 out = out + this.indent() + '' + (this.printMember(keyStr, longest) + ':') + ' ' + this.travel(item, path + '.' + keyStr, depth);
226 }
227 else {
228 2 this.indentLevel = this.indentLevel - 1;
229 2 return this.colorize('[Object]', 'depth');
230 }
231 64 if (i !== keys.length - 1) {
232 22 out = out + ',';
233 }
234 64 out = out + '\n';
235 }
236 42 this.indentLevel = this.indentLevel - 1;
237 42 out = out + this.indent() + '}';
238 42 return out;
239 };
240
241
242 1 internals.purdy.prototype.showCircular = function (index) {
243
244 5 let showPath = this.path[index];
245 5 showPath = showPath === '' ? '' : ' ' + showPath.slice(1, showPath.length);
246 5 return this.colorize('[Circular~' + showPath + ']', 'Circular');
247 };
248
249
250 1 internals.purdy.prototype.Array = function (array, path, depth) {
251
252 23 if (array.length === 0) {
253 1 return '[]';
254 }
255
256 22 ++depth;
257 22 const index = this.seen.indexOf(array);
258 22 if (index !== -1) {
259 2 return this.showCircular(index);
260 }
261 20 this.seen.push(array);
262 20 this.path.push(path);
263
264 20 let out = '[\n';
265 20 this.indentLevel = this.indentLevel + 1;
266
267 20 for (let i = 0; i < array.length; ++i) {
268 48 const item = array[i];
269 48 if (this.settings.path && path.length > 0) {
270 1 out = out + this.indent() +
271 this.colorize(this.settings.pathPrefix, 'path') +
272 this.tidyPath(path + '.' + i) + '\n';
273 }
274 48 const indexStr = this.settings.arrayIndex ? '[' + this.printMember(i, array.length) + '] ' : '';
275 48 if (this.settings.depth === null || this.settings.depth + 1 >= depth) {
276 45 out = out + this.indent() + '' + indexStr + this.travel(item, path + '.' + i, depth);
277 }
278 else {
279 3 this.indentLevel = this.indentLevel - 1;
280 3 return this.colorize('[Object]', 'depth');
281 }
282 45 if (i !== array.length - 1) {
283 28 out = out + ',';
284 }
285 45 out = out + '\n';
286 }
287 17 this.indentLevel = this.indentLevel - 1;
288 17 out = out + this.indent() + ']';
289 17 return out;
290 };
291
292
293 1 internals.purdy.prototype.Error = function (err) {
294
295 4 if (Object.keys(err).length === 0) {
296 1 return this.colorize('[' + err + ']', 'error');
297 }
298 3 const obj = this.Object(err, '', null);
299 3 const message = err.message ? ': ' + err.message : '';
300 3 return obj.replace(/^{/, '{ ' + this.colorize('[Error' + message + ']', 'error') );
301 };
302
303
304 1 internals.purdy.prototype.String = function (str) {
305
306 14 return '\'' + str + '\'';
307 };
308
309 1 internals.purdy.prototype.Arguments = function (obj) {
310
311 1 const arr = Array.prototype.slice.call(obj);
312 1 return this.Array(arr);
313 };
314
315
316 1 internals.purdy.prototype.Boolean = function (bool) {
317
318 3 if (bool === true) {
319 2 return this.colorize(bool + '', 'BoolTrue');
320 }
321 1 return this.colorize(bool + '', 'BoolFalse');
322 };
323
324
325 1 internals.purdy.prototype.Function = function (obj) {
326
327 8 const name = obj.name ? ': ' + obj.name : '';
328
329 8 if (Object.keys(obj).length === 0) {
330 6 return this.colorize('[Function' + name + ']', 'function');
331 }
332
333 2 const props = this.Object(obj, '', null);
334 2 return props.replace(/^{/, '{ ' + this.colorize('[Function' + name + ']', 'function') );
335 };
336
337
338 1 internals.purdy.prototype.indent = function () {
339
340 172 return internals.spaces(this.indentLevel * this.settings.indent);
341 };
342
343
344 1 internals.spaces = function (count) {
345
346 256 let out = '';
347 256 for (let i = 0; i < count; ++i) {
348 815 out = out + ' ';
349 }
350
351 256 return out;
352 };
353
354
355 1 internals.purdy.prototype.printMember = function (member, max) {
356
357 84 if (this.settings.align === 'left') {
358 56 max = 0;
359 }
360 84 const memberLength = member.length;
361 84 const maxLength = max.length;
362 84 const toShift = maxLength - memberLength;
363 84 return this.colorize(internals.spaces(toShift) + member, 'Key');
364 };
365

Linting Report

0 0