wcc-contentful 1.0.7 → 1.1.2
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/README.md +174 -9
- data/app/jobs/wcc/contentful/webhook_enable_job.rb +7 -7
- data/lib/wcc/contentful/instrumentation.rb +20 -2
- data/lib/wcc/contentful/link_visitor.rb +26 -30
- data/lib/wcc/contentful/middleware/store.rb +2 -1
- data/lib/wcc/contentful/model.rb +5 -128
- data/lib/wcc/contentful/model_api.rb +189 -0
- data/lib/wcc/contentful/model_builder.rb +10 -4
- data/lib/wcc/contentful/model_methods.rb +8 -10
- data/lib/wcc/contentful/model_singleton_methods.rb +8 -8
- data/lib/wcc/contentful/rspec.rb +7 -5
- data/lib/wcc/contentful/services.rb +59 -61
- data/lib/wcc/contentful/store/cdn_adapter.rb +7 -1
- data/lib/wcc/contentful/store/factory.rb +2 -6
- data/lib/wcc/contentful/store/memory_store.rb +47 -13
- data/lib/wcc/contentful/store/query.rb +22 -2
- data/lib/wcc/contentful/store/rspec_examples/basic_store.rb +0 -103
- data/lib/wcc/contentful/store/rspec_examples/operators/eq.rb +92 -0
- data/lib/wcc/contentful/store/rspec_examples/operators/in.rb +131 -0
- data/lib/wcc/contentful/store/rspec_examples/operators/ne.rb +77 -0
- data/lib/wcc/contentful/store/rspec_examples/operators/nin.rb +80 -0
- data/lib/wcc/contentful/store/rspec_examples/operators.rb +50 -0
- data/lib/wcc/contentful/store/rspec_examples.rb +2 -0
- data/lib/wcc/contentful/sync_engine.rb +0 -1
- data/lib/wcc/contentful/test/attributes.rb +0 -4
- data/lib/wcc/contentful/test/double.rb +4 -2
- data/lib/wcc/contentful/test/factory.rb +4 -2
- data/lib/wcc/contentful/version.rb +1 -1
- data/lib/wcc/contentful.rb +14 -8
- metadata +117 -37
@@ -34,6 +34,17 @@ module WCC::Contentful::Store
|
|
34
34
|
@extra = extra
|
35
35
|
end
|
36
36
|
|
37
|
+
FALSE_VALUES = [
|
38
|
+
false, 0,
|
39
|
+
'0', :"0",
|
40
|
+
'f', :f,
|
41
|
+
'F', :F,
|
42
|
+
'false', :false, # rubocop:disable Lint/BooleanSymbol
|
43
|
+
'FALSE', :FALSE,
|
44
|
+
'off', :off,
|
45
|
+
'OFF', :OFF
|
46
|
+
].to_set.freeze
|
47
|
+
|
37
48
|
# Returns a new chained Query that has a new condition. The new condition
|
38
49
|
# represents the WHERE comparison being applied here. The underlying store
|
39
50
|
# implementation translates this condition statement into an appropriate
|
@@ -50,7 +61,16 @@ module WCC::Contentful::Store
|
|
50
61
|
# @expected The expected value to compare the field's value against.
|
51
62
|
# @context A context object optionally containing `context[:locale]`
|
52
63
|
def apply_operator(operator, field, expected, context = nil)
|
64
|
+
operator ||= expected.is_a?(Array) ? :in : :eq
|
53
65
|
raise ArgumentError, "Operator #{operator} not supported" unless respond_to?(operator)
|
66
|
+
raise ArgumentError, 'value cannot be nil (try using exists: false)' if expected.nil?
|
67
|
+
|
68
|
+
case operator
|
69
|
+
when :in, :nin, :all
|
70
|
+
expected = Array(expected)
|
71
|
+
when :exists
|
72
|
+
expected = !FALSE_VALUES.include?(expected)
|
73
|
+
end
|
54
74
|
|
55
75
|
field = field.to_s if field.is_a? Symbol
|
56
76
|
path = field.is_a?(Array) ? field : field.split('.')
|
@@ -108,7 +128,7 @@ module WCC::Contentful::Store
|
|
108
128
|
includes = row.try(:includes) || row.try(:[], 1)
|
109
129
|
return entry unless entry && depth && depth > 0
|
110
130
|
|
111
|
-
WCC::Contentful::LinkVisitor.new(entry, :Link,
|
131
|
+
WCC::Contentful::LinkVisitor.new(entry, :Link,
|
112
132
|
# Walk all the links except for the leaf nodes
|
113
133
|
depth: depth - 1).map! do |val|
|
114
134
|
resolve_link(val, includes)
|
@@ -151,7 +171,7 @@ module WCC::Contentful::Store
|
|
151
171
|
elsif op?(k)
|
152
172
|
{ path: path, op: k.to_sym, expected: v }
|
153
173
|
else
|
154
|
-
{ path: path + [k], op:
|
174
|
+
{ path: path + [k], op: nil, expected: v }
|
155
175
|
end
|
156
176
|
end
|
157
177
|
end
|
@@ -130,24 +130,6 @@ RSpec.shared_examples 'basic store' do
|
|
130
130
|
JSON
|
131
131
|
end
|
132
132
|
|
133
|
-
before do
|
134
|
-
allow(WCC::Contentful).to receive(:types)
|
135
|
-
.and_return({
|
136
|
-
'root' => double(fields: {
|
137
|
-
'name' => double(name: 'name', type: :String, array: false),
|
138
|
-
'link' => double(name: 'link', type: :Link, array: false),
|
139
|
-
'links' => double(name: 'links', type: :Link, array: true)
|
140
|
-
}),
|
141
|
-
'shallow' => double(fields: {
|
142
|
-
'name' => double(name: 'name', type: :String, array: false)
|
143
|
-
}),
|
144
|
-
'deep' => double(fields: {
|
145
|
-
'name' => double(name: 'name', type: :String, array: false),
|
146
|
-
'subLink' => double(name: 'subLink', type: :Link, array: false)
|
147
|
-
})
|
148
|
-
})
|
149
|
-
end
|
150
|
-
|
151
133
|
describe '#set/#find' do
|
152
134
|
describe 'ensures that the stored value is of type Hash' do
|
153
135
|
it 'should not raise an error if value is a Hash' do
|
@@ -546,68 +528,6 @@ RSpec.shared_examples 'basic store' do
|
|
546
528
|
expect(found.dig('sys', 'id')).to eq('idTwo')
|
547
529
|
expect(found.dig('fields', 'system', 'en-US')).to eq('Two')
|
548
530
|
end
|
549
|
-
|
550
|
-
[
|
551
|
-
[Integer, proc { rand(-4_611_686_018_427_387_903..4_611_686_018_427_387_903) }],
|
552
|
-
[Float, proc { rand }]
|
553
|
-
].each do |(type, generator)|
|
554
|
-
context "by #{type} equality" do
|
555
|
-
it 'can apply filter object' do
|
556
|
-
data =
|
557
|
-
1.upto(10).map do |i|
|
558
|
-
{
|
559
|
-
'sys' => { 'id' => "k#{i}", 'contentType' => { 'sys' => { 'id' => 'test1' } } },
|
560
|
-
'fields' => { type.to_s => { 'en-US' => generator.call } }
|
561
|
-
}
|
562
|
-
end
|
563
|
-
|
564
|
-
desired_value = generator.call
|
565
|
-
desired = {
|
566
|
-
'sys' => { 'id' => "k#{rand}", 'contentType' => { 'sys' => { 'id' => 'test1' } } },
|
567
|
-
'fields' => { type.to_s => { 'en-US' => desired_value } }
|
568
|
-
}
|
569
|
-
|
570
|
-
data << desired
|
571
|
-
data.shuffle.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
572
|
-
|
573
|
-
# act
|
574
|
-
found = subject.find_by(content_type: 'test1', filter: { type.to_s => desired_value })
|
575
|
-
|
576
|
-
# assert
|
577
|
-
expect(found).to_not be_nil
|
578
|
-
expect(found).to eq(desired)
|
579
|
-
end
|
580
|
-
|
581
|
-
it 'filter object can find value in array' do
|
582
|
-
data =
|
583
|
-
1.upto(10).map do |i|
|
584
|
-
{
|
585
|
-
'sys' => {
|
586
|
-
'id' => "k#{i}",
|
587
|
-
'contentType' => { 'sys' => { 'id' => 'test1' } }
|
588
|
-
},
|
589
|
-
'fields' => { 'name' => { 'en-US' => [generator.call, generator.call] } }
|
590
|
-
}
|
591
|
-
end
|
592
|
-
|
593
|
-
desired_value = generator.call
|
594
|
-
desired = {
|
595
|
-
'sys' => { 'id' => "k#{rand}", 'contentType' => { 'sys' => { 'id' => 'test1' } } },
|
596
|
-
'fields' => { type.to_s => { 'en-US' => [generator.call, desired_value].shuffle } }
|
597
|
-
}
|
598
|
-
|
599
|
-
data << desired
|
600
|
-
data.shuffle.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
601
|
-
|
602
|
-
# act
|
603
|
-
found = subject.find_by(content_type: 'test1', filter: { type.to_s => { eq: desired_value } })
|
604
|
-
|
605
|
-
# assert
|
606
|
-
expect(found).to_not be_nil
|
607
|
-
expect(found).to eq(desired)
|
608
|
-
end
|
609
|
-
end
|
610
|
-
end
|
611
531
|
end
|
612
532
|
|
613
533
|
describe '#find_all' do
|
@@ -652,29 +572,6 @@ RSpec.shared_examples 'basic store' do
|
|
652
572
|
%w[k1 k5 k9]
|
653
573
|
)
|
654
574
|
end
|
655
|
-
|
656
|
-
it 'filter query eq can find value in array' do
|
657
|
-
content_types = %w[test1 test2 test3 test4]
|
658
|
-
data =
|
659
|
-
1.upto(10).map do |i|
|
660
|
-
{
|
661
|
-
'sys' => {
|
662
|
-
'id' => "k#{i}",
|
663
|
-
'contentType' => { 'sys' => { 'id' => content_types[i % content_types.length] } }
|
664
|
-
},
|
665
|
-
'fields' => { 'name' => { 'en-US' => ["test#{i}", "test_2_#{i}"] } }
|
666
|
-
}
|
667
|
-
end
|
668
|
-
data.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
669
|
-
|
670
|
-
# act
|
671
|
-
found = subject.find_all(content_type: 'test2')
|
672
|
-
.apply('name' => { eq: 'test_2_5' })
|
673
|
-
|
674
|
-
# assert
|
675
|
-
expect(found.count).to eq(1)
|
676
|
-
expect(found.first.dig('sys', 'id')).to eq('k5')
|
677
|
-
end
|
678
575
|
end
|
679
576
|
|
680
577
|
def make_link_to(id, link_type = 'Entry')
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_examples 'supports :eq operator' do
|
4
|
+
[
|
5
|
+
[String, proc { "test#{rand(1..10_000)}" }],
|
6
|
+
[Integer, proc { rand(-4_611_686_018_427_387_903..4_611_686_018_427_387_903) }],
|
7
|
+
[Float, proc { rand }]
|
8
|
+
].each do |(type, generator)|
|
9
|
+
context "with #{type} value" do
|
10
|
+
let(:desired_value) {
|
11
|
+
generator.call
|
12
|
+
}
|
13
|
+
|
14
|
+
let(:data) {
|
15
|
+
1.upto(3).map do |i|
|
16
|
+
{
|
17
|
+
'sys' => { 'id' => "k#{i}", 'contentType' => { 'sys' => { 'id' => 'test1' } } },
|
18
|
+
'fields' => { type.to_s => { 'en-US' => generator.call } }
|
19
|
+
}
|
20
|
+
end
|
21
|
+
}
|
22
|
+
|
23
|
+
let(:desired) {
|
24
|
+
{
|
25
|
+
'sys' => { 'id' => "k#{rand}", 'contentType' => { 'sys' => { 'id' => 'test1' } } },
|
26
|
+
'fields' => { type.to_s => { 'en-US' => desired_value } }
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
it 'find_by can apply filter object' do
|
31
|
+
[*data, desired].shuffle.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
32
|
+
|
33
|
+
# act
|
34
|
+
found = subject.find_by(content_type: 'test1', filter: { type.to_s => desired_value })
|
35
|
+
|
36
|
+
# assert
|
37
|
+
expect(found).to_not be_nil
|
38
|
+
expect(found).to eq(desired)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'find_by can find value in array' do
|
42
|
+
data =
|
43
|
+
1.upto(3).map do |i|
|
44
|
+
{
|
45
|
+
'sys' => {
|
46
|
+
'id' => "k#{i}",
|
47
|
+
'contentType' => { 'sys' => { 'id' => 'test1' } }
|
48
|
+
},
|
49
|
+
'fields' => { 'name' => { 'en-US' => [generator.call, generator.call] } }
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
desired_value = generator.call
|
54
|
+
desired = {
|
55
|
+
'sys' => { 'id' => "k#{rand}", 'contentType' => { 'sys' => { 'id' => 'test1' } } },
|
56
|
+
'fields' => { type.to_s => { 'en-US' => [generator.call, desired_value].shuffle } }
|
57
|
+
}
|
58
|
+
|
59
|
+
data << desired
|
60
|
+
data.shuffle.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
61
|
+
|
62
|
+
# act
|
63
|
+
found = subject.find_by(content_type: 'test1', filter: { type.to_s => { eq: desired_value } })
|
64
|
+
|
65
|
+
# assert
|
66
|
+
expect(found).to_not be_nil
|
67
|
+
expect(found).to eq(desired)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'find_all can apply operator' do
|
71
|
+
desired =
|
72
|
+
4.upto(5).map do |i|
|
73
|
+
{
|
74
|
+
'sys' => { 'id' => "k#{i}", 'contentType' => { 'sys' => { 'id' => 'test1' } } },
|
75
|
+
'fields' => { type.to_s => { 'en-US' => desired_value } }
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
[*data, *desired].shuffle.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
80
|
+
|
81
|
+
# act
|
82
|
+
found = subject.find_all(content_type: 'test1')
|
83
|
+
.eq(type.to_s, desired_value)
|
84
|
+
|
85
|
+
# assert
|
86
|
+
expect(found.count).to eq(2)
|
87
|
+
sorted = found.to_a.sort_by { |item| item.dig('sys', 'id') }
|
88
|
+
expect(sorted).to eq(desired)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_examples 'supports :in operator' do
|
4
|
+
it 'find_all with array on string field' do
|
5
|
+
ids = 1.upto(10).to_a
|
6
|
+
data =
|
7
|
+
ids.map do |i|
|
8
|
+
{
|
9
|
+
'sys' => {
|
10
|
+
'id' => "k#{i}",
|
11
|
+
'contentType' => { 'sys' => { 'id' => 'test' } }
|
12
|
+
},
|
13
|
+
'fields' => { 'name' => { 'en-US' => "test#{i}" } }
|
14
|
+
}
|
15
|
+
end
|
16
|
+
data.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
17
|
+
|
18
|
+
to_find = ids.shuffle.take(2)
|
19
|
+
|
20
|
+
# act
|
21
|
+
found = subject.find_all(content_type: 'test')
|
22
|
+
.in('name', to_find.map { |i| "test#{i}" })
|
23
|
+
|
24
|
+
expect(found.count).to eq(2)
|
25
|
+
expect(found.map { |item| item.dig('sys', 'id') }.sort).to eq(
|
26
|
+
to_find.map { |i| "k#{i}" }.sort
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'find_all with array on array field' do
|
31
|
+
ids = 1.upto(10).to_a
|
32
|
+
data =
|
33
|
+
ids.map do |i|
|
34
|
+
{
|
35
|
+
'sys' => {
|
36
|
+
'id' => "k#{i}",
|
37
|
+
'contentType' => { 'sys' => { 'id' => 'test' } }
|
38
|
+
},
|
39
|
+
'fields' => { 'name' => { 'en-US' => ["test#{i}", "test_2_#{i}"] } }
|
40
|
+
}
|
41
|
+
end
|
42
|
+
data.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
43
|
+
|
44
|
+
to_find1, to_find2 = ids.shuffle
|
45
|
+
|
46
|
+
# act
|
47
|
+
found = subject.find_all(content_type: 'test')
|
48
|
+
.in('name', ["test#{to_find1}", "test_2_#{to_find2}"])
|
49
|
+
|
50
|
+
expect(found.count).to eq(2)
|
51
|
+
expect(found.map { |item| item.dig('sys', 'id') }.sort).to eq(
|
52
|
+
["k#{to_find1}", "k#{to_find2}"].sort
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'find_all defaults to :in when given an array' do
|
57
|
+
ids = 1.upto(10).to_a
|
58
|
+
data =
|
59
|
+
ids.map do |i|
|
60
|
+
{
|
61
|
+
'sys' => {
|
62
|
+
'id' => "k#{i}",
|
63
|
+
'contentType' => { 'sys' => { 'id' => 'test' } }
|
64
|
+
},
|
65
|
+
'fields' => { 'name' => { 'en-US' => "test#{i}" } }
|
66
|
+
}
|
67
|
+
end
|
68
|
+
data.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
69
|
+
|
70
|
+
to_find = ids.shuffle.take(3)
|
71
|
+
|
72
|
+
# act
|
73
|
+
found = subject.find_all(content_type: 'test')
|
74
|
+
.apply('name' => to_find.map { |i| "test#{i}" })
|
75
|
+
|
76
|
+
expect(found.count).to eq(3)
|
77
|
+
expect(found.map { |item| item.dig('sys', 'id') }.sort).to eq(
|
78
|
+
to_find.map { |i| "k#{i}" }.sort
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'find_by with array on string field' do
|
83
|
+
ids = 1.upto(10).to_a
|
84
|
+
data =
|
85
|
+
ids.map do |i|
|
86
|
+
{
|
87
|
+
'sys' => {
|
88
|
+
'id' => "k#{i}",
|
89
|
+
'contentType' => { 'sys' => { 'id' => 'test' } }
|
90
|
+
},
|
91
|
+
'fields' => { 'name' => { 'en-US' => "test#{i}" } }
|
92
|
+
}
|
93
|
+
end
|
94
|
+
data.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
95
|
+
|
96
|
+
to_find = ids.sample
|
97
|
+
|
98
|
+
# act
|
99
|
+
found = subject.find_by(
|
100
|
+
content_type: 'test',
|
101
|
+
filter: { name: { in: ['asdf', "test#{to_find}"] } }
|
102
|
+
)
|
103
|
+
|
104
|
+
expect(found.dig('sys', 'id')).to eq("k#{to_find}")
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'find_by defaults to :in when given an array' do
|
108
|
+
ids = 1.upto(10).to_a
|
109
|
+
data =
|
110
|
+
ids.map do |i|
|
111
|
+
{
|
112
|
+
'sys' => {
|
113
|
+
'id' => "k#{i}",
|
114
|
+
'contentType' => { 'sys' => { 'id' => 'test' } }
|
115
|
+
},
|
116
|
+
'fields' => { 'name' => { 'en-US' => "test#{i}" } }
|
117
|
+
}
|
118
|
+
end
|
119
|
+
data.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
120
|
+
|
121
|
+
to_find = ids.sample
|
122
|
+
|
123
|
+
# act
|
124
|
+
found = subject.find_by(
|
125
|
+
content_type: 'test',
|
126
|
+
filter: { name: ['asdf', "test#{to_find}"] }
|
127
|
+
)
|
128
|
+
|
129
|
+
expect(found.dig('sys', 'id')).to eq("k#{to_find}")
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_examples 'supports :ne operator' do
|
4
|
+
[
|
5
|
+
[String, proc { "test#{rand(1..100_000)}" }],
|
6
|
+
[Integer, proc { rand(-4_611_686_018_427_387_903..4_611_686_018_427_387_903) }],
|
7
|
+
[Float, proc { rand }]
|
8
|
+
].each do |(type, generator)|
|
9
|
+
context "with #{type} value" do
|
10
|
+
let(:specified_value) {
|
11
|
+
generator.call
|
12
|
+
}
|
13
|
+
|
14
|
+
let(:desired) {
|
15
|
+
# desired entry doesn't have the specified_value
|
16
|
+
{
|
17
|
+
'sys' => { 'id' => "k#{rand}", 'contentType' => { 'sys' => { 'id' => 'test1' } } },
|
18
|
+
'fields' => { type.to_s => { 'en-US' => 1.upto(rand(2..5)).map { generator.call } } }
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
let(:data) {
|
23
|
+
1.upto(3).map do |i|
|
24
|
+
random_values = 1.upto(rand(2..5)).map { generator.call }
|
25
|
+
|
26
|
+
# remaining data does include the specified_value
|
27
|
+
{
|
28
|
+
'sys' => {
|
29
|
+
'id' => "k#{i}",
|
30
|
+
'contentType' => { 'sys' => { 'id' => 'test1' } }
|
31
|
+
},
|
32
|
+
'fields' => { type.to_s => { 'en-US' => [*random_values, specified_value].shuffle } }
|
33
|
+
}
|
34
|
+
end
|
35
|
+
}
|
36
|
+
|
37
|
+
it 'find_by can apply filter object' do
|
38
|
+
specified_value = generator.call
|
39
|
+
data = {
|
40
|
+
'sys' => { 'id' => "k#{rand}", 'contentType' => { 'sys' => { 'id' => 'test1' } } },
|
41
|
+
'fields' => { type.to_s => { 'en-US' => specified_value } }
|
42
|
+
}
|
43
|
+
|
44
|
+
subject.set(data.dig('sys', 'id'), data)
|
45
|
+
|
46
|
+
# act
|
47
|
+
found = subject.find_by(content_type: 'test1', filter: { type.to_s => { ne: specified_value } })
|
48
|
+
|
49
|
+
# assert
|
50
|
+
expect(found).to be_nil
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'find_by can find value in array' do
|
54
|
+
[*data, desired].shuffle.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
55
|
+
|
56
|
+
# act
|
57
|
+
found = subject.find_by(content_type: 'test1', filter: { type.to_s => { ne: specified_value } })
|
58
|
+
|
59
|
+
# assert
|
60
|
+
expect(found).to_not be_nil
|
61
|
+
expect(found).to eq(desired)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'find_all can apply operator' do
|
65
|
+
[*data, desired].shuffle.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
66
|
+
|
67
|
+
# act
|
68
|
+
found = subject.find_all(content_type: 'test1')
|
69
|
+
.ne(type.to_s, specified_value)
|
70
|
+
|
71
|
+
# assert
|
72
|
+
expect(found.count).to eq(1)
|
73
|
+
expect(found.first).to eq(desired)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_examples 'supports :nin operator' do
|
4
|
+
it 'find_all with array on string field' do
|
5
|
+
ids = 1.upto(10).to_a
|
6
|
+
data =
|
7
|
+
ids.map do |i|
|
8
|
+
{
|
9
|
+
'sys' => {
|
10
|
+
'id' => "k#{i}",
|
11
|
+
'contentType' => { 'sys' => { 'id' => 'test' } }
|
12
|
+
},
|
13
|
+
'fields' => { 'name' => { 'en-US' => "test#{i}" } }
|
14
|
+
}
|
15
|
+
end
|
16
|
+
data.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
17
|
+
|
18
|
+
to_exclude = ids.shuffle.take(2)
|
19
|
+
|
20
|
+
# act
|
21
|
+
found = subject.find_all(content_type: 'test')
|
22
|
+
.nin('name', to_exclude.map { |i| "test#{i}" })
|
23
|
+
|
24
|
+
expect(found.count).to eq(8)
|
25
|
+
expect(found.map { |item| item.dig('sys', 'id') }.sort).to eq(
|
26
|
+
(ids - to_exclude).map { |i| "k#{i}" }.sort
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'find_all with array on array field' do
|
31
|
+
ids = 1.upto(10).to_a
|
32
|
+
data =
|
33
|
+
ids.map do |i|
|
34
|
+
{
|
35
|
+
'sys' => {
|
36
|
+
'id' => "k#{i}",
|
37
|
+
'contentType' => { 'sys' => { 'id' => 'test' } }
|
38
|
+
},
|
39
|
+
'fields' => { 'name' => { 'en-US' => ["test#{i}", "test_2_#{i}"] } }
|
40
|
+
}
|
41
|
+
end
|
42
|
+
data.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
43
|
+
|
44
|
+
to_exclude1, to_exclude2 = ids.shuffle
|
45
|
+
|
46
|
+
# act
|
47
|
+
found = subject.find_all(content_type: 'test')
|
48
|
+
.nin('name', ["test#{to_exclude1}", "test_2_#{to_exclude2}"])
|
49
|
+
|
50
|
+
expect(found.count).to eq(8)
|
51
|
+
expect(found.map { |item| item.dig('sys', 'id') }.sort).to eq(
|
52
|
+
(ids - [to_exclude1, to_exclude2]).map { |i| "k#{i}" }.sort
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'find_by with array on string field' do
|
57
|
+
ids = 1.upto(2).to_a
|
58
|
+
data =
|
59
|
+
ids.map do |i|
|
60
|
+
{
|
61
|
+
'sys' => {
|
62
|
+
'id' => "k#{i}",
|
63
|
+
'contentType' => { 'sys' => { 'id' => 'test' } }
|
64
|
+
},
|
65
|
+
'fields' => { 'name' => { 'en-US' => "test#{i}" } }
|
66
|
+
}
|
67
|
+
end
|
68
|
+
data.each { |d| subject.set(d.dig('sys', 'id'), d) }
|
69
|
+
|
70
|
+
to_exclude, to_expect = ids.shuffle
|
71
|
+
|
72
|
+
# act
|
73
|
+
found = subject.find_by(
|
74
|
+
content_type: 'test',
|
75
|
+
filter: { name: { nin: ['asdf', "test#{to_exclude}"] } }
|
76
|
+
)
|
77
|
+
|
78
|
+
expect(found.dig('sys', 'id')).to eq("k#{to_expect}")
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './operators/eq'
|
4
|
+
require_relative './operators/ne'
|
5
|
+
require_relative './operators/in'
|
6
|
+
require_relative './operators/nin'
|
7
|
+
|
8
|
+
(WCC::Contentful::Store::Query::Interface::OPERATORS -
|
9
|
+
%i[eq ne in nin]).each do |op|
|
10
|
+
RSpec.shared_examples "supports :#{op} operator" do
|
11
|
+
it 'TODO'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
RSpec.shared_examples 'operators' do |feature_set|
|
16
|
+
supported_operators =
|
17
|
+
if feature_set.nil?
|
18
|
+
WCC::Contentful::Store::Query::Interface::OPERATORS
|
19
|
+
.each_with_object({}) { |k, h| h[k] = 'pending' }
|
20
|
+
elsif feature_set.is_a?(Array)
|
21
|
+
WCC::Contentful::Store::Query::Interface::OPERATORS
|
22
|
+
.each_with_object({}) { |k, h| h[k] = feature_set.include?(k.to_sym) }
|
23
|
+
elsif feature_s.is_a?(Hash)
|
24
|
+
feature_set
|
25
|
+
else
|
26
|
+
raise ArgumentError, 'Please provide a hash or array of operators to test'
|
27
|
+
end
|
28
|
+
|
29
|
+
supported_operators.each do |op, value|
|
30
|
+
next if value
|
31
|
+
|
32
|
+
it "does not support :#{op}" do
|
33
|
+
expect {
|
34
|
+
subject.find_all(content_type: 'test')
|
35
|
+
.apply('name' => { op => 'test' })
|
36
|
+
.to_a
|
37
|
+
}.to raise_error do |ex|
|
38
|
+
expect(ex.to_s).to match(/not supported/)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
supported_operators.each do |op, value|
|
44
|
+
next unless value
|
45
|
+
|
46
|
+
it_behaves_like "supports :#{op} operator" do
|
47
|
+
before { pending(":#{op} operator to be implemented") } if value == 'pending'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative './rspec_examples/basic_store'
|
4
|
+
require_relative './rspec_examples/operators'
|
4
5
|
require_relative './rspec_examples/nested_queries'
|
5
6
|
require_relative './rspec_examples/include_param'
|
6
7
|
|
@@ -41,6 +42,7 @@ RSpec.shared_examples 'contentful store' do |feature_set|
|
|
41
42
|
}.merge(feature_set&.symbolize_keys || {})
|
42
43
|
|
43
44
|
include_examples 'basic store'
|
45
|
+
include_examples 'operators', feature_set[:operators]
|
44
46
|
include_examples 'supports nested queries', feature_set[:nested_queries]
|
45
47
|
include_examples 'supports include param', feature_set[:include_param]
|
46
48
|
end
|
@@ -31,10 +31,6 @@ module WCC::Contentful::Test::Attributes
|
|
31
31
|
##
|
32
32
|
# Get a hash of default values for all attributes unique to the given Contentful model.
|
33
33
|
def defaults(const)
|
34
|
-
unless const < WCC::Contentful::Model
|
35
|
-
raise ArgumentError, "#{const} is not a subclass of WCC::Contentful::Model"
|
36
|
-
end
|
37
|
-
|
38
34
|
const.content_type_definition.fields.each_with_object({}) do |(name, f), h|
|
39
35
|
h[name.to_sym] = h[name.underscore.to_sym] = default_value(f)
|
40
36
|
end
|
@@ -7,8 +7,10 @@ module WCC::Contentful::Test::Double
|
|
7
7
|
# Builds a rspec double of the Contentful model for the given content_type.
|
8
8
|
# All attributes that are known to be required fields on the content type
|
9
9
|
# will return a default value based on the field type.
|
10
|
-
def contentful_double(
|
11
|
-
const
|
10
|
+
def contentful_double(const, **attrs)
|
11
|
+
unless const.respond_to?(:content_type_definition)
|
12
|
+
const = WCC::Contentful::Model.resolve_constant(const.to_s)
|
13
|
+
end
|
12
14
|
attrs.symbolize_keys!
|
13
15
|
|
14
16
|
bad_attrs = attrs.reject { |a| const.instance_methods.include?(a) }
|
@@ -7,8 +7,10 @@ module WCC::Contentful::Test::Factory
|
|
7
7
|
# Builds a in-memory instance of the Contentful model for the given content_type.
|
8
8
|
# All attributes that are known to be required fields on the content type
|
9
9
|
# will return a default value based on the field type.
|
10
|
-
def contentful_create(
|
11
|
-
const
|
10
|
+
def contentful_create(const, context = nil, **attrs)
|
11
|
+
unless const.respond_to?(:content_type_definition)
|
12
|
+
const = WCC::Contentful::Model.resolve_constant(const.to_s)
|
13
|
+
end
|
12
14
|
attrs = attrs.transform_keys { |a| a.to_s.camelize(:lower) }
|
13
15
|
|
14
16
|
id = attrs.delete('id')
|