jim 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/HISTORY +28 -0
  2. data/README.rdoc +1 -1
  3. data/Rakefile +2 -1
  4. data/jim.gemspec +67 -9
  5. data/lib/jim/bundler.rb +14 -11
  6. data/lib/jim/cli.rb +51 -9
  7. data/lib/jim/index.rb +3 -7
  8. data/lib/jim/installer.rb +140 -22
  9. data/lib/jim/templates/commands +21 -6
  10. data/lib/jim/version_parser.rb +2 -3
  11. data/lib/jim.rb +19 -2
  12. data/test/fixtures/jimfile +3 -3
  13. data/test/fixtures/sammy-0.5.0/HISTORY.md +135 -0
  14. data/test/fixtures/sammy-0.5.0/LICENSE +22 -0
  15. data/test/fixtures/sammy-0.5.0/README.md +81 -0
  16. data/test/fixtures/sammy-0.5.0/Rakefile +174 -0
  17. data/test/fixtures/sammy-0.5.0/examples/backend/README.md +23 -0
  18. data/test/fixtures/sammy-0.5.0/examples/backend/Rakefile +15 -0
  19. data/test/fixtures/sammy-0.5.0/examples/backend/app.rb +17 -0
  20. data/test/fixtures/sammy-0.5.0/examples/backend/app.ru +3 -0
  21. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/app.js +106 -0
  22. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.cloudkit.js +840 -0
  23. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.js +19 -0
  24. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/sammy.js +1013 -0
  25. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/index.html.erb +11 -0
  26. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task.html.erb +4 -0
  27. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task_details.html.erb +4 -0
  28. data/test/fixtures/sammy-0.5.0/examples/backend/views/app.sass +63 -0
  29. data/test/fixtures/sammy-0.5.0/examples/backend/views/index.haml +18 -0
  30. data/test/fixtures/sammy-0.5.0/examples/form_handling/files/form.html +12 -0
  31. data/test/fixtures/sammy-0.5.0/examples/form_handling/index.html +65 -0
  32. data/test/fixtures/sammy-0.5.0/examples/hello_world/index.html +50 -0
  33. data/test/fixtures/sammy-0.5.0/examples/location_override/README.md +15 -0
  34. data/test/fixtures/sammy-0.5.0/examples/location_override/data.html +110 -0
  35. data/test/fixtures/sammy-0.5.0/examples/location_override/index.html +79 -0
  36. data/test/fixtures/sammy-0.5.0/examples/location_override/test.html +121 -0
  37. data/test/fixtures/sammy-0.5.0/lib/min/sammy-0.5.0.min.js +5 -0
  38. data/test/fixtures/sammy-0.5.0/lib/min/sammy-lastest.min.js +5 -0
  39. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.cache.js +117 -0
  40. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.haml.js +539 -0
  41. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.json.js +362 -0
  42. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.mustache.js +415 -0
  43. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.nested_params.js +118 -0
  44. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.storage.js +515 -0
  45. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.template.js +117 -0
  46. data/test/fixtures/sammy-0.5.0/lib/sammy.js +1367 -0
  47. data/test/fixtures/sammy-0.5.0/test/fixtures/partial +1 -0
  48. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.html +1 -0
  49. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.noengine +1 -0
  50. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.template +1 -0
  51. data/test/fixtures/sammy-0.5.0/test/index.html +84 -0
  52. data/test/fixtures/sammy-0.5.0/test/test_sammy_application.js +953 -0
  53. data/test/fixtures/sammy-0.5.0/test/test_sammy_event_context.js +252 -0
  54. data/test/fixtures/sammy-0.5.0/test/test_sammy_location_proxy.js +91 -0
  55. data/test/fixtures/sammy-0.5.0/test/test_sammy_plugins.js +296 -0
  56. data/test/fixtures/sammy-0.5.0/test/test_sammy_storage.js +175 -0
  57. data/test/fixtures/sammy-0.5.0/test/test_server +27 -0
  58. data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.js +6078 -0
  59. data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.min.js +152 -0
  60. data/test/fixtures/sammy-0.5.0/vendor/jsdoc/doc.haml +58 -0
  61. data/test/fixtures/sammy-0.5.0/vendor/jsdoc/jsdoc.rb +143 -0
  62. data/test/fixtures/sammy-0.5.0/vendor/jslitmus.js +670 -0
  63. data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.css +119 -0
  64. data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.js +1043 -0
  65. data/test/fixtures/sammy-0.5.0/vendor/qunit-spec.js +127 -0
  66. data/test/helper.rb +23 -3
  67. data/test/test_jim_bundler.rb +9 -8
  68. data/test/test_jim_cli.rb +21 -12
  69. data/test/test_jim_installer.rb +152 -35
  70. data/test/test_jim_version_parser.rb +4 -0
  71. metadata +117 -27
  72. data/.document +0 -5
@@ -0,0 +1,252 @@
1
+ (function($) {
2
+ with(QUnit) {
3
+
4
+ var test_app = new Sammy.Application(function() {
5
+ this.silence_404 = true;
6
+ this.element_selector = '#main';
7
+ });
8
+ var test_context = new Sammy.EventContext(test_app, 'get', '#/test/:test', {test: 'hooray'});
9
+
10
+ context('Sammy', 'EventContext','init', {
11
+ before: function() {
12
+ this.app = test_app;
13
+ this.context = test_context;
14
+ }
15
+ })
16
+ .should('set app', function() {
17
+ deepEqual(this.context.app, this.app);
18
+ })
19
+ .should('set verb', function() {
20
+ equal(this.context.verb, 'get');
21
+ })
22
+ .should('set path', function() {
23
+ equal(this.context.path, '#/test/:test');
24
+ })
25
+ .should('set params', function() {
26
+ deepEqual(this.context.params, new Sammy.Object({test: 'hooray'}));
27
+ });
28
+
29
+
30
+ context('Sammy', 'EventContext', 'redirect', {
31
+ before: function() {
32
+ this.app = test_app;
33
+ this.context = test_context;
34
+ },
35
+ after: function() {
36
+ window.location.hash = '#';
37
+ }
38
+ })
39
+ .should('set full location if url is provided', function() {
40
+ this.context.redirect('index.html#/boosh');
41
+ equal('#/boosh', window.location.hash);
42
+ })
43
+ .should('only set hash if location is prefixed with #', function() {
44
+ this.context.redirect('#/blah');
45
+ equal('#/blah', window.location.hash);
46
+ })
47
+ .should('join the arguments with / if more then one argument is provided', function() {
48
+ var boosh = 'boosh';
49
+ this.context.redirect('#', 'blah', boosh);
50
+ equal('#/blah/boosh', window.location.hash);
51
+ });
52
+
53
+
54
+ context('Sammy', 'EventContext', 'notFound', {
55
+ before: function() {
56
+ this.context = test_context;
57
+ }
58
+ })
59
+ .should('throw 404 error', function() {
60
+ var context = this.context;
61
+ raised(/404/, function() {
62
+ context.notFound();
63
+ });
64
+ });
65
+
66
+ context('Sammy', 'EventContext', 'partial', {
67
+ before: function() {
68
+ this.app = test_app;
69
+ this.context = test_context;
70
+ }
71
+ })
72
+ .should('pass contents to callback', function() {
73
+ var contents = '';
74
+ this.context.partial('fixtures/partial.html', function(data) { contents = data; });
75
+ soon(function () {
76
+ equal(contents, '<div class="test_partial">PARTIAL</div>');
77
+ }, this, 2);
78
+ })
79
+ .should('not run through template() if Sammy.Template is not present', function() {
80
+ var contents = '';
81
+ this.context.partial('fixtures/partial.template', {name: 'TEMPLATE!', class_name: 'test_template'}, function(data) {
82
+ contents = data;
83
+ });
84
+ soon(function () {
85
+ equal(contents, '<div class="<%= class_name %>"><%= name %></div>');
86
+ }, this, 2);
87
+ })
88
+ .should('run through template() if Sammy.Template _is_ present', function() {
89
+ var contents = '';
90
+ var app = new Sammy.Application(function() { this.element_selector = '#main'; });
91
+ app.use(Sammy.Template);
92
+ this.context = new app.context_prototype(app);
93
+ this.context.partial('fixtures/partial.template', {name: 'TEMPLATE!', class_name: 'test_template'}, function(data) {
94
+ contents = data;
95
+ });
96
+ soon(function () {
97
+ equal(contents, '<div class="test_template">TEMPLATE!</div>');
98
+ }, this, 2);
99
+ })
100
+ .should('itterate over data if data is an array', function() {
101
+ var contents = '',
102
+ app = new Sammy.Application(function() { this.element_selector = '#main'; }),
103
+ data = [{name: 'one', class_name: 'it-1'}, {name: 'two', class_name: 'it-2'}],
104
+ expected = '<div class="it-1">one</div><div class="it-2">two</div>';
105
+
106
+ app.use(Sammy.Template);
107
+ this.context = new app.context_prototype(app);
108
+ this.context.partial('fixtures/partial.template', data);
109
+ this.context.partial('fixtures/partial.template', data, function(html) {
110
+ contents += html;
111
+ });
112
+ soon(function () {
113
+ equal($('#main').html(), expected);
114
+ equal(contents, expected);
115
+ }, this, 2, 2);
116
+ })
117
+ .should('cache template if cache() is present', function(){
118
+ var contents = '';
119
+ var app = new Sammy.Application(function() { this.element_selector = '#main'; });
120
+ app.use(Sammy.Template);
121
+ app.use(Sammy.Cache);
122
+ app.clearCache();
123
+ this.context = new app.context_prototype(app);
124
+ this.context.partial('fixtures/partial.html', function(data) {
125
+ contents = data;
126
+ });
127
+ soon(function () {
128
+ equal(contents, '<div class="test_partial">PARTIAL</div>');
129
+ equal(app.cache('partial:fixtures/partial.html'), '<div class="test_partial">PARTIAL</div>');
130
+ this.context.partial('fixtures/partial.html', function(data) {
131
+ contents = data;
132
+ });
133
+ equal(contents, '<div class="test_partial">PARTIAL</div>');
134
+ }, this, 1, 3);
135
+ })
136
+ .should('not cache template if cache is present and cache_partials: false', function() {
137
+ var contents = '';
138
+ var app = new Sammy.Application(function() { this.element_selector = '#main'; });
139
+ app.use(Sammy.Template);
140
+ app.use(Sammy.Cache);
141
+ app.clearCache();
142
+ app.cache_partials = false;
143
+ this.context = new app.context_prototype(app);
144
+ this.context.partial('fixtures/partial.html', function(data) {
145
+ contents = data;
146
+ });
147
+ soon(function () {
148
+ equal(contents, '<div class="test_partial">PARTIAL</div>');
149
+ ok(!app.cache('partial:fixtures/partial.html'));
150
+ }, this, 1, 2);
151
+ })
152
+ .should('replace default app element if no callback is passed', function() {
153
+ var contents = '';
154
+ var app = new Sammy.Application(function() { this.element_selector = '#main'; });
155
+ app.use(Sammy.Template);
156
+ this.context = new app.context_prototype(app);
157
+ this.context.partial('fixtures/partial.template', {name: 'TEMPLATE!', class_name: 'test_template'});
158
+ soon(function () {
159
+ equal(app.$element().text(), 'TEMPLATE!');
160
+ equal(app.$element().children('.test_template').length, 1);
161
+ }, this, 2, 2);
162
+ })
163
+ .should('trigger changed after the partial callback', function() {
164
+ var changed = false;
165
+ test_app.bind('changed', function() {
166
+ changed = true;
167
+ });
168
+ test_app.run();
169
+ this.context.partial('fixtures/partial.html', function(data) {
170
+ changed = false;
171
+ });
172
+ soon(function() {
173
+ ok(changed);
174
+ test_app.unload();
175
+ });
176
+ })
177
+ .should('use default engine if provided and template doesnt match an engine', function() {
178
+ var contents = '';
179
+ var app = new Sammy.Application(function() {
180
+ this.element_selector = '#main';
181
+ this.template_engine = 'template';
182
+
183
+ this.helper('template', function(template, data) {
184
+ return "!!!" + template.toString() + "!!!";
185
+ });
186
+ });
187
+ this.context = new app.context_prototype(app);
188
+ this.context.partial('fixtures/partial');
189
+ soon(function () {
190
+ equal(app.$element().text(), '!!!NOENGINE!!!');
191
+ });
192
+ })
193
+ .should('use default engine as a method if template doesnt match an engine', function() {
194
+ var contents = '';
195
+ var app = new Sammy.Application(function() {
196
+ this.element_selector = '#main';
197
+ this.template_engine = function(template, data) {
198
+ return "!!!" + template.toString() + "!!!";
199
+ };
200
+ });
201
+ this.context = new app.context_prototype(app);
202
+ this.context.partial('fixtures/partial.noengine');
203
+ soon(function () {
204
+ equal(app.$element().text(), '!!!NOENGINE!!!');
205
+ });
206
+ });
207
+
208
+ context('Sammy', 'EventContext', 'trigger', {
209
+ before: function() {
210
+ this.context = test_context;
211
+ test_app.run();
212
+ },
213
+ after: function() {
214
+ test_app.unload();
215
+ }
216
+ })
217
+ .should('trigger custom event on application', function() {
218
+ var spec_context = this;
219
+ spec_context.event_fired = false;
220
+ test_app.bind('custom', function() {
221
+ spec_context.event_fired = true;
222
+ });
223
+ this.context.trigger('custom');
224
+ soon(function() {
225
+ equal(spec_context.event_fired, true);
226
+ });
227
+ })
228
+ .should('set the context of the event to the Sammy.EventContext', function() {
229
+ var spec_context = this;
230
+ var event_context = null;
231
+ test_app.bind('other.custom', function() {
232
+ event_context = this;
233
+ });
234
+ this.context.trigger('other.custom');
235
+ soon(function() {
236
+ equal(event_context.toString(), test_context.toString());
237
+ });
238
+ })
239
+ .should('pass data as an argument to the bound method', function() {
240
+ var passed_data = null;
241
+ var test_data = {boosh: 'blurgh'};
242
+ test_app.bind('custom-with-data', function(e, data) {
243
+ passed_data = data;
244
+ });
245
+ this.context.trigger('custom-with-data', test_data);
246
+ soon(function() {
247
+ deepEqual(passed_data, test_data);
248
+ });
249
+ });
250
+
251
+ };
252
+ })(jQuery);
@@ -0,0 +1,91 @@
1
+ (function($) {
2
+ with(QUnit) {
3
+
4
+ context('Sammy', 'HashLocationProxy', {
5
+ before: function() {
6
+ this.app = new Sammy.Application;
7
+ this.proxy = new Sammy.HashLocationProxy(this.app);
8
+ this.has_native = (typeof window.onhashchange != 'undefined');
9
+ }
10
+ })
11
+ .should('store a pointer to the app', function() {
12
+ equal(this.proxy.app, this.app)
13
+ })
14
+ .should('set is_native true if onhashchange exists in window', function() {
15
+ if (this.has_native) {
16
+ var proxy = new Sammy.HashLocationProxy(this.app)
17
+ ok(proxy.is_native)
18
+ } else {
19
+ ok(true, 'No native hash change support.')
20
+ }
21
+ })
22
+ .should('set is_native to false if onhashchange does not exist in window', function() {
23
+ if (!this.has_native) {
24
+ var proxy = new Sammy.HashLocationProxy(this.app)
25
+ ok(!proxy.is_native)
26
+ } else {
27
+ ok(true, 'Native hash change support.')
28
+ }
29
+ })
30
+ .should('create poller on hash change', function() {
31
+ if (!this.has_native) {
32
+ ok(Sammy.HashLocationProxy._interval);
33
+ isType(Sammy.HashLocationProxy._interval, 'Number');
34
+ } else {
35
+ ok(true, 'Native hash change support.')
36
+ }
37
+ })
38
+ .should('only create a single poller', function() {
39
+ if (!this.has_native) {
40
+ var interval = Sammy.HashLocationProxy._interval;
41
+ var proxy = new Sammy.HashLocationProxy(this.app)
42
+ equal(Sammy.HashLocationProxy._interval, interval);
43
+ } else {
44
+ ok(true, 'Native hash change support.')
45
+ }
46
+ });
47
+
48
+
49
+ context('Sammy', 'DataLocationProxy', {
50
+ before: function() {
51
+ this.app = new Sammy.Application(function() {
52
+ this.location_proxy = new Sammy.DataLocationProxy(this);
53
+ });
54
+ }
55
+ })
56
+ .should('store a pointer to the app', function() {
57
+ equal(this.app.location_proxy.app, this.app);
58
+ })
59
+ .should('be able to configure data name', function() {
60
+ var proxy = new Sammy.DataLocationProxy(this.app, 'othername');
61
+ proxy.setLocation('newlocation');
62
+ equal($('body').data('othername'), 'newlocation');
63
+ })
64
+ .should('trigger app event when data changes', function() {
65
+ $('body').data(this.app.location_proxy.data_name, '');
66
+ var triggered = false, app = this.app;
67
+ app.bind('location-changed', function() {
68
+ triggered = true;
69
+ });
70
+ ok(!triggered);
71
+ app.run('#/');
72
+ $('body').data(this.app.location_proxy.data_name, '#/newhash');
73
+ soon(function() {
74
+ ok(triggered);
75
+ equal(this.app.getLocation(), '#/newhash');
76
+ app.unload();
77
+ }, this, 2, 3);
78
+ })
79
+ .should('return the current location from data', function() {
80
+ $('body').data(this.app.location_proxy.data_name, '#/zuh')
81
+ equal(this.app.location_proxy.getLocation(), '#/zuh');
82
+ })
83
+ .should('set the current location in data', function() {
84
+ $('body').data(this.app.location_proxy.data_name, '#/zuh')
85
+ equal(this.app.location_proxy.getLocation(), '#/zuh');
86
+ this.app.location_proxy.setLocation('#/boosh');
87
+ equal('#/boosh', this.app.location_proxy.getLocation());
88
+ });
89
+
90
+ }
91
+ })(jQuery);
@@ -0,0 +1,296 @@
1
+ (function($) {
2
+ with(QUnit) {
3
+ context('Sammy.Cache', 'cache', {
4
+ before: function() {
5
+ this.app = new Sammy.Application(function() {
6
+ this.use(Sammy.Cache);
7
+ this.clearCache();
8
+ this.cache('mycache', 'my value');
9
+ this.cache('mynumcache', 3);
10
+ });
11
+ this.other_app = new Sammy.Application(function() {
12
+ this.element_selector = '#main';
13
+ this.use(Sammy.Cache);
14
+ this.clearCache();
15
+ this.cache('mycache', 'not my value');
16
+ this.cache('mynumcache', 7);
17
+ });
18
+ }
19
+ })
20
+ .should('retrieve values by passing name', function() {
21
+ equal(this.app.cache('mycache'), 'my value');
22
+ equal(this.other_app.cache('mycache'), 'not my value');
23
+ equal(this.app.cache('mynumcache'), 3);
24
+ equal(this.other_app.cache('mynumcache'), 7);
25
+ })
26
+ .should('set values by passing value', function() {
27
+ this.app.cache('mycache', 'my new value');
28
+ equal(this.app.cache('mycache'), 'my new value');
29
+ })
30
+ .should('run callback only if value is not set', function() {
31
+ var inner_context = null;
32
+ var was_run = false;
33
+ this.app.cache('mycache', function() {
34
+ was_run = true;
35
+ return 'new value';
36
+ });
37
+ equal(was_run, false);
38
+ equal(inner_context, null);
39
+ this.app.cache('mynewcache', function() {
40
+ was_run = true;
41
+ inner_context = this;
42
+ return 'new value';
43
+ });
44
+ equal(was_run, true);
45
+ deepEqual(inner_context, this.app.store('cache'), "The inner context should equal the store");
46
+ equal(this.app.cache('mynewcache'), 'new value', "Should set the new value");
47
+ })
48
+ .should('clear specific cache value', function() {
49
+ this.app.store('cache').clear('mycache');
50
+ ok(!this.app.cache('mycache'))
51
+ });
52
+
53
+
54
+ context('Sammy', 'Template', {
55
+ before: function() {
56
+ this.app = new Sammy.Application(function() {
57
+ this.use(Sammy.Template);
58
+ });
59
+ this.context = new this.app.context_prototype(this.app, 'get', '#/', {});
60
+
61
+ this.alias_app = new Sammy.Application(function() {
62
+ this.use(Sammy.Template, 'tpl');
63
+ });
64
+ this.alias_context = new this.alias_app.context_prototype(this.alias_app, 'get', '#/', {});
65
+ }
66
+ })
67
+ .should('add template helper to event context', function() {
68
+ ok($.isFunction(this.context.template));
69
+ })
70
+ .should('interpolate content', function() {
71
+ var rendered = this.context.template('<div class="test_class"><%= text %></div>', {text: 'TEXT!'});
72
+ equal(rendered, '<div class="test_class">TEXT!</div>');
73
+ })
74
+ .should('set the context of the template to the test_context', function() {
75
+ this.context.blurgh = 'boosh';
76
+ var rendered = this.context.template('<div class="test_class"><%= text %> <%= blurgh %></div>', {text: 'TEXT!'});
77
+ equal(rendered, '<div class="test_class">TEXT! boosh</div>');
78
+ })
79
+ .should('render templates with a lot of single quotes', function() {
80
+ var rendered = this.context.template("<div class='test_class' id='test'>I'm <%= text %></div>", {text: 'TEXT!'});
81
+ equal(rendered, "<div class='test_class' id='test'>I'm TEXT!</div>");
82
+ })
83
+ .should('alias the template method and thus the extension', function() {
84
+ ok(!$.isFunction(this.alias_context.template));
85
+ ok($.isFunction(this.alias_context.tpl));
86
+ ok(this.alias_context.tpl.toString().match(/srender/));
87
+ });
88
+
89
+
90
+ context('Sammy.NestedParams', 'parsing', {
91
+ before: function () {
92
+ this.app = new Sammy.Application(function() {
93
+ this.element_selector = '#form_params';
94
+ this.use(Sammy.NestedParams);
95
+ this.route('post', /test_nested_params/, function() {
96
+ this.app.form_params = this.params;
97
+ return false;
98
+ });
99
+ });
100
+ }
101
+ })
102
+ .should('parse a twice submitted value', function() {
103
+ var app = this.app;
104
+ app.run('#/');
105
+ $('#nested_params_test_form').submit();
106
+ soon(function() {
107
+ ok(app.form_params);
108
+ equal(app.form_params['author'], 'Thoreau');
109
+ app.unload();
110
+ }, this, 1, 2);
111
+ })
112
+ .should('parse basic arrays', function() {
113
+ var app = this.app;
114
+ app.run('#/');
115
+ $('#nested_params_test_form').submit();
116
+ soon(function() {
117
+ ok(app.form_params);
118
+ equal(app.form_params['genre'][0], ['documentary']);
119
+ equal(app.form_params['genre'][1], ['nature']);
120
+ app.unload();
121
+ }, this, 1, 3);
122
+ })
123
+ .should('parse basic hashes', function() {
124
+ var app = this.app;
125
+ app.run('#/');
126
+ $('#nested_params_test_form').submit();
127
+ soon(function() {
128
+ ok(app.form_params);
129
+ equal(app.form_params['poll']['name'], 'Which beverage do you like best?');
130
+ equal(app.form_params['poll']['priority'], '10');
131
+ app.unload();
132
+ }, this, 1, 3);
133
+ })
134
+ .should('parse nested hashes', function() {
135
+ var app = this.app;
136
+ app.run('#/');
137
+ $('#nested_params_test_form').submit();
138
+ soon(function() {
139
+ ok(app.form_params);
140
+ equal(app.form_params['poll']['options']['1']['id'], 'Ko5Pi');
141
+ equal(app.form_params['poll']['options']['1']['name'], 'Coffee');
142
+ equal(app.form_params['poll']['options']['2']['id'], 'Oaj5N');
143
+ equal(app.form_params['poll']['options']['2']['name'], 'Tea');
144
+ app.unload();
145
+ }, this, 1, 5);
146
+ })
147
+ .should('parse arrays in nested hashes', function() {
148
+ var app = this.app;
149
+ app.run('#/');
150
+ $('#nested_params_test_form').submit();
151
+ soon(function() {
152
+ ok(app.form_params);
153
+ equal(app.form_params['poll']['options']['1']['ingredients'][0], 'Water');
154
+ equal(app.form_params['poll']['options']['1']['ingredients'][1], 'Coffein');
155
+ app.unload();
156
+ }, this, 1, 3);
157
+ })
158
+ .should('parse hashes in nested arrays in nested hashes', function() {
159
+ var app = this.app;
160
+ app.run('#/');
161
+ $('#nested_params_test_form').submit();
162
+ soon(function() {
163
+ ok(app.form_params);
164
+ equal(app.form_params['woods']['trees'][0]['name'], 'Spruce');
165
+ equal(app.form_params['woods']['trees'][1]['name'], 'Maple');
166
+ app.unload();
167
+ }, this, 1, 3);
168
+ })
169
+ .should('parse arrays in nested hashes in nested arrays', function() {
170
+ var app = this.app;
171
+ app.run('#/');
172
+ $('#nested_params_test_form').submit();
173
+ soon(function() {
174
+ ok(app.form_params);
175
+ equal(app.form_params['pages'][0]['words'][0], 'Woods');
176
+ equal(app.form_params['pages'][1]['words'][0], 'Money');
177
+ app.unload();
178
+ }, this, 1, 3);
179
+ })
180
+ .should('parse complex hashes in nested arrays in nested hashes', function() {
181
+ var app = this.app;
182
+ app.run('#/');
183
+ $('#nested_params_test_form').submit();
184
+ soon(function() {
185
+ ok(app.form_params);
186
+ equal(app.form_params['music']['instruments'][0]['name'], 'Piano');
187
+ equal(app.form_params['music']['instruments'][0]['size'], 'big');
188
+ equal(app.form_params['music']['instruments'][1]['name'], 'Flute');
189
+ equal(app.form_params['music']['instruments'][1]['size'], 'small');
190
+ app.unload();
191
+ }, this, 1, 5);
192
+ })
193
+ .should('unescape escaped params', function() {
194
+ var app = this.app;
195
+ app.run('#/');
196
+ $('#nested_params_test_form').submit();
197
+ soon(function() {
198
+ ok(app.form_params);
199
+ equal(app.form_params['title'], 'Walden!');
200
+ app.unload();
201
+ }, this, 1, 2);
202
+ });
203
+
204
+ context('Sammy.NestedParams', 'bad fields', {
205
+ before: function () {
206
+ this.app = new Sammy.Application(function() {
207
+ this.element_selector = '#form_params';
208
+ this.use(Sammy.NestedParams);
209
+ });
210
+ }
211
+ }).should('raise error for bad params', function() {
212
+ var app = this.app;
213
+ raised(/400/, function() {
214
+ app._parseFormParams($('#bad_nested_params_form'));
215
+ });
216
+ });
217
+
218
+
219
+ // Pretty much a copy of the Template tests
220
+ context('Sammy', 'Mustache', {
221
+ before: function() {
222
+ this.app = new Sammy.Application(function() {
223
+ this.use(Sammy.Mustache);
224
+ });
225
+ this.context = new this.app.context_prototype(this.app, 'get', '#/', {});
226
+
227
+ this.alias_app = new Sammy.Application(function() {
228
+ this.use(Sammy.Mustache, 'ms');
229
+ });
230
+ this.alias_context = new this.alias_app.context_prototype(this.alias_app, 'get', '#/', {});
231
+ }
232
+ })
233
+ .should('add mustache helper to event context', function() {
234
+ ok($.isFunction(this.context.mustache));
235
+ })
236
+ .should('interpolate content', function() {
237
+ var rendered = this.context.mustache('<div class="test_class">{{text}}</div>', {text: 'TEXT!'});
238
+ equal(rendered, '<div class="test_class">TEXT!</div>');
239
+ })
240
+ .should('set the context of the template to the test_context', function() {
241
+ this.context.blurgh = 'boosh';
242
+ var rendered = this.context.mustache('<div class="test_class">{{text}} {{blurgh}}</div>', {text: 'TEXT!'});
243
+ equal(rendered, '<div class="test_class">TEXT! boosh</div>');
244
+ })
245
+ .should('allow mustache partials by passing partials to data', function() {
246
+ var data = {blurgh: 'boosh', partials: {first: 'a {{what}}'}, first: {what: 'partial'}};
247
+ var rendered = this.context.mustache('<div class="test_class">{{>first}} {{blurgh}}</div>', data);
248
+ equal(rendered, '<div class="test_class">a partial boosh</div>');
249
+ })
250
+ .should('alias the mustache method and thus the extension', function() {
251
+ ok(!$.isFunction(this.alias_context.mustache));
252
+ ok($.isFunction(this.alias_context.ms));
253
+ ok(this.alias_context.ms.toString().match(/Mustache/));
254
+ });
255
+
256
+ context('Sammy', 'JSON', {
257
+ before: function() {
258
+ this.app = new Sammy.Application(function() {
259
+ this.use(Sammy.JSON);
260
+ });
261
+ this.context = new this.app.context_prototype(this.app, 'get', '#/', {});
262
+ }
263
+ })
264
+ .should('add json helper to event context', function() {
265
+ ok($.isFunction(this.context.json));
266
+ })
267
+ .should('ensure JSON is in the global namespace', function() {
268
+ ok($.isFunction(JSON.parse));
269
+ ok($.isFunction(JSON.stringify));
270
+ })
271
+ .should('parse JSON if object is a string', function() {
272
+ equal(this.context.json("{\"test\":\"123\"}").test, "123");
273
+ })
274
+ .should('stringify JSON if object is an object', function() {
275
+ equal(this.context.json({test: "123"}),"{\"test\":\"123\"}");
276
+ });
277
+
278
+
279
+ context('Sammy', 'Haml', {
280
+ before: function() {
281
+ this.app = new Sammy.Application(function() {
282
+ this.use(Sammy.Haml);
283
+ });
284
+ this.context = new this.app.context_prototype(this.app, 'get', '#/', {});
285
+ }
286
+ })
287
+ .should('add haml helper to context', function() {
288
+ ok($.isFunction(this.context.haml));
289
+ })
290
+ .should('use haml-js to render haml templates', function() {
291
+ var template = ".mytemplate= title";
292
+ deepEqual(this.context.haml(template, {title: "HAML!!"}), "<div class=\"mytemplate\">HAML!!\n</div>");
293
+ });
294
+
295
+ };
296
+ })(jQuery);