module SimpleNavigation
describe Item do
let!(:item_container) { ItemContainer.new }
let(:adapter) { double(:adapter) }
let(:item_args) { [item_container, :my_key, 'name', url, options] }
let(:item) { Item.new(*item_args) }
let(:options) { Hash.new }
let(:url) { 'url' }
before { allow(SimpleNavigation).to receive_messages(adapter: adapter) }
describe '#highlights_on' do
let(:options) {{ highlights_on: :test }}
it "returns the item's highlights_on option" do
expect(item.highlights_on).to eq :test
end
end
describe '#initialize' do
context 'when there is a sub_navigation' do
let(:subnav_container) { double(:subnav_container).as_null_object }
shared_examples 'creating sub navigation container' do
it 'creates a sub navigation container with a level+1' do
expect(item.sub_navigation.level).to eq 2
end
end
context 'when a block is given' do
it_behaves_like 'creating sub navigation container' do
let(:item) { Item.new(*item_args) {} }
end
it 'calls the block' do
allow(ItemContainer).to receive_messages(new: subnav_container)
expect{ |blk|
Item.new(*item_args, &blk)
}.to yield_with_args(subnav_container)
end
end
context 'when no block is given' do
context 'and items are given' do
let(:items) { [] }
let(:options) {{ items: items }}
it_behaves_like 'creating sub navigation container'
it "sets the items on the subnav_container" do
expect(item.sub_navigation.items).to eq items
end
end
context 'and no items are given' do
it "doesn't create a new ItemContainer" do
item = Item.new(*item_args)
expect(item.sub_navigation).to be_nil
end
end
end
end
context 'when a :method option is given' do
let(:options) {{ method: :delete }}
it "sets the item's method" do
expect(item.method).to eq :delete
end
end
context 'when no :method option is given' do
it "sets the item's method to nil" do
expect(item.method).to be_nil
end
end
context 'when an :highlights_on option is given' do
let(:highlights_on) { double(:highlights_on) }
let(:options) {{ highlights_on: highlights_on }}
it "sets the item's highlights_on" do
expect(item.highlights_on).to eq highlights_on
end
end
context 'when no :highlights_on option is given' do
it "sets the item's highlights_on to nil" do
expect(item.highlights_on).to be_nil
end
end
context 'when a url is given' do
context 'and it is a string' do
it "sets the item's url accordingly" do
expect(item.url).to eq 'url'
end
end
context 'and it is a proc' do
let(:url) { proc{ "my_" + "url" } }
it "sets the item's url accordingly" do
expect(item.url).to eq 'my_url'
end
end
context 'and it is nil' do
let(:url) { nil }
it "sets the item's url accordingly" do
expect(item.url).to be_nil
end
end
end
context 'when no url nor options is specified' do
let(:item_args) { [item_container, :my_key, 'name'] }
it "sets the item's url to nil" do
expect(item.url).to be_nil
end
end
context 'when only a url is given' do
let(:item_args) { [item_container, :my_key, 'name', 'url'] }
it "set the item's url accordingly" do
expect(item.url).to eq 'url'
end
end
context 'when url and options are given' do
let(:options) {{ html: { option: true } }}
before { allow(adapter).to receive_messages(current_page?: false) }
it "set the item's url accordingly" do
expect(item.url).to eq 'url'
end
it "sets the item's html_options accordingly" do
allow(item).to \
receive_messages(selected_by_subnav?: false,
selected_by_condition?: false)
expect(item.html_options).to include(option: true)
end
end
end
describe '#link_html_options' do
let(:options) {{ link_html: :test }}
it "returns the item's link_html option" do
expect(item.link_html_options).to eq :test
end
end
describe '#method' do
let(:options) {{ method: :test }}
it "returns the item's method option" do
expect(item.method).to eq :test
end
end
describe '#name' do
before do
allow(SimpleNavigation.config).to \
receive_messages(name_generator: proc{ |name| "#{name}" })
end
context 'when no option is given' do
context 'and the name_generator uses only the name' do
it 'uses the default name_generator' do
expect(item.name).to eq 'name'
end
end
context 'and the name_generator uses only the item itself' do
before do
allow(SimpleNavigation.config).to \
receive_messages(name_generator: proc{ |name, item| "#{item.key}" })
end
it 'uses the default name_generator' do
expect(item.name).to eq 'my_key'
end
end
end
context 'when the :apply_generator is false' do
it "returns the item's name" do
expect(item.name(apply_generator: false)).to eq 'name'
end
end
context 'when a block is given' do
let(:item_args) { [item_container, :my_key, -> { 'Name in block' }, url, options] }
it "returns the item's name that is defined in the block" do
expect(item.name).to include 'Name in block'
end
end
end
describe '#selected?' do
context 'when the item has no :highlights_on option' do
before { allow(SimpleNavigation).to receive_messages(config: config) }
context 'and auto highlighting is off' do
let(:config) { double(:config, auto_highlight: false) }
it 'returns false' do
expect(item.selected?).to be false
end
end
context 'and auto highlighting is on' do
let(:config) { double(:config, ignore_query_params_on_auto_highlight: true, ignore_anchors_on_auto_highlight: true, auto_highlight: true) }
context "and the current url matches the item's url" do
before { allow(adapter).to receive_messages(current_page?: true) }
it 'returns true' do
expect(item.selected?).to be true
end
end
context "and the current url does not match the item's url" do
let(:config) do
double(:config, auto_highlight: false, highlight_on_subpath: false)
end
before { allow(adapter).to receive_messages(current_page?: false) }
it 'returns false' do
expect(item.selected?).to be false
end
end
context 'and highlights_on_subpath is on' do
let(:config) do
double(:config, auto_highlight: true, highlight_on_subpath: true, ignore_query_params_on_auto_highlight: true, ignore_anchors_on_auto_highlight: true)
end
context "but item has no url" do
let(:url) { nil }
it 'returns false' do
expect(item.selected?).to be false
end
end
context "and the current url is a sub path of the item's url" do
before do
allow(adapter).to \
receive_messages(current_page?: false, request_uri: 'url/test')
end
it 'returns true' do
expect(item.selected?).to be true
end
end
context "and the current url is not a sub path of the item's url" do
before do
allow(adapter).to \
receive_messages(current_page?: false, request_uri: 'other/test')
end
it 'returns false' do
expect(item.selected?).to be false
end
end
end
end
end
context 'when the item has a :highlights_on option' do
context 'and it is a regular expression' do
before { allow(adapter).to receive_messages(request_uri: '/test') }
context 'and the current url matches the expression' do
let(:options) {{ highlights_on: /test/ }}
it 'returns true' do
expect(item.selected?).to be true
end
end
context 'and the current url does not match the expression' do
let(:options) {{ highlights_on: /other/ }}
it 'returns false' do
expect(item.selected?).to be false
end
end
end
context 'and it is a callable object' do
context 'and the call returns true' do
let(:options) {{ highlights_on: -> { true } }}
it 'returns true' do
expect(item.selected?).to be true
end
end
context 'and the call returns false' do
let(:options) {{ highlights_on: -> { false } }}
it 'returns false' do
expect(item.selected?).to be false
end
end
end
context 'and it is the :subpath symbol' do
let(:options) {{ highlights_on: :subpath }}
context "and the current url is a sub path of the item's url" do
before do
allow(adapter).to receive_messages(request_uri: 'url/test')
end
it 'returns true' do
expect(item.selected?).to be true
end
end
context "and the current url is not a sub path of the item's url" do
before do
allow(adapter).to receive_messages(request_uri: 'other/test')
end
it 'returns false' do
expect(item.selected?).to be false
end
end
end
context 'and it is non usable' do
let(:options) {{ highlights_on: :hello }}
it 'raises an exception' do
expect{ item.selected? }.to raise_error(ArgumentError, ':highlights_on must be a Regexp, Proc or :subpath')
end
end
end
end
describe '#selected_class' do
context 'when the item is selected' do
before { allow(item).to receive_messages(selected?: true) }
it 'returns the default selected_class' do
expect(item.selected_class).to eq 'selected'
end
context 'and selected_class is defined in the context' do
before { allow(item_container).to receive_messages(selected_class: 'defined') }
it "returns the context's selected_class" do
expect(item.selected_class).to eq 'defined'
end
end
end
context 'when the item is not selected' do
before { allow(item).to receive_messages(selected?: false) }
it 'returns nil' do
expect(item.selected_class).to be_nil
end
end
end
describe ':html_options argument' do
let(:selected_classes) { 'selected simple-navigation-active-leaf' }
context 'when the :class option is given' do
let(:options) {{ html: { class: 'my_class' } }}
context 'and the item is selected' do
before { allow(item).to receive_messages(selected?: true, selected_by_condition?: true) }
it "adds the specified class to the item's html classes" do
expect(item.html_options[:class]).to include('my_class')
end
it "doesn't replace the default html classes of a selected item" do
expect(item.html_options[:class]).to include(selected_classes)
end
end
context "and the item isn't selected" do
before { allow(item).to receive_messages(selected?: false, selected_by_condition?: false) }
it "sets the specified class as the item's html classes" do
expect(item.html_options[:class]).to include('my_class')
end
end
end
context "when the :class option isn't given" do
context 'and the item is selected' do
before { allow(item).to receive_messages(selected?: true, selected_by_condition?: true) }
it "sets the default html classes of a selected item" do
expect(item.html_options[:class]).to include(selected_classes)
end
end
context "and the item isn't selected" do
before { allow(item).to receive_messages(selected?: false, selected_by_condition?: false) }
it "doesn't set any html class on the item" do
expect(item.html_options[:class]).to be_blank
end
end
end
shared_examples 'generating id' do |id|
it "sets the item's html id to the specified id" do
expect(item.html_options[:id]).to eq id
end
end
describe 'when the :id option is given' do
let(:options) {{ html: { id: 'my_id' } }}
before do
allow(SimpleNavigation.config).to receive_messages(autogenerate_item_ids: generate_ids)
allow(item).to receive_messages(selected?: false, selected_by_condition?: false)
end
context 'and :autogenerate_item_ids is true' do
let(:generate_ids) { true }
it_behaves_like 'generating id', 'my_id'
end
context 'and :autogenerate_item_ids is false' do
let(:generate_ids) { false }
it_behaves_like 'generating id', 'my_id'
end
end
context "when the :id option isn't given" do
before do
allow(SimpleNavigation.config).to receive_messages(autogenerate_item_ids: generate_ids)
allow(item).to receive_messages(selected?: false, selected_by_condition?: false)
end
context 'and :autogenerate_item_ids is true' do
let(:generate_ids) { true }
it_behaves_like 'generating id', 'my_key'
end
context 'and :autogenerate_item_ids is false' do
let(:generate_ids) { false }
it "doesn't set any html id on the item" do
expect(item.html_options[:id]).to be_blank
end
end
end
end
end
end