contentful_lite 1.0.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +257 -0
- data/lib/contentful_lite/asset.rb +30 -0
- data/lib/contentful_lite/assets_array.rb +12 -0
- data/lib/contentful_lite/base_array.rb +29 -0
- data/lib/contentful_lite/client.rb +110 -0
- data/lib/contentful_lite/common_data.rb +95 -0
- data/lib/contentful_lite/deleted_entry.rb +10 -0
- data/lib/contentful_lite/entries_array.rb +62 -0
- data/lib/contentful_lite/entry.rb +52 -0
- data/lib/contentful_lite/entry_mapping.rb +23 -0
- data/lib/contentful_lite/link.rb +40 -0
- data/lib/contentful_lite/validations/entry.rb +68 -0
- data/lib/contentful_lite/validations/included_asset_validator.rb +14 -0
- data/lib/contentful_lite/validations/included_child_validator.rb +40 -0
- data/lib/contentful_lite/validations/included_entry_validator.rb +24 -0
- data/lib/contentful_lite/version.rb +3 -0
- data/lib/contentful_lite.rb +12 -0
- data/spec/asset_spec.rb +61 -0
- data/spec/assets_array_spec.rb +32 -0
- data/spec/base_array_spec.rb +25 -0
- data/spec/client_spec.rb +129 -0
- data/spec/common_data_spec.rb +111 -0
- data/spec/deleted_entry_spec.rb +30 -0
- data/spec/entries_array_spec.rb +102 -0
- data/spec/entry_mapping_spec.rb +20 -0
- data/spec/entry_spec.rb +84 -0
- data/spec/link_spec.rb +66 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/validations_spec.rb +366 -0
- metadata +186 -0
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ContentfulLite::EntriesArray do
|
4
|
+
let(:response) { JSON.parse(File.read('fixtures/entries/all.json')) }
|
5
|
+
let(:instance) { ContentfulLite::EntriesArray.new(response) }
|
6
|
+
|
7
|
+
describe 'should create an array of entries' do
|
8
|
+
it { expect(instance.first).to be_an ContentfulLite::Entry }
|
9
|
+
it { expect(instance.last).to be_an ContentfulLite::Entry }
|
10
|
+
it { expect(instance.sample).to be_an ContentfulLite::Entry }
|
11
|
+
|
12
|
+
it 'should solve the linked assets' do
|
13
|
+
expect(instance[4].fields['image']).to be_an ContentfulLite::Asset
|
14
|
+
expect(instance[4].fields['image'].url).to eq '//images.ctfassets.net/cfexampleapi/4hlteQAXS8iS0YCMU6QMWg/2a4d826144f014109364ccf5c891d2dd/jake.png'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should solve the nested mutually-related entries' do
|
18
|
+
expect(instance[5].fields['bestFriend']).to be_an ContentfulLite::Entry
|
19
|
+
expect(instance[5].fields['bestFriend'].fields['bestFriend']).to eq instance[5]
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should properly serialize the nested mutually-related entries' do
|
23
|
+
friend = instance[5].as_json['fields']['bestFriend']
|
24
|
+
expect(friend['sys']['type']).to eq('Entry')
|
25
|
+
expect(friend['sys']['id']).to eq('nyancat')
|
26
|
+
expect(friend['fields']['bestFriend']['sys']['type']).to eq('Link')
|
27
|
+
expect(friend['fields']['bestFriend']['sys']['id']).to eq('happycat')
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with an array of references' do
|
31
|
+
let(:response) { JSON.parse(File.read('fixtures/entries/all_with_reference_array.json')) }
|
32
|
+
|
33
|
+
it 'should solve the linked assets' do
|
34
|
+
expect(instance[4].fields['images'].first).to be_an ContentfulLite::Asset
|
35
|
+
expect(instance[4].fields['images'].first.url).to eq '//images.ctfassets.net/cfexampleapi/4hlteQAXS8iS0YCMU6QMWg/2a4d826144f014109364ccf5c891d2dd/jake.png'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should solve the nested mutually-related entries' do
|
39
|
+
expect(instance[5].fields['friends'].first).to be_an ContentfulLite::Entry
|
40
|
+
expect(instance[5].fields['friends'].first.fields['friends'].first).to eq instance[5]
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should properly serialize the nested mutually-related entries' do
|
44
|
+
friend = instance[5].as_json['fields']['friends'].first
|
45
|
+
expect(friend['sys']['type']).to eq('Entry')
|
46
|
+
expect(friend['sys']['id']).to eq('nyancat')
|
47
|
+
expect(friend['fields']['friends'].first['sys']['type']).to eq('Link')
|
48
|
+
expect(friend['fields']['friends'].first['sys']['id']).to eq('happycat')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'with multiple locales' do
|
53
|
+
let(:response) { JSON.parse(File.read('fixtures/entries/all_with_locales.json')) }
|
54
|
+
|
55
|
+
it { expect(instance[5].fields(locale: 'tlh')['name']).to eq("Quch vIghro'") }
|
56
|
+
|
57
|
+
it 'should solve the linked assets' do
|
58
|
+
expect(instance[4].fields['image']).to be_an ContentfulLite::Asset
|
59
|
+
expect(instance[4].fields['image'].url).to eq '//images.ctfassets.net/cfexampleapi/4hlteQAXS8iS0YCMU6QMWg/2a4d826144f014109364ccf5c891d2dd/jake.png'
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should solve the nested mutually-related entries' do
|
63
|
+
expect(instance[5].fields['bestFriend']).to be_an ContentfulLite::Entry
|
64
|
+
expect(instance[5].fields['bestFriend'].fields['bestFriend']).to eq instance[5]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when include nesting is not enough' do
|
69
|
+
let(:response) { JSON.parse(File.read('fixtures/entries/all_without_includes.json')) }
|
70
|
+
|
71
|
+
it { expect(instance.first).to be_an ContentfulLite::Entry }
|
72
|
+
it { expect(instance.last).to be_an ContentfulLite::Entry }
|
73
|
+
it { expect(instance.sample).to be_an ContentfulLite::Entry }
|
74
|
+
|
75
|
+
it 'should create links for the assets' do
|
76
|
+
expect(instance[4].fields['image']).to be_an ContentfulLite::Link
|
77
|
+
expect(instance[4].fields['image'].type).to eq :asset
|
78
|
+
expect(instance[4].fields['image'].id).to eq 'jake'
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should solve the nested mutually-related entries' do
|
82
|
+
expect(instance[5].fields['bestFriend']).to be_an ContentfulLite::Link
|
83
|
+
expect(instance[5].fields['bestFriend'].type).to eq :entry
|
84
|
+
expect(instance[5].fields['bestFriend'].id).to eq 'nyancat'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe 'serializing' do
|
89
|
+
subject { Marshal.load(Marshal.dump(instance)) }
|
90
|
+
|
91
|
+
it { expect(subject.first.id).to eq(instance.first.id) }
|
92
|
+
it { expect(subject.first.fields).to eq(instance.first.fields) }
|
93
|
+
it { expect(subject.last.id).to eq(instance.last.id) }
|
94
|
+
it { expect(subject.last.fields).to eq(instance.last.fields) }
|
95
|
+
|
96
|
+
it 'should solve the nested mutually-related entries' do
|
97
|
+
expect(subject[5].fields['bestFriend']).to be_an ContentfulLite::Entry
|
98
|
+
expect(subject[5].fields['bestFriend'].fields['bestFriend']).to eq subject[5]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ContentfulLite::EntryMapping do
|
4
|
+
let(:base_class) { Class.new.include(described_class) }
|
5
|
+
let!(:inherited_class) { Class.new(base_class) { content_type_id 'inherited_type' } }
|
6
|
+
|
7
|
+
describe '#get_class' do
|
8
|
+
subject { base_class.get_class(content_type) }
|
9
|
+
|
10
|
+
context 'for an existing content_type_id' do
|
11
|
+
let(:content_type) { 'inherited_type' }
|
12
|
+
it { is_expected.to eq(inherited_class) }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'for an invalid content_type_id' do
|
16
|
+
let(:content_type) { 'invalid_type' }
|
17
|
+
it { is_expected.to eq(base_class) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/spec/entry_spec.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ContentfulLite::Entry do
|
4
|
+
let(:entry_hash) { JSON.parse(File.read('fixtures/entries/nyancat.json')) }
|
5
|
+
let(:instance) { ContentfulLite::Entry.new(entry_hash) }
|
6
|
+
|
7
|
+
describe '#attributes' do
|
8
|
+
it { expect(instance.content_type_id).to eq 'cat' }
|
9
|
+
it { expect(instance.fields).to be_a Hash }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#contentful_link' do
|
13
|
+
subject { instance.contentful_link }
|
14
|
+
|
15
|
+
it { is_expected.to eq 'https://app.contentful.com/spaces/cfexampleapi/entries/nyancat' }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'Class methods' do
|
19
|
+
describe '#field_reader' do
|
20
|
+
let(:entry_class) do
|
21
|
+
Class.new(ContentfulLite::Entry) do
|
22
|
+
field_reader :name, localizable: true
|
23
|
+
field_reader :color, :bestFriend, :friends
|
24
|
+
field_reader :spayed, default: true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
subject { entry_class.new(entry_hash) }
|
28
|
+
|
29
|
+
it { expect(subject.color).to eq 'rainbow' }
|
30
|
+
it { expect(subject.bestFriend).to be_a ContentfulLite::Link }
|
31
|
+
it { expect(subject.bestFriend.id).to eq 'happycat' }
|
32
|
+
it { expect(subject.spayed).to eq true }
|
33
|
+
|
34
|
+
context 'when the spayed field is nil' do
|
35
|
+
before { entry_hash['fields']['spayed'] = nil }
|
36
|
+
|
37
|
+
it 'falls back to the provided default' do
|
38
|
+
expect(subject.spayed).to eq true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when the spayed field is set to false' do
|
43
|
+
before { entry_hash['fields']['spayed'] = false }
|
44
|
+
|
45
|
+
it { expect(subject.spayed).to eq false }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'with multiple locales' do
|
49
|
+
let(:entry_hash) { JSON.parse(File.read('fixtures/entries/nyancat_with_locales.json')) }
|
50
|
+
|
51
|
+
it { expect(subject.name).to eq 'Nyan Cat' }
|
52
|
+
it { expect(subject.color).to eq 'rainbow' }
|
53
|
+
it { expect(subject.color(locale: 'tlh')).to eq 'rainbow' }
|
54
|
+
it { expect(subject.with_locale('tlh') { subject.color }).to eq 'rainbow' }
|
55
|
+
it { expect(subject.bestFriend).to be_a ContentfulLite::Link }
|
56
|
+
it { expect(subject.bestFriend.id).to eq 'happycat' }
|
57
|
+
it { expect(subject.name(locale: 'tlh')).to eq 'Nyan vIghro\'' }
|
58
|
+
it { expect(subject.with_locale('tlh') { subject.name }).to eq 'Nyan vIghro\'' }
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with an array of references' do
|
62
|
+
let(:entry_hash) { JSON.parse(File.read('fixtures/entries/reference_array.json')) }
|
63
|
+
|
64
|
+
it { expect(subject.friends.first).to be_a ContentfulLite::Link }
|
65
|
+
it { expect(subject.friends.last).to be_a ContentfulLite::Link }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'serializing' do
|
71
|
+
subject { Marshal.load(Marshal.dump(instance)) }
|
72
|
+
|
73
|
+
it { expect(subject.id).to eq(instance.id) }
|
74
|
+
it { expect(subject.created_at).to eq(instance.created_at) }
|
75
|
+
it { expect(subject.updated_at).to eq(instance.updated_at) }
|
76
|
+
it { expect(subject.retrieved_at).to eq(instance.retrieved_at) }
|
77
|
+
it { expect(subject.locale).to eq(instance.locale) }
|
78
|
+
it { expect(subject.revision).to eq(instance.revision) }
|
79
|
+
it { expect(subject.space_id).to eq(instance.space_id) }
|
80
|
+
it { expect(subject.environment_id).to eq(instance.environment_id) }
|
81
|
+
it { expect(subject.content_type_id).to eq(instance.content_type_id) }
|
82
|
+
it { expect(subject.fields).to eq(instance.fields) }
|
83
|
+
end
|
84
|
+
end
|
data/spec/link_spec.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ContentfulLite::Link do
|
4
|
+
let(:entry_hash) { JSON.parse(File.read('fixtures/entries/nyancat.json')) }
|
5
|
+
subject { ContentfulLite::Link.new(entry_hash['fields']['bestFriend']) }
|
6
|
+
|
7
|
+
describe '#attributes' do
|
8
|
+
it { expect(subject.type).to eq :entry }
|
9
|
+
it { expect(subject.id).to eq 'happycat' }
|
10
|
+
|
11
|
+
context 'when converting from an Entry' do
|
12
|
+
let(:entry) { ContentfulLite::Entry.new(entry_hash) }
|
13
|
+
subject { ContentfulLite::Link.new(entry) }
|
14
|
+
|
15
|
+
it { expect(subject.type).to eq :entry }
|
16
|
+
it { expect(subject.id).to eq 'nyancat' }
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when converting from an Asset' do
|
20
|
+
let(:asset_hash) { JSON.parse(File.read('fixtures/assets/nyancat.json')) }
|
21
|
+
let(:asset) { ContentfulLite::Asset.new(asset_hash) }
|
22
|
+
subject { ContentfulLite::Link.new(asset) }
|
23
|
+
|
24
|
+
it { expect(subject.type).to eq :asset }
|
25
|
+
it { expect(subject.id).to eq 'nyancat' }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#==' do
|
30
|
+
let(:other_id) { 'happycat' }
|
31
|
+
let(:other_type) { 'Entry' }
|
32
|
+
let(:comparison) { ContentfulLite::Link.new( 'sys' => { 'linkType' => other_type, 'id' => other_id } ) }
|
33
|
+
|
34
|
+
it { is_expected.to eq comparison }
|
35
|
+
|
36
|
+
context 'when the id is different' do
|
37
|
+
let(:other_id) { 'other' }
|
38
|
+
|
39
|
+
it { is_expected.not_to eq comparison }
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when the type is different' do
|
43
|
+
let(:other_id) { 'asset' }
|
44
|
+
|
45
|
+
it { is_expected.not_to eq comparison }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'when the class is different' do
|
49
|
+
let(:comparison) { OpenStruct.new(id: other_id, type: :entry) }
|
50
|
+
|
51
|
+
it { is_expected.not_to eq comparison }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#as_json' do
|
56
|
+
it { expect(subject.as_json).to eq(entry_hash['fields']['bestFriend']) }
|
57
|
+
|
58
|
+
context 'when rails is passing some other parameters as hash' do
|
59
|
+
let(:hash) { { template: "something", status: 200 } }
|
60
|
+
|
61
|
+
it 'should not throw errors' do
|
62
|
+
expect(subject.as_json(hash)).to eq(entry_hash['fields']['bestFriend'])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
if ENV['COVERAGE']
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'webmock/rspec'
|
7
|
+
require 'vcr'
|
8
|
+
require 'contentful_lite'
|
9
|
+
|
10
|
+
VCR.configure do |config|
|
11
|
+
config.cassette_library_dir = 'fixtures/vcr_cassettes'
|
12
|
+
config.hook_into :webmock
|
13
|
+
|
14
|
+
config.default_cassette_options = { record: :once }
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec.configure do |config|
|
18
|
+
# Enable flags like --only-failures and --next-failure
|
19
|
+
config.example_status_persistence_file_path = '.rspec_status'
|
20
|
+
|
21
|
+
# Disable RSpec exposing methods globally on `Module` and `main`
|
22
|
+
config.disable_monkey_patching!
|
23
|
+
|
24
|
+
config.expect_with :rspec do |c|
|
25
|
+
c.syntax = :expect
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,366 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ContentfulLite::Validations::Entry do
|
4
|
+
def create_validable_model(validation_method, options)
|
5
|
+
klass = Class.new do
|
6
|
+
include ContentfulLite::Validations::Entry
|
7
|
+
attr_reader :fake_field
|
8
|
+
attr_accessor :locale
|
9
|
+
send(validation_method, :fake_field, options)
|
10
|
+
|
11
|
+
def initialize(value)
|
12
|
+
@fake_field = value
|
13
|
+
@locale = :en
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_locale(locale)
|
17
|
+
@locale = locale unless locale.nil?
|
18
|
+
yield
|
19
|
+
ensure
|
20
|
+
@locale = :en
|
21
|
+
end
|
22
|
+
end
|
23
|
+
allow(klass).to receive(:model_name).and_return ActiveModel::Name.new(klass, nil, 'FakeClasss')
|
24
|
+
allow(klass).to receive(:human_attribute_name).and_return 'fake_field'
|
25
|
+
klass
|
26
|
+
end
|
27
|
+
|
28
|
+
shared_context 'multiple locales support' do
|
29
|
+
before do # Mock Entry localization, as it is part of the entry class and not the validations module
|
30
|
+
allow(fake_model).to receive(:locales).and_return(%i[en es])
|
31
|
+
allow(fake_model).to receive(:fake_field) { value[fake_model.locale] }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:model_class) { create_validable_model(:validates_presence_of, {}) }
|
36
|
+
let(:fake_model) { model_class.new(value) }
|
37
|
+
|
38
|
+
describe '#valid?' do
|
39
|
+
include_context 'multiple locales support'
|
40
|
+
let(:value) { { en: 'valid', es: 'valid' } }
|
41
|
+
subject { fake_model.valid?(locale: :es) }
|
42
|
+
|
43
|
+
it { is_expected.to be_truthy }
|
44
|
+
|
45
|
+
context 'when the other locale has invalid content' do
|
46
|
+
let(:value) { { en: nil, es: 'valid' } }
|
47
|
+
it { is_expected.to be_truthy }
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when that locale has invalid content' do
|
51
|
+
let(:value) { { en: 'valid', es: nil } }
|
52
|
+
it { is_expected.to be_falsey }
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'when both locales have invalid content' do
|
56
|
+
let(:value) { { en: nil, es: nil } }
|
57
|
+
it { is_expected.to be_falsey }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#valid_for_all_locales?' do
|
62
|
+
include_context 'multiple locales support'
|
63
|
+
let(:value) { { en: 'valid', es: 'valid' } }
|
64
|
+
subject { fake_model.valid_for_all_locales? }
|
65
|
+
|
66
|
+
it { is_expected.to be_truthy }
|
67
|
+
|
68
|
+
context 'when first locale has invalid content' do
|
69
|
+
let(:value) { { en: nil, es: 'valid' } }
|
70
|
+
it { is_expected.to be_falsey }
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'when second locale has invalid content' do
|
74
|
+
let(:value) { { en: 'valid', es: nil } }
|
75
|
+
it { is_expected.to be_falsey }
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when both locales have invalid content' do
|
79
|
+
let(:value) { { en: nil, es: nil } }
|
80
|
+
it { is_expected.to be_falsey }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#errors' do
|
85
|
+
include_context 'multiple locales support'
|
86
|
+
let(:value) { { en: 'valid', es: 'valid' } }
|
87
|
+
subject(:en) { fake_model.tap(&:valid_for_all_locales?).errors(locale: :en)[:fake_field] }
|
88
|
+
subject(:es) { fake_model.tap(&:valid_for_all_locales?).errors(locale: :es)[:fake_field] }
|
89
|
+
|
90
|
+
it { expect(en).to be_empty }
|
91
|
+
it { expect(es).to be_empty }
|
92
|
+
|
93
|
+
context 'when first locale has invalid content' do
|
94
|
+
let(:value) { { en: nil, es: 'valid' } }
|
95
|
+
it { expect(en).to eq ["can't be blank"] }
|
96
|
+
it { expect(es).to be_empty }
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'when second locale has invalid content' do
|
100
|
+
let(:value) { { en: 'valid', es: nil } }
|
101
|
+
|
102
|
+
it { expect(en).to be_empty }
|
103
|
+
it { expect(es).to eq ["can't be blank"] }
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'when both locales have invalid content' do
|
107
|
+
let(:value) { { en: nil, es: nil } }
|
108
|
+
|
109
|
+
it { expect(en).to eq ["can't be blank"] }
|
110
|
+
it { expect(es).to eq ["can't be blank"] }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe '.validates_included_asset' do
|
115
|
+
subject { fake_model.tap(&:valid?).errors[:fake_field] }
|
116
|
+
|
117
|
+
let(:asset) { ContentfulLite::Asset.new(JSON.parse(File.read('fixtures/assets/nyancat.json'))) }
|
118
|
+
let(:model_class) do
|
119
|
+
create_validable_model(:validates_included_asset, options)
|
120
|
+
end
|
121
|
+
let(:value) { nil }
|
122
|
+
let(:options) { {} }
|
123
|
+
|
124
|
+
describe 'allow_blank' do
|
125
|
+
context 'when value is nil and blank is allowed' do
|
126
|
+
let(:options) { { allow_blank: true } }
|
127
|
+
|
128
|
+
it { is_expected.to be_empty }
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'when value is nil and blank is not allowed' do
|
132
|
+
let(:options) { { allow_blank: false } }
|
133
|
+
|
134
|
+
it { is_expected.to eq ['value is blank'] }
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'when value is [] and blank is allowed' do
|
138
|
+
let(:options) { { allow_blank: true } }
|
139
|
+
let(:value) { [] }
|
140
|
+
|
141
|
+
it { is_expected.to be_empty }
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'when value is [] and blank is not allowed' do
|
145
|
+
let(:options) { { allow_blank: false } }
|
146
|
+
let(:value) { [] }
|
147
|
+
|
148
|
+
it { is_expected.to eq ['value is blank'] }
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'when value exists and blank is not allowed' do
|
152
|
+
let(:value) { asset }
|
153
|
+
|
154
|
+
it { is_expected.to be_empty }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe 'array' do
|
159
|
+
context 'when value is not an array as expected' do
|
160
|
+
let(:value) { asset }
|
161
|
+
it { is_expected.to be_empty }
|
162
|
+
end
|
163
|
+
|
164
|
+
context 'when value is an array as expected' do
|
165
|
+
let(:value) { [asset] }
|
166
|
+
let(:options) { { array: true } }
|
167
|
+
it { is_expected.to be_empty }
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'when value is not an asset or array' do
|
171
|
+
let(:value) { Object.new }
|
172
|
+
it { is_expected.to eq ['value is not a published asset'] }
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'when value is an array with other objects' do
|
176
|
+
let(:value) { [asset, Object.new] }
|
177
|
+
let(:options) { { array: true } }
|
178
|
+
it { is_expected.to eq ['value[1] is not a published asset'] }
|
179
|
+
end
|
180
|
+
|
181
|
+
context 'when expects and array and has single value' do
|
182
|
+
let(:value) { asset }
|
183
|
+
let(:options) { { array: true } }
|
184
|
+
it { is_expected.to eq ['value is not an array'] }
|
185
|
+
end
|
186
|
+
|
187
|
+
context 'when expects a single value and has an array' do
|
188
|
+
let(:value) { [asset] }
|
189
|
+
it { is_expected.to eq ['value is not a published asset'] }
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe 'type' do
|
194
|
+
context 'when value is an image as expected' do
|
195
|
+
let(:options) { { type: :image } }
|
196
|
+
let(:value) { asset }
|
197
|
+
it { is_expected.to be_empty }
|
198
|
+
end
|
199
|
+
|
200
|
+
context 'when value is an image and expects a video' do
|
201
|
+
let(:options) { { type: :video } }
|
202
|
+
let(:value) { asset }
|
203
|
+
it { is_expected.to eq ['value has an invalid asset type. Expecting video'] }
|
204
|
+
end
|
205
|
+
|
206
|
+
context 'when values array has an image and expects only videos' do
|
207
|
+
let(:options) { { type: :video, array: true } }
|
208
|
+
let(:value) { [asset] }
|
209
|
+
it { is_expected.to eq ['value[0] has an invalid asset type. Expecting video'] }
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe '.validates_included_entry' do
|
215
|
+
subject { fake_model.tap(&:valid?).errors[:fake_field] }
|
216
|
+
|
217
|
+
let(:entry) { ContentfulLite::Entry.new(JSON.parse(File.read('fixtures/entries/nyancat.json'))) }
|
218
|
+
let(:model_class) do
|
219
|
+
create_validable_model(:validates_included_entry, options)
|
220
|
+
end
|
221
|
+
let(:value) { nil }
|
222
|
+
let(:options) { {} }
|
223
|
+
|
224
|
+
describe 'allow_blank' do
|
225
|
+
context 'when value is nil and blank is allowed' do
|
226
|
+
let(:options) { { allow_blank: true } }
|
227
|
+
|
228
|
+
it { is_expected.to be_empty }
|
229
|
+
end
|
230
|
+
|
231
|
+
context 'when value is nil and blank is not allowed' do
|
232
|
+
let(:options) { { allow_blank: false } }
|
233
|
+
|
234
|
+
it { is_expected.to eq ['value is blank'] }
|
235
|
+
end
|
236
|
+
|
237
|
+
context 'when value is [] and blank is allowed' do
|
238
|
+
let(:options) { { allow_blank: true } }
|
239
|
+
let(:value) { [] }
|
240
|
+
|
241
|
+
it { is_expected.to be_empty }
|
242
|
+
end
|
243
|
+
|
244
|
+
context 'when value is [] and blank is not allowed' do
|
245
|
+
let(:options) { { allow_blank: false } }
|
246
|
+
let(:value) { [] }
|
247
|
+
|
248
|
+
it { is_expected.to eq ['value is blank'] }
|
249
|
+
end
|
250
|
+
|
251
|
+
context 'when value exists and blank is not allowed' do
|
252
|
+
let(:value) { entry }
|
253
|
+
|
254
|
+
it { is_expected.to be_empty }
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
describe 'array' do
|
259
|
+
context 'when value is not an array as expected' do
|
260
|
+
let(:value) { entry }
|
261
|
+
it { is_expected.to be_empty }
|
262
|
+
end
|
263
|
+
|
264
|
+
context 'when value is an array as expected' do
|
265
|
+
let(:value) { [entry] }
|
266
|
+
let(:options) { { array: true } }
|
267
|
+
it { is_expected.to be_empty }
|
268
|
+
end
|
269
|
+
|
270
|
+
context 'when value is not an entry or array' do
|
271
|
+
let(:value) { Object.new }
|
272
|
+
it { is_expected.to eq ['value is not a published entry'] }
|
273
|
+
end
|
274
|
+
|
275
|
+
context 'when value is an array with other objects' do
|
276
|
+
let(:value) { [entry, Object.new] }
|
277
|
+
let(:options) { { array: true } }
|
278
|
+
it { is_expected.to eq ['value[1] is not a published entry'] }
|
279
|
+
end
|
280
|
+
|
281
|
+
context 'when expects and array and has single value' do
|
282
|
+
let(:value) { entry }
|
283
|
+
let(:options) { { array: true } }
|
284
|
+
it { is_expected.to eq ['value is not an array'] }
|
285
|
+
end
|
286
|
+
|
287
|
+
context 'when expects a single value and has an array' do
|
288
|
+
let(:value) { [entry] }
|
289
|
+
it { is_expected.to eq ['value is not a published entry'] }
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
describe 'invalid child' do
|
294
|
+
before { expect(entry).to receive(:valid?).and_return false }
|
295
|
+
|
296
|
+
context 'when the entry is invalid' do
|
297
|
+
let(:value) { entry }
|
298
|
+
|
299
|
+
it { is_expected.to eq ['value has invalid child entry nyancat'] }
|
300
|
+
end
|
301
|
+
|
302
|
+
context 'when is array and one of the entries is invalid' do
|
303
|
+
let(:value) { [entry] }
|
304
|
+
let(:options) { { array: true } }
|
305
|
+
|
306
|
+
it { is_expected.to eq ['value has invalid child entry nyancat'] }
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
context 'child is invalid only for a different locale' do
|
311
|
+
before do
|
312
|
+
allow(entry).to receive(:valid?).and_return true
|
313
|
+
allow(entry).to receive(:valid?).with(locale: :es).and_return false
|
314
|
+
end
|
315
|
+
let(:value) { entry }
|
316
|
+
it { is_expected.to be_empty }
|
317
|
+
|
318
|
+
context 'when calling validation and checking errors for that locale' do
|
319
|
+
subject { fake_model.tap{ |_| fake_model.valid?(locale: :es) }.errors(locale: :es)[:fake_field] }
|
320
|
+
it { is_expected.to eq ['value has invalid child entry nyancat'] }
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
context 'child is invalid only for the current locale' do
|
325
|
+
before do
|
326
|
+
allow(entry).to receive(:valid?).and_return true
|
327
|
+
allow(entry).to receive(:valid?).with(locale: :en).and_return false
|
328
|
+
end
|
329
|
+
let(:value) { entry }
|
330
|
+
it { is_expected.to eq ['value has invalid child entry nyancat'] }
|
331
|
+
end
|
332
|
+
|
333
|
+
describe 'allowed_models' do
|
334
|
+
let(:cat_entry) { cat_class.new(JSON.parse(File.read('fixtures/entries/nyancat.json'))) }
|
335
|
+
let(:cat_class) { Class.new(ContentfulLite::Entry) }
|
336
|
+
|
337
|
+
context 'when the entry is an allowed_model' do
|
338
|
+
let(:value) { cat_entry }
|
339
|
+
let(:options) { { allowed_models: [cat_class] } }
|
340
|
+
|
341
|
+
it { is_expected.to be_empty }
|
342
|
+
end
|
343
|
+
|
344
|
+
context 'when the entry is not an allowed_model' do
|
345
|
+
let(:value) { entry }
|
346
|
+
let(:options) { { allowed_models: [cat_class] } }
|
347
|
+
|
348
|
+
it { is_expected.to eq ["value has an invalid entry model. Expecting #{options[:allowed_models]}"] }
|
349
|
+
end
|
350
|
+
|
351
|
+
context 'when is array and all entries are allowed_models' do
|
352
|
+
let(:value) { [cat_entry] }
|
353
|
+
let(:options) { { allowed_models: [cat_class], array: true } }
|
354
|
+
|
355
|
+
it { is_expected.to be_empty }
|
356
|
+
end
|
357
|
+
|
358
|
+
context 'when is array and one entry is not an allowed_model' do
|
359
|
+
let(:value) { [cat_entry, entry] }
|
360
|
+
let(:options) { { allowed_models: [cat_class], array: true } }
|
361
|
+
|
362
|
+
it { is_expected.to eq ["value[1] has an invalid entry model. Expecting #{options[:allowed_models]}"] }
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|