aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZog2018-01-17 15:49:39 +0100
committerZog2018-01-25 17:18:00 +0100
commitef62577ec90a0eb06c831052b6ab8aea8ade405f (patch)
treec24c4deb965f3bb66835749aec1948eb06191d67
parent69d1f47e21fea3c151eabafcdd9051d9d10e92a3 (diff)
downloadchouette-core-ef62577ec90a0eb06c831052b6ab8aea8ade405f.tar.bz2
Refs #5586; Add more specs on AF83::Decorator::Link
-rw-r--r--lib/af83/decorator.rb146
-rw-r--r--lib/af83/decorator/link.rb153
-rw-r--r--spec/lib/af83/decorator/decorator_link_spec.rb75
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