tweak the form UI (errors, input separator) + add more tests

This commit is contained in:
did 2011-07-01 02:15:45 +02:00
parent e560c71ee5
commit 812965ad50
37 changed files with 286 additions and 108 deletions

View File

@ -25,7 +25,7 @@ gem 'locomotive_carrierwave', '0.5.4.beta3'
gem 'dragonfly', '~> 0.9.1'
gem 'rack-cache', :require => 'rack/cache'
gem 'custom_fields', '1.0.0.beta.19'
gem 'custom_fields', '1.0.0.beta.20'
gem 'cancan'
gem 'fog', '0.8.2'
gem 'mimetype-fu'

View File

@ -85,7 +85,7 @@ GEM
capybara (>= 1.0.0)
cucumber (~> 1.0.0)
nokogiri (>= 1.4.6)
custom_fields (1.0.0.beta.19)
custom_fields (1.0.0.beta.20)
activesupport (>= 3.0.7)
mongoid (= 2.0.2)
daemons (1.1.4)
@ -283,7 +283,7 @@ DEPENDENCIES
cancan
capybara
cucumber-rails (= 1.0.2)
custom_fields (= 1.0.0.beta.19)
custom_fields (= 1.0.0.beta.20)
database_cleaner
delayed_job (= 2.1.4)
delayed_job_mongoid (= 1.0.2)

View File

@ -3,7 +3,7 @@
= include_stylesheets :fancybox
= f.inputs :name => :information do
= f.input :name
= f.input :name, :wrapper_html => { :class => 'highlighted' }
= f.input :slug
= f.input :description
@ -13,10 +13,9 @@
= f.foldable_inputs :name => :presentation, :class => 'switchable' do
= f.input :highlighted_field_name, :as => :select, :collection => options_for_highlighted_field(f.object, 'contents'), :include_blank => false
= f.input :group_by_field_name, :as => :select, :collection => options_for_group_by_field(f.object, 'contents')
= f.custom_input :raw_item_template, :css => 'small-code' do
= f.custom_input :item_template, :css => 'small-code' do
%code{ :class => 'html' }
= f.text_area :raw_item_template, :class => 'small'
= f.errors_on :item_template
= f.foldable_inputs :name => :options, :class => 'switchable' do
= f.input :order_by, :as => :select, :collection => options_for_order_by(f.object, 'contents'), :include_blank => false

View File

@ -2,8 +2,9 @@
= form.inputs :name => title || :attributes do
- form.object.custom_fields.each do |field|
- required = highlighted_field_name == field._name || field.required
- highlighted = highlighted_field_name == field._name
- required = highlighted || field.required
= render "/admin/custom_fields/types/#{field.kind}", :form => form, :parent => parent, :field => field, :required => required
= render "/admin/custom_fields/types/#{field.kind}", :form => form, :parent => parent, :field => field, :required => required, :highlighted => highlighted
= render '/admin/custom_fields/category_tmpl'

View File

@ -1,2 +1,2 @@
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'toggle' do
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'toggle', :required => required do
= form.check_box field._alias.to_sym

View File

@ -1,4 +1,4 @@
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'toggle' do
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'toggle', :required => required do
= form.select field._name.to_sym, field.ordered_category_items.collect { |item| [item.name, item.id] }
%button.button.light.edit-categories-link{ :type => 'button', :'data-url' => edit_admin_custom_field_path(parent.class.model_name.underscore, parent.slug, field) }
%span!= t('.edit_categories')

View File

@ -1 +1 @@
= form.input field._alias.to_sym, :label => field.label, :hint => field.hint, :input_html => { :class => 'date' }
= form.input :"formatted_#{field._alias}", :label => field.label, :hint => field.hint, :input_html => { :class => 'date' }, :wrapper_html => { :class => 'date' }, :required => required

View File

@ -1,4 +1,4 @@
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'file' do
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'file', :required => required do
= form.file_field field._name.to_sym
- if form.object.send(:"#{field._name}?")
%p.remove

View File

@ -1,6 +1,6 @@
- field.target.constantize.reload_parent! # to make sure all the contents from the parent are loaded
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'has-many' do
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'has-many', :required => required do
.has-many-selector

View File

@ -2,5 +2,5 @@
- selected_id = form.object.send(field._alias.to_sym).try(:_id)
= form.input field._alias.to_sym, :label => field.label, :hint => field.hint, :input_html => { :class => 'has_one' }, :as => :select, :collection => options_for_has_one(field, selected_id), :selected => selected_id
= form.input field._alias.to_sym, :label => field.label, :hint => field.hint, :input_html => { :class => 'has_one' }, :as => :select, :collection => options_for_has_one(field, selected_id), :selected => selected_id, :required => required

View File

@ -1 +1 @@
= form.input field._alias.to_sym, :label => field.label, :hint => field.hint, :required => required
= form.input field._alias.to_sym, :label => field.label, :hint => field.hint, :required => required, :wrapper_html => { :class => "#{'highlighted' if highlighted}" }

View File

@ -6,12 +6,12 @@
= f.foldable_inputs :name => :information do
= f.input :title
= f.input :title, :wrapper_html => { :class => 'highlighted' }
- if not @page.index? and not @page.not_found?
= f.input :parent_id, :as => :select, :collection => parent_pages_options, :include_blank => false
= f.input :slug, :required => false, :hint => @page.slug.blank? ? ' ' : page_url(@page), :input_html => { :'data-url' => get_path_admin_pages_url, :disabled => @page.index? || @page.not_found? }, :wrapper_html => { :style => "#{'display: none' if @page.templatized?}; height: 50px" }
= f.input :slug, :required => false, :hint => @page.slug.blank? ? ' ' : page_url(@page), :input_html => { :'data-url' => get_path_admin_pages_url, :disabled => @page.index? || @page.not_found? }, :wrapper_html => { :style => "#{'display: none' if @page.templatized?};" }
= render 'editable_elements', :page => @page
@ -23,9 +23,9 @@
- if can?(:manage, @page)
= f.foldable_inputs :name => :advanced_options do
= f.foldable_inputs :name => :advanced_options, :id => 'advanced-options' do
= f.input :content_type_id, :as => :select, :collection => current_site.content_types.all.to_a, :include_blank => false, :wrapper_html => { :style => "#{'display: none' unless @page.templatized?}; height: 50px" }
= f.input :content_type_id, :as => :select, :collection => current_site.content_types.all.to_a, :include_blank => false, :wrapper_html => { :style => "#{'display: none' unless @page.templatized?}" }
= f.custom_input :templatized, :css => 'toggle', :style => "#{'display: none' if @page.redirect?}" do
= f.check_box :templatized

View File

@ -39,7 +39,7 @@ en:
reset: Reset site
default_site_template: "Use the default site template. Click <a href='#'>here</a> to upload a site template as a zip file instead."
content_type:
raw_item_template: Item template
item_template: Item template
api_accounts: Notified Accounts
content_instance:
_slug: Permalink
@ -91,7 +91,7 @@ en:
samples: "If enabled, the import process will also copy contents and assets"
reset: "If enabled, all the data of your site will be destroyed before importing the new site"
content_type:
raw_item_template: "You can customize the text displayed for each item in the list. Simply use Liquid. Ex: {{ content.name }})"
item_template: "You can customize the text displayed for each item in the list. Simply use Liquid. Ex: {{ content.name }})"
api_enabled: "It is used to let people from outside to create new instances (example: messages in a contact form)"
api_accounts: "A notification email will be sent to each of the accounts listed above when a new instance is created"

View File

@ -41,7 +41,7 @@ fr:
samples: Copier contenu
reset: Remettre à zéro
content_type:
raw_item_template: Template d'affichage
item_template: Template d'affichage
api_accounts: Comptes à notifier
content_instance:
_slug: Permalink
@ -93,6 +93,6 @@ fr:
reset: "Si activé, toutes les données de votre site seront détruites avant l'import du nouveau site"
content_type:
slug: Nom utilisé dans les templates liquid afin d'accéder aux enregistrements de ce modèle
raw_item_template: "Personnaliser le texte affiché pour chaque élément de la liste. Utilisez simplement du code Liquid. Ex: {{ content.name }}"
item_template: "Personnaliser le texte affiché pour chaque élément de la liste. Utilisez simplement du code Liquid. Ex: {{ content.name }}"
api_enabled: "Utilisé pour autoriser la création de nouvelles instances de l'extérieur (ex.: les messages dans un formulaire de contact)"
api_accounts: "Un email de notification sera envoyé à chaque compte listé ci-dessus lors de la création d'une nouvelle instance"

View File

@ -45,17 +45,21 @@ x cancan: (authors / designers / admin)
x theme asset
x features / specs
x enable rack-cache only for a specific url
- check hosting:
x more cucumber tests for the content types
x check hosting:
x heroku
- bushi.do
- deploy => okay
- unable to reach the console
- unable to set a new subdomain
- convert existing templates (the 2 of the themes section)
- liquid tag: Date.today (now), add a test to compare 2 dates
x bushi.do
x unable to reach the console
x deploy => okay
x unable to set a new subdomain
x liquid tag: Date.today (now), add a test to compare 2 dates
x better ui: increase text field length (auto sizable ?) + refactor error message
- tinyMCE => fullscreen
- icon for redirection page in the pages section (back-office)
- more cucumber tests for the content types
- rake task to import a remote template
- bug: duplicate fields (new entry) when errors in the content type form
- test and/or convert existing templates (the 2 of the themes section)
=> MERGE
@ -63,7 +67,7 @@ x enable rack-cache only for a specific url
- heroku: unable to upload a new file => okay
- import => okay
- delete an item => okay
- better ui: increase text field length + refactor error message
- overide sort for contents
BACKLOG:

View File

@ -13,7 +13,7 @@ Given %r{^I have "([^"]*)" as "([^"]*)" values of the "([^"]*)" model$} do |valu
field = content_type.content_custom_fields.detect { |f| f.label == field }
field.should_not be_nil
if field.kind == 'category'
if field.category?
values.split(',').collect(&:strip).each do |name|
field.category_items.build :name => name
end

View File

@ -4,29 +4,29 @@ module Locomotive
module Date
def localized_date(input, *args)
format, locale = args[0], args[1] rescue 'en'
return '' if input.blank?
return input.to_s if format.to_s.empty?
format, locale = args
locale ||= I18n.locale
format ||= I18n.t('date.formats.default', :locale => locale)
if input.is_a?(String)
begin
fragments = ::Date._strptime(input, I18n.t('date.formats.default'))
date = ::Date.new(fragments[:year], fragments[:mon], fragments[:mday])
fragments = ::Date._strptime(input, format)
input = ::Date.new(fragments[:year], fragments[:mon], fragments[:mday])
rescue
date = Time.parse(input)
input = Time.parse(input)
end
else
date = input
end
if date.respond_to?(:strftime)
I18n.locale = locale
I18n.l date, :format => format
else
input
end
return input.to_s unless input.respond_to?(:strftime)
I18n.l input, :format => format, :locale => locale
end
alias :format_date :localized_date
end
::Liquid::Template.register_filter(Date)

View File

@ -34,6 +34,12 @@ module Locomotive
end
end
def error_sentence(errors, options = {}) #:nodoc:
error_class = options[:error_class] || default_inline_error_class
error_msg = template.content_tag(:p, Formtastic::Util.html_safe(errors.to_sentence.untaint))
template.content_tag(:div, error_msg, :class => error_class)
end
# FIXME (Did): allows to pass attributes to the I18n translation key
def inline_hints_for(method, options) #:nodoc:
options[:hint] = localized_string(method, options[:hint], :hint, options[:hint_options] || {})

View File

@ -64,7 +64,8 @@ module Locomotive
'current_page' => self.params[:page],
'params' => self.params,
'url' => request.url,
'now' => Date.today
'now' => Time.now,
'today' => Date.today
}.merge(flash.stringify_keys) # data from api
if @page.templatized? # add instance from content type

View File

@ -40,7 +40,7 @@ Gem::Specification.new do |s|
s.add_dependency "dragonfly", "~> 0.9.1"
s.add_dependency "rack-cache"
s.add_dependency "custom_fields", "1.0.0.beta.19"
s.add_dependency "custom_fields", "1.0.0.beta.20"
s.add_dependency "cancan", "~> 1.6.0"
s.add_dependency "fog", "0.8.2"
s.add_dependency "mimetype-fu"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

View File

@ -80,15 +80,6 @@ $(document).ready(function() {
if ((css = $('#submenu > ul').attr('class')) != '')
$('#submenu > ul > li.' + css).addClass('on');
// form
$('.formtastic li input, .formtastic li textarea, .formtastic li code, .formtastic li select').focus(function() {
$('.formtastic li.error:not(.code) p.inline-errors').fadeOut(200);
if ($(this).parent().hasClass('error')) {
$(this).nextAll('p.inline-errors').show();
}
});
$('.formtastic li.error input').eq(0).focus();
// nifty code editor
$('code.html textarea').each(function() { addCodeMirrorEditor('liquid', $(this)); });
@ -119,7 +110,7 @@ $(document).ready(function() {
var parent = $(this).parent(), content = $(this).next();
if (parent.hasClass('folded')) {
parent.removeClass('folded');
content.slideDown('fast', function() { });
content.slideDown('fast', function() { parent.trigger('refresh'); });
} else
content.slideUp('fast', function() { parent.addClass('folded'); });
});
@ -132,4 +123,7 @@ $(document).ready(function() {
$('#site-selector').parent().submit();
} });
$('.formtastic fieldset.inputs').bind('refresh', function(e) { $(this).find('ol li:not(.item)').removeClass('last').filter(':visible').last().addClass('last'); })
.trigger('refresh');
});

View File

@ -25,15 +25,18 @@ $(document).ready(function() {
// console.log('subscribing...');
var lastFieldset = $('.formtastic.content_type fieldset').last();
$.subscribe('toggle.content_type_api_enabled.checked', function(event, data) {
// console.log('checked');
$('#content_type_api_accounts_input').show();
lastFieldset.trigger('refresh');
}, []);
$.subscribe('toggle.content_type_api_enabled.unchecked', function(event, data) {
// console.log('unchecked');
$('#content_type_api_accounts_input').hide();
lastFieldset.trigger('refresh');
}, []);
});

View File

@ -5,7 +5,7 @@ $(document).ready(function() {
var index = parseInt($(this).attr('href').match(/block-(.+)/)[1]);
$('#editable-elements .wrapper ul li.block').hide();
$('#block-' + index).show();
$('#block-' + index).show().find('fieldset').trigger('refresh');
$(this).parent().find('.on').removeClass('on');
$(this).addClass('on');

View File

@ -52,16 +52,20 @@ $(document).ready(function() {
// redirect feature
var advancedSettingsFieldset = $('.formtastic.page fieldset#advanced-options');
$.subscribe('toggle.page_redirect.checked', function(event, data) {
$('#page_templatized').parent('li').hide();
$('#page_cache_strategy_input').hide();
$('#page_redirect_url_input').show();
advancedSettingsFieldset.trigger('refresh');
}, []);
$.subscribe('toggle.page_redirect.unchecked', function(event, data) {
$('#page_templatized').parent('li').show();
$('#page_cache_strategy_input').show();
$('#page_redirect_url_input').hide();
advancedSettingsFieldset.trigger('refresh');
}, []);
// automatic slug from page title

View File

@ -0,0 +1,61 @@
/*!
* Autogrow Textarea Plugin Version v2.0
* http://www.technoreply.com/autogrow-textarea-plugin-version-2-0
*
* Copyright 2011, Jevin O. Sewaruth
*
* Date: March 13, 2011
*/
jQuery.fn.autoGrow = function(){
return this.each(function(){
// Variables
var colsDefault = this.cols;
var rowsDefault = this.rows;
//Functions
var grow = function() {
growByRef(this);
}
var growByRef = function(obj) {
var linesCount = 0;
var lines = obj.value.split('\n');
for (var i=lines.length-1; i>=0; --i)
{
linesCount += Math.floor((lines[i].length / colsDefault) + 1);
}
if (linesCount >= rowsDefault)
obj.rows = linesCount + 1;
else
obj.rows = rowsDefault;
}
var characterWidth = function (obj){
var characterWidth = 0;
var temp1 = 0;
var temp2 = 0;
var tempCols = obj.cols;
obj.cols = 1;
temp1 = obj.offsetWidth;
obj.cols = 2;
temp2 = obj.offsetWidth;
characterWidth = temp2 - temp1;
obj.cols = tempCols;
return characterWidth;
}
// Manipulations
this.style.width = "auto";
this.style.height = "auto";
this.style.overflow = "hidden";
this.style.width = ((characterWidth(this) * this.cols) + 6) + "px";
this.onkeyup = grow;
this.onfocus = grow;
this.onblur = grow;
growByRef(this);
});
};

View File

@ -3,6 +3,9 @@
var enableFileOrTextToggling = function() {
$('div.hidden').hide();
var fileSelectorFieldset = $('div#file-selector fieldset');
var textSelectorFieldset = $('div#text-selector fieldset');
$('span.alt').click(function(event) {
event.preventDefault();
@ -10,11 +13,13 @@ var enableFileOrTextToggling = function() {
$("div#text-selector").slideUp("normal", function() {
$("div#file-selector").slideDown();
$("input#theme_asset_performing_plain_text").val(false);
fileSelectorFieldset.trigger('refresh');
});
} else {
$("div#file-selector").slideUp("normal", function() {
$("div#text-selector").slideDown();
$("input#theme_asset_performing_plain_text").val(true);
textSelectorFieldset.trigger('refresh');
});
}
});

View File

@ -25,6 +25,15 @@
width: 20%;
}
#fancybox-inner form.formtastic fieldset ol li.string input,
#fancybox-inner form.formtastic fieldset ol li.password input,
#fancybox-inner form.formtastic fieldset ol li.numeric input,
#fancybox-inner form.formtastic fieldset ol li.text textarea,
#fancybox-inner form.formtastic fieldset ol li code textarea,
#fancybox-inner form.formtastic fieldset ol li input[type=password] {
width: 45%;
}
#fancybox-inner form.formtastic fieldset ol li p.inline-hints {
margin-left: 30%;
}

View File

@ -79,7 +79,15 @@ form.formtastic fieldset.inputs ol {
border-top: 1px solid #ccced7;
}
form.formtastic fieldset ol li { width: 100%; position: relative; margin-bottom: 1.3em; }
form.formtastic fieldset ol li { width: 100%; position: relative; margin-bottom: 0.8em; }
form.formtastic fieldset.inputs ol li {
background: url("/images/admin/form/input-sep.png") repeat-x 0 bottom;
margin-bottom: 0.7em;
padding-bottom: 1em;
}
form.formtastic fieldset.inputs ol li.last { background: none; margin-bottom: 0.8em; padding-bottom: 0px; }
form.formtastic fieldset ol li label { text-align: left; padding: 0.4em 2em 0 20px; font-size: 0.8em; width: 15%; color: #585a69; text-shadow: #fff 0px 1px; }
@ -92,74 +100,68 @@ form.formtastic fieldset ol li input[type=password] {
padding: 4px 5px;
font-size: 0.9em;
font-weight: bold;
width: 45%;
width: 700px;
color: #17171b;
background: white url(/images/admin/form/field.png) repeat-x 0 0;
border: 1px solid #a6a8b8;
border: 1px solid #d1d6e6;
-webkit-box-shadow: #f1f1f1 0px 1px;
-moz-box-shadow: #f1f1f1 0px 1px;
box-shadow: #f1f1f1 0px 1px;
}
form.formtastic fieldset ol li.string.highlighted input {
font-size: 1.1em;
width: 696px;
padding: 6px 7px;
}
form.formtastic fieldset ol li.text textarea.html {
height: 300px;
width: 46%;
}
form.formtastic fieldset ol li.date input {
width: 80px;
}
form.formtastic fieldset ol li p.inline-hints { margin-left: 20%; }
form.formtastic fieldset ol li p.inline-hints a { color: #1f82bc; }
form.formtastic fieldset ol li code { display: block; border: 1px solid #a6a8b8; margin: 10px 20px 0 20px; }
form.formtastic fieldset ol li code { display: block; border: 1px solid #d1d6e6; margin: 10px 20px 0 20px; }
form.formtastic fieldset ol li code.nude textarea {
width: 870px;
border: 0px;
}
/*form.formtastic fieldset ol li code.html iframe { width: 46% !important; }*/
form.formtastic fieldset ol li select { font-size: 0.9em; position: relative; top: 2px; color: #787a89; }
form.formtastic fieldset ol li.multiple select { width: 45%; }
form.formtastic fieldset ol li.error input,
form.formtastic fieldset ol li.error textarea,
form.formtastic fieldset ol li.error code iframe { border: 2px solid #ec3f48 !important; }
form.formtastic fieldset ol li.error code { border: none; }
form.formtastic fieldset ol li p.inline-errors {
display: none;
position: absolute;
top: 0px;
left: 630px;
width: 250px;
form.formtastic fieldset ol li div.inline-errors {
background: transparent url(/images/admin/form/error-arrow.png) no-repeat 17px 0;
margin: 2px 0 0 20%;
padding: 8px 0 0 0;
}
form.formtastic fieldset ol li div.inline-errors p {
display: inline-block;
width: auto;
margin: 0px;
padding: 6px 5px 8px 25px;
background: #ec3f48 url(/images/admin/form/error-arrow.png) no-repeat 0 0;
padding: 3px 12px 4px 30px;
color: #fff !important;
font-size: 0.7em !important;
text-shadow: #000 0px 1px;
font-size: 0.9em;
padding-left: 30px;
background: #cd0f19 url(/images/admin/form/icons/error.png) no-repeat 10px 6px;
}
form.formtastic fieldset ol li.code label { display: none; }
form.formtastic fieldset ol li.code p.inline-errors {
display: block;
float: left;
margin: 4px 16px 0 0;
position: relative;
left: 20px;
background-image: none;
form.formtastic fieldset ol li.code div.inline-errors {
margin-left: 20px;
}
form.formtastic fieldset ol li.small-code code { margin: 0px; display: inline-block; width: 75%; }
form.formtastic fieldset ol li.small-code p.inline-errors {
position: relative;
display: block !important;
float: none;
margin-left: 20%;
width: 45%;
margin: 0.5em 0px 0px 20%;
left: 0px;
}
form.formtastic fieldset ol .more { text-align: right; width: auto; margin: 10px 20px 0 0; line-height: 0.6em; }
form.formtastic fieldset ol .more a { text-decoration: none; color: #787A89; font-size: 0.7em; }
@ -309,7 +311,7 @@ form.formtastic fieldset.editable-list ol li.added input:focus {
font-weight: normal;
color: #787a89;
background: white url(/images/admin/form/field.png) repeat-x 0 0;
border: 1px solid #a6a8b8;
border: 1px solid #d1d6e6;
}
form.formtastic fieldset.editable-list ol li.added .inline-errors {
@ -410,10 +412,6 @@ form.formtastic fieldset.validations ol li.added em.key {
/* ___ content instance / editable elements___ */
form.content_instance fieldset ol li.text textarea {
width: 75%;
}
form.formtastic fieldset ol li.file p.remove {
margin: 5px 0 0 20%;
}

View File

@ -60,3 +60,22 @@
font-weight: normal;
}
#panel fieldset ol li div.inline-errors {
background: transparent url(/images/admin/form/error-arrow.png) no-repeat 17px 0;
margin: 2px 0 0 0;
padding: 8px 0 0 0;
}
#panel fieldset ol li div.inline-errors p {
display: inline-block;
width: auto;
margin: 0px;
padding: 3px 12px 4px 30px;
color: #fff !important;
text-shadow: #000 0px 1px;
font-size: 0.9em;
padding-left: 30px;
background: #cd0f19 url(/images/admin/form/icons/error.png) no-repeat 10px 6px;
}

View File

@ -5,8 +5,12 @@ describe Locomotive::Liquid::Drops::Content do
before(:each) do
@site = Factory.build(:site)
content_type = Factory.build(:content_type)
content_type.content_custom_fields.build :label => 'anything', :kind => 'String'
@content = content_type.contents.build(:meta_keywords => 'Libidinous, Angsty', :meta_description => "Quite the combination.")
content_type.content_custom_fields.build :label => 'anything', :kind => 'string'
content_type.content_custom_fields.build :label => 'published_at', :kind => 'date'
@content = content_type.contents.build({
:meta_keywords => 'Libidinous, Angsty',
:meta_description => "Quite the combination.",
:published_at => Date.today })
end
describe 'meta_keywords' do
@ -19,8 +23,27 @@ describe Locomotive::Liquid::Drops::Content do
it { should == @content.meta_description }
end
describe 'date comparaison' do
describe 'older than' do
subject { @content.published_at = 3.days.ago; render_template('{% if content.published_at < today %}In the past{% endif %}') }
it { should == 'In the past' }
end
describe 'more recent than' do
subject { @content.published_at = 1.days.since; render_template('{% if content.published_at > today %}In the future{% endif %}') }
it { should == 'In the future' }
end
describe 'equality' do
subject { render_template('{% if content.published_at == today %}Today{% endif %}') }
it { should == 'Today' }
end
end
def render_template(template = '', assigns = {})
assigns = { 'content' => @content }.merge(assigns)
assigns = { 'content' => @content, 'today' => Date.today }.merge(assigns)
Liquid::Template.parse(template).render(::Liquid::Context.new({}, assigns, { :site => @site }))
end

View File

@ -12,7 +12,7 @@ describe Locomotive::Liquid::Drops::Contents do
render_template '{{ contents.projects }}'
end
context '#group_by' do
describe '#group_by' do
it 'orders contents' do
@site.content_types.stubs(:where).returns([@content_type])

View File

@ -0,0 +1,38 @@
require 'spec_helper'
describe Locomotive::Liquid::Filters::Date do
include Locomotive::Liquid::Filters::Date
before(:each) do
@date = Date.parse('2007/06/29')
end
it 'prints an empty string it is nil or empty' do
localized_date(nil).should == ''
localized_date('').should == ''
end
it 'prints a date' do
localized_date(@date).should == '06/29/2007'
end
it 'prints a date with a custom format' do
localized_date(@date, '%d/%m/%Y').should == '29/06/2007'
end
it 'prints a date depending on the locale' do
I18n.locale = 'fr'
localized_date(@date).should == '29/06/2007'
I18n.locale = 'en'
end
it 'prints a date when forcing the locale' do
localized_date(@date, '%A %d %B %Y', 'fr').should == 'vendredi 29 juin 2007'
end
it 'has an alias for the localized_date filter: format_date' do
format_date(@date).should == '06/29/2007'
end
end

View File

@ -25,7 +25,7 @@ describe Locomotive::Liquid::Filters::Html do
stylesheet_tag('/trash/main.css').should == result
stylesheet_tag('/trash/main').should == result
end
it 'should return a link tag for a stylesheet file and media attribute set to print' do
result = "<link href=\"/sites/000000000000000000000042/theme/stylesheets/main.css\" media=\"print\" rel=\"stylesheet\" type=\"text/css\" />"
stylesheet_tag('main.css','print').should == result
@ -146,6 +146,4 @@ describe Locomotive::Liquid::Filters::Html do
klass.new
end
end

View File

@ -1,4 +1,5 @@
require 'spec_helper'
require 'ostruct'
describe 'Locomotive rendering system' do
@ -11,6 +12,20 @@ describe 'Locomotive rendering system' do
@page = Factory.build(:page, :site => nil, :published => true)
end
context '#liquid_context' do
it 'includes the current date and time' do
@controller.instance_variable_set(:@page, @page)
@controller.stubs(:flash).returns({})
@controller.stubs(:params).returns({})
@controller.stubs(:request).returns(OpenStruct.new(:url => '/'))
context = @controller.send(:locomotive_context)
context['now'].should_not be_blank
context['today'].should_not be_blank
end
end
context 'setting the response' do
before(:each) do