contracted_value 0.1.0.alpha.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/.codeclimate.yml +17 -0
- data/.editorconfig +24 -0
- data/.gitignore +35 -0
- data/.rubocop.yml +41 -0
- data/.travis.yml +25 -0
- data/Appraisals +9 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +346 -0
- data/Rakefile +16 -0
- data/contracted_value.gemspec +55 -0
- data/gemfiles/contracts_15_0.gemfile +7 -0
- data/gemfiles/contracts_16_0.gemfile +7 -0
- data/lib/contracted_value/core.rb +322 -0
- data/lib/contracted_value/version.rb +5 -0
- data/lib/contracted_value.rb +4 -0
- data/spec/contracted_value/value_spec.rb +680 -0
- data/spec/contracted_value_spec.rb +11 -0
- data/spec/spec_helper.rb +15 -0
- metadata +254 -0
@@ -0,0 +1,680 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
::RSpec.describe ::ContractedValue::Value do
|
6
|
+
|
7
|
+
shared_examples_for "attribute declaration" do
|
8
|
+
let(:value_class) do
|
9
|
+
raise "`value_class` absent"
|
10
|
+
end
|
11
|
+
|
12
|
+
example "does not raise error when NOT declaring any attribute" do
|
13
|
+
expect(->{ value_class }).to_not raise_error
|
14
|
+
end
|
15
|
+
|
16
|
+
example "does not raise error when declaring 1 attribute" do
|
17
|
+
expect(
|
18
|
+
->{
|
19
|
+
value_class.class_eval do
|
20
|
+
attribute(:attribute_1)
|
21
|
+
end
|
22
|
+
},
|
23
|
+
).to_not raise_error
|
24
|
+
end
|
25
|
+
|
26
|
+
example "does not raise error when declaring N attributes with different names" do
|
27
|
+
expect(
|
28
|
+
->{
|
29
|
+
value_class.class_eval do
|
30
|
+
attribute(:attribute_1)
|
31
|
+
attribute(:attribute_2)
|
32
|
+
end
|
33
|
+
},
|
34
|
+
).to_not raise_error
|
35
|
+
end
|
36
|
+
|
37
|
+
example "does raise error when declaring N attributes with the same name" do
|
38
|
+
expect(
|
39
|
+
->{
|
40
|
+
value_class.class_eval do
|
41
|
+
attribute(:attribute_1)
|
42
|
+
attribute(:attribute_2)
|
43
|
+
attribute(:attribute_1)
|
44
|
+
end
|
45
|
+
},
|
46
|
+
).to raise_error(::ContractedValue::Errors::DuplicateAttributeDeclaration)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
describe "attribute declaration" do
|
52
|
+
it_behaves_like "attribute declaration" do
|
53
|
+
let(:value_class) do
|
54
|
+
Class.new(described_class)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "attribute assignment" do
|
60
|
+
context "on object initialization" do
|
61
|
+
context "with class with no attribute declared with contract" do
|
62
|
+
let(:value_class) do
|
63
|
+
Class.new(described_class) do
|
64
|
+
attribute(:attribute_1)
|
65
|
+
attribute(:attribute_2)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
let(:default_inputs) do
|
70
|
+
{
|
71
|
+
attribute_1: 1,
|
72
|
+
attribute_2: 1,
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
let(:non_hash) do
|
77
|
+
[]
|
78
|
+
end
|
79
|
+
|
80
|
+
it "does raise error when input is not a hash" do
|
81
|
+
aggregate_failures do
|
82
|
+
expect(
|
83
|
+
->{
|
84
|
+
value_class.new(
|
85
|
+
non_hash,
|
86
|
+
)
|
87
|
+
},
|
88
|
+
).to raise_error(::ContractedValue::Errors::InvalidInputType)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it "does not raise error when input is a hash" do
|
93
|
+
aggregate_failures do
|
94
|
+
expect(
|
95
|
+
->{
|
96
|
+
value_class.new(
|
97
|
+
default_inputs,
|
98
|
+
)
|
99
|
+
},
|
100
|
+
).to_not raise_error
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it "does not raise error when input is a value" do
|
105
|
+
aggregate_failures do
|
106
|
+
expect(
|
107
|
+
->{
|
108
|
+
value_class.new(
|
109
|
+
value_class.new(
|
110
|
+
default_inputs,
|
111
|
+
),
|
112
|
+
)
|
113
|
+
},
|
114
|
+
).to_not raise_error
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it "does raise error when value of any declared attribute missing from input" do
|
119
|
+
aggregate_failures do
|
120
|
+
[
|
121
|
+
:attribute_1,
|
122
|
+
:attribute_2,
|
123
|
+
].each do |attr_name|
|
124
|
+
expect(
|
125
|
+
->{
|
126
|
+
value_class.new(
|
127
|
+
default_inputs.dup.tap{|h| h.delete(attr_name)},
|
128
|
+
)
|
129
|
+
},
|
130
|
+
).to raise_error(::ContractedValue::Errors::MissingAttributeInput)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
it "does not raise error when values of all declared attributes are present, even they are all nil" do
|
136
|
+
aggregate_failures do
|
137
|
+
[
|
138
|
+
:attribute_1,
|
139
|
+
:attribute_2,
|
140
|
+
].each do |attr_name|
|
141
|
+
expect(
|
142
|
+
->{
|
143
|
+
value_class.new(
|
144
|
+
default_inputs.each_with_object({}) do |(k, _v), h|
|
145
|
+
h[k] = nil
|
146
|
+
end
|
147
|
+
)
|
148
|
+
},
|
149
|
+
).to_not raise_error
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "with class with some attributes declared with contract" do
|
156
|
+
let(:value_class) do
|
157
|
+
Class.new(described_class) do
|
158
|
+
attribute(
|
159
|
+
:attribute_with_contract_1,
|
160
|
+
contract: ::Contracts::Builtin::And[::String, ::Contracts::Builtin::Not[::Contracts::Builtin::Send[:empty?]]],
|
161
|
+
)
|
162
|
+
attribute(
|
163
|
+
:attribute_with_contract_2,
|
164
|
+
contract: ::Contracts::Builtin::NatPos,
|
165
|
+
)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
let(:default_inputs) do
|
170
|
+
{
|
171
|
+
attribute_with_contract_1: "yo",
|
172
|
+
attribute_with_contract_2: 1,
|
173
|
+
}
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
it "does not raise error when all values are valid according to contracts" do
|
178
|
+
expect(
|
179
|
+
->{
|
180
|
+
value_class.new(
|
181
|
+
default_inputs
|
182
|
+
)
|
183
|
+
},
|
184
|
+
).to_not raise_error
|
185
|
+
end
|
186
|
+
|
187
|
+
it "does raise error when any value is invalid according to contracts" do
|
188
|
+
aggregate_failures do
|
189
|
+
expect(
|
190
|
+
->{
|
191
|
+
value_class.new(
|
192
|
+
default_inputs.merge(
|
193
|
+
attribute_with_contract_1: "",
|
194
|
+
),
|
195
|
+
)
|
196
|
+
},
|
197
|
+
).to raise_error(::ContractedValue::Errors::InvalidAttributeValue)
|
198
|
+
|
199
|
+
expect(
|
200
|
+
->{
|
201
|
+
value_class.new(
|
202
|
+
default_inputs.merge(
|
203
|
+
attribute_with_contract_2: 0,
|
204
|
+
),
|
205
|
+
)
|
206
|
+
},
|
207
|
+
).to raise_error(::ContractedValue::Errors::InvalidAttributeValue)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "attribute input value freezing" do
|
215
|
+
let(:value_object) do
|
216
|
+
value_class.new(
|
217
|
+
a_hash: hash_as_input,
|
218
|
+
)
|
219
|
+
end
|
220
|
+
|
221
|
+
let(:hash_as_input) do
|
222
|
+
{
|
223
|
+
hash: hash_as_deep_nested_content,
|
224
|
+
}
|
225
|
+
end
|
226
|
+
|
227
|
+
let(:hash_as_deep_nested_content) do
|
228
|
+
::Hash.new
|
229
|
+
end
|
230
|
+
|
231
|
+
shared_examples "attribute deeply frozen" do
|
232
|
+
it "does freeze the new object" do
|
233
|
+
expect(value_object).to be_frozen
|
234
|
+
end
|
235
|
+
|
236
|
+
it "does freeze the inputs" do
|
237
|
+
# Create it just before expectation
|
238
|
+
value_object
|
239
|
+
|
240
|
+
expect(
|
241
|
+
->{
|
242
|
+
hash_as_input[:a] = nil
|
243
|
+
},
|
244
|
+
).to raise_error(::RuntimeError, /can't modify frozen/)
|
245
|
+
end
|
246
|
+
|
247
|
+
it "does deeply freeze the inputs" do
|
248
|
+
# Create it just before expectation
|
249
|
+
value_object
|
250
|
+
|
251
|
+
expect(
|
252
|
+
->{
|
253
|
+
hash_as_deep_nested_content[:a] = nil
|
254
|
+
},
|
255
|
+
).to raise_error(::RuntimeError, /can't modify frozen/)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
shared_examples "attribute shallowly frozen" do
|
260
|
+
it "does freeze the new object" do
|
261
|
+
expect(value_object).to be_frozen
|
262
|
+
end
|
263
|
+
|
264
|
+
it "does freeze the inputs" do
|
265
|
+
# Create it just before expectation
|
266
|
+
value_object
|
267
|
+
|
268
|
+
expect(
|
269
|
+
->{
|
270
|
+
hash_as_input[:a] = nil
|
271
|
+
},
|
272
|
+
).to raise_error(::RuntimeError, /can't modify frozen/)
|
273
|
+
end
|
274
|
+
|
275
|
+
it "does not deeply freeze the inputs" do
|
276
|
+
# Create it just before expectation
|
277
|
+
value_object
|
278
|
+
|
279
|
+
expect(
|
280
|
+
->{
|
281
|
+
hash_as_deep_nested_content[:a] = nil
|
282
|
+
},
|
283
|
+
).to_not raise_error
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
shared_examples "attribute not frozen" do
|
288
|
+
it "does freeze the new object" do
|
289
|
+
expect(value_object).to be_frozen
|
290
|
+
end
|
291
|
+
|
292
|
+
it "does not freeze the inputs" do
|
293
|
+
# Create it just before expectation
|
294
|
+
value_object
|
295
|
+
|
296
|
+
expect(
|
297
|
+
->{
|
298
|
+
hash_as_input[:a] = nil
|
299
|
+
},
|
300
|
+
).to_not raise_error
|
301
|
+
end
|
302
|
+
|
303
|
+
it "does not deeply freeze the inputs" do
|
304
|
+
# Create it just before expectation
|
305
|
+
value_object
|
306
|
+
|
307
|
+
expect(
|
308
|
+
->{
|
309
|
+
hash_as_deep_nested_content[:a] = nil
|
310
|
+
},
|
311
|
+
).to_not raise_error
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context "when an attribute is declared without `refrigeration_mode` option" do
|
316
|
+
let(:value_class) do
|
317
|
+
Class.new(described_class) do
|
318
|
+
attribute(:a_hash)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
it_behaves_like "attribute deeply frozen"
|
323
|
+
end
|
324
|
+
|
325
|
+
context "when an attribute is declared with `refrigeration_mode` option (:deep)" do
|
326
|
+
let(:value_class) do
|
327
|
+
Class.new(described_class) do
|
328
|
+
attribute(
|
329
|
+
:a_hash,
|
330
|
+
refrigeration_mode: :deep,
|
331
|
+
)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
it_behaves_like "attribute deeply frozen"
|
336
|
+
end
|
337
|
+
|
338
|
+
context "when an attribute is declared with `refrigeration_mode` option (:shallow)" do
|
339
|
+
let(:value_class) do
|
340
|
+
Class.new(described_class) do
|
341
|
+
attribute(
|
342
|
+
:a_hash,
|
343
|
+
refrigeration_mode: :shallow,
|
344
|
+
)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
it_behaves_like "attribute shallowly frozen"
|
349
|
+
end
|
350
|
+
|
351
|
+
context "when an attribute is declared with `refrigeration_mode` option (:none)" do
|
352
|
+
let(:value_class) do
|
353
|
+
Class.new(described_class) do
|
354
|
+
attribute(
|
355
|
+
:a_hash,
|
356
|
+
refrigeration_mode: :none,
|
357
|
+
)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
it_behaves_like "attribute not frozen"
|
362
|
+
end
|
363
|
+
|
364
|
+
context "when an attribute is declared with invalid `refrigeration_mode` option" do
|
365
|
+
let(:value_class) do
|
366
|
+
Class.new(described_class) do
|
367
|
+
attribute(
|
368
|
+
:a_hash,
|
369
|
+
refrigeration_mode: :meow,
|
370
|
+
)
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
it "raises error on attribute declaration" do
|
375
|
+
expect do
|
376
|
+
value_class
|
377
|
+
end.to raise_error(::ContractedValue::Errors::InvalidRefrigerationMode)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
describe "attribute default value" do
|
383
|
+
context "when with option :default_value" do
|
384
|
+
let(:value_class) do
|
385
|
+
# Workaround strange issue that
|
386
|
+
# `let` cannot be used in class block
|
387
|
+
default_val = default_value
|
388
|
+
attr_contract = attribute_contract
|
389
|
+
|
390
|
+
Class.new(described_class) do
|
391
|
+
attribute(
|
392
|
+
:attr_with_default,
|
393
|
+
default_value: default_val,
|
394
|
+
contract: attr_contract,
|
395
|
+
)
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
let(:default_value) do
|
400
|
+
1
|
401
|
+
end
|
402
|
+
|
403
|
+
let(:attribute_contract) do
|
404
|
+
::Contracts::Builtin::Any
|
405
|
+
end
|
406
|
+
|
407
|
+
shared_examples "attribute with default value" do
|
408
|
+
it "returns default value when nothing provided" do
|
409
|
+
expect(
|
410
|
+
value_class.new.attr_with_default,
|
411
|
+
).to eq(default_value)
|
412
|
+
end
|
413
|
+
|
414
|
+
it "returns provided value when something provided" do
|
415
|
+
[
|
416
|
+
nil,
|
417
|
+
:wut,
|
418
|
+
-> { },
|
419
|
+
].each do |provided_value|
|
420
|
+
aggregate_failures do
|
421
|
+
expect(
|
422
|
+
value_class.new(
|
423
|
+
attr_with_default: provided_value,
|
424
|
+
).attr_with_default,
|
425
|
+
).to eq(provided_value)
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
context "and default value provided is `nil`" do
|
432
|
+
let(:default_value) do
|
433
|
+
nil
|
434
|
+
end
|
435
|
+
|
436
|
+
it_behaves_like "attribute with default value"
|
437
|
+
|
438
|
+
context "when default value violates contract" do
|
439
|
+
let(:attribute_contract) do
|
440
|
+
::Contracts::Builtin::Not[nil]
|
441
|
+
end
|
442
|
+
|
443
|
+
it "does raise error on attribute declaration" do
|
444
|
+
expect do
|
445
|
+
value_class
|
446
|
+
end.to raise_error(::ContractedValue::Errors::InvalidAttributeDefaultValue)
|
447
|
+
end
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
context "and default value provided is not `nil`" do
|
452
|
+
let(:default_value) do
|
453
|
+
123
|
454
|
+
end
|
455
|
+
|
456
|
+
it_behaves_like "attribute with default value"
|
457
|
+
|
458
|
+
context "when default value violates contract" do
|
459
|
+
let(:attribute_contract) do
|
460
|
+
::Symbol
|
461
|
+
end
|
462
|
+
|
463
|
+
it "does raise error on attribute declaration" do
|
464
|
+
expect do
|
465
|
+
value_class
|
466
|
+
end.to raise_error(::ContractedValue::Errors::InvalidAttributeDefaultValue)
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
context "and default value provided is mutable" do
|
472
|
+
|
473
|
+
context "as a string" do
|
474
|
+
let(:default_value) do
|
475
|
+
"PikaPika"
|
476
|
+
end
|
477
|
+
|
478
|
+
it_behaves_like "attribute with default value"
|
479
|
+
|
480
|
+
it "returns default value as frozen" do
|
481
|
+
expect(
|
482
|
+
value_class.new.attr_with_default,
|
483
|
+
).to be_frozen
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
context "as a hash" do
|
488
|
+
let(:default_value) do
|
489
|
+
{a: {b: :c}}
|
490
|
+
end
|
491
|
+
|
492
|
+
it_behaves_like "attribute with default value"
|
493
|
+
|
494
|
+
it "returns default value as frozen" do
|
495
|
+
aggregate_failures do
|
496
|
+
val = value_class.new.attr_with_default.fetch(:a)
|
497
|
+
|
498
|
+
expect(val).to eq({b: :c})
|
499
|
+
expect(val).to be_frozen
|
500
|
+
end
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
end
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
describe "sub-classes of a value class" do
|
509
|
+
|
510
|
+
describe "attribute declaration" do
|
511
|
+
let(:parent_value_class) do
|
512
|
+
Class.new(described_class)
|
513
|
+
end
|
514
|
+
|
515
|
+
it_behaves_like "attribute declaration" do
|
516
|
+
let(:value_class) do
|
517
|
+
Class.new(parent_value_class)
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
describe "usage of parent class attribute" do
|
522
|
+
|
523
|
+
let(:parent_value_class) do
|
524
|
+
Class.new(described_class).tap do |klass|
|
525
|
+
klass.class_eval do
|
526
|
+
# Too lazy to include parent attributes in all examples
|
527
|
+
attribute(:attribute_1)
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|
531
|
+
let(:child_value_class) do
|
532
|
+
Class.new(parent_value_class)
|
533
|
+
end
|
534
|
+
|
535
|
+
example "does not raise error" do
|
536
|
+
expect(
|
537
|
+
->{
|
538
|
+
child_value_class.new(attribute_1: "wut")
|
539
|
+
},
|
540
|
+
).to_not raise_error
|
541
|
+
end
|
542
|
+
|
543
|
+
end
|
544
|
+
|
545
|
+
describe "for new attributes absent in parent class" do
|
546
|
+
|
547
|
+
let(:parent_value_class) do
|
548
|
+
Class.new(described_class).tap do |klass|
|
549
|
+
klass.class_eval do
|
550
|
+
# Too lazy to include parent attributes in all examples
|
551
|
+
attribute(:attribute_1, default_value: nil)
|
552
|
+
attribute(:attribute_2, default_value: nil)
|
553
|
+
end
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
557
|
+
let(:child_value_class) do
|
558
|
+
Class.new(parent_value_class)
|
559
|
+
end
|
560
|
+
|
561
|
+
example "does not raise error when declaring 1 new attribute" do
|
562
|
+
expect(
|
563
|
+
->{
|
564
|
+
child_value_class.class_eval do
|
565
|
+
attribute(:attribute_3)
|
566
|
+
end
|
567
|
+
},
|
568
|
+
).to_not raise_error
|
569
|
+
end
|
570
|
+
|
571
|
+
example "does not raise error when declaring N attributes with different names" do
|
572
|
+
expect(
|
573
|
+
->{
|
574
|
+
child_value_class.class_eval do
|
575
|
+
attribute(:attribute_3)
|
576
|
+
attribute(:attribute_4)
|
577
|
+
end
|
578
|
+
},
|
579
|
+
).to_not raise_error
|
580
|
+
end
|
581
|
+
|
582
|
+
example "does raise error when declaring N attributes with the same name" do
|
583
|
+
expect(
|
584
|
+
->{
|
585
|
+
child_value_class.class_eval do
|
586
|
+
attribute(:attribute_3)
|
587
|
+
attribute(:attribute_4)
|
588
|
+
attribute(:attribute_3)
|
589
|
+
end
|
590
|
+
},
|
591
|
+
).to raise_error(::ContractedValue::Errors::DuplicateAttributeDeclaration)
|
592
|
+
end
|
593
|
+
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
describe "attribute redeclaration" do
|
598
|
+
|
599
|
+
let(:child_value_class) do
|
600
|
+
Class.new(parent_value_class)
|
601
|
+
end
|
602
|
+
|
603
|
+
describe "for existing attributes from parent class" do
|
604
|
+
let(:parent_value_class) do
|
605
|
+
Class.new(described_class).tap do |klass|
|
606
|
+
klass.class_eval do
|
607
|
+
attribute(:attribute_1)
|
608
|
+
attribute(:attribute_2)
|
609
|
+
end
|
610
|
+
end
|
611
|
+
end
|
612
|
+
it_behaves_like "attribute declaration" do
|
613
|
+
let(:value_class) do
|
614
|
+
child_value_class
|
615
|
+
end
|
616
|
+
end
|
617
|
+
end
|
618
|
+
|
619
|
+
describe "for existing attributes from parent class" do
|
620
|
+
|
621
|
+
let(:parent_value_class) do
|
622
|
+
Class.new(described_class).tap do |klass|
|
623
|
+
klass.class_eval do
|
624
|
+
attribute(
|
625
|
+
:attribute_1,
|
626
|
+
contract: ::String,
|
627
|
+
refrigeration_mode: :deep,
|
628
|
+
# `default_value` not specified on purpose
|
629
|
+
)
|
630
|
+
end
|
631
|
+
end
|
632
|
+
end
|
633
|
+
|
634
|
+
example "does not raise error when declaring existing attribute with different contract" do
|
635
|
+
expect(
|
636
|
+
->{
|
637
|
+
child_value_class.class_eval do
|
638
|
+
attribute(
|
639
|
+
:attribute_1,
|
640
|
+
contract: ::Contracts::Builtin::NatPos
|
641
|
+
)
|
642
|
+
end
|
643
|
+
child_value_class.new(attribute_1: "")
|
644
|
+
},
|
645
|
+
).to raise_error(::ContractedValue::Errors::InvalidAttributeValue)
|
646
|
+
end
|
647
|
+
|
648
|
+
example "does not raise error when declaring existing attribute with different default_value" do
|
649
|
+
expect(
|
650
|
+
->{
|
651
|
+
child_value_class.class_eval do
|
652
|
+
attribute(
|
653
|
+
:attribute_1,
|
654
|
+
default_value: nil,
|
655
|
+
)
|
656
|
+
end
|
657
|
+
child_value_class.new
|
658
|
+
},
|
659
|
+
).to_not raise_error
|
660
|
+
end
|
661
|
+
|
662
|
+
example "does not raise error when declaring existing attribute with different refrigeration_mode" do
|
663
|
+
child_value_class.class_eval do
|
664
|
+
attribute(
|
665
|
+
:attribute_1,
|
666
|
+
refrigeration_mode: :none,
|
667
|
+
)
|
668
|
+
end
|
669
|
+
value_object = child_value_class.new(attribute_1: String.new)
|
670
|
+
expect(value_object).to be_frozen
|
671
|
+
expect(value_object.attribute_1).to_not be_frozen
|
672
|
+
end
|
673
|
+
|
674
|
+
end
|
675
|
+
|
676
|
+
end
|
677
|
+
|
678
|
+
end
|
679
|
+
|
680
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
|
4
|
+
require "contracted_value"
|
5
|
+
|
6
|
+
if ENV["TRAVIS"]
|
7
|
+
require "simplecov"
|
8
|
+
SimpleCov.start
|
9
|
+
|
10
|
+
require "codecov"
|
11
|
+
SimpleCov.formatter = SimpleCov::Formatter::Codecov
|
12
|
+
end
|
13
|
+
|
14
|
+
require "rspec"
|
15
|
+
require "rspec/its"
|