cuprum-collections 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +48 -0
  3. data/DEVELOPMENT.md +2 -2
  4. data/README.md +13 -11
  5. data/lib/cuprum/collections/association.rb +256 -0
  6. data/lib/cuprum/collections/associations/belongs_to.rb +32 -0
  7. data/lib/cuprum/collections/associations/has_many.rb +23 -0
  8. data/lib/cuprum/collections/associations/has_one.rb +23 -0
  9. data/lib/cuprum/collections/associations.rb +10 -0
  10. data/lib/cuprum/collections/basic/collection.rb +39 -74
  11. data/lib/cuprum/collections/basic/commands/find_many.rb +1 -1
  12. data/lib/cuprum/collections/basic/commands/find_matching.rb +1 -1
  13. data/lib/cuprum/collections/basic/repository.rb +9 -33
  14. data/lib/cuprum/collections/basic.rb +1 -0
  15. data/lib/cuprum/collections/collection.rb +154 -0
  16. data/lib/cuprum/collections/commands/associations/find_many.rb +161 -0
  17. data/lib/cuprum/collections/commands/associations/require_many.rb +48 -0
  18. data/lib/cuprum/collections/commands/associations.rb +13 -0
  19. data/lib/cuprum/collections/commands/find_one_matching.rb +1 -1
  20. data/lib/cuprum/collections/commands.rb +1 -0
  21. data/lib/cuprum/collections/errors/abstract_find_error.rb +1 -1
  22. data/lib/cuprum/collections/relation.rb +401 -0
  23. data/lib/cuprum/collections/repository.rb +71 -4
  24. data/lib/cuprum/collections/resource.rb +65 -0
  25. data/lib/cuprum/collections/rspec/contracts/association_contracts.rb +2137 -0
  26. data/lib/cuprum/collections/rspec/contracts/basic/command_contracts.rb +484 -0
  27. data/lib/cuprum/collections/rspec/contracts/basic.rb +11 -0
  28. data/lib/cuprum/collections/rspec/contracts/collection_contracts.rb +429 -0
  29. data/lib/cuprum/collections/rspec/contracts/command_contracts.rb +1462 -0
  30. data/lib/cuprum/collections/rspec/contracts/query_contracts.rb +1093 -0
  31. data/lib/cuprum/collections/rspec/contracts/relation_contracts.rb +1381 -0
  32. data/lib/cuprum/collections/rspec/contracts/repository_contracts.rb +605 -0
  33. data/lib/cuprum/collections/rspec/contracts.rb +23 -0
  34. data/lib/cuprum/collections/rspec/fixtures.rb +85 -82
  35. data/lib/cuprum/collections/rspec.rb +4 -1
  36. data/lib/cuprum/collections/version.rb +1 -1
  37. data/lib/cuprum/collections.rb +9 -4
  38. metadata +23 -19
  39. data/lib/cuprum/collections/base.rb +0 -11
  40. data/lib/cuprum/collections/basic/rspec/command_contract.rb +0 -392
  41. data/lib/cuprum/collections/rspec/assign_one_command_contract.rb +0 -168
  42. data/lib/cuprum/collections/rspec/build_one_command_contract.rb +0 -93
  43. data/lib/cuprum/collections/rspec/collection_contract.rb +0 -190
  44. data/lib/cuprum/collections/rspec/destroy_one_command_contract.rb +0 -108
  45. data/lib/cuprum/collections/rspec/find_many_command_contract.rb +0 -407
  46. data/lib/cuprum/collections/rspec/find_matching_command_contract.rb +0 -194
  47. data/lib/cuprum/collections/rspec/find_one_command_contract.rb +0 -157
  48. data/lib/cuprum/collections/rspec/insert_one_command_contract.rb +0 -84
  49. data/lib/cuprum/collections/rspec/query_builder_contract.rb +0 -92
  50. data/lib/cuprum/collections/rspec/query_contract.rb +0 -650
  51. data/lib/cuprum/collections/rspec/querying_contract.rb +0 -298
  52. data/lib/cuprum/collections/rspec/repository_contract.rb +0 -235
  53. data/lib/cuprum/collections/rspec/update_one_command_contract.rb +0 -80
  54. data/lib/cuprum/collections/rspec/validate_one_command_contract.rb +0 -96
@@ -1,298 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'cuprum/collections/queries'
4
- require 'cuprum/collections/rspec'
5
-
6
- module Cuprum::Collections::RSpec
7
- OPERATORS = Cuprum::Collections::Queries::Operators
8
- private_constant :OPERATORS
9
-
10
- # Shared contexts for specs that define querying behavior.
11
- QUERYING_CONTEXTS = lambda do
12
- let(:filter) { nil }
13
- let(:strategy) { nil }
14
- let(:limit) { nil }
15
- let(:offset) { nil }
16
- let(:order) { nil }
17
-
18
- shared_context 'when the query has limit: value' do
19
- let(:limit) { 3 }
20
- let(:matching_data) { super()[0...limit] }
21
- end
22
-
23
- shared_context 'when the query has offset: value' do
24
- let(:offset) { 2 }
25
- let(:matching_data) { super()[offset..] || [] }
26
- end
27
-
28
- shared_context 'when the query has order: a simple ordering' do
29
- let(:order) { :title }
30
- let(:matching_data) { super().sort_by { |item| item['title'] } }
31
- end
32
-
33
- shared_context 'when the query has order: a complex ordering' do
34
- let(:order) do
35
- {
36
- author: :asc,
37
- title: :desc
38
- }
39
- end
40
- let(:matching_data) do
41
- super().sort do |u, v|
42
- cmp = u['author'] <=> v['author']
43
-
44
- cmp.zero? ? (v['title'] <=> u['title']) : cmp
45
- end
46
- end
47
- end
48
-
49
- shared_context 'when the query has where: a simple block filter' do
50
- let(:filter) { -> { { author: 'Ursula K. LeGuin' } } }
51
- let(:matching_data) do
52
- super().select { |item| item['author'] == 'Ursula K. LeGuin' }
53
- end
54
- end
55
-
56
- shared_context 'when the query has where: a complex block filter' do
57
- let(:filter) do
58
- lambda do
59
- {
60
- author: equals('Ursula K. LeGuin'),
61
- series: not_equal('Earthsea')
62
- }
63
- end
64
- end
65
- let(:matching_data) do
66
- super()
67
- .select { |item| item['author'] == 'Ursula K. LeGuin' }
68
- .reject { |item| item['series'] == 'Earthsea' }
69
- end
70
- end
71
-
72
- shared_context 'when the query has where: a greater_than filter' do
73
- let(:filter) { -> { { published_at: greater_than('1970-12-01') } } }
74
- let(:matching_data) do
75
- super().select { |item| item['published_at'] > '1970-12-01' }
76
- end
77
- end
78
-
79
- shared_context 'when the query has where: a greater_than_or_equal_to ' \
80
- 'filter' \
81
- do
82
- let(:filter) do
83
- -> { { published_at: greater_than_or_equal_to('1970-12-01') } }
84
- end
85
- let(:matching_data) do
86
- super().select { |item| item['published_at'] >= '1970-12-01' }
87
- end
88
- end
89
-
90
- shared_context 'when the query has where: a less_than filter' do
91
- let(:filter) { -> { { published_at: less_than('1970-12-01') } } }
92
- let(:matching_data) do
93
- super().select { |item| item['published_at'] < '1970-12-01' }
94
- end
95
- end
96
-
97
- shared_context 'when the query has where: a less_than_or_equal_to filter' do
98
- let(:filter) do
99
- -> { { published_at: less_than_or_equal_to('1970-12-01') } }
100
- end
101
- let(:matching_data) do
102
- super().select { |item| item['published_at'] <= '1970-12-01' }
103
- end
104
- end
105
-
106
- shared_context 'when the query has where: an equal block filter' do
107
- let(:filter) { -> { { author: equals('Ursula K. LeGuin') } } }
108
- let(:matching_data) do
109
- super().select { |item| item['author'] == 'Ursula K. LeGuin' }
110
- end
111
- end
112
-
113
- shared_context 'when the query has where: a not_equal block filter' do
114
- let(:filter) { -> { { author: not_equal('Ursula K. LeGuin') } } }
115
- let(:matching_data) do
116
- super().reject { |item| item['author'] == 'Ursula K. LeGuin' }
117
- end
118
- end
119
-
120
- shared_context 'when the query has where: a not_one_of block filter' do
121
- let(:filter) do
122
- -> { { series: not_one_of(['Earthsea', 'The Lord of the Rings']) } }
123
- end
124
- let(:matching_data) do
125
- super().reject do |item|
126
- ['Earthsea', 'The Lord of the Rings'].include?(item['series'])
127
- end
128
- end
129
- end
130
-
131
- shared_context 'when the query has where: a one_of block filter' do
132
- let(:filter) do
133
- -> { { series: one_of(['Earthsea', 'The Lord of the Rings']) } }
134
- end
135
- let(:matching_data) do
136
- super().select do |item|
137
- ['Earthsea', 'The Lord of the Rings'].include?(item['series'])
138
- end
139
- end
140
- end
141
-
142
- shared_context 'when the query has multiple query options' do
143
- let(:filter) { -> { { author: 'Ursula K. LeGuin' } } }
144
- let(:strategy) { nil }
145
- let(:order) { { title: :desc } }
146
- let(:limit) { 2 }
147
- let(:offset) { 1 }
148
- let(:matching_data) do
149
- super()
150
- .select { |item| item['author'] == 'Ursula K. LeGuin' }
151
- .sort { |u, v| v['title'] <=> u['title'] }
152
- .slice(1, 2) || []
153
- end
154
- end
155
- end
156
-
157
- # Contract validating the behavior objects that perform queries.
158
- QUERYING_CONTRACT = lambda do |block:, operators: OPERATORS.values|
159
- wrap_context 'when the query has limit: value' do
160
- instance_exec(&block)
161
- end
162
-
163
- wrap_context 'when the query has offset: value' do
164
- instance_exec(&block)
165
- end
166
-
167
- wrap_context 'when the query has order: a simple ordering' do
168
- instance_exec(&block)
169
- end
170
-
171
- wrap_context 'when the query has order: a complex ordering' do
172
- instance_exec(&block)
173
- end
174
-
175
- context 'when the query has where: a block filter' do
176
- context 'with a simple filter' do
177
- include_context 'when the query has where: a simple block filter'
178
-
179
- instance_exec(&block)
180
- end
181
-
182
- context 'with a complex filter' do
183
- include_context 'when the query has where: a complex block filter'
184
-
185
- if operators.include?(OPERATORS::EQUAL) &&
186
- operators.include?(OPERATORS::NOT_EQUAL)
187
- instance_exec(&block)
188
- else
189
- # :nocov:
190
- pending
191
- # :nocov:
192
- end
193
- end
194
-
195
- context 'with an equals filter' do
196
- include_context 'when the query has where: an equal block filter'
197
-
198
- if operators.include?(OPERATORS::EQUAL)
199
- instance_exec(&block)
200
- else
201
- # :nocov:
202
- pending
203
- # :nocov:
204
- end
205
- end
206
-
207
- context 'with a greater_than filter' do
208
- include_context 'when the query has where: a greater_than filter'
209
-
210
- if operators.include?(OPERATORS::GREATER_THAN)
211
- instance_exec(&block)
212
- else
213
- # :nocov:
214
- pending
215
- # :nocov:
216
- end
217
- end
218
-
219
- context 'with a greater_than_or_equal_to filter' do
220
- include_context \
221
- 'when the query has where: a greater_than_or_equal_to filter'
222
-
223
- if operators.include?(OPERATORS::GREATER_THAN_OR_EQUAL_TO)
224
- instance_exec(&block)
225
- else
226
- # :nocov:
227
- pending
228
- # :nocov:
229
- end
230
- end
231
-
232
- context 'with a less_than filter' do
233
- include_context 'when the query has where: a less_than filter'
234
-
235
- if operators.include?(OPERATORS::LESS_THAN)
236
- instance_exec(&block)
237
- else
238
- # :nocov:
239
- pending
240
- # :nocov:
241
- end
242
- end
243
-
244
- context 'with a less_than_or_equal_to filter' do
245
- include_context \
246
- 'when the query has where: a less_than_or_equal_to filter'
247
-
248
- if operators.include?(OPERATORS::LESS_THAN_OR_EQUAL_TO)
249
- instance_exec(&block)
250
- else
251
- # :nocov:
252
- pending
253
- # :nocov:
254
- end
255
- end
256
-
257
- context 'with a not_equal filter' do
258
- include_context 'when the query has where: a not_equal block filter'
259
-
260
- if operators.include?(OPERATORS::NOT_EQUAL)
261
- instance_exec(&block)
262
- else
263
- # :nocov:
264
- pending
265
- # :nocov:
266
- end
267
- end
268
-
269
- context 'with a not_one_of filter' do
270
- include_context 'when the query has where: a not_one_of block filter'
271
-
272
- if operators.include?(OPERATORS::NOT_ONE_OF)
273
- instance_exec(&block)
274
- else
275
- # :nocov:
276
- pending
277
- # :nocov:
278
- end
279
- end
280
-
281
- context 'with a one_of filter' do
282
- include_context 'when the query has where: a one_of block filter'
283
-
284
- if operators.include?(OPERATORS::ONE_OF)
285
- instance_exec(&block)
286
- else
287
- # :nocov:
288
- pending
289
- # :nocov:
290
- end
291
- end
292
- end
293
-
294
- wrap_context 'when the query has multiple query options' do
295
- instance_exec(&block)
296
- end
297
- end
298
- end
@@ -1,235 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rspec/sleeping_king_studios/contract'
4
-
5
- require 'cuprum/collections/rspec'
6
-
7
- module Cuprum::Collections::RSpec
8
- # Contract validating the behavior of a Repository.
9
- module RepositoryContract
10
- extend RSpec::SleepingKingStudios::Contract
11
-
12
- # @!method apply(example_group)
13
- # Adds the contract to the example group.
14
- #
15
- # @param example_group [RSpec::Core::ExampleGroup] The example group to
16
- # which the contract is applied.
17
- contract do
18
- describe '#[]' do
19
- let(:error_class) do
20
- described_class::UndefinedCollectionError
21
- end
22
- let(:error_message) do
23
- "repository does not define collection #{collection_name.inspect}"
24
- end
25
-
26
- it { expect(repository).to respond_to(:[]).with(1).argument }
27
-
28
- describe 'with nil' do
29
- let(:collection_name) { nil }
30
-
31
- it 'should raise an exception' do
32
- expect { repository[collection_name] }
33
- .to raise_error(error_class, error_message)
34
- end
35
- end
36
-
37
- describe 'with an object' do
38
- let(:collection_name) { Object.new.freeze }
39
-
40
- it 'should raise an exception' do
41
- expect { repository[collection_name] }
42
- .to raise_error(error_class, error_message)
43
- end
44
- end
45
-
46
- describe 'with an invalid string' do
47
- let(:collection_name) { 'invalid_name' }
48
-
49
- it 'should raise an exception' do
50
- expect { repository[collection_name] }
51
- .to raise_error(error_class, error_message)
52
- end
53
- end
54
-
55
- describe 'with an invalid symbol' do
56
- let(:collection_name) { :invalid_name }
57
-
58
- it 'should raise an exception' do
59
- expect { repository[collection_name] }
60
- .to raise_error(error_class, error_message)
61
- end
62
- end
63
-
64
- wrap_context 'when the repository has many collections' do
65
- describe 'with an invalid string' do
66
- let(:collection_name) { 'invalid_name' }
67
-
68
- it 'should raise an exception' do
69
- expect { repository[collection_name] }
70
- .to raise_error(error_class, error_message)
71
- end
72
- end
73
-
74
- describe 'with an invalid symbol' do
75
- let(:collection_name) { :invalid_name }
76
-
77
- it 'should raise an exception' do
78
- expect { repository[collection_name] }
79
- .to raise_error(error_class, error_message)
80
- end
81
- end
82
-
83
- describe 'with a valid string' do
84
- let(:collection) { collections.values.first }
85
- let(:collection_name) { collections.keys.first }
86
-
87
- it { expect(repository[collection_name]).to be collection }
88
- end
89
-
90
- describe 'with a valid symbol' do
91
- let(:collection) { collections.values.first }
92
- let(:collection_name) { collections.keys.first.intern }
93
-
94
- it { expect(repository[collection_name]).to be collection }
95
- end
96
- end
97
- end
98
-
99
- describe '#add' do
100
- let(:error_class) do
101
- described_class::InvalidCollectionError
102
- end
103
- let(:error_message) do
104
- "#{collection.inspect} is not a valid collection"
105
- end
106
-
107
- it 'should define the method' do
108
- expect(repository)
109
- .to respond_to(:add)
110
- .with(1).argument
111
- .and_keywords(:force)
112
- end
113
-
114
- it 'should alias #add as #<<' do
115
- expect(repository.method(:<<)).to be == repository.method(:add)
116
- end
117
-
118
- describe 'with nil' do
119
- let(:collection) { nil }
120
-
121
- it 'should raise an exception' do
122
- expect { repository.add(collection) }
123
- .to raise_error(error_class, error_message)
124
- end
125
- end
126
-
127
- describe 'with an object' do
128
- let(:collection) { Object.new.freeze }
129
-
130
- it 'should raise an exception' do
131
- expect { repository.add(collection) }
132
- .to raise_error(error_class, error_message)
133
- end
134
- end
135
-
136
- describe 'with a collection' do
137
- it { expect(repository.add(example_collection)).to be repository }
138
-
139
- it 'should add the collection to the repository' do
140
- repository.add(example_collection)
141
-
142
- expect(repository[example_collection.qualified_name])
143
- .to be example_collection
144
- end
145
-
146
- describe 'with force: true' do
147
- it 'should add the collection to the repository' do
148
- repository.add(example_collection, force: true)
149
-
150
- expect(repository[example_collection.qualified_name])
151
- .to be example_collection
152
- end
153
- end
154
-
155
- context 'when the collection already exists' do
156
- let(:error_message) do
157
- "collection #{example_collection.qualified_name} already exists"
158
- end
159
-
160
- before(:example) do
161
- allow(repository)
162
- .to receive(:key?)
163
- .with(example_collection.qualified_name)
164
- .and_return(true)
165
- end
166
-
167
- it 'should raise an exception' do
168
- expect { repository.add(example_collection) }
169
- .to raise_error(
170
- described_class::DuplicateCollectionError,
171
- error_message
172
- )
173
- end
174
-
175
- it 'should not update the repository' do
176
- begin
177
- repository.add(example_collection)
178
- rescue described_class::DuplicateCollectionError
179
- # Do nothing.
180
- end
181
-
182
- expect { repository[example_collection.qualified_name] }
183
- .to raise_error(
184
- described_class::UndefinedCollectionError,
185
- 'repository does not define collection ' \
186
- "#{example_collection.qualified_name.inspect}"
187
- )
188
- end
189
-
190
- describe 'with force: true' do
191
- it 'should add the collection to the repository' do
192
- repository.add(example_collection, force: true)
193
-
194
- expect(repository[example_collection.qualified_name])
195
- .to be example_collection
196
- end
197
- end
198
- end
199
- end
200
- end
201
-
202
- describe '#key?' do
203
- it { expect(repository).to respond_to(:key?).with(1).argument }
204
-
205
- it { expect(repository.key? nil).to be false }
206
-
207
- it { expect(repository.key? Object.new.freeze).to be false }
208
-
209
- it { expect(repository.key? 'invalid_name').to be false }
210
-
211
- it { expect(repository.key? :invalid_name).to be false }
212
-
213
- wrap_context 'when the repository has many collections' do
214
- it { expect(repository.key? 'invalid_name').to be false }
215
-
216
- it { expect(repository.key? :invalid_name).to be false }
217
-
218
- it { expect(repository.key? collections.keys.first).to be true }
219
-
220
- it 'should include the key' do
221
- expect(repository.key? collections.keys.first.intern).to be true
222
- end
223
- end
224
- end
225
-
226
- describe '#keys' do
227
- include_examples 'should define reader', :keys, []
228
-
229
- wrap_context 'when the repository has many collections' do
230
- it { expect(repository.keys).to be == collections.keys }
231
- end
232
- end
233
- end
234
- end
235
- end
@@ -1,80 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'cuprum/collections/rspec'
4
-
5
- module Cuprum::Collections::RSpec
6
- # Contract validating the behavior of an UpdateOne command implementation.
7
- UPDATE_ONE_COMMAND_CONTRACT = lambda do
8
- describe '#call' do
9
- let(:mapped_data) do
10
- defined?(super()) ? super() : data
11
- end
12
- let(:matching_data) { attributes }
13
- let(:expected_data) do
14
- defined?(super()) ? super() : matching_data
15
- end
16
- let(:primary_key_name) do
17
- defined?(super()) ? super() : :id
18
- end
19
- let(:scoped) do
20
- key = primary_key_name
21
- value = entity[primary_key_name.to_s]
22
-
23
- query.where { { key => value } }
24
- end
25
-
26
- it 'should validate the :entity keyword' do
27
- expect(command)
28
- .to validate_parameter(:call, :entity)
29
- .using_constraint(entity_type)
30
- end
31
-
32
- context 'when the item does not exist in the collection' do
33
- let(:expected_error) do
34
- Cuprum::Collections::Errors::NotFound.new(
35
- attribute_name: primary_key_name,
36
- attribute_value: attributes[primary_key_name],
37
- collection_name: collection_name,
38
- primary_key: true
39
- )
40
- end
41
- let(:matching_data) { mapped_data.first }
42
-
43
- it 'should return a failing result' do
44
- expect(command.call(entity: entity))
45
- .to be_a_failing_result
46
- .with_error(expected_error)
47
- end
48
-
49
- it 'should not append an item to the collection' do
50
- expect { command.call(entity: entity) }
51
- .not_to(change { query.reset.count })
52
- end
53
- end
54
-
55
- context 'when the item exists in the collection' do
56
- let(:data) { fixtures_data }
57
- let(:matching_data) do
58
- mapped_data.first.merge(super())
59
- end
60
-
61
- it 'should return a passing result' do
62
- expect(command.call(entity: entity))
63
- .to be_a_passing_result
64
- .with_value(be == expected_data)
65
- end
66
-
67
- it 'should not append an item to the collection' do
68
- expect { command.call(entity: entity) }
69
- .not_to(change { query.reset.count })
70
- end
71
-
72
- it 'should set the attributes' do
73
- command.call(entity: entity)
74
-
75
- expect(scoped.to_a.first).to be == expected_data
76
- end
77
- end
78
- end
79
- end
80
- end
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'cuprum/collections/rspec'
4
-
5
- module Cuprum::Collections::RSpec
6
- # Contract validating the behavior of a ValidateOne command implementation.
7
- VALIDATE_ONE_COMMAND_CONTRACT = lambda do |default_contract:|
8
- describe '#call' do
9
- it 'should validate the :contract keyword' do
10
- expect(command)
11
- .to validate_parameter(:call, :contract)
12
- .with_value(Object.new.freeze)
13
- .using_constraint(Stannum::Constraints::Base, optional: true)
14
- end
15
-
16
- it 'should validate the :entity keyword' do
17
- expect(command)
18
- .to validate_parameter(:call, :entity)
19
- .with_value(Object.new.freeze)
20
- .using_constraint(entity_type)
21
- end
22
-
23
- describe 'with contract: nil' do
24
- if default_contract
25
- context 'when the entity does not match the default contract' do
26
- let(:attributes) { invalid_default_attributes }
27
- let(:expected_error) do
28
- Cuprum::Collections::Errors::FailedValidation.new(
29
- entity_class: entity.class,
30
- errors: expected_errors
31
- )
32
- end
33
-
34
- it 'should return a failing result' do
35
- expect(command.call(entity: entity))
36
- .to be_a_failing_result
37
- .with_error(expected_error)
38
- end
39
- end
40
-
41
- context 'when the entity matches the default contract' do
42
- let(:attributes) { valid_default_attributes }
43
-
44
- it 'should return a passing result' do
45
- expect(command.call(entity: entity))
46
- .to be_a_passing_result
47
- .with_value(entity)
48
- end
49
- end
50
- else
51
- let(:attributes) { valid_attributes }
52
- let(:expected_error) do
53
- Cuprum::Collections::Errors::MissingDefaultContract.new(
54
- entity_class: entity.class
55
- )
56
- end
57
-
58
- it 'should return a failing result' do
59
- expect(command.call(entity: entity))
60
- .to be_a_failing_result
61
- .with_error(expected_error)
62
- end
63
- end
64
- end
65
-
66
- describe 'with contract: value' do
67
- context 'when the entity does not match the contract' do
68
- let(:attributes) { invalid_attributes }
69
- let(:errors) { contract.errors_for(entity) }
70
- let(:expected_error) do
71
- Cuprum::Collections::Errors::FailedValidation.new(
72
- entity_class: entity.class,
73
- errors: errors
74
- )
75
- end
76
-
77
- it 'should return a failing result' do
78
- expect(command.call(contract: contract, entity: entity))
79
- .to be_a_failing_result
80
- .with_error(expected_error)
81
- end
82
- end
83
-
84
- context 'when the entity matches the contract' do
85
- let(:attributes) { valid_attributes }
86
-
87
- it 'should return a passing result' do
88
- expect(command.call(contract: contract, entity: entity))
89
- .to be_a_passing_result
90
- .with_value(entity)
91
- end
92
- end
93
- end
94
- end
95
- end
96
- end