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.
@@ -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