content entry repository (only FS), some methods are still missing [WIP]

did committed Feb 28, 2015
commit 66f2f77ca831980def1ae9f3e60dfd90d5602ac2
Showing 31 changed files with 1025 additions and 571 deletions
locomotive/steam/adapters/filesystem.rb b/lib/locomotive/steam/adapters/filesystem.rb +7 -3
@@ @@ -49,11 +49,15 @@ module Locomotive::Steam
end
def memoized_dataset(mapper, scope)
- cache.fetch(mapper.name) do
+ cache.fetch(cache_key(mapper, scope)) do
dataset(mapper, scope)
end
end
+ def cache_key(mapper, scope)
+ "#{scope.to_key}_#{mapper.name}"
+ end
+
def dataset(mapper, scope)
Locomotive::Steam::Adapters::Memory::Dataset.new(mapper.name).tap do |dataset|
populate_dataset(dataset, mapper, scope)
@@ @@ -78,7 +82,7 @@ module Locomotive::Steam
end
def build_yaml_loaders
- %i(sites pages content_types snippets translations theme_assets).inject({}) do |memo, name|
+ %i(sites pages content_types content_entries snippets translations theme_assets).inject({}) do |memo, name|
memo[name] = build_klass('YAMLLoaders', name).new(site_path)
memo
end
@@ @@ -86,7 +90,7 @@ module Locomotive::Steam
def build_sanitizers
hash = Hash.new { build_klass('Sanitizers', :simple).new }
- %i(pages content_types snippets).inject(hash) do |memo, name|
+ %i(pages content_types content_entries snippets).inject(hash) do |memo, name|
memo[name] = build_klass('Sanitizers', name).new
memo
end
locomotive/steam/adapters/filesystem/sanitizers/content_entry.rb b/lib/locomotive/steam/adapters/filesystem/sanitizers/content_entry.rb +73 -0
@@ @@ -1,3 +1,76 @@
+ module Locomotive::Steam
+ module Adapters
+ module Filesystem
+ module Sanitizers
+
+ class ContentEntry
+
+ include Adapters::Filesystem::Sanitizer
+
+ def apply_to_entity(entity)
+ super
+ add_label(entity)
+ end
+
+ def apply_to_dataset(dataset)
+ dataset.all.each do |entry|
+ set_slug(entry, dataset)
+ end
+ end
+
+ private
+
+ def add_label(entry)
+ value = entry.attributes.delete(:_label)
+ name = entry.content_type.label_field_name
+
+ if entry.attributes[name].respond_to?(:translations) # localized?
+ entry.attributes[name][default_locale] = value
+ else
+ entry.attributes[name] ||= value
+ end
+ end
+
+ def set_slug(entry, dataset)
+ if entry._label.respond_to?(:translations) # localized?
+ entry[:_slug] ||= {}
+ entry._label.each do |locale, label|
+ entry[:_slug][locale] ||= slugify(label, dataset, locale)
+ end
+ else
+ entry[:_slug] ||= slugify(entry._label, dataset)
+ end
+ end
+
+ def slugify(label, dataset, locale = nil)
+ base, index = label.permalink(false), nil
+ _slugify = -> (i) { [base, i].compact.join('-') }
+
+ while !is_slug_unique?(_slugify.call(index), dataset, locale)
+ index = index ? index + 1 : 1
+ end
+
+ _slugify.call(index)
+ end
+
+ def is_slug_unique?(slug, dataset, locale)
+ dataset.query(locale) { where(_slug: slug) }.first.nil?
+ # Filesystem::MemoryAdapter::Query.new(collection, locale) do
+ # where(_slug: slug)
+ # end.first.nil?
+ end
+
+ end
+
+ end
+ end
+ end
+ end
+
+
+
+
+
# module Locomotive
# module Steam
# module Repositories
locomotive/steam/adapters/filesystem/yaml_loaders/content_entry.rb b/lib/locomotive/steam/adapters/filesystem/yaml_loaders/content_entry.rb +50 -51
@@ @@ -1,51 +1,50 @@
- # module Locomotive
- # module Steam
- # module Repositories
- # module Filesystem
- # module YAMLLoaders
-
- # class ContentEntry < Struct.new(:root_path, :cache)
-
- # include YAMLLoaders::Concerns::Common
-
- # def list_of_attributes(content_type)
- # cache.fetch("data/#{content_type.slug}") { load_list(content_type) }
- # end
-
- # def write(content_type, attributes)
- # list = cache.read("data/#{content_type.slug}")
-
- # list << attributes.merge(content_type: content_type)
- # end
-
- # private
-
- # def load_list(content_type)
- # [].tap do |list|
- # each(content_type.slug) do |label, attributes, position|
- # default = { content_type: content_type, _position: position, _label: label.to_s }
- # list << default.merge(attributes)
- # end
- # end
- # end
-
- # def each(slug, &block)
- # position = 0
- # load(File.join(path, "#{slug}.yml")).each do |element|
- # label, attributes = element.keys.first, element.values.first
- # yield(label, attributes, position)
- # position += 1
- # end
- # end
-
- # def path
- # File.join(root_path, 'data')
- # end
-
- # end
-
- # end
- # end
- # end
- # end
- # end
+ module Locomotive
+ module Steam
+ module Adapters
+ module Filesystem
+ module YAMLLoaders
+
+ class ContentEntry
+
+ include Adapters::Filesystem::YAMLLoader
+
+ def load(scope)
+ super
+ load_list
+ end
+
+ private
+
+ def load_list
+ [].tap do |list|
+ each(content_type_slug) do |label, attributes, position|
+ default = { _position: position, _label: label.to_s }
+ list << default.merge(attributes)
+ end
+ end
+ end
+
+ def each(slug, &block)
+ position = 0
+ _load(File.join(path, "#{slug}.yml")).each do |element|
+ label, attributes = element.keys.first, element.values.first
+ yield(label, attributes, position)
+ position += 1
+ end
+ end
+
+ def path
+ File.join(site_path, 'data')
+ end
+
+ def content_type_slug
+ @scope.context[:content_type].slug
+ end
+
+ end
+
+ end
+ end
+ end
+ end
+ end
locomotive/steam/adapters/memory/dataset.rb b/lib/locomotive/steam/adapters/memory/dataset.rb +3 -3
@@ @@ -55,9 +55,9 @@ module Locomotive::Steam
!!id && records.has_key?(id)
end
- # def query
- # Query.new(self)
- # end
+ def query(locale = nil, &block)
+ Query.new(self, locale, &block)
+ end
def clear!
@records = {}
locomotive/steam/entities/content_entry.rb b/lib/locomotive/steam/entities/content_entry.rb +139 -0
@@ @@ -0,0 +1,139 @@
+ require 'chronic'
+
+ module Locomotive::Steam
+
+ class ContentEntry
+
+ ASSOCIATION_NAMES = [:belongs_to, :has_many, :many_to_many].freeze
+
+ include Locomotive::Steam::Models::Entity
+
+ attr_accessor :content_type
+
+ def initialize(attributes = {})
+ super({
+ _visible: true,
+ _position: 0,
+ created_at: Time.now,
+ updated_at: Time.now
+ }.merge(attributes))
+ end
+
+ def _visible?; !!self[:_visible]; end
+ alias :visible? :_visible?
+
+ def _slug; self[:_slug]; end
+ alias :_permalink :_slug
+
+ def method_missing(name, *args, &block)
+ if is_dynamic_attribute?(name)
+ cast_value(name)
+ elsif attributes.include?(name)
+ self[name]
+ else
+ super
+ end
+ end
+
+ def valid?
+ errors.clear
+ content_type.fields.required.each do |field|
+ errors.add_on_blank(field.name.to_sym)
+ end
+ errors.empty?
+ end
+
+ def content_type
+ @content_type || attributes[:content_type]
+ end
+
+ def content_type_slug
+ content_type.slug
+ end
+
+ def _label
+ self[content_type.label_field_name]
+ end
+
+ # def localized_attributes
+ # self.class.localized_attributes + content_type.localized_fields_names
+ # end
+
+ def to_liquid
+ Locomotive::Steam::Liquid::Drops::ContentEntry.new(self)
+ end
+
+ private
+
+ def is_dynamic_attribute?(name)
+ content_type.fields_by_name.has_key?(name)
+ end
+
+ def cast_value(name)
+ field = content_type.fields_by_name[name]
+
+ begin
+ _cast_value(field)
+ rescue Exception => e
+ Locomotive::Common::Logger.info "[#{content_type.slug}][#{_label}] Unable to cast the \"#{name}\" field, reason: #{e.message}".yellow
+ nil
+ end
+ end
+
+ def _cast_value(field)
+ if ASSOCIATION_NAMES.include?(field.type)
+ AssociationMetadata.new(field.type, self, field, [*attributes[field.name]])
+ elsif private_methods.include?(:"_cast_#{field.type}")
+ send(:"_cast_#{field.type}", field.name)
+ else
+ attributes[field.name]
+ end
+ end
+
+ def _cast_integer(name)
+ _cast_convertor(name, &:to_i)
+ end
+
+ def _cast_float(name)
+ _cast_convertor(name, &:to_f)
+ end
+
+ def _cast_file(name)
+ _cast_convertor(name) do |value|
+ value.present? ? { 'url' => value } : nil
+ end
+ end
+
+ def _cast_date(name)
+ _cast_time(name, :to_date)
+ end
+
+ def _cast_date_time(name)
+ _cast_time(name, :to_date)
+ end
+
+ def _cast_time(name, end_method)
+ _cast_convertor(name) do |value|
+ value.is_a?(String) ? Chronic.parse(value).send(end_method) : value
+ end
+ end
+
+ def _cast_convertor(name, &block)
+ if (value = attributes[name]).respond_to?(:translations)
+ value.each { |l, _value| value[l] = yield(_value) }
+ value
+ else
+ yield(value)
+ end
+ end
+
+ class AssociationMetadata < Struct.new(:type, :source, :field, :target_slugs)
+ def association; true; end
+ def inverse_of; field.inverse_of; end
+ def target_class_slug; field.class_name; end
+ def order_by; field[:order_by]; end
+ end
+
+ end
+
+ end
locomotive/steam/entities/content_type.rb b/lib/locomotive/steam/entities/content_type.rb +11 -0
@@ @@ -16,6 +16,17 @@ module Locomotive::Steam
self.entries_custom_fields
end
+ def fields_by_name
+ @fields_by_name ||= (fields.all.inject({}) do |memo, field|
+ memo[field.name] = field
+ memo
+ end)
+ end
+
+ def localized_fields_names
+ self.fields.localized_fields_names
+ end
+
def label_field_name
(self[:label_field_name] || fields.first.name).to_sym
end
locomotive/steam/models/i18n_field.rb b/lib/locomotive/steam/models/i18n_field.rb +4 -0
@@ @@ -27,6 +27,10 @@ module Locomotive::Steam
@translations.values
end
+ def each(&block)
+ @translations.each(&block)
+ end
+
end
end
locomotive/steam/models/mapper.rb b/lib/locomotive/steam/models/mapper.rb +0 -1
@@ @@ -72,7 +72,6 @@ module Locomotive::Steam
def set_default_attributes(entity)
@default_attributes.each do |(name, value)|
- # _value = value.respond_to?(:call) ? @repository.instance_eval(&value) : value
_value = value.respond_to?(:call) ? value.call(@repository) : value
entity.send(:"#{name}=", _value)
end
locomotive/steam/models/repository.rb b/lib/locomotive/steam/models/repository.rb +5 -3
@@ @@ -35,11 +35,13 @@ module Locomotive::Steam
alias :all :query
- def mapper
+ def mapper(memoized = true)
name, options, block = mapper_options
- @mapper ||= Mapper.new(name, options, self, &block)
- end
+ return @mapper if @mapper && memoized
+
+ @mapper = Mapper.new(name, options, self, &block)
+ end
# TODO: not sure about that. could it be used further in the dev
# def collection_name
locomotive/steam/models/scope.rb b/lib/locomotive/steam/models/scope.rb +15 -1
@@ @@ -1,7 +1,13 @@
module Locomotive::Steam
module Models
- class Scope < Struct.new(:site, :locale)
+ class Scope
+
+ attr_accessor :site, :locale, :context
+
+ def initialize(site, locale, context = nil)
+ @site, @locale, @context = site, locale, (context || {})
+ end
def default_locale
site.try(:default_locale)
@@ @@ -11,6 +17,14 @@ module Locomotive::Steam
site.try(:locales)
end
+ def to_key
+ ['site', @site.try(:_id)].tap do |base|
+ @context.each do |name, object|
+ base << [name, object.try(:_id)]
+ end
+ end.flatten.join('_')
+ end
+
end
end
locomotive/steam/repositories/content_entry_repository.rb b/lib/locomotive/steam/repositories/content_entry_repository.rb +200 -0
@@ @@ -0,0 +1,200 @@
+ module Locomotive
+ module Steam
+
+ class ContentEntryRepository
+
+ include Models::Repository
+
+ attr_accessor :content_type
+
+ def initialize(adapter, site = nil, locale = nil, content_type_repository = nil)
+ @adapter = adapter
+ @scope = Locomotive::Steam::Models::Scope.new(site, locale)
+ @content_type_repository = content_type_repository
+ end
+
+ # Entity mapping
+ mapping :content_entries, entity: ContentEntry do
+ localized_attributes :_slug, :seo_title, :meta_description, :meta_keywords
+
+ default_attribute :content_type, -> (repository) { repository.content_type }
+
+ # # embedded association
+ # association :entries_custom_fields, ContentTypeFieldRepository
+ end
+
+ def all(type, conditions = {})
+ conditions = { _visible: true }.merge(conditions || {})
+
+ self.content_type = type # used for creating the scope
+ self.scope.context[:content_type] = type
+
+ # filter the entries by the content type they belong to
+ conditions[:content_type_id] = type._id
+
+ # priority:
+ # 1/ order_by passed in the conditions parameter
+ # 2/ the default order (_position) defined in the content type
+ order_by = conditions.delete(:order_by)|| conditions.delete('order_by') || type.order_by
+
+ query { where(conditions).order_by(order_by) }.all
+ end
+
+ # Engine: content_type.entries.build(attributes)
+ def build(type, attributes = {})
+ raise 'TODO, delegate to the adapter'
+
+ # collection_options[:model].new(attributes).tap do |entry|
+ # # set the reference to the content type
+ # entry.content_type = type
+ # end
+ end
+
+ # Engine: entry.save
+ def persist(entry)
+ return nil if entry.nil?
+
+ raise 'TODO, delegate to the adapter'
+
+ # collection = memoized_collection(entry.content_type)
+
+ # # slugify entry
+ # sanitizer.set_slug(entry, collection)
+
+ # collection << entry # immediate result
+
+ # # make sure we write it back to the data source
+ # loader.write(entry.content_type, entry.attributes)
+ end
+
+ # Engine: all(conditions).count > 0
+ def exists?(type, conditions = {})
+ query(type) { where(conditions) }.all.size > 0
+ end
+
+ # Engine: not necessary
+ def by_slug(type, slug)
+ query(type) { where(_slug: slug) }.first
+ end
+
+ # Engine: entry.send(:name) :-)
+ def value_for(name, entry, conditions = {})
+ value = entry.send(name)
+
+ if value.respond_to?(:association)
+ association(value, conditions || {})
+ else
+ value
+ end
+ end
+
+ # Engine: entry.next
+ def next(entry)
+ next_or_previous(entry, 'gt', 'lt')
+ end
+
+ # Engine: entry.previous
+ def previous(entry)
+ next_or_previous(entry, 'lt', 'gt')
+ end
+
+ # Engine: content_type.entries.klass.send(:group_by_select_option, name, content_type.order_by_definition)
+ def group_by_select_option(type, name)
+ return {} if type.nil? || name.nil? || type.fields_by_name[name].type != :select
+
+ raise 'TODO: implement the group_by method'
+ _groups = all(type).group_by(&name)
+
+ groups = content_type_repository.select_options(type, name).map do |option|
+ { name: option, entries: _groups.delete(option) || [] }
+ end
+
+ unless _groups.blank?
+ groups << (empty = { name: nil, entries: [] })
+ _groups.values.each { |list| empty[:entries] += list }
+ end
+
+ groups
+ end
+
+ private
+
+ def scoped_query(type, &block)
+ self.content_type = type
+ query(&block)
+ end
+
+ def mapper(memoized = true)
+ super(false).tap do |mapper|
+ unless self.content_type.localized_fields_names.blank?
+ mapper.localized_attributes(*self.content_type.localized_fields_names)
+ end
+ end
+ end
+
+ def type_from(slug)
+ content_type_repository.by_slug(slug)
+ end
+
+ def localized_slug(entry)
+ raise 'SHOULD NOT BE USED'
+ localized_attribute(entry, :_slug)
+ end
+
+ def association(metadata, conditions = {})
+ case metadata.type
+ when :belongs_to then belongs_to_association(metadata)
+ when :has_many then has_many_association(metadata, conditions)
+ when :many_to_many then many_to_many_association(metadata, conditions)
+ end
+ end
+
+ def belongs_to_association(metadata)
+ type = type_from(metadata.target_class_slug)
+ by_slug(type, metadata.target_slugs.first)
+ end
+
+ def has_many_association(metadata, conditions)
+ many_association(metadata,
+ { metadata.target_field => localized_slug(metadata.source) }.merge(conditions))
+ end
+
+ def many_to_many_association(metadata, conditions)
+ many_association(metadata,
+ { '_slug.in' => metadata.target_slugs }.merge(conditions))
+ end
+
+ def many_association(metadata, conditions)
+ type = type_from(metadata.target_class_slug)
+
+ if order_by = metadata.order_by
+ conditions = { order_by: order_by }.merge(conditions)
+ end
+
+ all(type, conditions)
+ end
+
+ # def memoized_collection(content_type)
+ # slug = content_type.slug
+ # @collections ||= {}
+
+ # return @collections[slug] if @collections[slug]
+
+ # @collections[slug] = collection(content_type)
+ # end
+
+ def next_or_previous(entry, asc_op, desc_op)
+ return nil if entry.nil?
+
+ type = entry.content_type
+ column, direction = type.order_by.split
+ operator = direction == 'asc' ? asc_op : desc_op
+ value = localized_attribute(entry, column)
+
+ query(type) { where("#{column}.#{operator}" => value) }.first
+ end
+
+ end
+
+ end
+ end
locomotive/steam/repositories/content_type_field_repository.rb b/lib/locomotive/steam/repositories/content_type_field_repository.rb +4 -0
@@ @@ -22,6 +22,10 @@ module Locomotive
end
end
+ def required
+ query { where(required: true) }.all
+ end
+
def localized_names
query { where(localized: true) }.all.map(&:name)
end
locomotive/steam/repositories/filesystem/content_entry.rb b/lib/locomotive/steam/repositories/filesystem/content_entry.rb +1 -1
@@ @@ -56,7 +56,7 @@
# query(type) { where(_slug: slug) }.first
# end
- # # Engine: entry.name :-)
+ # # Engine: entry.send(:name) :-)
# def value_for(name, entry, conditions = {})
# value = entry.send(name)
spec/unit/adapters/filesystem/yaml_loaders/content_entry_spec.rb +18 -15
@@ @@ -1,22 +1,25 @@
- # require 'spec_helper'
+ require 'spec_helper'
- # describe Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::ContentEntry do
+ require_relative '../../../../../lib/locomotive/steam/adapters/filesystem/yaml_loader.rb'
+ require_relative '../../../../../lib/locomotive/steam/adapters/filesystem/yaml_loaders/content_entry.rb'
- # let(:root_path) { default_fixture_site_path }
- # let(:cache) { NoCacheStore.new }
- # let(:content_type) { instance_double('Articles', slug: 'bands') }
- # let(:loader) { Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::ContentEntry.new(root_path, cache) }
+ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::ContentEntry do
- # describe '#list_of_attributes' do
+ let(:site_path) { default_fixture_site_path }
+ let(:content_type) { instance_double('Articles', slug: 'bands') }
+ let(:scope) { instance_double('Scope', locale: :en, context: { content_type: content_type }) }
+ let(:loader) { described_class.new(site_path) }
- # subject { loader.list_of_attributes(content_type).sort { |a, b| a[:_label] <=> b[:_label] } }
+ describe '#load' do
- # it 'tests various stuff' do
- # expect(subject.size).to eq 3
- # expect(subject.first[:_label]).to eq 'Alice in Chains'
- # expect(subject.first[:content_type]).to eq content_type
- # end
+ subject { loader.load(scope).sort { |a, b| a[:_label] <=> b[:_label] } }
- # end
+ it 'tests various stuff' do
+ expect(subject.size).to eq 3
+ expect(subject.first[:_label]).to eq 'Alice in Chains'
+ expect(subject.first[:content_type]).to eq nil
+ end
- # end
+ end
+
+ end
spec/unit/adapters/filesystem_adapter_spec.rb +1 -1
@@ @@ -5,7 +5,7 @@ require_relative '../../../lib/locomotive/steam/adapters/filesystem.rb'
describe Locomotive::Steam::FilesystemAdapter do
let(:mapper) { instance_double('Mapper', name: :test) }
- let(:scope) { instance_double('Scope', site: site, locale: nil) }
+ let(:scope) { instance_double('Scope', site: site, locale: nil, to_key: 'key') }
let(:adapter) { Locomotive::Steam::FilesystemAdapter.new(nil) }
describe '#key' do
spec/unit/entities/content_entry_spec.rb +186 -0
@@ @@ -0,0 +1,186 @@
+ require 'spec_helper'
+
+ describe Locomotive::Steam::ContentEntry do
+
+ let(:fields) { nil }
+ let(:repository) { instance_double('FieldRepository', all: fields) }
+ let(:type) { instance_double('ContentType', slug: 'articles', label_field_name: :title, fields: repository) }
+ let(:attributes) { { title: 'Hello world', _slug: 'hello-world' } }
+ let(:content_entry) { described_class.new(attributes) }
+
+ before { content_entry.content_type = type }
+
+ describe '#valid?' do
+
+ let(:fields) { [instance_double('Field', name: :title, type: 'string', required: true)] }
+
+ before do
+ allow(repository).to receive(:required).and_return(fields)
+ allow(type).to receive(:fields_by_name).and_return({ title: fields.first })
+ end
+
+ subject { content_entry.valid? }
+ it { is_expected.to eq true }
+
+ context 'missing attribute' do
+
+ let(:attributes) { {} }
+ it { is_expected.to eq false }
+ it { subject; expect(content_entry.errors[:title]).to eq(["can't not be blank"]) }
+ it { subject; expect(content_entry.errors.empty?).to eq false }
+
+ end
+
+ describe 'adding a custom error message' do
+
+ before { content_entry.errors.add(:title, 'is mandatory') }
+
+ it { expect(content_entry.errors[:title]).to eq(['is mandatory']) }
+
+ end
+
+ end
+
+ describe '#_label' do
+
+ subject { content_entry._label }
+ it { is_expected.to eq 'Hello world' }
+
+ end
+
+ describe '#content_type_slug' do
+
+ subject { content_entry.content_type_slug }
+ it { is_expected.to eq 'articles' }
+
+ end
+
+ # describe '#localized_attributes' do
+
+ # subject { content_entry.localized_attributes }
+ # it { is_expected.to include :seo_title }
+ # it { is_expected.to include :title }
+ # it { is_expected.to include :_slug }
+
+ # end
+
+ describe 'dynamic attributes' do
+
+ let(:field_type) { :string }
+ let(:attributes) { { my_field: value } }
+ let(:field) { instance_double('Field', name: :my_field, type: field_type) }
+
+ before { allow(type).to receive(:fields_by_name).and_return(my_field: field) }
+
+ subject { content_entry.my_field }
+
+ describe 'unable to cast it' do
+
+ let(:field_type) { :float }
+ let(:value) { [] }
+ it { is_expected.to eq nil }
+
+ end
+
+ context 'no provided value, should return nil' do
+
+ let(:attributes) { {} }
+ it { is_expected.to eq nil }
+
+ end
+
+ context 'a string' do
+ let(:value) { 'Hello world' }
+ it { is_expected.to eq 'Hello world' }
+ context 'localized' do
+ let(:value) { build_i18n_field(en: 'Hello world', fr: 'Bonjour monde') }
+ it { expect(subject.translations).to eq('en' => 'Hello world', 'fr' => 'Bonjour monde') }
+ end
+ end
+
+ context 'an integer' do
+ let(:field_type) { :integer }
+ let(:value) { '42' }
+ it { is_expected.to eq 42 }
+ context 'localized' do
+ let(:value) { build_i18n_field(en: 42, fr: '42') }
+ it { expect(subject.translations).to eq('en' => 42, 'fr' => 42) }
+ end
+ end
+
+ context 'a float' do
+ let(:field_type) { :float }
+ let(:value) { '42.0' }
+ it { is_expected.to eq 42.0 }
+ context 'localized' do
+ let(:value) { build_i18n_field(en: 42.0, fr: '42.0') }
+ it { expect(subject.translations).to eq('en' => 42.0, 'fr' => 42.0) }
+ end
+ end
+
+ context 'a date' do
+ let(:field_type) { :date }
+ let(:value) { '2007/06/29' }
+ let(:date) { Date.parse('2007/06/29') }
+ it { is_expected.to eq date }
+ context 'localized' do
+ let(:value) { build_i18n_field(en: '2007/06/29', fr: date) }
+ it { expect(subject.translations).to eq('en' => date, 'fr' => date) }
+ end
+ end
+
+ context 'a date time' do
+ let(:field_type) { :date_time }
+ let(:value) { '2007/06/29 00:00:00' }
+ let(:datetime) { DateTime.parse('2007/06/29 00:00:00') }
+ it { is_expected.to eq datetime }
+ context 'localized' do
+ let(:value) { build_i18n_field(en: '2007/06/29 00:00:00', fr: datetime) }
+ it { expect(subject.translations).to eq('en' => datetime, 'fr' => datetime) }
+ end
+ end
+
+ context 'a file' do
+ let(:field_type) { :file }
+ let(:value) { 'foo.png' }
+ it { is_expected.to eq({ 'url' => 'foo.png' }) }
+ context 'localized' do
+ let(:value) { build_i18n_field(en: 'foo-en.png', fr: 'foo-fr.png') }
+ it { expect(subject.translations).to eq('en' => { 'url' => 'foo-en.png' }, 'fr' => { 'url' => 'foo-fr.png' }) }
+ end
+ end
+
+ context 'a belongs_to relationship' do
+ let(:field_type) { :belongs_to }
+ let(:value) { 'john-doe' }
+ it { expect(subject.type).to eq :belongs_to }
+ it { expect(subject.target_slugs).to eq ['john-doe'] }
+ it { expect(subject.source).to eq content_entry }
+ it { expect(subject.field).to eq field }
+ end
+
+ context 'a has_many relationship' do
+ let(:field_type) { :has_many }
+ let(:value) { nil }
+ it { expect(subject.type).to eq :has_many }
+ it { expect(subject.target_slugs).to eq [] }
+ it { expect(subject.source).to eq content_entry }
+ it { expect(subject.field).to eq field }
+ end
+
+ context 'a many_to_many relationship' do
+ let(:field_type) { :many_to_many }
+ let(:value) { ['john-doe', 'jane-doe'] }
+ it { expect(subject.type).to eq :many_to_many }
+ it { expect(subject.target_slugs).to eq ['john-doe', 'jane-doe'] }
+ it { expect(subject.source).to eq content_entry }
+ it { expect(subject.field).to eq field }
+ end
+
+ end
+
+ def build_i18n_field(translations = {})
+ Locomotive::Steam::Models::I18nField.new(:my_field, translations)
+ end
+
+ end
spec/unit/entities/content_type_spec.rb +9 -1
@@ @@ -3,9 +3,10 @@ require 'spec_helper'
describe Locomotive::Steam::ContentType do
let(:fields) { [instance_double('Field1', label: 'Title', name: :title, localized: false), instance_double('Field2', label: 'Author', name: :author, localized: true)] }
+ let(:repository) { instance_double('FieldRepository', all: fields, first: fields.first) }
let(:content_type) { described_class.new(name: 'Articles') }
- before { allow(content_type).to receive(:fields).and_return(fields) }
+ before { allow(content_type).to receive(:fields).and_return(repository) }
describe '#label_field_name' do
@@ @@ -21,6 +22,13 @@ describe Locomotive::Steam::ContentType do
end
+ describe '#fields_by_name' do
+
+ subject { content_type.fields_by_name }
+ it { expect(subject.keys).to eq [:title, :author] }
+
+ end
+
# describe '#localized_fields_names' do
# subject { content_type.localized_fields_names }
spec/unit/entities/page_spec.rb +1 -1
@@ @@ -3,7 +3,7 @@ require 'spec_helper'
describe Locomotive::Steam::Page do
let(:attributes) { {} }
- let(:page) { Locomotive::Steam::Page.new(attributes) }
+ let(:page) { described_class.new(attributes) }
describe '#index?' do
spec/unit/entities/site_spec.rb +1 -1
@@ @@ -3,7 +3,7 @@ require 'spec_helper'
describe Locomotive::Steam::Site do
let(:attributes) { {} }
- let(:site) { Locomotive::Steam::Site.new(attributes) }
+ let(:site) { described_class.new(attributes) }
describe '#handle' do
spec/unit/models/mapper_spec.rb +1 -1
@@ @@ -6,7 +6,7 @@ describe Locomotive::Steam::Models::Mapper do
let(:name) { 'pages' }
let(:options) { { entity: MyPage } }
let(:block) { nil }
- let(:mapper) { Locomotive::Steam::Models::Mapper.new(name, options, repository, &block) }
+ let(:mapper) { described_class.new(name, options, repository, &block) }
describe '#localized attributes' do
spec/unit/models/scope_spec.rb +27 -0
@@ @@ -0,0 +1,27 @@
+ require 'spec_helper'
+
+ describe Locomotive::Steam::Models::Scope do
+
+ let(:site) { instance_double('Site', _id: 1) }
+ let(:locale) { :en }
+ let(:context) { nil }
+ let(:scope) { described_class.new(site, locale, context) }
+
+ describe '#to_key' do
+
+ subject { scope.to_key }
+
+ it { is_expected.to eq 'site_1' }
+
+ context 'with a content type for instance' do
+
+ let(:content_type) { instance_double('ContentType', _id: 42) }
+ let(:context) { { content_type: content_type } }
+
+ it { is_expected.to eq 'site_1_content_type_42' }
+
+ end
+
+ end
+
+ end
spec/unit/repositories/content_entry_repository_spec.rb +269 -0
@@ @@ -0,0 +1,269 @@
+ require 'spec_helper'
+
+ require_relative '../../../lib/locomotive/steam/adapters/filesystem.rb'
+
+ describe Locomotive::Steam::ContentEntryRepository do
+
+ let(:type) { instance_double('Articles', _id: 1, slug: 'articles', order_by: nil, label_field_name: :title, localized_fields_names: [:title], fields_by_name: { title: instance_double('Field', name: :title, type: :string) }) }
+ let(:entries) { [{ content_type_id: 1, _position: 0, _label: 'Update #1', title: { fr: 'Mise a jour #1' }, text: { en: 'added some free stuff', fr: 'phrase FR' }, date: '2009/05/12', category: 'General' }] }
+ let(:locale) { :en }
+ let(:site) { instance_double('Site', _id: 1, default_locale: :en, locales: %i(en fr)) }
+ let(:adapter) { Locomotive::Steam::FilesystemAdapter.new(nil) }
+
+ let(:content_type_repository) { instance_double('ContentTypeRepository') }
+ let(:repository) { described_class.new(adapter, site, locale, content_type_repository) }
+
+ before do
+ allow(adapter).to receive(:collection).and_return(entries)
+ adapter.cache = NoCacheStore.new
+ end
+
+ describe '#all' do
+
+ let(:conditions) { nil }
+
+ subject { repository.all(type, conditions) }
+
+ it { expect(subject.size).to eq 1 }
+
+ describe 'first element' do
+
+ subject { repository.all(type, conditions).first }
+
+ it { expect(subject.class).to eq Locomotive::Steam::ContentEntry }
+ it { expect(subject._label.translations).to eq('en' => 'Update #1', 'fr' => 'Mise a jour #1') }
+ it { expect(subject._slug.translations).to eq('en' => 'update-number-1', 'fr' => 'mise-a-jour-number-1') }
+ it { expect(subject.title.translations).to eq('en' => 'Update #1', 'fr' => 'Mise a jour #1') }
+ it { expect(subject.content_type).to eq type }
+
+ end
+
+ end
+
+ # describe '#build' do
+
+ # let(:attributes) { { title: 'Hello world' } }
+ # subject { repository.build(type, attributes) }
+
+ # it { expect(subject.title).to eq 'Hello world' }
+
+ # end
+
+ # describe '#persist' do
+
+ # let(:entry) { instance_double('NewEntry', _visible: true, content_type: type, _label: 'Hello world', attributes: { title: 'Hello world' }) }
+ # subject { repository.persist(entry) }
+
+ # before do
+ # expect(entry).to receive(:[]).with(:_slug).and_return(nil)
+ # expect(entry).to receive(:[]=).with(:_slug, 'hello-world')
+ # expect(loader).to receive(:write).with(type, { title: 'Hello world' })
+ # end
+
+ # it { expect { subject }.to change { repository.all(type).size }.by(1) }
+
+ # end
+
+ # describe '#exists?' do
+
+ # let(:conditions) { {} }
+ # subject { repository.exists?(type, conditions) }
+
+ # it { expect(subject).to eq true }
+
+ # context 'more specific conditions' do
+
+ # let(:conditions) { { '_slug' => 'update-number-1' } }
+ # it { expect(subject).to eq true }
+
+ # end
+
+ # context 'conditions which do match any entries' do
+
+ # let(:conditions) { { '_slug' => 'foo' } }
+ # it { expect(subject).to eq false }
+
+ # end
+
+ # end
+
+ # describe '#by_slug' do
+
+ # let(:slug) { nil }
+ # subject { repository.by_slug(type, slug) }
+
+ # it { is_expected.to eq nil }
+
+ # context 'existing slug' do
+ # let(:slug) { 'update-number-1' }
+ # it { expect(subject.title).to eq({ en: 'Update #1', fr: 'Mise a jour #1' }) }
+ # end
+
+ # end
+
+ # describe '#value_for' do
+
+ # let(:name) { :title }
+ # let(:entry) { instance_double('Article', title: 'Hello world') }
+
+ # subject { repository.value_for(name, entry) }
+
+ # it { is_expected.to eq 'Hello world' }
+
+ # describe 'association do' do
+
+ # let(:author_type) { instance_double('AuthorType') }
+ # let(:entry) { instance_double('Article', _slug: 'hello-world', author: association, authors: association) }
+
+ # before do
+ # allow(content_type_repository).to receive(:by_slug).with(:authors).and_return(:author_type)
+ # end
+
+ # context 'belongs_to association' do
+
+ # let(:association) { instance_double('Association', type: :belongs_to, association: true, target_class_slug: :authors, target_slugs: ['john-doe'], order_by: nil) }
+ # let(:name) { :author }
+
+ # before do
+ # expect(repository).to receive(:by_slug).with(:author_type, 'john-doe').and_return('John Doe')
+ # end
+
+ # it { expect(subject).to eq 'John Doe' }
+
+ # end
+
+ # context 'has_many association' do
+
+ # let(:association) { instance_double('Association', type: :has_many, association: true, target_class_slug: :authors, target_field: :article, order_by: 'created_at') }
+ # let(:name) { :authors }
+
+ # before do
+ # allow(association).to receive(:source).and_return(entry)
+ # expect(repository).to receive(:all).with(:author_type, { article: 'hello-world', order_by: 'created_at' }).and_return(%w(jane john))
+ # end
+
+ # it { expect(subject).to eq %w(jane john) }
+
+ # end
+
+ # context 'many_to_many association' do
+
+ # let(:association) { instance_double('Association', type: :many_to_many, association: true, target_class_slug: :authors, target_slugs: %w(jane john), order_by: nil) }
+ # let(:name) { :authors }
+
+ # before do
+ # expect(repository).to receive(:all).with(:author_type, { '_slug.in' => %w(jane john) }).and_return(%w(jane john))
+ # end
+
+ # it { expect(subject).to eq %w(jane john) }
+
+ # end
+
+ # end
+
+ # end
+
+ # describe '#next' do
+
+ # let(:type) { instance_double('Articles', slug: 'articles', order_by: '_position asc', label_field_name: :title, localized_fields_names: [:title], fields_by_name: { title: instance_double('Field', name: :title, type: :string) }) }
+ # let(:entries) do
+ # [
+ # { content_type: type, _position: 0, _label: 'Update #1', title: { fr: 'Mise a jour #1' }, text: { en: 'added some free stuff', fr: 'phrase FR' }, date: '2009/05/12', category: 'General' },
+ # { content_type: type, _position: 1, _label: 'Update #2', title: { fr: 'Mise a jour #2' }, text: { en: 'bla bla', fr: 'blabbla' }, date: '2009/05/12', category: 'General' },
+ # { content_type: type, _position: 2, _label: 'Update #3', title: { fr: 'Mise a jour #2' }, text: { en: 'bla bla', fr: 'blabbla' }, date: '2009/05/12', category: 'General' }
+ # ]
+ # end
+
+ # let(:entry) { nil }
+ # subject { repository.next(entry) }
+
+ # it { is_expected.to eq nil }
+
+ # context 'being last' do
+
+ # let(:entry) { instance_double('Entry', content_type: type, _position: 2) }
+ # it { repository.send(:collection, type).inspect; is_expected.to eq nil }
+
+ # end
+
+ # context 'being middle' do
+
+ # let(:entry) { instance_double('Entry', content_type: type, _position: 1) }
+ # it { expect(subject._position).to eq 2 }
+
+ # end
+
+ # end
+
+ # describe '#previous' do
+
+ # let(:type) { instance_double('Articles', slug: 'articles', order_by: '_position asc', label_field_name: :title, localized_fields_names: [:title], fields_by_name: { title: instance_double('Field', name: :title, type: :string) }) }
+ # let(:entries) do
+ # [
+ # { content_type: type, _position: 0, _label: 'Update #1', title: { fr: 'Mise a jour #1' }, text: { en: 'added some free stuff', fr: 'phrase FR' }, date: '2009/05/12', category: 'General' },
+ # { content_type: type, _position: 1, _label: 'Update #2', title: { fr: 'Mise a jour #2' }, text: { en: 'bla bla', fr: 'blabbla' }, date: '2009/05/12', category: 'General' },
+ # { content_type: type, _position: 2, _label: 'Update #3', title: { fr: 'Mise a jour #2' }, text: { en: 'bla bla', fr: 'blabbla' }, date: '2009/05/12', category: 'General' }
+ # ]
+ # end
+
+ # let(:entry) { nil }
+ # subject { repository.previous(entry) }
+
+ # it { is_expected.to eq nil }
+
+ # context 'being first' do
+
+ # let(:entry) { instance_double('Entry', content_type: type, _position: 0) }
+ # it { repository.send(:collection, type).inspect; is_expected.to eq nil }
+
+ # end
+
+ # context 'being middle' do
+
+ # let(:entry) { instance_double('Entry', content_type: type, _position: 1) }
+ # it { expect(subject._position).to eq 0 }
+
+ # end
+
+ # end
+
+ # describe '#group_by_select_option' do
+
+ # let(:type) { nil }
+ # let(:name) { nil }
+
+ # subject { repository.group_by_select_option(type, name) }
+
+ # it { is_expected.to eq({}) }
+
+ # context 'select field' do
+
+ # let(:fields) do
+ # {
+ # title: instance_double('TitleField', name: :title, type: :string),
+ # category: instance_double('SelectField', name: :category, type: :select, select_options: { en: ['cooking', 'bread'], fr: ['cuisine', 'pain'] })
+ # }
+ # end
+ # let(:type) { instance_double('Articles', slug: 'articles', order_by: '_position asc', label_field_name: :title, localized_fields_names: [:title, :category], fields_by_name: fields) }
+ # let(:name) { :category }
+
+ # let(:entries) do
+ # [
+ # { content_type: type, _position: 0, _label: 'Recipe #1', category: 'cooking' },
+ # { content_type: type, _position: 1, _label: 'Recipe #2', category: 'bread' },
+ # { content_type: type, _position: 2, _label: 'Recipe #3', category: 'bread' },
+ # { content_type: type, _position: 3, _label: 'Recipe #4', category: 'unknown' }
+ # ]
+ # end
+
+ # before { allow(content_type_repository).to receive(:select_options).and_return(%w(cooking wine bread)) }
+
+ # it { expect(subject.size).to eq 4 }
+ # it { expect(subject.map { |h| h[:name] }).to eq ['cooking', 'wine', 'bread', nil] }
+ # it { expect(subject.map { |h| h[:entries].size }).to eq [1, 0, 2, 1] }
+
+ # end
+
+ # end
+
+ end
spec/unit/repositories/filesystem/content_type_spec.rb +0 -130
@@ @@ -1,130 +0,0 @@
- # require 'spec_helper'
-
- # describe Locomotive::Steam::Repositories::Filesystem::ContentType do
-
- # let(:fields) { [{ title: { hint: 'Title of the article', type: 'string' } }, { author: { type: 'string', label: 'Fullname of the author' } }] }
- # let(:loader) { instance_double('Loader', list_of_attributes: [{ slug: 'articles', name: 'Articles', fields: fields }]) }
- # let(:site) { instance_double('Site', default_locale: :en, locales: [:en, :fr]) }
- # let(:locale) { :en }
-
- # let(:repository) { Locomotive::Steam::Repositories::Filesystem::ContentType.new(loader, site, locale) }
-
- # describe '#collection' do
-
- # subject { repository.send(:collection).first }
-
- # it { expect(subject.class).to eq Locomotive::Steam::Repositories::Filesystem::Models::ContentType }
-
- # it 'applies the sanitizer' do
- # expect(subject.name).to eq('Articles')
- # expect(subject.slug).to eq('articles')
- # expect(subject.fields.size).to eq 2
- # expect(subject.fields_by_name.size).to eq 2
- # end
-
- # describe 'a field of the first element' do
-
- # subject { repository.send(:collection).first.fields.first }
-
- # it { expect(subject.class).to eq Locomotive::Steam::Repositories::Filesystem::Models::ContentTypeField }
-
- # it 'has properties' do
- # expect(subject.name).to eq :title
- # expect(subject.label).to eq 'Title'
- # expect(subject.hint).to eq 'Title of the article'
- # expect(subject.type).to eq :string
- # end
-
- # end
-
- # end
-
- # describe '#by_slug' do
-
- # let(:slug) { nil }
- # subject { repository.by_slug(slug) }
-
- # it { is_expected.to eq nil }
-
- # context 'existing content type' do
-
- # let(:slug) { 'articles' }
- # it { expect(subject.name).to eq 'Articles' }
-
- # end
-
- # context 'slug is already a content type' do
-
- # let(:slug) { instance_double('ContentType') }
- # it { is_expected.to eq slug }
-
- # end
-
- # end
-
- # describe '#fields_for' do
-
- # let(:type) { nil }
- # subject { repository.fields_for(type) }
-
- # it { is_expected.to eq nil }
-
- # context 'with fields' do
-
- # let(:type) { instance_double('ContentType', fields: [true]) }
- # it { is_expected.to eq([true]) }
-
- # end
-
- # end
-
- # describe '#look_for_unique_fields' do
-
- # let(:type) { nil }
- # subject { repository.look_for_unique_fields(type) }
-
- # it { is_expected.to eq nil }
-
- # context 'with fields' do
-
- # let(:field) { instance_double('Field', name: :title) }
- # let(:type) { instance_double('ContentType', query_fields: [field])}
-
- # it { expect(subject).to eq(title: field) }
-
- # end
-
- # end
-
- # describe '#select_options' do
-
- # let(:type) { repository.by_slug('articles') }
- # let(:name) { nil }
- # subject { repository.select_options(type, name) }
-
- # it { is_expected.to eq nil }
-
- # context 'a select field' do
-
- # let(:fields) do
- # [
- # { title: { hint: 'Title of the article', type: 'string' } },
- # { category: { type: 'select', select_options: { en: ['cooking', 'bread'], fr: ['cuisine', 'pain'] } } }
- # ]
- # end
-
- # let(:name) { :category }
- # it { is_expected.to eq %w(cooking bread) }
-
- # context 'not a select field' do
-
- # let(:name) { :title }
- # it { is_expected.to eq nil }
-
- # end
-
- # end
-
- # end
-
- # end
spec/unit/repositories/filesystem/models/content_entry_spec.rb +0 -184
@@ @@ -1,184 +0,0 @@
- # require 'spec_helper'
-
- # describe Locomotive::Steam::Repositories::Filesystem::Models::ContentEntry do
-
- # let(:fields) { {} }
- # let(:type) { instance_double('ContentType', slug: 'articles', label_field_name: :title, localized_fields_names: [:title], fields_by_name: fields) }
- # let(:attributes) { { title: 'Hello world', _slug: 'hello-world' } }
- # let(:content_entry) do
- # Locomotive::Steam::Repositories::Filesystem::Models::ContentEntry.new(attributes).tap do |entry|
- # entry.content_type = type
- # end
- # end
-
- # describe '#valid?' do
-
- # let(:fields) { { title: instance_double('TitleField', name: :title, type: :string, required?: true)} }
-
- # subject { content_entry.valid? }
- # it { is_expected.to eq true }
-
- # context 'missing attribute' do
-
- # let(:attributes) { {} }
- # it { is_expected.to eq false }
- # it { subject; expect(content_entry.errors[:title]).to eq(["can't not be blank"]) }
- # it { subject; expect(content_entry.errors.empty?).to eq false }
-
- # end
-
- # describe 'adding a custom error message' do
-
- # before { content_entry.errors.add(:title, 'is mandatory') }
-
- # it { expect(content_entry.errors[:title]).to eq(['is mandatory']) }
-
- # end
-
- # end
-
- # describe '#_label' do
-
- # subject { content_entry._label }
- # it { is_expected.to eq 'Hello world' }
-
- # end
-
- # describe '#_id' do
-
- # subject { content_entry._id }
- # it { is_expected.to eq 'hello-world' }
-
- # end
-
- # describe '#content_type_slug' do
-
- # subject { content_entry.content_type_slug }
- # it { is_expected.to eq 'articles' }
-
- # end
-
- # describe '#localized_attributes' do
-
- # subject { content_entry.localized_attributes }
- # it { is_expected.to include :seo_title }
- # it { is_expected.to include :title }
- # it { is_expected.to include :_slug }
-
- # end
-
- # describe 'dynamic attributes' do
-
- # let(:field_type) { :string }
- # let(:attributes) { { my_field: value } }
- # let(:field) { instance_double('Field', name: :my_field, type: field_type) }
- # before { allow(type).to receive(:fields_by_name).and_return(my_field: field) }
-
- # subject { content_entry.my_field }
-
- # describe 'unable to cast it' do
-
- # let(:field_type) { :float }
- # let(:value) { [] }
- # it { is_expected.to eq nil }
-
- # end
-
- # context 'no provided value, should return nil' do
-
- # let(:attributes) { {} }
- # it { is_expected.to eq nil }
-
- # end
-
- # context 'a string' do
- # let(:value) { 'Hello world' }
- # it { is_expected.to eq 'Hello world' }
- # context 'localized' do
- # let(:value) { { en: 'Hello world', fr: 'Bonjour monde' } }
- # it { is_expected.to eq({ en: 'Hello world', fr: 'Bonjour monde' }) }
- # end
- # end
-
- # context 'an integer' do
- # let(:field_type) { :integer }
- # let(:value) { '42' }
- # it { is_expected.to eq 42 }
- # context 'localized' do
- # let(:value) { { en: 42, fr: '42' } }
- # it { is_expected.to eq({ en: 42, fr: 42 }) }
- # end
- # end
-
- # context 'a float' do
- # let(:field_type) { :float }
- # let(:value) { '42.0' }
- # it { is_expected.to eq 42.0 }
- # context 'localized' do
- # let(:value) { { en: 42.0, fr: '42.0' } }
- # it { is_expected.to eq({ en: 42.0, fr: 42.0 }) }
- # end
- # end
-
- # context 'a date' do
- # let(:field_type) { :date }
- # let(:value) { '2007/06/29' }
- # let(:date) { Date.parse('2007/06/29') }
- # it { is_expected.to eq date }
- # context 'localized' do
- # let(:value) { { en: '2007/06/29', fr: date } }
- # it { is_expected.to eq({ en: date, fr: date }) }
- # end
- # end
-
- # context 'a date time' do
- # let(:field_type) { :date_time }
- # let(:value) { '2007/06/29 00:00:00' }
- # let(:datetime) { DateTime.parse('2007/06/29 00:00:00') }
- # it { is_expected.to eq datetime }
- # context 'localized' do
- # let(:value) { { en: '2007/06/29 00:00:00', fr: datetime } }
- # it { is_expected.to eq({ en: datetime, fr: datetime }) }
- # end
- # end
-
- # context 'a file' do
- # let(:field_type) { :file }
- # let(:value) { 'foo.png' }
- # it { is_expected.to eq({ 'url' => 'foo.png' }) }
- # context 'localized' do
- # let(:value) { { en: 'foo-en.png', fr: 'foo-fr.png' } }
- # it { is_expected.to eq({ en: { 'url' => 'foo-en.png' }, fr: { 'url' => 'foo-fr.png' } }) }
- # end
- # end
-
- # context 'a belongs_to relationship' do
- # let(:field_type) { :belongs_to }
- # let(:value) { 'john-doe' }
- # it { expect(subject.type).to eq :belongs_to }
- # it { expect(subject.target_slugs).to eq ['john-doe'] }
- # it { expect(subject.source).to eq content_entry }
- # it { expect(subject.field).to eq field }
- # end
-
- # context 'a has_many relationship' do
- # let(:field_type) { :has_many }
- # let(:value) { nil }
- # it { expect(subject.type).to eq :has_many }
- # it { expect(subject.target_slugs).to eq [] }
- # it { expect(subject.source).to eq content_entry }
- # it { expect(subject.field).to eq field }
- # end
-
- # context 'a many_to_many relationship' do
- # let(:field_type) { :many_to_many }
- # let(:value) { ['john-doe', 'jane-doe'] }
- # it { expect(subject.type).to eq :many_to_many }
- # it { expect(subject.target_slugs).to eq ['john-doe', 'jane-doe'] }
- # it { expect(subject.source).to eq content_entry }
- # it { expect(subject.field).to eq field }
- # end
-
- # end
-
- # end
spec/unit/repositories/filesystem/models/content_type_spec.rb +0 -50
@@ @@ -1,50 +0,0 @@
- # require 'spec_helper'
-
- # describe Locomotive::Steam::Repositories::Filesystem::Models::ContentType do
-
- # let(:fields) { [instance_double('Field1', label: 'Title', name: :title, localized: false), instance_double('Field2', label: 'Author', name: :author, localized: true)] }
- # let(:content_type) do
- # Locomotive::Steam::Repositories::Filesystem::Models::ContentType.new(name: 'Articles').tap do |type|
- # type.fields = fields
- # end
- # end
-
- # describe '#label_field_name' do
-
- # subject { content_type.label_field_name }
- # it { is_expected.to eq :title }
-
- # context 'defined within the content type itself' do
-
- # before { allow(content_type.attributes).to receive(:[]).with(:label_field_name).and_return('author') }
- # it { is_expected.to eq :author }
-
- # end
-
- # end
-
- # describe '#localized_fields_names' do
-
- # subject { content_type.localized_fields_names }
- # it { is_expected.to eq [:author] }
-
- # end
-
- # describe '#order_by' do
-
- # subject { content_type.order_by }
- # it { is_expected.to eq '_position asc' }
-
- # context 'specifying manually' do
-
- # before do
- # content_type.attributes[:order_by] = 'manually'
- # content_type.attributes[:order_direction] = 'desc'
- # end
- # it { is_expected.to eq '_position desc' }
-
- # end
-
- # end
-
- # end
spec/unit/repositories/filesystem/yaml_loaders/content_entry_spec.rb +0 -22
@@ @@ -1,22 +0,0 @@
- # require 'spec_helper'
-
- # describe Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::ContentEntry do
-
- # let(:root_path) { default_fixture_site_path }
- # let(:cache) { NoCacheStore.new }
- # let(:content_type) { instance_double('Articles', slug: 'bands') }
- # let(:loader) { Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::ContentEntry.new(root_path, cache) }
-
- # describe '#list_of_attributes' do
-
- # subject { loader.list_of_attributes(content_type).sort { |a, b| a[:_label] <=> b[:_label] } }
-
- # it 'tests various stuff' do
- # expect(subject.size).to eq 3
- # expect(subject.first[:_label]).to eq 'Alice in Chains'
- # expect(subject.first[:content_type]).to eq content_type
- # end
-
- # end
-
- # end
spec/unit/repositories/filesystem/yaml_loaders/content_type_spec.rb +0 -20
@@ @@ -1,20 +0,0 @@
- # require 'spec_helper'
-
- # describe Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::ContentType do
-
- # let(:root_path) { default_fixture_site_path }
- # let(:cache) { NoCacheStore.new }
- # let(:loader) { Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::ContentType.new(root_path, cache) }
-
- # describe '#list_of_attributes' do
-
- # subject { loader.list_of_attributes.sort { |a, b| a[:slug] <=> b[:slug] } }
-
- # it 'tests various stuff' do
- # expect(subject.size).to eq 5
- # expect(subject.first[:slug]).to eq('bands')
- # end
-
- # end
-
- # end
spec/unit/repositories/filesystem/yaml_loaders/page_spec.rb +0 -21
@@ @@ -1,21 +0,0 @@
- # require 'spec_helper'
-
- # describe Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::Page do
-
- # let(:root_path) { default_fixture_site_path }
- # let(:default_locale) { :en }
- # let(:cache) { NoCacheStore.new }
- # let(:loader) { Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::Page.new(root_path, default_locale, cache) }
-
- # describe '#list_of_attributes' do
-
- # subject { loader.list_of_attributes.sort { |a, b| a[:_fullpath] <=> b[:_fullpath] } }
-
- # it 'tests various stuff' do
- # expect(subject.size).to eq 21
- # expect(subject.first[:title]).to eq({ en: 'Page not found' })
- # end
-
- # end
-
- # end
spec/unit/repositories/filesystem/yaml_loaders/site_spec.rb +0 -17
@@ @@ -1,17 +0,0 @@
- # require 'spec_helper'
-
- # describe Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::Site do
-
- # let(:root_path) { default_fixture_site_path }
- # let(:cache) { NoCacheStore.new }
- # let(:loader) { Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::Site.new(root_path, cache) }
-
- # describe '#attributes' do
-
- # subject { loader.attributes }
-
- # it { expect(subject[:name]).to eq 'Sample website' }
-
- # end
-
- # end
spec/unit/repositories/filesystem/yaml_loaders/snippet_spec.rb +0 -23
@@ @@ -1,23 +0,0 @@
- # require 'spec_helper'
-
- # describe Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::Snippet do
-
- # let(:root_path) { default_fixture_site_path }
- # let(:default_locale) { :en }
- # let(:cache) { NoCacheStore.new }
- # let(:loader) { Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::Snippet.new(root_path, default_locale, cache) }
-
- # describe '#list_of_attributes' do
-
- # subject { loader.list_of_attributes.sort { |a, b| a[:name] <=> b[:name] } }
-
- # it 'tests various stuff' do
- # expect(subject.size).to eq 4
- # expect(subject.first[:slug]).to eq('a_complicated-one')
- # expect(subject[1][:name]).to eq('Footer')
- # expect(subject[1][:slug]).to eq('footer')
- # end
-
- # end
-
- # end
spec/unit/repositories/filesystem/yaml_loaders/translation_spec.rb +0 -21
@@ @@ -1,21 +0,0 @@
- # require 'spec_helper'
-
- # describe Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::Translation do
-
- # let(:root_path) { default_fixture_site_path }
- # let(:cache) { NoCacheStore.new }
- # let(:loader) { Locomotive::Steam::Repositories::Filesystem::YAMLLoaders::Translation.new(root_path, cache) }
-
- # describe '#list_of_attributes' do
-
- # subject { loader.list_of_attributes }
-
- # it 'tests various stuff' do
- # expect(subject.size).to eq 1
- # expect(subject.first[:key]).to eq('powered_by')
- # expect(subject.first[:values]).to eq({ 'en' => 'Powered by', 'fr' => 'Propulsé par' })
- # end
-
- # end
-
- # end