Nav Tag spec round 1
arnaud sellenet
committed Jun 17, 2014
commit 4161b6649952e160941c794095b6e550548893a3
Showing 2
changed files with
175 additions
and 22 deletions
locomotive/steam/liquid/tags/nav.rb b/lib/locomotive/steam/liquid/tags/nav.rb
+24
-22
| @@ | @@ -16,7 +16,7 @@ module Locomotive |
| Syntax = /(#{::Liquid::Expression}+)?/ | |
| - | attr_accessor :current_page, :mounting_point |
| + | attr_accessor :current_page, :site |
| def initialize(tag_name, markup, tokens, options) | |
| if markup =~ Syntax | |
| @@ | @@ -32,7 +32,6 @@ module Locomotive |
| def render(context) | |
| self.set_accessors_from_context(context) | |
| - | |
| entries = self.fetch_entries | |
| output = self.build_entries_output(entries) | |
| @@ | @@ -72,17 +71,19 @@ module Locomotive |
| # @return [ Array ] List of pages | |
| # | |
| def fetch_entries | |
| - | children = (case @source |
| - | when 'site' then self.mounting_point.pages['index'] |
| + | children = root.children.try(:clone) || [] |
| + | children.delete_if { |p| !include_page?(p) } |
| + | end |
| + | |
| + | def root |
| + | case @source |
| + | when 'site' then Locomotive::Models['pages']['index'] |
| when 'parent' then self.current_page.parent || self.current_page | |
| when 'page' then self.current_page | |
| else | |
| - | self.mounting_point.pages[@source] |
| - | end).children.try(:clone) || [] |
| - | |
| - | children.delete_if { |p| !include_page?(p) } |
| + | Locomotive::Models['pages'][@source] |
| + | end |
| end | |
| - | |
| # Determine whether or not a page should be a part of the menu. | |
| # | |
| # @param [ Object ] page The page | |
| @@ | @@ -93,7 +94,7 @@ module Locomotive |
| if !page.listed? || page.templatized? || !page.published? | |
| false | |
| elsif @_options[:exclude] | |
| - | (page.fullpath =~ @_options[:exclude]).nil? |
| + | (page.fullpath[:en] =~ @_options[:exclude]).nil? |
| else | |
| true | |
| end | |
| @@ | @@ -106,7 +107,7 @@ module Locomotive |
| # @return [ Boolean ] | |
| # | |
| def page_selected?(page) | |
| - | self.current_page.fullpath =~ /^#{page.fullpath}(\/.*)?$/ |
| + | self.current_page.fullpath[:en] =~ /^#{page.fullpath[:en]}(\/.*)?$/ |
| end | |
| # Determine if the children of a page have to be rendered or not. | |
| @@ | @@ -131,7 +132,7 @@ module Locomotive |
| # | |
| def entry_label(page) | |
| icon = @_options[:icon] ? '<span></span>' : '' | |
| - | title = @_options[:liquid_render] ? @_options[:liquid_render].render('page' => page) : page.title |
| + | title = @_options[:liquid_render] ? @_options[:liquid_render].render('page' => page) : page.title[::I18n.locale] |
| if icon.blank? | |
| title | |
| @@ | @@ -149,10 +150,10 @@ module Locomotive |
| # @return [ String ] The localized url | |
| # | |
| def entry_url(page) | |
| - | if ::I18n.locale.to_s == self.mounting_point.default_locale.to_s |
| - | "/#{page.fullpath}" |
| + | if ::I18n.locale.to_s == self.site.default_locale.to_s |
| + | "/#{page.fullpath[::I18n.locale]}" |
| else | |
| - | "/#{::I18n.locale}/#{page.fullpath}" |
| + | "/#{::I18n.locale}/#{page.fullpath[::I18n.locale]}" |
| end | |
| end | |
| @@ | @@ -165,7 +166,8 @@ module Locomotive |
| # | |
| def entry_css(page, css = '') | |
| _css = 'link' | |
| - | _css += " #{page} #{@_options[:active_class]}" if self.page_selected?(page) |
| + | #_css += " #{page} #{@_options[:active_class]}" if self.page_selected?(page) |
| + | _css += " #{@_options[:active_class]}" if self.page_selected?(page) |
| (_css + " #{css}").strip | |
| end | |
| @@ | @@ -191,7 +193,7 @@ module Locomotive |
| options = %{ class="dropdown-toggle" data-toggle="dropdown"} | |
| end | |
| - | self.render_tag(:li, id: "#{page.slug.to_s.dasherize}-link", css: css) do |
| + | self.render_tag(:li, id: "#{page.slug[::I18n.locale].to_s.dasherize}-link", css: css) do |
| children_output = depth.succ <= @_options[:depth].to_i ? self.render_entry_children(page, depth.succ) : '' | |
| %{<a href="#{url}"#{options}>#{label}</a>} + children_output | |
| end | |
| @@ | @@ -209,7 +211,7 @@ module Locomotive |
| css = self.bootstrap? ? 'dropdown-menu' : '' | |
| unless entries.empty? | |
| - | self.render_tag(:ul, id: "#{@_options[:id]}-#{page.slug.to_s.dasherize}", css: css) do |
| + | self.render_tag(:ul, id: "#{@_options[:id]}-#{page.slug[::I18n.locale].dasherize}", css: css) do |
| self.build_entries_output(entries, depth) | |
| end | |
| else | |
| @@ | @@ -234,11 +236,11 @@ module Locomotive |
| end | |
| # Avoid to call context.registers to get the current page | |
| - | # and the mounting point. |
| + | # and the site. |
| # | |
| def set_accessors_from_context(context) | |
| self.current_page = context.registers[:page] | |
| - | self.mounting_point = context.registers[:mounting_point] |
| + | self.site = context.registers[:site] |
| end | |
| # Parse the template of the snippet give in option of the tag. | |
| @@ | @@ -249,7 +251,7 @@ module Locomotive |
| source = if template_name.include?('{') | |
| template_name | |
| else | |
| - | context[:mounting_point].snippets[template_name].try(:source) |
| + | context[:site].snippets[template_name].try(:source) |
| end | |
| source ? ::Liquid::Template.parse(source) : nil | |
| @@ | @@ -284,4 +286,4 @@ module Locomotive |
| end | |
| end | |
| end | |
| - | end |
| \ No newline at end of file | |
| + | end |
spec/unit/liquid/tags/nav_spec.rb
+151
-0
| @@ | @@ -0,0 +1,151 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Liquid::Tags::Nav do |
| + | |
| + | subject { Locomotive::Steam::Liquid::Tags::Nav } |
| + | let(:entity_class) { Locomotive::Steam::Entities::Page } |
| + | let(:site_class) { Locomotive::Steam::Entities::Site } |
| + | let(:home) { entity_class.new fullpath: { en: 'index' }} |
| + | let(:site) { site_class.new locales: %w(en fr) } |
| + | |
| + | before do |
| + | home_children = [ |
| + | entity_class.new(title: { en: 'Child #1' }, fullpath: { en: 'child_1' }, slug: { en: 'child_1' }, published: true, listed: true), |
| + | entity_class.new(title: { en: 'Child #2' }, fullpath: { en: 'child_2' }, slug: { en: 'child_2' }, published: true, listed: true) |
| + | ] |
| + | home.stub(children: home_children) |
| + | |
| + | other_children = [ |
| + | entity_class.new(title: { en: 'Child #2.1' }, fullpath: { en: 'child_2/sub_child_1' }, slug: { en: 'sub_child_1' }, published: true, listed: true), |
| + | entity_class.new(title: { en: 'Child #2.2' }, fullpath: { en: 'child_2/sub_child_2' }, slug: { en: 'sub_child_2' }, published: true, listed: true), |
| + | entity_class.new(title: { en: 'Unpublished #2.2' }, fullpath: { en: 'child_2/sub_child_unpublishd_2' }, slug: { en: 'sub_child_unpublished_2' }, published: false, listed: true), |
| + | entity_class.new(title: { en: 'Templatized #2.3' }, fullpath: { en: 'child_2/sub_child_template_3' }, slug: { en: 'sub_child_template_3' }, published: true, templatized: true, listed: true), |
| + | entity_class.new(title: { en: 'Unlisted #2.4' }, fullpath: { en: 'child_2/sub_child_unlisted_4' }, slug: { en: 'sub_child_unlisted_4' }, published: true, listed: false) |
| + | ] |
| + | home.children.last.stub(children: other_children) |
| + | |
| + | pages = [home] |
| + | Locomotive::Models['pages'].stub(root: pages) |
| + | Locomotive::Models['pages'].stub(all: pages) |
| + | Locomotive::Models['pages'].stub(:[]).with('index').and_return home |
| + | end |
| + | |
| + | context '#rendering' do |
| + | |
| + | it 'renders from site' do |
| + | render_nav.should == '<nav id="nav"><ul><li id="child-1-link" class="link first"><a href="/child_1">Child #1</a></li><li id="child-2-link" class="link last"><a href="/child_2">Child #2</a></li></ul></nav>' |
| + | end |
| + | |
| + | it 'renders from page' do |
| + | render_nav('page').should == '<nav id="nav"><ul><li id="child-1-link" class="link first"><a href="/child_1">Child #1</a></li><li id="child-2-link" class="link last"><a href="/child_2">Child #2</a></li></ul></nav>' |
| + | end |
| + | |
| + | it 'renders from parent' do |
| + | (page = home.children.last.children.first).stub(parent: home.children.last) |
| + | output = render_nav 'parent', { page: page } |
| + | output.should == '<nav id="nav"><ul><li id="sub-child-1-link" class="link on first"><a href="/child_2/sub_child_1">Child #2.1</a></li><li id="sub-child-2-link" class="link last"><a href="/child_2/sub_child_2">Child #2.2</a></li></ul></nav>' |
| + | end |
| + | |
| + | it 'renders children to depth' do |
| + | output = render_nav('site', {}, 'depth: 2') |
| + | |
| + | output.should match(/<nav id="nav">/) |
| + | output.should match(/<ul>/) |
| + | output.should match(/<li id="child-1-link" class="link first">/) |
| + | output.should match(/<\/a><ul id="nav-child-2">/) |
| + | output.should match(/<li id="sub-child-1-link" class="link first">/) |
| + | output.should match(/<li id="sub-child-2-link" class="link last">/) |
| + | output.should match(/<\/a><\/li><\/ul><\/li><\/ul><\/nav>/) |
| + | end |
| + | |
| + | it 'does not render templatized pages' do |
| + | output = render_nav('site', {}, 'depth: 2') |
| + | |
| + | output.should_not match(/sub-child-template-3/) |
| + | end |
| + | |
| + | it 'does not render unpublished pages' do |
| + | output = render_nav('site', {}, 'depth: 2') |
| + | |
| + | output.should_not match(/sub-child-unpublished-3/) |
| + | end |
| + | |
| + | it 'does not render unlisted pages' do |
| + | output = render_nav('site', {}, 'depth: 2') |
| + | |
| + | output.should_not match(/sub-child-unlisted-3/) |
| + | end |
| + | |
| + | it 'does not render nested excluded pages' do |
| + | output = render_nav('site', {}, 'depth: 2, exclude: "child_2/sub_child_2"') |
| + | |
| + | output.should match(/<li id="child-2-link" class="link last">/) |
| + | output.should match(/<li id="sub-child-1-link" class="link first last">/) |
| + | output.should_not match(/sub-child-2/) |
| + | |
| + | output = render_nav('site', {}, 'depth: 2, exclude: "child_2"') |
| + | |
| + | output.should match(/<li id="child-1-link" class="link first last">/) |
| + | output.should_not match(/child-2/) |
| + | output.should_not match(/sub-child/) |
| + | end |
| + | |
| + | it 'adds an icon before the link' do |
| + | render_nav('site', {}, 'icon: true') |
| + | .should match(/<li id="child-1-link" class="link first"><a href="\/child_1"><span><\/span> Child #1<\/a>/) |
| + | render_nav('site', {}, 'icon: before') |
| + | .should match(/<li id="child-1-link" class="link first"><a href="\/child_1"><span><\/span> Child #1<\/a>/) |
| + | end |
| + | |
| + | it 'adds an icon after the link' do |
| + | render_nav('site', {}, 'icon: after') |
| + | .should match(/<li id="child-1-link" class="link first"><a href="\/child_1">Child #1 <span><\/span><\/a><\/li>/) |
| + | end |
| + | |
| + | it 'renders a snippet for the title' do |
| + | render_nav('site', {}, 'snippet: "-{{page.title}} {{ foo.png | theme_image_tag }}-"') |
| + | .should match( /<li id="child-1-link" class="link first"><a href="\/child_1">-Child #1 <img src=\"\" >-<\/a><\/li>/) |
| + | end |
| + | |
| + | it 'assigns a different dom id' do |
| + | render_nav('site', {}, 'id: "main-nav"') |
| + | .should match(/<nav id="main-nav">/) |
| + | end |
| + | |
| + | it 'assigns a class' do |
| + | render_nav('site', {}, 'class: "nav"') |
| + | .should match(/<nav id="nav" class="nav">/) |
| + | end |
| + | |
| + | it 'assigns a class other than "on" for a selected item' do |
| + | (page = @home.children.last.children.first).stubs(:parent).returns(@home.children.last) |
| + | output = render_nav 'parent', { page: page }, 'active_class: "active"' |
| + | output.should match(/<li id="sub-child-1-link" class="link active first">/) |
| + | end |
| + | |
| + | it 'excludes entries based on a regexp' do |
| + | render_nav('page', {}, 'exclude: "child_1"').should == '<nav id="nav"><ul><li id="child-2-link" class="link first last"><a href="/child_2">Child #2</a></li></ul></nav>' |
| + | end |
| + | |
| + | it 'does not render the parent ul' do |
| + | render_nav('site', {}, 'no_wrapper: true') |
| + | .should_not match(/<ul id="nav">/) |
| + | end |
| + | |
| + | it 'localizes the links' do |
| + | I18n.with_locale('fr') do |
| + | render_nav.should == '<nav id="nav"><ul><li id="child-1-link" class="link first"><a href="/fr/child_1">Child #1</a></li><li id="child-2-link" class="link last"><a href="/fr/child_2">Child #2</a></li></ul></nav>' |
| + | end |
| + | end |
| + | |
| + | end |
| + | |
| + | def render_nav(source = 'site', registers = {}, template_option = '') |
| + | registers = { site: site, page: home }.merge(registers) |
| + | liquid_context = ::Liquid::Context.new({}, {}, registers) |
| + | |
| + | output = Liquid::Template.parse("{% nav #{source} #{template_option} %}").render(liquid_context) |
| + | output.gsub(/\n\s{0,}/, '') |
| + | end |
| + | |
| + | end |