apotomo 1.0.5 → 1.1.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. data/.gitignore +5 -0
  2. data/CHANGES.textile +35 -7
  3. data/Gemfile +0 -2
  4. data/README.rdoc +9 -9
  5. data/apotomo.gemspec +3 -3
  6. data/lib/apotomo.rb +4 -47
  7. data/lib/apotomo/event.rb +2 -0
  8. data/lib/apotomo/event_handler.rb +0 -3
  9. data/lib/apotomo/event_methods.rb +6 -2
  10. data/lib/apotomo/invoke_event_handler.rb +5 -3
  11. data/lib/apotomo/javascript_generator.rb +19 -16
  12. data/lib/apotomo/rails/controller_methods.rb +84 -131
  13. data/lib/apotomo/rails/view_helper.rb +15 -31
  14. data/lib/apotomo/railtie.rb +24 -0
  15. data/lib/apotomo/request_processor.rb +17 -48
  16. data/lib/apotomo/test_case.rb +5 -5
  17. data/lib/apotomo/tree_node.rb +52 -61
  18. data/lib/apotomo/version.rb +1 -1
  19. data/lib/apotomo/widget.rb +70 -146
  20. data/lib/apotomo/widget/javascript_methods.rb +39 -0
  21. data/lib/apotomo/widget_shortcuts.rb +14 -40
  22. data/lib/generators/apotomo/widget_generator.rb +8 -9
  23. data/lib/generators/erb/widget_generator.rb +17 -0
  24. data/lib/generators/haml/widget_generator.rb +20 -0
  25. data/lib/generators/{apotomo/templates → templates}/view.erb +1 -1
  26. data/lib/generators/templates/view.haml +4 -0
  27. data/lib/generators/{apotomo/templates → templates}/widget.rb +1 -1
  28. data/lib/generators/{apotomo/templates → templates}/widget_test.rb +1 -1
  29. data/lib/generators/test_unit/widget_generator.rb +14 -0
  30. data/test/rails/caching_test.rb +10 -17
  31. data/test/rails/controller_methods_test.rb +9 -81
  32. data/test/rails/rails_integration_test.rb +76 -60
  33. data/test/rails/view_helper_test.rb +17 -28
  34. data/test/rails/widget_generator_test.rb +19 -31
  35. data/test/support/test_case_methods.rb +6 -20
  36. data/test/test_helper.rb +15 -25
  37. data/test/unit/event_handler_test.rb +1 -0
  38. data/test/unit/event_methods_test.rb +20 -8
  39. data/test/unit/event_test.rb +5 -0
  40. data/test/unit/javascript_generator_test.rb +19 -19
  41. data/test/unit/render_test.rb +17 -112
  42. data/test/unit/request_processor_test.rb +73 -111
  43. data/test/unit/test_case_test.rb +13 -7
  44. data/test/unit/widget_shortcuts_test.rb +24 -53
  45. data/test/unit/widget_test.rb +76 -36
  46. data/test/widgets/mouse/eat.erb +1 -0
  47. data/test/{fixtures → widgets}/mouse/eating.html.erb +0 -0
  48. data/test/{fixtures → widgets}/mouse/educate.html.erb +0 -0
  49. data/test/{fixtures → widgets}/mouse/feed.html.erb +0 -0
  50. data/test/{fixtures → widgets}/mouse/make_me_squeak.html.erb +0 -0
  51. data/test/{fixtures → widgets}/mouse/posing.html.erb +0 -0
  52. data/test/widgets/mouse/snuggle.html.erb +1 -0
  53. metadata +32 -50
  54. data/lib/apotomo/container_widget.rb +0 -10
  55. data/lib/apotomo/persistence.rb +0 -112
  56. data/lib/apotomo/rails/view_methods.rb +0 -7
  57. data/lib/apotomo/stateful_widget.rb +0 -29
  58. data/lib/apotomo/transition.rb +0 -46
  59. data/lib/generators/apotomo/templates/view.haml +0 -4
  60. data/test/dummy/log/production.log +0 -0
  61. data/test/dummy/log/server.log +0 -0
  62. data/test/dummy/public/javascripts/application.js +0 -2
  63. data/test/dummy/public/javascripts/controls.js +0 -965
  64. data/test/dummy/public/javascripts/dragdrop.js +0 -974
  65. data/test/dummy/public/javascripts/effects.js +0 -1123
  66. data/test/dummy/public/javascripts/prototype.js +0 -6001
  67. data/test/dummy/public/javascripts/rails.js +0 -175
  68. data/test/dummy/script/rails +0 -6
  69. data/test/dummy/tmp/app/cells/mouse_widget.rb +0 -11
  70. data/test/dummy/tmp/app/cells/mouse_widget/snuggle.html.erb +0 -7
  71. data/test/dummy/tmp/app/cells/mouse_widget/squeak.html.erb +0 -7
  72. data/test/dummy/tmp/test/widgets/mouse_widget_test.rb +0 -12
  73. data/test/fixtures/application_widget_tree.rb +0 -2
  74. data/test/fixtures/mouse/snuggle.html.erb +0 -1
  75. data/test/rails/view_methods_test.rb +0 -38
  76. data/test/unit/container_test.rb +0 -21
  77. data/test/unit/invoke_test.rb +0 -126
  78. data/test/unit/persistence_test.rb +0 -201
  79. data/test/unit/stateful_widget_test.rb +0 -58
  80. data/test/unit/test_addressing.rb +0 -110
  81. data/test/unit/test_jump_to_state.rb +0 -89
  82. data/test/unit/test_tab_panel.rb +0 -71
  83. data/test/unit/transition_test.rb +0 -34
@@ -1,175 +0,0 @@
1
- (function() {
2
- // Technique from Juriy Zaytsev
3
- // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
4
- function isEventSupported(eventName) {
5
- var el = document.createElement('div');
6
- eventName = 'on' + eventName;
7
- var isSupported = (eventName in el);
8
- if (!isSupported) {
9
- el.setAttribute(eventName, 'return;');
10
- isSupported = typeof el[eventName] == 'function';
11
- }
12
- el = null;
13
- return isSupported;
14
- }
15
-
16
- function isForm(element) {
17
- return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM'
18
- }
19
-
20
- function isInput(element) {
21
- if (Object.isElement(element)) {
22
- var name = element.nodeName.toUpperCase()
23
- return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA'
24
- }
25
- else return false
26
- }
27
-
28
- var submitBubbles = isEventSupported('submit'),
29
- changeBubbles = isEventSupported('change')
30
-
31
- if (!submitBubbles || !changeBubbles) {
32
- // augment the Event.Handler class to observe custom events when needed
33
- Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap(
34
- function(init, element, eventName, selector, callback) {
35
- init(element, eventName, selector, callback)
36
- // is the handler being attached to an element that doesn't support this event?
37
- if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) ||
38
- (!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) {
39
- // "submit" => "emulated:submit"
40
- this.eventName = 'emulated:' + this.eventName
41
- }
42
- }
43
- )
44
- }
45
-
46
- if (!submitBubbles) {
47
- // discover forms on the page by observing focus events which always bubble
48
- document.on('focusin', 'form', function(focusEvent, form) {
49
- // special handler for the real "submit" event (one-time operation)
50
- if (!form.retrieve('emulated:submit')) {
51
- form.on('submit', function(submitEvent) {
52
- var emulated = form.fire('emulated:submit', submitEvent, true)
53
- // if custom event received preventDefault, cancel the real one too
54
- if (emulated.returnValue === false) submitEvent.preventDefault()
55
- })
56
- form.store('emulated:submit', true)
57
- }
58
- })
59
- }
60
-
61
- if (!changeBubbles) {
62
- // discover form inputs on the page
63
- document.on('focusin', 'input, select, texarea', function(focusEvent, input) {
64
- // special handler for real "change" events
65
- if (!input.retrieve('emulated:change')) {
66
- input.on('change', function(changeEvent) {
67
- input.fire('emulated:change', changeEvent, true)
68
- })
69
- input.store('emulated:change', true)
70
- }
71
- })
72
- }
73
-
74
- function handleRemote(element) {
75
- var method, url, params;
76
-
77
- var event = element.fire("ajax:before");
78
- if (event.stopped) return false;
79
-
80
- if (element.tagName.toLowerCase() === 'form') {
81
- method = element.readAttribute('method') || 'post';
82
- url = element.readAttribute('action');
83
- params = element.serialize();
84
- } else {
85
- method = element.readAttribute('data-method') || 'get';
86
- url = element.readAttribute('href');
87
- params = {};
88
- }
89
-
90
- new Ajax.Request(url, {
91
- method: method,
92
- parameters: params,
93
- evalScripts: true,
94
-
95
- onComplete: function(request) { element.fire("ajax:complete", request); },
96
- onSuccess: function(request) { element.fire("ajax:success", request); },
97
- onFailure: function(request) { element.fire("ajax:failure", request); }
98
- });
99
-
100
- element.fire("ajax:after");
101
- }
102
-
103
- function handleMethod(element) {
104
- var method = element.readAttribute('data-method'),
105
- url = element.readAttribute('href'),
106
- csrf_param = $$('meta[name=csrf-param]')[0],
107
- csrf_token = $$('meta[name=csrf-token]')[0];
108
-
109
- var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
110
- element.parentNode.insert(form);
111
-
112
- if (method !== 'post') {
113
- var field = new Element('input', { type: 'hidden', name: '_method', value: method });
114
- form.insert(field);
115
- }
116
-
117
- if (csrf_param) {
118
- var param = csrf_param.readAttribute('content'),
119
- token = csrf_token.readAttribute('content'),
120
- field = new Element('input', { type: 'hidden', name: param, value: token });
121
- form.insert(field);
122
- }
123
-
124
- form.submit();
125
- }
126
-
127
-
128
- document.on("click", "*[data-confirm]", function(event, element) {
129
- var message = element.readAttribute('data-confirm');
130
- if (!confirm(message)) event.stop();
131
- });
132
-
133
- document.on("click", "a[data-remote]", function(event, element) {
134
- if (event.stopped) return;
135
- handleRemote(element);
136
- event.stop();
137
- });
138
-
139
- document.on("click", "a[data-method]", function(event, element) {
140
- if (event.stopped) return;
141
- handleMethod(element);
142
- event.stop();
143
- });
144
-
145
- document.on("submit", function(event) {
146
- var element = event.findElement(),
147
- message = element.readAttribute('data-confirm');
148
- if (message && !confirm(message)) {
149
- event.stop();
150
- return false;
151
- }
152
-
153
- var inputs = element.select("input[type=submit][data-disable-with]");
154
- inputs.each(function(input) {
155
- input.disabled = true;
156
- input.writeAttribute('data-original-value', input.value);
157
- input.value = input.readAttribute('data-disable-with');
158
- });
159
-
160
- var element = event.findElement("form[data-remote]");
161
- if (element) {
162
- handleRemote(element);
163
- event.stop();
164
- }
165
- });
166
-
167
- document.on("ajax:after", "form", function(event, element) {
168
- var inputs = element.select("input[type=submit][disabled=true][data-disable-with]");
169
- inputs.each(function(input) {
170
- input.value = input.readAttribute('data-original-value');
171
- input.removeAttribute('data-original-value');
172
- input.disabled = false;
173
- });
174
- });
175
- })();
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
-
4
- APP_PATH = File.expand_path('../../config/application', __FILE__)
5
- require File.expand_path('../../config/boot', __FILE__)
6
- require 'rails/commands'
@@ -1,11 +0,0 @@
1
- class MouseWidget < Apotomo::Widget
2
-
3
- def squeak
4
- render
5
- end
6
-
7
- def snuggle
8
- render
9
- end
10
-
11
- end
@@ -1,7 +0,0 @@
1
- <h1>
2
- MouseWidget#snuggle
3
- </h1>
4
-
5
- <p>
6
- Find me in app/cells/mouse_widget/snuggle.html.erb
7
- </p>
@@ -1,7 +0,0 @@
1
- <h1>
2
- MouseWidget#squeak
3
- </h1>
4
-
5
- <p>
6
- Find me in app/cells/mouse_widget/squeak.html.erb
7
- </p>
@@ -1,12 +0,0 @@
1
- require 'test_helper'
2
-
3
- class MouseWidgetTest < Apotomo::TestCase
4
- has_widgets do |root|
5
- root << widget(:mouse_widget, 'me')
6
- end
7
-
8
- test "display" do
9
- render_widget 'me'
10
- assert_select "h1"
11
- end
12
- end
@@ -1,2 +0,0 @@
1
- class ApplicationWidgetTree < Apotomo::WidgetTree
2
- end
@@ -1 +0,0 @@
1
- <div id="<%= @name %>"><snuggle><%= rendered_children.collect{|e| e.last}.join("").html_safe %></snuggle></div>
@@ -1,38 +0,0 @@
1
- require 'test_helper'
2
-
3
- class ViewMethodsTest < ActionController::TestCase
4
- include Apotomo::TestCaseMethods::TestController
5
-
6
- context "A Rails controller view" do
7
- setup do
8
- @controller.instance_variable_set(:@mum, mouse_mock('mum', 'snuggle') {def snuggle; render; end})
9
- @controller.instance_eval do
10
- def widget
11
- use_widgets do |root|
12
- root << @mum
13
- end
14
- render :inline => "<%= render_widget 'mum' %>"
15
- end
16
- end
17
- end
18
-
19
- should "respond to render_widget" do
20
- get :widget
21
- assert_select "#mum>snuggle"
22
- end
23
-
24
- should "respond to url_for_event" do
25
- @controller.instance_eval do
26
- def widget
27
- use_widgets do |root|
28
- root << @mum
29
- end
30
- render :inline => "<%= url_for_event :footsteps, :source => 'mum' %>"
31
- end
32
- end
33
-
34
- get :widget
35
- assert_equal "/barn/render_event_response?source=mum&amp;type=footsteps", @response.body
36
- end
37
- end
38
- end
@@ -1,21 +0,0 @@
1
- require 'test_helper'
2
-
3
- class ContainerTest < Test::Unit::TestCase
4
- include Apotomo::TestCaseMethods::TestController
5
-
6
- context "Rendering a container" do
7
- setup do
8
- @family = container('family')
9
- end
10
-
11
- should "return an empty view if childless" do
12
- assert_equal "<div id=\"family\"></div>", @family.invoke
13
- end
14
-
15
- should "provide a family picture" do
16
- @family << mouse_mock('mum')
17
- @family << mouse_mock('kid')
18
- assert_equal "<div id=\"family\"><div id=\"mum\">burp!</div>\n<div id=\"kid\">burp!</div></div>", @family.invoke
19
- end
20
- end
21
- end
@@ -1,126 +0,0 @@
1
- require 'test_helper'
2
-
3
- class InvokeTest < Test::Unit::TestCase
4
- include Apotomo::TestCaseMethods::TestController
5
-
6
- class LocalMouse < MouseCell
7
- def snuggle; render; end
8
- def educate; render :view => :snuggle; end
9
- end
10
-
11
- context "Invoking a single widget" do
12
- setup do
13
- @mum = LocalMouse.new(parent_controller, 'mum', :snuggle)
14
- end
15
-
16
- context "implicitely" do
17
- should "always enter the given state" do
18
- @mum.invoke :snuggle
19
- assert_equal 'snuggle', @mum.last_state
20
-
21
- @mum.invoke :educate
22
- assert_equal 'educate', @mum.last_state
23
- end
24
- end
25
-
26
- context "explicitely" do
27
- should "per default enter the start state" do
28
- @mum.invoke
29
- assert_equal 'snuggle', @mum.last_state
30
-
31
- @mum.invoke
32
- assert_equal 'snuggle', @mum.last_state
33
- end
34
-
35
- context "with defined transitions" do
36
- setup do
37
- @mum.instance_eval do
38
- self.class.transition :from => :snuggle, :to => :educate
39
- end
40
-
41
- @mum.invoke
42
- assert_equal 'snuggle', @mum.last_state
43
- end
44
-
45
- should "automatically follow the transitions if defined" do
46
- assert_equal 'snuggle', @mum.last_state
47
- @mum.invoke
48
- assert_equal 'educate', @mum.last_state
49
- end
50
-
51
- should "nevertheless allow undefined implicit invokes" do
52
- @mum.invoke :snuggle
53
- assert_equal 'snuggle', @mum.last_state
54
- end
55
- end
56
- end
57
- end
58
-
59
- context "Invoking a widget family" do
60
- setup do
61
- @mum = LocalMouse.new(parent_controller, 'mum', :snuggle)
62
-
63
- # create an anonym class for @kid so we don't pollute with #transition's.
64
- @mum << @kid = mouse_class_mock.new(parent_controller, 'kid', :snooze)
65
- @kid.instance_eval do
66
- def snooze; render :nothing => true; end
67
- def listen; render :nothing => true; end
68
- end
69
- end
70
-
71
- context "implicitely" do
72
- should "per default send kid to its start state" do
73
- @mum.invoke :snuggle
74
- assert_equal 'snuggle', @mum.last_state
75
- assert_equal 'snooze', @kid.last_state
76
-
77
- @mum.invoke :educate
78
- assert_equal 'educate', @mum.last_state
79
- assert_equal 'snooze', @kid.last_state
80
- end
81
-
82
- should "follow the kid's transition if defined" do
83
- @kid.instance_eval do
84
- self.class.transition :from => :snooze, :to => :listen
85
- end
86
-
87
- @mum.invoke :snuggle
88
- @mum.invoke :educate
89
- assert_equal 'educate', @mum.last_state
90
- assert_equal 'listen', @kid.last_state
91
- end
92
-
93
- should "send kid to the given state passed to #render" do
94
- @mum.instance_eval do
95
- def snuggle
96
- render :invoke => {'kid' => :listen}
97
- end
98
- end
99
-
100
- @mum.invoke :snuggle
101
- assert_equal 'snuggle', @mum.last_state
102
- assert_equal 'listen', @kid.last_state
103
- end
104
-
105
- should "send kid to the :invoke state as it overrides #transition" do
106
- @kid.instance_eval do
107
- self.class.transition :from => :snooze, :to => :listen
108
- end
109
-
110
- @mum.instance_eval do
111
- def educate
112
- render :nothing => true, :invoke => {'kid' => :snooze}
113
- end
114
- end
115
-
116
- @mum.invoke :snuggle
117
- assert_equal 'snuggle', @mum.last_state
118
- assert_equal 'snooze', @kid.last_state
119
-
120
- @mum.invoke :educate
121
- assert_equal 'educate', @mum.last_state
122
- assert_equal 'snooze', @kid.last_state
123
- end
124
- end
125
- end
126
- end
@@ -1,201 +0,0 @@
1
- require 'test_helper'
2
-
3
- class PersistenceTest < Test::Unit::TestCase
4
- include Apotomo::TestCaseMethods::TestController
5
-
6
- class PersistentMouse < Apotomo::StatefulWidget # we need a named class for marshalling.
7
- attr_reader :who, :what
8
-
9
- def educate
10
- @who = "the cat"
11
- @what = "run away"
12
- render :nothing => true
13
- end
14
-
15
- def recap; render :nothing => true; end
16
- end
17
-
18
- def stateless(name)
19
- Apotomo::Widget.new(parent_controller, name, :eat)
20
- end
21
-
22
- def stateful(name)
23
- PersistentMouse.new(parent_controller, name, :educate)
24
- end
25
-
26
- context "StatefulWidget" do
27
-
28
- context ".stateful_branches_for" do
29
- should "provide all stateful branch-roots seen from root" do
30
- @root = stateless('root')
31
- @root << mum_and_kid!
32
- @root << stateless('berry') << @jerry = mouse_mock('jerry', :eat)
33
-
34
- assert_equal ['mum', 'jerry'], Apotomo::StatefulWidget.stateful_branches_for(@root).collect {|n| n.name}
35
- end
36
- end
37
- end
38
-
39
- context "freezing and thawing a widget family" do
40
- setup do
41
- mum_and_kid!
42
- @storage = {}
43
- end
44
-
45
- context "and calling #flush_storage" do
46
- should "clear the storage from frozen data" do
47
- @root = stateless('root')
48
- @root << @mum
49
-
50
- Apotomo::StatefulWidget.freeze_for(@storage, @root)
51
-
52
- assert @storage[:apotomo_stateful_branches]
53
- assert @storage[:apotomo_widget_ivars]
54
-
55
- Apotomo::StatefulWidget.flush_storage(@storage)
56
-
57
- assert_nil @storage[:apotomo_stateful_branches]
58
- assert_nil @storage[:apotomo_widget_ivars]
59
- end
60
- end
61
-
62
- should "push @mum's freezable ivars to the storage when calling #freeze_ivars_to" do
63
- @mum.freeze_ivars_to(@storage)
64
-
65
- assert_equal 1, @storage.size
66
- assert_equal 6, @storage['mum'].size
67
- end
68
-
69
- should "push family's freezable ivars to the storage when calling #freeze_data_to" do
70
- @kid << mouse_mock('pet')
71
- @mum.freeze_data_to(@storage)
72
-
73
- assert_equal 3, @storage.size
74
- assert_equal 6, @storage['mum'].size
75
- assert_equal 6, @storage['mum/kid'].size
76
- assert_equal 5, @storage['mum/kid/pet'].size
77
- end
78
-
79
- should "push ivars and structure to the storage when calling #freeze_to" do
80
- @mum.freeze_to(@storage)
81
- assert_equal 2, @storage[:apotomo_widget_ivars].size
82
- assert_kind_of Apotomo::StatefulWidget, @storage[:apotomo_root]
83
- end
84
-
85
- context "that has also stateless widgets" do
86
- setup do
87
- @root = stateless('root')
88
- @root << mum_and_kid!
89
- @root << stateless('berry') << @jerry = mouse_mock('jerry', :eat)
90
- @root << stateless('tom')
91
-
92
- Apotomo::StatefulWidget.freeze_for(@storage, @root)
93
- end
94
-
95
- should "ignore stateless widgets when calling #freeze_for" do
96
- assert_equal(['root/mum', 'root/mum/kid', "root/berry/jerry"], @storage[:apotomo_widget_ivars].keys)
97
- end
98
-
99
- should "save stateful branches only" do
100
- assert_equal([[[MouseCell, 'mum', 'root'], [MouseCell, 'kid', 'mum']], [[MouseCell, 'jerry', 'berry']]], @storage[:apotomo_stateful_branches])
101
- end
102
-
103
- should "attach stateful branches to the tree in thaw_for" do
104
- @new_root = stateless('root')
105
- @new_root << stateless('berry')
106
- assert_equal @new_root, Apotomo::StatefulWidget.thaw_for(@controller, @storage, @new_root)
107
-
108
- assert_equal 5, @new_root.size # without tom.
109
- end
110
-
111
- should "re-establish ivars recursivly when calling #thaw_for" do
112
- @storage[:apotomo_stateful_branches] = Marshal.load(Marshal.dump(@storage[:apotomo_stateful_branches]))
113
-
114
- @new_root = stateless('root')
115
- @new_root << stateless('berry')
116
- @new_root = Apotomo::StatefulWidget.thaw_for(@controller, @storage, @new_root)
117
-
118
- assert_equal :answer_squeak, @new_root['mum'].instance_variable_get(:@start_state)
119
- assert_equal :peek, @new_root['mum']['kid'].instance_variable_get(:@start_state)
120
- end
121
-
122
- should "raise an exception when thaw_for can't find the branch's parent" do
123
- @new_root = stateless('dad')
124
-
125
- assert_raises RuntimeError do
126
- Apotomo::StatefulWidget.thaw_for(@controller, @storage, @new_root)
127
- end
128
- end
129
-
130
- should "clear the fields in the storage when fetching in #thaw_for" do
131
- @new_root = stateless('root')
132
- @new_root << stateless('berry')
133
-
134
- Apotomo::StatefulWidget.thaw_for(@controller, @storage, @new_root)
135
-
136
- assert_nil @storage[:apotomo_stateful_branches]
137
- assert_nil @storage[:apotomo_widget_ivars]
138
- end
139
- end
140
-
141
- should "update @mum's ivars when calling #thaw_ivars_from" do
142
- @mum.instance_variable_set(:@name, "zombie mum")
143
- assert_equal 'zombie mum', @mum.name
144
-
145
- @mum.thaw_ivars_from({'zombie mum' => {'@name' => 'mum'}})
146
- assert_equal 'mum', @mum.name
147
- end
148
-
149
- should "update family's ivars when calling #thaw_data_from" do
150
- @kid << @pet = mouse_mock('pet')
151
- @kid.instance_variable_set(:@name, "paranoid kid")
152
- @pet.instance_variable_set(:@name, "mad dog")
153
- assert_equal "paranoid kid", @kid.name
154
-
155
- @mum.thaw_data_from({ "mum/paranoid kid" => {'@name' => 'kid'},
156
- "mum/kid/mad dog" => {'@name' => 'pet'}})
157
- assert_equal 'kid', @kid.name
158
- assert_equal 'pet', @pet.name
159
- end
160
-
161
-
162
- end
163
-
164
- context "#dump_tree" do
165
- setup do
166
- @mum = stateful('mum')
167
- @mum << @kid = stateful('kid')
168
- @kid << @pet = stateful('pet')
169
- @mum << @berry = stateful('berry')
170
-
171
- end
172
-
173
- should "return a list of widget metadata" do
174
- assert_equal [[PersistentMouse, 'mum', nil], [PersistentMouse, 'kid', 'mum'], [PersistentMouse, 'pet', 'kid'], [PersistentMouse, 'berry', 'mum']], @mum.dump_tree
175
- end
176
-
177
- should "return a tree for #load_tree" do
178
- cold_widgets = @mum.dump_tree
179
- assert_equal ['mum', 'kid', 'pet', 'berry'], Apotomo::StatefulWidget.send(:load_tree, @controller, cold_widgets).collect { |n| n.name }
180
- end
181
-
182
- context "#frozen_widget_in?" do
183
- should "return true if a valid widget is passed" do
184
- @session = {}
185
- assert_not Apotomo::StatefulWidget.frozen_widget_in?(@session)
186
- Apotomo::StatefulWidget.freeze_for(@session, @berry)
187
- assert Apotomo::StatefulWidget.frozen_widget_in?(@session)
188
- end
189
- end
190
- end
191
-
192
-
193
-
194
- context "#symbolized_instance_variables?" do
195
- should "return instance_variables as symbols" do
196
- @mum = mouse_mock
197
- assert_equal @mum.instance_variables.size, @mum.symbolized_instance_variables.size
198
- assert_not @mum.symbolized_instance_variables.find { |ivar| ivar.kind_of? String }
199
- end
200
- end
201
- end