skn_utils 1.4.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.
@@ -0,0 +1,123 @@
1
+ ##
2
+ # spec/lib/skn_utils/generic_bean_spec.rb
3
+ #
4
+
5
+ RSpec.describe SknUtils::PageControls, "PageControls Marshal'able Bean class " do
6
+ let(:object) {
7
+ SknUtils::PageControls.new({one: "one",
8
+ two: "two",
9
+ three: {four: 4, five: 5, six: {seven: 7, eight: "eight" }},
10
+ four: {any_key: "any value"},
11
+ five: [],
12
+ six: [{any_key: "any value"},
13
+ {four: 4,
14
+ five: 5,
15
+ six: {seven: 7, eight: "eight" },
16
+ twenty:[{seven: 7, eight: 8 }, {nine: 9, ten: 10 }]
17
+ }
18
+ ]
19
+ })
20
+ }
21
+
22
+ context "Internal Operations, assuming :dept => :multi_with_arrays and enable_serialization => true" do
23
+ it "Creates an empty bean if no params are passed" do
24
+ is_expected.to be
25
+ end
26
+ it "Can be Marshalled after dynamically adding a key/value." do
27
+ expect { object.fifty = {any_key: "any value"} }.not_to raise_error
28
+ expect { object.sixty = 60 }.not_to raise_error
29
+ dmp = obj = ""
30
+ expect { dmp = Marshal.dump(object) }.not_to raise_error
31
+ expect { obj = Marshal.load(dmp) }.not_to raise_error
32
+ expect(obj).to be_a(SknUtils::PageControls)
33
+ expect( object.fifty.any_key).to eql "any value"
34
+ expect( object.sixty).to eql 60
35
+ end
36
+ it "Initializes from a hash" do
37
+ expect(object).to be
38
+ end
39
+ it "Does not modify the base class, only singleton instance methods" do
40
+ obj1 = SknUtils::PageControls.new({one: "one", two: "two"})
41
+ obj2 = SknUtils::PageControls.new({three: "3", four: "4"})
42
+ expect(obj1.one).to eql "one"
43
+ expect(obj2.three).to eql "3"
44
+ expect(obj2.one?).to be false
45
+ expect(obj1.three?).to be false
46
+ expect { obj1.three }.to raise_error NoMethodError
47
+ expect { obj2.one }.to raise_error NoMethodError
48
+ end
49
+ it "Supports predicates(?)" do
50
+ expect(object.one?).to be true
51
+ expect(object.three.five?).to be true
52
+ end
53
+ it "Does not support - respond_to - methods, because it has no accessor methods" do
54
+ expect(object).not_to respond_to(:one)
55
+ expect(object.one).to eql "one"
56
+ end
57
+ it "nest objects if multi-level hash is given" do
58
+ expect(object.three).to be_a(SknUtils::PageControls)
59
+ expect(object.three.five).to eq(5)
60
+ end
61
+ it "nest objects if multi-level array of hashes is given" do
62
+ expect(object.six).to be_a(Array)
63
+ expect(object.six.first).to be_a(SknUtils::PageControls)
64
+ expect(object.six.last).to be_a(SknUtils::PageControls)
65
+ expect(object.six.last.six.eight).to eq('eight')
66
+ end
67
+ it "nest objects if multi-level array of hashes, and an element contains another array of hashes, is given" do
68
+ expect(object.six.first).to be_a(SknUtils::PageControls)
69
+ expect(object.six).to be_a(Array)
70
+ expect(object.six.last.twenty).to be_a(Array)
71
+ expect(object.six.last.twenty.first).to be_a(SknUtils::PageControls)
72
+ expect(object.six.last.twenty.last).to be_a(SknUtils::PageControls)
73
+ expect(object.six.last.twenty.first.eight).to eq(8)
74
+ expect(object.six.last.twenty.last.ten).to eq(10)
75
+ end
76
+ it "nest arrays of objects if array of hashes is dynamically given (post-create)" do
77
+ expect { object.one_array = [{one: "one", two: "two"},{one: 1, two: 2}] }.not_to raise_error
78
+ expect(object.one_array.first.one).to eql("one")
79
+ expect(object.one_array.last.two).to eql(2)
80
+ expect(object.one_array[0]).to be_a(SknUtils::PageControls)
81
+ end
82
+ it "#attributes method returns a hash of all attributes and their values." do
83
+ expect(object.attributes).to be_a(Hash)
84
+ expect(object.attributes[:one]).to be_eql("one")
85
+ expect(object.attributes[:three]).to be_a(Hash)
86
+ expect(object.attributes[:six].last[:six][:eight]).to eql('eight')
87
+ end
88
+ end
89
+
90
+ shared_examples_for "retains initialization options" do
91
+ it "retains depth_level option flag" do
92
+ expect(@obj.depth_level).to eql(:multi_with_arrays)
93
+ end
94
+ it "retains serialization option flag" do
95
+ expect(@obj.serialization_required?).to be true
96
+ end
97
+ end
98
+
99
+ context "Basic Operations without marshaling " do
100
+ before :each do
101
+ @obj = object
102
+ end
103
+ it_behaves_like "retains initialization options"
104
+ it_behaves_like "marshalable ruby pojo"
105
+ end
106
+ context "Basic Operations after Yaml marshaling " do
107
+ before :each do
108
+ dmp = YAML::dump(object)
109
+ @obj = YAML::load(dmp)
110
+ end
111
+ it_behaves_like "retains initialization options"
112
+ it_behaves_like "marshalable ruby pojo"
113
+ end
114
+ context "Basic Operations after Marshal marshaling " do
115
+ before :each do
116
+ dmp = Marshal.dump(object)
117
+ @obj = Marshal.load(dmp)
118
+ end
119
+ it_behaves_like "retains initialization options"
120
+ it_behaves_like "marshalable ruby pojo"
121
+ end
122
+
123
+ end
@@ -0,0 +1,92 @@
1
+ ##
2
+ # spec/lib/skn_utils/result_bean_spec.rb
3
+ #
4
+
5
+ RSpec.describe SknUtils::ResultBean, "Result Bean class - Basic useage." do
6
+ let(:object) {
7
+ SknUtils::ResultBean.new({one: "one",
8
+ two: "two",
9
+ three: {four: 4, five: 5, six: {seven: 7, eight: "eight" }},
10
+ four: {any_key: "any value"},
11
+ five: []
12
+ })
13
+ }
14
+
15
+ context "Internal Operations, assuming :dept => :multi and enable_serialization => false" do
16
+ it "Creates an empty bean if no params are passed" do
17
+ is_expected.to be
18
+ end
19
+ it "Initializes from a hash" do
20
+ expect(SknUtils::ResultBean.new({one: "one", two: "two"})).to be
21
+ end
22
+ it "Does not modify the base class, only singleton instance methods" do
23
+ obj1 = SknUtils::ResultBean.new({one: "one", two: "two"})
24
+ obj2 = SknUtils::ResultBean.new({three: 3, four: "4"})
25
+ expect(obj1.one).to eql "one"
26
+ expect(obj2.three).to eql 3
27
+ expect(obj2.one?).to be false
28
+ expect(obj1.three?).to be false
29
+ expect { obj1.three }.to raise_error NoMethodError
30
+ expect { obj2.one }.to raise_error NoMethodError
31
+ end
32
+ it "Supports - respond_to - methods, because it has accessor methods" do
33
+ expect(object).to respond_to(:one)
34
+ end
35
+ end
36
+
37
+ shared_examples_for "retains initialization options" do
38
+ it "retains depth_level option flag" do
39
+ expect(@obj.depth_level).to eql(:multi)
40
+ end
41
+ it "retains serialization option flag" do
42
+ expect(@obj.serialization_required?).to be false
43
+ end
44
+ end
45
+
46
+ context "Basic Operations after Marshal marshaling " do
47
+ it "Singleton objects (like ResultBean) cannot be marshaled" do
48
+ expect { Marshal.dump(object) }.to raise_error TypeError
49
+ end
50
+ end
51
+ context "Basic Operations without marshaling " do
52
+ before :each do
53
+ @obj = object
54
+ end
55
+ it_behaves_like "retains initialization options"
56
+ it_behaves_like "ruby pojo"
57
+ end
58
+ context "Basic Operations after Yaml marshaling " do
59
+ before :each do
60
+ dmp = YAML::dump(object)
61
+ @obj = YAML::load(dmp)
62
+ end
63
+ it_behaves_like "retains initialization options"
64
+ it_behaves_like "ruby pojo"
65
+ end
66
+ context "ResultBeans stripped of their internal singleton accessors can be Marshaled! " do
67
+ before :each do
68
+ dmp = YAML::dump(object)
69
+ obj = YAML::load(dmp) # Yaml'ing removes singleton accessor methods'
70
+ # by initializing object without using its
71
+ # initialize() method
72
+
73
+ dmp = Marshal.dump(obj) # Now Marshal load/dump will work
74
+ @obj = Marshal.load(dmp) # Use GenericBean if Marshal support is needed
75
+ end
76
+ it_behaves_like "retains initialization options"
77
+ it_behaves_like "ruby pojo"
78
+ end
79
+ context "Basic Operations after Yaml marshaling via restored accessors " do
80
+ before :each do
81
+ dmp = YAML::dump(object)
82
+ @obj = YAML::load(dmp)
83
+ # Restore setters
84
+ @obj.attributes.keys.each do |k|
85
+ @obj.singleton_class.send(:attr_accessor, k)
86
+ end
87
+ end
88
+ it_behaves_like "retains initialization options"
89
+ it_behaves_like "ruby pojo"
90
+ end
91
+
92
+ end
@@ -0,0 +1,178 @@
1
+ ##
2
+ # spec/lib/skn_utils/result_bean_with_errors_spec.rb
3
+ #
4
+
5
+ RSpec.describe SknUtils::ResultBeanWithErrors, "Result Bean class with ActiveModel::Errors object " do
6
+ let(:object) {
7
+ SknUtils::ResultBeanWithErrors.new({one: "one",
8
+ two: "two",
9
+ three: {four: 4, five: 5, six: {seven: 7, eight: "eight" }},
10
+ four: {any_key: "any value"},
11
+ five: []
12
+ })
13
+ }
14
+
15
+ context "Internal Operations, assuming :dept => :multi and enable_serialization => false" do
16
+ it "Creates an empty bean if no params are passed" do
17
+ is_expected.to be
18
+ expect(subject.errors).to be
19
+ end
20
+ it "Initializes from a hash that DOES NOT include an errors.object " do
21
+ expect(SknUtils::ResultBeanWithErrors.new({one: "one", two: "two"})).to be
22
+ end
23
+ it "Initializes from a hash that DOES include an errors.object " do
24
+ errors = ActiveModel::Errors.new(self) ## VERY BAD IDEAL
25
+ expect(SknUtils::ResultBeanWithErrors.new({one: "one", two: "two", errors: errors})).to be
26
+ end
27
+ it "Does not modify the base class, only singleton instance methods" do
28
+ obj1 = SknUtils::ResultBeanWithErrors.new({one: "one", two: "two"})
29
+ obj2 = SknUtils::ResultBeanWithErrors.new({three: "3", four: "4"})
30
+ expect(obj1.one).to eql "one"
31
+ expect(obj2.three).to eql "3"
32
+ expect(obj2.one?).to be_falsey
33
+ expect(obj1.three?).to be_falsey
34
+ expect { obj1.three }.to raise_error NoMethodError
35
+ expect { obj2.one }.to raise_error NoMethodError
36
+ end
37
+ it "Supports - respond_to - methods, because it has accessor methods" do
38
+ expect(object).to respond_to(:one)
39
+ end
40
+ end
41
+
42
+ shared_examples_for "retains initialization options" do
43
+ it "retains depth_level option flag" do
44
+ expect(@obj.depth_level).to eql(:multi)
45
+ end
46
+ it "retains serialization option flag" do
47
+ expect(@obj.serialization_required?).to be false
48
+ end
49
+ end
50
+
51
+ context "ActiveModel:Errors object" do
52
+ it "#errors method returns an ActiveModel::Errors object" do
53
+ obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: "two"})
54
+ expect(obj.errors).to be_an_instance_of(ActiveModel::Errors)
55
+ end
56
+
57
+ it "#errors method accepts additional errors" do
58
+ obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: "two"})
59
+ obj.errors.add(:one,"must be numeric.")
60
+ expect(obj.errors.size).to be 1
61
+ end
62
+
63
+ it "#errors.full_messages method returns messages" do
64
+ obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: "two"})
65
+ obj.errors.add(:one,"must be numeric.")
66
+ expect(obj.errors.full_messages.first).to include("numeric")
67
+ end
68
+
69
+ it "#errors.add_on_empty method correctly adds new errors" do
70
+ obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
71
+ obj.errors.add_on_empty(:two)
72
+ expect(obj.errors.count).to be 1
73
+ end
74
+
75
+ it "#errors.add_on_blank method correctly adds new errors" do
76
+ obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
77
+ obj.errors.add_on_blank(:two)
78
+ expect(obj.errors.count).to be 1
79
+ end
80
+
81
+ it "#errors.get method correctly retrieves existing message by attribute" do
82
+ obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
83
+ obj.errors.add_on_blank(:two)
84
+ expect(obj.errors.get(:two).first).to include("blank")
85
+ end
86
+
87
+ it "#errors[] method correctly retrieves existing message by attribute" do
88
+ obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
89
+ obj.errors.add_on_blank(:two)
90
+ expect(obj.errors[:two].first).to include("blank")
91
+ end
92
+
93
+ it "#errors.set method correctly adds sets message on attribute" do
94
+ obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
95
+ obj.errors.set(:two, "Required value, must not be empty")
96
+ expect(obj.errors.get(:two)).to include("Required")
97
+ end
98
+
99
+ it "#errors.include? method correctly determines that an error exists for the given key" do
100
+ obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
101
+ obj.errors.add(:two, "Required value, must not be empty")
102
+ result = obj.errors.include?(:two)
103
+ expect(result).to be_truthy
104
+ result = obj.errors.include?(:one)
105
+ expect(result).to be_falsey
106
+ end
107
+
108
+ it "#errors.delete method correctly removes an error for the given key" do
109
+ obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
110
+ obj.errors.add(:two, "Required value, must not be empty")
111
+ result = obj.errors.include?(:two)
112
+ expect(result).to be_truthy
113
+ obj.errors.delete(:two)
114
+ result = obj.errors.include?(:two)
115
+ expect(result).to be_falsey
116
+ end
117
+ end
118
+
119
+ context "Serialization" do
120
+ before :each do
121
+ @obj = object
122
+ end
123
+ it "Serialization does not include the errors object." do
124
+ expect(@obj.to_hash[:errors]).not_to be
125
+ expect(@obj.errors).to be_a(ActiveModel::Errors)
126
+ end
127
+
128
+ it_behaves_like "retains initialization options"
129
+ it_behaves_like "ruby pojo"
130
+ end
131
+
132
+ context "Basic Operations after Marshal marshaling " do
133
+ it "Singleton objects (like ResultBean) cannot be marshaled" do
134
+ expect { Marshal.dump(object) }.to raise_error TypeError
135
+ end
136
+ end
137
+ context "Basic Operations without marshaling " do
138
+ before :each do
139
+ @obj = object
140
+ end
141
+ it_behaves_like "retains initialization options"
142
+ it_behaves_like "ruby pojo"
143
+ end
144
+ context "Basic Operations after Yaml marshaling " do
145
+ before :each do
146
+ dmp = YAML::dump(object)
147
+ @obj = YAML::load(dmp)
148
+ end
149
+ it_behaves_like "retains initialization options"
150
+ it_behaves_like "ruby pojo"
151
+ end
152
+ context "ResultBeans stripped of their internal singleton accessors can be Marshaled! " do
153
+ before :each do
154
+ dmp = YAML::dump(object)
155
+ obj = YAML::load(dmp) # Yaml'ing removes singleton accessor methods'
156
+ # by initializing object without using its
157
+ # initialize() method
158
+
159
+ dmp = Marshal.dump(obj) # Now Marshal load/dump will work
160
+ @obj = Marshal.load(dmp) # Use GenericBean if Marshal support is needed
161
+ end
162
+ it_behaves_like "retains initialization options"
163
+ it_behaves_like "ruby pojo"
164
+ end
165
+ context "Basic Operations after Yaml marshaling via restored accessors " do
166
+ before :each do
167
+ dmp = YAML::dump(object)
168
+ @obj = YAML::load(dmp)
169
+ # Restore setters
170
+ @obj.attributes.keys.each do |k|
171
+ @obj.singleton_class.send(:attr_accessor, k)
172
+ end
173
+ end
174
+ it_behaves_like "retains initialization options"
175
+ it_behaves_like "ruby pojo"
176
+ end
177
+
178
+ end
@@ -0,0 +1,39 @@
1
+ ENV['RAILS_ENV'] ||= 'test'
2
+
3
+ require 'active_model'
4
+ require 'skn_utils'
5
+ require 'rspec'
6
+
7
+ # Shared Examples and Support Routines
8
+ Dir["./spec/support/**/*.rb"].sort.each { |f| require f}
9
+
10
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
11
+ RSpec.configure do |config|
12
+ Kernel.srand config.seed
13
+
14
+ config.order = :random
15
+ config.color = true
16
+ config.tty = false
17
+ config.formatter = :progress #:html, :textmate, :documentation
18
+
19
+ config.filter_run :focus
20
+ config.run_all_when_everything_filtered = true
21
+
22
+ config.disable_monkey_patching! # -- breaks rspec runtime
23
+ config.warnings = true
24
+ # config.profile_examples = 10
25
+
26
+ if config.files_to_run.one?
27
+ config.formatter = :documentation
28
+ end
29
+
30
+ config.expect_with :rspec do |expectations|
31
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
32
+ expectations.syntax = :expect
33
+ end
34
+
35
+ config.mock_with :rspec do |mocks|
36
+ mocks.verify_partial_doubles = true
37
+ end
38
+
39
+ end
@@ -0,0 +1,55 @@
1
+ ##
2
+ # <root>/spec/support/shared_example_marshalable_ruby_pojo.rb
3
+ #
4
+ # refs: page_controls, generic_bean
5
+ #
6
+
7
+ RSpec.shared_examples "marshalable ruby pojo" do
8
+ it "provides getters" do
9
+ expect(@obj.one).to be_eql("one")
10
+ expect(@obj.two).to be_eql("two")
11
+ end
12
+ it "provides setters" do
13
+ @obj.one = "1"
14
+ @obj.two = "2"
15
+ expect(@obj.two).to be_eql("2")
16
+ expect(@obj.one).to be_eql("1")
17
+ end
18
+ it "#clear_attribute sets given attribute to nil." do
19
+ expect(@obj.two).to be_eql("two")
20
+ expect(@obj.clear_two).to be_nil
21
+ end
22
+ it "#attribute? returns true or false based on contents of attribute." do
23
+ expect(@obj.two?).to be true
24
+ @obj.two = false
25
+ expect(@obj.two?).to be false
26
+ @obj.clear_two
27
+ expect(@obj.two?).to be false
28
+ expect(@obj.three?).to be true
29
+ expect(@obj.four?).to be true
30
+ @obj.clear_three
31
+ expect(@obj.three?).to be false
32
+ @obj.clear_four
33
+ expect(@obj.four?).to be false
34
+ end
35
+ it "#attribute? returns false when attribute is not defined or unknown" do
36
+ expect(@obj.address?).to be false
37
+ end
38
+ it "raises an 'NoMethodError' error when attribute does not exist" do
39
+ expect { @obj.address }.to raise_error NoMethodError
40
+ end
41
+ context "transformations are enabled with " do
42
+ it "#to_json method returns a serialized version of this object." do
43
+ expect(object.to_json).to include(":\"")
44
+ end
45
+ it "#to_xml method returns a serialized version of this object." do
46
+ expect(object.to_xml).to include("xml version")
47
+ end
48
+ it "#to_hash method returns a serialized version of this object." do
49
+ expect(object.to_hash).to be_a(Hash)
50
+ end
51
+ it "#attributes method returns original input hash." do
52
+ expect(object.attributes).to be_a(Hash)
53
+ end
54
+ end
55
+ end