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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +145 -0
- data/DEVELOPMENT.md +20 -0
- data/README.md +356 -63
- data/lib/cuprum/rails/action.rb +32 -16
- data/lib/cuprum/rails/actions/create.rb +62 -15
- data/lib/cuprum/rails/actions/destroy.rb +23 -7
- data/lib/cuprum/rails/actions/edit.rb +23 -7
- data/lib/cuprum/rails/actions/index.rb +30 -10
- data/lib/cuprum/rails/actions/middleware/associations/cache.rb +112 -0
- data/lib/cuprum/rails/actions/middleware/associations/find.rb +23 -0
- data/lib/cuprum/rails/actions/middleware/associations/parent.rb +70 -0
- data/lib/cuprum/rails/actions/middleware/associations/query.rb +140 -0
- data/lib/cuprum/rails/actions/middleware/associations.rb +12 -0
- data/lib/cuprum/rails/actions/middleware/log_request.rb +126 -0
- data/lib/cuprum/rails/actions/middleware/log_result.rb +51 -0
- data/lib/cuprum/rails/actions/middleware/resources/find.rb +44 -0
- data/lib/cuprum/rails/actions/middleware/resources/query.rb +91 -0
- data/lib/cuprum/rails/actions/middleware/resources.rb +11 -0
- data/lib/cuprum/rails/actions/middleware.rb +13 -0
- data/lib/cuprum/rails/actions/new.rb +16 -4
- data/lib/cuprum/rails/actions/parameter_validation.rb +60 -0
- data/lib/cuprum/rails/actions/resource_action.rb +119 -42
- data/lib/cuprum/rails/actions/show.rb +23 -7
- data/lib/cuprum/rails/actions/update.rb +70 -22
- data/lib/cuprum/rails/actions.rb +11 -7
- data/lib/cuprum/rails/collection.rb +27 -47
- data/lib/cuprum/rails/command.rb +3 -1
- data/lib/cuprum/rails/commands/destroy_one.rb +10 -6
- data/lib/cuprum/rails/commands/find_many.rb +8 -1
- data/lib/cuprum/rails/commands/find_matching.rb +1 -1
- data/lib/cuprum/rails/commands/find_one.rb +8 -0
- data/lib/cuprum/rails/commands/insert_one.rb +17 -6
- data/lib/cuprum/rails/commands/update_one.rb +16 -5
- data/lib/cuprum/rails/constraints/parameters_contract.rb +14 -0
- data/lib/cuprum/rails/constraints.rb +10 -0
- data/lib/cuprum/rails/controller.rb +12 -2
- data/lib/cuprum/rails/controllers/action.rb +100 -0
- data/lib/cuprum/rails/controllers/class_methods/actions.rb +33 -7
- data/lib/cuprum/rails/controllers/class_methods/configuration.rb +36 -0
- data/lib/cuprum/rails/controllers/class_methods/middleware.rb +88 -0
- data/lib/cuprum/rails/controllers/class_methods/validations.rb +2 -2
- data/lib/cuprum/rails/controllers/configuration.rb +41 -1
- data/lib/cuprum/rails/controllers/middleware.rb +59 -0
- data/lib/cuprum/rails/controllers.rb +2 -0
- data/lib/cuprum/rails/errors/invalid_parameters.rb +55 -0
- data/lib/cuprum/rails/errors/invalid_statement.rb +11 -0
- data/lib/cuprum/rails/errors/missing_parameter.rb +42 -0
- data/lib/cuprum/rails/errors/resource_error.rb +46 -0
- data/lib/cuprum/rails/errors.rb +6 -1
- data/lib/cuprum/rails/map_errors.rb +29 -1
- data/lib/cuprum/rails/query.rb +1 -1
- data/lib/cuprum/rails/repository.rb +12 -25
- data/lib/cuprum/rails/request.rb +149 -60
- data/lib/cuprum/rails/resource.rb +119 -85
- data/lib/cuprum/rails/responders/base_responder.rb +78 -0
- data/lib/cuprum/rails/responders/html/plural_resource.rb +9 -39
- data/lib/cuprum/rails/responders/html/rendering.rb +81 -0
- data/lib/cuprum/rails/responders/html/resource.rb +107 -0
- data/lib/cuprum/rails/responders/html/singular_resource.rb +9 -38
- data/lib/cuprum/rails/responders/html.rb +2 -0
- data/lib/cuprum/rails/responders/html_responder.rb +8 -52
- data/lib/cuprum/rails/responders/json/resource.rb +3 -3
- data/lib/cuprum/rails/responders/json_responder.rb +31 -16
- data/lib/cuprum/rails/responders/matching.rb +29 -27
- data/lib/cuprum/rails/responders/serialization.rb +11 -9
- data/lib/cuprum/rails/responders.rb +1 -0
- data/lib/cuprum/rails/responses/head_response.rb +24 -0
- data/lib/cuprum/rails/responses/html/redirect_back_response.rb +55 -0
- data/lib/cuprum/rails/responses/html/redirect_response.rb +19 -4
- data/lib/cuprum/rails/responses/html/render_response.rb +17 -5
- data/lib/cuprum/rails/responses/html.rb +6 -2
- data/lib/cuprum/rails/responses.rb +1 -0
- data/lib/cuprum/rails/result.rb +36 -0
- data/lib/cuprum/rails/routes.rb +36 -23
- data/lib/cuprum/rails/rspec/contract_helpers.rb +57 -0
- data/lib/cuprum/rails/rspec/contracts/action_contracts.rb +754 -0
- data/lib/cuprum/rails/rspec/contracts/actions/create_contracts.rb +289 -0
- data/lib/cuprum/rails/rspec/contracts/actions/destroy_contracts.rb +164 -0
- data/lib/cuprum/rails/rspec/contracts/actions/edit_contracts.rb +73 -0
- data/lib/cuprum/rails/rspec/contracts/actions/index_contracts.rb +108 -0
- data/lib/cuprum/rails/rspec/contracts/actions/new_contracts.rb +111 -0
- data/lib/cuprum/rails/rspec/contracts/actions/show_contracts.rb +72 -0
- data/lib/cuprum/rails/rspec/contracts/actions/update_contracts.rb +263 -0
- data/lib/cuprum/rails/rspec/contracts/actions.rb +8 -0
- data/lib/cuprum/rails/rspec/contracts/command_contracts.rb +479 -0
- data/lib/cuprum/rails/rspec/contracts/responder_contracts.rb +232 -0
- data/lib/cuprum/rails/rspec/contracts/routes_contracts.rb +363 -0
- data/lib/cuprum/rails/rspec/contracts/serializers_contracts.rb +70 -0
- data/lib/cuprum/rails/rspec/contracts.rb +8 -0
- data/lib/cuprum/rails/rspec/matchers/be_a_result_matcher.rb +64 -0
- data/lib/cuprum/rails/rspec/matchers.rb +41 -0
- data/lib/cuprum/rails/serializers/base_serializer.rb +60 -0
- data/lib/cuprum/rails/serializers/context.rb +84 -0
- data/lib/cuprum/rails/serializers/json/active_record_serializer.rb +2 -2
- data/lib/cuprum/rails/serializers/json/array_serializer.rb +9 -8
- data/lib/cuprum/rails/serializers/json/attributes_serializer.rb +95 -172
- data/lib/cuprum/rails/serializers/json/error_serializer.rb +2 -2
- data/lib/cuprum/rails/serializers/json/hash_serializer.rb +9 -8
- data/lib/cuprum/rails/serializers/json/identity_serializer.rb +3 -3
- data/lib/cuprum/rails/serializers/json/properties_serializer.rb +252 -0
- data/lib/cuprum/rails/serializers/json.rb +2 -1
- data/lib/cuprum/rails/serializers.rb +3 -1
- data/lib/cuprum/rails/version.rb +1 -1
- data/lib/cuprum/rails.rb +19 -16
- metadata +73 -131
- data/lib/cuprum/rails/controller_action.rb +0 -121
- data/lib/cuprum/rails/errors/missing_parameters.rb +0 -33
- data/lib/cuprum/rails/errors/missing_primary_key.rb +0 -46
- data/lib/cuprum/rails/errors/undefined_permitted_attributes.rb +0 -34
- data/lib/cuprum/rails/rspec/command_contract.rb +0 -460
- data/lib/cuprum/rails/rspec/define_route_contract.rb +0 -84
- 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
|