cuprum-rails 0.1.0 → 0.2.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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +145 -0
  3. data/DEVELOPMENT.md +20 -0
  4. data/README.md +356 -63
  5. data/lib/cuprum/rails/action.rb +32 -16
  6. data/lib/cuprum/rails/actions/create.rb +62 -15
  7. data/lib/cuprum/rails/actions/destroy.rb +23 -7
  8. data/lib/cuprum/rails/actions/edit.rb +23 -7
  9. data/lib/cuprum/rails/actions/index.rb +30 -10
  10. data/lib/cuprum/rails/actions/middleware/associations/cache.rb +112 -0
  11. data/lib/cuprum/rails/actions/middleware/associations/find.rb +23 -0
  12. data/lib/cuprum/rails/actions/middleware/associations/parent.rb +70 -0
  13. data/lib/cuprum/rails/actions/middleware/associations/query.rb +140 -0
  14. data/lib/cuprum/rails/actions/middleware/associations.rb +12 -0
  15. data/lib/cuprum/rails/actions/middleware/log_request.rb +126 -0
  16. data/lib/cuprum/rails/actions/middleware/log_result.rb +51 -0
  17. data/lib/cuprum/rails/actions/middleware/resources/find.rb +44 -0
  18. data/lib/cuprum/rails/actions/middleware/resources/query.rb +91 -0
  19. data/lib/cuprum/rails/actions/middleware/resources.rb +11 -0
  20. data/lib/cuprum/rails/actions/middleware.rb +13 -0
  21. data/lib/cuprum/rails/actions/new.rb +16 -4
  22. data/lib/cuprum/rails/actions/parameter_validation.rb +60 -0
  23. data/lib/cuprum/rails/actions/resource_action.rb +119 -42
  24. data/lib/cuprum/rails/actions/show.rb +23 -7
  25. data/lib/cuprum/rails/actions/update.rb +70 -22
  26. data/lib/cuprum/rails/actions.rb +11 -7
  27. data/lib/cuprum/rails/collection.rb +27 -47
  28. data/lib/cuprum/rails/command.rb +3 -1
  29. data/lib/cuprum/rails/commands/destroy_one.rb +10 -6
  30. data/lib/cuprum/rails/commands/find_many.rb +8 -1
  31. data/lib/cuprum/rails/commands/find_matching.rb +1 -1
  32. data/lib/cuprum/rails/commands/find_one.rb +8 -0
  33. data/lib/cuprum/rails/commands/insert_one.rb +17 -6
  34. data/lib/cuprum/rails/commands/update_one.rb +16 -5
  35. data/lib/cuprum/rails/constraints/parameters_contract.rb +14 -0
  36. data/lib/cuprum/rails/constraints.rb +10 -0
  37. data/lib/cuprum/rails/controller.rb +12 -2
  38. data/lib/cuprum/rails/controllers/action.rb +100 -0
  39. data/lib/cuprum/rails/controllers/class_methods/actions.rb +33 -7
  40. data/lib/cuprum/rails/controllers/class_methods/configuration.rb +36 -0
  41. data/lib/cuprum/rails/controllers/class_methods/middleware.rb +88 -0
  42. data/lib/cuprum/rails/controllers/class_methods/validations.rb +2 -2
  43. data/lib/cuprum/rails/controllers/configuration.rb +41 -1
  44. data/lib/cuprum/rails/controllers/middleware.rb +59 -0
  45. data/lib/cuprum/rails/controllers.rb +2 -0
  46. data/lib/cuprum/rails/errors/invalid_parameters.rb +55 -0
  47. data/lib/cuprum/rails/errors/invalid_statement.rb +11 -0
  48. data/lib/cuprum/rails/errors/missing_parameter.rb +42 -0
  49. data/lib/cuprum/rails/errors/resource_error.rb +46 -0
  50. data/lib/cuprum/rails/errors.rb +6 -1
  51. data/lib/cuprum/rails/map_errors.rb +29 -1
  52. data/lib/cuprum/rails/query.rb +1 -1
  53. data/lib/cuprum/rails/repository.rb +12 -25
  54. data/lib/cuprum/rails/request.rb +149 -60
  55. data/lib/cuprum/rails/resource.rb +119 -85
  56. data/lib/cuprum/rails/responders/base_responder.rb +78 -0
  57. data/lib/cuprum/rails/responders/html/plural_resource.rb +9 -39
  58. data/lib/cuprum/rails/responders/html/rendering.rb +81 -0
  59. data/lib/cuprum/rails/responders/html/resource.rb +107 -0
  60. data/lib/cuprum/rails/responders/html/singular_resource.rb +9 -38
  61. data/lib/cuprum/rails/responders/html.rb +2 -0
  62. data/lib/cuprum/rails/responders/html_responder.rb +8 -52
  63. data/lib/cuprum/rails/responders/json/resource.rb +3 -3
  64. data/lib/cuprum/rails/responders/json_responder.rb +31 -16
  65. data/lib/cuprum/rails/responders/matching.rb +29 -27
  66. data/lib/cuprum/rails/responders/serialization.rb +11 -9
  67. data/lib/cuprum/rails/responders.rb +1 -0
  68. data/lib/cuprum/rails/responses/head_response.rb +24 -0
  69. data/lib/cuprum/rails/responses/html/redirect_back_response.rb +55 -0
  70. data/lib/cuprum/rails/responses/html/redirect_response.rb +19 -4
  71. data/lib/cuprum/rails/responses/html/render_response.rb +17 -5
  72. data/lib/cuprum/rails/responses/html.rb +6 -2
  73. data/lib/cuprum/rails/responses.rb +1 -0
  74. data/lib/cuprum/rails/result.rb +36 -0
  75. data/lib/cuprum/rails/routes.rb +36 -23
  76. data/lib/cuprum/rails/rspec/contract_helpers.rb +57 -0
  77. data/lib/cuprum/rails/rspec/contracts/action_contracts.rb +754 -0
  78. data/lib/cuprum/rails/rspec/contracts/actions/create_contracts.rb +289 -0
  79. data/lib/cuprum/rails/rspec/contracts/actions/destroy_contracts.rb +164 -0
  80. data/lib/cuprum/rails/rspec/contracts/actions/edit_contracts.rb +73 -0
  81. data/lib/cuprum/rails/rspec/contracts/actions/index_contracts.rb +108 -0
  82. data/lib/cuprum/rails/rspec/contracts/actions/new_contracts.rb +111 -0
  83. data/lib/cuprum/rails/rspec/contracts/actions/show_contracts.rb +72 -0
  84. data/lib/cuprum/rails/rspec/contracts/actions/update_contracts.rb +263 -0
  85. data/lib/cuprum/rails/rspec/contracts/actions.rb +8 -0
  86. data/lib/cuprum/rails/rspec/contracts/command_contracts.rb +479 -0
  87. data/lib/cuprum/rails/rspec/contracts/responder_contracts.rb +232 -0
  88. data/lib/cuprum/rails/rspec/contracts/routes_contracts.rb +363 -0
  89. data/lib/cuprum/rails/rspec/contracts/serializers_contracts.rb +70 -0
  90. data/lib/cuprum/rails/rspec/contracts.rb +8 -0
  91. data/lib/cuprum/rails/rspec/matchers/be_a_result_matcher.rb +64 -0
  92. data/lib/cuprum/rails/rspec/matchers.rb +41 -0
  93. data/lib/cuprum/rails/serializers/base_serializer.rb +60 -0
  94. data/lib/cuprum/rails/serializers/context.rb +84 -0
  95. data/lib/cuprum/rails/serializers/json/active_record_serializer.rb +2 -2
  96. data/lib/cuprum/rails/serializers/json/array_serializer.rb +9 -8
  97. data/lib/cuprum/rails/serializers/json/attributes_serializer.rb +95 -172
  98. data/lib/cuprum/rails/serializers/json/error_serializer.rb +2 -2
  99. data/lib/cuprum/rails/serializers/json/hash_serializer.rb +9 -8
  100. data/lib/cuprum/rails/serializers/json/identity_serializer.rb +3 -3
  101. data/lib/cuprum/rails/serializers/json/properties_serializer.rb +252 -0
  102. data/lib/cuprum/rails/serializers/json.rb +2 -1
  103. data/lib/cuprum/rails/serializers.rb +3 -1
  104. data/lib/cuprum/rails/version.rb +1 -1
  105. data/lib/cuprum/rails.rb +19 -16
  106. metadata +73 -131
  107. data/lib/cuprum/rails/controller_action.rb +0 -121
  108. data/lib/cuprum/rails/errors/missing_parameters.rb +0 -33
  109. data/lib/cuprum/rails/errors/missing_primary_key.rb +0 -46
  110. data/lib/cuprum/rails/errors/undefined_permitted_attributes.rb +0 -34
  111. data/lib/cuprum/rails/rspec/command_contract.rb +0 -460
  112. data/lib/cuprum/rails/rspec/define_route_contract.rb +0 -84
  113. data/lib/cuprum/rails/serializers/json/serializer.rb +0 -66
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/sleeping_king_studios/contract'
4
+
5
+ require 'cuprum/rails/rspec/contract_helpers'
6
+ require 'cuprum/rails/rspec/contracts/action_contracts'
7
+ require 'cuprum/rails/rspec/contracts/actions'
8
+
9
+ module Cuprum::Rails::RSpec::Contracts::Actions
10
+ # Namespace for RSpec new contracts, which validate new implementations.
11
+ module NewContracts
12
+ # Contract asserting the action implements the new action interface.
13
+ module ShouldBeANewActionContract
14
+ extend RSpec::SleepingKingStudios::Contract
15
+
16
+ # @method apply(example_group, **options, &block)
17
+ # Adds the contract to the example group.
18
+ #
19
+ # @param example_group [RSpec::Core::ExampleGroup] The example group to
20
+ # which the contract is applied.
21
+ #
22
+ # @option options [Hash<String>] expected_attributes_on_success The
23
+ # expected attributes for the returned object. Defaults to the value
24
+ # of valid_attributes.
25
+ # @option options [Hash<String>] expected_value_on_success The expected
26
+ # value for the passing result. Defaults to a Hash with the created
27
+ # entity.
28
+ # @option options [#to_proc] examples_on_success Extra examples to run
29
+ # for the passing case.
30
+ #
31
+ # @yield Additional examples to run for the passing case.
32
+ contract do |**options, &block|
33
+ include Cuprum::Rails::RSpec::Contracts::ActionContracts
34
+ include Cuprum::Rails::RSpec::Contracts::Actions::NewContracts
35
+
36
+ # :nocov:
37
+ if options[:examples_on_success] && block
38
+ raise ArgumentError, 'provide either :examples_on_success or a block'
39
+ elsif block
40
+ options[:examples_on_success] = block
41
+ end
42
+ # :nocov:
43
+
44
+ include_contract 'should be a resource action'
45
+
46
+ include_contract(
47
+ 'should build the entity',
48
+ expected_attributes: options[:expected_attributes_on_success],
49
+ expected_value: options[:expected_value_on_success],
50
+ &options[:examples_on_success]
51
+ )
52
+ end
53
+ end
54
+
55
+ # Contract asserting the action builds a new entity.
56
+ module ShouldBuildTheEntityContract
57
+ extend RSpec::SleepingKingStudios::Contract
58
+
59
+ # @!method apply(example_group, **options)
60
+ # Adds the contract to the example group.
61
+ #
62
+ # @param example_group [RSpec::Core::ExampleGroup] The example group to
63
+ # which the contract is applied.
64
+ #
65
+ # @option options [Hash<String>] expected_attributes The expected
66
+ # attributes for the returned object.
67
+ # @option options [Hash<String>] expected_value The expected value for
68
+ # the passing result. Defaults to a Hash with the built entity.
69
+ # @option options [Hash<String>] params The parameters used to build the
70
+ # request. Defaults to the id of the entity and the given attributes.
71
+ #
72
+ # @yield Additional examples.
73
+ contract do |**options, &block|
74
+ describe '#call' do
75
+ include Cuprum::Rails::RSpec::ContractHelpers
76
+
77
+ let(:request) do
78
+ Cuprum::Rails::Request.new(params: configured_params)
79
+ end
80
+ let(:configured_params) do
81
+ option_with_default(options[:params], default: {})
82
+ end
83
+ let(:configured_expected_attributes) do
84
+ option_with_default(options[:expected_attributes], default: {})
85
+ end
86
+ let(:configured_expected_entity) do
87
+ configured_resource
88
+ .entity_class
89
+ .new(configured_expected_attributes)
90
+ end
91
+ let(:configured_expected_value) do
92
+ resource_name = configured_resource.singular_name
93
+
94
+ option_with_default(
95
+ options[:expected_value],
96
+ default: { resource_name => configured_expected_entity }
97
+ )
98
+ end
99
+
100
+ it 'should return a passing result' do
101
+ expect(call_action)
102
+ .to be_a_passing_result
103
+ .with_value(configured_expected_value)
104
+ end
105
+
106
+ instance_exec(&block) if block
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/sleeping_king_studios/contract'
4
+
5
+ require 'cuprum/rails/rspec/contract_helpers'
6
+ require 'cuprum/rails/rspec/contracts/action_contracts'
7
+ require 'cuprum/rails/rspec/contracts/actions'
8
+
9
+ module Cuprum::Rails::RSpec::Contracts::Actions
10
+ # Namespace for RSpec show contracts, which validate show implementations.
11
+ module ShowContracts
12
+ # Contract asserting the action implements the show action interface.
13
+ module ShouldBeAShowActionContract
14
+ extend RSpec::SleepingKingStudios::Contract
15
+
16
+ # @method apply(example_group, existing_entity:, **options)
17
+ # Adds the contract to the example group.
18
+ #
19
+ # @param example_group [RSpec::Core::ExampleGroup] The example group to
20
+ # which the contract is applied.
21
+ # @param existing_entity [Object] The existing entity to find.
22
+ #
23
+ # @option options [#to_proc] examples_on_failure Extra examples to run
24
+ # for the failing cases.
25
+ # @option options [#to_proc] examples_on_success Extra examples to run
26
+ # for the passing case.
27
+ # @option options [Hash<String>] expected_value_on_success The expected
28
+ # value for the passing result. Defaults to a Hash with the found
29
+ # entity.
30
+ # @option options [Hash<String>] params The parameters used to build the
31
+ # request. Defaults to the id of the entity.
32
+ # @option options [Object] primary_key_value The value of the primary
33
+ # key for the missing entity.
34
+ #
35
+ # @yield Additional examples to run for the passing case.
36
+
37
+ contract do |existing_entity:, **options, &block|
38
+ include Cuprum::Rails::RSpec::Contracts::ActionContracts
39
+
40
+ # :nocov:
41
+ if options[:examples_on_success] && block
42
+ raise ArgumentError, 'provide either :examples_on_success or a block'
43
+ elsif block
44
+ options[:examples_on_success] = block
45
+ end
46
+ # :nocov:
47
+
48
+ include_contract 'should be a resource action'
49
+
50
+ include_contract(
51
+ 'should require primary key',
52
+ &options[:examples_on_failure]
53
+ )
54
+
55
+ include_contract(
56
+ 'should require existing entity',
57
+ params: options[:params],
58
+ primary_key_value: options[:primary_key_value],
59
+ &options[:examples_on_failure]
60
+ )
61
+
62
+ include_contract(
63
+ 'should find the entity',
64
+ existing_entity: existing_entity,
65
+ expected_value: options[:expected_value_on_success],
66
+ params: options[:params],
67
+ &options[:examples_on_success]
68
+ )
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,263 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/sleeping_king_studios/contract'
4
+
5
+ require 'cuprum/rails/rspec/contract_helpers'
6
+ require 'cuprum/rails/rspec/contracts/action_contracts'
7
+ require 'cuprum/rails/rspec/contracts/actions'
8
+
9
+ module Cuprum::Rails::RSpec::Contracts::Actions
10
+ # Namespace for RSpec update contracts, which validate update implementations.
11
+ module UpdateContracts
12
+ # @private
13
+ def self.parameters(context:, resource:, **options) # rubocop:disable Metrics/MethodLength
14
+ attributes =
15
+ Cuprum::Rails::RSpec::ContractHelpers.option_with_default(
16
+ options[:valid_attributes],
17
+ context: context
18
+ )
19
+ entity =
20
+ Cuprum::Rails::RSpec::ContractHelpers.option_with_default(
21
+ options[:existing_entity],
22
+ context: context
23
+ )
24
+ resource_name = resource.singular_name
25
+
26
+ Cuprum::Rails::RSpec::ContractHelpers.option_with_default(
27
+ options[:params],
28
+ context: context,
29
+ default: {
30
+ 'id' => entity[resource.primary_key],
31
+ resource_name => attributes
32
+ }
33
+ )
34
+ end
35
+
36
+ # Contract asserting the action implements the show action interface.
37
+ module ShouldBeAnUpdateActionContract
38
+ extend RSpec::SleepingKingStudios::Contract
39
+
40
+ # @method apply(example_group, existing_entity:, invalid_attributes:, valid_attributes:, **options)
41
+ # Adds the contract to the example group.
42
+ #
43
+ # @param example_group [RSpec::Core::ExampleGroup] The example group to
44
+ # which the contract is applied.
45
+ # @param existing_entity [Object] The existing entity to update.
46
+ # @param invalid_attributes [Hash<String>] A set of attributes that will
47
+ # fail validation.
48
+ # @param valid_attributes [Hash<String>] A set of attributes that will
49
+ # pass validation.
50
+ #
51
+ # @option options [#to_proc] examples_on_failure Extra examples to run
52
+ # for the failing cases.
53
+ # @option options [#to_proc] examples_on_success Extra examples to run
54
+ # for the passing case.
55
+ # @option options [Hash<String>] expected_value_on_success The expected
56
+ # value for the passing result. Defaults to a Hash with the updated
57
+ # entity.
58
+ # @option options [Hash<String>] expected_attributes The expected
59
+ # attributes for both a failed validation and a returned entity.
60
+ # @option options [Hash<String>] expected_attributes_on_failure The
61
+ # expected attributes for a failed validation. Defaults to the value
62
+ # of invalid_attributes.
63
+ # @option options [Hash<String>] expected_attributes_on_success The
64
+ # expected attributes for the returned object. Defaults to the value
65
+ # of valid_attributes.
66
+ # @option options [Hash<String>] expected_value_on_success The expected
67
+ # value for the passing result. Defaults to a Hash with the updated
68
+ # entity.
69
+ # @option options [Hash<String>] params The parameters used to build the
70
+ # request. Defaults to the id of the entity and the given attributes.
71
+ # @option options [Object] primary_key_value The value of the primary
72
+ # key for the missing entity.
73
+ #
74
+ # @yield Additional examples to run for the passing case.
75
+
76
+ contract do |existing_entity:, invalid_attributes:, valid_attributes:, **options, &block| # rubocop:disable Layout/LineLength
77
+ include Cuprum::Rails::RSpec::Contracts::ActionContracts
78
+ include Cuprum::Rails::RSpec::Contracts::Actions::UpdateContracts
79
+
80
+ # :nocov:
81
+ if options[:examples_on_success] && block
82
+ raise ArgumentError, 'provide either :examples_on_success or a block'
83
+ elsif block
84
+ options[:examples_on_success] = block
85
+ end
86
+ # :nocov:
87
+
88
+ configured_params = lambda do
89
+ Cuprum::Rails::RSpec::Contracts::Actions::UpdateContracts.parameters(
90
+ context: self,
91
+ existing_entity: existing_entity,
92
+ resource: configured_resource,
93
+ valid_attributes: valid_attributes,
94
+ **options
95
+ )
96
+ end
97
+
98
+ should_not_update_the_entity = lambda do
99
+ it 'should not update the entity' do
100
+ entity = existing_entity
101
+ entity = instance_exec(&entity) if entity.is_a?(Proc)
102
+
103
+ expect { call_action }
104
+ .not_to(change { entity.reload.attributes })
105
+ end
106
+
107
+ # :nocov:
108
+ if options[:examples_on_failure]
109
+ instance_exec(&options[:examples_on_failure])
110
+ end
111
+ # :nocov:
112
+ end
113
+
114
+ include_contract 'should be a resource action',
115
+ require_permitted_attributes: true
116
+
117
+ include_contract(
118
+ 'should require primary key',
119
+ params: configured_params,
120
+ &should_not_update_the_entity
121
+ )
122
+
123
+ include_contract(
124
+ 'should require parameters',
125
+ params: configured_params,
126
+ &should_not_update_the_entity
127
+ )
128
+
129
+ include_contract(
130
+ 'should require existing entity',
131
+ params: configured_params,
132
+ primary_key_value: options[:primary_key_value],
133
+ &should_not_update_the_entity
134
+ )
135
+
136
+ include_contract(
137
+ 'should validate attributes',
138
+ existing_entity: existing_entity,
139
+ expected_attributes: options.fetch(
140
+ :expected_attributes,
141
+ options[:expected_attributes_on_failure]
142
+ ),
143
+ invalid_attributes: invalid_attributes,
144
+ params: configured_params,
145
+ &should_not_update_the_entity
146
+ )
147
+
148
+ include_contract(
149
+ 'should update the entity',
150
+ existing_entity: existing_entity,
151
+ expected_attributes: options.fetch(
152
+ :expected_attributes,
153
+ options[:expected_attributes_on_success]
154
+ ),
155
+ expected_value: options[:expected_value_on_success],
156
+ valid_attributes: valid_attributes,
157
+ params: configured_params,
158
+ &options[:examples_on_success]
159
+ )
160
+ end
161
+ end
162
+
163
+ # Contract asserting the action updates the entity.
164
+ module ShouldUpdateTheEntityContract
165
+ extend RSpec::SleepingKingStudios::Contract
166
+
167
+ # @!method apply(example_group, existing_entity:, valid_attributes:, **options)
168
+ # Adds the contract to the example group.
169
+ #
170
+ # @param example_group [RSpec::Core::ExampleGroup] The example group to
171
+ # which the contract is applied.
172
+ # @param existing_entity [Object] The existing entity to find.
173
+ # @param valid_attributes [Hash<String>] A set of attributes that will
174
+ # pass validation.
175
+ #
176
+ # @option options [Hash<String>] expected_attributes The expected
177
+ # attributes for the returned object. Defaults to the value of
178
+ # valid_attributes.
179
+ # @option options [Hash<String>] expected_value The expected value for
180
+ # the passing result. Defaults to a Hash with the created entity.
181
+ # @option options [Hash<String>] params The parameters used to build the
182
+ # request. Defaults to the id of the entity and the given attributes.
183
+ #
184
+ # @yield Additional examples.
185
+ contract do |existing_entity:, valid_attributes:, **options, &block|
186
+ describe '#call' do
187
+ include Cuprum::Rails::RSpec::ContractHelpers
188
+
189
+ context 'with valid parameters' do
190
+ let(:request) do
191
+ Cuprum::Rails::Request.new(params: configured_params)
192
+ end
193
+ let(:configured_params) do
194
+ Cuprum::Rails::RSpec::Contracts::Actions::UpdateContracts
195
+ .parameters(
196
+ context: self,
197
+ existing_entity: existing_entity,
198
+ resource: configured_resource,
199
+ valid_attributes: valid_attributes,
200
+ **options
201
+ )
202
+ end
203
+ let(:configured_existing_entity) do
204
+ option_with_default(existing_entity)
205
+ end
206
+ let(:configured_valid_attributes) do
207
+ option_with_default(valid_attributes)
208
+ end
209
+ let(:configured_expected_attributes) do
210
+ existing_attributes =
211
+ configured_existing_entity
212
+ .attributes
213
+ .tap { |hsh| hsh.delete('updated_at') }
214
+
215
+ option_with_default(
216
+ options[:expected_attributes],
217
+ default: existing_attributes.merge(configured_valid_attributes)
218
+ )
219
+ end
220
+ let(:configured_expected_entity) do
221
+ configured_resource
222
+ .entity_class
223
+ .find(
224
+ configured_existing_entity[configured_resource.primary_key]
225
+ )
226
+ end
227
+ let(:configured_expected_value) do
228
+ resource_name = configured_resource.singular_name
229
+
230
+ option_with_default(
231
+ options[:expected_value],
232
+ default: {
233
+ resource_name => configured_expected_entity
234
+ }
235
+ )
236
+ end
237
+
238
+ it 'should return a passing result' do
239
+ expect(call_action)
240
+ .to be_a_passing_result
241
+ .with_value(configured_expected_value)
242
+ end
243
+
244
+ it 'should update the entity' do
245
+ expect { call_action }
246
+ .to(
247
+ change do
248
+ configured_existing_entity
249
+ .reload
250
+ .attributes
251
+ .tap { |hsh| hsh.delete('updated_at') }
252
+ end
253
+ .to(be >= configured_expected_attributes)
254
+ )
255
+ end
256
+
257
+ instance_exec(&block) if block
258
+ end
259
+ end
260
+ end
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/rails/rspec/contracts'
4
+
5
+ module Cuprum::Rails::RSpec::Contracts
6
+ # Namespace for RSpec action contracts, which validate action implementations.
7
+ module Actions; end
8
+ end