apotomo 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +10 -0
- data/Gemfile.lock +47 -0
- data/README +141 -0
- data/README.rdoc +141 -0
- data/Rakefile +78 -0
- data/TODO +36 -0
- data/app/cells/apotomo/child_switch_widget/switch.html.erb +1 -0
- data/app/cells/apotomo/child_switch_widget/switch.rhtml +1 -0
- data/app/cells/apotomo/deep_link_widget.rb +27 -0
- data/app/cells/apotomo/deep_link_widget/setup.html.erb +20 -0
- data/app/cells/apotomo/java_script_widget.rb +12 -0
- data/app/cells/apotomo/tab_panel_widget.rb +87 -0
- data/app/cells/apotomo/tab_panel_widget/display.html.erb +57 -0
- data/app/cells/apotomo/tab_widget.rb +18 -0
- data/app/cells/apotomo/tab_widget/display.html.erb +1 -0
- data/config/routes.rb +3 -0
- data/generators/widget/USAGE +15 -0
- data/generators/widget/templates/functional_test.rb +8 -0
- data/generators/widget/templates/view.html.erb +2 -0
- data/generators/widget/templates/view.html.haml +3 -0
- data/generators/widget/templates/widget.rb +8 -0
- data/generators/widget/widget_generator.rb +34 -0
- data/lib/apotomo.rb +59 -0
- data/lib/apotomo/caching.rb +37 -0
- data/lib/apotomo/container_widget.rb +10 -0
- data/lib/apotomo/deep_link_methods.rb +90 -0
- data/lib/apotomo/event.rb +9 -0
- data/lib/apotomo/event_handler.rb +23 -0
- data/lib/apotomo/event_methods.rb +102 -0
- data/lib/apotomo/invoke_event_handler.rb +24 -0
- data/lib/apotomo/javascript_generator.rb +57 -0
- data/lib/apotomo/persistence.rb +139 -0
- data/lib/apotomo/proc_event_handler.rb +18 -0
- data/lib/apotomo/rails/controller_methods.rb +161 -0
- data/lib/apotomo/rails/view_helper.rb +95 -0
- data/lib/apotomo/rails/view_methods.rb +7 -0
- data/lib/apotomo/request_processor.rb +92 -0
- data/lib/apotomo/stateful_widget.rb +8 -0
- data/lib/apotomo/transition.rb +46 -0
- data/lib/apotomo/tree_node.rb +186 -0
- data/lib/apotomo/version.rb +5 -0
- data/lib/apotomo/widget.rb +289 -0
- data/lib/apotomo/widget_shortcuts.rb +36 -0
- data/rails/init.rb +0 -0
- data/test/fixtures/application_widget_tree.rb +2 -0
- data/test/rails/controller_methods_test.rb +206 -0
- data/test/rails/rails_integration_test.rb +99 -0
- data/test/rails/view_helper_test.rb +77 -0
- data/test/rails/view_methods_test.rb +40 -0
- data/test/rails/widget_generator_test.rb +47 -0
- data/test/support/assertions_helper.rb +13 -0
- data/test/support/test_case_methods.rb +68 -0
- data/test/test_helper.rb +77 -0
- data/test/unit/apotomo_test.rb +20 -0
- data/test/unit/container_test.rb +20 -0
- data/test/unit/event_handler_test.rb +67 -0
- data/test/unit/event_methods_test.rb +83 -0
- data/test/unit/event_test.rb +30 -0
- data/test/unit/invoke_test.rb +123 -0
- data/test/unit/javascript_generator_test.rb +90 -0
- data/test/unit/onfire_integration_test.rb +19 -0
- data/test/unit/persistence_test.rb +240 -0
- data/test/unit/render_test.rb +203 -0
- data/test/unit/request_processor_test.rb +178 -0
- data/test/unit/stateful_widget_test.rb +135 -0
- data/test/unit/test_addressing.rb +111 -0
- data/test/unit/test_caching.rb +54 -0
- data/test/unit/test_jump_to_state.rb +89 -0
- data/test/unit/test_tab_panel.rb +72 -0
- data/test/unit/test_widget_shortcuts.rb +45 -0
- data/test/unit/transition_test.rb +33 -0
- data/test/unit/widget_shortcuts_test.rb +68 -0
- data/test/unit/widget_test.rb +24 -0
- metadata +215 -0
@@ -0,0 +1,203 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. test_helper])
|
2
|
+
|
3
|
+
class RenderTest < ActionView::TestCase
|
4
|
+
context "Rendering a single widget" do
|
5
|
+
setup do
|
6
|
+
@mum = mouse_mock
|
7
|
+
end
|
8
|
+
|
9
|
+
should "per default display the state content framed in a div" do
|
10
|
+
assert_equal '<div id="mouse">burp!</div>', @mum.invoke(:eating)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "with :text" do
|
14
|
+
setup do
|
15
|
+
@mum.instance_eval { def eating; render :text => "burp!!!"; end }
|
16
|
+
end
|
17
|
+
|
18
|
+
should "render the :text" do
|
19
|
+
assert_equal "burp!!!", @mum.invoke
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
context "with :suppress_js" do
|
25
|
+
setup do
|
26
|
+
@mum.instance_eval do
|
27
|
+
def snuggle; render; end
|
28
|
+
self.class.send :attr_reader, :suppress_js
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
should "per default be false" do
|
33
|
+
@mum.invoke :snuggle
|
34
|
+
assert !@mum.suppress_js
|
35
|
+
end
|
36
|
+
|
37
|
+
should "be true when set" do
|
38
|
+
@mum.instance_eval do
|
39
|
+
def snuggle; render :suppress_js => true; end
|
40
|
+
end
|
41
|
+
@mum.invoke :snuggle
|
42
|
+
assert @mum.suppress_js
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
should "expose its instance variables in the rendered view" do
|
47
|
+
@mum = mouse_mock('mum', :educate) do
|
48
|
+
def educate
|
49
|
+
@who = "the cat"
|
50
|
+
@what = "run away"
|
51
|
+
render
|
52
|
+
end
|
53
|
+
end
|
54
|
+
assert_equal 'If you see the cat do run away!', @mum.invoke(:educate)
|
55
|
+
end
|
56
|
+
|
57
|
+
context "with #emit" do
|
58
|
+
setup do
|
59
|
+
@kid = mouse_mock('kid', :squeak)
|
60
|
+
@kid.instance_eval do
|
61
|
+
def squeak
|
62
|
+
render :text => "squeeeeaaak"
|
63
|
+
end
|
64
|
+
|
65
|
+
def render(*)
|
66
|
+
@rendered = true
|
67
|
+
super
|
68
|
+
end
|
69
|
+
def rendered?; @rendered; end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "and :text" do
|
74
|
+
setup do
|
75
|
+
@mum.instance_eval do
|
76
|
+
def squeak
|
77
|
+
emit :text => "squeak();"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
should "just return the plain :text" do
|
83
|
+
assert_equal 'squeak();', @mum.invoke(:squeak)
|
84
|
+
end
|
85
|
+
|
86
|
+
should "not render children" do
|
87
|
+
@mum << @kid
|
88
|
+
@mum.invoke(:squeak)
|
89
|
+
|
90
|
+
assert_not @kid.rendered?
|
91
|
+
end
|
92
|
+
|
93
|
+
should "allow rendering children" do
|
94
|
+
@mum.instance_eval do
|
95
|
+
def squeak
|
96
|
+
emit :text => "squeak();", :render_children => true
|
97
|
+
end
|
98
|
+
end
|
99
|
+
@mum << @kid
|
100
|
+
@mum.invoke(:squeak)
|
101
|
+
|
102
|
+
assert @kid.rendered?
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "and no options" do
|
107
|
+
setup do
|
108
|
+
@mum.instance_eval do
|
109
|
+
def squeak
|
110
|
+
emit
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
should "render the view" do
|
116
|
+
assert_equal "<div id=\"mouse\">burp!</div>", @mum.invoke(:eating)
|
117
|
+
end
|
118
|
+
|
119
|
+
should "render the children, too" do
|
120
|
+
@mum << @kid
|
121
|
+
@mum.invoke(:eating)
|
122
|
+
assert @kid.rendered?
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context "and :view" do
|
127
|
+
setup do
|
128
|
+
@mum.instance_eval do
|
129
|
+
def squeak
|
130
|
+
emit :view => :snuggle
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
should "render the :view" do
|
136
|
+
assert_equal "<div id=\"mouse\"><snuggle></snuggle></div>", @mum.invoke(:squeak)
|
137
|
+
end
|
138
|
+
|
139
|
+
should "render the children" do
|
140
|
+
@mum << @kid
|
141
|
+
|
142
|
+
assert_equal "<div id=\"mouse\"><snuggle>squeeeeaaak</snuggle></div>", @mum.invoke(:squeak)
|
143
|
+
assert @kid.rendered?
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "with #update" do
|
149
|
+
setup do
|
150
|
+
Apotomo.js_framework = :prototype
|
151
|
+
end
|
152
|
+
|
153
|
+
should "wrap the :text in an update statement" do
|
154
|
+
@mum.instance_eval do
|
155
|
+
def squeak
|
156
|
+
update :text => "squeak!"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
assert_equal "$(\"mouse\").update(\"squeak!\")", @mum.invoke(:squeak)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "with #replace" do
|
164
|
+
setup do
|
165
|
+
Apotomo.js_framework = :prototype
|
166
|
+
end
|
167
|
+
|
168
|
+
should "wrap the :text in a replace statement" do
|
169
|
+
@mum.instance_eval do
|
170
|
+
def squeak
|
171
|
+
replace :text => '<div id="mum">squeak!</div>'
|
172
|
+
end
|
173
|
+
end
|
174
|
+
assert_equal "$(\"mouse\").replace(\"<div id=\\\"mum\\\">squeak!<\\/div>\")", @mum.invoke(:squeak)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "rendering a widget family" do
|
180
|
+
setup do
|
181
|
+
@mum = mouse_mock('mum', :snuggle) do
|
182
|
+
def snuggle; render; end
|
183
|
+
end
|
184
|
+
|
185
|
+
@mum << @kid = mouse_mock('kid')
|
186
|
+
end
|
187
|
+
|
188
|
+
should "per default render kid's content inside mums div with rendered_children" do
|
189
|
+
assert_equal '<div id="mum"><snuggle><div id="kid">burp!</div></snuggle></div>', @mum.invoke(:snuggle)
|
190
|
+
end
|
191
|
+
|
192
|
+
should "skip kids if :render_children=>false but still provide a rendered_children hash" do
|
193
|
+
@mum.instance_eval do
|
194
|
+
def snuggle; render :render_children => false; end
|
195
|
+
end
|
196
|
+
|
197
|
+
assert_equal '<div id="mum"><snuggle></snuggle></div>', @mum.invoke(:snuggle)
|
198
|
+
end
|
199
|
+
|
200
|
+
should_eventually "provide an ordered rendered_children hash"
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. test_helper])
|
2
|
+
|
3
|
+
class RequestProcessorTest < Test::Unit::TestCase
|
4
|
+
context "#root" do
|
5
|
+
should "allow external modification of the tree" do
|
6
|
+
@processor = Apotomo::RequestProcessor.new({})
|
7
|
+
root = @processor.root
|
8
|
+
root << mouse_mock
|
9
|
+
assert_equal 2, @processor.root.size
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "option processing at construction time" do
|
14
|
+
context "with empty session and options" do
|
15
|
+
setup do
|
16
|
+
@processor = Apotomo::RequestProcessor.new({})
|
17
|
+
end
|
18
|
+
|
19
|
+
should "mark the tree as flushed" do
|
20
|
+
assert @processor.widgets_flushed?
|
21
|
+
end
|
22
|
+
|
23
|
+
should "provide a single root-node for #root" do
|
24
|
+
assert_equal 1, @processor.root.size
|
25
|
+
end
|
26
|
+
|
27
|
+
should "initialize version to 0" do
|
28
|
+
assert_equal 0, @processor.root.version
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "with session" do
|
33
|
+
setup do
|
34
|
+
mum_and_kid!
|
35
|
+
@mum.version = 1
|
36
|
+
@session = {:apotomo_stateful_branches => [[@mum, 'root']]}
|
37
|
+
@processor = Apotomo::RequestProcessor.new(@session)
|
38
|
+
end
|
39
|
+
|
40
|
+
should "provide a widget family for #root" do
|
41
|
+
assert_equal 3, @processor.root.size
|
42
|
+
assert_equal 1, @processor.root['mum'].version
|
43
|
+
assert_not @processor.widgets_flushed?
|
44
|
+
end
|
45
|
+
|
46
|
+
context "having a flush flag set" do
|
47
|
+
setup do
|
48
|
+
@processor = Apotomo::RequestProcessor.new(@session, :flush_widgets => true)
|
49
|
+
end
|
50
|
+
|
51
|
+
should "provide a single root for #root when :flush_widgets is set" do
|
52
|
+
assert_equal 1, @processor.root.size
|
53
|
+
assert @processor.widgets_flushed?
|
54
|
+
end
|
55
|
+
|
56
|
+
should "wipe-out our session variables" do
|
57
|
+
assert_nil @session[:apotomo_stateful_branches]
|
58
|
+
assert_nil @session[:apotomo_widget_ivars]
|
59
|
+
end
|
60
|
+
|
61
|
+
should ""
|
62
|
+
end
|
63
|
+
|
64
|
+
context "and with stateless widgets" do
|
65
|
+
setup do
|
66
|
+
@session = {:apotomo_stateful_branches => [[@mum, 'grandma']]}
|
67
|
+
@processor = Apotomo::RequestProcessor.new(@session, {}, [Proc.new { |root| root << Apotomo::Widget.new('grandma', :eating) }])
|
68
|
+
end
|
69
|
+
|
70
|
+
should "first attach passed stateless, then stateful widgets to root" do
|
71
|
+
assert_equal 4, @processor.root.size
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
context "#process_for" do
|
79
|
+
setup do
|
80
|
+
### FIXME: what about that automatic @controller everywhere?
|
81
|
+
mum_and_kid!
|
82
|
+
@mum.controller = nil # check if controller gets connected.
|
83
|
+
@processor = Apotomo::RequestProcessor.new({:apotomo_stateful_branches => [[@mum, 'root']]}, :js_framework => :prototype)
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
@kid.respond_to_event :doorSlam, :with => :eating, :on => 'mum'
|
90
|
+
@kid.respond_to_event :doorSlam, :with => :squeak
|
91
|
+
@mum.respond_to_event :doorSlam, :with => :squeak
|
92
|
+
|
93
|
+
@mum.instance_eval do
|
94
|
+
def squeak; render :js => 'squeak();'; end
|
95
|
+
end
|
96
|
+
@kid.instance_eval do
|
97
|
+
def squeak; render :text => 'squeak!', :update => :true; end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
should "return 2 page_updates when @kid squeaks" do
|
102
|
+
res = @processor.process_for({:type => :squeak, :source => 'kid'}, @controller)
|
103
|
+
|
104
|
+
assert_equal ["alert!", "squeak"], res
|
105
|
+
end
|
106
|
+
|
107
|
+
should "raise an exception when :source is unknown" do
|
108
|
+
assert_raises RuntimeError do
|
109
|
+
@processor.process_for({:type => :squeak, :source => 'tom'}, @controller)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
context "#freeze!" do
|
117
|
+
should "serialize stateful branches to @session" do
|
118
|
+
@processor = Apotomo::RequestProcessor.new({})
|
119
|
+
@processor.root << mum_and_kid!
|
120
|
+
assert_equal 3, @processor.root.size
|
121
|
+
@processor.freeze!
|
122
|
+
|
123
|
+
@processor = Apotomo::RequestProcessor.new(@processor.session)
|
124
|
+
assert_equal 3, @processor.root.size
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context "#render_widget_for" do
|
129
|
+
setup do
|
130
|
+
@mum = mouse_mock('mum', :snuggle) do
|
131
|
+
def snuggle; render; end
|
132
|
+
end
|
133
|
+
@mum.controller = nil
|
134
|
+
|
135
|
+
@processor = Apotomo::RequestProcessor.new({:apotomo_stateful_branches => [[@mum, 'root']]})
|
136
|
+
end
|
137
|
+
|
138
|
+
should "render the widget when passing an existing widget id" do
|
139
|
+
assert_equal '<div id="mum"><snuggle></snuggle></div>', @processor.render_widget_for('mum', {}, @controller)
|
140
|
+
end
|
141
|
+
|
142
|
+
should "render the widget when passing an existing widget instance" do
|
143
|
+
assert_equal '<div id="mum"><snuggle></snuggle></div>', @processor.render_widget_for(@mum, {}, @controller)
|
144
|
+
end
|
145
|
+
|
146
|
+
should "raise an exception when a non-existent widget id id passed" do
|
147
|
+
assert_raises RuntimeError do
|
148
|
+
@processor.render_widget_for('mummy', {}, @controller)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context "invoking #address_for" do
|
154
|
+
setup do
|
155
|
+
@processor = Apotomo::RequestProcessor.new({})
|
156
|
+
end
|
157
|
+
|
158
|
+
should "accept an event :type" do
|
159
|
+
assert_equal({:type => :squeak, :source => 'mum'}, @processor.address_for(:type => :squeak, :source => 'mum'))
|
160
|
+
end
|
161
|
+
|
162
|
+
should "accept arbitrary options" do
|
163
|
+
assert_equal({:type => :squeak, :volume => 'loud', :source => 'mum'}, @processor.address_for(:type => :squeak, :volume => 'loud', :source => 'mum'))
|
164
|
+
end
|
165
|
+
|
166
|
+
should "complain if no type given" do
|
167
|
+
assert_raises RuntimeError do
|
168
|
+
@processor.address_for(:source => 'mum')
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
should "complain if no source given" do
|
173
|
+
assert_raises RuntimeError do
|
174
|
+
@processor.address_for(:type => :footsteps)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class StatefulWidgetTest < Test::Unit::TestCase
|
4
|
+
context "The StatefulWidget" do
|
5
|
+
setup do
|
6
|
+
@mum = Apotomo::StatefulWidget.new('mum', :squeak)
|
7
|
+
end
|
8
|
+
|
9
|
+
should "accept an id as first option" do
|
10
|
+
assert_equal 'mum', @mum.name
|
11
|
+
end
|
12
|
+
|
13
|
+
should "accept a start state as second option" do
|
14
|
+
assert_equal :squeak, @mum.instance_variable_get('@start_state')
|
15
|
+
end
|
16
|
+
|
17
|
+
should "respond to #version" do
|
18
|
+
assert_equal 0, mouse_mock.version
|
19
|
+
end
|
20
|
+
|
21
|
+
should "have a version setter" do
|
22
|
+
@mum = mouse_mock
|
23
|
+
@mum.version = 1
|
24
|
+
assert_equal 1, @mum.version
|
25
|
+
end
|
26
|
+
|
27
|
+
context "responding to #address_for_event" do
|
28
|
+
should "accept an event :type" do
|
29
|
+
assert_equal({:type => :squeak, :source => 'mum'}, @mum.address_for_event(:type => :squeak))
|
30
|
+
end
|
31
|
+
|
32
|
+
should "accept a :source" do
|
33
|
+
assert_equal({:type => :squeak, :source => 'kid'}, @mum.address_for_event(:type => :squeak, :source => 'kid'))
|
34
|
+
end
|
35
|
+
|
36
|
+
should "accept arbitrary options" do
|
37
|
+
assert_equal({:type => :squeak, :volume => 'loud', :source => 'mum'}, @mum.address_for_event(:type => :squeak, :volume => 'loud'))
|
38
|
+
end
|
39
|
+
|
40
|
+
should "complain if no type given" do
|
41
|
+
assert_raises RuntimeError do
|
42
|
+
@mum.address_for_event(:source => 'mum')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "implementing visibility" do
|
48
|
+
should "per default respond to #visible?" do
|
49
|
+
assert @mum.visible?
|
50
|
+
end
|
51
|
+
|
52
|
+
should "expose a setter therefore" do
|
53
|
+
@mum.visible = false
|
54
|
+
assert_not @mum.visible?
|
55
|
+
end
|
56
|
+
|
57
|
+
context "in a widget family" do
|
58
|
+
setup do
|
59
|
+
@mum << @jerry = mouse_mock('jerry')
|
60
|
+
@mum << @berry = mouse_mock('berry')
|
61
|
+
end
|
62
|
+
|
63
|
+
should "per default return all #visible_children" do
|
64
|
+
assert_equal [@jerry, @berry], @mum.visible_children
|
65
|
+
assert_equal [], @jerry.visible_children
|
66
|
+
end
|
67
|
+
|
68
|
+
should "hide berry in #visible_children if he's invisible" do
|
69
|
+
@berry.visible = false
|
70
|
+
assert_equal [@jerry], @mum.visible_children
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
should "respond to #find_widget" do
|
76
|
+
mum_and_kid!
|
77
|
+
assert_not @mum.find_widget('pet')
|
78
|
+
assert @kid, @mum.find_widget('kid')
|
79
|
+
end
|
80
|
+
|
81
|
+
should "respond to the WidgetShortcuts methods, like #widget" do
|
82
|
+
assert_respond_to @mum, :widget
|
83
|
+
end
|
84
|
+
|
85
|
+
context "with initialize_hooks" do
|
86
|
+
should "expose its class_inheritable_array with #initialize_hooks" do
|
87
|
+
@mum = mouse_class_mock.new('mum', :eating)
|
88
|
+
@mum.class.instance_eval { self.initialize_hooks << :initialize_mouse }
|
89
|
+
assert ::Apotomo::StatefulWidget.initialize_hooks.size + 1 == @mum.class.initialize_hooks.size
|
90
|
+
end
|
91
|
+
|
92
|
+
should "execute the initialize_hooks in the correct order in #process_initialize_hooks" do
|
93
|
+
@mum = mouse_class_mock.new('mum', :eating)
|
94
|
+
@mum.class.instance_eval do
|
95
|
+
define_method(:executed) { |*args| @executed ||= [] }
|
96
|
+
define_method(:setup) { |*args| executed << :setup }
|
97
|
+
define_method(:configure) { |*args| executed << :configure }
|
98
|
+
initialize_hooks << :setup
|
99
|
+
initialize_hooks << :configure
|
100
|
+
end
|
101
|
+
|
102
|
+
assert_equal [:setup, :configure], @mum.class.new('zombie', nil).executed
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "mum having a family" do
|
108
|
+
setup do
|
109
|
+
mum_and_kid!
|
110
|
+
@mum << @berry = mouse_mock('berry')
|
111
|
+
@berry << @pet = mouse_mock('pet')
|
112
|
+
end
|
113
|
+
|
114
|
+
context "responding to #render_children" do
|
115
|
+
should "return an OrderedHash for the rendered kids" do
|
116
|
+
kids = @mum.render_children
|
117
|
+
assert_kind_of ::ActiveSupport::OrderedHash, kids
|
118
|
+
assert_equal 2, kids.size
|
119
|
+
end
|
120
|
+
|
121
|
+
should "return an OrderedHash even if there are no kids" do
|
122
|
+
kids = @kid.render_children
|
123
|
+
assert_kind_of ::ActiveSupport::OrderedHash, kids
|
124
|
+
assert_equal 0, kids.size
|
125
|
+
end
|
126
|
+
|
127
|
+
should "return an empty OrderedHash when all kids are invisible" do
|
128
|
+
@pet.visible = false
|
129
|
+
kids = @berry.render_children
|
130
|
+
assert_kind_of ::ActiveSupport::OrderedHash, kids
|
131
|
+
assert_equal 0, kids.size
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|