require 'spec_helper' require 'compo' describe Compo::UrlFinder do subject { Compo::UrlFinder } describe '.find' do let(:target) { Compo::Leaf.new } let(:root) do s = Compo::HashBranch.new a = Compo::HashBranch.new b = Compo::ArrayBranch.new d = Compo::Leaf.new e = Compo::Leaf.new zero = Compo::Leaf.new s.add('a', a) a.add('b', b) b.add(0, zero) b.add(1, target) s.add('d', d) a.add('e', e) s end context 'when given a nil root' do specify { expect { |b| subject.find(nil, 'a/b/1', &b) }.to raise_error } end context 'when given a nil URL' do specify { expect { |b| subject.find(root, nil, &b) }.to raise_error } end shared_examples 'a successful finding' do it 'returns the correct resource' do expect { |b| subject.find(root, url, &b) }.to yield_with_args(target) end end shared_examples 'an unsuccessful finding' do specify do expect { |b| subject.find(root, url, &b) }.to raise_error( "Could not find resource: #{url}" ) end end shared_examples 'an unsuccessful finding with custom error' do specify do mp = ->(_) { :a } expect { |b| subject.find(root, url, missing_proc: mp, &b) } .to yield_with_args(:a) end end context 'when given a correct root but incorrect URL' do context 'using the default missing resource handler' do context 'when the URL has a leading slash' do it_behaves_like 'an unsuccessful finding' do let(:url) { '/a/z' } end end context 'when the URL has a trailing slash' do it_behaves_like 'an unsuccessful finding' do let(:url) { 'a/z/' } end end context 'when the URL has a leading and trailing slash' do it_behaves_like 'an unsuccessful finding' do let(:url) { '/a/z/' } end end context 'when the URL has neither leading nor trailing slash' do it_behaves_like 'an unsuccessful finding' do let(:url) { 'a/z' } end end end context 'using a custom error handler' do context 'when the URL has a leading slash' do it_behaves_like 'an unsuccessful finding with custom error' do let(:url) { '/d/e/d' } end end context 'when the URL has a trailing slash' do it_behaves_like 'an unsuccessful finding with custom error' do let(:url) { 'd/e/d/' } end end context 'when the URL has a leading and trailing slash' do it_behaves_like 'an unsuccessful finding with custom error' do let(:url) { '/d/e/d/' } end end context 'when the URL has neither leading nor trailing slash' do it_behaves_like 'an unsuccessful finding with custom error' do let(:url) { 'd/e/d' } end end end end context 'when given a correct root and URL' do context 'when the URL leads to a resource' do context 'when the URL has a leading slash' do it_behaves_like 'a successful finding' do let(:url) { '/a/b/1' } end end context 'when the URL has a trailing slash' do it_behaves_like 'a successful finding' do let(:url) { 'a/b/1/' } end end context 'when the URL has a leading and trailing slash' do it_behaves_like 'a successful finding' do let(:url) { '/a/b/1/' } end end context 'when the URL has neither leading nor trailing slash' do it_behaves_like 'a successful finding' do let(:url) { 'a/b/1' } end end end end end end