active_component 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +4 -0
- data/.rspec +1 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +30 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +65 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/active_component.gemspec +104 -0
- data/init.rb +1 -0
- data/lib/active_component.rb +196 -0
- data/lib/active_component/base.rb +930 -0
- data/lib/active_component/components/block.rb +20 -0
- data/lib/active_component/components/empty_tag.rb +26 -0
- data/lib/active_component/components/heading.rb +60 -0
- data/lib/active_component/components/inline_tag.rb +24 -0
- data/lib/active_component/components/section.rb +39 -0
- data/lib/active_component/components/table.rb +61 -0
- data/lib/active_component/config.rb +33 -0
- data/lib/active_component/core_extensions.rb +99 -0
- data/lib/active_component/template_handler.rb +20 -0
- data/pkg/active_component-0.1.2.gem +0 -0
- data/spec/active_component_spec.rb +156 -0
- data/spec/active_component_spec_helper.rb +10 -0
- data/spec/base_spec.rb +154 -0
- data/spec/components/block_spec.rb +51 -0
- data/spec/components/heading_spec.rb +95 -0
- data/spec/components/section_spec.rb +35 -0
- data/spec/components/table_spec.rb +88 -0
- data/spec/core_extensions_spec.rb +62 -0
- data/spec/factories.rb +23 -0
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +15 -0
- metadata +166 -0
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe ActiveComponent::Base do
|
4
|
+
|
5
|
+
context "component initialization" do
|
6
|
+
describe "html_class" do
|
7
|
+
it "should include the hyphenized component title" do
|
8
|
+
g = GreetingBox.new
|
9
|
+
g.title = "Happy greeting box"
|
10
|
+
g.instance_eval {[html_class].flatten}.should be_include 'happy-greeting-box'
|
11
|
+
d = Div.new
|
12
|
+
d.title = "Happy div"
|
13
|
+
d.instance_eval {[html_class].flatten}.should be_include 'happy-div'
|
14
|
+
end
|
15
|
+
it "should include the class_name unless it is an html tag wrapper" do
|
16
|
+
g = GreetingBox.new
|
17
|
+
g.instance_eval {[html_class].flatten}.should be_include 'greeting-box'
|
18
|
+
d = Div.new
|
19
|
+
d.instance_eval {[html_class].flatten}.should_not be_include 'div'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class NewsWidget < ActiveComponent::Base
|
24
|
+
attr_accessor :author
|
25
|
+
|
26
|
+
def initialize(*args, &content_block)
|
27
|
+
init_component(args, [:content, :title, :author, :attributes], &content_block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "init_component" do
|
32
|
+
context "custom component" do
|
33
|
+
before :all do
|
34
|
+
@news_content = "The pope claims that condoms are not necessarily evil. Where is this heading to?"
|
35
|
+
# TODO support for special character removal pending
|
36
|
+
#@news_title = "Scandal in the Vatican!"
|
37
|
+
@news_title = "Scandal in the Vatican"
|
38
|
+
@news_author = "Karl Atzinger"
|
39
|
+
@news_attributes = {:class => 'gossip', :title => 'click to read whole article'}
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should set all parameters correctly when given in order" do
|
43
|
+
n = NewsWidget.new @news_content, @news_title, @news_author, {:class => 'gossip'}
|
44
|
+
n.content.should == @news_content
|
45
|
+
n.title.should == @news_title
|
46
|
+
n.author.should == @news_author
|
47
|
+
n.attributes.should == {:class => ['scandal-in-the-vatican', 'news-widget', 'gossip']}
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should set all parameters correctly when given as key value pairs" do
|
51
|
+
n = NewsWidget.new :attributes => @news_attributes, :title => @news_title, :content => @news_content, :author => @news_author
|
52
|
+
n.content.should == @news_content
|
53
|
+
n.title.should == @news_title
|
54
|
+
n.author.should == @news_author
|
55
|
+
n.attributes.should == {:title => @news_attributes[:title], :class => ['scandal-in-the-vatican', 'news-widget', 'gossip']}
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should set all parameters correctly when given in a mixed way" do
|
59
|
+
n = NewsWidget.new @news_title, @news_author, :content => @news_content, :attributes => @news_attributes
|
60
|
+
n.content.should == @news_content
|
61
|
+
n.title.should == @news_title
|
62
|
+
n.author.should == @news_author
|
63
|
+
n.attributes.should == {:title => @news_attributes[:title], :class => ['scandal-in-the-vatican', 'news-widget', 'gossip']}
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should prioritize content blocks over content arguments" do
|
67
|
+
n = NewsWidget.new(:content => "ignorable") { @news_content }
|
68
|
+
n.content.should == @news_content
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should fill @attributes with remaining arguments of the last hash" do
|
72
|
+
n = NewsWidget.new @news_title, :id => 'news', :content => @news_content, :class => @news_attributes[:class]
|
73
|
+
n.content.should == @news_content
|
74
|
+
n.title.should == @news_title
|
75
|
+
n.attributes.should == {:id => 'news', :class => ['scandal-in-the-vatican', 'news-widget', 'gossip']}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "html wrapper component (grand-child of base)" do
|
80
|
+
before :all do
|
81
|
+
@bq_content = "It is better to be quotable than to be honest."
|
82
|
+
@bq_title = "Tom Stoppard on Quotations"
|
83
|
+
@bq_attributes = {:class => 'quotes', :cites => "http://www.quotationspage.com/quote/368.html"}
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should set all parameters correctly when given in order" do
|
87
|
+
bq = Blockquote.new @bq_content, @bq_title, @bq_author, @bq_attributes
|
88
|
+
bq.content.should == @bq_content
|
89
|
+
bq.title.should == @bq_title
|
90
|
+
bq.attributes.should == {:cites => @bq_attributes[:cites], :class => [@bq_title.hyphenize, 'quotes']}
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should set all parameters correctly when given as key value pairs" do
|
94
|
+
bq = Blockquote.new :attributes => @bq_attributes, :title => @bq_title, :content => @bq_content
|
95
|
+
bq.content.should == @bq_content
|
96
|
+
bq.title.should == @bq_title
|
97
|
+
bq.attributes.should == {:cites => @bq_attributes[:cites], :class => [@bq_title.hyphenize, 'quotes']}
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should set all parameters correctly when given in a mixed way" do
|
101
|
+
bq = Blockquote.new @bq_title, :content => @bq_content, :attributes => @bq_attributes
|
102
|
+
bq.content.should == @bq_content
|
103
|
+
bq.title.should == @bq_title
|
104
|
+
bq.attributes.should == {:cites => @bq_attributes[:cites], :class => [@bq_title.hyphenize, 'quotes']}
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should prioritize content blocks over content arguments" do
|
108
|
+
bq = Blockquote.new(:content => "ignorable") { @bq_content }
|
109
|
+
bq.content.should == @bq_content
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should fill attributes with remaining arguments of the last hash" do
|
113
|
+
bq = Blockquote.new @bq_title, :cites => "http://www.quotationspage.com/quote/368.html", :content => @bq_content, :class => 'quotes'
|
114
|
+
bq.content.should == @bq_content
|
115
|
+
bq.title.should == @bq_title
|
116
|
+
bq.attributes.should == {:cites => @bq_attributes[:cites], :class => [@bq_title.hyphenize, 'quotes']}
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "tree node management" do
|
124
|
+
it "should enable to add nodes as children" do
|
125
|
+
a = Block.new
|
126
|
+
b = Block.new("foo")
|
127
|
+
c = Block.new("bar")
|
128
|
+
a << b
|
129
|
+
a << c
|
130
|
+
a[b.object_id].should == b
|
131
|
+
children = []
|
132
|
+
a.children {|child| children << child.node_name}
|
133
|
+
children.should == [b.object_id, c.object_id]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "instantiation helpers" do
|
138
|
+
it "should be available after creating a component" do
|
139
|
+
class NewGreetingBox < ActiveComponent::Base; end
|
140
|
+
ActiveComponent.instance_methods.map(&:to_sym).should be_include(:new_greeting_box)
|
141
|
+
end
|
142
|
+
|
143
|
+
# TODO: How to test this?
|
144
|
+
it "should be available to ActionView and render output"
|
145
|
+
# class GreetingBox < ActiveComponent::Base
|
146
|
+
# def initialize(*args, &content_block); init_component(args, [:content], &content_block); end
|
147
|
+
# def to_html; Span.new("Hello " + print_object(content), :class => 'greeting').to_html; end
|
148
|
+
# end
|
149
|
+
# ActiveComponent::TemplateHandler.new.instance_eval { compile(greeting_box("world")) }.should == "not specified yet"
|
150
|
+
# end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Block do
|
4
|
+
include ActiveComponent
|
5
|
+
include Haml::Helpers
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@content = "It is better to be quotable than to be honest."
|
9
|
+
@title = "Tom Stoppard on Quotations"
|
10
|
+
@tag_type = :blockquote
|
11
|
+
@attributes = {:class => 'quotes', :cites => "http://www.quotationspage.com/quote/368.html"}
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "initialize" do
|
15
|
+
it "should assume :div as default block type" do
|
16
|
+
block = Block.new { @content }
|
17
|
+
block.tag_type.should == :div
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should not be possible to overwrite tag_type for subclasses of Block" do
|
21
|
+
for elem in ActiveComponent::BLOCK_ELEMENTS
|
22
|
+
elem_class = elem.to_s.camelize.constantize
|
23
|
+
block = elem_class.new(:tag_type => :block) { @content }
|
24
|
+
block.tag_type.should == elem
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "to_html" do
|
30
|
+
it "should render nested blocks" do
|
31
|
+
init_buffer
|
32
|
+
block = Block.new @title, @tag_type, @attributes do
|
33
|
+
[
|
34
|
+
Block.new(@title, :tag_type => :h1),
|
35
|
+
Block.new(@content, :tag_type => :p),
|
36
|
+
Block.new("Details", :tag_type => :aside) do
|
37
|
+
print_buffer do
|
38
|
+
tag_to_buffer :dl do
|
39
|
+
tag_to_buffer :dt, "Author"
|
40
|
+
tag_to_buffer :dd, "Tom Stoppard"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
]
|
45
|
+
end
|
46
|
+
block.to_html.should == "<#{@tag_type} cites='#{@attributes[:cites]}' class='#{@title.hyphenize} block #{@attributes[:class]}'>\n <h1 class='block'>\n #{@title}\n </h1>\n <p class='block'>\n #{@content}\n </p>\n <aside class='details block'>\n <dl>\n <dt>Author</dt>\n <dd>Tom Stoppard</dd>\n </dl>\n \n </aside>\n \n</#{@tag_type}>\n"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Heading do
|
4
|
+
include ActiveComponent
|
5
|
+
include Haml::Helpers
|
6
|
+
|
7
|
+
before :all do
|
8
|
+
@content = "Wall Street Retreats in the Face of a Slowdown"
|
9
|
+
@title = "Business News"
|
10
|
+
@level = 3
|
11
|
+
@attributes = {:class => 'news business'}
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "siblings_level" do
|
15
|
+
|
16
|
+
it "should adopt correct siblings level" do
|
17
|
+
h1 = Heading.new('header 1', :level => 3)
|
18
|
+
h2 = Heading.new
|
19
|
+
h3 = Heading.new [h1, h2]
|
20
|
+
h2.siblings_level.should == 3
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return nil if no heading sibling exists" do
|
24
|
+
h1 = Heading.new
|
25
|
+
h2 = Heading.new h1
|
26
|
+
h1.siblings_level.should be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return nil if existing heading sibling has no rank" do
|
30
|
+
h1 = Heading.new('header 1')
|
31
|
+
h2 = Heading.new
|
32
|
+
h3 = Heading.new [h1, h2]
|
33
|
+
h2.siblings_level.should be_nil
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "determine_level" do
|
39
|
+
|
40
|
+
it "should return the rank of a given sibling Heading" do
|
41
|
+
h1 = Heading.new(:level => 3)
|
42
|
+
h2 = Heading.new
|
43
|
+
h3 = Heading.new([h1, h2])
|
44
|
+
|
45
|
+
h2.determine_level.should == 3
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should determine heading rank correctly based on the hierarchy" do
|
49
|
+
h1 = Heading.new('header 1')
|
50
|
+
h2 = Heading.new('header 2')
|
51
|
+
h3 = Heading.new('header 3')
|
52
|
+
div2 = Div.new(:content => [h2, h3])
|
53
|
+
div = Div.new(:content => [
|
54
|
+
h1,
|
55
|
+
div2
|
56
|
+
])
|
57
|
+
h2.determine_level.should == 2
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
describe "to_html" do
|
64
|
+
|
65
|
+
it "should compute heading levels automatically based on the node hierarchy" do
|
66
|
+
section = Section.new(:heading => @title, :content => [
|
67
|
+
Heading.new("It's better to be honest!"),
|
68
|
+
Section.new(:heading => "Tom Stoppard", :content => [
|
69
|
+
Div.new(:title => "Some div inbetween", :content => [
|
70
|
+
Heading.new("Yet Another Heading"),
|
71
|
+
Section.new("Details", :heading => "Leaf Heading")
|
72
|
+
])
|
73
|
+
])
|
74
|
+
])
|
75
|
+
section.to_html.should == "<section>\n <h1 class='heading'>\n Business News\n </h1>\n \n <h1 class='heading'>\n It's better to be honest!\n </h1>\n \n <section>\n <h2 class='heading'>\n Tom Stoppard\n </h2>\n \n <div class='some-div-inbetween'>\n <h3 class='heading'>\n Yet Another Heading\n </h3>\n \n <section>\n <h4 class='heading'>\n Leaf Heading\n </h4>\n \n Details\n </section>\n \n </div>\n \n </section>\n \n</section>\n"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should compute heading levels automatically also when block syntax used" do
|
79
|
+
section = Section.new(:heading => @title, :content => [
|
80
|
+
Heading.new("It's better to be honest!"),
|
81
|
+
Section.new(:heading => "Tom Stoppard", :content => [
|
82
|
+
Div.new(:title => "Some div inbetween") do
|
83
|
+
[
|
84
|
+
Heading.new("Yet Another Heading"),
|
85
|
+
Section.new("Details", :heading => "Leaf Heading")
|
86
|
+
]
|
87
|
+
end
|
88
|
+
])
|
89
|
+
])
|
90
|
+
section.to_html.should == "<section>\n <h1 class='heading'>\n Business News\n </h1>\n \n <h1 class='heading'>\n It's better to be honest!\n </h1>\n \n <section>\n <h2 class='heading'>\n Tom Stoppard\n </h2>\n \n <div class='some-div-inbetween'>\n <h3 class='heading'>\n Yet Another Heading\n </h3>\n \n <section>\n <h4 class='heading'>\n Leaf Heading\n </h4>\n \n Details\n </section>\n \n </div>\n \n </section>\n \n</section>\n"
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Section do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@content = "It is better to be quotable than to be honest."
|
7
|
+
@title = "Tom Stoppard on Quotations"
|
8
|
+
@tag_type = :blockquote
|
9
|
+
@attributes = {:class => 'quotes', :cites => "http://www.quotationspage.com/quote/368.html"}
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "initialize" do
|
13
|
+
it "should assume :section as default section type" do
|
14
|
+
section = Section.new @content
|
15
|
+
section.tag_type.should == :section
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should not be possible to overwrite tag_type for subclasses of section" do
|
19
|
+
for elem in ActiveComponent::SECTION_ELEMENTS
|
20
|
+
elem_class = elem.to_s.camelize.constantize
|
21
|
+
section = elem_class.new(:tag_type => :section) { @content }
|
22
|
+
section.tag_type.should == elem
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "to_html" do
|
28
|
+
it "should be able to render nested sections"
|
29
|
+
|
30
|
+
it "should be able to render section subclasses" do
|
31
|
+
b = Blockquote.new(@content, @title, @attributes)
|
32
|
+
b.to_html.should == "<blockquote cites='http://www.quotationspage.com/quote/368.html' class='tom-stoppard-on-quotations quotes'>\n It is better to be quotable than to be honest.\n</blockquote>"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Table do
|
4
|
+
|
5
|
+
def things
|
6
|
+
things = []
|
7
|
+
things << Factory.build(:thing, :name => "thingamabob", :color => :yellow)
|
8
|
+
things << Factory.build(:thing, :name => "whatchamacallit", :color => :red)
|
9
|
+
things << Factory.build(:thing, :name => "gizmo", :color => :blue)
|
10
|
+
things
|
11
|
+
end
|
12
|
+
|
13
|
+
context "rendering a matrix of primitive data" do
|
14
|
+
it "should render without further input" do
|
15
|
+
content = [["a", 1, "first entry"], ["b", 2, "second entry"]]
|
16
|
+
table = Table.new content
|
17
|
+
table.to_html.should == "<table cellspacing='0' class='arrays'>\n <tr>\n <td>a</td>\n <td>1</td>\n <td>first entry</td>\n </tr>\n <tr>\n <td>b</td>\n <td>2</td>\n <td>second entry</td>\n </tr>\n</table>\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should render correctly with all inputs set" do
|
21
|
+
content = [["a", 1, "first entry"], ["b", 2, "second entry"]]
|
22
|
+
table = Table.new content, 'examples', :cols => :to_s, :headers => ["char", "number", "entry"]
|
23
|
+
table.to_html.should == "<table cellspacing='0' class='examples'>\n <tr>\n <th>char</th>\n <th>number</th>\n <th>entry</th>\n </tr>\n <tr>\n <td>a</td>\n <td>1</td>\n <td>first entry</td>\n </tr>\n <tr>\n <td>b</td>\n <td>2</td>\n <td>second entry</td>\n </tr>\n</table>\n"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "rendering a collection of complex objects (e.g. instances of an Active Record model)" do
|
28
|
+
it "should render without further input" do
|
29
|
+
things = [Factory.build(:thing), Factory.build(:thing, :name => "Whatchamacallit", :color => :red)]
|
30
|
+
table = Table.new things
|
31
|
+
table.to_html.should == "<table cellspacing='0' class='things'>\n <tr>\n <th>Name</th>\n <th>Color</th>\n </tr>\n <tr>\n <td>Thingamabob</td>\n <td>yellow</td>\n </tr>\n <tr>\n <td>Whatchamacallit</td>\n <td>red</td>\n </tr>\n</table>\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should render complex ojects correctly with all inputs set" do
|
35
|
+
color_temperature = proc {|thing| [:yellow, :orange, :red].include?(thing.color) ? "warm" : "cold"}
|
36
|
+
table = Table.new things, 'things-table', :cols => [:name, color_temperature], :headers => ["Name", "Color Temperature"]
|
37
|
+
table.to_html.should == "<table cellspacing='0' class='things-table'>\n <tr>\n <th>Name</th>\n <th>Color Temperature</th>\n </tr>\n <tr>\n <td>thingamabob</td>\n <td>warm</td>\n </tr>\n <tr>\n <td>whatchamacallit</td>\n <td>warm</td>\n </tr>\n <tr>\n <td>gizmo</td>\n <td>cold</td>\n </tr>\n</table>\n"
|
38
|
+
end
|
39
|
+
|
40
|
+
# According Haml template code
|
41
|
+
#-----------------------------
|
42
|
+
# %table
|
43
|
+
# %tr
|
44
|
+
# %th Name
|
45
|
+
# %th Reverse Name
|
46
|
+
# %th Color Temperature
|
47
|
+
# - @things.each |thing| do
|
48
|
+
# %tr
|
49
|
+
# %td= thing.name
|
50
|
+
# %td= thing.name.reverse
|
51
|
+
# %td.color-temp
|
52
|
+
# - temp = [:yellow, :orange, :red].include?(thing.color) ? "warm" : "cold"
|
53
|
+
# %span{:class => temp}
|
54
|
+
# = temp + "!"
|
55
|
+
it "should render complex ojects using other components" do
|
56
|
+
table = Table.new(things, 'things-table', :headers => ["Name", "Color Temperature"], :cols => [
|
57
|
+
:name,
|
58
|
+
proc {|thing| thing.name.reverse},
|
59
|
+
proc do |thing|
|
60
|
+
temp = [:yellow, :orange, :red].include?(thing.color) ? "warm" : "cold"
|
61
|
+
Span.new(temp + "!", :class => temp)
|
62
|
+
end
|
63
|
+
])
|
64
|
+
table.to_html.should == "<table cellspacing='0' class='things-table'>\n <tr>\n <th>Name</th>\n <th>Color Temperature</th>\n </tr>\n <tr>\n <td>thingamabob</td>\n <td>bobamagniht</td>\n <td>\n <span class='warm'>\n warm!\n </span>\n \n </td>\n </tr>\n <tr>\n <td>whatchamacallit</td>\n <td>tillacamahctahw</td>\n <td>\n <span class='warm'>\n warm!\n </span>\n \n </td>\n </tr>\n <tr>\n <td>gizmo</td>\n <td>omzig</td>\n <td>\n <span class='cold'>\n cold!\n </span>\n \n </td>\n </tr>\n</table>\n"
|
65
|
+
end
|
66
|
+
#
|
67
|
+
# it "should render using short hand helper functions"
|
68
|
+
# pending {}
|
69
|
+
# #tab = table(things, 'color-table', :cols => [ col(:name, 'Name'), col(nil, 'Reverse Name') {|thing| thing.name.reverse} ])
|
70
|
+
# #col(:title => 'Color Temperature', :class => 'color-temp') { |thing|
|
71
|
+
# # temp = [:yellow, :orange, :red].include?(thing.color) ? "warm" : "cold"
|
72
|
+
# # span(temp + "!", :class => temp)
|
73
|
+
# #}
|
74
|
+
# #tab.to_html.should == "not specified yet"
|
75
|
+
# end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "passing HTML attributes" do
|
79
|
+
it "should forward attributes for headers" do
|
80
|
+
table = Table.new things, :title => "my-things",
|
81
|
+
:style => "padding: 10px", :class => "custom-class", :cellpadding => 0,
|
82
|
+
:header_attrs => [{:class => 'name-header', :width => '200px'}, {:id => 'temp-col-header', :style => 'color: red'}]
|
83
|
+
table.row_attrs = [{:class => 'head-row'}] + table.content.map {|thing| {:class => thing.name}}
|
84
|
+
table.to_html.should == "<table cellpadding='0' cellspacing='0' class='my-things custom-class' style='padding: 10px'>\n <tr class='head-row'>\n <th class='name-header' width='200px'>Name</th>\n <th id='temp-col-header' style='color: red'>Color</th>\n </tr>\n <tr class='thingamabob'>\n <td>thingamabob</td>\n <td>yellow</td>\n </tr>\n <tr class='whatchamacallit'>\n <td>whatchamacallit</td>\n <td>red</td>\n </tr>\n <tr class='gizmo'>\n <td>gizmo</td>\n <td>blue</td>\n </tr>\n</table>\n"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#TODO transmogrify on more than 2 levels
|
4
|
+
|
5
|
+
describe Object do
|
6
|
+
|
7
|
+
context "transmogrify" do
|
8
|
+
it "should yield self if its not enumerable" do
|
9
|
+
block = Proc.new {|x| x.to_s.to_sym}
|
10
|
+
obj = Object.new
|
11
|
+
obj.transmogrify(&block).should eql(block.call(obj))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
context "transmogrify_with_index" do
|
15
|
+
it "should not differ from transmogrify" do
|
16
|
+
block = Proc.new {|x| x.to_s.to_sym}
|
17
|
+
obj = Object.new
|
18
|
+
obj.transmogrify_with_index(&block).should eql(obj.transmogrify(&block))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
describe Enumerable do
|
25
|
+
|
26
|
+
context "transmogrify" do
|
27
|
+
before(:each) do
|
28
|
+
@has_yielded = false
|
29
|
+
@results = []
|
30
|
+
@block = Proc.new do |x|
|
31
|
+
@results << x.to_s.to_sym
|
32
|
+
@has_yielded = true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
it "should yield each element" do
|
36
|
+
%w(a b c).transmogrify(&@block)
|
37
|
+
@has_yielded.should be_true
|
38
|
+
@results.should eql([:a, :b, :c])
|
39
|
+
end
|
40
|
+
after(:each) do
|
41
|
+
@has_yielded, @results, @block = nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "transmogrify_with_index" do
|
46
|
+
before(:each) do
|
47
|
+
@has_yielded = false
|
48
|
+
@results = {}
|
49
|
+
@block = Proc.new do |elem, index|
|
50
|
+
@results[index] = elem.to_s.to_sym
|
51
|
+
end
|
52
|
+
end
|
53
|
+
it "should yield each element with index" do
|
54
|
+
%w(a b c).transmogrify_with_index(&@block)
|
55
|
+
@results.should == { 0 => :a, 1 => :b, 2 => :c }
|
56
|
+
end
|
57
|
+
after(:each) do
|
58
|
+
@result, @results, @block = nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|