smart_properties 1.8.0 → 1.8.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 +4 -4
- data/lib/smart_properties.rb +2 -1
- data/spec/acceptance_checking_spec.rb +99 -0
- data/spec/base_spec.rb +85 -0
- data/spec/configuration_error_spec.rb +17 -0
- data/spec/conversion_spec.rb +30 -0
- data/spec/default_values_spec.rb +51 -0
- data/spec/inheritance_spec.rb +136 -0
- data/spec/required_values_spec.rb +104 -0
- data/spec/spec_helper.rb +0 -1
- data/spec/support/dummy_class.rb +9 -0
- metadata +18 -4
- data/spec/smart_properties_spec.rb +0 -794
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01dcc093f88456b5adc03fda8756ce4c82fadf2d
|
4
|
+
data.tar.gz: 02e619aa94f6b2a1106e787f5f4ccfe4745f5b4d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba7245f78b5720fe02adbf55f89a87f4a92c6525813fde45160c647f6506a76de3127606c0835c58584562a74ed05e2e106a69590372049983f89168a75014bd
|
7
|
+
data.tar.gz: 7b2ec9c3656e8d361e370118c9ef7f964770541a5ad84b725136796516179d25ddb225ea1fccb643fbe8fbe1408b0a429fdc97fb9227bb1bf15071e77c605c95
|
data/lib/smart_properties.rb
CHANGED
@@ -21,7 +21,7 @@
|
|
21
21
|
# :required => true
|
22
22
|
#
|
23
23
|
module SmartProperties
|
24
|
-
VERSION = "1.8.
|
24
|
+
VERSION = "1.8.1"
|
25
25
|
|
26
26
|
class Error < ::ArgumentError; end
|
27
27
|
class ConfigurationError < Error; end
|
@@ -156,6 +156,7 @@ module SmartProperties
|
|
156
156
|
def prepare(value, scope)
|
157
157
|
raise MissingValueError.new(scope, self) if required?(scope) && value.nil?
|
158
158
|
value = convert(value, scope) unless value.nil?
|
159
|
+
raise MissingValueError.new(scope, self) if required?(scope) && value.nil?
|
159
160
|
raise InvalidValueError.new(scope, self, value) unless accepts?(value, scope)
|
160
161
|
value
|
161
162
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe SmartProperties, 'acceptance checking' do
|
4
|
+
context "when used to build a class that has a property called :visible which uses an array of valid values for acceptance checking" do
|
5
|
+
subject(:klass) { DummyClass.new { property :visible, accepts: [true, false] } }
|
6
|
+
|
7
|
+
context "an instance of this class" do
|
8
|
+
subject(:instance) { klass.new }
|
9
|
+
|
10
|
+
it "should allow to set true as value for visible" do
|
11
|
+
expect { instance.visible = true }.to_not raise_error
|
12
|
+
expect { instance[:visible] = true }.to_not raise_error
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should allow to set false as value for visible" do
|
16
|
+
expect { instance.visible = false }.to_not raise_error
|
17
|
+
expect { instance[:visible] = false }.to_not raise_error
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should not allow to set :maybe as value for visible" do
|
21
|
+
exception = SmartProperties::InvalidValueError
|
22
|
+
message = "Dummy does not accept :maybe as value for the property visible"
|
23
|
+
further_expectations = lambda { |error| expect(error.to_hash[:visible]).to eq('does not accept :maybe as value') }
|
24
|
+
|
25
|
+
expect { klass.new visible: :maybe }.to raise_error(exception, message, &further_expectations)
|
26
|
+
expect { klass.new { |i| i.visible = :maybe } }.to raise_error(exception, message, &further_expectations)
|
27
|
+
|
28
|
+
expect { instance.visible = :maybe }.to raise_error(exception, message, &further_expectations)
|
29
|
+
expect { instance[:visible] = :maybe }.to raise_error(exception, message, &further_expectations)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when used to build a class that has a property called :title that accepts either a String or a Symbol" do
|
35
|
+
subject(:klass) { DummyClass.new { property :title, accepts: [String, Symbol] } }
|
36
|
+
|
37
|
+
context "an instance of this class" do
|
38
|
+
subject(:instance) { klass.new }
|
39
|
+
|
40
|
+
it "should accept a String as title" do
|
41
|
+
expect { subject.title = "Test" }.to_not raise_error
|
42
|
+
expect { subject[:title] = "Test" }.to_not raise_error
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should accept a Symbol as title" do
|
46
|
+
expect { subject.title = :test }.to_not raise_error
|
47
|
+
expect { subject[:title] = :test }.to_not raise_error
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should not an instance of any other type' do
|
51
|
+
exception = SmartProperties::InvalidValueError
|
52
|
+
message = 'Dummy does not accept 13 as value for the property title'
|
53
|
+
further_expectations = lambda { |error| expect(error.to_hash[:title]).to eq('does not accept 13 as value') }
|
54
|
+
|
55
|
+
expect { klass.new title: 13 }.to raise_error(exception, message, &further_expectations)
|
56
|
+
expect { klass.new { |i| i.title = 13 } }.to raise_error(exception, message, &further_expectations)
|
57
|
+
|
58
|
+
expect { instance.title = 13 }.to raise_error(exception, message, &further_expectations)
|
59
|
+
expect { instance[:title] = 13 }.to raise_error(exception, message, &further_expectations)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when used to build a class that has a property called :license_plate which uses a lambda statement for accpetance checking' do
|
65
|
+
subject(:klass) do
|
66
|
+
DummyClass.new do
|
67
|
+
property :license_plate, accepts: lambda { |v| license_plate_pattern.match(v) }
|
68
|
+
|
69
|
+
def license_plate_pattern
|
70
|
+
/\w{1,2} \w{1,2} \d{1,4}/
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'an instance of this class' do
|
76
|
+
subject(:instance) { klass.new }
|
77
|
+
|
78
|
+
it 'should not a accept "invalid" as value for license_plate' do
|
79
|
+
exception = SmartProperties::InvalidValueError
|
80
|
+
message = 'Dummy does not accept "invalid" as value for the property license_plate'
|
81
|
+
further_expectations = lambda { |error| expect(error.to_hash[:license_plate]).to eq('does not accept "invalid" as value') }
|
82
|
+
|
83
|
+
expect { klass.new license_plate: "invalid" }.to raise_error(exception, message, &further_expectations)
|
84
|
+
expect { klass.new { |i| i.license_plate = "invalid" } }.to raise_error(exception, message, &further_expectations)
|
85
|
+
|
86
|
+
expect { instance.license_plate = "invalid" }.to raise_error(exception, message, &further_expectations)
|
87
|
+
expect { instance[:license_plate] = "invalid" }.to raise_error(exception, message, &further_expectations)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should accept "NE RD 1337" as license plate' do
|
91
|
+
expect { klass.new.license_plate = "NE RD 1337" }.to_not raise_error
|
92
|
+
expect { klass.new { |i| i.license_plate = "NE RD 1337" } }.to_not raise_error
|
93
|
+
|
94
|
+
expect { instance.license_plate = "NE RD 1337" }.to_not raise_error
|
95
|
+
expect { instance[:license_plate] = "NE RD 1337" }.to_not raise_error
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe SmartProperties do
|
4
|
+
it 'should add a protected class method called .property when included' do
|
5
|
+
klass = Class.new { include SmartProperties }
|
6
|
+
expect(klass.respond_to?(:property, true)).to eq(true)
|
7
|
+
expect { klass.property }.to raise_error(NoMethodError)
|
8
|
+
end
|
9
|
+
|
10
|
+
context "when used to build a class that has a property called title that utilizes the full feature set of SmartProperties" do
|
11
|
+
subject(:klass) do
|
12
|
+
default_title = double(to_title: 'chunky')
|
13
|
+
|
14
|
+
DummyClass.new do
|
15
|
+
property :title, converts: :to_title, accepts: String, required: true, default: default_title
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it { is_expected.to have_smart_property(:title) }
|
20
|
+
|
21
|
+
context "an instance of this class when initialized with no arguments" do
|
22
|
+
subject(:instance) { klass.new }
|
23
|
+
|
24
|
+
it "should have the default title" do
|
25
|
+
expect(instance.title).to eq('chunky')
|
26
|
+
expect(instance[:title]).to eq('chunky')
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should convert all values that are assigned to title into strings when using the #title= method" do
|
30
|
+
instance.title = double(to_title: 'bacon')
|
31
|
+
expect(instance.title).to eq('bacon')
|
32
|
+
|
33
|
+
instance[:title] = double(to_title: 'yummy')
|
34
|
+
expect(instance.title).to eq('yummy')
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should not allow to assign an object as title that do not respond to #to_title" do
|
38
|
+
exception = NoMethodError
|
39
|
+
message = /undefined method `to_title'/
|
40
|
+
|
41
|
+
expect { instance.title = Object.new }.to raise_error(exception, message)
|
42
|
+
expect { instance[:title] = Object.new }.to raise_error(exception, message)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should not allow to assign nil as the title" do
|
46
|
+
exception = SmartProperties::MissingValueError
|
47
|
+
message = "Dummy requires the property title to be set"
|
48
|
+
further_expectations = lambda do |error|
|
49
|
+
expect(error.to_hash[:title]).to eq('must be set')
|
50
|
+
end
|
51
|
+
|
52
|
+
expect { instance.title = nil }.to raise_error(exception, message, &further_expectations)
|
53
|
+
expect { instance[:title] = nil }.to raise_error(exception, message, &further_expectations)
|
54
|
+
|
55
|
+
expect { instance.title = double(to_title: nil) }.to raise_error(exception, message, &further_expectations)
|
56
|
+
expect { instance[:title] = double(to_title: nil) }.to raise_error(exception, message, &further_expectations)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not influence other instances that have been initialized with different attributes" do
|
60
|
+
other_instance = klass.new title: double(to_title: 'Lorem ipsum')
|
61
|
+
|
62
|
+
expect(instance.title).to eq('chunky')
|
63
|
+
expect(other_instance.title).to eq('Lorem ipsum')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'an instance of this class when initialized with a title argument' do
|
68
|
+
it "should have the title specified by the corresponding keyword argument" do
|
69
|
+
instance = klass.new(title: double(to_title: 'bacon'))
|
70
|
+
expect(instance.title).to eq('bacon')
|
71
|
+
expect(instance[:title]).to eq('bacon')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "an instance of this class when initialized with a block" do
|
76
|
+
it "should have the title specified in the block" do
|
77
|
+
instance = klass.new do |c|
|
78
|
+
c.title = double(to_title: 'bacon')
|
79
|
+
end
|
80
|
+
expect(instance.title).to eq('bacon')
|
81
|
+
expect(instance[:title]).to eq('bacon')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe SmartProperties, 'configuration error' do
|
4
|
+
subject(:klass) { DummyClass.new }
|
5
|
+
|
6
|
+
context "when defining a property with invalid configuration options" do
|
7
|
+
it "should report all invalid options" do
|
8
|
+
invalid_property_definition = lambda do
|
9
|
+
klass.class_eval do
|
10
|
+
property :title, invalid_option_1: 'boom', invalid_option_2: 'boom', invalid_option_3: 'boom'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
expect(&invalid_property_definition).to raise_error(SmartProperties::ConfigurationError, "SmartProperties do not support the following configuration options: invalid_option_1, invalid_option_2, invalid_option_3.")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe SmartProperties, 'conversion' do
|
4
|
+
context "when defining a class with a property whose converter is an object that responds to #to_proc" do
|
5
|
+
subject(:klass) do
|
6
|
+
converter = double(to_proc: lambda { |t| content_tag(:p, t.to_s) })
|
7
|
+
DummyClass.new do
|
8
|
+
property :title, converts: converter
|
9
|
+
|
10
|
+
def content_tag(name, content)
|
11
|
+
"<%s>%s</%s>" % [name, content, name]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "an instance of this class" do
|
17
|
+
subject(:instance) { klass.new }
|
18
|
+
|
19
|
+
it "should convert the property using the proc" do
|
20
|
+
instance = klass.new title: 'Chunky Bacon'
|
21
|
+
expect(instance.title).to eq("<p>Chunky Bacon</p>")
|
22
|
+
expect(instance[:title]).to eq("<p>Chunky Bacon</p>")
|
23
|
+
|
24
|
+
instance.title = "Lorem Ipsum"
|
25
|
+
expect(instance.title).to eq("<p>Lorem Ipsum</p>")
|
26
|
+
expect(instance[:title]).to eq("<p>Lorem Ipsum</p>")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe SmartProperties, 'default values' do
|
4
|
+
context 'when used to build a class that has a property called :id whose default value is a lambda statement for retrieving the object_id' do
|
5
|
+
subject(:klass) { DummyClass.new { property :id, default: lambda { object_id } } }
|
6
|
+
|
7
|
+
context "an instance of this class" do
|
8
|
+
it "should evaluate the lambda in its own scope and thus differ from every other instance" do
|
9
|
+
first_instance, second_instance = klass.new, klass.new
|
10
|
+
expect(klass.new.id).to_not eq(klass.new.id)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when used to build a class that has a property called :boom whose default value is a lambda statement that raises an exception' do
|
16
|
+
subject(:klass) { DummyClass.new { property :boom, default: lambda { raise 'Boom!' } } }
|
17
|
+
|
18
|
+
context "an instance of this class" do
|
19
|
+
it "should raise during initialization if no other value for :boom has been provided" do
|
20
|
+
expect { klass.new }.to raise_error(RuntimeError, 'Boom!')
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should not evaluate the lambda expression and thus not raise during initialization if a different value for :boom has been provided as a a parameter or in the initalization block" do
|
24
|
+
expect { klass.new(boom: 'Everything is just fine!') }.not_to raise_error
|
25
|
+
expect { klass.new { |inst| inst.boom = 'Everything is just fine!' } }.not_to raise_error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when building a class that has a property with a default value" do
|
31
|
+
subject(:klass) { DummyClass.new { property :title, default: 'Lorem Ipsum' } }
|
32
|
+
|
33
|
+
context 'an instance of that class' do
|
34
|
+
it 'should return nil for the title when the title was explicitly set to this value during initialization' do
|
35
|
+
instance = klass.new(title: nil)
|
36
|
+
expect(instance.title).to be_nil
|
37
|
+
expect(instance[:title]).to be_nil
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should return the default value if no other value has been provided during initialization' do
|
41
|
+
instance = klass.new
|
42
|
+
expect(instance.title).to eq('Lorem Ipsum')
|
43
|
+
expect(instance[:title]).to eq('Lorem Ipsum')
|
44
|
+
|
45
|
+
instance = klass.new {}
|
46
|
+
expect(instance.title).to eq('Lorem Ipsum')
|
47
|
+
expect(instance[:title]).to eq('Lorem Ipsum')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe SmartProperties, 'intheritance' do
|
4
|
+
context 'when used to build a class that has a required property with no default called :text whose getter is overriden' do
|
5
|
+
subject(:klass) do
|
6
|
+
DummyClass.new do
|
7
|
+
property :text, required: true
|
8
|
+
def text; "<em>#{super}</em>"; end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
specify "an instance of this class should raise an error during initilization if no value for :text has been specified" do
|
13
|
+
expect { klass.new }.to raise_error(SmartProperties::InitializationError)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when modeling the following class hiearchy: Base > Section > SectionWithSubtitle' do
|
18
|
+
let!(:base) do
|
19
|
+
Class.new do
|
20
|
+
attr_reader :content
|
21
|
+
def initialize(content = nil)
|
22
|
+
@content = content
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
let!(:section) { DummyClass.new(base) { property :title } }
|
27
|
+
let!(:subsection) { DummyClass.new(section) { property :subtitle } }
|
28
|
+
|
29
|
+
context 'the base class' do
|
30
|
+
it('should not respond to #properties') { expect(base).to_not respond_to(:properties) }
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'the section class' do
|
34
|
+
it('should respond to #properties') { expect(section).to respond_to(:properties) }
|
35
|
+
|
36
|
+
context 'an instance of this class' do
|
37
|
+
subject { section.new }
|
38
|
+
it { is_expected.to have_smart_property(:title) }
|
39
|
+
it { is_expected.to_not have_smart_property(:subtitle) }
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'an instance of this class when initialized with content' do
|
43
|
+
subject(:instance) { section.new('some content') }
|
44
|
+
it('should have content') { expect(instance.content).to eq('some content') }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'the subsectionclass' do
|
49
|
+
it('should respond to #properties') { expect(subsection).to respond_to(:properties) }
|
50
|
+
|
51
|
+
context 'an instance of this class' do
|
52
|
+
subject(:instance) { subsection.new }
|
53
|
+
it { is_expected.to have_smart_property(:title) }
|
54
|
+
it { is_expected.to have_smart_property(:subtitle) }
|
55
|
+
|
56
|
+
it 'should have content, a title, and a subtile when initialized with these parameters' do
|
57
|
+
instance = subsection.new('some content', title: 'some title', subtitle: 'some subtitle')
|
58
|
+
expect(instance.content).to eq('some content')
|
59
|
+
expect(instance.title).to eq('some title')
|
60
|
+
expect(instance.subtitle).to eq('some subtitle')
|
61
|
+
|
62
|
+
instance = subsection.new('some content') do |s|
|
63
|
+
s.title, s.subtitle = 'some title', 'some subtitle'
|
64
|
+
end
|
65
|
+
expect(instance.content).to eq('some content')
|
66
|
+
expect(instance.title).to eq('some title')
|
67
|
+
expect(instance.subtitle).to eq('some subtitle')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when the section class is extended with a property at runtime' do
|
73
|
+
before { section.send(:property, :type) }
|
74
|
+
|
75
|
+
context 'the section class' do
|
76
|
+
subject { section }
|
77
|
+
it { is_expected.to have_smart_property(:type) }
|
78
|
+
|
79
|
+
it 'should have content, a title, and a type when initialized with these parameters' do
|
80
|
+
instance = subsection.new('some content', title: 'some title', type: 'important')
|
81
|
+
expect(instance.content).to eq('some content')
|
82
|
+
expect(instance.title).to eq('some title')
|
83
|
+
expect(instance.type).to eq('important')
|
84
|
+
|
85
|
+
instance = subsection.new('some content') do |s|
|
86
|
+
s.title, s.type = 'some title', 'important'
|
87
|
+
end
|
88
|
+
expect(instance.content).to eq('some content')
|
89
|
+
expect(instance.title).to eq('some title')
|
90
|
+
expect(instance.type).to eq('important')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'the subsection class' do
|
95
|
+
subject { subsection }
|
96
|
+
it { is_expected.to have_smart_property(:type) }
|
97
|
+
|
98
|
+
it 'should have content, a title, a subtitle, and a type when initialized with these parameters' do
|
99
|
+
instance = subsection.new('some content', title: 'some title', subtitle: 'some subtitle', type: 'important')
|
100
|
+
expect(instance.content).to eq('some content')
|
101
|
+
expect(instance.title).to eq('some title')
|
102
|
+
expect(instance.subtitle).to eq('some subtitle')
|
103
|
+
expect(instance.type).to eq('important')
|
104
|
+
|
105
|
+
instance = subsection.new('some content') do |s|
|
106
|
+
s.title, s.subtitle, s.type = 'some title', 'some subtitle', 'important'
|
107
|
+
end
|
108
|
+
expect(instance.content).to eq('some content')
|
109
|
+
expect(instance.title).to eq('some title')
|
110
|
+
expect(instance.subtitle).to eq('some subtitle')
|
111
|
+
expect(instance.type).to eq('important')
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'when the section class overrides the getter of the title property and uses super to retrieve the property\'s original value' do
|
117
|
+
before do
|
118
|
+
section.class_eval do
|
119
|
+
def title; super.to_s.upcase; end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
specify 'an instance of the section class should transform the value as defined in the overridden getter' do
|
124
|
+
instance = section.new(title: 'some title')
|
125
|
+
expect(instance.title).to eq('SOME TITLE')
|
126
|
+
expect(instance[:title]).to eq('SOME TITLE')
|
127
|
+
end
|
128
|
+
|
129
|
+
specify 'an instance of the subsection class should transform the value as defined in the overridden getter in the superclass' do
|
130
|
+
instance = subsection.new(title: 'some title')
|
131
|
+
expect(instance.title).to eq('SOME TITLE')
|
132
|
+
expect(instance[:title]).to eq('SOME TITLE')
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe SmartProperties do
|
4
|
+
context "when building a class that has a property which is required and has no default" do
|
5
|
+
subject(:klass) { DummyClass.new { property :title, required: true } }
|
6
|
+
|
7
|
+
context 'an instance of this class' do
|
8
|
+
it 'should have the correct title when provided with a title during initialization' do
|
9
|
+
instance = klass.new title: 'Lorem Ipsum'
|
10
|
+
expect(instance.title).to eq('Lorem Ipsum')
|
11
|
+
expect(instance[:title]).to eq('Lorem Ipsum')
|
12
|
+
|
13
|
+
instance = klass.new { |i| i.title = 'Lorem Ipsum' }
|
14
|
+
expect(instance.title).to eq('Lorem Ipsum')
|
15
|
+
expect(instance[:title]).to eq('Lorem Ipsum')
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should raise an error stating that required properties are missing when initialized without a title" do
|
19
|
+
exception = SmartProperties::InitializationError
|
20
|
+
message = "Dummy requires the following properties to be set: title"
|
21
|
+
further_expectations = lambda { |error| expect(error.to_hash[:title]).to eq('must be set') }
|
22
|
+
|
23
|
+
expect { klass.new }.to raise_error(exception, message, &further_expectations)
|
24
|
+
expect { klass.new {} }.to raise_error(exception, message, &further_expectations)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should not allow to set nil as the property's value" do
|
28
|
+
instance = klass.new title: 'Lorem Ipsum'
|
29
|
+
|
30
|
+
exception = SmartProperties::MissingValueError
|
31
|
+
message = "Dummy requires the property title to be set"
|
32
|
+
further_expectations = lambda do |error|
|
33
|
+
expect(error.to_hash[:title]).to eq('must be set')
|
34
|
+
end
|
35
|
+
|
36
|
+
expect { instance.title = nil }.to raise_error(exception, message, &further_expectations)
|
37
|
+
expect { instance[:title] = nil }.to raise_error(exception, message, &further_expectations)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when building a class that has a property name which is only required if the property anonymous is set to false" do
|
43
|
+
subject(:klass) do
|
44
|
+
DummyClass.new do
|
45
|
+
property :name, required: lambda { not anonymous }
|
46
|
+
property :anonymous, accepts: [true, false], default: true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should not raise an error when created with no arguments" do
|
51
|
+
expect { klass.new }.to_not raise_error
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should raise an error indicating that a required property was not specified when created with no name and anonymous being set to false" do
|
55
|
+
exception = SmartProperties::InitializationError
|
56
|
+
message = "Dummy requires the following properties to be set: name"
|
57
|
+
further_expectations = lambda { |error| expect(error.to_hash[:name]).to eq("must be set") }
|
58
|
+
|
59
|
+
expect { klass.new anonymous: false }.to raise_error(exception, message, &further_expectations)
|
60
|
+
expect { klass.new { |i| i.anonymous = false } }.to raise_error(exception, message, &further_expectations)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should not raise an error when created with a name and anonymous being set to false" do
|
64
|
+
expect { klass.new name: "John Doe", anonymous: false }.to_not raise_error
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when building a class that has a property which is required and has false as default" do
|
69
|
+
subject(:klass) { DummyClass.new { property :flag, required: true, default: false } }
|
70
|
+
|
71
|
+
context 'an instance of this class' do
|
72
|
+
it 'should return true as value for this property if provided with this value for the property during initialization' do
|
73
|
+
instance = klass.new flag: true
|
74
|
+
expect(instance.flag).to eq(true)
|
75
|
+
expect(instance[:flag]).to eq(true)
|
76
|
+
|
77
|
+
instance = klass.new { |i| i.flag = true }
|
78
|
+
expect(instance.flag).to eq(true)
|
79
|
+
expect(instance[:flag]).to eq(true)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should return false as value for this property when initialized with no arguments' do
|
83
|
+
instance = klass.new
|
84
|
+
expect(instance.flag).to eq(false)
|
85
|
+
expect(instance[:flag]).to eq(false)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when building a class that has a required property with a default value and a malicious converter that always returns nil" do
|
91
|
+
subject(:klass) { DummyClass.new { property :title, required: true, converts: ->(_) { nil }, default: "Lorem Ipsum" } }
|
92
|
+
|
93
|
+
context 'an instance of this class' do
|
94
|
+
it "should raise an error when initialized" do
|
95
|
+
exception = SmartProperties::MissingValueError
|
96
|
+
message = "Dummy requires the property title to be set"
|
97
|
+
further_expectations = lambda { |error| expect(error.to_hash[:title]).to eq("must be set") }
|
98
|
+
|
99
|
+
expect { klass.new }.to raise_error(exception, message)
|
100
|
+
expect { klass.new(title: 'Lorem Ipsum') }.to raise_error(exception, message, &further_expectations)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smart_properties
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
4
|
+
version: 1.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Tennhard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -57,8 +57,15 @@ files:
|
|
57
57
|
- Rakefile
|
58
58
|
- lib/smart_properties.rb
|
59
59
|
- smart_properties.gemspec
|
60
|
-
- spec/
|
60
|
+
- spec/acceptance_checking_spec.rb
|
61
|
+
- spec/base_spec.rb
|
62
|
+
- spec/configuration_error_spec.rb
|
63
|
+
- spec/conversion_spec.rb
|
64
|
+
- spec/default_values_spec.rb
|
65
|
+
- spec/inheritance_spec.rb
|
66
|
+
- spec/required_values_spec.rb
|
61
67
|
- spec/spec_helper.rb
|
68
|
+
- spec/support/dummy_class.rb
|
62
69
|
- spec/support/smart_property_matcher.rb
|
63
70
|
homepage: ''
|
64
71
|
licenses: []
|
@@ -84,7 +91,14 @@ signing_key:
|
|
84
91
|
specification_version: 4
|
85
92
|
summary: SmartProperties – Ruby accessors on steroids
|
86
93
|
test_files:
|
87
|
-
- spec/
|
94
|
+
- spec/acceptance_checking_spec.rb
|
95
|
+
- spec/base_spec.rb
|
96
|
+
- spec/configuration_error_spec.rb
|
97
|
+
- spec/conversion_spec.rb
|
98
|
+
- spec/default_values_spec.rb
|
99
|
+
- spec/inheritance_spec.rb
|
100
|
+
- spec/required_values_spec.rb
|
88
101
|
- spec/spec_helper.rb
|
102
|
+
- spec/support/dummy_class.rb
|
89
103
|
- spec/support/smart_property_matcher.rb
|
90
104
|
has_rdoc:
|