contentful_lite 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,52 @@
1
+ module ContentfulLite
2
+ class Entry
3
+ include CommonData
4
+ include EntryMapping
5
+ include Validations::Entry
6
+
7
+ # The id for the content type of this entry
8
+ attr_reader :content_type_id
9
+
10
+ # @param raw [Hash] raw response from Contentful API
11
+ # @api private
12
+ def initialize(raw)
13
+ super(raw)
14
+ @content_type_id = raw['sys']['contentType']['sys']['id']
15
+ @localized_fields.values.each do |fields|
16
+ fields.transform_values! { |value| build_link(value) }
17
+ end
18
+ end
19
+
20
+ # Gets the URL to view/edit the entry on Contentful webapp
21
+ # @return [String]
22
+ def contentful_link
23
+ "https://app.contentful.com/spaces/#{space_id}/entries/#{id}"
24
+ end
25
+
26
+ # Defines a field existing on the content type. This macro registers the
27
+ # accessor for that field
28
+ # @param attrs [Array<Symbol,String>] The field names
29
+ # @param default [Object, nil] The default value to return if field is not present on API response
30
+ # @param localizable [Boolean] If the field is marked as localizable
31
+ # @example Defines two string localizable localized fields
32
+ # field_reader :first_name, :last_name, localizable: true
33
+ # @see https://github.com/JuulLabs-OSS/contentful_lite#creating-your-model-classes-with-macros
34
+ def self.field_reader(*attrs, default: nil, localizable: false)
35
+ attrs.each do |k|
36
+ define_method(k) do |locale: nil|
37
+ field = fields(locale: localizable ? locale : default_locale)[k.to_s]
38
+ field.nil? ? default : field
39
+ end
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def build_link(value)
46
+ return value.map!{ |element| build_link(element) } if value.is_a?(Array)
47
+ return value unless value.is_a?(Hash) && value.fetch('sys', {}).fetch('type', '') == 'Link'
48
+
49
+ ContentfulLite::Link.new(value)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,23 @@
1
+ require 'active_support/concern'
2
+
3
+ module ContentfulLite
4
+ # @api private
5
+ module EntryMapping
6
+ extend ActiveSupport::Concern
7
+
8
+ included do |base_klass|
9
+ base_klass.define_singleton_method(:content_type_id) do |name|
10
+ klass = self
11
+ base_klass.class_eval do
12
+ @mappings ||= {}
13
+ @mappings[name] = klass
14
+ end
15
+ end
16
+
17
+ base_klass.define_singleton_method(:get_class) do |content_type_id|
18
+ @mappings ||= {}
19
+ @mappings[content_type_id] || base_klass
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ module ContentfulLite
2
+ # A link to any type of contentful entity
3
+ class Link
4
+ # The unique id of the linked entity
5
+ attr_reader :id
6
+ # The type of the linked entity
7
+ attr_reader :type
8
+
9
+ # @param input [ContentfulLite::CommonData, Hash] data to build the instance
10
+ # @api private
11
+ def initialize(input)
12
+ if input.is_a?(ContentfulLite::CommonData)
13
+ @id = input.id
14
+ @type = input.sys['type'].downcase.to_sym
15
+ else
16
+ @type = input['sys']['linkType'].downcase.to_sym
17
+ @id = input['sys']['id']
18
+ end
19
+ end
20
+
21
+ # Equality comparison
22
+ # @param other [Object] the object to compare
23
+ # @return [Boolean] true if other is ContentfulLite::Link with same id and type
24
+ def ==(other)
25
+ self.class == other.class && type == other.type && id == other.id
26
+ end
27
+
28
+ # Provided for compatibility with Rails JSON serializer
29
+ # @return [Hash] a Hash representation of the link, to be formated as JSON
30
+ def as_json(**)
31
+ {
32
+ 'sys' => {
33
+ 'type' => "Link",
34
+ 'linkType' => type.to_s.capitalize,
35
+ 'id' => id
36
+ }
37
+ }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,68 @@
1
+ require 'active_support/concern'
2
+ require 'active_model'
3
+ require 'contentful_lite/validations/included_child_validator'
4
+ require 'contentful_lite/validations/included_asset_validator'
5
+ require 'contentful_lite/validations/included_entry_validator'
6
+
7
+ module ContentfulLite
8
+ module Validations
9
+ module Entry
10
+ extend ActiveSupport::Concern
11
+
12
+ included do |base_class|
13
+ base_class.include(ActiveModel::Validations)
14
+ base_class.define_method(:errors) do |locale: nil|
15
+ @errors ||= Hash.new { |hash, key| hash[key] = ActiveModel::Errors.new(self) }
16
+ @errors[locale || self.locale]
17
+ end
18
+ base_class.define_method(:valid?) do |locale: nil|
19
+ with_locale(locale) { super() }
20
+ end
21
+ end
22
+
23
+ # @!method self.validates_included_entry(*attr_names, **options)
24
+ # Adds a validation on one or more fields to ensure it's a reference field
25
+ # and the values are entries with one of the specified types
26
+ # @param attr_names [Array<string>] the fields to validate
27
+ # @param options [Hash] the options Hash
28
+ # @option options [Array<Class>] :allowed_models the contentful content types that will be allowed
29
+ # @option options [Boolean] :allow_blank if true it allows the field to be empty
30
+ # @option options [Boolean] :array if true, the field must be an array of references.
31
+ # If not, it must be a single reference.
32
+ class_methods do
33
+ def validates_included_entry(*attr_names)
34
+ validates_with IncludedEntryValidator, _merge_attributes(attr_names)
35
+ end
36
+ end
37
+
38
+ # @!method self.validates_included_asset(*attr_names, **options)
39
+ # Adds a validation on one or more fields to ensure it's a reference field
40
+ # and the values are assets
41
+ # @param attr_names [Array<string>] the fields to validate
42
+ # @param options [Hash] the options Hash
43
+ # @option options [Array<Class>] :type the asset content types that will be allowed
44
+ # @option options [Boolean] :allow_blank if true it allows the field to be empty
45
+ # @option options [Boolean] :array if true, the field must be an array of references.
46
+ # If not, it must be a single reference.
47
+ class_methods do
48
+ def validates_included_asset(*attr_names)
49
+ validates_with IncludedAssetValidator, _merge_attributes(attr_names)
50
+ end
51
+ end
52
+
53
+ # Validates all locales
54
+ # @return [boolean] is entry valid across al locales?
55
+ def valid_for_all_locales?
56
+ locales.map do |locale|
57
+ valid?(locale: locale)
58
+ end.all?
59
+ end
60
+
61
+ # Gets the error messages for all the locales at once
62
+ # @return [Hash] a hash with locale as keys and errors as values
63
+ def errors_for_all_locales
64
+ @errors
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,14 @@
1
+ module ContentfulLite
2
+ module Validations
3
+ # @api private
4
+ class IncludedAssetValidator < ActiveModel::EachValidator
5
+ include IncludedChildValidator
6
+ add_options_keys :type
7
+
8
+ def validate_child(record, attr_name, value, idx = nil)
9
+ record_error(record, attr_name, "value#{idx} is not a published asset") && return unless value.is_a?(ContentfulLite::Asset)
10
+ record_error(record, attr_name, "value#{idx} has an invalid asset type. Expecting #{options[:type]}") if options[:type] && !value&.content_type&.include?(options[:type].to_s)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,40 @@
1
+ module ContentfulLite
2
+ module Validations
3
+ # @api private
4
+ module IncludedChildValidator
5
+ extend ActiveSupport::Concern
6
+ BASE_OPTIONS = %i[allow_blank array].freeze
7
+
8
+ def validate_each(record, attr_name, value)
9
+ if value.blank?
10
+ record_error(record, attr_name, "value is blank") unless options[:allow_blank]
11
+ elsif options[:array]
12
+ validate_array(record, attr_name, value)
13
+ else
14
+ validate_child(record, attr_name, value)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def record_error(record, attr_name, message)
21
+ record.errors.add(attr_name, :invalid, { message: message }.merge(options.except(self.class.options_keys)))
22
+ end
23
+
24
+ def validate_array(record, attr_name, value)
25
+ record_error(record, attr_name, "value is not an array") && return unless value.is_a?(Array)
26
+ value.each_with_index { |asset, idx| validate_child(record, attr_name, asset, "[#{idx}]") }
27
+ end
28
+
29
+ class_methods do
30
+ def add_options_keys(*options)
31
+ @options_keys = BASE_OPTIONS + options
32
+ end
33
+
34
+ def options_keys
35
+ @options_keys
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,24 @@
1
+ module ContentfulLite
2
+ module Validations
3
+ # @api private
4
+ class IncludedEntryValidator < ActiveModel::EachValidator
5
+ include IncludedChildValidator
6
+ add_options_keys :allowed_models
7
+
8
+ def validate_child(record, attr_name, value, idx = nil)
9
+ unless value.is_a?(ContentfulLite::Entry)
10
+ record_error(record, attr_name, "value#{idx} is not a published entry")
11
+ return
12
+ end
13
+ record_error(record, attr_name, "value has invalid child entry #{value.id}") unless value.valid?(locale: record.locale)
14
+ record_error(record, attr_name, "value#{idx} has an invalid entry model. Expecting #{options[:allowed_models]}") if invalid_model?(value)
15
+ end
16
+
17
+ def invalid_model?(value)
18
+ return false unless options[:allowed_models]
19
+
20
+ options[:allowed_models]&.none?{ |type| value.is_a?(type) }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module ContentfulLite
2
+ VERSION = "1.0.2".freeze
3
+ end
@@ -0,0 +1,12 @@
1
+ require "contentful_lite/validations/entry"
2
+ require "contentful_lite/version"
3
+ require "contentful_lite/common_data"
4
+ require "contentful_lite/link"
5
+ require "contentful_lite/asset"
6
+ require "contentful_lite/entry_mapping"
7
+ require "contentful_lite/entry"
8
+ require "contentful_lite/deleted_entry"
9
+ require "contentful_lite/base_array"
10
+ require "contentful_lite/assets_array"
11
+ require "contentful_lite/entries_array"
12
+ require "contentful_lite/client"
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ContentfulLite::Asset do
4
+ let(:asset_hash) { JSON.parse(File.read('fixtures/assets/nyancat.json')) }
5
+ let(:instance) { ContentfulLite::Asset.new(asset_hash) }
6
+
7
+ describe '#attributes' do
8
+ it { expect(instance.title).to eq 'Nyan Cat' }
9
+ it { expect(instance.description).to eq '' }
10
+ it { expect(instance.url).to eq '//images.ctfassets.net/cfexampleapi/4gp6taAwW4CmSgumq2ekUm/9da0cd1936871b8d72343e895a00d611/Nyan_cat_250px_frame.png' }
11
+ it { expect(instance.file_name).to eq 'Nyan_cat_250px_frame.png' }
12
+ it { expect(instance.content_type).to eq 'image/png' }
13
+
14
+ context 'for unpublished assets without a file' do
15
+ let(:asset_hash) { JSON.parse(File.read('fixtures/assets/unpublished.json')) }
16
+
17
+ it { expect(instance.title).to be_nil }
18
+ it { expect(instance.description).to eq '' }
19
+ it { expect(instance.url).to be_nil }
20
+ it { expect(instance.file_name).to be_nil }
21
+ it { expect(instance.content_type).to be_nil }
22
+ end
23
+
24
+ context 'when requesting multiple locales at once' do
25
+ let(:asset_hash) { JSON.parse(File.read('fixtures/assets/nyancat_with_locales.json')) }
26
+
27
+ it { expect(instance.title).to eq 'Nyan Cat' }
28
+ it { expect(instance.description).to eq '' }
29
+ it { expect(instance.url).to eq '//images.ctfassets.net/cfexampleapi/4gp6taAwW4CmSgumq2ekUm/9da0cd1936871b8d72343e895a00d611/Nyan_cat_250px_frame.png' }
30
+ it { expect(instance.file_name).to eq 'Nyan_cat_250px_frame.png' }
31
+ it { expect(instance.content_type).to eq 'image/png' }
32
+ it { expect(instance.title(locale: 'tlh')).to eq "Nyan vIghro'" }
33
+ it { expect(instance.description(locale: 'tlh')).to eq '' }
34
+ end
35
+ end
36
+
37
+ describe '#contentful_link' do
38
+ subject { instance.contentful_link }
39
+
40
+ it { is_expected.to eq 'https://app.contentful.com/spaces/cfexampleapi/assets/nyancat' }
41
+ end
42
+
43
+ describe 'serializing' do
44
+ subject { Marshal.load(Marshal.dump(instance)) }
45
+
46
+ it { expect(subject.id).to eq(instance.id) }
47
+ it { expect(subject.created_at).to eq(instance.created_at) }
48
+ it { expect(subject.updated_at).to eq(instance.updated_at) }
49
+ it { expect(subject.retrieved_at).to eq(instance.retrieved_at) }
50
+ it { expect(subject.locale).to eq(instance.locale) }
51
+ it { expect(subject.revision).to eq(instance.revision) }
52
+ it { expect(subject.space_id).to eq(instance.space_id) }
53
+ it { expect(subject.environment_id).to eq(instance.environment_id) }
54
+ it { expect(subject.title).to eq(instance.title) }
55
+ it { expect(subject.description).to eq(instance.description) }
56
+ it { expect(subject.file_name).to eq(instance.file_name) }
57
+ it { expect(subject.content_type).to eq(instance.content_type) }
58
+ it { expect(subject.url).to eq(instance.url) }
59
+ it { expect(subject.file_details).to eq(instance.file_details) }
60
+ end
61
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ContentfulLite::AssetsArray do
4
+ let(:response) { JSON.parse(File.read('fixtures/assets/all.json')) }
5
+ let(:instance) { ContentfulLite::AssetsArray.new(response) }
6
+
7
+ describe 'should create an array of assets' do
8
+ it { expect(instance.first).to be_an ContentfulLite::Asset }
9
+ it { expect(instance.last).to be_an ContentfulLite::Asset }
10
+ it { expect(instance.sample).to be_an ContentfulLite::Asset }
11
+ end
12
+
13
+ context 'with multiple locales' do
14
+ let(:response) { JSON.parse(File.read('fixtures/assets/all_with_locales.json')) }
15
+
16
+ describe 'should create an array of assets' do
17
+ it { expect(instance.first).to be_an ContentfulLite::Asset }
18
+ it { expect(instance.first.title).to be_a String }
19
+ end
20
+ end
21
+
22
+ describe 'serializing' do
23
+ subject { Marshal.load(Marshal.dump(instance)) }
24
+
25
+ it { expect(subject.first.id).to eq(instance.first.id) }
26
+ it { expect(subject.first.file_name).to eq(instance.first.file_name) }
27
+ it { expect(subject.last.file_details).to eq(instance.last.file_details) }
28
+ it { expect(subject.last.id).to eq(instance.last.id) }
29
+ it { expect(subject.last.file_name).to eq(instance.last.file_name) }
30
+ it { expect(subject.last.file_details).to eq(instance.last.file_details) }
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ContentfulLite::BaseArray do
4
+ let(:instance) { ContentfulLite::BaseArray.new(response) }
5
+
6
+ describe '#attributes' do
7
+ context 'for an array of assets' do
8
+ let(:response) { JSON.parse(File.read('fixtures/assets/all.json')) }
9
+
10
+ it { expect(instance.total).to eq 4 }
11
+ it { expect(instance.skip).to eq 0 }
12
+ it { expect(instance.limit).to eq 100 }
13
+ end
14
+ end
15
+
16
+ describe '#attributes' do
17
+ context 'for an array of entries' do
18
+ let(:response) { JSON.parse(File.read('fixtures/entries/all.json')) }
19
+
20
+ it { expect(instance.total).to eq 10 }
21
+ it { expect(instance.skip).to eq 0 }
22
+ it { expect(instance.limit).to eq 100 }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ContentfulLite::Client do
4
+ let(:instance) { ContentfulLite::Client.new(space_id: 'cfexampleapi', access_token: 'b4c0n73n7fu1') }
5
+
6
+ around(:each) do |example|
7
+ if defined?(cassette_name)
8
+ VCR.use_cassette("client/#{cassette_name}") do
9
+ example.run
10
+ end
11
+ else
12
+ example.run
13
+ end
14
+ end
15
+
16
+ describe '#entries' do
17
+ let(:cassette_name) { 'entries' }
18
+ let(:query) { {} }
19
+ subject do
20
+ instance.entries(query)
21
+ end
22
+
23
+ it { is_expected.to be_a(ContentfulLite::EntriesArray) }
24
+
25
+ context 'when the query is invalid' do
26
+ let(:cassette_name) { 'invalid_query' }
27
+ let(:query) { { invalid_parameter: 'invalid_value' } }
28
+
29
+ it { expect { subject }.to raise_error(ContentfulLite::Client::RequestError, "InvalidQuery: The query you sent was invalid. Probably a filter or ordering specification is not applicable to the type of a field.") }
30
+ end
31
+
32
+ context 'when the query has an array parameter' do
33
+ let(:cassette_name) { 'array_parameter' }
34
+ let(:query) { { 'sys.id[in]': ['nyancat', 'happycat'] } }
35
+
36
+ it { is_expected.to be_a(ContentfulLite::EntriesArray) }
37
+ it { expect(subject.size).to eq 2 }
38
+ end
39
+ end
40
+
41
+ describe '#entry' do
42
+ let(:cassette_name) { 'entry' }
43
+ let(:query) { {} }
44
+ let(:entry_id) { 'nyancat' }
45
+ subject do
46
+ instance.entry(entry_id, query)
47
+ end
48
+
49
+ it { is_expected.to be_a(ContentfulLite::Entry) }
50
+
51
+ context 'when the query is invalid' do
52
+ let(:cassette_name) { 'entry_invalid_query' }
53
+ let(:query) { { locale: 'invalid_value' } }
54
+
55
+ it { expect { subject }.to raise_error(ContentfulLite::Client::RequestError, "BadRequest: Unknown locale: invalid_value") }
56
+ end
57
+
58
+ context 'when the id is not found' do
59
+ let(:cassette_name) { 'entry_missings_id' }
60
+ let(:entry_id) { 'invalidcat' }
61
+
62
+ it { expect { subject }.to raise_error(ContentfulLite::Client::NotFoundError, "NotFound: The resource could not be found.") }
63
+ end
64
+ end
65
+
66
+ describe '#assets' do
67
+ let(:cassette_name) { 'assets' }
68
+ let(:query) { {} }
69
+ subject do
70
+ instance.assets(query)
71
+ end
72
+
73
+ it { is_expected.to be_a(ContentfulLite::AssetsArray) }
74
+
75
+ context 'when the query is invalid' do
76
+ let(:cassette_name) { 'assets_invalid_query' }
77
+ let(:query) { { invalid_parameter: 'invalid_value' } }
78
+
79
+ it { expect { subject }.to raise_error(ContentfulLite::Client::RequestError, "InvalidQuery: The query you sent was invalid. Probably a filter or ordering specification is not applicable to the type of a field.") }
80
+ end
81
+ end
82
+
83
+ describe '#asset' do
84
+ let(:cassette_name) { 'asset' }
85
+ let(:query) { {} }
86
+ let(:asset_id) { 'nyancat' }
87
+ subject do
88
+ instance.asset(asset_id, query)
89
+ end
90
+
91
+ it { is_expected.to be_a(ContentfulLite::Asset) }
92
+
93
+ context 'when the query is invalid' do
94
+ let(:cassette_name) { 'asset_invalid_query' }
95
+ let(:query) { { locale: 'invalid_value' } }
96
+
97
+ it { expect { subject }.to raise_error(ContentfulLite::Client::RequestError, "BadRequest: Unknown locale: invalid_value") }
98
+ end
99
+
100
+ context 'when the id is not found' do
101
+ let(:cassette_name) { 'asset_missings_id' }
102
+ let(:asset_id) { 'invalidcat' }
103
+
104
+ it { expect { subject }.to raise_error(ContentfulLite::Client::NotFoundError, "NotFound: The resource could not be found.") }
105
+ end
106
+ end
107
+
108
+ describe '#build_resource' do
109
+ let(:fixture) { 'entries/nyancat' }
110
+ let(:hash) { JSON.parse(File.read("fixtures/#{fixture}.json")) }
111
+ subject do
112
+ instance.build_resource(hash)
113
+ end
114
+
115
+ it { is_expected.to be_a(ContentfulLite::Entry) }
116
+
117
+ context 'when the resource is an asset' do
118
+ let(:fixture) { 'assets/nyancat' }
119
+
120
+ it { is_expected.to be_a(ContentfulLite::Asset) }
121
+ end
122
+
123
+ context 'when the resource is a DeletedEntry' do
124
+ let(:fixture) { 'entries/deleted_entry' }
125
+
126
+ it { is_expected.to be_a(ContentfulLite::DeletedEntry) }
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ContentfulLite::CommonData do
4
+ let(:klass) { Class.new.include(described_class) }
5
+ let(:instance) { klass.new(raw_hash) }
6
+
7
+ describe '#attributes' do
8
+ context 'with an entry' do
9
+ let(:raw_hash) { JSON.parse(File.read('fixtures/entries/nyancat.json')) }
10
+
11
+ it { expect(instance.id).to eq 'nyancat' }
12
+ it { expect(instance.created_at).to eq DateTime.new(2013, 6, 27, 22, 46, 19.513) }
13
+ it { expect(instance.updated_at).to eq DateTime.new(2013, 9, 4, 9, 19, 39.027) }
14
+ it { expect(instance.locale).to eq 'en-US' }
15
+ it { expect(instance.revision).to eq 5 }
16
+ it { expect(instance.space_id).to eq 'cfexampleapi' }
17
+ it { expect(instance.environment_id).to eq 'master' }
18
+ it { expect(instance.retrieved_at).to be_a DateTime }
19
+ end
20
+ end
21
+
22
+ describe '#attributes' do
23
+ context 'with an asset' do
24
+ let(:raw_hash) { JSON.parse(File.read('fixtures/assets/nyancat.json')) }
25
+
26
+ it { expect(instance.id).to eq 'nyancat' }
27
+ it { expect(instance.created_at).to eq DateTime.new(2013, 9, 2, 14, 56, 34.240) }
28
+ it { expect(instance.updated_at).to eq DateTime.new(2013, 9, 2, 14, 56, 34.240) }
29
+ it { expect(instance.locale).to eq 'en-US' }
30
+ it { expect(instance.revision).to eq 1 }
31
+ it { expect(instance.space_id).to eq 'cfexampleapi' }
32
+ it { expect(instance.environment_id).to eq 'master' }
33
+ it { expect(instance.retrieved_at).to be_a DateTime }
34
+ end
35
+ end
36
+
37
+ describe '#fields' do
38
+ subject { instance.fields['name'] }
39
+
40
+ context 'for a single locale entry' do
41
+ let(:raw_hash) { JSON.parse(File.read('fixtures/entries/nyancat.json')) }
42
+
43
+ it { is_expected.to eq 'Nyan Cat' }
44
+
45
+ context 'when specific locale is requested' do
46
+ subject { instance.fields(locale: 'tlh')['name'] }
47
+
48
+ it { is_expected.to eq nil }
49
+ end
50
+ end
51
+
52
+ context 'for a multiple locale entry' do
53
+ let(:raw_hash) { JSON.parse(File.read('fixtures/entries/nyancat_with_locales.json')) }
54
+
55
+ it { is_expected.to eq 'Nyan Cat' }
56
+
57
+ context 'when specific locale is requested' do
58
+ subject { instance.fields(locale: 'tlh')['name'] }
59
+
60
+ it { is_expected.to eq "Nyan vIghro'" }
61
+ end
62
+ end
63
+ end
64
+
65
+ describe '#with_locale' do
66
+ subject { instance.with_locale('tlh') { instance.fields['name'] } }
67
+
68
+ context 'for a multiple locale entry' do
69
+ let(:raw_hash) { JSON.parse(File.read('fixtures/entries/nyancat_with_locales.json')) }
70
+
71
+ it { is_expected.to eq "Nyan vIghro'" }
72
+ end
73
+ end
74
+
75
+ describe '#to_link' do
76
+ let(:raw_hash) { JSON.parse(File.read('fixtures/entries/nyancat.json')) }
77
+
78
+ subject { instance.to_link }
79
+
80
+ it { expect(subject.id).to eq 'nyancat' }
81
+ it { expect(subject.type).to eq :entry }
82
+
83
+ context 'with an asset' do
84
+ let(:raw_hash) { JSON.parse(File.read('fixtures/assets/nyancat.json')) }
85
+
86
+ it { expect(subject.id).to eq 'nyancat' }
87
+ it { expect(subject.type).to eq :asset }
88
+ end
89
+ end
90
+
91
+ describe '#as_json' do
92
+ let(:raw_hash) { JSON.parse(File.read('fixtures/entries/nyancat.json')) }
93
+
94
+ subject { instance.as_json }
95
+
96
+ it { is_expected.to eq(raw_hash) }
97
+
98
+ context 'when rails is passing some other parameters as hash' do
99
+ let(:hash) { { template: "something", status: 200 } }
100
+ subject { instance.as_json(hash) }
101
+
102
+ it { is_expected.to eq(raw_hash) }
103
+ end
104
+
105
+ context 'when rails is passing parameters with named args syntax' do
106
+ subject { instance.as_json(template: "something", status: 200) }
107
+
108
+ it { is_expected.to eq(raw_hash) }
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ContentfulLite::DeletedEntry do
4
+ let(:entry_hash) { JSON.parse(File.read('fixtures/entries/deleted_entry.json')) }
5
+ let(:instance) { ContentfulLite::DeletedEntry.new(entry_hash) }
6
+
7
+ describe '#attributes' do
8
+ it { expect(instance.content_type_id).to eq 'cat' }
9
+ it { expect(instance.id).to eq 'deletedcat' }
10
+ end
11
+
12
+ describe '#contentful_link' do
13
+ subject { instance.contentful_link }
14
+
15
+ it { expect { subject }.to raise_error NotImplementedError }
16
+ end
17
+
18
+ describe 'serializing' do
19
+ subject { Marshal.load(Marshal.dump(instance)) }
20
+
21
+ it { expect(subject.id).to eq(instance.id) }
22
+ it { expect(subject.created_at).to eq(instance.created_at) }
23
+ it { expect(subject.updated_at).to eq(instance.updated_at) }
24
+ it { expect(subject.retrieved_at).to eq(instance.retrieved_at) }
25
+ it { expect(subject.revision).to eq(instance.revision) }
26
+ it { expect(subject.space_id).to eq(instance.space_id) }
27
+ it { expect(subject.environment_id).to eq(instance.environment_id) }
28
+ it { expect(subject.content_type_id).to eq(instance.content_type_id) }
29
+ end
30
+ end