diff options
| -rw-r--r-- | Gemfile | 1 | ||||
| -rw-r--r-- | Gemfile.lock | 7 | ||||
| -rw-r--r-- | app/decorators/line_decorator.rb | 111 | ||||
| -rw-r--r-- | app/helpers/table_builder_helper.rb | 2 | ||||
| -rw-r--r-- | app/views/lines/index.html.slim | 1 | ||||
| -rw-r--r-- | config/locales/lines.en.yml | 1 | ||||
| -rw-r--r-- | config/locales/lines.fr.yml | 1 | ||||
| -rw-r--r-- | lib/af83/decorator.rb | 124 | ||||
| -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 | 
12 files changed, 614 insertions, 63 deletions
| @@ -174,6 +174,7 @@ group :test do    gem 'simplecov-rcov', :require => false    gem 'htmlbeautifier'    gem 'timecop' +  gem 'rspec-snapshot'  end  group :test, :development, :dev do diff --git a/Gemfile.lock b/Gemfile.lock index ba1a90a5a..09ef00f94 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -442,6 +442,10 @@ GEM      roo (2.7.1)        nokogiri (~> 1)        rubyzip (~> 1.1, < 2.0.0) +    rspec (3.5.0) +      rspec-core (~> 3.5.0) +      rspec-expectations (~> 3.5.0) +      rspec-mocks (~> 3.5.0)      rspec-core (3.5.4)        rspec-support (~> 3.5.0)      rspec-expectations (3.5.0) @@ -458,6 +462,8 @@ GEM        rspec-expectations (~> 3.5.0)        rspec-mocks (~> 3.5.0)        rspec-support (~> 3.5.0) +    rspec-snapshot (0.1.1) +      rspec (> 3.0.0)      rspec-support (3.5.0)      ruby-graphviz (1.2.3)      rubycas-client (2.3.9) @@ -674,6 +680,7 @@ DEPENDENCIES    rgeo (~> 0.5.2)    roo    rspec-rails (~> 3.5.0) +  rspec-snapshot    rubyzip    sass-rails (~> 4.0.3)    sawyer (~> 0.6.0) diff --git a/app/decorators/line_decorator.rb b/app/decorators/line_decorator.rb index 9c0cf7292..8e8e3bbc5 100644 --- a/app/decorators/line_decorator.rb +++ b/app/decorators/line_decorator.rb @@ -1,76 +1,67 @@ -class LineDecorator < Draper::Decorator +class LineDecorator < AF83::Decorator    decorates Chouette::Line    delegate_all -  # Requires: -  #   context: { -  #     line_referential: , -  #     current_organisation: -  #   } -  def action_links -    links = [] +  ### primary (and secondary) can be +  ### - a single action +  ### - an array of actions +  ### - a boolean -    links << Link.new( -      content: h.t('lines.actions.show_network'), -      href: [context[:line_referential], object.network] -    ) +  action_link primary: :index do |l| +    l.content h.t('lines.actions.show') +    l.href   { [context[:line_referential], object] } +  end -    links << Link.new( -      content: h.t('lines.actions.show_company'), -      href: [context[:line_referential], object.company], -      disabled: object.company.nil? -    ) +  action_link do |l| +    l.content h.t('lines.actions.show_network') +    l.href   { [context[:line_referential], object.network] } +  end -    if h.policy(Chouette::Line).create? && -      context[:line_referential].organisations.include?( -        context[:current_organisation] -      ) -      links << Link.new( -        content: h.t('lines.actions.edit'), -        href: h.edit_line_referential_line_path(context[:line_referential], object.id) -      ) -    end +  action_link do |l| +    l.content  { h.t('lines.actions.show_company') } +    l.href     { [context[:line_referential], object.company] } +    l.disabled { object.company.nil? } +  end -    if h.policy(Chouette::Line).create? && -      context[:line_referential].organisations.include?( -        context[:current_organisation] -      ) -      links << Link.new( -        content: h.t('lines.actions.new'), -        href: h.new_line_referential_line_path(context[:line_referential]) -      ) -    end +  can_edit_line = ->(){ h.policy(Chouette::Line).create? && context[:line_referential].organisations.include?(context[:current_organisation]) } -    if h.policy(object).deactivate? -      links << Link.new( -        content: h.deactivate_link_content('lines.actions.deactivate'), -        href: h.deactivate_line_referential_line_path(context[:line_referential], object), -        method: :put, -        data: {confirm: h.t('lines.actions.deactivate_confirm')}, -        extra_class: "delete-action" -      ) +  with_condition can_edit_line do +    action_link on: :index do |l| +      l.content { h.t('lines.actions.new') } +      l.href    { h.new_line_referential_line_path(context[:line_referential]) }      end -    if h.policy(object).activate? -      links << Link.new( -        content: h.activate_link_content('lines.actions.activate'), -        href: h.activate_line_referential_line_path(context[:line_referential], object), -        method: :put, -        data: {confirm: h.t('lines.actions.activate_confirm')}, -        extra_class: "delete-action" -      ) +    action_link on: %i(index show), primary: :show do |l| +      l.content { h.t('lines.actions.edit') } +      l.href    { h.edit_line_referential_line_path(context[:line_referential], object.id) }      end +  end -    if h.policy(object).destroy? -      links << Link.new( -        content: h.destroy_link_content('lines.actions.destroy'), -        href: h.line_referential_line_path(context[:line_referential], object), -        method: :delete, -        data: {confirm: h.t('lines.actions.destroy_confirm')} -      ) -    end +  ### the option :policy will automatically check for the corresponding method +  ### on the object's policy + +  action_link policy: :deactivate, secondary: true do |l| +    l.content  { h.deactivate_link_content('lines.actions.deactivate') } +    l.href     { h.deactivate_line_referential_line_path(context[:line_referential], object) } +    l.method   :put +    l.data     confirm: h.t('lines.actions.deactivate_confirm') +    l.extra_class "delete-action" +  end + +  action_link policy: :activate, secondary: true do |l| +    l.content  { h.activate_link_content('lines.actions.activate') } +    l.href     { h.activate_line_referential_line_path(context[:line_referential], object) } +    l.method   :put +    l.data     confirm: h.t('lines.actions.activate_confirm') +    l.extra_class "delete-action" +  end -    links +  action_link policy: :destroy do |l| +    l.content  { h.destroy_link_content('lines.actions.destroy') } +    l.href     { h.line_referential_line_path(context[:line_referential], object) } +    l.method   :delete +    l.data     confirm: h.t('lines.actions.destroy_confirm') +    l.extra_class "delete-action"    end  end diff --git a/app/helpers/table_builder_helper.rb b/app/helpers/table_builder_helper.rb index dede51920..e66e9c942 100644 --- a/app/helpers/table_builder_helper.rb +++ b/app/helpers/table_builder_helper.rb @@ -309,7 +309,7 @@ module TableBuilderHelper      menu = content_tag :ul, class: 'dropdown-menu' do        (          CustomLinks.new(item, pundit_user, links, referential).links + -        item.action_links.select { |link| link.is_a?(Link) } +        item.action_links        ).map do |link|          gear_menu_link(link)        end.join.html_safe diff --git a/app/views/lines/index.html.slim b/app/views/lines/index.html.slim index b62263263..399a2d8e1 100644 --- a/app/views/lines/index.html.slim +++ b/app/views/lines/index.html.slim @@ -52,7 +52,6 @@                  attribute: Proc.new { |n| n.transport_submode.present? ? t("enumerize.transport_submode.#{n.try(:transport_submode)}") : "-" } \                ) \              ], -            links: [:show],              cls: 'table has-filter has-search'            = new_pagination @lines, 'pull-right' diff --git a/config/locales/lines.en.yml b/config/locales/lines.en.yml index 4b2bdfdb8..8e0189bd8 100644 --- a/config/locales/lines.en.yml +++ b/config/locales/lines.en.yml @@ -17,6 +17,7 @@ en:        export_kml_all: "Export KML lines"        export_hub: "Export HUB line"        export_hub_all: "Export HUB lines" +      show: 'Show'        show_network: 'Show network'        show_company: 'Show company'      new: diff --git a/config/locales/lines.fr.yml b/config/locales/lines.fr.yml index 6317e2930..2159f06ab 100644 --- a/config/locales/lines.fr.yml +++ b/config/locales/lines.fr.yml @@ -17,6 +17,7 @@ fr:        export_kml_all: "Export KML des lignes"        export_hub: "Export HUB de la ligne"        export_hub_all: "Export HUB des lignes" +      show: 'Consulter'        show_network: 'Voir le réseau'        show_company: 'Voir le transporteur principal'      new: diff --git a/lib/af83/decorator.rb b/lib/af83/decorator.rb new file mode 100644 index 000000000..f1570008f --- /dev/null +++ b/lib/af83/decorator.rb @@ -0,0 +1,124 @@ +class AF83::Decorator < Draper::Decorator +  def self.action_link args={} +    args[:if] = @_condition if args[:if].nil? +    options, link_options = parse_options args + +    link = Link.new(link_options) +    yield link if block_given? +    raise IncompleteLinkDefinition.new(link.errors) unless link.complete? + +    weight = options[:weight] || 1 +    @_action_links ||= [] +    @_action_links[weight] ||= [] +    @_action_links[weight] << link +  end + +  def self.with_condition condition, &block +    @_condition = condition +    instance_eval &block +    @_condition = nil +  end + +  def self.action_links action +    (@_action_links || []).flatten.compact.select{|l| l.for_action?(action)} +  end + +  def action_links action=:index +    self.class.action_links(action)\ +    .map{|l| l.bind_to_context(self)}\ +    .select{|l| l.enabled?} +  end + +  def check_policy policy +    _object = policy.to_s == "create" ? object.class : object +    method = "#{policy}?" +    h.policy(_object).send(method) +  end + +  private +  def self.parse_options args +    options = {} +    %i(primary secondary permission weight).each do |k| +      options[k] = args.delete(k) if args.has_key?(k) +    end +    link_options = args.dup +    actions = args.delete :actions +    actions ||= args.delete :on +    actions ||= [args.delete(:action)] +    actions = [actions] unless actions.is_a?(Array) +    link_options[:_actions] = actions.compact +    link_options[:_if] = args.delete(:if) +    link_options[:_policy] = args.delete(:policy) +    [options, link_options] +  end + +  class Link +    REQUIRED_ATTRIBUTES = %i(href content) + +    attr_reader :context + +    def initialize options={} +      @options = options +    end + +    def bind_to_context context +      @context = context +      self +    end + +    def method *args +      link_method *args +    end + +    def method_missing name, *args, &block +      if block_given? +        @options[name] = block +      elsif args.size == 0 +        out = @options[name] +        out = context.instance_exec(&out) if out.is_a?(Proc) +        out +      else +        @options[name] = args.first +      end +    end + +    def complete? +      @missing_attributes = REQUIRED_ATTRIBUTES.select{|a| !@options[a].present?} +      @missing_attributes.empty? +    end + +    def enabled_actions +      @options[:_actions].map(&:to_s) || [] +    end + +    def for_action? action +      enabled_actions.empty? || enabled_actions.include?(action.to_s) +    end + +    def enabled? +      enabled = false +      if @options[:_if].nil? +        enabled = true +      elsif @options[:_if].is_a?(Proc) +        enabled = context.instance_exec(&@options[:_if]) +      else +        enabled = !!@options[:_if] +      end + +      enabled = enabled && check_policy(@options[:_policy]) if @options[:_policy].present? + +      enabled +    end + +    def check_policy(policy) +      @context.check_policy policy +    end + +    def errors +      "Missing attributes: #{@missing_attributes.to_sentence}" +    end +  end + +  class IncompleteLinkDefinition < RuntimeError +  end +end 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) }) } | 
