cuprum-collections 0.3.0 → 0.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.
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