awesome_print 1.9.2 → 2.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
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