cistern 2.2.7 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -3
- data/CHANGELOG.md +57 -0
- data/README.md +13 -13
- data/lib/cistern/attributes.rb +82 -46
- data/lib/cistern/client.rb +73 -18
- data/lib/cistern/collection.rb +31 -6
- data/lib/cistern/model.rb +46 -11
- data/lib/cistern/request.rb +33 -8
- data/lib/cistern/singular.rb +12 -4
- data/lib/cistern/version.rb +1 -1
- data/spec/attributes_spec.rb +166 -0
- data/spec/collection_spec.rb +18 -2
- data/spec/coverage_spec.rb +35 -0
- data/spec/mock_data_spec.rb +2 -2
- data/spec/model_spec.rb +11 -163
- data/spec/request_spec.rb +29 -8
- data/spec/singular_spec.rb +9 -2
- data/spec/spec_helper.rb +9 -3
- metadata +6 -2
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'coverage', :coverage do
|
4
|
+
class CoverageSpec < Sample::Model
|
5
|
+
identity :id
|
6
|
+
|
7
|
+
attribute :used, type: :string
|
8
|
+
attribute :unused, type: :string
|
9
|
+
end
|
10
|
+
|
11
|
+
let!(:obj) { CoverageSpec.new(used: 'foo', unused: 'bar') }
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
CoverageSpec.attributes[:used][:coverage_hits] = 0
|
15
|
+
expect(obj.used).to eq('foo') # once
|
16
|
+
expect(obj.used).to eq('foo') # twice
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should store the file path where the attribute was defined' do
|
20
|
+
expect(CoverageSpec.attributes[:used][:coverage_file]).to eq(__FILE__)
|
21
|
+
expect(CoverageSpec.attributes[:unused][:coverage_file]).to eq(__FILE__)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should store the line number where the attribute was defined' do
|
25
|
+
src_lines = File.read(__FILE__).lines
|
26
|
+
|
27
|
+
expect(src_lines[CoverageSpec.attributes[:used][:coverage_line] - 1]).to match(/attribute :used/)
|
28
|
+
expect(src_lines[CoverageSpec.attributes[:unused][:coverage_line] - 1]).to match(/attribute :unused/)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should store how many times an attribute's reader is called" do
|
32
|
+
expect(CoverageSpec.attributes[:used][:coverage_hits]).to eq(2)
|
33
|
+
expect(CoverageSpec.attributes[:unused][:coverage_hits]).to eq(0)
|
34
|
+
end
|
35
|
+
end
|
data/spec/mock_data_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe 'mock data' do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def mock(diagnosis)
|
9
|
-
|
9
|
+
cistern.data.store(:diagnosis, cistern.data.fetch(:diagnosis) + [diagnosis])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -15,7 +15,7 @@ describe 'mock data' do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def mock(treatment)
|
18
|
-
|
18
|
+
cistern.data[:treatments] += [treatment]
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
data/spec/model_spec.rb
CHANGED
@@ -8,11 +8,11 @@ describe 'Cistern::Model' do
|
|
8
8
|
attribute :properties
|
9
9
|
|
10
10
|
def save
|
11
|
-
|
11
|
+
dirty_attributes
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
it 'should merge and save attributes' do
|
15
|
+
it 'should merge and save dirty attributes' do
|
16
16
|
model = UpdateSpec.new(name: 'steve')
|
17
17
|
model.save
|
18
18
|
|
@@ -55,7 +55,7 @@ describe 'Cistern::Model' do
|
|
55
55
|
end
|
56
56
|
|
57
57
|
class SpecificModelService::Jimbob < SpecificModelService::Model
|
58
|
-
|
58
|
+
cistern_method :john_boy
|
59
59
|
end
|
60
60
|
|
61
61
|
expect(SpecificModelService.new).not_to respond_to(:jimbob)
|
@@ -80,170 +80,18 @@ describe 'Cistern::Model' do
|
|
80
80
|
expect(duplicate.name).to eq('string')
|
81
81
|
end
|
82
82
|
|
83
|
-
|
84
|
-
class
|
85
|
-
|
86
|
-
attribute :name, type: :string
|
87
|
-
attribute :created_at, type: :time
|
88
|
-
attribute :flag, type: :boolean
|
89
|
-
attribute :list, type: :array
|
90
|
-
attribute :number, type: :integer
|
91
|
-
attribute :floater, type: :float
|
92
|
-
attribute :butternut_id, squash: %w(squash id), type: :integer
|
93
|
-
attribute :butternut_type, squash: %w(squash type)
|
94
|
-
attribute :squash
|
95
|
-
attribute :vegetable, aliases: 'squash'
|
96
|
-
attribute :custom, parser: lambda { |v, _| "X!#{v}" }
|
97
|
-
attribute :default, default: 'im a squash'
|
98
|
-
attribute :string_allow_nil, type: :string, allow_nil: true
|
99
|
-
|
100
|
-
attribute :same_alias_1, aliases: 'nested'
|
101
|
-
attribute :same_alias_2, aliases: 'nested'
|
102
|
-
|
103
|
-
attribute :same_alias_squashed_1, squash: %w(nested attr_1)
|
104
|
-
attribute :same_alias_squashed_2, squash: %w(nested attr_2)
|
105
|
-
attribute :same_alias_squashed_3, squash: %w(nested attr_2)
|
106
|
-
attribute :adam_attributes, aliases: 'attributes'
|
107
|
-
|
108
|
-
def save
|
109
|
-
requires :flag
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'should parse string' do
|
114
|
-
expect(TypeSpec.new(name: 1).name).to eq('1')
|
115
|
-
expect(TypeSpec.new(name: "b").name).to eq('b')
|
116
|
-
expect(TypeSpec.new(name: nil).name).to eq("")
|
117
|
-
end
|
118
|
-
|
119
|
-
it 'should allow nils in string types' do
|
120
|
-
expect(TypeSpec.new(string_allow_nil: nil).string_allow_nil).to eq(nil)
|
121
|
-
end
|
122
|
-
it "should handle a 'attributes' aliased attribute" do
|
123
|
-
expect(TypeSpec.new(attributes: 'x').adam_attributes).to eq('x')
|
124
|
-
end
|
125
|
-
|
126
|
-
it 'should parse time' do
|
127
|
-
time = Time.now
|
128
|
-
created_at = TypeSpec.new(created_at: time.to_s).created_at
|
129
|
-
expect(created_at).to be_a(Time)
|
130
|
-
expect(created_at.to_i).to eq(time.to_i)
|
131
|
-
end
|
132
|
-
|
133
|
-
it 'should parse boolean' do
|
134
|
-
expect(TypeSpec.new(flag: 'false').flag).to be_falsey
|
135
|
-
expect(TypeSpec.new(flag: 'true').flag).to be_truthy
|
136
|
-
expect(TypeSpec.new(flag: false).flag).to be_falsey
|
137
|
-
expect(TypeSpec.new(flag: true).flag).to be_truthy
|
138
|
-
expect(TypeSpec.new(flag: '0').flag).to be_falsey
|
139
|
-
expect(TypeSpec.new(flag: '1').flag).to be_truthy
|
140
|
-
expect(TypeSpec.new(flag: 0).flag).to be_falsey
|
141
|
-
expect(TypeSpec.new(flag: 1).flag).to be_truthy
|
142
|
-
expect(TypeSpec.new(flag: false)).not_to be_flag
|
143
|
-
expect(TypeSpec.new(flag: true)).to be_flag
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'should parse an array' do
|
147
|
-
expect(TypeSpec.new(list: []).list).to eq([])
|
148
|
-
expect(TypeSpec.new(list: 'item').list).to eq(['item'])
|
149
|
-
end
|
150
|
-
|
151
|
-
it 'should parse a float' do
|
152
|
-
expect(TypeSpec.new(floater: '0.01').floater).to eq(0.01)
|
153
|
-
expect(TypeSpec.new(floater: 0.01).floater).to eq(0.01)
|
154
|
-
end
|
155
|
-
|
156
|
-
it 'should use custom parser' do
|
157
|
-
expect(TypeSpec.new(custom: '15').custom).to eq('X!15')
|
158
|
-
end
|
159
|
-
|
160
|
-
it 'should squash, cast, alias an attribute and keep a vanilla reference' do
|
161
|
-
# vanilla squash
|
162
|
-
expect(TypeSpec.new({ 'squash' => { 'id' => '12', 'type' => 'fred' } }).butternut_type).to eq('fred')
|
163
|
-
expect(TypeSpec.new({ 'squash' => { 'id' => '12', 'type' => nil } }).butternut_type).to be_nil
|
164
|
-
expect(TypeSpec.new({ 'squash' => nil }).butternut_type).to be_nil
|
165
|
-
|
166
|
-
# composite processors: squash and cast
|
167
|
-
expect(TypeSpec.new({ 'squash' => { 'id' => '12', 'type' => 'fred' } }).butternut_id).to eq(12)
|
168
|
-
expect(TypeSpec.new({ 'squash' => { 'id' => nil, 'type' => 'fred' } }).butternut_id).to be_nil
|
169
|
-
expect(TypeSpec.new({ 'squash' => { 'type' => 'fred' } }).butternut_id).to be_nil
|
170
|
-
|
171
|
-
# override intermediate processing
|
172
|
-
expect(TypeSpec.new({ 'squash' => { 'id' => '12', 'type' => 'fred' } }).squash).to eq({ 'id' => '12', 'type' => 'fred' })
|
173
|
-
|
174
|
-
# alias of override
|
175
|
-
expect(TypeSpec.new({ 'squash' => { 'id' => '12', 'type' => 'fred' } }).vegetable).to eq({ 'id' => '12', 'type' => 'fred' })
|
176
|
-
end
|
177
|
-
|
178
|
-
it 'should set a default value' do
|
179
|
-
expect(TypeSpec.new.default).to eq('im a squash')
|
180
|
-
end
|
181
|
-
|
182
|
-
it 'should override a default value' do
|
183
|
-
expect(TypeSpec.new(default: 'now im a different squash').default).to eq('now im a different squash')
|
184
|
-
end
|
185
|
-
|
186
|
-
context 'allowing the same alias for multiple attributes' do
|
187
|
-
it 'should do so when not squashing' do
|
188
|
-
type_spec = TypeSpec.new({ 'nested' => 'bamboo' })
|
189
|
-
expect(type_spec.same_alias_1).to eq('bamboo')
|
190
|
-
expect(type_spec.same_alias_2).to eq('bamboo')
|
191
|
-
end
|
192
|
-
|
193
|
-
it 'should do so when squashing' do
|
194
|
-
type_spec = TypeSpec.new({ 'nested' => { 'attr_1' => 'bamboo', 'attr_2' => 'panda' } })
|
195
|
-
expect(type_spec.same_alias_squashed_1).to eq('bamboo')
|
196
|
-
expect(type_spec.same_alias_squashed_2).to eq('panda')
|
197
|
-
expect(type_spec.same_alias_squashed_3).to eq('panda')
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
it 'should slice out unaccounted for attributes' do
|
202
|
-
expect(TypeSpec.new({ 'something' => { 'id' => '12' } }).attributes.keys).not_to include('something')
|
83
|
+
describe 'deprecation', :deprecated do
|
84
|
+
class DeprecatedModelService
|
85
|
+
include Cistern::Client
|
203
86
|
end
|
204
87
|
|
205
|
-
|
206
|
-
|
207
|
-
|
88
|
+
it 'responds to #service' do
|
89
|
+
class Deprecation < DeprecatedModelService::Model
|
90
|
+
service_method :deprecator
|
208
91
|
end
|
209
92
|
|
210
|
-
|
211
|
-
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
context 'attribute coverage info collecting', :coverage do
|
217
|
-
class CoverageSpec < Sample::Model
|
218
|
-
identity :id
|
219
|
-
|
220
|
-
attribute :used, type: :string
|
221
|
-
attribute :unused, type: :string
|
222
|
-
end
|
223
|
-
|
224
|
-
let!(:obj) { CoverageSpec.new(used: 'foo', unused: 'bar') }
|
225
|
-
|
226
|
-
before(:each) do
|
227
|
-
CoverageSpec.attributes[:used][:coverage_hits] = 0
|
228
|
-
expect(obj.used).to eq('foo') # once
|
229
|
-
expect(obj.used).to eq('foo') # twice
|
230
|
-
end
|
231
|
-
|
232
|
-
it 'should store the file path where the attribute was defined' do
|
233
|
-
expect(CoverageSpec.attributes[:used][:coverage_file]).to eq(__FILE__)
|
234
|
-
expect(CoverageSpec.attributes[:unused][:coverage_file]).to eq(__FILE__)
|
235
|
-
end
|
236
|
-
|
237
|
-
it 'should store the line number where the attribute was defined' do
|
238
|
-
src_lines = File.read(__FILE__).lines
|
239
|
-
|
240
|
-
expect(src_lines[CoverageSpec.attributes[:used][:coverage_line] - 1]).to match(/attribute :used/)
|
241
|
-
expect(src_lines[CoverageSpec.attributes[:unused][:coverage_line] - 1]).to match(/attribute :unused/)
|
242
|
-
end
|
243
|
-
|
244
|
-
it "should store how many times an attribute's reader is called" do
|
245
|
-
expect(CoverageSpec.attributes[:used][:coverage_hits]).to eq(2)
|
246
|
-
expect(CoverageSpec.attributes[:unused][:coverage_hits]).to eq(0)
|
93
|
+
sample = DeprecatedModelService.new.deprecator
|
94
|
+
expect(sample.service).to eq(sample.cistern)
|
247
95
|
end
|
248
96
|
end
|
249
97
|
end
|
data/spec/request_spec.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe 'Cistern::Request' do
|
4
|
-
class
|
4
|
+
class RequestService
|
5
|
+
include Cistern::Client
|
6
|
+
|
5
7
|
recognizes :key
|
6
8
|
|
7
9
|
class Real
|
@@ -14,11 +16,11 @@ describe 'Cistern::Request' do
|
|
14
16
|
end
|
15
17
|
|
16
18
|
# @todo Sample::Service.request
|
17
|
-
class ListSamples <
|
18
|
-
|
19
|
+
class ListSamples < RequestService::Request
|
20
|
+
cistern_method :list_all_samples
|
19
21
|
|
20
22
|
def real(*args)
|
21
|
-
|
23
|
+
cistern.service_args + args + ['real']
|
22
24
|
end
|
23
25
|
|
24
26
|
def mock(*args)
|
@@ -27,11 +29,30 @@ describe 'Cistern::Request' do
|
|
27
29
|
end
|
28
30
|
|
29
31
|
it 'should execute a new-style request' do
|
30
|
-
expect(
|
31
|
-
expect(
|
32
|
-
expect(
|
32
|
+
expect(RequestService.new.list_all_samples('sample1')).to eq([{}, 'sample1', 'real'])
|
33
|
+
expect(RequestService::Real.new.list_all_samples('sample2')).to eq(%w(sample2 real))
|
34
|
+
expect(RequestService::Mock.new.list_all_samples('sample3')).to eq(%w(sample3 mock))
|
33
35
|
|
34
36
|
# service access
|
35
|
-
expect(
|
37
|
+
expect(RequestService.new(key: 'value').list_all_samples('stat')).to eq([{ key: 'value' }, 'stat', 'real'])
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'deprecation', :deprecated do
|
41
|
+
class DeprecatedRequestService
|
42
|
+
include Cistern::Client
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'responds to #service' do
|
46
|
+
class ListDeprecations < DeprecatedRequestService::Request
|
47
|
+
service_method :list_deprecations
|
48
|
+
|
49
|
+
def real
|
50
|
+
self
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
sample = DeprecatedRequestService.new.list_deprecations
|
55
|
+
expect(sample.service).to eq(sample.cistern)
|
56
|
+
end
|
36
57
|
end
|
37
58
|
end
|
data/spec/singular_spec.rb
CHANGED
@@ -6,8 +6,8 @@ describe 'Cistern::Singular' do
|
|
6
6
|
attribute :count, type: :number
|
7
7
|
|
8
8
|
def fetch_attributes
|
9
|
-
# test that initialize waits for
|
10
|
-
fail 'missing
|
9
|
+
# test that initialize waits for cistern to be defined
|
10
|
+
fail 'missing cistern' unless cistern
|
11
11
|
|
12
12
|
@counter ||= 0
|
13
13
|
@counter += 1
|
@@ -19,6 +19,13 @@ describe 'Cistern::Singular' do
|
|
19
19
|
expect(Sample.new.sample_singular.name).to eq('amazing')
|
20
20
|
end
|
21
21
|
|
22
|
+
describe 'deprecation', :deprecated do
|
23
|
+
it 'responds to #service' do
|
24
|
+
sample = Sample.new.sample_singular
|
25
|
+
expect(sample.service).to eq(sample.cistern)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
22
29
|
it 'should reload' do
|
23
30
|
singular = Sample.new.sample_singular
|
24
31
|
old_count = singular.count
|
data/spec/spec_helper.rb
CHANGED
@@ -8,12 +8,18 @@ Dir[File.expand_path('../{support,shared,matchers,fixtures}/*.rb', __FILE__)].ea
|
|
8
8
|
|
9
9
|
Bundler.require(:test)
|
10
10
|
|
11
|
-
Cistern.deprecation_warnings =
|
11
|
+
Cistern.deprecation_warnings = !!ENV['DEBUG']
|
12
12
|
|
13
|
-
RSpec.configure do |
|
13
|
+
RSpec.configure do |rspec|
|
14
14
|
if Kernel.respond_to?(:caller_locations)
|
15
15
|
require File.expand_path('../../lib/cistern/coverage', __FILE__)
|
16
16
|
else
|
17
|
-
|
17
|
+
rspec.filter_run_excluding(:coverage)
|
18
|
+
end
|
19
|
+
rspec.around(:each, :deprecated) do |example|
|
20
|
+
original_value = Cistern.deprecation_warnings?
|
21
|
+
Cistern.deprecation_warnings = false
|
22
|
+
example.run
|
23
|
+
Cistern.deprecation_warnings = original_value
|
18
24
|
end
|
19
25
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cistern
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Lane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: API client framework extracted from Fog
|
14
14
|
email:
|
@@ -50,8 +50,10 @@ files:
|
|
50
50
|
- lib/cistern/timeout.rb
|
51
51
|
- lib/cistern/version.rb
|
52
52
|
- lib/cistern/wait_for.rb
|
53
|
+
- spec/attributes_spec.rb
|
53
54
|
- spec/client_spec.rb
|
54
55
|
- spec/collection_spec.rb
|
56
|
+
- spec/coverage_spec.rb
|
55
57
|
- spec/dirty_spec.rb
|
56
58
|
- spec/formatter_spec.rb
|
57
59
|
- spec/hash_spec.rb
|
@@ -88,8 +90,10 @@ signing_key:
|
|
88
90
|
specification_version: 4
|
89
91
|
summary: API client framework
|
90
92
|
test_files:
|
93
|
+
- spec/attributes_spec.rb
|
91
94
|
- spec/client_spec.rb
|
92
95
|
- spec/collection_spec.rb
|
96
|
+
- spec/coverage_spec.rb
|
93
97
|
- spec/dirty_spec.rb
|
94
98
|
- spec/formatter_spec.rb
|
95
99
|
- spec/hash_spec.rb
|