attributor 5.4 → 6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/lib/attributor/attribute.rb +101 -84
- data/lib/attributor/extras/field_selector.rb +4 -0
- data/lib/attributor/families/numeric.rb +19 -6
- data/lib/attributor/families/temporal.rb +16 -9
- data/lib/attributor/hash_dsl_compiler.rb +6 -5
- data/lib/attributor/type.rb +26 -3
- data/lib/attributor/types/bigdecimal.rb +6 -1
- data/lib/attributor/types/boolean.rb +5 -0
- data/lib/attributor/types/collection.rb +19 -0
- data/lib/attributor/types/csv.rb +4 -0
- data/lib/attributor/types/date.rb +7 -1
- data/lib/attributor/types/date_time.rb +7 -1
- data/lib/attributor/types/float.rb +4 -3
- data/lib/attributor/types/hash.rb +86 -23
- data/lib/attributor/types/integer.rb +7 -1
- data/lib/attributor/types/model.rb +9 -21
- data/lib/attributor/types/object.rb +5 -0
- data/lib/attributor/types/polymorphic.rb +0 -1
- data/lib/attributor/types/string.rb +19 -0
- data/lib/attributor/types/symbol.rb +5 -0
- data/lib/attributor/types/tempfile.rb +4 -0
- data/lib/attributor/types/time.rb +6 -2
- data/lib/attributor/types/uri.rb +8 -0
- data/lib/attributor/version.rb +1 -1
- data/lib/attributor.rb +3 -7
- data/spec/attribute_spec.rb +148 -124
- data/spec/extras/field_selector/field_selector_spec.rb +9 -0
- data/spec/hash_dsl_compiler_spec.rb +5 -5
- data/spec/spec_helper.rb +0 -2
- data/spec/support/integers.rb +7 -0
- data/spec/support/models.rb +7 -7
- data/spec/types/bigdecimal_spec.rb +8 -0
- data/spec/types/boolean_spec.rb +10 -0
- data/spec/types/collection_spec.rb +16 -0
- data/spec/types/date_spec.rb +9 -0
- data/spec/types/date_time_spec.rb +9 -0
- data/spec/types/float_spec.rb +8 -0
- data/spec/types/hash_spec.rb +181 -22
- data/spec/types/integer_spec.rb +9 -0
- data/spec/types/model_spec.rb +7 -1
- data/spec/types/string_spec.rb +10 -0
- data/spec/types/temporal_spec.rb +5 -1
- data/spec/types/time_spec.rb +9 -0
- data/spec/types/uri_spec.rb +9 -0
- metadata +5 -6
- data/lib/attributor/attribute_resolver.rb +0 -111
- data/spec/attribute_resolver_spec.rb +0 -237
data/spec/attribute_spec.rb
CHANGED
@@ -11,7 +11,7 @@ describe Attributor::Attribute do
|
|
11
11
|
|
12
12
|
context 'initialize' do
|
13
13
|
its(:type) { should be type }
|
14
|
-
its(:options) { should
|
14
|
+
its(:options) { should eq attribute_options }
|
15
15
|
|
16
16
|
it 'calls check_options!' do
|
17
17
|
expect_any_instance_of(Attributor::Attribute).to receive(:check_options!)
|
@@ -36,17 +36,49 @@ describe Attributor::Attribute do
|
|
36
36
|
it { should eq other_attribute }
|
37
37
|
end
|
38
38
|
|
39
|
+
context 'describe_json_schema' do
|
40
|
+
let(:type) { PositiveIntegerType }
|
41
|
+
|
42
|
+
let(:attribute_options) do
|
43
|
+
{
|
44
|
+
values: [1,20],
|
45
|
+
description: "something",
|
46
|
+
example: 20,
|
47
|
+
max: 1000,
|
48
|
+
default: 1
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'reports all of the possible attributes' do
|
53
|
+
let(:js){ subject.as_json_schema(example: 20) }
|
54
|
+
|
55
|
+
it 'including the attribute-specific ones' do
|
56
|
+
expect(js[:enum]).to eq( [1,20])
|
57
|
+
expect(js[:description]).to eq( "something")
|
58
|
+
expect(js[:default]).to eq(1)
|
59
|
+
expect(js[:example]).to eq(20)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'as well as the type-specific ones' do
|
63
|
+
expect(js[:type]).to eq(:integer)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
39
70
|
context 'describe' do
|
40
|
-
let(:attribute_options) { {
|
71
|
+
let(:attribute_options) { {required: true, values: ['one'], description: "something", min: 0} }
|
41
72
|
let(:expected) do
|
42
|
-
h = {
|
43
|
-
common = attribute_options.select
|
73
|
+
h = {type: {name: 'String', id: type.id, family: type.family}}
|
74
|
+
common = attribute_options.select{|k,v| Attributor::Attribute::TOP_LEVEL_OPTIONS.include? k }
|
44
75
|
h.merge!(common)
|
45
|
-
h[:options] = {
|
76
|
+
h[:options] = {min: 0}
|
46
77
|
h
|
47
78
|
end
|
48
79
|
|
49
|
-
|
80
|
+
# It has both the type-included options (min) as well as the attribute options (max)
|
81
|
+
its(:describe) { should == expected }
|
50
82
|
|
51
83
|
context 'with example options' do
|
52
84
|
let(:attribute_options) { { description: 'something', example: 'ex_def' } }
|
@@ -163,6 +195,49 @@ describe Attributor::Attribute do
|
|
163
195
|
end.not_to raise_error
|
164
196
|
end
|
165
197
|
end
|
198
|
+
|
199
|
+
context 'custom_options' do
|
200
|
+
let(:option_name) { :foo }
|
201
|
+
let(:custom_option_args) { [option_name, String] }
|
202
|
+
|
203
|
+
around do |example|
|
204
|
+
Attributor::Attribute.custom_option *custom_option_args
|
205
|
+
example.run
|
206
|
+
Attributor::Attribute.custom_options.delete option_name
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'raises ArgumentError if given an existing option' do
|
210
|
+
expect {
|
211
|
+
Attributor::Attribute.custom_option :default, Object
|
212
|
+
}.to raise_error(ArgumentError)
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'accepts custom options' do
|
216
|
+
expect do
|
217
|
+
Attributor::Attribute.new(Integer, foo: 'unvalidated')
|
218
|
+
end.not_to raise_error
|
219
|
+
end
|
220
|
+
|
221
|
+
context 'can validate the custom option value' do
|
222
|
+
let(:custom_option_args) { [option_name, String, values: ['valid']] }
|
223
|
+
it 'does not raise with a valid option value' do
|
224
|
+
expect do
|
225
|
+
Attributor::Attribute.new(Integer, foo: 'valid')
|
226
|
+
end.not_to raise_error
|
227
|
+
end
|
228
|
+
it 'raises with an invalid option value' do
|
229
|
+
expect do
|
230
|
+
Attributor::Attribute.new(Integer, foo: 'invalid')
|
231
|
+
end.to raise_error(Attributor::AttributorException)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'appear in as_json_schema' do
|
236
|
+
attribute = Attributor::Attribute.new(Integer, foo: 'valid')
|
237
|
+
json_schema = attribute.as_json_schema
|
238
|
+
expect(json_schema[:'x-foo']).to eq 'valid'
|
239
|
+
end
|
240
|
+
end
|
166
241
|
end
|
167
242
|
|
168
243
|
context 'example' do
|
@@ -383,10 +458,49 @@ describe Attributor::Attribute do
|
|
383
458
|
context 'applying attribute options' do
|
384
459
|
context ':required' do
|
385
460
|
let(:attribute_options) { { required: true } }
|
461
|
+
context 'has no effect on a bare attribute' do
|
462
|
+
let(:value) { 'val' }
|
463
|
+
it 'it does not error, as we do not know if the parent attribute key was passed in (done at the Hash level)' do
|
464
|
+
expect(attribute.validate(value, context)).to be_empty
|
465
|
+
end
|
466
|
+
end
|
467
|
+
end
|
468
|
+
context ':null false (non-nullable)' do
|
469
|
+
let(:attribute_options) { { null: false } }
|
386
470
|
context 'with a nil value' do
|
387
471
|
let(:value) { nil }
|
388
472
|
it 'returns an error' do
|
389
|
-
expect(attribute.validate(value, context).first).to eq 'Attribute context is
|
473
|
+
expect(attribute.validate(value, context).first).to eq 'Attribute context is not nullable'
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|
477
|
+
context ':null true (nullable)' do
|
478
|
+
let(:attribute_options) { { null: true } }
|
479
|
+
context 'with a nil value' do
|
480
|
+
let(:value) { nil }
|
481
|
+
it 'does not error' do
|
482
|
+
expect(attribute.validate(value, context)).to be_empty
|
483
|
+
end
|
484
|
+
end
|
485
|
+
end
|
486
|
+
context 'defaults to non-nullable if null not defined' do
|
487
|
+
let(:attribute_options) { { } }
|
488
|
+
context 'with a nil value' do
|
489
|
+
let(:value) { nil }
|
490
|
+
it 'returns an error' do
|
491
|
+
expect(Attributor::Attribute.default_for_null).to be(false)
|
492
|
+
expect(attribute.validate(value, context).first).to eq 'Attribute context is not nullable'
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
context 'default can be overrideable with true' do
|
498
|
+
let(:attribute_options) { { } }
|
499
|
+
context 'with a nil value' do
|
500
|
+
let(:value) { nil }
|
501
|
+
it 'suceeds' do
|
502
|
+
expect(Attributor::Attribute).to receive(:default_for_null).and_return(true)
|
503
|
+
expect(attribute.validate(value, context)).to be_empty
|
390
504
|
end
|
391
505
|
end
|
392
506
|
end
|
@@ -432,6 +546,13 @@ describe Attributor::Attribute do
|
|
432
546
|
end
|
433
547
|
end
|
434
548
|
|
549
|
+
context 'with a nil value' do
|
550
|
+
let(:value) { nil }
|
551
|
+
it 'returns no errors' do
|
552
|
+
expect(errors).to be_empty
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
435
556
|
context 'with a value of a value different than the native_type' do
|
436
557
|
let(:value) { 1 }
|
437
558
|
|
@@ -441,58 +562,6 @@ describe Attributor::Attribute do
|
|
441
562
|
end
|
442
563
|
end
|
443
564
|
end
|
444
|
-
|
445
|
-
context '#validate_missing_value' do
|
446
|
-
let(:key) { '$.instance.ssh_key.name' }
|
447
|
-
let(:value) { /\w+/.gen }
|
448
|
-
|
449
|
-
let(:attribute_options) { { required_if: key } }
|
450
|
-
|
451
|
-
let(:ssh_key) { double('ssh_key', name: value) }
|
452
|
-
let(:instance) { double('instance', ssh_key: ssh_key) }
|
453
|
-
|
454
|
-
before { Attributor::AttributeResolver.current.register('instance', instance) }
|
455
|
-
|
456
|
-
let(:attribute_context) { ['$', 'params', 'key_material'] }
|
457
|
-
subject(:errors) { attribute.validate_missing_value(attribute_context) }
|
458
|
-
|
459
|
-
context 'for a simple dependency without a predicate' do
|
460
|
-
context 'that is satisfied' do
|
461
|
-
it { should_not be_empty }
|
462
|
-
end
|
463
|
-
|
464
|
-
context 'that is missing' do
|
465
|
-
let(:value) { nil }
|
466
|
-
it { should be_empty }
|
467
|
-
end
|
468
|
-
end
|
469
|
-
|
470
|
-
context 'with a dependency that has a predicate' do
|
471
|
-
let(:value) { 'default_ssh_key_name' }
|
472
|
-
# subject(:errors) { attribute.validate_missing_value('') }
|
473
|
-
|
474
|
-
context 'where the target attribute exists, and matches the predicate' do
|
475
|
-
let(:attribute_options) { { required_if: { key => /default/ } } }
|
476
|
-
|
477
|
-
it { should_not be_empty }
|
478
|
-
|
479
|
-
its(:first) { should match(/Attribute #{Regexp.quote(Attributor.humanize_context(attribute_context))} is required when #{Regexp.quote(key)} matches/) }
|
480
|
-
end
|
481
|
-
|
482
|
-
context 'where the target attribute exists, but does not match the predicate' do
|
483
|
-
let(:attribute_options) { { required_if: { key => /other/ } } }
|
484
|
-
|
485
|
-
it { should be_empty }
|
486
|
-
end
|
487
|
-
|
488
|
-
context 'where the target attribute does not exist' do
|
489
|
-
let(:attribute_options) { { required_if: { key => /default/ } } }
|
490
|
-
let(:ssh_key) { double('ssh_key', name: nil) }
|
491
|
-
|
492
|
-
it { should be_empty }
|
493
|
-
end
|
494
|
-
end
|
495
|
-
end
|
496
565
|
end
|
497
566
|
|
498
567
|
context 'for an attribute for a subclass of Model' do
|
@@ -561,71 +630,6 @@ describe Attributor::Attribute do
|
|
561
630
|
end
|
562
631
|
end
|
563
632
|
end
|
564
|
-
|
565
|
-
context '#validate_missing_value' do
|
566
|
-
let(:type) { Duck }
|
567
|
-
let(:attribute_name) { nil }
|
568
|
-
let(:attribute) { Duck.attributes[attribute_name] }
|
569
|
-
|
570
|
-
let(:attribute_context) { ['$', 'duck', attribute_name.to_s] }
|
571
|
-
subject(:errors) { attribute.validate_missing_value(attribute_context) }
|
572
|
-
|
573
|
-
before do
|
574
|
-
Attributor::AttributeResolver.current.register('duck', duck)
|
575
|
-
end
|
576
|
-
|
577
|
-
context 'for a dependency with no predicate' do
|
578
|
-
let(:attribute_name) { :email }
|
579
|
-
|
580
|
-
let(:duck) do
|
581
|
-
d = Duck.new
|
582
|
-
d.age = 1
|
583
|
-
d.name = 'Donald'
|
584
|
-
d
|
585
|
-
end
|
586
|
-
|
587
|
-
context 'where the target attribute exists, and matches the predicate' do
|
588
|
-
it { should_not be_empty }
|
589
|
-
its(:first) { should eq 'Attribute $.duck.email is required when name (for $.duck) is present.' }
|
590
|
-
end
|
591
|
-
context 'where the target attribute does not exist' do
|
592
|
-
before do
|
593
|
-
duck.name = nil
|
594
|
-
end
|
595
|
-
it { should be_empty }
|
596
|
-
end
|
597
|
-
end
|
598
|
-
|
599
|
-
context 'for a dependency with a predicate' do
|
600
|
-
let(:attribute_name) { :age }
|
601
|
-
|
602
|
-
let(:duck) do
|
603
|
-
d = Duck.new
|
604
|
-
d.name = 'Daffy'
|
605
|
-
d.email = 'daffy@darkwing.uoregon.edu' # he's a duck,get it?
|
606
|
-
d
|
607
|
-
end
|
608
|
-
|
609
|
-
context 'where the target attribute exists, and matches the predicate' do
|
610
|
-
it { should_not be_empty }
|
611
|
-
its(:first) { should match(/Attribute #{Regexp.quote('$.duck.age')} is required when name #{Regexp.quote('(for $.duck)')} matches/) }
|
612
|
-
end
|
613
|
-
|
614
|
-
context 'where the target attribute exists, and does not match the predicate' do
|
615
|
-
before do
|
616
|
-
duck.name = 'Donald'
|
617
|
-
end
|
618
|
-
it { should be_empty }
|
619
|
-
end
|
620
|
-
|
621
|
-
context 'where the target attribute does not exist' do
|
622
|
-
before do
|
623
|
-
duck.name = nil
|
624
|
-
end
|
625
|
-
it { should be_empty }
|
626
|
-
end
|
627
|
-
end
|
628
|
-
end
|
629
633
|
end
|
630
634
|
end
|
631
635
|
|
@@ -682,4 +686,24 @@ describe Attributor::Attribute do
|
|
682
686
|
end
|
683
687
|
end
|
684
688
|
end
|
689
|
+
|
690
|
+
context '.nullable_attribute?' do
|
691
|
+
subject { described_class.nullable_attribute?(options) }
|
692
|
+
context 'with null: true option' do
|
693
|
+
let(:options) { { null: true } }
|
694
|
+
it { should be_truthy }
|
695
|
+
end
|
696
|
+
context 'with null: false option' do
|
697
|
+
let(:options) { { null: false } }
|
698
|
+
it { should be_falsey }
|
699
|
+
end
|
700
|
+
context 'defaults to false without any null option' do
|
701
|
+
let(:options) { { } }
|
702
|
+
it { should be_falsey }
|
703
|
+
end
|
704
|
+
context 'defaults to false if null: nil' do
|
705
|
+
let(:options) { { null: nil } }
|
706
|
+
it { should be_falsey }
|
707
|
+
end
|
708
|
+
end
|
685
709
|
end
|
@@ -33,4 +33,13 @@ describe Attributor::FieldSelector do
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
context '.as_json_schema' do
|
38
|
+
subject(:js){ type.as_json_schema }
|
39
|
+
it 'adds the right attributes' do
|
40
|
+
expect(js.keys).to include(:type, :'x-type_name')
|
41
|
+
expect(js[:type]).to eq(:string)
|
42
|
+
expect(js[:'x-type_name']).to eq('FieldSelector')
|
43
|
+
end
|
44
|
+
end
|
36
45
|
end
|
@@ -109,31 +109,31 @@ describe Attributor::HashDSLCompiler do
|
|
109
109
|
context 'for :all' do
|
110
110
|
let(:arguments) { { all: [:one, :two, :three] } }
|
111
111
|
let(:value) { [:one] }
|
112
|
-
let(:validation_error) { [
|
112
|
+
let(:validation_error) { ["Attribute $.key(:two) is required.", "Attribute $.key(:three) is required."] }
|
113
113
|
it { expect(subject).to include(*validation_error) }
|
114
114
|
end
|
115
115
|
context 'for :exactly' do
|
116
116
|
let(:requirement) { req_class.new(exactly: 1).of(:one, :two) }
|
117
117
|
let(:value) { [:one, :two] }
|
118
|
-
let(:validation_error) { 'Exactly 1 of the following
|
118
|
+
let(:validation_error) { 'Exactly 1 of the following attributes [:one, :two] are required for $. Found 2 instead: [:one, :two]' }
|
119
119
|
it { expect(subject).to include(validation_error) }
|
120
120
|
end
|
121
121
|
context 'for :at_least' do
|
122
122
|
let(:requirement) { req_class.new(at_least: 2).of(:one, :two, :three) }
|
123
123
|
let(:value) { [:one] }
|
124
|
-
let(:validation_error) { 'At least 2
|
124
|
+
let(:validation_error) { 'At least 2 attributes out of [:one, :two, :three] are required to be passed in for $. Found [:one]' }
|
125
125
|
it { expect(subject).to include(validation_error) }
|
126
126
|
end
|
127
127
|
context 'for :at_most' do
|
128
128
|
let(:requirement) { req_class.new(at_most: 1).of(:one, :two, :three) }
|
129
129
|
let(:value) { [:one, :two] }
|
130
|
-
let(:validation_error) { 'At most 1
|
130
|
+
let(:validation_error) { 'At most 1 attributes out of [:one, :two, :three] can be passed in for $. Found [:one, :two]' }
|
131
131
|
it { expect(subject).to include(validation_error) }
|
132
132
|
end
|
133
133
|
context 'for :exclusive' do
|
134
134
|
let(:arguments) { { exclusive: [:one, :two] } }
|
135
135
|
let(:value) { [:one, :two] }
|
136
|
-
let(:validation_error) { '
|
136
|
+
let(:validation_error) { 'Attributes [:one, :two] are mutually exclusive for $.' }
|
137
137
|
it { expect(subject).to include(validation_error) }
|
138
138
|
end
|
139
139
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -23,9 +23,7 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
|
23
23
|
|
24
24
|
RSpec.configure do |config|
|
25
25
|
config.around(:each) do |example|
|
26
|
-
Attributor::AttributeResolver.current = Attributor::AttributeResolver.new
|
27
26
|
example.run
|
28
|
-
Attributor::AttributeResolver.current = nil
|
29
27
|
end
|
30
28
|
end
|
31
29
|
|
data/spec/support/models.rb
CHANGED
@@ -11,9 +11,9 @@ end
|
|
11
11
|
|
12
12
|
class Duck < Attributor::Model
|
13
13
|
attributes do
|
14
|
-
attribute :age, Attributor::Integer
|
14
|
+
attribute :age, Attributor::Integer
|
15
15
|
attribute :name, Attributor::String
|
16
|
-
attribute :email, Attributor::String
|
16
|
+
attribute :email, Attributor::String
|
17
17
|
attribute :angry, Attributor::Boolean, default: true, example: /true|false/, description: 'Angry bird?'
|
18
18
|
attribute :weight, Attributor::Float, example: /\d{1,2}\.\d/, description: 'The weight of the duck'
|
19
19
|
attribute :type, Attributor::Symbol, values: [:duck]
|
@@ -50,15 +50,15 @@ class Cormorant < Attributor::Model
|
|
50
50
|
end
|
51
51
|
|
52
52
|
# This will be a collection of arbitrary Ruby Objects
|
53
|
-
attribute :
|
53
|
+
attribute :all_the_fish, Attributor::Collection, description: 'All kinds of fish for feeding the babies'
|
54
54
|
|
55
55
|
# This will be a collection of Cormorants (note, this relationship is circular)
|
56
|
-
attribute :neighbors, Attributor::Collection.of(Cormorant), description: 'Neighbor cormorants'
|
56
|
+
attribute :neighbors, Attributor::Collection.of(Cormorant), member_options: {null: false}, description: 'Neighbor cormorants', null: false
|
57
57
|
|
58
58
|
# This will be a collection of instances of an anonymous Struct class, each having two well-defined attributes
|
59
59
|
|
60
60
|
attribute :babies, Attributor::Collection.of(Attributor::Struct), description: 'All the babies', member_options: { identity: :name } do
|
61
|
-
attribute :name, Attributor::String, example: /[:name]/, description: 'The name of the baby cormorant'
|
61
|
+
attribute :name, Attributor::String, example: /[:name]/, description: 'The name of the baby cormorant', required: true
|
62
62
|
attribute :months, Attributor::Integer, default: 0, min: 0, description: 'The age in months of the baby cormorant'
|
63
63
|
attribute :weight, Attributor::Float, example: /\d{1,2}\.\d{3}/, description: 'The weight in kg of the baby cormorant'
|
64
64
|
end
|
@@ -76,8 +76,8 @@ end
|
|
76
76
|
|
77
77
|
class Address < Attributor::Model
|
78
78
|
attributes do
|
79
|
-
attribute :name, String, example: /\w
|
80
|
-
attribute :state, String, values: %w(OR CA)
|
79
|
+
attribute :name, String, example: /\w+/, null: true
|
80
|
+
attribute :state, String, values: %w(OR CA), null: false
|
81
81
|
attribute :person, Person, example: proc { |address, context| Person.example(context, address: address) }
|
82
82
|
requires :name
|
83
83
|
end
|
@@ -45,4 +45,12 @@ describe Attributor::BigDecimal do
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
48
|
+
context '.as_json_schema' do
|
49
|
+
subject(:js){ type.as_json_schema }
|
50
|
+
it 'adds the right attributes' do
|
51
|
+
expect(js.keys).to include(:type, :'x-type_name')
|
52
|
+
expect(js[:type]).to eq(:number)
|
53
|
+
expect(js[:'x-type_name']).to eq('BigDecimal')
|
54
|
+
end
|
55
|
+
end
|
48
56
|
end
|
data/spec/types/boolean_spec.rb
CHANGED
@@ -7,6 +7,8 @@ describe Attributor::Boolean do
|
|
7
7
|
expect(type.new.is_a?(Attributor::Dumpable)).not_to be(true)
|
8
8
|
end
|
9
9
|
|
10
|
+
its(:json_schema_type){ should eq(:boolean)}
|
11
|
+
|
10
12
|
context '.valid_type?' do
|
11
13
|
context 'for incoming Boolean values' do
|
12
14
|
[false, true].each do |value|
|
@@ -63,4 +65,12 @@ describe Attributor::Boolean do
|
|
63
65
|
end
|
64
66
|
end
|
65
67
|
end
|
68
|
+
context '.as_json_schema' do
|
69
|
+
subject(:js){ type.as_json_schema }
|
70
|
+
it 'adds the right attributes' do
|
71
|
+
expect(js.keys).to include(:type, :'x-type_name')
|
72
|
+
expect(js[:type]).to eq(:boolean)
|
73
|
+
expect(js[:'x-type_name']).to eq('Boolean')
|
74
|
+
end
|
75
|
+
end
|
66
76
|
end
|
@@ -344,4 +344,20 @@ describe Attributor::Collection do
|
|
344
344
|
end.to_not raise_error
|
345
345
|
end
|
346
346
|
end
|
347
|
+
|
348
|
+
context '.as_json_schema' do
|
349
|
+
let(:member_type) { Attributor::String }
|
350
|
+
let(:type) { Attributor::Collection.of(member_type) }
|
351
|
+
let(:attribute_options) do
|
352
|
+
{}
|
353
|
+
end
|
354
|
+
subject(:js){ type.as_json_schema(attribute_options: attribute_options) }
|
355
|
+
|
356
|
+
it 'adds the right attributes' do
|
357
|
+
expect(js.keys).to include(:type, :'x-type_name', :items)
|
358
|
+
expect(js[:type]).to eq(:array)
|
359
|
+
expect(js[:'x-type_name']).to eq('Collection')
|
360
|
+
expect(js[:items]).to eq(member_type.as_json_schema)
|
361
|
+
end
|
362
|
+
end
|
347
363
|
end
|
data/spec/types/date_spec.rb
CHANGED
@@ -92,4 +92,13 @@ describe Attributor::Date do
|
|
92
92
|
end
|
93
93
|
end
|
94
94
|
end
|
95
|
+
context '.as_json_schema' do
|
96
|
+
subject(:js){ type.as_json_schema }
|
97
|
+
it 'adds the right attributes' do
|
98
|
+
expect(js.keys).to include(:type, :'x-type_name')
|
99
|
+
expect(js[:type]).to eq(:string)
|
100
|
+
expect(js[:format]).to eq(:'date')
|
101
|
+
expect(js[:'x-type_name']).to eq('Date')
|
102
|
+
end
|
103
|
+
end
|
95
104
|
end
|
@@ -92,4 +92,13 @@ describe Attributor::DateTime do
|
|
92
92
|
end
|
93
93
|
end
|
94
94
|
end
|
95
|
+
context '.as_json_schema' do
|
96
|
+
subject(:js){ type.as_json_schema }
|
97
|
+
it 'adds the right attributes' do
|
98
|
+
expect(js.keys).to include(:type, :'x-type_name', :format)
|
99
|
+
expect(js[:type]).to eq(:string)
|
100
|
+
expect(js[:format]).to eq(:'date-time')
|
101
|
+
expect(js[:'x-type_name']).to eq('DateTime')
|
102
|
+
end
|
103
|
+
end
|
95
104
|
end
|
data/spec/types/float_spec.rb
CHANGED
@@ -76,4 +76,12 @@ describe Attributor::Float do
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
79
|
+
context '.as_json_schema' do
|
80
|
+
subject(:js){ type.as_json_schema }
|
81
|
+
it 'adds the right attributes' do
|
82
|
+
expect(js.keys).to include(:type, :'x-type_name')
|
83
|
+
expect(js[:type]).to eq(:number)
|
84
|
+
expect(js[:'x-type_name']).to eq('Float')
|
85
|
+
end
|
86
|
+
end
|
79
87
|
end
|