cuprum-collections 0.4.0 → 0.5.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 +73 -0
- data/README.md +5 -5
- data/lib/cuprum/collections/association.rb +9 -28
- data/lib/cuprum/collections/associations/belongs_to.rb +1 -8
- data/lib/cuprum/collections/associations/has_many.rb +1 -10
- data/lib/cuprum/collections/associations/has_one.rb +1 -10
- data/lib/cuprum/collections/basic/collection.rb +56 -49
- data/lib/cuprum/collections/basic/command.rb +22 -88
- data/lib/cuprum/collections/basic/commands/assign_one.rb +2 -6
- data/lib/cuprum/collections/basic/commands/build_one.rb +1 -4
- data/lib/cuprum/collections/basic/commands/destroy_one.rb +4 -8
- data/lib/cuprum/collections/basic/commands/find_many.rb +4 -24
- data/lib/cuprum/collections/basic/commands/find_matching.rb +5 -21
- data/lib/cuprum/collections/basic/commands/find_one.rb +3 -20
- data/lib/cuprum/collections/basic/commands/insert_one.rb +3 -6
- data/lib/cuprum/collections/basic/commands/update_one.rb +3 -6
- data/lib/cuprum/collections/basic/commands/validate_one.rb +13 -18
- data/lib/cuprum/collections/basic/query.rb +26 -40
- data/lib/cuprum/collections/basic/repository.rb +4 -3
- data/lib/cuprum/collections/basic/scopes/all_scope.rb +25 -0
- data/lib/cuprum/collections/basic/scopes/base.rb +32 -0
- data/lib/cuprum/collections/basic/scopes/builder.rb +39 -0
- data/lib/cuprum/collections/basic/scopes/conjunction_scope.rb +20 -0
- data/lib/cuprum/collections/basic/scopes/criteria_scope.rb +62 -0
- data/lib/cuprum/collections/basic/scopes/disjunction_scope.rb +20 -0
- data/lib/cuprum/collections/basic/scopes/none_scope.rb +33 -0
- data/lib/cuprum/collections/basic/scopes.rb +23 -0
- data/lib/cuprum/collections/basic.rb +1 -0
- data/lib/cuprum/collections/collection.rb +24 -82
- data/lib/cuprum/collections/collection_command.rb +116 -0
- data/lib/cuprum/collections/commands/abstract_find_many.rb +11 -21
- data/lib/cuprum/collections/commands/abstract_find_matching.rb +43 -24
- data/lib/cuprum/collections/commands/abstract_find_one.rb +7 -10
- data/lib/cuprum/collections/commands/associations/find_many.rb +3 -8
- data/lib/cuprum/collections/commands/associations/require_many.rb +5 -5
- data/lib/cuprum/collections/commands/create.rb +3 -3
- data/lib/cuprum/collections/commands/find_one_matching.rb +6 -6
- data/lib/cuprum/collections/commands/query_command.rb +19 -0
- data/lib/cuprum/collections/commands/update.rb +3 -3
- data/lib/cuprum/collections/commands/upsert.rb +10 -10
- data/lib/cuprum/collections/commands.rb +1 -0
- data/lib/cuprum/collections/constraints/ordering.rb +2 -2
- data/lib/cuprum/collections/errors/abstract_find_error.rb +25 -42
- data/lib/cuprum/collections/errors/extra_attributes.rb +3 -3
- data/lib/cuprum/collections/errors/failed_validation.rb +2 -2
- data/lib/cuprum/collections/errors/invalid_parameters.rb +2 -2
- data/lib/cuprum/collections/errors/invalid_query.rb +10 -16
- data/lib/cuprum/collections/errors/missing_default_contract.rb +1 -1
- data/lib/cuprum/collections/errors/unknown_operator.rb +1 -1
- data/lib/cuprum/collections/queries.rb +31 -0
- data/lib/cuprum/collections/query.rb +50 -62
- data/lib/cuprum/collections/relation.rb +5 -383
- data/lib/cuprum/collections/relations/cardinality.rb +66 -0
- data/lib/cuprum/collections/relations/options.rb +18 -0
- data/lib/cuprum/collections/relations/parameters.rb +217 -0
- data/lib/cuprum/collections/relations/primary_keys.rb +23 -0
- data/lib/cuprum/collections/relations/scope.rb +65 -0
- data/lib/cuprum/collections/relations.rb +14 -0
- data/lib/cuprum/collections/repository.rb +5 -5
- data/lib/cuprum/collections/resource.rb +10 -41
- data/lib/cuprum/collections/rspec/contracts/association_contracts.rb +80 -90
- data/lib/cuprum/collections/rspec/contracts/collection_contracts.rb +69 -111
- data/lib/cuprum/collections/rspec/contracts/command_contracts.rb +42 -1335
- data/lib/cuprum/collections/rspec/contracts/query_contracts.rb +352 -531
- data/lib/cuprum/collections/rspec/contracts/relation_contracts.rb +74 -191
- data/lib/cuprum/collections/rspec/contracts/repository_contracts.rb +13 -13
- data/lib/cuprum/collections/rspec/contracts/scope_contracts.rb +1029 -0
- data/lib/cuprum/collections/rspec/contracts/scopes/builder_contracts.rb +856 -0
- data/lib/cuprum/collections/rspec/contracts/scopes/composition_contracts.rb +1430 -0
- data/lib/cuprum/collections/rspec/contracts/scopes/criteria_contracts.rb +2217 -0
- data/lib/cuprum/collections/rspec/contracts/scopes/logical_contracts.rb +297 -0
- data/lib/cuprum/collections/rspec/contracts/scopes.rb +13 -0
- data/lib/cuprum/collections/rspec/contracts.rb +2 -0
- data/lib/cuprum/collections/rspec/deferred/association_examples.rb +2098 -0
- data/lib/cuprum/collections/rspec/deferred/collection_examples.rb +338 -0
- data/lib/cuprum/collections/rspec/deferred/command_examples.rb +160 -0
- data/lib/cuprum/collections/rspec/deferred/commands/assign_one_examples.rb +178 -0
- data/lib/cuprum/collections/rspec/deferred/commands/build_one_examples.rb +94 -0
- data/lib/cuprum/collections/rspec/deferred/commands/destroy_one_examples.rb +118 -0
- data/lib/cuprum/collections/rspec/deferred/commands/find_many_examples.rb +307 -0
- data/lib/cuprum/collections/rspec/deferred/commands/find_matching_examples.rb +143 -0
- data/lib/cuprum/collections/rspec/deferred/commands/find_one_examples.rb +116 -0
- data/lib/cuprum/collections/rspec/deferred/commands/insert_one_examples.rb +103 -0
- data/lib/cuprum/collections/rspec/deferred/commands/update_one_examples.rb +99 -0
- data/lib/cuprum/collections/rspec/deferred/commands/validate_one_examples.rb +117 -0
- data/lib/cuprum/collections/rspec/deferred/commands.rb +8 -0
- data/lib/cuprum/collections/rspec/deferred/relation_examples.rb +1437 -0
- data/lib/cuprum/collections/rspec/deferred/resource_examples.rb +26 -0
- data/lib/cuprum/collections/rspec/deferred.rb +8 -0
- data/lib/cuprum/collections/scope.rb +29 -0
- data/lib/cuprum/collections/scopes/all.rb +51 -0
- data/lib/cuprum/collections/scopes/all_scope.rb +18 -0
- data/lib/cuprum/collections/scopes/base.rb +79 -0
- data/lib/cuprum/collections/scopes/builder.rb +39 -0
- data/lib/cuprum/collections/scopes/building.rb +221 -0
- data/lib/cuprum/collections/scopes/composition.rb +162 -0
- data/lib/cuprum/collections/scopes/conjunction.rb +44 -0
- data/lib/cuprum/collections/scopes/conjunction_scope.rb +12 -0
- data/lib/cuprum/collections/scopes/container.rb +65 -0
- data/lib/cuprum/collections/scopes/criteria/parser.rb +241 -0
- data/lib/cuprum/collections/scopes/criteria.rb +206 -0
- data/lib/cuprum/collections/scopes/criteria_scope.rb +12 -0
- data/lib/cuprum/collections/scopes/disjunction.rb +45 -0
- data/lib/cuprum/collections/scopes/disjunction_scope.rb +12 -0
- data/lib/cuprum/collections/scopes/none.rb +62 -0
- data/lib/cuprum/collections/scopes/none_scope.rb +18 -0
- data/lib/cuprum/collections/scopes.rb +23 -0
- data/lib/cuprum/collections/version.rb +2 -2
- data/lib/cuprum/collections.rb +14 -9
- metadata +61 -15
- data/lib/cuprum/collections/basic/query_builder.rb +0 -69
- data/lib/cuprum/collections/command.rb +0 -26
- data/lib/cuprum/collections/queries/parse.rb +0 -22
- data/lib/cuprum/collections/queries/parse_block.rb +0 -206
- data/lib/cuprum/collections/queries/parse_strategy.rb +0 -91
- data/lib/cuprum/collections/query_builder.rb +0 -61
- data/lib/cuprum/collections/rspec/contracts/basic/command_contracts.rb +0 -484
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/collections/rspec/deferred/command_examples'
|
4
|
+
require 'cuprum/collections/rspec/deferred/commands'
|
5
|
+
|
6
|
+
module Cuprum::Collections::RSpec::Deferred::Commands
|
7
|
+
# Namespace for deferred example groups for validating BuildOne commands.
|
8
|
+
module BuildOneExamples
|
9
|
+
include RSpec::SleepingKingStudios::Deferred::Provider
|
10
|
+
|
11
|
+
deferred_examples 'should implement the BuildOne command' \
|
12
|
+
do |allow_extra_attributes: true|
|
13
|
+
describe '#call' do
|
14
|
+
include Cuprum::Collections::RSpec::Deferred::CommandExamples
|
15
|
+
|
16
|
+
shared_examples 'should build the entity' do
|
17
|
+
it { expect(result).to be_a_passing_result }
|
18
|
+
|
19
|
+
it { expect(result.value).to be == expected_value }
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:attributes) { {} }
|
23
|
+
let(:result) { command.call(attributes:) }
|
24
|
+
let(:expected_attributes) do
|
25
|
+
attributes
|
26
|
+
end
|
27
|
+
let(:expected_value) do
|
28
|
+
defined?(super()) ? super() : attributes
|
29
|
+
end
|
30
|
+
|
31
|
+
def call_command
|
32
|
+
command.call(attributes:)
|
33
|
+
end
|
34
|
+
|
35
|
+
include_deferred 'should validate the attributes parameter'
|
36
|
+
|
37
|
+
describe 'with an empty attributes hash' do
|
38
|
+
let(:attributes) { {} }
|
39
|
+
|
40
|
+
include_examples 'should build the entity'
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'with an attributes hash with partial attributes' do
|
44
|
+
let(:attributes) { { title: 'Gideon the Ninth' } }
|
45
|
+
|
46
|
+
include_examples 'should build the entity'
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'with an attributes hash with full attributes' do
|
50
|
+
let(:attributes) do
|
51
|
+
{
|
52
|
+
title: 'Gideon the Ninth',
|
53
|
+
author: 'Tamsyn Muir',
|
54
|
+
series: 'The Locked Tomb',
|
55
|
+
category: 'Horror'
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
include_examples 'should build the entity'
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'with an attributes hash with extra attributes' do
|
63
|
+
let(:attributes) do
|
64
|
+
{
|
65
|
+
title: 'The Book of Lost Tales',
|
66
|
+
audiobook: true
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
if allow_extra_attributes
|
71
|
+
include_examples 'should build the entity'
|
72
|
+
else
|
73
|
+
# :nocov:
|
74
|
+
let(:valid_attributes) do
|
75
|
+
defined?(super()) ? super() : expected_attributes.keys
|
76
|
+
end
|
77
|
+
let(:expected_error) do
|
78
|
+
Cuprum::Collections::Errors::ExtraAttributes.new(
|
79
|
+
entity_class:,
|
80
|
+
extra_attributes: %w[audiobook],
|
81
|
+
valid_attributes:
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should return a failing result' do
|
86
|
+
expect(result).to be_a_failing_result.with_error(expected_error)
|
87
|
+
end
|
88
|
+
# :nocov:
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/collections/rspec/deferred/command_examples'
|
4
|
+
require 'cuprum/collections/rspec/deferred/commands'
|
5
|
+
|
6
|
+
module Cuprum::Collections::RSpec::Deferred::Commands
|
7
|
+
# Namespace for deferred example groups for validating DestroyOne commands.
|
8
|
+
module DestroyOneExamples
|
9
|
+
include RSpec::SleepingKingStudios::Deferred::Provider
|
10
|
+
|
11
|
+
deferred_examples 'should implement the DestroyOne command' do
|
12
|
+
describe '#call' do
|
13
|
+
include Cuprum::Collections::RSpec::Deferred::CommandExamples
|
14
|
+
|
15
|
+
let(:query) { collection.query }
|
16
|
+
let(:mapped_data) do
|
17
|
+
defined?(super()) ? super() : data
|
18
|
+
end
|
19
|
+
let(:invalid_primary_key_value) do
|
20
|
+
defined?(super()) ? super() : 100
|
21
|
+
end
|
22
|
+
let(:valid_primary_key_value) do
|
23
|
+
defined?(super()) ? super() : 0
|
24
|
+
end
|
25
|
+
|
26
|
+
def call_command
|
27
|
+
command.call(primary_key:)
|
28
|
+
end
|
29
|
+
|
30
|
+
include_deferred 'should validate the primary key parameter'
|
31
|
+
|
32
|
+
describe 'with an invalid primary key' do
|
33
|
+
let(:primary_key) { invalid_primary_key_value }
|
34
|
+
let(:expected_error) do
|
35
|
+
Cuprum::Collections::Errors::NotFound.new(
|
36
|
+
attribute_name: collection.primary_key_name,
|
37
|
+
attribute_value: primary_key,
|
38
|
+
collection_name: collection.name,
|
39
|
+
primary_key: true
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should return a failing result' do
|
44
|
+
expect(command.call(primary_key:))
|
45
|
+
.to be_a_failing_result
|
46
|
+
.with_error(expected_error)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should not remove an entity from the collection' do
|
50
|
+
expect { command.call(primary_key:) }
|
51
|
+
.not_to(change { query.reset.count })
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'when the collection has many items' do
|
56
|
+
let(:data) { fixtures_data }
|
57
|
+
let(:matching_data) do
|
58
|
+
mapped_data.find do |item|
|
59
|
+
item[collection.primary_key_name.to_s] == primary_key
|
60
|
+
end
|
61
|
+
end
|
62
|
+
let!(:expected_data) do
|
63
|
+
defined?(super()) ? super() : matching_data
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'with an invalid primary key' do
|
67
|
+
let(:primary_key) { invalid_primary_key_value }
|
68
|
+
let(:expected_error) do
|
69
|
+
Cuprum::Collections::Errors::NotFound.new(
|
70
|
+
attribute_name: collection.primary_key_name,
|
71
|
+
attribute_value: primary_key,
|
72
|
+
collection_name: collection.name,
|
73
|
+
primary_key: true
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should return a failing result' do
|
78
|
+
expect(command.call(primary_key:))
|
79
|
+
.to be_a_failing_result
|
80
|
+
.with_error(expected_error)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should not remove an entity from the collection' do
|
84
|
+
expect { command.call(primary_key:) }
|
85
|
+
.not_to(change { query.reset.count })
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'with a valid primary key' do
|
90
|
+
let(:primary_key) { valid_primary_key_value }
|
91
|
+
|
92
|
+
it 'should return a passing result' do
|
93
|
+
expect(command.call(primary_key:))
|
94
|
+
.to be_a_passing_result
|
95
|
+
.with_value(expected_data)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should remove an entity from the collection' do
|
99
|
+
expect { command.call(primary_key:) }
|
100
|
+
.to(
|
101
|
+
change { query.reset.count }.by(-1)
|
102
|
+
)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should remove the entity from the collection' do
|
106
|
+
command.call(primary_key:)
|
107
|
+
|
108
|
+
expect(
|
109
|
+
query.map { |item| item[collection.primary_key_name.to_s] }
|
110
|
+
)
|
111
|
+
.not_to include primary_key
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,307 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/collections/rspec/deferred/command_examples'
|
4
|
+
require 'cuprum/collections/rspec/deferred/commands'
|
5
|
+
|
6
|
+
module Cuprum::Collections::RSpec::Deferred::Commands
|
7
|
+
# Namespace for deferred example groups for validating FindMany commands.
|
8
|
+
module FindManyExamples
|
9
|
+
include RSpec::SleepingKingStudios::Deferred::Provider
|
10
|
+
|
11
|
+
deferred_examples 'should implement the FindMany command' do
|
12
|
+
describe '#call' do
|
13
|
+
include Cuprum::Collections::RSpec::Deferred::CommandExamples
|
14
|
+
|
15
|
+
let(:mapped_data) do
|
16
|
+
defined?(super()) ? super() : data
|
17
|
+
end
|
18
|
+
let(:primary_key_name) { defined?(super()) ? super() : 'id' }
|
19
|
+
let(:primary_key_type) { defined?(super()) ? super() : Integer }
|
20
|
+
let(:invalid_primary_key_values) do
|
21
|
+
defined?(super()) ? super() : [100, 101, 102]
|
22
|
+
end
|
23
|
+
let(:valid_primary_key_values) do
|
24
|
+
defined?(super()) ? super() : [0, 1, 2]
|
25
|
+
end
|
26
|
+
let(:primary_keys) { [] }
|
27
|
+
let(:options) { {} }
|
28
|
+
|
29
|
+
def call_command
|
30
|
+
command.call(primary_keys:, **options)
|
31
|
+
end
|
32
|
+
|
33
|
+
include_deferred 'should validate the primary keys parameter'
|
34
|
+
|
35
|
+
describe 'with an invalid allow_partial value' do
|
36
|
+
let(:options) { super().merge(allow_partial: Object.new.freeze) }
|
37
|
+
|
38
|
+
include_deferred 'should validate the parameter',
|
39
|
+
:allow_partial,
|
40
|
+
'sleeping_king_studios.tools.assertions.boolean'
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'with an invalid envelope value' do
|
44
|
+
let(:options) { super().merge(envelope: Object.new.freeze) }
|
45
|
+
|
46
|
+
include_deferred 'should validate the parameter',
|
47
|
+
:envelope,
|
48
|
+
'sleeping_king_studios.tools.assertions.boolean'
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'with an empty array of primary keys' do
|
52
|
+
let(:primary_keys) { [] }
|
53
|
+
let(:expected_data) { [] }
|
54
|
+
|
55
|
+
it 'should return a passing result' do
|
56
|
+
expect(command.call(primary_keys:))
|
57
|
+
.to be_a_passing_result
|
58
|
+
.with_value(expected_data)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'with an array of invalid primary keys' do
|
63
|
+
let(:primary_keys) { invalid_primary_key_values }
|
64
|
+
let(:expected_error) do
|
65
|
+
Cuprum::Errors::MultipleErrors.new(
|
66
|
+
errors: primary_keys.map do |primary_key|
|
67
|
+
Cuprum::Collections::Errors::NotFound.new(
|
68
|
+
attribute_name: collection.primary_key_name,
|
69
|
+
attribute_value: primary_key,
|
70
|
+
collection_name: collection.name,
|
71
|
+
primary_key: true
|
72
|
+
)
|
73
|
+
end
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should return a failing result' do
|
78
|
+
expect(command.call(primary_keys:))
|
79
|
+
.to be_a_failing_result
|
80
|
+
.with_error(expected_error)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when the collection has many items' do
|
85
|
+
let(:data) { fixtures_data }
|
86
|
+
let(:matching_data) do
|
87
|
+
primary_keys
|
88
|
+
.map do |key|
|
89
|
+
mapped_data.find { |item| item[primary_key_name.to_s] == key }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
let(:expected_data) do
|
93
|
+
defined?(super()) ? super() : matching_data
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'with an empty array of primary keys' do
|
97
|
+
let(:primary_keys) { [] }
|
98
|
+
let(:expected_data) { [] }
|
99
|
+
|
100
|
+
it 'should return a passing result' do
|
101
|
+
expect(command.call(primary_keys:))
|
102
|
+
.to be_a_passing_result
|
103
|
+
.with_value(expected_data)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'with an array of invalid primary keys' do
|
108
|
+
let(:primary_keys) { invalid_primary_key_values }
|
109
|
+
let(:expected_error) do
|
110
|
+
Cuprum::Errors::MultipleErrors.new(
|
111
|
+
errors: primary_keys.map do |primary_key|
|
112
|
+
Cuprum::Collections::Errors::NotFound.new(
|
113
|
+
attribute_name: collection.primary_key_name,
|
114
|
+
attribute_value: primary_key,
|
115
|
+
collection_name: collection.name,
|
116
|
+
primary_key: true
|
117
|
+
)
|
118
|
+
end
|
119
|
+
)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should return a failing result' do
|
123
|
+
expect(command.call(primary_keys:))
|
124
|
+
.to be_a_failing_result
|
125
|
+
.with_error(expected_error)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe 'with a partially valid array of primary keys' do
|
130
|
+
let(:primary_keys) do
|
131
|
+
invalid_primary_key_values + valid_primary_key_values
|
132
|
+
end
|
133
|
+
let(:expected_error) do
|
134
|
+
Cuprum::Errors::MultipleErrors.new(
|
135
|
+
errors: primary_keys.map do |primary_key|
|
136
|
+
unless invalid_primary_key_values.include?(primary_key)
|
137
|
+
next nil
|
138
|
+
end
|
139
|
+
|
140
|
+
Cuprum::Collections::Errors::NotFound.new(
|
141
|
+
attribute_name: collection.primary_key_name,
|
142
|
+
attribute_value: primary_key,
|
143
|
+
collection_name: collection.name,
|
144
|
+
primary_key: true
|
145
|
+
)
|
146
|
+
end
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should return a failing result' do
|
151
|
+
expect(command.call(primary_keys:))
|
152
|
+
.to be_a_failing_result
|
153
|
+
.with_error(expected_error)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe 'with a valid array of primary keys' do
|
158
|
+
let(:primary_keys) { valid_primary_key_values }
|
159
|
+
|
160
|
+
it 'should return a passing result' do
|
161
|
+
expect(command.call(primary_keys:))
|
162
|
+
.to be_a_passing_result
|
163
|
+
.with_value(expected_data)
|
164
|
+
end
|
165
|
+
|
166
|
+
describe 'with an ordered array of primary keys' do
|
167
|
+
let(:primary_keys) { valid_primary_key_values.reverse }
|
168
|
+
|
169
|
+
it 'should return a passing result' do
|
170
|
+
expect(command.call(primary_keys:))
|
171
|
+
.to be_a_passing_result
|
172
|
+
.with_value(expected_data)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe 'with allow_partial: true' do
|
178
|
+
describe 'with an array of invalid primary keys' do
|
179
|
+
let(:primary_keys) { invalid_primary_key_values }
|
180
|
+
let(:expected_error) do
|
181
|
+
Cuprum::Errors::MultipleErrors.new(
|
182
|
+
errors: invalid_primary_key_values.map do |primary_key|
|
183
|
+
Cuprum::Collections::Errors::NotFound.new(
|
184
|
+
attribute_name: collection.primary_key_name,
|
185
|
+
attribute_value: primary_key,
|
186
|
+
collection_name: collection.name,
|
187
|
+
primary_key: true
|
188
|
+
)
|
189
|
+
end
|
190
|
+
)
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should return a failing result' do
|
194
|
+
expect(command.call(primary_keys:))
|
195
|
+
.to be_a_failing_result
|
196
|
+
.with_error(expected_error)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe 'with a partially valid array of primary keys' do
|
201
|
+
let(:primary_keys) do
|
202
|
+
invalid_primary_key_values + valid_primary_key_values
|
203
|
+
end
|
204
|
+
let(:expected_error) do
|
205
|
+
Cuprum::Errors::MultipleErrors.new(
|
206
|
+
errors: primary_keys.map do |primary_key|
|
207
|
+
unless invalid_primary_key_values.include?(primary_key)
|
208
|
+
next nil
|
209
|
+
end
|
210
|
+
|
211
|
+
Cuprum::Collections::Errors::NotFound.new(
|
212
|
+
attribute_name: collection.primary_key_name,
|
213
|
+
attribute_value: primary_key,
|
214
|
+
collection_name: collection.name,
|
215
|
+
primary_key: true
|
216
|
+
)
|
217
|
+
end
|
218
|
+
)
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'should return a passing result' do
|
222
|
+
expect(
|
223
|
+
command.call(
|
224
|
+
primary_keys:,
|
225
|
+
allow_partial: true
|
226
|
+
)
|
227
|
+
)
|
228
|
+
.to be_a_passing_result
|
229
|
+
.with_value(expected_data)
|
230
|
+
.and_error(expected_error)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe 'with a valid array of primary keys' do
|
235
|
+
let(:primary_keys) { valid_primary_key_values }
|
236
|
+
|
237
|
+
it 'should return a passing result' do
|
238
|
+
expect(
|
239
|
+
command.call(
|
240
|
+
primary_keys:,
|
241
|
+
allow_partial: true
|
242
|
+
)
|
243
|
+
)
|
244
|
+
.to be_a_passing_result
|
245
|
+
.with_value(expected_data)
|
246
|
+
end
|
247
|
+
|
248
|
+
describe 'with an ordered array of primary keys' do
|
249
|
+
let(:primary_keys) { valid_primary_key_values.reverse }
|
250
|
+
|
251
|
+
it 'should return a passing result' do
|
252
|
+
expect(
|
253
|
+
command.call(
|
254
|
+
primary_keys:,
|
255
|
+
allow_partial: true
|
256
|
+
)
|
257
|
+
)
|
258
|
+
.to be_a_passing_result
|
259
|
+
.with_value(expected_data)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
describe 'with envelope: true' do
|
266
|
+
describe 'with an empty array of primary keys' do
|
267
|
+
let(:primary_keys) { [] }
|
268
|
+
let(:expected_data) { [] }
|
269
|
+
|
270
|
+
it 'should return a passing result' do
|
271
|
+
expect(
|
272
|
+
command.call(primary_keys:, envelope: true)
|
273
|
+
)
|
274
|
+
.to be_a_passing_result
|
275
|
+
.with_value(match({ collection.name => expected_data }))
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
describe 'with a valid array of primary keys' do
|
280
|
+
let(:primary_keys) { valid_primary_key_values }
|
281
|
+
|
282
|
+
it 'should return a passing result' do
|
283
|
+
expect(
|
284
|
+
command.call(primary_keys:, envelope: true)
|
285
|
+
)
|
286
|
+
.to be_a_passing_result
|
287
|
+
.with_value(match({ collection.name => expected_data }))
|
288
|
+
end
|
289
|
+
|
290
|
+
describe 'with an ordered array of primary keys' do
|
291
|
+
let(:primary_keys) { valid_primary_key_values.reverse }
|
292
|
+
|
293
|
+
it 'should return a passing result' do
|
294
|
+
expect(
|
295
|
+
command.call(primary_keys:, envelope: true)
|
296
|
+
)
|
297
|
+
.to be_a_passing_result
|
298
|
+
.with_value(match({ collection.name => expected_data }))
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/collections/rspec/contracts/query_contracts'
|
4
|
+
require 'cuprum/collections/rspec/deferred/command_examples'
|
5
|
+
require 'cuprum/collections/rspec/deferred/commands'
|
6
|
+
|
7
|
+
module Cuprum::Collections::RSpec::Deferred::Commands
|
8
|
+
# Namespace for deferred example groups for validating FindMatching commands.
|
9
|
+
module FindMatchingExamples
|
10
|
+
include RSpec::SleepingKingStudios::Deferred::Provider
|
11
|
+
|
12
|
+
deferred_examples 'should implement the FindMatching command' do
|
13
|
+
describe '#call' do
|
14
|
+
include Cuprum::Collections::RSpec::Contracts::QueryContracts
|
15
|
+
include Cuprum::Collections::RSpec::Deferred::CommandExamples
|
16
|
+
|
17
|
+
shared_examples 'should return the matching items' do
|
18
|
+
it { expect(result).to be_a_passing_result }
|
19
|
+
|
20
|
+
it { expect(result.value).to be_a Enumerator }
|
21
|
+
|
22
|
+
it { expect(result.value.to_a).to be == expected_data }
|
23
|
+
end
|
24
|
+
|
25
|
+
shared_examples 'should return the wrapped items' do
|
26
|
+
it { expect(result).to be_a_passing_result }
|
27
|
+
|
28
|
+
it { expect(result.value).to be_a Hash }
|
29
|
+
|
30
|
+
it { expect(result.value.keys).to be == [collection.name] }
|
31
|
+
|
32
|
+
it { expect(result.value[collection.name]).to be == expected_data }
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:filter) { nil }
|
36
|
+
let(:limit) { nil }
|
37
|
+
let(:offset) { nil }
|
38
|
+
let(:order) { nil }
|
39
|
+
let(:options) do
|
40
|
+
opts = {}
|
41
|
+
|
42
|
+
opts[:limit] = limit if limit
|
43
|
+
opts[:offset] = offset if offset
|
44
|
+
opts[:order] = order if order
|
45
|
+
opts[:where] = filter unless filter.nil? || filter.is_a?(Proc)
|
46
|
+
|
47
|
+
opts
|
48
|
+
end
|
49
|
+
let(:block) { filter.is_a?(Proc) ? filter : nil }
|
50
|
+
let(:result) { command.call(**options, &block) }
|
51
|
+
let(:data) { [] }
|
52
|
+
let(:filtered_data) do
|
53
|
+
defined?(super()) ? super() : data
|
54
|
+
end
|
55
|
+
let(:matching_data) do
|
56
|
+
defined?(super()) ? super() : filtered_data
|
57
|
+
end
|
58
|
+
let(:expected_data) do
|
59
|
+
defined?(super()) ? super() : matching_data
|
60
|
+
end
|
61
|
+
|
62
|
+
def call_command
|
63
|
+
command.call(**options, &block)
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'with an invalid envelope value' do
|
67
|
+
let(:options) { super().merge(envelope: Object.new.freeze) }
|
68
|
+
|
69
|
+
include_deferred 'should validate the parameter',
|
70
|
+
:envelope,
|
71
|
+
'sleeping_king_studios.tools.assertions.boolean'
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'with an invalid limit value' do
|
75
|
+
let(:options) { super().merge(limit: Object.new.freeze) }
|
76
|
+
|
77
|
+
include_deferred 'should validate the parameter',
|
78
|
+
:limit,
|
79
|
+
'sleeping_king_studios.tools.assertions.instance_of',
|
80
|
+
expected: Integer
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'with an invalid offset value' do
|
84
|
+
let(:options) { super().merge(offset: Object.new.freeze) }
|
85
|
+
|
86
|
+
include_deferred 'should validate the parameter',
|
87
|
+
:offset,
|
88
|
+
'sleeping_king_studios.tools.assertions.instance_of',
|
89
|
+
expected: Integer
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'with an invalid order value' do
|
93
|
+
let(:options) { super().merge(order: Object.new.freeze) }
|
94
|
+
|
95
|
+
include_deferred 'should validate the parameter',
|
96
|
+
:order,
|
97
|
+
message: 'order is not a valid sort order'
|
98
|
+
end
|
99
|
+
|
100
|
+
describe 'with an invalid where value' do
|
101
|
+
let(:options) { super().merge(where: Object.new.freeze) }
|
102
|
+
|
103
|
+
include_deferred 'should validate the parameter',
|
104
|
+
:where,
|
105
|
+
message: 'where is not a scope or query hash'
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'with an invalid filter block' do
|
109
|
+
let(:block) { -> {} }
|
110
|
+
let(:expected_error) do
|
111
|
+
an_instance_of(Cuprum::Collections::Errors::InvalidQuery)
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should return a failing result' do
|
115
|
+
expect(result).to be_a_failing_result.with_error(expected_error)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
include_examples 'should return the matching items'
|
120
|
+
|
121
|
+
describe 'with envelope: true' do
|
122
|
+
let(:options) { super().merge(envelope: true) }
|
123
|
+
|
124
|
+
include_examples 'should return the wrapped items'
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'when the collection has many items' do
|
128
|
+
let(:data) { fixtures_data }
|
129
|
+
|
130
|
+
include_contract 'should query the collection' do
|
131
|
+
include_examples 'should return the matching items'
|
132
|
+
|
133
|
+
describe 'with envelope: true' do
|
134
|
+
let(:options) { super().merge(envelope: true) }
|
135
|
+
|
136
|
+
include_examples 'should return the wrapped items'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|