require 'spec_helper' describe 'Locomotive::Steam::Liquid::Tags::Nav' do let(:index) { instance_double('IndexPage', fullpath: 'index', published: true) } let(:depth_1) do [ instance_double('Child1', title: 'Child #1', slug: 'child-1', fullpath: 'child-1', published?: true, listed?: true, templatized?: false, localized_attributes: [], to_liquid: { 'title' => 'Child #1' }), instance_double('Child2', title: 'Child #2', slug: 'child-2', fullpath: 'child-2', published?: true, listed?: true, templatized?: false, localized_attributes: [], to_liquid: { 'title' => 'Child #2' }) ] end let(:depth_2) do [ instance_double('Child2_1', title: 'Child #2.1', slug: 'child-2-1', fullpath: 'child-2/child-2-1', published?: true, listed?: true, templatized?: false, localized_attributes: []), instance_double('Child2_2', title: 'Child #2.2', slug: 'child-2-2', fullpath: 'child-2/child-2-2', published?: true, listed?: true, templatized?: false, localized_attributes: []), instance_double('UnpublishedChild2_3', title: 'Child #2.3', slug: 'child-2-3', fullpath: 'child-2/child-2-3', published?: false, listed?: true, templatized?: false, localized_attributes: []), instance_double('TemplatizedChild2_4', title: 'Child #2.4', slug: 'child-2-4', fullpath: 'child-2/child-2-4', published?: true, listed?: true, templatized?: true, localized_attributes: []), instance_double('UnlistedChild2_4', title: 'Child #2.5', slug: 'child-2-5', fullpath: 'child-2/child-2-5', published?: true, listed?: false, templatized?: false, localized_attributes: []) ] end let(:prefix_default) { false } let(:source) { '{% nav site %}' } let(:site) { instance_double('Site', name: 'My portfolio', default_locale: 'en', prefix_default_locale: prefix_default) } let(:page) { index } let(:services) { Locomotive::Steam::Services.build_instance } let(:repository) { services.repositories.page } let(:assigns) { {} } let(:registers) { { services: services, site: site, page: page } } let(:context) { ::Liquid::Context.new(assigns, {}, registers) } let(:options) { { services: services } } let(:output) { render_template(source, context, options) } before { allow(services).to receive(:current_site).and_return(site) } describe 'rendering' do subject { output } describe 'from a site' do before do allow(repository).to receive(:root).and_return(index) allow(repository).to receive(:children_of).with(index).and_return(depth_1) end it { is_expected.to eq %{<nav id="nav"><ul><li id="child-1-link" class="link first"><a href="/child-1">Child #1</a></li>\n<li id="child-2-link" class="link last"><a href="/child-2">Child #2</a></li></ul></nav>} } context 'prefix_default_locale is true' do let(:prefix_default) { true } it { is_expected.to eq %{<nav id="nav"><ul><li id="child-1-link" class="link first"><a href="/en/child-1">Child #1</a></li>\n<li id="child-2-link" class="link last"><a href="/en/child-2">Child #2</a></li></ul></nav>} } end end describe 'from a page' do let(:source) { '{% nav page %}' } before do allow(repository).to receive(:children_of).with(index).and_return(depth_1) end it { is_expected.to eq %{<nav id="nav"><ul><li id="child-1-link" class="link first"><a href="/child-1">Child #1</a></li>\n<li id="child-2-link" class="link last"><a href="/child-2">Child #2</a></li></ul></nav>} } end describe 'from the parent page' do let(:source) { '{% nav parent %}' } describe 'no parent page, use the current page instead' do before do allow(repository).to receive(:parent_of).with(index).and_return(nil) allow(repository).to receive(:children_of).with(index).and_return(depth_1) end it { is_expected.to eq %{<nav id="nav"><ul><li id="child-1-link" class="link first"><a href="/child-1">Child #1</a></li>\n<li id="child-2-link" class="link last"><a href="/child-2">Child #2</a></li></ul></nav>} } end end describe 'from a page' do let(:source) { '{% nav index %}' } describe 'no parent page, use the current page instead' do before do allow(repository).to receive(:by_fullpath).with('index').and_return(index) allow(repository).to receive(:children_of).with(index).and_return(depth_1) end it { is_expected.to eq %{<nav id="nav"><ul><li id="child-1-link" class="link first"><a href="/child-1">Child #1</a></li>\n<li id="child-2-link" class="link last"><a href="/child-2">Child #2</a></li></ul></nav>} } end end describe 'no wrapper' do let(:source) { '{% nav site, no_wrapper: true %}' } before do allow(repository).to receive(:root).and_return(index) allow(repository).to receive(:children_of).with(index).and_return(depth_1) end it { is_expected.to eq %{<li id="child-1-link" class="link first"><a href="/child-1">Child #1</a></li>\n<li id="child-2-link" class="link last"><a href="/child-2">Child #2</a></li>} } end describe 'with icons' do before do allow(repository).to receive(:root).and_return(index) allow(repository).to receive(:children_of).with(index).and_return(depth_1) end describe 'before' do let(:source) { '{% nav site, icon: before, no_wrapper: true %}' } it { is_expected.to include %{<li id="child-1-link" class="link first"><a href="/child-1"><span></span> Child #1</a></li>} } end describe 'after' do let(:source) { '{% nav site, icon: after, no_wrapper: true %}' } it { is_expected.to include %{<li id="child-1-link" class="link first"><a href="/child-1">Child #1 <span></span></a></li>} } end end describe 'including the second levels of pages (depth = 2)' do let(:source) { '{% nav site, depth: 2 %}' } before do allow(repository).to receive(:root).and_return(index) allow(repository).to receive(:children_of).with(index).and_return(depth_1) allow(repository).to receive(:children_of).with(depth_1.first).and_return([]) allow(repository).to receive(:children_of).with(depth_1.last).and_return(depth_2) end it { is_expected.to eq %{<nav id="nav"><ul><li id="child-1-link" class="link first"><a href="/child-1">Child #1</a></li>\n<li id="child-2-link" class="link last"><a href="/child-2">Child #2</a><ul id="nav-child-2"><li id="child-2-1-link" class="link first"><a href="/child-2/child-2-1">Child #2.1</a></li>\n<li id="child-2-2-link" class="link last"><a href="/child-2/child-2-2">Child #2.2</a></li></ul></li></ul></nav>} } describe 'with bootstrap' do let(:source) { '{% nav site, bootstrap: true, depth: 2 %}' } it { is_expected.to eq %{<nav id="nav"><ul><li id="child-1-link" class="link first"><a href="/child-1">Child #1</a></li>\n<li id="child-2-link" class="link last dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Child #2 <b class="caret"></b></a><ul id="nav-child-2" class="dropdown-menu"><li id="child-2-1-link" class="link first"><a href="/child-2/child-2-1">Child #2.1</a></li>\n<li id="child-2-2-link" class="link last"><a href="/child-2/child-2-2">Child #2.2</a></li></ul></li></ul></nav>} } end describe 'excluding pages' do let(:source) { '{% nav site, depth: 2, exclude: "child-2/child-2-2" %}' } it { is_expected.to eq %{<nav id="nav"><ul><li id="child-1-link" class="link first"><a href="/child-1">Child #1</a></li>\n<li id="child-2-link" class="link last"><a href="/child-2">Child #2</a><ul id="nav-child-2"><li id="child-2-1-link" class="link first last"><a href="/child-2/child-2-1">Child #2.1</a></li></ul></li></ul></nav>} } end end describe 'using a snippet to render the title' do let(:source) { %({% nav site, snippet: "{{page.title}}!" %}) } before do allow(repository).to receive(:root).and_return(index) allow(repository).to receive(:children_of).with(index).and_return(depth_1) allow(repository).to receive(:root).and_return(index) end it { is_expected.to include %{<a href="/child-1">Child #1!</a>} } describe 'from a registered snippet' do let(:source) { %({% nav site, snippet: nav_title %}) } let(:snippet) { instance_double('Snippet', liquid_source: '{{ page.title }}!') } before do allow(services.snippet_finder).to receive(:find).with('nav_title').and_return(snippet) end it { is_expected.to include %{<a href="/child-1">Child #1!</a>} } context "the snippet doesn't exist" do let(:snippet) { nil } it { is_expected.to include %{<a href="/child-1">Child #1</a>} } end end end describe 'changing the dom id and the class' do let(:source) { %({% nav site, id: "main-nav", class: "nav" %}) } before do allow(repository).to receive(:root).and_return(index) allow(repository).to receive(:children_of).with(index).and_return(depth_1) end it { is_expected.to include %{<nav id="main-nav" class="nav">} } end describe 'assigning a class other than "on" for a selected item' do let(:source) { %({% nav parent, active_class: "active" %}) } let(:page) { depth_1.first } before do allow(repository).to receive(:parent_of).with(page).and_return(index) allow(repository).to receive(:children_of).with(index).and_return(depth_1) end it { is_expected.to include %{<li id="child-1-link" class="link active first">} } end describe 'localizing the links' do let(:source) { %({% nav parent, active_class: "active" %}) } before do services.url_builder.current_locale = 'fr' allow(repository).to receive(:parent_of).with(page).and_return(index) allow(repository).to receive(:children_of).with(index).and_return(depth_1) end it { is_expected.to include %{<nav id="nav"><ul><li id="child-1-link" class="link first"><a href="/fr/child-1">Child #1</a></li>\n<li id="child-2-link" class="link last"><a href="/fr/child-2">Child #2</a></li></ul></nav>} } end end end