module SimpleNavigation describe Helpers do subject(:controller) { test_controller_class.new } let(:invoices_item) { navigation[:invoices] } let(:item) { nil } let(:navigation) { setup_navigation('nav_id', 'nav_class') } let(:test_controller_class) do Class.new { include SimpleNavigation::Helpers } end let(:unpaid_item) { invoices_item.sub_navigation[:unpaid] } before do allow(Configuration).to receive(:eval_config) allow(SimpleNavigation).to receive_messages(load_config: nil, primary_navigation: navigation, config_file?: true, context_for_eval: controller) select_an_item(navigation[item]) if item end describe '#active_navigation_item_name' do context 'when no item is selected' do it 'returns an empty string for no parameters' do expect(controller.active_navigation_item_name).to eq '' end it "returns an empty string for level: 1" do item_name = controller.active_navigation_item_name(level: 1) expect(item_name).to eq '' end it 'returns an empty string for level: 2' do item_name = controller.active_navigation_item_name(level: 2) expect(item_name).to eq '' end it 'returns an empty string for level: :all' do item_name = controller.active_navigation_item_name(level: :all) expect(item_name).to eq '' end end context 'when an item is selected' do context "and it's a primary item" do let(:item) { :invoices } it 'returns an empty string' do expect(controller.active_navigation_item_name).to eq '' end it "returns the selected item's name for level: 1" do item_name = controller.active_navigation_item_name(level: 1) expect(item_name).to eq 'Invoices' end it 'returns an empty string for level: 2' do item_name = controller.active_navigation_item_name(level: 2) expect(item_name).to eq '' end it 'returns an empty string for level: :all' do item_name = controller.active_navigation_item_name(level: :all) expect(item_name).to eq '' end end context "and it's a sub navigation item" do before do select_an_item(invoices_item) select_an_item(unpaid_item) end it "returns the selected item's name" do expect(controller.active_navigation_item_name).to eq 'Unpaid' end it "returns the selected item's parent name for level: 1" do item_name = controller.active_navigation_item_name(level: 1) expect(item_name).to eq 'Invoices' end it "returns the selected item's name for level: 2" do item_name = controller.active_navigation_item_name(level: 2) expect(item_name).to eq 'Unpaid' end it "returns the selected item's name for level: :all" do item_name = controller.active_navigation_item_name(level: :all) expect(item_name).to eq 'Unpaid' end end end end describe '#active_navigation_item_key' do context 'when no item is selected' do it 'returns nil' do expect(controller.active_navigation_item_key).to be_nil end it 'returns nil for no parameters' do expect(controller.active_navigation_item_key).to be_nil end it "returns nil for level: 1" do item_key = controller.active_navigation_item_key(level: 1) expect(item_key).to be_nil end it 'returns nil for level: 2' do item_key = controller.active_navigation_item_key(level: 2) expect(item_key).to be_nil end it 'returns nil for level: :all' do item_key = controller.active_navigation_item_key(level: :all) expect(item_key).to be_nil end end context 'when an item is selected' do context "and it's a primary item" do let(:item) { :invoices } it 'returns nil for no parameters' do expect(controller.active_navigation_item_key).to be_nil end it "returns the selected item's name for level: 1" do item_key = controller.active_navigation_item_key(level: 1) expect(item_key).to eq :invoices end it 'returns nil for level: 2' do item_key = controller.active_navigation_item_key(level: 2) expect(item_key).to be_nil end it 'returns nil for level: :all' do item_key = controller.active_navigation_item_key(level: :all) expect(item_key).to be_nil end end context "and it's a sub navigation item" do before do select_an_item(invoices_item) select_an_item(unpaid_item) end it "returns the selected item's name" do expect(controller.active_navigation_item_key).to eq :unpaid end it "returns the selected item's parent name for level: 1" do item_key = controller.active_navigation_item_key(level: 1) expect(item_key).to eq :invoices end it "returns the selected item's name for level: 2" do item_key = controller.active_navigation_item_key(level: 2) expect(item_key).to eq :unpaid end it "returns the selected item's name for level: :all" do item_key = controller.active_navigation_item_key(level: :all) expect(item_key).to eq :unpaid end end end end describe '#active_navigation_item' do context 'when no item is selected' do it 'returns nil for no parameters' do expect(controller.active_navigation_item).to be_nil end it "returns nil for level: 1" do item_key = controller.active_navigation_item(level: 1) expect(item_key).to be_nil end it 'returns nil for level: 2' do item_key = controller.active_navigation_item(level: 2) expect(item_key).to be_nil end it 'returns nil for level: :all' do item_key = controller.active_navigation_item(level: :all) expect(item_key).to be_nil end end context 'when an item is selected' do context "and it's a primary item" do let(:item) { :invoices } it 'returns nil for no parameters' do expect(controller.active_navigation_item).to be_nil end it "returns the selected item's name for level: 1" do item_key = controller.active_navigation_item(level: 1) expect(item_key).to be invoices_item end it 'returns nil for level: 2' do item_key = controller.active_navigation_item(level: 2) expect(item_key).to be_nil end it 'returns nil for level: :all' do item_key = controller.active_navigation_item(level: :all) expect(item_key).to be_nil end end context "and it's a sub navigation item" do before do select_an_item(invoices_item) select_an_item(unpaid_item) end it "returns the selected item's name for no parameters" do expect(controller.active_navigation_item).to be unpaid_item end it "returns the selected item's parent name for level: 1" do item_key = controller.active_navigation_item(level: 1) expect(item_key).to be invoices_item end it "returns the selected item's name for level: 2" do item_key = controller.active_navigation_item(level: 2) expect(item_key).to eq unpaid_item end it "returns the selected item's name for level: :all" do item_key = controller.active_navigation_item(level: :all) expect(item_key).to eq unpaid_item end end end end describe '#active_navigation_item_container' do shared_examples 'returning items container' do it 'returns the primary navigation for no parameters' do expect(controller.active_navigation_item_container).to be navigation end it "returns the primary navigation for level: 1" do item_container = controller.active_navigation_item_container(level: 1) expect(item_container).to be navigation end it 'returns the primary navigation level: :all' do item_container = controller.active_navigation_item_container(level: :all) expect(item_container).to be navigation end end context 'when no item is selected' do it_behaves_like 'returning items container' it 'returns nil for level: 2' do item_container = controller.active_navigation_item_container(level: 2) expect(item_container).to be_nil end end context 'when an item is selected' do context "and it's a primary item" do let(:item) { :invoices } it_behaves_like 'returning items container' it 'returns the invoices items container for level: 2' do item_container = controller.active_navigation_item_container(level: 2) expect(item_container).to be invoices_item.sub_navigation end end context "and it's a sub navigation item" do before do select_an_item(invoices_item) select_an_item(unpaid_item) end it_behaves_like 'returning items container' it 'returns the invoices items container for level: 2' do item_container = controller.active_navigation_item_container(level: 2) expect(item_container).to be invoices_item.sub_navigation end end end end describe '#render_navigation' do it 'evaluates the configuration on every request' do expect(SimpleNavigation).to receive(:load_config).twice 2.times { controller.render_navigation } end it 'loads the :default configuration' do expect(SimpleNavigation).to receive(:load_config).with(:default) controller.render_navigation end it "doesn't set the items directly" do expect(SimpleNavigation.config).not_to receive(:items) controller.render_navigation end it 'looks up the active_item_container based on the level' do expect(SimpleNavigation).to receive(:active_item_container_for) .with(:all) controller.render_navigation end context 'when the :context option is specified' do it 'loads the configuration for the specified context' do expect(SimpleNavigation).to receive(:load_config).with(:my_context) controller.render_navigation(context: :my_context) end end context 'when the :items option is specified' do let(:items) { double(:items) } it 'sets the items directly' do expect(SimpleNavigation.config).to receive(:items).with(items) controller.render_navigation(items: items) end end context 'when the :level option is set' do context 'and its value is 1' do it 'calls render on the primary navigation' do expect(navigation).to receive(:render).with(level: 1) controller.render_navigation(level: 1) end end context 'and its value is 2' do context 'and the active_item_container is set' do let(:item_container) { double(:container).as_null_object } before do allow(SimpleNavigation).to receive_messages(active_item_container_for: item_container) end it 'finds the selected sub navigation for the specified level' do expect(SimpleNavigation).to receive(:active_item_container_for) .with(2) controller.render_navigation(level: 2) end it 'calls render on the active item_container' do expect(item_container).to receive(:render).with(level: 2) controller.render_navigation(level: 2) end end context "and the active_item_container isn't set" do it "doesn't raise an exception" do expect{ controller.render_navigation(level: 2) }.not_to raise_error end end end context "and its value isn't a valid level" do it 'raises an exception' do expect{ controller.render_navigation(level: :invalid) }.to raise_error(ArgumentError, 'Invalid navigation level: invalid') end end end context 'when the :levels option is set' do before { allow(SimpleNavigation).to receive_messages(active_item_container_for: navigation) } it 'treats it like the :level option' do expect(navigation).to receive(:render).with(level: 2) controller.render_navigation(levels: 2) end end context 'when a block is given' do it 'calls the block passing it an item container' do expect{ |blk| controller.render_navigation(&blk) }.to yield_with_args(ItemContainer) end end context 'when no primary configuration is defined' do before { allow(SimpleNavigation).to receive_messages(primary_navigation: nil) } it 'raises an exception' do expect{controller.render_navigation}.to raise_error(RuntimeError, 'no primary navigation defined, either use a navigation config file or pass items directly to render_navigation') end end context "when active_item_container is set" do let(:active_item_container) { double(:container).as_null_object } before do allow(SimpleNavigation).to receive_messages(active_item_container_for: active_item_container) end it 'calls render on the active_item_container' do expect(active_item_container).to receive(:render) controller.render_navigation end end end end end