diff options
| author | Zog | 2018-01-15 10:34:30 +0100 |
|---|---|---|
| committer | Zog | 2018-01-25 17:17:57 +0100 |
| commit | 8c9ce8f5c143d1e9d3f2c038e447a01ee59c91d3 (patch) | |
| tree | ed94d90b5ae6e6ad77973bd0e8dddcf335a0d995 /spec | |
| parent | 5ecadfdead964381304fcf56a2564e2045988ef7 (diff) | |
| download | chouette-core-8c9ce8f5c143d1e9d3f2c038e447a01ee59c91d3.tar.bz2 | |
Refs #5586 @4h; First `action_links` refactor
- Implement new API
- Migrate the LineDecorator
- ensure no change on the "lines/index" view
Diffstat (limited to 'spec')
| -rw-r--r-- | spec/lib/af83/decorator/decorator_spec.rb | 423 | ||||
| -rw-r--r-- | spec/spec_helper.rb | 1 | ||||
| -rw-r--r-- | spec/views/lines/__snapshots__/lines/index.snap | 1 | ||||
| -rw-r--r-- | spec/views/lines/index.html.slim_spec.rb | 4 |
4 files changed, 428 insertions, 1 deletions
diff --git a/spec/lib/af83/decorator/decorator_spec.rb b/spec/lib/af83/decorator/decorator_spec.rb new file mode 100644 index 000000000..2e046b004 --- /dev/null +++ b/spec/lib/af83/decorator/decorator_spec.rb @@ -0,0 +1,423 @@ +RSpec.describe AF83::Decorator, type: :decorator do + describe(:parse_options) do + let(:options){ + {primary: true, secondary: %i(index show), permission: :blublu, weight: 12} + } + let(:link_options){ + {foo: :foo, bar: :bar} + } + let(:args){ options.dup.update(link_options.dup) } + it "should separate options from link_options" do + _options, _link_options = AF83::Decorator.send :parse_options, args + expect(_options).to eq options + link_options.each do |k, v| + expect(_link_options[k]).to eq v + end + end + end + + link_should_match_options = ->(link, options){ + options.each do |k, v| + expect(link.send(k)).to eq v + end + } + + describe(:action_links) do + let(:decorated) do + obj = create :line + decorator.decorate(obj) + end + + context "without links" do + let(:decorator) do + Class.new(AF83::Decorator) + end + + it "should return no link" do + links = decorated.action_links + expect(links.size).to eq 0 + end + end + + context "with a single link" do + let(:link_options) do + { + href: "/foo/bar", + content: "Blublu" + } + end + + context "incompletetly defined" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link href: "bar" + klass + end + + it "should raise an error" do + expect{decorator}.to raise_error(AF83::Decorator::IncompleteLinkDefinition) + end + end + + context "defined inline" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link link_options + klass + end + + it "should return the defined link" do + links = decorated.action_links + expect(links.size).to eq 1 + instance_exec links.first, link_options, &link_should_match_options + end + end + + context "defined in a block" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link do |l| + l.href link_options[:href] + l.content link_options[:content] + end + klass + end + + it "should return the defined link" do + links = decorated.action_links + expect(links.size).to eq 1 + instance_exec links.first, link_options, &link_should_match_options + end + end + + context "with proc attributes" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link do |l| + l.href { context[:href] } + l.content link_options[:content] + end + klass + end + + let(:decorated) do + obj = create :line + decorator.decorate(obj, context: {href: link_options[:href]}) + end + + it "should return the defined link" do + links = decorated.action_links + expect(links.size).to eq 1 + expect(links.first.href).to eq link_options[:href] + end + end + + context "with a method attributes" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link do |l| + l.href link_options[:href] + l.content link_options[:content] + l.method :put + end + klass + end + + let(:decorated) do + obj = create :line + decorator.decorate(obj, context: {href: link_options[:href]}) + end + + it "should return the defined method" do + links = decorated.action_links + expect(links.size).to eq 1 + expect(links.first.method).to eq :put + end + end + end + + context "with 2 links" do + let(:link_options_1) do + { + href: "/foo/bar", + content: "Blublu" + } + end + + let(:link_options_2) do + { + href: "/foo/bar/baz", + content: "Foo" + } + end + + context "without weight" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link link_options_1 + klass.action_link link_options_2 + klass + end + + it "should return links in the sequence they were defined" do + links = decorated.action_links + expect(links.size).to eq 2 + instance_exec links.first, link_options_1, &link_should_match_options + instance_exec links.last, link_options_2, &link_should_match_options + end + end + + context "with weight" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link link_options_1.update(weight: 10) + klass.action_link link_options_2 + klass + end + + it "should return links in the sequence they were defined" do + links = decorated.action_links + expect(links.size).to eq 2 + instance_exec links.first, link_options_2, &link_should_match_options + instance_exec links.last, link_options_1, &link_should_match_options + end + end + + context "scoped by action" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link link_options_1.update(action: :index) + klass.action_link link_options_2 + klass + end + + it "should only return links defined for the given action" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + instance_exec links.first, link_options_2, &link_should_match_options + end + end + + context "with a policy" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link href: "foo", content: "foo", policy: :edit + klass + end + + context "when the policy is not met" do + before(:each) do + Draper::HelperProxy.any_instance.stub(:policy){ + klass = Class.new do + def edit? + false + end + end.new + } + end + + it "should not return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 0 + end + end + + context "when the policy is met" do + before(:each) do + Draper::HelperProxy.any_instance.stub(:policy){ + klass = Class.new do + def edit? + true + end + end.new + } + end + + it "should not return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + end + end + end + + context "with a condition" do + context "set with 'with_condition'" do + context "as a value" do + context "when the condition is true" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_condition true do + action_link href: "foo", content: "foo" + end + klass + end + + it "should return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + end + end + + context "when the condition is false" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_condition false do + action_link href: "foo", content: "foo" + end + klass + end + + it "should not return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 0 + end + end + end + + context "as a Proc" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.with_condition ->{context[:show_link]} do + action_link href: "foo", content: "foo" + end + klass + end + + context "when the condition is true" do + let(:decorated) do + obj = create :line + decorator.decorate(obj, context: {show_link: true}) + end + + it "should return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + end + end + + context "when the condition is false" do + let(:decorated) do + obj = create :line + decorator.decorate(obj, context: {show_link: false}) + end + + it "should not return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 0 + end + end + end + end + + context "set inline" do + context "as a value" do + context "when the condition is true" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link link_options_1.update(if: true) + klass + end + + it "should return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + end + end + + context "when the condition is false" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link link_options_1.update(if: false) + klass + end + + it "should not return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 0 + end + end + end + + context "as a Proc" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link link_options_1.update(if: ->{context[:show_link]}) + klass + end + + context "when the condition is true" do + let(:decorated) do + obj = create :line + decorator.decorate(obj, context: {show_link: true}) + end + + it "should return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + end + end + + context "when the condition is false" do + let(:decorated) do + obj = create :line + decorator.decorate(obj, context: {show_link: false}) + end + + it "should not return the link" do + links = decorated.action_links(:show) + expect(links.size).to eq 0 + end + end + end + end + end + + context "scoped by action" do + context "with a single action" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link link_options_1.update(action: :index) + klass.action_link link_options_2 + klass + end + + it "should only return links defined for the given action" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + instance_exec links.first, link_options_2, &link_should_match_options + end + end + + context "with several actions" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link link_options_1.update(actions: %i(index edit)) + klass.action_link link_options_2.update(actions: %i(show edit)) + klass + end + + it "should only return links defined for the given action" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + instance_exec links.first, link_options_2, &link_should_match_options + end + end + + context "with the keyword 'on'" do + let(:decorator) do + klass = Class.new(AF83::Decorator) + klass.action_link link_options_1.update(on: %i(index edit)) + klass.action_link link_options_2.update(on: :show) + klass + end + + it "should only return links defined for the given action" do + links = decorated.action_links(:show) + expect(links.size).to eq 1 + instance_exec links.first, link_options_2, &link_should_match_options + end + end + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2d13d3802..cde252236 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -100,7 +100,6 @@ RSpec.configure do |config| # The different available types are documented in the features, such as in # https://relishapp.com/rspec/rspec-rails/docs config.infer_spec_type_from_file_location! - end Shoulda::Matchers.configure do |config| diff --git a/spec/views/lines/__snapshots__/lines/index.snap b/spec/views/lines/__snapshots__/lines/index.snap new file mode 100644 index 000000000..f68f4f13b --- /dev/null +++ b/spec/views/lines/__snapshots__/lines/index.snap @@ -0,0 +1 @@ +<div class="page_content"><div class="container-fluid"><div class="row"><div class="col-lg-12"><form class="form form-filter" id="chouette/line_search" action="/line_referentials/4/lines" accept-charset="UTF-8" method="get"><input name="utf8" type="hidden" value="✓" /><div class="ffg-row"><div class="input-group search_bar"><input placeholder="Recherche par nom, nom court ou ID Codif..." class="form-control" type="search" name="q[name_or_number_or_objectid_cont]" id="q_name_or_number_or_objectid_cont" /><span class="input-group-btn"><button class="btn btn-default" id="search-btn" type="submit"><span class="fa fa-search"></span></button></span></div></div><div class="ffg-row"><div class="form-group togglable"><label class="control-label" for="q_Réseau">Réseau</label><div class="form-group checkbox_list"><input type="hidden" name="q[network_id_eq_any][]" value="" /></div></div><div class="form-group togglable"><label class="control-label" for="q_Transporteur principal">Transporteur principal</label><div class="form-group checkbox_list"><input type="hidden" name="q[company_id_eq_any][]" value="" /></div></div><div class="form-group togglable"><label class="control-label" for="q_Mode de transport">Mode de transport</label><div class="form-group checkbox_list"><span class="checkbox"><label for="q_transport_mode_eq_any_bus"><input class="check_boxes optional" type="checkbox" value="bus" name="q[transport_mode_eq_any][]" id="q_transport_mode_eq_any_bus" /><span>Bus</span></label></span><span class="checkbox"><label for="q_transport_mode_eq_any_funicular"><input class="check_boxes optional" type="checkbox" value="funicular" name="q[transport_mode_eq_any][]" id="q_transport_mode_eq_any_funicular" /><span>Funiculaire</span></label></span><span class="checkbox"><label for="q_transport_mode_eq_any_metro"><input class="check_boxes optional" type="checkbox" value="metro" name="q[transport_mode_eq_any][]" id="q_transport_mode_eq_any_metro" /><span>Métro</span></label></span><span class="checkbox"><label for="q_transport_mode_eq_any_rail"><input class="check_boxes optional" type="checkbox" value="rail" name="q[transport_mode_eq_any][]" id="q_transport_mode_eq_any_rail" /><span>Train</span></label></span><span class="checkbox"><label for="q_transport_mode_eq_any_tram"><input class="check_boxes optional" type="checkbox" value="tram" name="q[transport_mode_eq_any][]" id="q_transport_mode_eq_any_tram" /><span>Tramway</span></label></span><input type="hidden" name="q[transport_mode_eq_any][]" value="" /></div></div><div class="form-group togglable"><label class="control-label" for="q_Sous mode de transport">Sous mode de transport</label><div class="form-group checkbox_list"><span class="checkbox"><label for="q_transport_submode_eq_any_highfrequencybus"><input class="check_boxes optional" type="checkbox" value="highFrequencyBus" name="q[transport_submode_eq_any][]" id="q_transport_submode_eq_any_highfrequencybus" /><span>Bus à haute fréquence</span></label></span><span class="checkbox"><label for="q_transport_submode_eq_any_demandandresponsebus"><input class="check_boxes optional" type="checkbox" value="demandAndResponseBus" name="q[transport_submode_eq_any][]" id="q_transport_submode_eq_any_demandandresponsebus" /><span>Bus à la demande</span></label></span><span class="checkbox"><label for="q_transport_submode_eq_any_nightbus"><input class="check_boxes optional" type="checkbox" value="nightBus" name="q[transport_submode_eq_any][]" id="q_transport_submode_eq_any_nightbus" /><span>Bus de nuit</span></label></span><span class="checkbox"><label for="q_transport_submode_eq_any_expressbus"><input class="check_boxes optional" type="checkbox" value="expressBus" name="q[transport_submode_eq_any][]" id="q_transport_submode_eq_any_expressbus" /><span>Bus express</span></label></span><span class="checkbox"><label for="q_transport_submode_eq_any_interregionalrail"><input class="check_boxes optional" type="checkbox" value="interregionalRail" name="q[transport_submode_eq_any][]" id="q_transport_submode_eq_any_interregionalrail" /><span>Intercités</span></label></span><span class="checkbox"><label for="q_transport_submode_eq_any_airportlinkbus"><input class="check_boxes optional" type="checkbox" value="airportLinkBus" name="q[transport_submode_eq_any][]" id="q_transport_submode_eq_any_airportlinkbus" /><span>Navette interne aéroport</span></label></span><span class="checkbox"><label for="q_transport_submode_eq_any_regionalrail"><input class="check_boxes optional" type="checkbox" value="regionalRail" name="q[transport_submode_eq_any][]" id="q_transport_submode_eq_any_regionalrail" /><span>TER</span></label></span><span class="checkbox"><label for="q_transport_submode_eq_any_suburbanrailway"><input class="check_boxes optional" type="checkbox" value="suburbanRailway" name="q[transport_submode_eq_any][]" id="q_transport_submode_eq_any_suburbanrailway" /><span>Train</span></label></span><span class="checkbox"><label for="q_transport_submode_eq_any_railshuttle"><input class="check_boxes optional" type="checkbox" value="railShuttle" name="q[transport_submode_eq_any][]" id="q_transport_submode_eq_any_railshuttle" /><span>Val</span></label></span><input type="hidden" name="q[transport_submode_eq_any][]" value="" /></div></div></div><div class="actions"><a class="btn btn-link" href="/line_referentials/4/lines">Effacer</a><input type="submit" name="commit" value="Filtrer" class="btn btn-default" /></div></form></div></div><div class="row"><div class="col-lg-12"><table class="table has-filter has-search"><thead><tr><th>ID Codifligne</th><th><a href="/line_referentials/4/lines?direction=desc&sort=number">Numéro<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th><th><a href="/line_referentials/4/lines?direction=desc&sort=name">Nom de la ligne<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th><th><a href="/line_referentials/4/lines?direction=desc&sort=deactivated">Activé<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th><th><a href="/line_referentials/4/lines?direction=desc&sort=networks.name">Réseau<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th><th><a href="/line_referentials/4/lines?direction=desc&sort=companies.name">Transporteur principal<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th><th><a href="/line_referentials/4/lines?direction=desc&sort=transport_mode">Mode de transport<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th><th><a href="/line_referentials/4/lines?direction=desc&sort=transport_submode">Sous mode de transport<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th><th></th></tr></thead><tbody><tr class="line-1"><td>1</td><td>1</td><td title="Voir"><a href="/line_referentials/4/lines/1">Line 1</a></td><td><span class="fa fa-check-circle fa-lg text-success"></span>Oui</td><td>Network 1</td><td>Company 1</td><td>Bus</td><td>-</td><td class="actions"><div class="btn-group"><div class="btn dropdown-toggle" data-toggle="dropdown"><span class="fa fa-cog"></span></div><ul class="dropdown-menu"><li><a href="/line_referentials/4/lines/1">Consulter</a></li><li><a href="/line_referentials/4/networks/1">Voir le réseau</a></li><li><a href="/line_referentials/4/companies/1">Voir le transporteur principal</a></li></ul></div></td></tr><tr class="line-2"><td>2</td><td>2</td><td title="Voir"><a href="/line_referentials/4/lines/2">Line 2</a></td><td><span class="fa fa-check-circle fa-lg text-success"></span>Oui</td><td>Network 2</td><td>Company 2</td><td>Bus</td><td>-</td><td class="actions"><div class="btn-group"><div class="btn dropdown-toggle" data-toggle="dropdown"><span class="fa fa-cog"></span></div><ul class="dropdown-menu"><li><a href="/line_referentials/4/lines/2">Consulter</a></li><li><a href="/line_referentials/4/networks/2">Voir le réseau</a></li><li><a href="/line_referentials/4/companies/2">Voir le transporteur principal</a></li></ul></div></td></tr></tbody></table><div class="pagination pull-right">Liste des lignes 1 à 2 sur 2</div></div></div></div></div>
\ No newline at end of file diff --git a/spec/views/lines/index.html.slim_spec.rb b/spec/views/lines/index.html.slim_spec.rb index 498784912..9237487e3 100644 --- a/spec/views/lines/index.html.slim_spec.rb +++ b/spec/views/lines/index.html.slim_spec.rb @@ -32,6 +32,10 @@ describe "/lines/index", :type => :view do common_items.call() it { should have_the_right_number_of_links(lines, 3) } + it "should match the snapshot" do + expect(rendered).to match_snapshot("lines/index") + end + with_permission "lines.change_status" do common_items.call() it { should have_link_for_each_item(lines, "deactivate", -> (line){ view.deactivate_line_referential_line_path(line_referential, line) }) } |
