amazing_print 1.0.0

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 (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/Appraisals +60 -0
  4. data/CHANGELOG.md +2 -0
  5. data/CONTRIBUTING.md +81 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +21 -0
  8. data/README.md +356 -0
  9. data/Rakefile +23 -0
  10. data/lib/amazing_print.rb +46 -0
  11. data/lib/amazing_print/colorize.rb +25 -0
  12. data/lib/amazing_print/core_ext/awesome_method_array.rb +82 -0
  13. data/lib/amazing_print/core_ext/class.rb +23 -0
  14. data/lib/amazing_print/core_ext/kernel.rb +25 -0
  15. data/lib/amazing_print/core_ext/logger.rb +21 -0
  16. data/lib/amazing_print/core_ext/method.rb +21 -0
  17. data/lib/amazing_print/core_ext/object.rb +23 -0
  18. data/lib/amazing_print/core_ext/string.rb +42 -0
  19. data/lib/amazing_print/custom_defaults.rb +57 -0
  20. data/lib/amazing_print/ext/action_view.rb +22 -0
  21. data/lib/amazing_print/ext/active_record.rb +103 -0
  22. data/lib/amazing_print/ext/active_support.rb +45 -0
  23. data/lib/amazing_print/ext/mongo_mapper.rb +125 -0
  24. data/lib/amazing_print/ext/mongoid.rb +68 -0
  25. data/lib/amazing_print/ext/nobrainer.rb +53 -0
  26. data/lib/amazing_print/ext/nokogiri.rb +45 -0
  27. data/lib/amazing_print/ext/ostruct.rb +27 -0
  28. data/lib/amazing_print/ext/ripple.rb +71 -0
  29. data/lib/amazing_print/ext/sequel.rb +55 -0
  30. data/lib/amazing_print/formatter.rb +120 -0
  31. data/lib/amazing_print/formatters.rb +14 -0
  32. data/lib/amazing_print/formatters/array_formatter.rb +139 -0
  33. data/lib/amazing_print/formatters/base_formatter.rb +148 -0
  34. data/lib/amazing_print/formatters/class_formatter.rb +24 -0
  35. data/lib/amazing_print/formatters/dir_formatter.rb +21 -0
  36. data/lib/amazing_print/formatters/file_formatter.rb +21 -0
  37. data/lib/amazing_print/formatters/hash_formatter.rb +106 -0
  38. data/lib/amazing_print/formatters/method_formatter.rb +21 -0
  39. data/lib/amazing_print/formatters/object_formatter.rb +82 -0
  40. data/lib/amazing_print/formatters/simple_formatter.rb +20 -0
  41. data/lib/amazing_print/formatters/struct_formatter.rb +74 -0
  42. data/lib/amazing_print/indentator.rb +17 -0
  43. data/lib/amazing_print/inspector.rb +175 -0
  44. data/lib/amazing_print/version.rb +10 -0
  45. data/lib/ap.rb +10 -0
  46. data/spec/active_record_helper.rb +30 -0
  47. data/spec/colors_spec.rb +114 -0
  48. data/spec/core_ext/logger_spec.rb +44 -0
  49. data/spec/core_ext/string_spec.rb +20 -0
  50. data/spec/ext/action_view_spec.rb +17 -0
  51. data/spec/ext/active_record_spec.rb +297 -0
  52. data/spec/ext/active_support_spec.rb +26 -0
  53. data/spec/ext/mongo_mapper_spec.rb +259 -0
  54. data/spec/ext/mongoid_spec.rb +66 -0
  55. data/spec/ext/nobrainer_spec.rb +58 -0
  56. data/spec/ext/nokogiri_spec.rb +50 -0
  57. data/spec/ext/ostruct_spec.rb +22 -0
  58. data/spec/ext/ripple_spec.rb +47 -0
  59. data/spec/formats_spec.rb +779 -0
  60. data/spec/methods_spec.rb +478 -0
  61. data/spec/misc_spec.rb +245 -0
  62. data/spec/objects_spec.rb +219 -0
  63. data/spec/spec_helper.rb +106 -0
  64. data/spec/support/active_record_data.rb +20 -0
  65. data/spec/support/active_record_data/3_2_diana.txt +24 -0
  66. data/spec/support/active_record_data/3_2_diana_legacy.txt +24 -0
  67. data/spec/support/active_record_data/3_2_multi.txt +50 -0
  68. data/spec/support/active_record_data/3_2_multi_legacy.txt +50 -0
  69. data/spec/support/active_record_data/4_0_diana.txt +98 -0
  70. data/spec/support/active_record_data/4_0_multi.txt +198 -0
  71. data/spec/support/active_record_data/4_1_diana.txt +97 -0
  72. data/spec/support/active_record_data/4_1_multi.txt +196 -0
  73. data/spec/support/active_record_data/4_2_diana.txt +109 -0
  74. data/spec/support/active_record_data/4_2_diana_legacy.txt +109 -0
  75. data/spec/support/active_record_data/4_2_multi.txt +220 -0
  76. data/spec/support/active_record_data/4_2_multi_legacy.txt +220 -0
  77. data/spec/support/active_record_data/5_0_diana.txt +105 -0
  78. data/spec/support/active_record_data/5_0_multi.txt +212 -0
  79. data/spec/support/active_record_data/5_1_diana.txt +104 -0
  80. data/spec/support/active_record_data/5_1_multi.txt +210 -0
  81. data/spec/support/active_record_data/5_2_diana.txt +104 -0
  82. data/spec/support/active_record_data/5_2_multi.txt +210 -0
  83. data/spec/support/active_record_data/6_0_diana.txt +104 -0
  84. data/spec/support/active_record_data/6_0_multi.txt +210 -0
  85. data/spec/support/ext_verifier.rb +41 -0
  86. data/spec/support/mongoid_versions.rb +22 -0
  87. data/spec/support/rails_versions.rb +50 -0
  88. metadata +243 -0
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'AmazingPrint Ostruct extension' do
4
+ before do
5
+ @ap = AmazingPrint::Inspector.new(plain: true, sort_keys: true)
6
+ end
7
+
8
+ it 'empty hash' do
9
+ struct = OpenStruct.new
10
+ expect(@ap.send(:awesome, struct)).to eq('OpenStruct {}')
11
+ end
12
+
13
+ it 'plain multiline' do
14
+ struct = OpenStruct.new name: 'Foo', address: 'Bar'
15
+ expect(@ap.send(:awesome, struct)).to eq <<~EOS.strip
16
+ OpenStruct {
17
+ :address => "Bar",
18
+ :name => "Foo"
19
+ }
20
+ EOS
21
+ end
22
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'AmazingPrint/Ripple', skip: -> { !ExtVerifier.has_ripple? }.call do
4
+ if ExtVerifier.has_ripple?
5
+ before :all do
6
+ class RippleUser
7
+ include Ripple::Document
8
+
9
+ key_on :_id
10
+ property :_id, String
11
+ property :first_name, String
12
+ property :last_name, String
13
+ end
14
+ end
15
+
16
+ after :all do
17
+ Object.instance_eval { remove_const :RippleUser }
18
+ end
19
+ end
20
+
21
+ before do
22
+ @ap = AmazingPrint::Inspector.new plain: true, sort_keys: true
23
+ end
24
+
25
+ it 'should print class instance' do
26
+ user = RippleUser.new _id: '12345', first_name: 'Al', last_name: 'Capone'
27
+ out = @ap.send :awesome, user
28
+
29
+ expect(out).to be_similar_to <<~EOS.strip
30
+ #<RippleUser:placeholder_id> {
31
+ :_id => "12345",
32
+ :first_name => "Al",
33
+ :last_name => "Capone"
34
+ }
35
+ EOS
36
+ end
37
+
38
+ it 'should print the class' do
39
+ expect(@ap.send(:awesome, RippleUser)).to eq <<~EOS.strip
40
+ class RippleUser < Object {
41
+ :_id => :string,
42
+ :first_name => :string,
43
+ :last_name => :string
44
+ }
45
+ EOS
46
+ end
47
+ end
@@ -0,0 +1,779 @@
1
+ require 'spec_helper'
2
+ require 'bigdecimal'
3
+ require 'set'
4
+
5
+ RSpec.describe 'AmazingPrint' do
6
+ describe 'Array' do
7
+ before do
8
+ @arr = [1, :two, 'three', [nil, [true, false]]]
9
+ end
10
+
11
+ it 'empty array' do
12
+ expect([].ai).to eq('[]')
13
+ end
14
+
15
+ it 'plain multiline' do
16
+ expect(@arr.ai(plain: true)).to eq <<~EOS.strip
17
+ [
18
+ [0] 1,
19
+ [1] :two,
20
+ [2] "three",
21
+ [3] [
22
+ [0] nil,
23
+ [1] [
24
+ [0] true,
25
+ [1] false
26
+ ]
27
+ ]
28
+ ]
29
+ EOS
30
+ end
31
+
32
+ it 'plain multiline without index' do
33
+ expect(@arr.ai(plain: true, index: false)).to eq <<~EOS.strip
34
+ [
35
+ 1,
36
+ :two,
37
+ "three",
38
+ [
39
+ nil,
40
+ [
41
+ true,
42
+ false
43
+ ]
44
+ ]
45
+ ]
46
+ EOS
47
+ end
48
+
49
+ it 'plain multiline indented' do
50
+ expect(@arr.ai(plain: true, indent: 2)).to eq <<~EOS.strip
51
+ [
52
+ [0] 1,
53
+ [1] :two,
54
+ [2] "three",
55
+ [3] [
56
+ [0] nil,
57
+ [1] [
58
+ [0] true,
59
+ [1] false
60
+ ]
61
+ ]
62
+ ]
63
+ EOS
64
+ end
65
+
66
+ it 'plain multiline indented without index' do
67
+ expect(@arr.ai(plain: true, indent: 2, index: false)).to eq <<~EOS.strip
68
+ [
69
+ 1,
70
+ :two,
71
+ "three",
72
+ [
73
+ nil,
74
+ [
75
+ true,
76
+ false
77
+ ]
78
+ ]
79
+ ]
80
+ EOS
81
+ end
82
+
83
+ it 'plain single line' do
84
+ expect(@arr.ai(plain: true, multiline: false)).to eq('[ 1, :two, "three", [ nil, [ true, false ] ] ]')
85
+ end
86
+
87
+ it 'colored multiline (default)' do
88
+ expect(@arr.ai).to eq <<~EOS.strip
89
+ [
90
+ \e[1;37m[0] \e[0m\e[1;34m1\e[0m,
91
+ \e[1;37m[1] \e[0m\e[0;36m:two\e[0m,
92
+ \e[1;37m[2] \e[0m\e[0;33m\"three\"\e[0m,
93
+ \e[1;37m[3] \e[0m[
94
+ \e[1;37m[0] \e[0m\e[1;31mnil\e[0m,
95
+ \e[1;37m[1] \e[0m[
96
+ \e[1;37m[0] \e[0m\e[1;32mtrue\e[0m,
97
+ \e[1;37m[1] \e[0m\e[1;31mfalse\e[0m
98
+ ]
99
+ ]
100
+ ]
101
+ EOS
102
+ end
103
+
104
+ it 'colored multiline indented' do
105
+ expect(@arr.ai(indent: 8)).to eq <<~EOS.strip
106
+ [
107
+ \e[1;37m[0] \e[0m\e[1;34m1\e[0m,
108
+ \e[1;37m[1] \e[0m\e[0;36m:two\e[0m,
109
+ \e[1;37m[2] \e[0m\e[0;33m\"three\"\e[0m,
110
+ \e[1;37m[3] \e[0m[
111
+ \e[1;37m[0] \e[0m\e[1;31mnil\e[0m,
112
+ \e[1;37m[1] \e[0m[
113
+ \e[1;37m[0] \e[0m\e[1;32mtrue\e[0m,
114
+ \e[1;37m[1] \e[0m\e[1;31mfalse\e[0m
115
+ ]
116
+ ]
117
+ ]
118
+ EOS
119
+ end
120
+
121
+ it 'colored single line' do
122
+ expect(@arr.ai(multiline: false)).to eq("[ \e[1;34m1\e[0m, \e[0;36m:two\e[0m, \e[0;33m\"three\"\e[0m, [ \e[1;31mnil\e[0m, [ \e[1;32mtrue\e[0m, \e[1;31mfalse\e[0m ] ] ]")
123
+ end
124
+ end
125
+
126
+ #------------------------------------------------------------------------------
127
+ describe 'Nested Array' do
128
+ before do
129
+ @arr = [1, 2]
130
+ @arr << @arr
131
+ end
132
+
133
+ it 'plain multiline' do
134
+ expect(@arr.ai(plain: true)).to eq <<~EOS.strip
135
+ [
136
+ [0] 1,
137
+ [1] 2,
138
+ [2] [...]
139
+ ]
140
+ EOS
141
+ end
142
+
143
+ it 'plain multiline without index' do
144
+ expect(@arr.ai(plain: true, index: false)).to eq <<~EOS.strip
145
+ [
146
+ 1,
147
+ 2,
148
+ [...]
149
+ ]
150
+ EOS
151
+ end
152
+
153
+ it 'plain single line' do
154
+ expect(@arr.ai(plain: true, multiline: false)).to eq('[ 1, 2, [...] ]')
155
+ end
156
+ end
157
+
158
+ #------------------------------------------------------------------------------
159
+ describe 'Limited Output Array' do
160
+ before(:each) do
161
+ @arr = (1..1000).to_a
162
+ end
163
+
164
+ it 'plain limited output large' do
165
+ expect(@arr.ai(plain: true, limit: true)).to eq <<~EOS.strip
166
+ [
167
+ [ 0] 1,
168
+ [ 1] 2,
169
+ [ 2] 3,
170
+ [ 3] .. [996],
171
+ [997] 998,
172
+ [998] 999,
173
+ [999] 1000
174
+ ]
175
+ EOS
176
+ end
177
+
178
+ it 'plain limited output small' do
179
+ @arr = @arr[0..3]
180
+ expect(@arr.ai(plain: true, limit: true)).to eq <<~EOS.strip
181
+ [
182
+ [0] 1,
183
+ [1] 2,
184
+ [2] 3,
185
+ [3] 4
186
+ ]
187
+ EOS
188
+ end
189
+
190
+ it 'plain limited output with 10 lines' do
191
+ expect(@arr.ai(plain: true, limit: 10)).to eq <<~EOS.strip
192
+ [
193
+ [ 0] 1,
194
+ [ 1] 2,
195
+ [ 2] 3,
196
+ [ 3] 4,
197
+ [ 4] 5,
198
+ [ 5] .. [995],
199
+ [996] 997,
200
+ [997] 998,
201
+ [998] 999,
202
+ [999] 1000
203
+ ]
204
+ EOS
205
+ end
206
+
207
+ it 'plain limited output with 11 lines' do
208
+ expect(@arr.ai(plain: true, limit: 11)).to eq <<~EOS.strip
209
+ [
210
+ [ 0] 1,
211
+ [ 1] 2,
212
+ [ 2] 3,
213
+ [ 3] 4,
214
+ [ 4] 5,
215
+ [ 5] .. [994],
216
+ [995] 996,
217
+ [996] 997,
218
+ [997] 998,
219
+ [998] 999,
220
+ [999] 1000
221
+ ]
222
+ EOS
223
+ end
224
+ end
225
+
226
+ #------------------------------------------------------------------------------
227
+ describe 'Limited Output Hash' do
228
+ before(:each) do
229
+ @hash = ('a'..'z').inject({}) { |h, v| h.merge({ v => v.to_sym }) }
230
+ end
231
+
232
+ it 'plain limited output' do
233
+ expect(@hash.ai(sort_keys: true, plain: true, limit: true)).to eq <<~EOS.strip
234
+ {
235
+ "a" => :a,
236
+ "b" => :b,
237
+ "c" => :c,
238
+ "d" => :d .. "w" => :w,
239
+ "x" => :x,
240
+ "y" => :y,
241
+ "z" => :z
242
+ }
243
+ EOS
244
+ end
245
+ end
246
+
247
+ #------------------------------------------------------------------------------
248
+ describe 'Hash' do
249
+ before do
250
+ @hash = { 1 => { sym: { 'str' => { [1, 2, 3] => { { k: :v } => Hash } } } } }
251
+ end
252
+
253
+ it 'empty hash' do
254
+ expect({}.ai).to eq('{}')
255
+ end
256
+
257
+ it 'plain multiline' do
258
+ expect(@hash.ai(plain: true)).to eq <<~EOS.strip
259
+ {
260
+ 1 => {
261
+ :sym => {
262
+ "str" => {
263
+ [ 1, 2, 3 ] => {
264
+ { :k => :v } => Hash < Object
265
+ }
266
+ }
267
+ }
268
+ }
269
+ }
270
+ EOS
271
+ end
272
+
273
+ it 'new hash syntax' do
274
+ expect(@hash.ai(plain: true, ruby19_syntax: true)).to eq <<~EOS.strip
275
+ {
276
+ 1 => {
277
+ sym: {
278
+ "str" => {
279
+ [ 1, 2, 3 ] => {
280
+ { k: :v } => Hash < Object
281
+ }
282
+ }
283
+ }
284
+ }
285
+ }
286
+ EOS
287
+ end
288
+
289
+ it 'plain multiline indented' do
290
+ expect(@hash.ai(plain: true, indent: 1)).to eq <<~EOS.strip
291
+ {
292
+ 1 => {
293
+ :sym => {
294
+ "str" => {
295
+ [ 1, 2, 3 ] => {
296
+ { :k => :v } => Hash < Object
297
+ }
298
+ }
299
+ }
300
+ }
301
+ }
302
+ EOS
303
+ end
304
+
305
+ it 'plain single line' do
306
+ expect(@hash.ai(plain: true, multiline: false)).to eq('{ 1 => { :sym => { "str" => { [ 1, 2, 3 ] => { { :k => :v } => Hash < Object } } } } }')
307
+ end
308
+
309
+ it 'colored multiline (default)' do
310
+ expect(@hash.ai).to eq <<~EOS.strip
311
+ {
312
+ 1\e[0;37m => \e[0m{
313
+ :sym\e[0;37m => \e[0m{
314
+ \"str\"\e[0;37m => \e[0m{
315
+ [ 1, 2, 3 ]\e[0;37m => \e[0m{
316
+ { :k => :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m
317
+ }
318
+ }
319
+ }
320
+ }
321
+ }
322
+ EOS
323
+ end
324
+
325
+ it 'colored with new hash syntax' do
326
+ expect(@hash.ai(ruby19_syntax: true)).to eq <<~EOS.strip
327
+ {
328
+ 1\e[0;37m => \e[0m{
329
+ sym\e[0;37m: \e[0m{
330
+ \"str\"\e[0;37m => \e[0m{
331
+ [ 1, 2, 3 ]\e[0;37m => \e[0m{
332
+ { k: :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m
333
+ }
334
+ }
335
+ }
336
+ }
337
+ }
338
+ EOS
339
+ end
340
+
341
+ it 'colored multiline indented' do
342
+ expect(@hash.ai(indent: 2)).to eq <<~EOS.strip
343
+ {
344
+ 1\e[0;37m => \e[0m{
345
+ :sym\e[0;37m => \e[0m{
346
+ \"str\"\e[0;37m => \e[0m{
347
+ [ 1, 2, 3 ]\e[0;37m => \e[0m{
348
+ { :k => :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m
349
+ }
350
+ }
351
+ }
352
+ }
353
+ }
354
+ EOS
355
+ end
356
+
357
+ it 'colored single line' do
358
+ expect(@hash.ai(multiline: false)).to eq("{ 1\e[0;37m => \e[0m{ :sym\e[0;37m => \e[0m{ \"str\"\e[0;37m => \e[0m{ [ 1, 2, 3 ]\e[0;37m => \e[0m{ { :k => :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m } } } } }")
359
+ end
360
+ end
361
+
362
+ #------------------------------------------------------------------------------
363
+ describe 'Nested Hash' do
364
+ before do
365
+ @hash = {}
366
+ @hash[:a] = @hash
367
+ end
368
+
369
+ it 'plain multiline' do
370
+ expect(@hash.ai(plain: true)).to eq <<~EOS.strip
371
+ {
372
+ :a => {...}
373
+ }
374
+ EOS
375
+ end
376
+
377
+ it 'plain single line' do
378
+ expect(@hash.ai(plain: true, multiline: false)).to eq('{ :a => {...} }')
379
+ end
380
+ end
381
+
382
+ #------------------------------------------------------------------------------
383
+ describe 'Hash with several keys' do
384
+ before do
385
+ @hash = { 'b' => 'b', :a => 'a', :z => 'z', 'alpha' => 'alpha' }
386
+ end
387
+
388
+ it 'plain multiline' do
389
+ out = @hash.ai(plain: true)
390
+ if RUBY_VERSION.to_f < 1.9 # Order of @hash keys is not guaranteed.
391
+ expect(out).to match(/^\{[^\}]+\}/m)
392
+ expect(out).to match(/ "b" => "b",?/)
393
+ expect(out).to match(/ :a => "a",?/)
394
+ expect(out).to match(/ :z => "z",?/)
395
+ expect(out).to match(/ "alpha" => "alpha",?$/)
396
+ else
397
+ expect(out).to eq <<~EOS.strip
398
+ {
399
+ "b" => "b",
400
+ :a => "a",
401
+ :z => "z",
402
+ "alpha" => "alpha"
403
+ }
404
+ EOS
405
+ end
406
+ end
407
+
408
+ it 'plain multiline with sorted keys' do
409
+ expect(@hash.ai(plain: true, sort_keys: true)).to eq <<~EOS.strip
410
+ {
411
+ :a => "a",
412
+ "alpha" => "alpha",
413
+ "b" => "b",
414
+ :z => "z"
415
+ }
416
+ EOS
417
+ end
418
+ end
419
+
420
+ #------------------------------------------------------------------------------
421
+ describe 'Negative options[:indent]' do
422
+ #
423
+ # With Ruby < 1.9 the order of hash keys is not defined so we can't
424
+ # reliably compare the output string.
425
+ #
426
+ it 'hash keys must be left aligned' do
427
+ hash = { [0, 0, 255] => :yellow, :red => 'rgb(255, 0, 0)', 'magenta' => 'rgb(255, 0, 255)' }
428
+ out = hash.ai(plain: true, indent: -4, sort_keys: true)
429
+ expect(out).to eq <<~EOS.strip
430
+ {
431
+ [ 0, 0, 255 ] => :yellow,
432
+ "magenta" => "rgb(255, 0, 255)",
433
+ :red => "rgb(255, 0, 0)"
434
+ }
435
+ EOS
436
+ end
437
+
438
+ it 'nested hash keys should be indented (array of hashes)' do
439
+ arr = [{ a: 1, bb: 22, ccc: 333 }, { 1 => :a, 22 => :bb, 333 => :ccc }]
440
+ out = arr.ai(plain: true, indent: -4, sort_keys: true)
441
+ expect(out).to eq <<~EOS.strip
442
+ [
443
+ [0] {
444
+ :a => 1,
445
+ :bb => 22,
446
+ :ccc => 333
447
+ },
448
+ [1] {
449
+ 1 => :a,
450
+ 22 => :bb,
451
+ 333 => :ccc
452
+ }
453
+ ]
454
+ EOS
455
+ end
456
+
457
+ it 'nested hash keys should be indented (hash of hashes)' do
458
+ arr = { first: { a: 1, bb: 22, ccc: 333 }, second: { 1 => :a, 22 => :bb, 333 => :ccc } }
459
+ out = arr.ai(plain: true, indent: -4, sort_keys: true)
460
+ expect(out).to eq <<~EOS.strip
461
+ {
462
+ :first => {
463
+ :a => 1,
464
+ :bb => 22,
465
+ :ccc => 333
466
+ },
467
+ :second => {
468
+ 1 => :a,
469
+ 22 => :bb,
470
+ 333 => :ccc
471
+ }
472
+ }
473
+ EOS
474
+ end
475
+ end
476
+
477
+ #------------------------------------------------------------------------------
478
+ describe 'Class' do
479
+ it 'should show superclass (plain)' do
480
+ expect(self.class.ai(plain: true)).to eq("#{self.class} < #{self.class.superclass}")
481
+ end
482
+
483
+ it 'should show superclass (color)' do
484
+ expect(self.class.ai).to eq("#{self.class} < #{self.class.superclass}".yellow)
485
+ end
486
+ end
487
+
488
+ #------------------------------------------------------------------------------
489
+ describe 'File' do
490
+ it 'should display a file (plain)' do
491
+ File.open(__FILE__, 'r') do |f|
492
+ expect(f.ai(plain: true)).to eq("#{f.inspect}\n" << `ls -alF #{f.path}`.chop)
493
+ end
494
+ end
495
+ end
496
+
497
+ #------------------------------------------------------------------------------
498
+ describe 'Dir' do
499
+ it 'should display a direcory (plain)' do
500
+ Dir.open(File.dirname(__FILE__)) do |d|
501
+ expect(d.ai(plain: true)).to eq("#{d.inspect}\n" << `ls -alF #{d.path}`.chop)
502
+ end
503
+ end
504
+ end
505
+
506
+ #------------------------------------------------------------------------------
507
+ describe 'BigDecimal and Rational' do
508
+ it 'should present BigDecimal object with arbitrary precision' do
509
+ big = BigDecimal('201020102010201020102010201020102010.4')
510
+ expect(big.ai(plain: true)).to eq('201020102010201020102010201020102010.4')
511
+ end
512
+
513
+ it 'should present Rational object with arbitrary precision' do
514
+ rat = Rational(201_020_102_010_201_020_102_010_201_020_102_010, 2)
515
+ out = rat.ai(plain: true)
516
+ #
517
+ # Ruby 1.9 slightly changed the format of Rational#to_s, see
518
+ # http://techtime.getharvest.com/blog/harvest-is-now-on-ruby-1-dot-9-3 and
519
+ # http://www.ruby-forum.com/topic/189397
520
+ #
521
+ if RUBY_VERSION < '1.9'
522
+ expect(out).to eq('100510051005100510051005100510051005')
523
+ else
524
+ expect(out).to eq('100510051005100510051005100510051005/1')
525
+ end
526
+ end
527
+ end
528
+
529
+ #------------------------------------------------------------------------------
530
+ describe 'Utility methods' do
531
+ it 'should merge options' do
532
+ ap = AmazingPrint::Inspector.new
533
+ ap.send(:merge_options!, { color: { array: :black }, indent: 0 })
534
+ options = ap.instance_variable_get('@options')
535
+ expect(options[:color][:array]).to eq(:black)
536
+ expect(options[:indent]).to eq(0)
537
+ end
538
+ end
539
+
540
+ #------------------------------------------------------------------------------
541
+ describe 'Set' do
542
+ before do
543
+ @arr = [1, :two, 'three']
544
+ @set = Set.new(@arr)
545
+ end
546
+
547
+ it 'empty set' do
548
+ expect(Set.new.ai).to eq([].ai)
549
+ end
550
+
551
+ if RUBY_VERSION > '1.9'
552
+ it 'plain multiline' do
553
+ expect(@set.ai(plain: true)).to eq(@arr.ai(plain: true))
554
+ end
555
+
556
+ it 'plain multiline indented' do
557
+ expect(@set.ai(plain: true, indent: 1)).to eq(@arr.ai(plain: true, indent: 1))
558
+ end
559
+
560
+ it 'plain single line' do
561
+ expect(@set.ai(plain: true, multiline: false)).to eq(@arr.ai(plain: true, multiline: false))
562
+ end
563
+
564
+ it 'colored multiline (default)' do
565
+ expect(@set.ai).to eq(@arr.ai)
566
+ end
567
+ else # Prior to Ruby 1.9 the order of set values is unpredicatble.
568
+ it 'plain multiline' do
569
+ expect(@set.sort_by { |x| x.to_s }.ai(plain: true)).to eq(@arr.sort_by { |x| x.to_s }.ai(plain: true))
570
+ end
571
+
572
+ it 'plain multiline indented' do
573
+ expect(@set.sort_by { |x| x.to_s }.ai(plain: true, indent: 1)).to eq(@arr.sort_by { |x| x.to_s }.ai(plain: true, indent: 1))
574
+ end
575
+
576
+ it 'plain single line' do
577
+ expect(@set.sort_by { |x| x.to_s }.ai(plain: true, multiline: false)).to eq(@arr.sort_by { |x| x.to_s }.ai(plain: true, multiline: false))
578
+ end
579
+
580
+ it 'colored multiline (default)' do
581
+ expect(@set.sort_by { |x| x.to_s }.ai).to eq(@arr.sort_by { |x| x.to_s }.ai)
582
+ end
583
+ end
584
+ end
585
+
586
+ #------------------------------------------------------------------------------
587
+ describe 'Struct' do
588
+ before do
589
+ @struct = if defined?(Struct::SimpleStruct)
590
+ Struct::SimpleStruct.new
591
+ else
592
+ Struct.new('SimpleStruct', :name, :address).new
593
+ end
594
+ @struct.name = 'Herman Munster'
595
+ @struct.address = '1313 Mockingbird Lane'
596
+ end
597
+
598
+ it 'empty struct' do
599
+ expect(Struct.new('EmptyStruct').ai).to eq("\e[1;33mStruct::EmptyStruct < Struct\e[0m")
600
+ end
601
+
602
+ it 'plain multiline' do
603
+ s1 = <<-EOS.strip
604
+ address = \"1313 Mockingbird Lane\",
605
+ name = \"Herman Munster\"
606
+ EOS
607
+ s2 = <<-EOS.strip
608
+ name = \"Herman Munster\",
609
+ address = \"1313 Mockingbird Lane\"
610
+ EOS
611
+ expect(@struct.ai(plain: true)).to satisfy { |out| out.match(s1) || out.match(s2) }
612
+ end
613
+
614
+ it 'plain multiline indented' do
615
+ s1 = <<-EOS.strip
616
+ address = "1313 Mockingbird Lane",
617
+ name = "Herman Munster"
618
+ EOS
619
+ s2 = <<-EOS.strip
620
+ name = "Herman Munster",
621
+ address = "1313 Mockingbird Lane"
622
+ EOS
623
+ expect(@struct.ai(plain: true, indent: 1)).to satisfy { |out| out.match(s1) || out.match(s2) }
624
+ end
625
+
626
+ it 'plain single line' do
627
+ s1 = 'address = "1313 Mockingbird Lane", name = "Herman Munster"'
628
+ s2 = 'name = "Herman Munster", address = "1313 Mockingbird Lane"'
629
+ expect(@struct.ai(plain: true, multiline: false)).to satisfy { |out| out.match(s1) || out.match(s2) }
630
+ end
631
+
632
+ it 'colored multiline (default)' do
633
+ s1 = <<-EOS.strip
634
+ address\e[0;37m = \e[0m\e[0;33m\"1313 Mockingbird Lane\"\e[0m,
635
+ name\e[0;37m = \e[0m\e[0;33m\"Herman Munster\"\e[0m
636
+ EOS
637
+ s2 = <<-EOS.strip
638
+ name\e[0;37m = \e[0m\e[0;33m\"Herman Munster\"\e[0m,
639
+ address\e[0;37m = \e[0m\e[0;33m\"1313 Mockingbird Lane\"\e[0m
640
+ EOS
641
+ expect(@struct.ai).to satisfy { |out| out.include?(s1) || out.include?(s2) }
642
+ end
643
+ end
644
+
645
+ #------------------------------------------------------------------------------
646
+ describe 'Inherited from standard Ruby classes' do
647
+ after do
648
+ Object.instance_eval { remove_const :My } if defined?(My)
649
+ end
650
+
651
+ it 'inherited from Array should be displayed as Array' do
652
+ class My < Array; end
653
+
654
+ my = My.new([1, :two, 'three', [nil, [true, false]]])
655
+ expect(my.ai(plain: true)).to eq <<~EOS.strip
656
+ [
657
+ [0] 1,
658
+ [1] :two,
659
+ [2] "three",
660
+ [3] [
661
+ [0] nil,
662
+ [1] [
663
+ [0] true,
664
+ [1] false
665
+ ]
666
+ ]
667
+ ]
668
+ EOS
669
+ end
670
+
671
+ it 'inherited from Hash should be displayed as Hash' do
672
+ class My < Hash; end
673
+
674
+ my = My[{ 1 => { sym: { 'str' => { [1, 2, 3] => { { k: :v } => Hash } } } } }]
675
+ expect(my.ai(plain: true)).to eq <<~EOS.strip
676
+ {
677
+ 1 => {
678
+ :sym => {
679
+ "str" => {
680
+ [ 1, 2, 3 ] => {
681
+ { :k => :v } => Hash < Object
682
+ }
683
+ }
684
+ }
685
+ }
686
+ }
687
+ EOS
688
+ end
689
+
690
+ it 'inherited from File should be displayed as File' do
691
+ class My < File; end
692
+
693
+ my = begin
694
+ File.new('/dev/null')
695
+ rescue StandardError
696
+ File.new('nul')
697
+ end
698
+ expect(my.ai(plain: true)).to eq("#{my.inspect}\n" << `ls -alF #{my.path}`.chop)
699
+ end
700
+
701
+ it 'inherited from Dir should be displayed as Dir' do
702
+ class My < Dir; end
703
+
704
+ require 'tmpdir'
705
+ my = My.new(Dir.tmpdir)
706
+ expect(my.ai(plain: true)).to eq("#{my.inspect}\n" << `ls -alF #{my.path}`.chop)
707
+ end
708
+
709
+ it 'should handle a class that defines its own #send method' do
710
+ class My
711
+ def send(arg1, arg2, arg3); end
712
+ end
713
+
714
+ my = My.new
715
+ expect { my.methods.ai(plain: true) }.not_to raise_error
716
+ end
717
+
718
+ it 'should handle a class defines its own #method method (ex. request.method)' do
719
+ class My
720
+ def method
721
+ 'POST'
722
+ end
723
+ end
724
+
725
+ my = My.new
726
+ expect { my.methods.ai(plain: true) }.not_to raise_error
727
+ end
728
+
729
+ describe 'should handle a class that defines its own #to_hash method' do
730
+ it 'that takes arguments' do
731
+ class My
732
+ def to_hash(a, b); end
733
+ end
734
+
735
+ my = My.new
736
+ expect { my.ai(plain: true) }.not_to raise_error
737
+ end
738
+
739
+ it 'that returns nil' do
740
+ class My
741
+ def to_hash
742
+ nil
743
+ end
744
+ end
745
+
746
+ my = My.new
747
+ expect { my.ai(plain: true) }.not_to raise_error
748
+ end
749
+
750
+ it "that returns an object that doesn't support #keys" do
751
+ class My
752
+ def to_hash
753
+ object = Object.new
754
+ object.define_singleton_method('[]') { return nil }
755
+
756
+ object
757
+ end
758
+ end
759
+
760
+ my = My.new
761
+ expect { my.ai(plain: true) }.not_to raise_error
762
+ end
763
+
764
+ it "that returns an object that doesn't support subscripting" do
765
+ class My
766
+ def to_hash
767
+ object = Object.new
768
+ object.define_singleton_method(:keys) { return [:foo] }
769
+
770
+ object
771
+ end
772
+ end
773
+
774
+ my = My.new
775
+ expect { my.ai(plain: true) }.not_to raise_error
776
+ end
777
+ end
778
+ end
779
+ end