cistern 2.2.7 → 2.3.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/.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
|