percent 0.0.1
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.
- checksums.yaml +7 -0
- data/lib/percent.rb +9 -0
- data/lib/percent/active_model/percentage_validator.rb +11 -0
- data/lib/percent/active_record/migration_extensions/options.rb +21 -0
- data/lib/percent/active_record/migration_extensions/schema_statements.rb +18 -0
- data/lib/percent/active_record/migration_extensions/table.rb +18 -0
- data/lib/percent/active_record/percentizable.rb +71 -0
- data/lib/percent/hooks.rb +18 -0
- data/lib/percent/railtie.rb +7 -0
- data/lib/percentage.rb +127 -0
- data/percent.gemspec +25 -0
- data/spec/lib/percent/active_record/migration_extensions/schema_statements_spec.rb +73 -0
- data/spec/lib/percent/active_record/migration_extensions/table_spec.rb +74 -0
- data/spec/lib/percent/active_record/percentizable_spec.rb +350 -0
- data/spec/lib/percentage_spec.rb +719 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/models.rb +18 -0
- data/spec/support/schema.rb +17 -0
- metadata +152 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
if defined? ActiveRecord
|
|
4
|
+
describe Percent::ActiveRecord::Percentizable do
|
|
5
|
+
describe '#percentize' do
|
|
6
|
+
shared_examples_for 'Survey methods' do
|
|
7
|
+
it { is_expected.to respond_to(:percent_complete) }
|
|
8
|
+
it { is_expected.to respond_to(:percent_complete=) }
|
|
9
|
+
it { is_expected.to respond_to(:non_fraction_ending_percent) }
|
|
10
|
+
it { is_expected.to respond_to(:non_fraction_ending_percent=) }
|
|
11
|
+
it { is_expected.to respond_to(:percent) }
|
|
12
|
+
it { is_expected.to respond_to(:percent=) }
|
|
13
|
+
it { is_expected.to respond_to(:optional) }
|
|
14
|
+
it { is_expected.to respond_to(:optional=) }
|
|
15
|
+
it { is_expected.to respond_to(:sans_validation) }
|
|
16
|
+
it { is_expected.to respond_to(:sans_validation=) }
|
|
17
|
+
it { is_expected.to respond_to(:sans_frac_validate) }
|
|
18
|
+
it { is_expected.to respond_to(:sans_frac_validate=) }
|
|
19
|
+
it { is_expected.to respond_to(:in_a_weird_range) }
|
|
20
|
+
it { is_expected.to respond_to(:in_a_weird_range=) }
|
|
21
|
+
it { is_expected.to respond_to(:in_fraction_range) }
|
|
22
|
+
it { is_expected.to respond_to(:in_fraction_range=) }
|
|
23
|
+
it { is_expected.to respond_to(:first_percent) }
|
|
24
|
+
it { is_expected.to respond_to(:first_percent=) }
|
|
25
|
+
it { is_expected.to respond_to(:second_percent) }
|
|
26
|
+
it { is_expected.to respond_to(:second_percent=) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
let (:subject) do
|
|
30
|
+
Survey.create percent_complete_fraction: 0.1,
|
|
31
|
+
non_fraction_ending: 0.2,
|
|
32
|
+
as_option_percent_fraction: 0.3,
|
|
33
|
+
optional_fraction: 0.4,
|
|
34
|
+
sans_validation_fraction: 0.5,
|
|
35
|
+
sans_frac_validate_fraction: 0.6,
|
|
36
|
+
in_a_weird_range_fraction: 0.7,
|
|
37
|
+
in_fraction_range_fraction: 0.8,
|
|
38
|
+
first_percent_fraction: 0.9,
|
|
39
|
+
second_percent_fraction: 1.0
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe 'methods' do
|
|
43
|
+
it_should_behave_like 'Survey methods'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'inherited class instance' do
|
|
47
|
+
let (:subject) { InheritedPercentizeSurvey.new }
|
|
48
|
+
it_should_behave_like 'Survey methods'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe 'percentized attribute getter' do
|
|
52
|
+
it 'attaches a Percentage object to model field' do
|
|
53
|
+
expect(subject.percent_complete).to be_an_instance_of Percentage
|
|
54
|
+
expect(subject.non_fraction_ending_percent).to be_an_instance_of Percentage
|
|
55
|
+
expect(subject.percent).to be_an_instance_of Percentage
|
|
56
|
+
expect(subject.optional).to be_an_instance_of Percentage
|
|
57
|
+
expect(subject.sans_validation).to be_an_instance_of Percentage
|
|
58
|
+
expect(subject.sans_frac_validate).to be_an_instance_of Percentage
|
|
59
|
+
expect(subject.in_a_weird_range).to be_an_instance_of Percentage
|
|
60
|
+
expect(subject.in_fraction_range).to be_an_instance_of Percentage
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'attaches a Percentage object to multiple model fields' do
|
|
64
|
+
expect(subject.first_percent).to be_an_instance_of Percentage
|
|
65
|
+
expect(subject.second_percent).to be_an_instance_of Percentage
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'returns the expected percentage amount as a Percentage object' do
|
|
69
|
+
expect(subject.percent_complete).to eql Percentage.new(10)
|
|
70
|
+
expect(subject.non_fraction_ending_percent).to eql Percentage.new(20)
|
|
71
|
+
expect(subject.percent).to eql Percentage.new(30)
|
|
72
|
+
expect(subject.optional).to eql Percentage.new(40)
|
|
73
|
+
expect(subject.sans_validation).to eql Percentage.new(50)
|
|
74
|
+
expect(subject.sans_frac_validate).to eql Percentage.new(60)
|
|
75
|
+
expect(subject.in_a_weird_range).to eql Percentage.new(70)
|
|
76
|
+
expect(subject.in_fraction_range).to eql Percentage.new(80)
|
|
77
|
+
expect(subject.first_percent).to eql Percentage.new(90)
|
|
78
|
+
expect(subject.second_percent).to eql Percentage.new(100)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
describe 'percentized attribute setter' do
|
|
83
|
+
context 'assign value to percentized attribute' do
|
|
84
|
+
it 'assigns the correct value from a Percentage object' do
|
|
85
|
+
subject.percent_complete = Percentage.new(0)
|
|
86
|
+
expect(subject.save).to be_truthy
|
|
87
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new(0)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'assigns the correct value from an integer' do
|
|
91
|
+
subject.percent_complete = 10
|
|
92
|
+
expect(subject.save).to be_truthy
|
|
93
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.1')
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'assigns the correct value from a complex number' do
|
|
97
|
+
subject.percent_complete = Complex(20,0)
|
|
98
|
+
expect(subject.save).to be_truthy
|
|
99
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.2')
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'assigns the correct value from a decimal' do
|
|
103
|
+
subject.percent_complete = BigDecimal.new(30)
|
|
104
|
+
expect(subject.save).to be_truthy
|
|
105
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.3')
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it 'assigns the correct value from a float' do
|
|
109
|
+
subject.percent_complete = 40.0
|
|
110
|
+
expect(subject.save).to be_truthy
|
|
111
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.4')
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'assigns the correct value from a rational number' do
|
|
115
|
+
subject.percent_complete = Rational(100,2)
|
|
116
|
+
expect(subject.save).to be_truthy
|
|
117
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.5')
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'assigns the correct value from a string with value "60"' do
|
|
121
|
+
subject.percent_complete = '60'
|
|
122
|
+
expect(subject.save).to be_truthy
|
|
123
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.6')
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'assigns the correct value from a string with value "70.0"' do
|
|
127
|
+
subject.percent_complete = '70.0'
|
|
128
|
+
expect(subject.save).to be_truthy
|
|
129
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.7')
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it 'assigns the correct value from a string with value "0.8E2"' do
|
|
133
|
+
subject.percent_complete = '0.8E2'
|
|
134
|
+
expect(subject.save).to be_truthy
|
|
135
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.8')
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'assigns the correct value from a string with value "810/9"' do
|
|
139
|
+
subject.percent_complete = '810/9'
|
|
140
|
+
expect(subject.save).to be_truthy
|
|
141
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.9')
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'assigns the correct value from a string with value "100%"' do
|
|
145
|
+
subject.percent_complete = '100%'
|
|
146
|
+
expect(subject.save).to be_truthy
|
|
147
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new(1)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
context 'assign value to percentized attribute on create' do
|
|
152
|
+
it 'assigns the correct value from a Percentage object' do
|
|
153
|
+
subject = Survey.create percent_complete: 15.0,
|
|
154
|
+
non_fraction_ending_percent: 0,
|
|
155
|
+
percent: 0,
|
|
156
|
+
sans_frac_validate: 0
|
|
157
|
+
expect(subject.valid?).to be_truthy
|
|
158
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.15')
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it 'assigns the correct value from a number' do
|
|
162
|
+
subject = Survey.create percent_complete: 35.0,
|
|
163
|
+
non_fraction_ending_percent: 0,
|
|
164
|
+
percent: 0,
|
|
165
|
+
sans_frac_validate: 0
|
|
166
|
+
expect(subject.valid?).to be_truthy
|
|
167
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.35')
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it 'assigns the correct value from a string' do
|
|
171
|
+
subject = Survey.create percent_complete: '55',
|
|
172
|
+
non_fraction_ending_percent: 0,
|
|
173
|
+
percent: 0,
|
|
174
|
+
sans_frac_validate: 0
|
|
175
|
+
expect(subject.valid?).to be_truthy
|
|
176
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.55')
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
context 'assign value to percentized attribute on update' do
|
|
181
|
+
it 'assigns the correct value from a Percentage object' do
|
|
182
|
+
expect(subject.update_attributes percent_complete: Percentage.new(25)).to be_truthy
|
|
183
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.25')
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it 'assigns the correct value from a number' do
|
|
187
|
+
expect(subject.update_attributes percent_complete: 45.0).to be_truthy
|
|
188
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.45')
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it 'assigns the correct value from a string' do
|
|
192
|
+
expect(subject.update_attributes percent_complete: '65').to be_truthy
|
|
193
|
+
expect(subject.percent_complete_fraction).to eql BigDecimal.new('0.65')
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
describe 'numericality validation' do
|
|
199
|
+
context 'when no validation options are passed' do
|
|
200
|
+
it 'ensures that the percentage can not be nil' do
|
|
201
|
+
subject.percent_complete = nil
|
|
202
|
+
expect(subject).to_not be_valid
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it 'ensures that the percentage is between 0 and 100' do
|
|
206
|
+
subject.percent_complete = true
|
|
207
|
+
expect(subject).to be_valid
|
|
208
|
+
|
|
209
|
+
subject.percent_complete = false
|
|
210
|
+
expect(subject).to be_valid
|
|
211
|
+
|
|
212
|
+
subject.percent_complete = -1
|
|
213
|
+
expect(subject).to_not be_valid
|
|
214
|
+
|
|
215
|
+
subject.percent_complete = 101
|
|
216
|
+
expect(subject).to_not be_valid
|
|
217
|
+
|
|
218
|
+
subject.percent_complete = 10
|
|
219
|
+
expect(subject).to be_valid
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
context 'when validation options are passed' do
|
|
224
|
+
it 'ensures that the percentage matches the given criteria' do
|
|
225
|
+
subject.in_a_weird_range = -10
|
|
226
|
+
expect(subject).to_not be_valid
|
|
227
|
+
|
|
228
|
+
subject.in_a_weird_range = 0
|
|
229
|
+
expect(subject).to be_valid
|
|
230
|
+
|
|
231
|
+
subject.in_a_weird_range = true
|
|
232
|
+
expect(subject).to be_valid
|
|
233
|
+
|
|
234
|
+
subject.in_a_weird_range = false
|
|
235
|
+
expect(subject).to be_valid
|
|
236
|
+
|
|
237
|
+
subject.in_a_weird_range = 200
|
|
238
|
+
expect(subject).to_not be_valid
|
|
239
|
+
|
|
240
|
+
subject.in_a_weird_range = 100
|
|
241
|
+
expect(subject).to be_valid
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
context 'when false is passed' do
|
|
246
|
+
it 'should not validate any values passed to the attribute' do
|
|
247
|
+
subject.sans_frac_validate_fraction = 'string'
|
|
248
|
+
expect(subject).to be_valid
|
|
249
|
+
|
|
250
|
+
subject.sans_frac_validate_fraction = false
|
|
251
|
+
expect(subject).to be_valid
|
|
252
|
+
|
|
253
|
+
subject.sans_frac_validate_fraction = true
|
|
254
|
+
expect(subject).to be_valid
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
describe 'fraction numericality validation' do
|
|
260
|
+
context 'when no validation options are passed' do
|
|
261
|
+
it 'ensures that the percentage fraction can not be nil' do
|
|
262
|
+
subject.percent_complete_fraction = nil
|
|
263
|
+
expect(subject).to_not be_valid
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
it 'ensures that the percentage fraction is between 0 and 1' do
|
|
267
|
+
subject.percent_complete_fraction = -0.01
|
|
268
|
+
expect(subject).to_not be_valid
|
|
269
|
+
|
|
270
|
+
subject.percent_complete_fraction = 1.01
|
|
271
|
+
expect(subject).to_not be_valid
|
|
272
|
+
|
|
273
|
+
subject.percent_complete_fraction = 0.1
|
|
274
|
+
expect(subject).to be_valid
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
context 'when validation options are passed' do
|
|
279
|
+
it 'ensures that the percentage matches the given criteria' do
|
|
280
|
+
subject.in_fraction_range_fraction = -0.1
|
|
281
|
+
expect(subject).to_not be_valid
|
|
282
|
+
|
|
283
|
+
subject.in_fraction_range_fraction = 0
|
|
284
|
+
expect(subject).to be_valid
|
|
285
|
+
|
|
286
|
+
subject.in_fraction_range_fraction = 2
|
|
287
|
+
expect(subject).to_not be_valid
|
|
288
|
+
|
|
289
|
+
subject.in_fraction_range_fraction = 1
|
|
290
|
+
expect(subject).to be_valid
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
describe 'allow nil validation' do
|
|
296
|
+
context 'when no validation is passed' do
|
|
297
|
+
it 'ensures that the percentage and percentage fraction can not be nil' do
|
|
298
|
+
subject.percent_complete_fraction = nil
|
|
299
|
+
expect(subject).to_not be_valid
|
|
300
|
+
subject.percent_complete = nil
|
|
301
|
+
expect(subject).to_not be_valid
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
context 'when false is passed' do
|
|
306
|
+
it 'ensures that the percentage and percentage fraction can not be nil' do
|
|
307
|
+
subject.percent_complete_fraction = nil
|
|
308
|
+
expect(subject).to_not be_valid
|
|
309
|
+
subject.percent_complete = nil
|
|
310
|
+
expect(subject).to_not be_valid
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
context 'when true is passed' do
|
|
315
|
+
it 'allows the percentage and percentage fraction to be nil' do
|
|
316
|
+
subject.optional_fraction = nil
|
|
317
|
+
expect(subject).to be_valid
|
|
318
|
+
subject.optional = nil
|
|
319
|
+
expect(subject).to be_valid
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
describe 'disable validation' do
|
|
325
|
+
context 'when disable validation is given a true value' do
|
|
326
|
+
it 'should allow any value' do
|
|
327
|
+
subject.sans_validation = nil
|
|
328
|
+
expect(subject).to be_valid
|
|
329
|
+
|
|
330
|
+
subject.sans_validation = 'string'
|
|
331
|
+
expect(subject).to be_valid
|
|
332
|
+
|
|
333
|
+
subject.sans_validation_fraction = nil
|
|
334
|
+
expect(subject).to be_valid
|
|
335
|
+
|
|
336
|
+
subject.sans_validation_fraction = 'string'
|
|
337
|
+
expect(subject).to be_valid
|
|
338
|
+
|
|
339
|
+
subject.sans_validation_fraction = false
|
|
340
|
+
expect(subject).to be_valid
|
|
341
|
+
|
|
342
|
+
subject.sans_validation_fraction = true
|
|
343
|
+
expect(subject).to be_valid
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
end
|
|
@@ -0,0 +1,719 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Percentage do
|
|
4
|
+
subject { Percentage.new value }
|
|
5
|
+
let (:value) { 0 }
|
|
6
|
+
|
|
7
|
+
describe 'methods' do
|
|
8
|
+
it { is_expected.to respond_to(:value) }
|
|
9
|
+
it { is_expected.to respond_to(:to_i) }
|
|
10
|
+
it { is_expected.to respond_to(:to_c) }
|
|
11
|
+
it { is_expected.to respond_to(:to_d) }
|
|
12
|
+
it { is_expected.to respond_to(:to_f) }
|
|
13
|
+
it { is_expected.to respond_to(:to_r) }
|
|
14
|
+
it { is_expected.to respond_to(:to_complex) }
|
|
15
|
+
it { is_expected.to respond_to(:to_decimal) }
|
|
16
|
+
it { is_expected.to respond_to(:to_float) }
|
|
17
|
+
it { is_expected.to respond_to(:to_rational) }
|
|
18
|
+
it { is_expected.to respond_to(:to_s) }
|
|
19
|
+
it { is_expected.to respond_to(:to_str) }
|
|
20
|
+
it { is_expected.to respond_to(:to_string) }
|
|
21
|
+
it { is_expected.to respond_to(:format) }
|
|
22
|
+
it { is_expected.to respond_to(:to_amount) }
|
|
23
|
+
it { is_expected.to respond_to(:inspect) }
|
|
24
|
+
it { is_expected.to respond_to(:==) }
|
|
25
|
+
it { is_expected.to respond_to(:eql?) }
|
|
26
|
+
it { is_expected.to respond_to(:<=>) }
|
|
27
|
+
it { is_expected.to respond_to(:+) }
|
|
28
|
+
it { is_expected.to respond_to(:-) }
|
|
29
|
+
it { is_expected.to respond_to(:/) }
|
|
30
|
+
it { is_expected.to respond_to(:*) }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe 'class methods' do
|
|
34
|
+
subject { Percentage }
|
|
35
|
+
|
|
36
|
+
it { is_expected.to respond_to(:from_fraction) }
|
|
37
|
+
it { is_expected.to respond_to(:from_amount) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'Initialization methods' do
|
|
41
|
+
shared_examples 'a percentage' do |amount|
|
|
42
|
+
let (:decimal_value) { amount.to_d / 100 }
|
|
43
|
+
let (:string_value) { "#{amount.to_f}%" }
|
|
44
|
+
|
|
45
|
+
it 'should equal the given percentage' do
|
|
46
|
+
expect(subject.value).to eql decimal_value
|
|
47
|
+
expect(subject.format).to eql string_value
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe '#initialize' do
|
|
52
|
+
context 'with value of 50' do
|
|
53
|
+
let (:value) { 50 }
|
|
54
|
+
it_should_behave_like 'a percentage', 50
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context 'with value of 0.5' do
|
|
58
|
+
let (:value) { 0.5 }
|
|
59
|
+
it_should_behave_like 'a percentage', 50
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context 'with a numeric value of 1/2' do
|
|
63
|
+
let (:value) { Rational 1, 2 }
|
|
64
|
+
it_should_behave_like 'a percentage', 50
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context 'with a numeric value of 0.5E0' do
|
|
68
|
+
let (:value) { BigDecimal.new '0.5' }
|
|
69
|
+
it_should_behave_like 'a percentage', 50
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context 'with a numeric value of 0.5+0i' do
|
|
73
|
+
let (:value) { Complex(0.5, 0) }
|
|
74
|
+
it_should_behave_like 'a percentage', 50
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context 'with a string value of "50"' do
|
|
78
|
+
let (:value) { '50' }
|
|
79
|
+
it_should_behave_like 'a percentage', 50
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context 'with a string value of "50%"' do
|
|
83
|
+
let (:value) { '50%' }
|
|
84
|
+
it_should_behave_like 'a percentage', 50
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
context 'with a string value of "50.0%"' do
|
|
88
|
+
let (:value) { '50.0%' }
|
|
89
|
+
it_should_behave_like 'a percentage', 50
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context 'with a string value of ".5"' do
|
|
93
|
+
let (:value) { '.5' }
|
|
94
|
+
it_should_behave_like 'a percentage', 50
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context 'with a string value of "0.5"' do
|
|
98
|
+
let (:value) { '0.5' }
|
|
99
|
+
it_should_behave_like 'a percentage', 50
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context 'with a string value of "0.5E0"' do
|
|
103
|
+
let (:value) { '0.5E0' }
|
|
104
|
+
it_should_behave_like 'a percentage', 50
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context 'with a string value of "1/2"' do
|
|
108
|
+
let (:value) { '1/2' }
|
|
109
|
+
it_should_behave_like 'a percentage', 50
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context 'with a boolean value of true' do
|
|
113
|
+
let (:value) { true }
|
|
114
|
+
it_should_behave_like 'a percentage', 100
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context 'with a boolean value of false' do
|
|
118
|
+
let (:value) { false }
|
|
119
|
+
it_should_behave_like 'a percentage', 0
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
describe '#self.from_fraction' do
|
|
124
|
+
let (:subject) { Percentage.from_fraction value }
|
|
125
|
+
|
|
126
|
+
context 'with a numeric value of 50.0' do
|
|
127
|
+
let (:value) { 50.0 }
|
|
128
|
+
it_should_behave_like 'a percentage', 5000
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
context 'with a numeric value of 50' do
|
|
132
|
+
let (:value) { 50 }
|
|
133
|
+
it_should_behave_like 'a percentage', 5000
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
context 'with a numeric value of 1' do
|
|
137
|
+
let (:value) { 1 }
|
|
138
|
+
it_should_behave_like 'a percentage', 100
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
context 'with a numeric value of 0' do
|
|
142
|
+
let (:value) { 0 }
|
|
143
|
+
it_should_behave_like 'a percentage', 0
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
context 'with a string value of "50.0"' do
|
|
147
|
+
let (:value) { '50.0' }
|
|
148
|
+
it_should_behave_like 'a percentage', 5000
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
context 'with a string value of "50"' do
|
|
152
|
+
let (:value) { '50' }
|
|
153
|
+
it_should_behave_like 'a percentage', 5000
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
context 'with a string value of "1"' do
|
|
157
|
+
let (:value) { '1' }
|
|
158
|
+
it_should_behave_like 'a percentage', 100
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
context 'with a string value of "0"' do
|
|
162
|
+
let (:value) { '0' }
|
|
163
|
+
it_should_behave_like 'a percentage', 0
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
describe '#self.from_amount' do
|
|
168
|
+
let (:subject) { Percentage.from_amount value }
|
|
169
|
+
|
|
170
|
+
context 'with a numeric value of 50' do
|
|
171
|
+
let (:value) { 50 }
|
|
172
|
+
it_should_behave_like 'a percentage', 50
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context 'with a numeric value of 50.0' do
|
|
176
|
+
let (:value) { 50.0 }
|
|
177
|
+
it_should_behave_like 'a percentage', 50
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
context 'with a numeric value of 0.5E2' do
|
|
181
|
+
let (:value) { BigDecimal.new 50 }
|
|
182
|
+
it_should_behave_like 'a percentage', 50
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
context 'with a numeric value of 100/2' do
|
|
186
|
+
let (:value) { Rational 100, 2 }
|
|
187
|
+
it_should_behave_like 'a percentage', 50
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
context 'with a string value of "50"' do
|
|
191
|
+
let (:value) { '50' }
|
|
192
|
+
it_should_behave_like 'a percentage', 50
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
context 'with a string value of "50.0"' do
|
|
196
|
+
let (:value) { '50.0' }
|
|
197
|
+
it_should_behave_like 'a percentage', 50
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
context 'with a string value of "0.5E2"' do
|
|
201
|
+
let (:value) { '0.5E2' }
|
|
202
|
+
it_should_behave_like 'a percentage', 50
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
context 'with a string value of "200/4"' do
|
|
206
|
+
let (:value) { '200/4' }
|
|
207
|
+
it_should_behave_like 'a percentage', 50
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
context 'Attributes' do
|
|
213
|
+
describe '#value' do
|
|
214
|
+
context 'when a value is passed to an initialization method' do
|
|
215
|
+
let (:value) { BigDecimal('1.5') }
|
|
216
|
+
|
|
217
|
+
it 'should return that value' do
|
|
218
|
+
expect(subject.value).to eql value
|
|
219
|
+
expect(Percentage.from_fraction(value).value).to eql value
|
|
220
|
+
expect(Percentage.from_amount(value * 100).value).to eql value
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
context 'when nothing is passed to an initialization method' do
|
|
225
|
+
it 'should return 0' do
|
|
226
|
+
expect(Percentage.new.value).to eql BigDecimal(0)
|
|
227
|
+
expect(Percentage.from_fraction.value).to eql BigDecimal(0)
|
|
228
|
+
expect(Percentage.from_amount.value).to eql BigDecimal(0)
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
context 'Conversions' do
|
|
235
|
+
let (:value) { 75 }
|
|
236
|
+
|
|
237
|
+
describe '#to_i' do
|
|
238
|
+
context 'with a numeric value of 75' do
|
|
239
|
+
it 'should return 75' do
|
|
240
|
+
expect(subject.to_i).to eql 75
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
describe '#to_c' do
|
|
246
|
+
context 'with a numeric value of 75' do
|
|
247
|
+
it 'should return 0.75E0+0i' do
|
|
248
|
+
expect(subject.to_c).to eql Complex(BigDecimal.new('0.75'), 0)
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
describe '#to_d' do
|
|
254
|
+
context 'with a numeric value of 75' do
|
|
255
|
+
it 'should return 0.75E0' do
|
|
256
|
+
expect(subject.to_d).to eql BigDecimal.new('0.75')
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
describe '#to_f' do
|
|
262
|
+
context 'with a numeric value of 75' do
|
|
263
|
+
it 'should return 0.75' do
|
|
264
|
+
expect(subject.to_f).to eql 0.75
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
describe '#to_r' do
|
|
270
|
+
context 'with a numeric value of 75' do
|
|
271
|
+
it 'should return 3/4' do
|
|
272
|
+
expect(subject.to_r).to eql Rational(3,4)
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
describe '#to_complex' do
|
|
278
|
+
context 'with a numeric value of 75' do
|
|
279
|
+
it 'should return 0.75E2+0i' do
|
|
280
|
+
expect(subject.to_complex).to eql Complex(BigDecimal.new(75), 0)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
describe '#to_decimal' do
|
|
286
|
+
context 'with a numeric value of 75' do
|
|
287
|
+
it 'should return 0.75E2' do
|
|
288
|
+
expect(subject.to_decimal).to eql BigDecimal(75)
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
describe '#to_float' do
|
|
294
|
+
context 'with a numeric value of 75' do
|
|
295
|
+
it 'should return 75.0' do
|
|
296
|
+
expect(subject.to_float).to eql 75.0
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
describe '#to_rational' do
|
|
302
|
+
context 'with a numeric value of 75' do
|
|
303
|
+
it 'should return 75/1' do
|
|
304
|
+
expect(subject.to_rational).to eql Rational(75,1)
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
describe '#to_s' do
|
|
310
|
+
context 'with a numeric value of 75' do
|
|
311
|
+
it 'should return "75"' do
|
|
312
|
+
expect(subject.to_s).to eql '75'
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
context 'with a numeric value of 0.75' do
|
|
317
|
+
let (:value) { 0.75 }
|
|
318
|
+
it 'should return "75"' do
|
|
319
|
+
expect(subject.to_s).to eql '75'
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
context 'with a numeric value of 0.755' do
|
|
324
|
+
let (:value) { 0.755 }
|
|
325
|
+
it 'should return "75.5"' do
|
|
326
|
+
expect(subject.to_s).to eql '75.5'
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
describe '#to_str' do
|
|
332
|
+
context 'with a numeric value of 75' do
|
|
333
|
+
it 'should return "0.75"' do
|
|
334
|
+
expect(subject.to_str).to eql '0.75'
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
describe '#to_string' do
|
|
340
|
+
context 'with a numeric value of 75' do
|
|
341
|
+
it 'should return "75%"' do
|
|
342
|
+
expect(subject.to_string).to eql '75%'
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
context 'with a numeric value of 0.75' do
|
|
347
|
+
let (:value) { 0.75 }
|
|
348
|
+
it 'should return "75%"' do
|
|
349
|
+
expect(subject.to_string).to eql '75%'
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
context 'with a numeric value of 0.755' do
|
|
354
|
+
let (:value) { 0.755 }
|
|
355
|
+
it 'should return "75.5%"' do
|
|
356
|
+
expect(subject.to_string).to eql '75.5%'
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
describe "#format" do
|
|
362
|
+
context 'with a value of 0.6666' do
|
|
363
|
+
let (:value) { 0.6666 }
|
|
364
|
+
|
|
365
|
+
context 'when passed no options' do
|
|
366
|
+
it 'should return "66.66%"' do
|
|
367
|
+
expect(subject.format).to eql '66.66%'
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
context 'when passed percent_sign: true' do
|
|
372
|
+
it 'should return "66.66%"' do
|
|
373
|
+
expect(subject.format percent_sign: true).to eql '66.66%'
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
context 'when passed percent_sign: false' do
|
|
378
|
+
it 'should return "66.66"' do
|
|
379
|
+
expect(subject.format percent_sign: false).to eql '66.66'
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
context 'when passed as_decimal: true' do
|
|
384
|
+
it 'should return "0.6666"' do
|
|
385
|
+
expect(subject.format as_decimal: true).to eql '0.6666'
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
context 'when passed rounded: true' do
|
|
390
|
+
it 'should return "67%"' do
|
|
391
|
+
expect(subject.format rounded: true).to eql '67%'
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
context 'when passed no_decimal: true' do
|
|
396
|
+
it 'should return "66%"' do
|
|
397
|
+
expect(subject.format no_decimal: true).to eql '66%'
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
context 'when passed no_decimal_if_whole: true' do
|
|
402
|
+
it 'should return "66.66%"' do
|
|
403
|
+
expect(subject.format no_decimal_if_whole: true).to eql '66.66%'
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
context 'when passed space_before_sign: true' do
|
|
408
|
+
it 'should return "66.66 %"' do
|
|
409
|
+
expect(subject.format space_before_sign: true).to eql '66.66 %'
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
context 'when passed percent_sign: false, rounded: true, space_before_sign: true' do
|
|
414
|
+
it 'should return "67 "' do
|
|
415
|
+
f = subject.format percent_sign: false, rounded: true, space_before_sign: true
|
|
416
|
+
expect(f).to eql '67 '
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
context 'when passed no_decimal: true, space_before_sign: true' do
|
|
421
|
+
it 'should return "66 %"' do
|
|
422
|
+
f = subject.format no_decimal: true, space_before_sign: true
|
|
423
|
+
expect(f).to eql '66 %'
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
context 'when passed percent_sign: false, as_decimal: true, no_decimal: true' do
|
|
428
|
+
it 'should return "0.6666"' do
|
|
429
|
+
f = subject.format percent_sign: false, as_decimal: true, no_decimal: true
|
|
430
|
+
expect(f).to eql '0.6666'
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
context 'when passed no_decimal_if_whole: true, no_decimal: true, rounded: true' do
|
|
435
|
+
it 'should return "67%"' do
|
|
436
|
+
f = subject.format no_decimal_if_whole: true, no_decimal: true, rounded: true
|
|
437
|
+
expect(f).to eql '67%'
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
context 'when passed no_decimal_if_whole: true, no_decimal: true' do
|
|
442
|
+
it 'should return "66%"' do
|
|
443
|
+
f = subject.format no_decimal_if_whole: true, no_decimal: true
|
|
444
|
+
expect(f).to eql '66%'
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
describe '#to_amount' do
|
|
451
|
+
context 'with a numeric value of 75' do
|
|
452
|
+
it 'should return 75' do
|
|
453
|
+
expect(subject.to_amount).to eql 75
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
context 'with a numeric value of 0.75' do
|
|
458
|
+
let (:value) { 0.75 }
|
|
459
|
+
it 'should return 75' do
|
|
460
|
+
expect(subject.to_amount).to eql 75
|
|
461
|
+
end
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
context 'with a numeric value of 0.755' do
|
|
465
|
+
let (:value) { 0.755 }
|
|
466
|
+
it 'should return 75.5' do
|
|
467
|
+
expect(subject.to_amount).to eql 75.5
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
context 'Comparisons' do
|
|
474
|
+
let (:value) { 100 }
|
|
475
|
+
let (:duplicate) { Percentage.new value }
|
|
476
|
+
let (:other) { Percentage.new 99 }
|
|
477
|
+
|
|
478
|
+
shared_examples_for 'full ==' do
|
|
479
|
+
it 'should equal a number with the same value' do
|
|
480
|
+
expect(equivalent == subject).to eql true
|
|
481
|
+
expect(equivalent >= subject).to eql true
|
|
482
|
+
expect(equivalent <= subject).to eql true
|
|
483
|
+
expect(equivalent != subject).to eql false
|
|
484
|
+
expect(equivalent > subject).to eql false
|
|
485
|
+
expect(equivalent < subject).to eql false
|
|
486
|
+
|
|
487
|
+
expect(subject == equivalent).to eql true
|
|
488
|
+
expect(subject >= equivalent).to eql true
|
|
489
|
+
expect(subject <= equivalent).to eql true
|
|
490
|
+
expect(subject != equivalent).to eql false
|
|
491
|
+
expect(subject > equivalent).to eql false
|
|
492
|
+
expect(subject < equivalent).to eql false
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
it 'should not equal a number with a different value' do
|
|
496
|
+
expect(subject == different).to eql false
|
|
497
|
+
expect(subject != different).to eql true
|
|
498
|
+
|
|
499
|
+
expect(different == subject).to eql false
|
|
500
|
+
expect(different != subject).to eql true
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
shared_examples_for 'comparisons' do
|
|
505
|
+
it 'should know when something is greater than' do
|
|
506
|
+
expect(subject > smaller).to be true
|
|
507
|
+
expect(subject > larger ).to be false
|
|
508
|
+
expect(smaller > subject).to be false
|
|
509
|
+
expect(larger > subject).to be true
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
it 'should know when something is less than' do
|
|
513
|
+
expect(subject < smaller).to be false
|
|
514
|
+
expect(subject < larger ).to be true
|
|
515
|
+
expect(smaller < subject).to be true
|
|
516
|
+
expect(larger < subject).to be false
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
it 'should know when something is greater than or equal to' do
|
|
520
|
+
expect(subject >= smaller).to be true
|
|
521
|
+
expect(subject >= larger ).to be false
|
|
522
|
+
expect(smaller >= subject).to be false
|
|
523
|
+
expect(larger >= subject).to be true
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
it 'should know when something is less than or equal to' do
|
|
527
|
+
expect(subject <= smaller).to be false
|
|
528
|
+
expect(subject <= larger ).to be true
|
|
529
|
+
expect(smaller <= subject).to be true
|
|
530
|
+
expect(larger <= subject).to be false
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
describe '#==' do
|
|
535
|
+
context 'comparing with percentage' do
|
|
536
|
+
it 'should equal itself' do
|
|
537
|
+
expect(subject == subject).to eql true
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
it 'should equal a different percentage object with the same value' do
|
|
541
|
+
expect(subject == duplicate).to eql true
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
it 'should not equal a different percentage' do
|
|
545
|
+
expect(subject == other).to eql false
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
context 'comparing with integer' do
|
|
550
|
+
let (:equivalent) { 1 }
|
|
551
|
+
let (:different) { 2 }
|
|
552
|
+
it_should_behave_like 'full =='
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
context 'comparing with complex' do
|
|
556
|
+
let (:equivalent) { Complex(1.0,0) }
|
|
557
|
+
let (:different) { Complex(1.00101,0) }
|
|
558
|
+
|
|
559
|
+
it 'should equal a number with the same value' do
|
|
560
|
+
expect(equivalent == subject).to eql true
|
|
561
|
+
expect(equivalent != subject).to eql false
|
|
562
|
+
|
|
563
|
+
expect(subject == equivalent).to eql true
|
|
564
|
+
expect(subject != equivalent).to eql false
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
it 'should not equal a number with a different value' do
|
|
568
|
+
expect(subject == different).to eql false
|
|
569
|
+
expect(subject != different).to eql true
|
|
570
|
+
|
|
571
|
+
expect(different == subject).to eql false
|
|
572
|
+
expect(different != subject).to eql true
|
|
573
|
+
end
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
context 'comparing with decimal' do
|
|
577
|
+
let (:equivalent) { BigDecimal.new(1) }
|
|
578
|
+
let (:different) { BigDecimal.new('.99') }
|
|
579
|
+
it_should_behave_like 'full =='
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
context 'comparing with float' do
|
|
583
|
+
let (:equivalent) { 1.0 }
|
|
584
|
+
let (:different) { 1.1010 }
|
|
585
|
+
it_should_behave_like 'full =='
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
context 'comparing with rational' do
|
|
589
|
+
let (:equivalent) { Rational(1) }
|
|
590
|
+
let (:different) { Rational(9,8) }
|
|
591
|
+
it_should_behave_like 'full =='
|
|
592
|
+
end
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
describe '#eql?' do
|
|
596
|
+
it 'should equal itself' do
|
|
597
|
+
expect(subject.eql? subject).to eql true
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
it 'should equal a different percentage object with the same value' do
|
|
601
|
+
expect(subject.eql? duplicate).to eql true
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
it 'should not equal a different percentage' do
|
|
605
|
+
expect(subject.eql? other).to eql false
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
it 'should not equal any other numbers with the same value' do
|
|
609
|
+
expect(subject.eql? 1).to eql false
|
|
610
|
+
expect(subject.eql? 1.0).to eql false
|
|
611
|
+
expect(subject.eql? Complex(1, 0)).to eql false
|
|
612
|
+
expect(subject.eql? Rational(1)).to eql false
|
|
613
|
+
expect(subject.eql? BigDecimal.new(1)).to eql false
|
|
614
|
+
end
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
describe 'comparable' do
|
|
618
|
+
it 'is comparable' do
|
|
619
|
+
expect(subject.is_a? Comparable).to be true
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
context 'compared to other percentages' do
|
|
623
|
+
let (:smaller) { other }
|
|
624
|
+
let (:larger) { Percentage.new 101 }
|
|
625
|
+
it_should_behave_like 'comparisons'
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
context 'compared to decimals' do
|
|
629
|
+
let (:smaller) { BigDecimal.new '0.999999' }
|
|
630
|
+
let (:larger) { BigDecimal.new '1.000001' }
|
|
631
|
+
it_should_behave_like 'comparisons'
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
context 'compared to floats' do
|
|
635
|
+
let (:smaller) { 0.999999 }
|
|
636
|
+
let (:larger) { 1.000001 }
|
|
637
|
+
it_should_behave_like 'comparisons'
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
context 'compared to integers' do
|
|
641
|
+
let (:smaller) { 0 }
|
|
642
|
+
let (:larger) { 2 }
|
|
643
|
+
it_should_behave_like 'comparisons'
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
context 'compared to rationals' do
|
|
647
|
+
let (:denominator) { 10 ** 10 }
|
|
648
|
+
let (:smaller) { Rational denominator - 1, denominator }
|
|
649
|
+
let (:larger) { Rational denominator + 1, denominator }
|
|
650
|
+
it_should_behave_like 'comparisons'
|
|
651
|
+
end
|
|
652
|
+
end
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
context 'Mathematical operations' do
|
|
656
|
+
let (:value) { 25 }
|
|
657
|
+
let (:number) { 10 }
|
|
658
|
+
|
|
659
|
+
describe '#+' do
|
|
660
|
+
context 'when adding two percentages' do
|
|
661
|
+
it 'should return the sum of the two percentages' do
|
|
662
|
+
expect(subject + subject).to eql Percentage.new(50)
|
|
663
|
+
end
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
context 'when adding a percent and a number' do
|
|
667
|
+
it 'should return sum of the two' do
|
|
668
|
+
expect(subject + number).to eq 10.25
|
|
669
|
+
expect(number + subject).to eq 10.25
|
|
670
|
+
end
|
|
671
|
+
end
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
describe '#-' do
|
|
675
|
+
context 'when subtracting two percentages' do
|
|
676
|
+
it 'should return the difference of the two percentages' do
|
|
677
|
+
expect(subject - subject).to eql Percentage.new(0)
|
|
678
|
+
end
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
context 'when subtracting a percent and a number' do
|
|
682
|
+
it 'should return the difference between the two' do
|
|
683
|
+
expect(subject - number).to eq -9.75
|
|
684
|
+
expect(number - subject).to eq 9.75
|
|
685
|
+
end
|
|
686
|
+
end
|
|
687
|
+
end
|
|
688
|
+
|
|
689
|
+
describe '#*' do
|
|
690
|
+
context 'when multiplying two percentagess' do
|
|
691
|
+
it 'should return the product of the two percentages' do
|
|
692
|
+
expect(subject * subject).to eql Percentage.from_amount(6.25)
|
|
693
|
+
end
|
|
694
|
+
end
|
|
695
|
+
|
|
696
|
+
context 'when multiplying a percent and a number' do
|
|
697
|
+
it 'should return the product of the two' do
|
|
698
|
+
expect(subject * number).to eq 2.5
|
|
699
|
+
expect(number * subject).to eq 2.5
|
|
700
|
+
end
|
|
701
|
+
end
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
describe '#/' do
|
|
705
|
+
context 'when dividing two percentages' do
|
|
706
|
+
it 'should return the quotient of the two percentages' do
|
|
707
|
+
expect(subject / subject).to eql Percentage.new(100)
|
|
708
|
+
end
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
context 'when subtracting a percent and a number' do
|
|
712
|
+
it 'should return the quotient' do
|
|
713
|
+
expect(subject / number).to eq 0.025
|
|
714
|
+
expect(number / subject).to eq 40.0
|
|
715
|
+
end
|
|
716
|
+
end
|
|
717
|
+
end
|
|
718
|
+
end
|
|
719
|
+
end
|