awesome_print 1.9.2 → 2.0.0.pre

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 (116) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -1
  3. data/Appraisals +2 -33
  4. data/CHANGELOG.md +6 -15
  5. data/CONTRIBUTING.md +0 -1
  6. data/README.md +7 -49
  7. data/lib/ap.rb +1 -5
  8. data/lib/awesome_print.rb +7 -29
  9. data/lib/awesome_print/colorize.rb +2 -0
  10. data/lib/awesome_print/core_ext/active_support.rb +7 -0
  11. data/lib/awesome_print/core_ext/awesome_method_array.rb +0 -6
  12. data/lib/awesome_print/core_ext/class.rb +0 -5
  13. data/lib/awesome_print/core_ext/kernel.rb +0 -5
  14. data/lib/awesome_print/core_ext/logger.rb +0 -5
  15. data/lib/awesome_print/core_ext/object.rb +0 -5
  16. data/lib/awesome_print/core_ext/string.rb +0 -5
  17. data/lib/awesome_print/custom_defaults.rb +1 -1
  18. data/lib/awesome_print/formatter.rb +38 -106
  19. data/lib/awesome_print/formatters/array_formatter.rb +11 -8
  20. data/lib/awesome_print/formatters/base_formatter.rb +20 -53
  21. data/lib/awesome_print/formatters/bigdecimal_formatter.rb +20 -0
  22. data/lib/awesome_print/formatters/class_formatter.rb +5 -6
  23. data/lib/awesome_print/formatters/dir_formatter.rb +4 -6
  24. data/lib/awesome_print/formatters/ext/active_model_error_formatter.rb +44 -0
  25. data/lib/awesome_print/formatters/ext/active_record_attributeset_formatter.rb +27 -0
  26. data/lib/awesome_print/formatters/ext/active_record_class_formatter.rb +43 -0
  27. data/lib/awesome_print/formatters/ext/active_record_instance_formatter.rb +48 -0
  28. data/lib/awesome_print/formatters/ext/active_record_relation_formatter.rb +19 -0
  29. data/lib/awesome_print/formatters/ext/bson_objectid_formatter.rb +20 -0
  30. data/lib/awesome_print/formatters/ext/hash_with_indifferent_access_formatter.rb +20 -0
  31. data/lib/awesome_print/formatters/ext/mongoid_document_formatter.rb +59 -0
  32. data/lib/awesome_print/formatters/ext/nokogiri_document_formatter.rb +30 -0
  33. data/lib/awesome_print/formatters/ext/nokogiri_node_formatter.rb +29 -0
  34. data/lib/awesome_print/formatters/ext/nokogiri_nodeset_formatter.rb +32 -0
  35. data/lib/awesome_print/formatters/ext/sequel_dataset_formatter.rb +20 -0
  36. data/lib/awesome_print/formatters/ext/sequel_model_class_formatter.rb +25 -0
  37. data/lib/awesome_print/formatters/ext/sequel_model_formatter.rb +26 -0
  38. data/lib/awesome_print/formatters/ext/time_with_zone_formatter.rb +24 -0
  39. data/lib/awesome_print/formatters/fallback_formatter.rb +55 -0
  40. data/lib/awesome_print/formatters/false_class_formatter.rb +15 -0
  41. data/lib/awesome_print/formatters/file_formatter.rb +4 -6
  42. data/lib/awesome_print/formatters/hash_formatter.rb +12 -7
  43. data/lib/awesome_print/formatters/integer_formatter.rb +11 -0
  44. data/lib/awesome_print/formatters/method_formatter.rb +8 -6
  45. data/lib/awesome_print/formatters/module_formatter.rb +18 -0
  46. data/lib/awesome_print/formatters/nil_class_formatter.rb +19 -0
  47. data/lib/awesome_print/formatters/object_formatter.rb +19 -9
  48. data/lib/awesome_print/formatters/open_struct.rb +19 -0
  49. data/lib/awesome_print/formatters/range_formatter.rb +11 -0
  50. data/lib/awesome_print/formatters/rational_formatter.rb +15 -0
  51. data/lib/awesome_print/formatters/set_formatter.rb +19 -0
  52. data/lib/awesome_print/formatters/simple_formatter.rb +10 -8
  53. data/lib/awesome_print/formatters/string_formatter.rb +14 -0
  54. data/lib/awesome_print/formatters/struct_formatter.rb +8 -6
  55. data/lib/awesome_print/formatters/symbol_formatter.rb +18 -0
  56. data/lib/awesome_print/formatters/true_class_formatter.rb +15 -0
  57. data/lib/awesome_print/formatters/unbound_method_formatter.rb +15 -0
  58. data/lib/awesome_print/inspector.rb +18 -17
  59. data/lib/awesome_print/limiter.rb +63 -0
  60. data/lib/awesome_print/registrar.rb +20 -0
  61. data/lib/awesome_print/version.rb +6 -6
  62. data/spec/formatters/array_spec.rb +251 -0
  63. data/spec/formatters/big_decimal_spec.rb +28 -0
  64. data/spec/formatters/class_spec.rb +91 -0
  65. data/spec/formatters/dir_file_spec.rb +43 -0
  66. data/spec/{ext → formatters/ext}/active_record_spec.rb +14 -58
  67. data/spec/{ext → formatters/ext}/active_support_spec.rb +7 -11
  68. data/spec/{ext → formatters/ext}/mongoid_spec.rb +2 -2
  69. data/spec/{ext → formatters/ext}/nokogiri_spec.rb +0 -0
  70. data/spec/formatters/hash_spec.rb +284 -0
  71. data/spec/{methods_spec.rb → formatters/methods_spec.rb} +3 -5
  72. data/spec/{objects_spec.rb → formatters/objects_spec.rb} +0 -0
  73. data/spec/{ext → formatters}/ostruct_spec.rb +1 -0
  74. data/spec/formatters/set_spec.rb +49 -0
  75. data/spec/formatters/struct_spec.rb +61 -0
  76. data/spec/merge_options_spec.rb +13 -0
  77. data/spec/misc_spec.rb +3 -10
  78. data/spec/spec_helper.rb +2 -9
  79. data/spec/support/ext_verifier.rb +0 -15
  80. data/spec/support/mongoid_versions.rb +4 -8
  81. data/spec/support/rails_versions.rb +2 -32
  82. metadata +100 -78
  83. data/awesome_print.gemspec +0 -33
  84. data/init.rb +0 -1
  85. data/lib/awesome_print/core_ext/method.rb +0 -21
  86. data/lib/awesome_print/ext/action_view.rb +0 -22
  87. data/lib/awesome_print/ext/active_record.rb +0 -103
  88. data/lib/awesome_print/ext/active_support.rb +0 -47
  89. data/lib/awesome_print/ext/mongo_mapper.rb +0 -124
  90. data/lib/awesome_print/ext/mongoid.rb +0 -67
  91. data/lib/awesome_print/ext/nobrainer.rb +0 -52
  92. data/lib/awesome_print/ext/nokogiri.rb +0 -45
  93. data/lib/awesome_print/ext/ostruct.rb +0 -27
  94. data/lib/awesome_print/ext/ripple.rb +0 -71
  95. data/lib/awesome_print/ext/sequel.rb +0 -58
  96. data/spec/ext/action_view_spec.rb +0 -21
  97. data/spec/ext/mongo_mapper_spec.rb +0 -261
  98. data/spec/ext/nobrainer_spec.rb +0 -59
  99. data/spec/ext/ripple_spec.rb +0 -48
  100. data/spec/formats_spec.rb +0 -779
  101. data/spec/support/active_record_data/3_2_diana.txt +0 -24
  102. data/spec/support/active_record_data/3_2_diana_legacy.txt +0 -24
  103. data/spec/support/active_record_data/3_2_multi.txt +0 -50
  104. data/spec/support/active_record_data/3_2_multi_legacy.txt +0 -50
  105. data/spec/support/active_record_data/4_0_diana.txt +0 -98
  106. data/spec/support/active_record_data/4_0_multi.txt +0 -198
  107. data/spec/support/active_record_data/4_1_diana.txt +0 -97
  108. data/spec/support/active_record_data/4_1_multi.txt +0 -196
  109. data/spec/support/active_record_data/4_2_diana.txt +0 -109
  110. data/spec/support/active_record_data/4_2_diana_legacy.txt +0 -109
  111. data/spec/support/active_record_data/4_2_multi.txt +0 -220
  112. data/spec/support/active_record_data/4_2_multi_legacy.txt +0 -220
  113. data/spec/support/active_record_data/6_0_diana.txt +0 -104
  114. data/spec/support/active_record_data/6_0_multi.txt +0 -210
  115. data/spec/support/active_record_data/6_1_diana.txt +0 -109
  116. data/spec/support/active_record_data/6_1_multi.txt +0 -220
@@ -0,0 +1,28 @@
1
+ require_relative '../spec_helper'
2
+ require 'bigdecimal'
3
+ require 'rational'
4
+
5
+ RSpec.describe 'AwesomePrint' do
6
+ #------------------------------------------------------------------------------
7
+ describe 'BigDecimal and Rational' do
8
+ it 'should present BigDecimal object with arbitrary precision' do
9
+ big = BigDecimal('201020102010201020102010201020102010.4')
10
+ expect(big.ai(plain: true)).to eq('201020102010201020102010201020102010.4')
11
+ end
12
+
13
+ it 'should present Rational object with arbitrary precision' do
14
+ rat = Rational(201020102010201020102010201020102010, 2)
15
+ out = rat.ai(plain: true)
16
+ #
17
+ # Ruby 1.9 slightly changed the format of Rational#to_s, see
18
+ # http://techtime.getharvest.com/blog/harvest-is-now-on-ruby-1-dot-9-3 and
19
+ # http://www.ruby-forum.com/topic/189397
20
+ #
21
+ if RUBY_VERSION < '1.9'
22
+ expect(out).to eq('100510051005100510051005100510051005')
23
+ else
24
+ expect(out).to eq('100510051005100510051005100510051005/1')
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,91 @@
1
+ require_relative '../spec_helper'
2
+
3
+ RSpec.describe 'AwesomePrint' do
4
+
5
+ describe 'Class' do
6
+ it 'should show superclass (plain)' do
7
+ expect(self.class.ai(plain: true)).to eq("#{self.class} < #{self.class.superclass}")
8
+ end
9
+
10
+ it 'should show superclass (color)' do
11
+ expect(self.class.ai).to eq("#{self.class} < #{self.class.superclass}".yellow)
12
+ end
13
+ end
14
+
15
+ describe 'Inherited from standard Ruby classes' do
16
+ after do
17
+ Object.instance_eval { remove_const :My } if defined?(My)
18
+ end
19
+
20
+ it 'should handle a class that defines its own #send method' do
21
+ class My
22
+ def send(arg1, arg2, arg3); end
23
+ end
24
+
25
+ my = My.new
26
+ expect { my.methods.ai(plain: true) }.not_to raise_error
27
+ end
28
+
29
+ it 'should handle a class defines its own #method method (ex. request.method)' do
30
+ class My
31
+ def method
32
+ 'POST'
33
+ end
34
+ end
35
+
36
+ my = My.new
37
+ expect { my.methods.ai(plain: true) }.not_to raise_error
38
+ end
39
+
40
+ describe 'should handle a class that defines its own #to_hash method' do
41
+ it 'that takes arguments' do
42
+ class My
43
+ def to_hash(a, b)
44
+ end
45
+ end
46
+
47
+ my = My.new
48
+ expect { my.ai(plain: true) }.not_to raise_error
49
+ end
50
+
51
+ it 'that returns nil' do
52
+ class My
53
+ def to_hash()
54
+ return nil
55
+ end
56
+ end
57
+
58
+ my = My.new
59
+ expect { my.ai(plain: true) }.not_to raise_error
60
+ end
61
+
62
+ it "that returns an object that doesn't support #keys" do
63
+ class My
64
+ def to_hash()
65
+ object = Object.new
66
+ object.define_singleton_method('[]') { return nil }
67
+
68
+ return object
69
+ end
70
+ end
71
+
72
+ my = My.new
73
+ expect { my.ai(plain: true) }.not_to raise_error
74
+ end
75
+
76
+ it "that returns an object that doesn't support subscripting" do
77
+ class My
78
+ def to_hash()
79
+ object = Object.new
80
+ object.define_singleton_method(:keys) { return [:foo] }
81
+
82
+ return object
83
+ end
84
+ end
85
+
86
+ my = My.new
87
+ expect { my.ai(plain: true) }.not_to raise_error
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,43 @@
1
+ require_relative '../spec_helper'
2
+
3
+ RSpec.describe 'AwesomePrint' do
4
+
5
+ describe 'File' do
6
+ it 'should display a file (plain)' do
7
+ File.open(__FILE__, 'r') do |f|
8
+ expect(f.ai(plain: true)).to eq("#{f.inspect}\n" << `ls -alF #{f.path}`.chop)
9
+ end
10
+ end
11
+ end
12
+
13
+ describe 'Dir' do
14
+ it 'should display a direcory (plain)' do
15
+ Dir.open(File.dirname(__FILE__)) do |d|
16
+ expect(d.ai(plain: true)).to eq("#{d.inspect}\n" << `ls -alF #{d.path}`.chop)
17
+ end
18
+ end
19
+ end
20
+
21
+ describe 'Inherited from standard Ruby classes' do
22
+ after do
23
+ Object.instance_eval { remove_const :My } if defined?(My)
24
+ end
25
+
26
+ it 'inherited from File should be displayed as File' do
27
+ class My < File; end
28
+
29
+ my = File.new('/dev/null') rescue File.new('nul')
30
+ expect(my.ai(plain: true)).to eq("#{my.inspect}\n" << `ls -alF #{my.path}`.chop)
31
+ end
32
+
33
+ it 'inherited from Dir should be displayed as Dir' do
34
+ class My < Dir; end
35
+
36
+ require 'tmpdir'
37
+ my = My.new(Dir.tmpdir)
38
+
39
+ expect(my.ai(plain: true)).to eq("#{my.inspect}\n" << `ls -alF #{my.path}`.chop)
40
+ end
41
+
42
+ end
43
+ end
@@ -21,11 +21,7 @@ RSpec.describe 'AwesomePrint/ActiveRecord', skip: -> { !ExtVerifier.has_rails? }
21
21
  :rank => 1
22
22
  }
23
23
  EOS
24
-
25
- expect(RUBY_VERSION).to be >= '2.5'
26
-
27
24
  str.sub!('?', '1992-10-10 12:30:00 UTC')
28
-
29
25
  expect(out).to be_similar_to(str)
30
26
  end
31
27
 
@@ -49,10 +45,8 @@ RSpec.describe 'AwesomePrint/ActiveRecord', skip: -> { !ExtVerifier.has_rails? }
49
45
  }
50
46
  ]
51
47
  EOS
52
-
53
48
  str.sub!('??', '1992-10-10 12:30:00 UTC')
54
49
  str.sub!('?!', '2003-05-26 14:15:00 UTC')
55
-
56
50
  expect(out).to be_similar_to(str)
57
51
  end
58
52
 
@@ -78,10 +72,8 @@ RSpec.describe 'AwesomePrint/ActiveRecord', skip: -> { !ExtVerifier.has_rails? }
78
72
  }
79
73
  ]
80
74
  EOS
81
-
82
75
  str.sub!('??', '1992-10-10 12:30:00 UTC')
83
76
  str.sub!('?!', '2003-05-26 14:15:00 UTC')
84
-
85
77
  expect(out).to be_similar_to(str)
86
78
  end
87
79
  end
@@ -120,24 +112,12 @@ EOS
120
112
  out = @ap.awesome(@diana)
121
113
 
122
114
  raw_object_string =
123
- if activerecord_6_1?
124
- ActiveRecordData.raw_6_1_diana
125
- elsif activerecord_6_0?
126
- ActiveRecordData.raw_6_0_diana
127
- elsif activerecord_5_2?
115
+ if activerecord_5_2?
128
116
  ActiveRecordData.raw_5_2_diana
129
117
  elsif activerecord_5_1?
130
118
  ActiveRecordData.raw_5_1_diana
131
119
  elsif activerecord_5_0?
132
120
  ActiveRecordData.raw_5_0_diana
133
- elsif activerecord_4_2?
134
- ActiveRecordData.raw_4_2_diana
135
- elsif activerecord_4_1?
136
- ActiveRecordData.raw_4_1_diana
137
- elsif activerecord_4_0?
138
- ActiveRecordData.raw_4_0_diana
139
- elsif activerecord_3_2?
140
- ActiveRecordData.raw_3_2_diana
141
121
  end
142
122
  raw_object_string.sub!('?', '1992-10-10 12:30:00')
143
123
  expect(out).to be_similar_to(raw_object_string)
@@ -147,27 +127,16 @@ EOS
147
127
  out = @ap.awesome([@diana, @laura])
148
128
 
149
129
  raw_object_string =
150
- if activerecord_6_1?
151
- ActiveRecordData.raw_6_1_multi
152
- elsif activerecord_6_0?
153
- ActiveRecordData.raw_6_0_multi
154
- elsif activerecord_5_2?
130
+ if activerecord_5_2?
155
131
  ActiveRecordData.raw_5_2_multi
156
132
  elsif activerecord_5_1?
157
133
  ActiveRecordData.raw_5_1_multi
158
134
  elsif activerecord_5_0?
159
135
  ActiveRecordData.raw_5_0_multi
160
- elsif activerecord_4_2?
161
- ActiveRecordData.raw_4_2_multi
162
- elsif activerecord_4_1?
163
- ActiveRecordData.raw_4_1_multi
164
- elsif activerecord_4_0?
165
- ActiveRecordData.raw_4_0_multi
166
- elsif activerecord_3_2?
167
- ActiveRecordData.raw_3_2_multi
168
136
  end
169
137
  raw_object_string.sub!('?', '1992-10-10 12:30:00')
170
138
  raw_object_string.sub!('?', '2003-05-26 14:15:00')
139
+
171
140
  expect(out).to be_similar_to(raw_object_string)
172
141
  end
173
142
  end
@@ -218,43 +187,30 @@ class SubUser < User {
218
187
  # spec 1
219
188
  out = @ap.awesome(User.methods.grep(/first/))
220
189
 
221
- if RUBY_VERSION >= '3.0.0'
222
- expect(out).to match(/\sfirst\(\*\*,\s&&\)/)
223
- elsif RUBY_VERSION >= '2.7.0'
224
- if ActiveRecord::VERSION::STRING >= '3.2'
225
- expect(out).to match(/\sfirst\(\*\*,\s&&\)\s+User/)
226
- else
227
- expect(out).to match(/\sfirst\(\*\*,\s&&\)\s+User \(ActiveRecord::Base\)/)
228
- end
190
+ if RUBY_VERSION >= '2.4.4'
191
+ expect(out).to match(/\sfirst\(\*arg.*?\)\s+User/)
229
192
  else
230
- if ActiveRecord::VERSION::STRING >= '3.2'
231
- expect(out).to match(/\sfirst\(\*arg.*?\)\s+User/)
232
- else
233
- expect(out).to match(/\sfirst\(\*arg.*?\)\s+User \(ActiveRecord::Base\)/)
234
- end
193
+ expect(out).to match(/\sfirst\(\*args,\s&block\)\s+Class \(ActiveRecord::Querying\)/)
235
194
  end
236
195
 
237
196
  # spec 2
238
197
  out = @ap.awesome(User.methods.grep(/primary_key/))
239
- if RUBY_VERSION >= '3.0.0'
240
- expect(out).to match(/\sprimary_key\(.*?\)/)
241
- else
198
+
199
+ if RUBY_VERSION >= '2.4.4'
242
200
  expect(out).to match(/\sprimary_key\(.*?\)\s+User/)
201
+ else
202
+ expect(out).to match(/\sprimary_key\(.*?\)\s+Class \(ActiveRecord::AttributeMethods::PrimaryKey::ClassMethods\)/)
243
203
  end
244
204
 
245
205
  # spec 3
246
206
  out = @ap.awesome(User.methods.grep(/validate/))
247
- if ActiveRecord::VERSION::MAJOR < 3
248
- expect(out).to match(/\svalidate\(\*arg.*?\)\s+User \(ActiveRecord::Base\)/)
207
+
208
+ if RUBY_VERSION >= '2.4.4'
209
+ expect(out).to match(/\svalidate\(\*arg.*?\)\s+User/)
249
210
  else
250
- if RUBY_VERSION >= '3.0.0'
251
- expect(out).to match(/\svalidate\(\*arg.*?\)/)
252
- else
253
- expect(out).to match(/\svalidate\(\*arg.*?\)\s+User/)
254
- end
211
+ expect(out).to match(/\svalidate\(\*arg.*?\)\s+Class \(ActiveModel::Validations::ClassMethods\)/)
255
212
  end
256
213
 
257
214
  end
258
215
  end
259
216
  end
260
-
@@ -8,18 +8,9 @@ RSpec.describe 'AwesomePrint::ActiveSupport', skip: -> { !ExtVerifier.has_rails?
8
8
  it 'should format ActiveSupport::TimeWithZone as regular Time' do
9
9
  Time.zone = 'Eastern Time (US & Canada)'
10
10
  time = Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone
11
- if activerecord_6_1?
12
- expect(@ap.send(:awesome, time)).to eq("\e[0;32mSat, 10 Feb 2007 15:30:45.000000000 EST -05:00\e[0m")
13
- else
14
- expect(@ap.send(:awesome, time)).to eq("\e[0;32mSat, 10 Feb 2007 15:30:45 EST -05:00\e[0m")
15
- end
11
+ expect(@ap.send(:awesome, time)).to eq("\e[0;32mSat, 10 Feb 2007 15:30:45 EST -05:00\e[0m")
16
12
  end
17
-
18
- it 'should format HashWithIndifferentAccess as regular Hash' do
19
- hash = HashWithIndifferentAccess.new({ hello: 'world' })
20
- expect(@ap.send(:awesome, hash)).to eq("{\n \"hello\"\e[0;37m => \e[0m\e[0;33m\"world\"\e[0m\n}")
21
- end
22
-
13
+ #
23
14
  # ActiveSupport sticks in instance variables to the date object. Make sure
24
15
  # we ignore that and format Date instance as regular date.
25
16
  it 'should formate Date object as date' do
@@ -27,4 +18,9 @@ RSpec.describe 'AwesomePrint::ActiveSupport', skip: -> { !ExtVerifier.has_rails?
27
18
  expect(date.ai(plain: true)).to eq('Mon, 26 May 2003')
28
19
  expect(date.ai).to eq("\e[0;32mMon, 26 May 2003\e[0m")
29
20
  end
21
+
22
+ it 'should format HashWithIndifferentAccess as regular Hash' do
23
+ hash = HashWithIndifferentAccess.new({ hello: 'world' })
24
+ expect(@ap.send(:awesome, hash)).to eq("{\n \"hello\"\e[0;37m => \e[0m\e[0;33m\"world\"\e[0m\n}")
25
+ end
30
26
  end
@@ -40,7 +40,7 @@ RSpec.describe 'AwesomePrint/Mongoid', skip: -> { !ExtVerifier.has_mongoid? }.ca
40
40
  it 'should print the class' do
41
41
  class_spec = <<-EOS.strip
42
42
  class MongoUser < Object {
43
- :_id => :"bson/object_id",
43
+ :_id => :bson/object_id,
44
44
  :first_name => :string,
45
45
  :last_name => :string
46
46
  }
@@ -57,7 +57,7 @@ class MongoUser < Object {
57
57
 
58
58
  class_spec = <<-EOS.strip
59
59
  class Chamelion < Object {
60
- :_id => :"bson/object_id",
60
+ :_id => :bson/object_id,
61
61
  :last_attribute => :object
62
62
  }
63
63
  EOS
File without changes
@@ -0,0 +1,284 @@
1
+ require_relative '../spec_helper'
2
+
3
+ RSpec.describe 'AwesomePrint' do
4
+
5
+ #------------------------------------------------------------------------------
6
+ describe 'Limited Output Hash' do
7
+ before(:each) do
8
+ @hash = ('a'..'z').inject({}) { |h, v| h.merge({ v => v.to_sym }) }
9
+ end
10
+
11
+ it 'plain limited output' do
12
+ expect(@hash.ai(sort_keys: true, plain: true, limit: true)).to eq <<-EOS.strip
13
+ {
14
+ "a" => :a,
15
+ "b" => :b,
16
+ "c" => :c,
17
+ "d" => :d .. "w" => :w,
18
+ "x" => :x,
19
+ "y" => :y,
20
+ "z" => :z
21
+ }
22
+ EOS
23
+ end
24
+ end
25
+
26
+ #------------------------------------------------------------------------------
27
+ describe 'Hash' do
28
+ before do
29
+ @hash = { 1 => { sym: { 'str' => { [1, 2, 3] => { { k: :v } => Hash } } } } }
30
+ end
31
+
32
+ it 'empty hash' do
33
+ expect({}.ai).to eq('{}')
34
+ end
35
+
36
+ it 'plain multiline' do
37
+ expect(@hash.ai(plain: true)).to eq <<-EOS.strip
38
+ {
39
+ 1 => {
40
+ :sym => {
41
+ "str" => {
42
+ [ 1, 2, 3 ] => {
43
+ { :k => :v } => Hash < Object
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
49
+ EOS
50
+ end
51
+
52
+ it 'new hash syntax' do
53
+ expect(@hash.ai(plain: true, ruby19_syntax: true)).to eq <<-EOS.strip
54
+ {
55
+ 1 => {
56
+ sym: {
57
+ "str" => {
58
+ [ 1, 2, 3 ] => {
59
+ { k: :v } => Hash < Object
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
65
+ EOS
66
+ end
67
+
68
+ it 'plain multiline indented' do
69
+ expect(@hash.ai(plain: true, indent: 1)).to eq <<-EOS.strip
70
+ {
71
+ 1 => {
72
+ :sym => {
73
+ "str" => {
74
+ [ 1, 2, 3 ] => {
75
+ { :k => :v } => Hash < Object
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+ EOS
82
+ end
83
+
84
+ it 'plain single line' do
85
+ expect(@hash.ai(plain: true, multiline: false)).to eq('{ 1 => { :sym => { "str" => { [ 1, 2, 3 ] => { { :k => :v } => Hash < Object } } } } }')
86
+ end
87
+
88
+ it 'colored multiline (default)' do
89
+ expect(@hash.ai).to eq <<-EOS.strip
90
+ {
91
+ 1\e[0;37m => \e[0m{
92
+ :sym\e[0;37m => \e[0m{
93
+ \"str\"\e[0;37m => \e[0m{
94
+ [ 1, 2, 3 ]\e[0;37m => \e[0m{
95
+ { :k => :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m
96
+ }
97
+ }
98
+ }
99
+ }
100
+ }
101
+ EOS
102
+ end
103
+
104
+ it 'colored with new hash syntax' do
105
+ expect(@hash.ai(ruby19_syntax: true)).to eq <<-EOS.strip
106
+ {
107
+ 1\e[0;37m => \e[0m{
108
+ sym\e[0;37m: \e[0m{
109
+ \"str\"\e[0;37m => \e[0m{
110
+ [ 1, 2, 3 ]\e[0;37m => \e[0m{
111
+ { k: :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ EOS
118
+ end
119
+
120
+ it 'colored multiline indented' do
121
+ expect(@hash.ai(indent: 2)).to eq <<-EOS.strip
122
+ {
123
+ 1\e[0;37m => \e[0m{
124
+ :sym\e[0;37m => \e[0m{
125
+ \"str\"\e[0;37m => \e[0m{
126
+ [ 1, 2, 3 ]\e[0;37m => \e[0m{
127
+ { :k => :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m
128
+ }
129
+ }
130
+ }
131
+ }
132
+ }
133
+ EOS
134
+ end
135
+
136
+ it 'colored single line' do
137
+ 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 } } } } }")
138
+ end
139
+
140
+ end
141
+
142
+ #------------------------------------------------------------------------------
143
+ describe 'Nested Hash' do
144
+ before do
145
+ @hash = {}
146
+ @hash[:a] = @hash
147
+ end
148
+
149
+ it 'plain multiline' do
150
+ expect(@hash.ai(plain: true)).to eq <<-EOS.strip
151
+ {
152
+ :a => {...}
153
+ }
154
+ EOS
155
+ end
156
+
157
+ it 'plain single line' do
158
+ expect(@hash.ai(plain: true, multiline: false)).to eq('{ :a => {...} }')
159
+ end
160
+ end
161
+
162
+ #------------------------------------------------------------------------------
163
+ describe 'Hash with several keys' do
164
+ before do
165
+ @hash = { 'b' => 'b', :a => 'a', :z => 'z', 'alpha' => 'alpha' }
166
+ end
167
+
168
+ it 'plain multiline' do
169
+ out = @hash.ai(plain: true)
170
+ if RUBY_VERSION.to_f < 1.9 # Order of @hash keys is not guaranteed.
171
+ expect(out).to match(/^\{[^\}]+\}/m)
172
+ expect(out).to match(/ "b" => "b",?/)
173
+ expect(out).to match(/ :a => "a",?/)
174
+ expect(out).to match(/ :z => "z",?/)
175
+ expect(out).to match(/ "alpha" => "alpha",?$/)
176
+ else
177
+ expect(out).to eq <<-EOS.strip
178
+ {
179
+ "b" => "b",
180
+ :a => "a",
181
+ :z => "z",
182
+ "alpha" => "alpha"
183
+ }
184
+ EOS
185
+ end
186
+ end
187
+
188
+ it 'plain multiline with sorted keys' do
189
+ expect(@hash.ai(plain: true, sort_keys: true)).to eq <<-EOS.strip
190
+ {
191
+ :a => "a",
192
+ "alpha" => "alpha",
193
+ "b" => "b",
194
+ :z => "z"
195
+ }
196
+ EOS
197
+ end
198
+
199
+ end
200
+
201
+ #------------------------------------------------------------------------------
202
+ describe 'Negative options[:indent]' do
203
+ #
204
+ # With Ruby < 1.9 the order of hash keys is not defined so we can't
205
+ # reliably compare the output string.
206
+ #
207
+ it 'hash keys must be left aligned' do
208
+ hash = { [0, 0, 255] => :yellow, :red => 'rgb(255, 0, 0)', 'magenta' => 'rgb(255, 0, 255)' }
209
+ out = hash.ai(plain: true, indent: -4, sort_keys: true)
210
+ expect(out).to eq <<-EOS.strip
211
+ {
212
+ [ 0, 0, 255 ] => :yellow,
213
+ "magenta" => "rgb(255, 0, 255)",
214
+ :red => "rgb(255, 0, 0)"
215
+ }
216
+ EOS
217
+ end
218
+
219
+ it 'nested hash keys should be indented (array of hashes)' do
220
+ arr = [{ a: 1, bb: 22, ccc: 333 }, { 1 => :a, 22 => :bb, 333 => :ccc }]
221
+ out = arr.ai(plain: true, indent: -4, sort_keys: true)
222
+ expect(out).to eq <<-EOS.strip
223
+ [
224
+ [0] {
225
+ :a => 1,
226
+ :bb => 22,
227
+ :ccc => 333
228
+ },
229
+ [1] {
230
+ 1 => :a,
231
+ 22 => :bb,
232
+ 333 => :ccc
233
+ }
234
+ ]
235
+ EOS
236
+ end
237
+
238
+ it 'nested hash keys should be indented (hash of hashes)' do
239
+ arr = { first: { a: 1, bb: 22, ccc: 333 }, second: { 1 => :a, 22 => :bb, 333 => :ccc } }
240
+ out = arr.ai(plain: true, indent: -4, sort_keys: true)
241
+ expect(out).to eq <<-EOS.strip
242
+ {
243
+ :first => {
244
+ :a => 1,
245
+ :bb => 22,
246
+ :ccc => 333
247
+ },
248
+ :second => {
249
+ 1 => :a,
250
+ 22 => :bb,
251
+ 333 => :ccc
252
+ }
253
+ }
254
+ EOS
255
+ end
256
+ end
257
+
258
+ #------------------------------------------------------------------------------
259
+ describe 'Inherited from standard Ruby classes' do
260
+ after do
261
+ Object.instance_eval { remove_const :My } if defined?(My)
262
+ end
263
+
264
+ it 'inherited from Hash should be displayed as Hash' do
265
+ class My < Hash; end
266
+
267
+ my = My[{ 1 => { sym: { 'str' => { [1, 2, 3] => { { k: :v } => Hash } } } } }]
268
+ expect(my.ai(plain: true)).to eq <<-EOS.strip
269
+ {
270
+ 1 => {
271
+ :sym => {
272
+ "str" => {
273
+ [ 1, 2, 3 ] => {
274
+ { :k => :v } => Hash < Object
275
+ }
276
+ }
277
+ }
278
+ }
279
+ }
280
+ EOS
281
+ end
282
+
283
+ end
284
+ end