diff options
| author | Zog | 2018-01-17 15:49:39 +0100 | 
|---|---|---|
| committer | Zog | 2018-01-17 15:49:39 +0100 | 
| commit | 3d2ada1541337efa64334dcafa6214556e76ad27 (patch) | |
| tree | 6a93b4277b68526478e491b94187e35b38039873 | |
| parent | 8049b8c0c3b083e77bf355f5e079f2b5f16391b9 (diff) | |
| download | chouette-core-3d2ada1541337efa64334dcafa6214556e76ad27.tar.bz2 | |
Refs #5586; Add more specs on AF83::Decorator::Link
| -rw-r--r-- | lib/af83/decorator.rb | 146 | ||||
| -rw-r--r-- | lib/af83/decorator/link.rb | 153 | ||||
| -rw-r--r-- | spec/lib/af83/decorator/decorator_link_spec.rb | 75 | 
3 files changed, 228 insertions, 146 deletions
| diff --git a/lib/af83/decorator.rb b/lib/af83/decorator.rb index ba9a46cb0..53e09fed3 100644 --- a/lib/af83/decorator.rb +++ b/lib/af83/decorator.rb @@ -107,152 +107,6 @@ class AF83::Decorator < ModelDecorator      end    end -  class Link -    REQUIRED_ATTRIBUTES = %i(href content) - -    attr_reader :context -    attr_reader :action - -    def initialize options={} -      @options = options -    end - -    def bind_to_context context, action -      @context = context -      @action = action -      self -    end - -    def method *args -      link_method *args -    end - -    def class *args -      link_class 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(self, &out)  if out.is_a?(Proc) -        out -      else -        @options[name] = args.first -      end -    end - -    def options -      @options.symbolize_keys -    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=nil -      action ||= @action -      enabled_actions.empty? || enabled_actions.include?(action.to_s) -    end - -    def actions_for_group group -      val = @options[:_groups][group] -      val.is_a?(Array) ? val.map(&:to_s) : val -    end - -    def in_group_for_action? group -      vals = actions_for_group(group) -      if vals.is_a?(Array) -        return vals.include?(@action.to_s) -      elsif vals.is_a?(String) || vals.is_a?(Symbol) -        vals.to_s == @action.to_s -      else -        !!vals -      end -    end - -    def primary? -      in_group_for_action? :primary -    end - -    def secondary? -      in_group_for_action? :secondary -    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 = enabled && check_feature(@options[:_feature]) if @options[:_feature].present? - -      enabled -    end - -    def check_policy(policy) -      @context.check_policy policy -    end - -    def check_feature(feature) -      @context.check_feature feature -    end - -    def errors -      "Missing attributes: #{@missing_attributes.to_sentence}" -    end - -    def extra_class val=nil -      if val.present? -        @options[:link_class] ||= [] -        @options[:link_class] << val -        @options[:link_class].flatten! -      else -        (options[:link_class] || []).join(' ') -      end -    end - -    def html_options -      out = {} -      options.each do |k, v| -        out[k] = self.send(k) unless k == :content || k == :href || k.to_s =~ /^_/ -      end -      out[:class] = extra_class -      out.delete(:link_class) -      out[:class] += " disabled" if disabled -      out[:disabled] = !!disabled -      out -    end - -    def to_html -      if block_given? -        link = Link.new(@options) -        yield link -        return link.bind_to_context(context, @action).to_html -      end -      if type&.to_sym == :button -        HTMLElement.new( -          :button, -          content, -          html_options -        ).to_html -      else -        context.h.link_to content, href, html_options -      end -    end -  end -    class IncompleteLinkDefinition < RuntimeError    end diff --git a/lib/af83/decorator/link.rb b/lib/af83/decorator/link.rb new file mode 100644 index 000000000..e7ab90d55 --- /dev/null +++ b/lib/af83/decorator/link.rb @@ -0,0 +1,153 @@ +class AF83::Decorator::Link +  REQUIRED_ATTRIBUTES = %i(href content) + +  attr_reader :context +  attr_reader :action + +  def initialize options={} +    @options = {} +    options.each do |k, v| +      send "#{k}", v +    end +  end + +  def bind_to_context context, action +    @context = context +    @action = action +    self +  end + +  def method *args +    link_method *args +  end + +  def class *args +    link_class 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(self, &out)  if out.is_a?(Proc) +      out +    else +      # we can use l.foo("bar") or l.foo = "bar" +      if name.to_s =~ /\=$/ +        _name = name.to_s.gsub(/=$/, '') +        return send(_name, *args, &block) +      end +      @options[name] = args.first +    end +  end + +  def options +    @options.symbolize_keys +  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=nil +    action ||= @action +    enabled_actions.empty? || enabled_actions.include?(action.to_s) +  end + +  def actions_for_group group +    val = @options[:_groups][group] +    val.is_a?(Array) ? val.map(&:to_s) : val +  end + +  def in_group_for_action? group +    vals = actions_for_group(group) +    if vals.is_a?(Array) +      return vals.include?(@action.to_s) +    elsif vals.is_a?(String) || vals.is_a?(Symbol) +      vals.to_s == @action.to_s +    else +      !!vals +    end +  end + +  def primary? +    in_group_for_action? :primary +  end + +  def secondary? +    in_group_for_action? :secondary +  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 = enabled && check_feature(@options[:_feature]) if @options[:_feature].present? + +    enabled +  end + +  def check_policy(policy) +    @context.check_policy policy +  end + +  def check_feature(feature) +    @context.check_feature feature +  end + +  def errors +    "Missing attributes: #{@missing_attributes.to_sentence}" +  end + +  def extra_class val=nil +    if val.present? +      @options[:link_class] ||= [] +      @options[:link_class] << val +      @options[:link_class].flatten! +    else +      (options[:link_class] || []).join(' ') +    end +  end + +  def html_options +    out = {} +    options.each do |k, v| +      out[k] = self.send(k) unless k == :content || k == :href || k.to_s =~ /^_/ +    end +    out[:class] = extra_class +    out.delete(:link_class) +    out[:class] += " disabled" if disabled +    out[:disabled] = !!disabled +    out +  end + +  def to_html +    if block_given? +      link = Link.new(@options) +      yield link +      return link.bind_to_context(context, @action).to_html +    end +    if type&.to_sym == :button +      HTMLElement.new( +        :button, +        content, +        html_options +      ).to_html +    else +      context.h.link_to content, href, html_options +    end +  end +end diff --git a/spec/lib/af83/decorator/decorator_link_spec.rb b/spec/lib/af83/decorator/decorator_link_spec.rb new file mode 100644 index 000000000..356dcc527 --- /dev/null +++ b/spec/lib/af83/decorator/decorator_link_spec.rb @@ -0,0 +1,75 @@ +RSpec.describe AF83::Decorator::Link, type: :decorator do +  describe "#complete?" do +    context "on a imcomplete link" do +      it "should be false" do +        expect(AF83::Decorator::Link.new.complete?).to be_falsy +        expect(AF83::Decorator::Link.new(content: "foo").complete?).to be_falsy +        expect(AF83::Decorator::Link.new(href: "foo").complete?).to be_falsy +      end +    end + +    context "on a complete link" do +      it "should be true" do +        expect(AF83::Decorator::Link.new(href: "foo", content: "foo").complete?).to be_truthy +      end +    end +  end + +  describe "#class" do +    let(:link){ +      AF83::Decorator::Link.new(href: "foo", content: "foo", class: "initial_class") +    } + +    it "should override exisiting class" do +      expect(link.html_options[:class]).to eq "initial_class" +      link.class "new_class" +      expect(link.html_options[:class]).to eq "new_class" +      link.class = "another_class" +      expect(link.html_options[:class]).to eq "another_class" +    end +  end + +  describe "#extra_class" do +    let(:link){ +      AF83::Decorator::Link.new(href: "foo", content: "foo", class: "initial_class") +    } + +    it "should add to exisiting class" do +      expect(link.html_options[:class]).to eq "initial_class" +      link.extra_class "new_class" +      expect(link.html_options[:class]).to eq "initial_class new_class" +      link.extra_class = "another_class" +      expect(link.html_options[:class]).to eq "initial_class new_class another_class" +    end +  end + +  describe "#type" do + +    let(:link){ +      AF83::Decorator::Link.new(href: "foo", content: "foo") +    } + +    let(:context){ +      Class.new do +        def h +          Class.new do +            def link_to *args +              HTMLElement.new(:a, 'foo', {}).to_html +            end +          end.new +        end +      end.new +    } + +    it "should allow for buttons" do +      link.type = :button +      expect(link.to_html).to match /\<button.*\<\/button\>/ +    end + +    it "should fallback to <a>" do +      link.type = :spaghetti +      link.bind_to_context context, :show +      expect(link.to_html).to match /\<a.*\<\/a\>/ +    end +  end +end | 
