wcc-contentful 1.0.6 → 1.1.1

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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +174 -9
  3. data/app/jobs/wcc/contentful/webhook_enable_job.rb +7 -7
  4. data/lib/wcc/contentful/instrumentation.rb +20 -2
  5. data/lib/wcc/contentful/link_visitor.rb +26 -30
  6. data/lib/wcc/contentful/middleware/store.rb +2 -1
  7. data/lib/wcc/contentful/model.rb +5 -122
  8. data/lib/wcc/contentful/model_api.rb +182 -0
  9. data/lib/wcc/contentful/model_builder.rb +10 -4
  10. data/lib/wcc/contentful/model_methods.rb +8 -10
  11. data/lib/wcc/contentful/model_singleton_methods.rb +6 -6
  12. data/lib/wcc/contentful/rspec.rb +7 -5
  13. data/lib/wcc/contentful/services.rb +59 -61
  14. data/lib/wcc/contentful/store/cdn_adapter.rb +7 -1
  15. data/lib/wcc/contentful/store/factory.rb +2 -6
  16. data/lib/wcc/contentful/store/memory_store.rb +47 -13
  17. data/lib/wcc/contentful/store/query.rb +22 -2
  18. data/lib/wcc/contentful/store/rspec_examples/basic_store.rb +0 -103
  19. data/lib/wcc/contentful/store/rspec_examples/operators/eq.rb +92 -0
  20. data/lib/wcc/contentful/store/rspec_examples/operators/in.rb +131 -0
  21. data/lib/wcc/contentful/store/rspec_examples/operators/ne.rb +77 -0
  22. data/lib/wcc/contentful/store/rspec_examples/operators/nin.rb +80 -0
  23. data/lib/wcc/contentful/store/rspec_examples/operators.rb +50 -0
  24. data/lib/wcc/contentful/store/rspec_examples.rb +2 -0
  25. data/lib/wcc/contentful/sync_engine.rb +0 -1
  26. data/lib/wcc/contentful/test/attributes.rb +0 -4
  27. data/lib/wcc/contentful/test/double.rb +4 -2
  28. data/lib/wcc/contentful/test/factory.rb +4 -2
  29. data/lib/wcc/contentful/version.rb +1 -1
  30. data/lib/wcc/contentful.rb +14 -8
  31. data/wcc-contentful.gemspec +0 -5
  32. 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, :Asset,
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: :eq, expected: v }
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
@@ -49,7 +49,6 @@ module WCC::Contentful
49
49
  end
50
50
 
51
51
  @store = store
52
- @state = read_state if should_sync?
53
52
  end
54
53
  if state
55
54
  @state = token_wrapper_factory(state)
@@ -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(content_type, **attrs)
11
- const = WCC::Contentful::Model.resolve_constant(content_type)
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(content_type, context = nil, **attrs)
11
- const = WCC::Contentful::Model.resolve_constant(content_type.to_s)
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')
@@ -2,6 +2,6 @@
2
2
 
3
3
  module WCC
4
4
  module Contentful
5
- VERSION = '1.0.6'
5
+ VERSION = '1.1.1'
6
6
  end
7
7
  end