hobo 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/hobo +3 -2
- data/hobo_files/plugin/CHANGES.txt +299 -2
- data/hobo_files/plugin/Rakefile +12 -10
- data/hobo_files/plugin/generators/hobo/templates/guest.rb +1 -13
- data/hobo_files/plugin/generators/hobo_migration/hobo_migration_generator.rb +11 -7
- data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +1 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_rapid.js +1 -1
- data/hobo_files/plugin/generators/hobo_rapid/templates/lowpro.js +405 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +1 -1
- data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +1 -9
- data/hobo_files/plugin/init.rb +5 -0
- data/hobo_files/plugin/lib/active_record/has_many_association.rb +1 -1
- data/hobo_files/plugin/lib/extensions.rb +26 -5
- data/hobo_files/plugin/lib/extensions/test_case.rb +1 -1
- data/hobo_files/plugin/lib/hobo.rb +37 -11
- data/hobo_files/plugin/lib/hobo/authenticated_user.rb +7 -2
- data/hobo_files/plugin/lib/hobo/authentication_support.rb +7 -6
- data/hobo_files/plugin/lib/hobo/composite_model.rb +5 -0
- data/hobo_files/plugin/lib/hobo/controller.rb +4 -4
- data/hobo_files/plugin/lib/hobo/dryml.rb +5 -5
- data/hobo_files/plugin/lib/hobo/dryml/part_context.rb +3 -6
- data/hobo_files/plugin/lib/hobo/dryml/template.rb +16 -15
- data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +24 -20
- data/hobo_files/plugin/lib/hobo/email_address.rb +4 -0
- data/hobo_files/plugin/lib/hobo/field_spec.rb +2 -1
- data/hobo_files/plugin/lib/hobo/guest.rb +21 -0
- data/hobo_files/plugin/lib/hobo/hobo_helper.rb +42 -2
- data/hobo_files/plugin/lib/hobo/http_parameters.rb +225 -0
- data/hobo_files/plugin/lib/hobo/model.rb +55 -37
- data/hobo_files/plugin/lib/hobo/model_controller.rb +151 -151
- data/hobo_files/plugin/lib/hobo/model_queries.rb +30 -5
- data/hobo_files/plugin/lib/hobo/user_controller.rb +27 -16
- data/hobo_files/plugin/lib/hobo/where_fragment.rb +6 -1
- data/hobo_files/plugin/tags/rapid.dryml +88 -58
- data/hobo_files/plugin/tags/rapid_document_tags.dryml +5 -5
- data/hobo_files/plugin/tags/rapid_editing.dryml +3 -3
- data/hobo_files/plugin/tags/rapid_forms.dryml +35 -26
- data/hobo_files/plugin/tags/rapid_navigation.dryml +13 -12
- data/hobo_files/plugin/tags/rapid_pages.dryml +35 -31
- data/hobo_files/plugin/tags/rapid_plus.dryml +41 -0
- data/hobo_files/plugin/tags/rapid_support.dryml +18 -9
- data/hobo_files/plugin/tasks/dump_fixtures.rake +61 -0
- metadata +7 -11
- data/hobo_files/plugin/spec/fixtures/users.yml +0 -9
- data/hobo_files/plugin/spec/spec.opts +0 -6
- data/hobo_files/plugin/spec/spec_helper.rb +0 -28
- data/hobo_files/plugin/spec/unit/hobo/dryml/template_spec.rb +0 -650
@@ -1,28 +0,0 @@
|
|
1
|
-
ENV['RAILS_ENV'] ||= 'mysql'
|
2
|
-
require File.dirname(__FILE__) + '/rails_root/config/environment.rb'
|
3
|
-
|
4
|
-
# Run the migrations
|
5
|
-
ActiveRecord::Migrator.migrate("#{RAILS_ROOT}/db/migrate")
|
6
|
-
|
7
|
-
require 'spec/rails'
|
8
|
-
|
9
|
-
Spec::Runner.configure do |config|
|
10
|
-
config.use_transactional_fixtures = true
|
11
|
-
config.use_instantiated_fixtures = false
|
12
|
-
config.fixture_path = File.dirname(__FILE__) + "/fixtures/"
|
13
|
-
config.before(:each, :behaviour_type => :controller) do
|
14
|
-
raise_controller_errors
|
15
|
-
end
|
16
|
-
|
17
|
-
# You can declare fixtures for each behaviour like this:
|
18
|
-
# describe "...." do
|
19
|
-
# fixtures :table_a, :table_b
|
20
|
-
#
|
21
|
-
# Alternatively, if you prefer to declare them only once, you can
|
22
|
-
# do so here, like so ...
|
23
|
-
#
|
24
|
-
# config.global_fixtures = :table_a, :table_b
|
25
|
-
#
|
26
|
-
# If you declare global fixtures, be aware that they will be declared
|
27
|
-
# for all of your examples, even those that don't use them.
|
28
|
-
end
|
@@ -1,650 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
|
-
|
3
|
-
Template = Hobo::Dryml::Template
|
4
|
-
DrymlException = Hobo::Dryml::DrymlException
|
5
|
-
|
6
|
-
describe Template do
|
7
|
-
|
8
|
-
# --- Tag Compilation Examples --- #
|
9
|
-
|
10
|
-
# --- Compilation: Calling Block Tags --- #
|
11
|
-
|
12
|
-
it "should compile block-tag calls as method calls" do
|
13
|
-
compile_dryml("<foo/>").should == "<%= foo() %>"
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should compile attributes as keyword parameters" do
|
17
|
-
compile_dryml("<foo a='1' b='2'/>").should == '<%= foo({:a => "1", :b => "2"}) %>'
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should compile code attributes as ruby code" do
|
21
|
-
compile_dryml("<foo a='&1 + 2'/>").should == '<%= foo({:a => (1 + 2)}) %>'
|
22
|
-
end
|
23
|
-
|
24
|
-
it "should compile block-tag attributes with no RHS as passing `true`" do
|
25
|
-
compile_dryml("<foo a/>").should == '<%= foo({:a => (true)}) %>'
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should compile content of a block-tag call as a Ruby block" do
|
29
|
-
compile_dryml("<foo>the body</foo>").should == "<% _output(foo() do |foo_default_tagbody| %>the body<% end) %>"
|
30
|
-
end
|
31
|
-
|
32
|
-
it "should support <default_tagbody/> inside the content of a block-tag" do
|
33
|
-
compile_dryml("<foo>!!<default_tagbody/>??</foo>").should ==
|
34
|
-
"<% _output(foo() do |foo_default_tagbody| %>!!<% foo_default_tagbody && foo_default_tagbody.call %>??<% end) %>"
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should support the 'for' attribute on <default_tagbody/>" do
|
38
|
-
compile_dryml("<x><y>123<default_tagbody for='x'/>456</y></x>").should ==
|
39
|
-
"<% _output(x() do |x_default_tagbody| %><% _output(y() do |y_default_tagbody| %>" +
|
40
|
-
"123<% x_default_tagbody && x_default_tagbody.call %>456" +
|
41
|
-
"<% end) %><% end) %>"
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should allow :foo as a shorthand for field='foo' on block tags" do
|
45
|
-
compile_dryml("<foo:name/>").should == '<%= foo({:field => "name"}) %>'
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should allow :title as a shorthand for field='title' on block tags (title is a static tag)" do
|
49
|
-
compile_dryml("<foo:name/>").should == '<%= foo({:field => "name"}) %>'
|
50
|
-
end
|
51
|
-
|
52
|
-
it "should allow close tags to ommit the :field_name part" do
|
53
|
-
compile_dryml("<foo:name></foo>").should == '<%= foo({:field => "name"}) %>'
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should compile block-tag calls with merge_attrs" do
|
57
|
-
compile_dryml("<foo merge_attrs/>").should == "<%= foo({}.merge((attributes) || {})) %>"
|
58
|
-
compile_dryml("<foo a='1' merge_attrs/>").should == '<%= foo({:a => "1"}.merge((attributes) || {})) %>'
|
59
|
-
end
|
60
|
-
|
61
|
-
# --- Compilation: Defining Block Tags --- #
|
62
|
-
|
63
|
-
it "should compile defs with lower-case names as block tags" do
|
64
|
-
compile_def("<def tag='foo'></def>").should ==
|
65
|
-
"<% def foo(all_attributes={}, &__block__); " +
|
66
|
-
"parameters = nil; " +
|
67
|
-
"_tag_context(all_attributes, __block__) do |tagbody| attributes, = _tag_locals(all_attributes, []) %>" +
|
68
|
-
"<% _erbout; end; end %>"
|
69
|
-
end
|
70
|
-
|
71
|
-
it "should compile attrs in defs as local variables" do
|
72
|
-
compile_def("<def tag='foo' attrs='a, b'></def>").should ==
|
73
|
-
"<% def foo(all_attributes={}, &__block__); " +
|
74
|
-
"parameters = nil; " +
|
75
|
-
"_tag_context(all_attributes, __block__) do |tagbody| " +
|
76
|
-
"a, b, attributes, = _tag_locals(all_attributes, [:a, :b]) %>" +
|
77
|
-
"<% _erbout; end; end %>"
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should allow a default tagbody to be given inside the <tagbody> tag" do
|
81
|
-
compile_def("<def tag='foo'>123 <tagbody>blah</tagbody> 456</def>").should ==
|
82
|
-
"<% def foo(all_attributes={}, &__block__); " +
|
83
|
-
"parameters = nil; " +
|
84
|
-
"_tag_context(all_attributes, __block__) do |tagbody| attributes, = _tag_locals(all_attributes, []) %>" +
|
85
|
-
"123 " +
|
86
|
-
"<% _output(do_tagbody(tagbody, {}, proc { %>blah<% })) %>" +
|
87
|
-
" 456" +
|
88
|
-
"<% _erbout; end; end %>"
|
89
|
-
end
|
90
|
-
|
91
|
-
# --- Compilation: Defining Templates --- #
|
92
|
-
|
93
|
-
it "should compile defs with cap names as templates" do
|
94
|
-
# Note the presence of the `parameters` param, which block-tags don't have
|
95
|
-
compile_def("<def tag='Foo'></def>").should ==
|
96
|
-
"<% def Foo(all_attributes={}, all_parameters={}, &__block__); " +
|
97
|
-
"parameters = all_parameters - []; " +
|
98
|
-
"_tag_context(all_attributes, __block__) do |tagbody| attributes, = _tag_locals(all_attributes, []) %>" +
|
99
|
-
"<% _erbout; end; end %>"
|
100
|
-
end
|
101
|
-
|
102
|
-
it "should dissallow `param` outside of template definitions" do
|
103
|
-
proc { compile_dryml("<foo param/>") }.should raise_error(DrymlException)
|
104
|
-
end
|
105
|
-
|
106
|
-
it "should compile param tag-calls as calls to `call_block_tag_parameter`" do
|
107
|
-
compile_in_template("<foo param a='1'/>").should == '<%= call_block_tag_parameter(:foo, {:a => "1"}, all_parameters[:foo]) %>'
|
108
|
-
end
|
109
|
-
|
110
|
-
it "should compile with support for named params" do
|
111
|
-
compile_in_template("<foo param='zap'/>").should == "<%= call_block_tag_parameter(:foo, {}, all_parameters[:zap]) %>"
|
112
|
-
end
|
113
|
-
|
114
|
-
it "should compile a param tag-call with a body" do
|
115
|
-
compile_in_template("<foo param>abc</foo>").should ==
|
116
|
-
"<% _output(call_block_tag_parameter(:foo, {}, all_parameters[:foo]) do |foo_default_tagbody| %>abc<% end) %>"
|
117
|
-
end
|
118
|
-
|
119
|
-
it "should compile a param tag-call with a body and a call to <default_tagbody/>" do
|
120
|
-
compile_in_template("<foo param>!!<default_tagbody/>!!</foo>").should ==
|
121
|
-
"<% _output(call_block_tag_parameter(:foo, {}, all_parameters[:foo]) do |foo_default_tagbody| %>" +
|
122
|
-
"!!<% foo_default_tagbody && foo_default_tagbody.call %>!!<% end) %>"
|
123
|
-
end
|
124
|
-
|
125
|
-
it "should compile param template-calls as calls to `call_template_parameter`" do
|
126
|
-
compile_in_template("<Foo param/>").should ==
|
127
|
-
"<% _output(call_template_parameter(:Foo, {}, {}, all_parameters[:Foo])) %>"
|
128
|
-
end
|
129
|
-
|
130
|
-
it "should compile param template-calls with parameters as calls to `call_template_parameter`" do
|
131
|
-
compile_in_template("<Foo param><a x='1'/></Foo>").should ==
|
132
|
-
'<% _output(call_template_parameter(:Foo, {}, {:a => proc { {:x => "1"} }, }, all_parameters[:Foo])) %>'
|
133
|
-
end
|
134
|
-
|
135
|
-
it "should compile template parameters with param" do
|
136
|
-
compile_in_template("<Foo><abc param/></Foo>").should ==
|
137
|
-
'<% _output(Foo({}, {:abc => merge_option_procs(proc { {} }, all_parameters[:abc]), })) %>'
|
138
|
-
end
|
139
|
-
|
140
|
-
it "should compile template parameters with named params" do
|
141
|
-
compile_in_template("<Foo><abc param='x'/></Foo>").should ==
|
142
|
-
'<% _output(Foo({}, {:abc => merge_option_procs(proc { {} }, all_parameters[:x]), })) %>'
|
143
|
-
end
|
144
|
-
|
145
|
-
it "should compile template parameters with param and attributes" do
|
146
|
-
compile_in_template("<Foo><abc param='x' a='b'/></Foo>").should ==
|
147
|
-
'<% _output(Foo({}, {:abc => merge_option_procs(proc { {:a => "b"} }, all_parameters[:x]), })) %>'
|
148
|
-
end
|
149
|
-
|
150
|
-
it "should compile template parameters with param and a tag body" do
|
151
|
-
compile_in_template("<Foo><abc param>ha!</abc></Foo>").should ==
|
152
|
-
'<% _output(Foo({}, {:abc => merge_option_procs(' +
|
153
|
-
'proc { {:tagbody => proc {|abc_default_tagbody| new_context { %>ha!<% } } } }, all_parameters[:abc]), })) %>'
|
154
|
-
end
|
155
|
-
|
156
|
-
it "should compile template parameters which are template calls themselves" do
|
157
|
-
compile_in_template("<Foo><Baa param x='1'/></Foo>").should ==
|
158
|
-
'<% _output(Foo({}, {:Baa => merge_template_parameter_procs(proc { [{:x => "1"}, {}] }, all_parameters[:Baa]), })) %>'
|
159
|
-
end
|
160
|
-
|
161
|
-
it "should compile template parameters which are templates themselves with their own parameters" do
|
162
|
-
compile_in_template("<Foo><Baa param><x>hello</x></Baa></Foo>").should ==
|
163
|
-
'<% _output(Foo({}, {:Baa => merge_template_parameter_procs(' +
|
164
|
-
'proc { [{}, {:x => proc { {:tagbody => proc {|x_default_tagbody| new_context { %>hello<% } } } }, }] }, all_parameters[:Baa]), })) %>'
|
165
|
-
end
|
166
|
-
|
167
|
-
# --- Compilation: Calling Templates --- #
|
168
|
-
|
169
|
-
it "should compile template calls as method calls" do
|
170
|
-
compile_dryml("<Foo/>").should == "<% _output(Foo({}, {})) %>"
|
171
|
-
end
|
172
|
-
|
173
|
-
it "should compile attributes on template calls as keyword parameters" do
|
174
|
-
compile_dryml("<Foo a='1' b='2'/>").should == '<% _output(Foo({:a => "1", :b => "2"}, {})) %>'
|
175
|
-
end
|
176
|
-
|
177
|
-
it "should compile template parameters as procs" do
|
178
|
-
compile_dryml("<Foo><x>hello</x><y>world</y></Foo>").should ==
|
179
|
-
'<% _output(Foo({}, {' +
|
180
|
-
':x => proc { {:tagbody => proc {|x_default_tagbody| new_context { %>hello<% } } } }, ' +
|
181
|
-
':y => proc { {:tagbody => proc {|y_default_tagbody| new_context { %>world<% } } } }, })) %>'
|
182
|
-
end
|
183
|
-
|
184
|
-
it "should compile template parameters with attributes" do
|
185
|
-
compile_dryml("<Foo><abc x='1'>hello</abc></Foo>").should ==
|
186
|
-
'<% _output(Foo({}, {:abc => proc { {:x => "1", :tagbody => proc {|abc_default_tagbody| new_context { %>hello<% } } } }, })) %>'
|
187
|
-
end
|
188
|
-
|
189
|
-
it "should allow :foo as a shorthand for field='foo' on template tags" do
|
190
|
-
compile_dryml("<Foo:name/>").should == '<% _output(Foo({:field => "name"}, {})) %>'
|
191
|
-
end
|
192
|
-
|
193
|
-
it "should dissallow tag-bodies on template calls" do
|
194
|
-
proc { compile_dryml("<Foo>this is a tag body</Foo>") }.should raise_error(DrymlException)
|
195
|
-
end
|
196
|
-
|
197
|
-
it "should dissallow tag-bodies on nested template calls" do
|
198
|
-
proc { compile_dryml("<Foo><Baa>this is a tag body</Baa></Foo>") }.should raise_error(DrymlException)
|
199
|
-
end
|
200
|
-
|
201
|
-
it "should compile template parameters which are themselves templates" do
|
202
|
-
# Template parameters which are themselves templates are procs
|
203
|
-
# that return a pair of hashes, the first is the attributes to the
|
204
|
-
# template, the second is the sub-template procs
|
205
|
-
compile_dryml("<Foo><Baa x='1'><a>hello</a></Baa></Foo>").should ==
|
206
|
-
'<% _output(Foo({}, ' +
|
207
|
-
'{:Baa => proc { [{:x => "1"}, {:a => proc { {:tagbody => proc {|a_default_tagbody| new_context { %>hello<% } } } }, }] }, })) %>'
|
208
|
-
end
|
209
|
-
|
210
|
-
it "should compile 'replace' parameters" do
|
211
|
-
compile_dryml("<Page><head replace>abc</head></Page>").should ==
|
212
|
-
'<% _output(Page({}, {:head => proc {|head__default| new_context { %>abc<% } }, })) %>'
|
213
|
-
end
|
214
|
-
|
215
|
-
it "should compile 'replace' parameters with a default parameter call" do
|
216
|
-
compile_dryml("<Page><head replace>abc <head restore>blah</head></head></Page>").should ==
|
217
|
-
|
218
|
-
'<% _output(Page({}, {:head => proc {|head__default| new_context { %>abc ' +
|
219
|
-
'<% _output(head__default.call_with_block({}) do |head_default_tagbody| %>blah<% end) %>' +
|
220
|
-
'<% } }, })) %>'
|
221
|
-
end
|
222
|
-
|
223
|
-
it "should compile 'replace' template parameters with a default parameter call" do
|
224
|
-
compile_dryml("<Page><Head replace>abc <Head restore/></Head></Page>").should ==
|
225
|
-
|
226
|
-
'<% _output(Page({}, {:Head => proc {|Head__default| new_context { %>abc ' +
|
227
|
-
'<% _output(Head__default.call({}, {})) %>' +
|
228
|
-
'<% } }, })) %>'
|
229
|
-
end
|
230
|
-
|
231
|
-
# --- Tag Evalutation Examples --- #
|
232
|
-
|
233
|
-
|
234
|
-
# --- Static Tags --- #
|
235
|
-
|
236
|
-
it "should pass through tags declared as static" do
|
237
|
-
"p".should be_in(Hobo.static_tags)
|
238
|
-
eval_dryml("<p>abc</p>").should == "<p>abc</p>"
|
239
|
-
eval_dryml("<p x='1' y='2'>abc</p>").should == "<p x='1' y='2'>abc</p>"
|
240
|
-
end
|
241
|
-
|
242
|
-
it "should pass through attributes with no rhs on static tags" do
|
243
|
-
"p".should be_in(Hobo.static_tags)
|
244
|
-
eval_dryml("<p foo baa>abc</p>").should == "<p foo baa>abc</p>"
|
245
|
-
end
|
246
|
-
|
247
|
-
it "should support attribute merging on static tags" do
|
248
|
-
eval_dryml(%(<p class="big" id="x" merge_attrs="&{:class => 'small', :id => 'y', :a => 'b'}"/>)).
|
249
|
-
should be_dom_equal_to('<p class="big small" id="y" a="b"/>')
|
250
|
-
end
|
251
|
-
|
252
|
-
it "should support attribute merging of all extra attributes on static tags" do
|
253
|
-
eval_dryml(%(<def tag="x"><p class="big" id="x" merge_attrs/></def>
|
254
|
-
<x class='small' id='y' a='b'/>)).
|
255
|
-
should be_dom_equal_to('<p class="big small" id="y" a="b"/>')
|
256
|
-
end
|
257
|
-
|
258
|
-
|
259
|
-
# --- Block Tags --- #
|
260
|
-
|
261
|
-
|
262
|
-
def eval_with_defs(dryml)
|
263
|
-
eval_dryml(<<-END + dryml).strip
|
264
|
-
<def tag="t">plain tag</def>
|
265
|
-
|
266
|
-
<def tag="t_attr" attrs="x">it is <%= x %></def>
|
267
|
-
|
268
|
-
<def tag="t_body">( <tagbody>hmm</tagbody> )</def>
|
269
|
-
|
270
|
-
<def tag="merge_attrs_example"><p merge_attrs>hi</p></def>
|
271
|
-
END
|
272
|
-
end
|
273
|
-
|
274
|
-
it "should call block tags" do
|
275
|
-
eval_with_defs("<t/>").should == "plain tag"
|
276
|
-
end
|
277
|
-
|
278
|
-
|
279
|
-
it "should call block tags passing attributes" do
|
280
|
-
eval_with_defs("<t_attr x='10'/>").should == "it is 10"
|
281
|
-
end
|
282
|
-
|
283
|
-
it "should call block tags with a body" do
|
284
|
-
eval_with_defs("<t_body>foo</t_body>").should == "( foo )"
|
285
|
-
end
|
286
|
-
|
287
|
-
it "should allow tagbody to have a default" do
|
288
|
-
eval_with_defs("<t_body/>").should == "( hmm )"
|
289
|
-
end
|
290
|
-
|
291
|
-
it "should provide access to the default tagbody when overriding the body" do
|
292
|
-
eval_with_defs("<t_body>[<default_tagbody/>]</t_body>").should == "( [hmm] )"
|
293
|
-
end
|
294
|
-
|
295
|
-
it "should support merge_attrs on static tags" do
|
296
|
-
eval_with_defs('<merge_attrs_example class="x"/>').should == '<p class="x">hi</p>'
|
297
|
-
end
|
298
|
-
|
299
|
-
it "should make the declared attributes available via the 'attrs_for' method" do
|
300
|
-
eval_with_defs('<%= attrs_for(:t_attr).inspect %>').should == '[:x]'
|
301
|
-
end
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
# --- Template Tags --- #
|
306
|
-
|
307
|
-
def eval_with_templates(dryml)
|
308
|
-
eval_dryml(<<-END + dryml).strip
|
309
|
-
<def tag="defined" attrs="a, b">a is <%= a %>, b is <%= b %>, body is <tagbody/></def>
|
310
|
-
|
311
|
-
<def tag="T">plain template</def>
|
312
|
-
|
313
|
-
<def tag="StaticMerge"><p>a <b name="big" param>bold</b> word</p></def>
|
314
|
-
|
315
|
-
<def tag="EmptyStaticMerge"><img name="big" src="..." param/></def>
|
316
|
-
|
317
|
-
<def tag="DefTagMerge">foo <defined param b="3">baa</defined>!</def>
|
318
|
-
|
319
|
-
<def tag="NestedStaticMerge">merge StaticMerge: <StaticMerge param/></def>
|
320
|
-
|
321
|
-
<def tag="ParameterMerge">parameter merge: <StaticMerge><b param/></StaticMerge></def>
|
322
|
-
END
|
323
|
-
end
|
324
|
-
|
325
|
-
it "should call template tags" do
|
326
|
-
eval_with_templates("<T/>").should == "plain template"
|
327
|
-
end
|
328
|
-
|
329
|
-
it "should add attributes to static tags when merging" do
|
330
|
-
eval_with_templates("<StaticMerge><b onclick='alert()'/></StaticMerge>").should ==
|
331
|
-
'<p>a <b name="big" onclick="alert()">bold</b> word</p>'
|
332
|
-
end
|
333
|
-
|
334
|
-
it "should override attributes on static tags when merging" do
|
335
|
-
eval_with_templates("<StaticMerge><b name='small'/></StaticMerge>").should ==
|
336
|
-
'<p>a <b name="small">bold</b> word</p>'
|
337
|
-
end
|
338
|
-
|
339
|
-
it "should replace tag bodies on static tags when merging" do
|
340
|
-
eval_with_templates('<StaticMerge><b>BOLD</b></StaticMerge>').should ==
|
341
|
-
'<p>a <b name="big">BOLD</b> word</p>'
|
342
|
-
end
|
343
|
-
|
344
|
-
it "should add attributes to defined tags when merging" do
|
345
|
-
eval_with_templates('<DefTagMerge><defined a="2"/></DefTagMerge>').should ==
|
346
|
-
'foo a is 2, b is 3, body is baa!'
|
347
|
-
end
|
348
|
-
|
349
|
-
it "should override attributes on defined tags when merging" do
|
350
|
-
eval_with_templates('<DefTagMerge><defined b="2"/></DefTagMerge>').should ==
|
351
|
-
'foo a is , b is 2, body is baa!'
|
352
|
-
end
|
353
|
-
|
354
|
-
it "should replace tag bodies on defined tags when merging" do
|
355
|
-
eval_with_templates('<DefTagMerge><defined>zip</defined></DefTagMerge>').should ==
|
356
|
-
'foo a is , b is 3, body is zip!'
|
357
|
-
end
|
358
|
-
|
359
|
-
it "should leave non-merged tags unchanged" do
|
360
|
-
eval_with_templates('<StaticMerge></StaticMerge>').should ==
|
361
|
-
'<p>a <b name="big">bold</b> word</p>'
|
362
|
-
end
|
363
|
-
|
364
|
-
it "should merge into static tags with no body" do
|
365
|
-
eval_with_templates("<EmptyStaticMerge><img name='small'/></EmptyStaticMerge>").should ==
|
366
|
-
'<img name="small" src="..." />'
|
367
|
-
end
|
368
|
-
|
369
|
-
it "should merge template parameters into nested templates" do
|
370
|
-
eval_with_templates('<NestedStaticMerge><StaticMerge><b name="small"/></StaticMerge></NestedStaticMerge>').should ==
|
371
|
-
'merge StaticMerge: <p>a <b name="small">bold</b> word</p>'
|
372
|
-
end
|
373
|
-
|
374
|
-
it "should merge the body of template parameters into nested templates" do
|
375
|
-
eval_with_templates('<NestedStaticMerge><StaticMerge><b>BOLD</b></StaticMerge></NestedStaticMerge>').should ==
|
376
|
-
'merge StaticMerge: <p>a <b name="big">BOLD</b> word</p>'
|
377
|
-
end
|
378
|
-
|
379
|
-
it "should allow param names to be defined dynamically" do
|
380
|
-
eval_dryml('<def tag="T"><p param="& :a.to_s + :b.to_s"/></def>' +
|
381
|
-
'<T><ab x="1"/></T>').should == '<p x="1" />'
|
382
|
-
end
|
383
|
-
|
384
|
-
it "should allow params to be defined on other params" do
|
385
|
-
eval_with_templates('<ParameterMerge><b name="small">foo</b></ParameterMerge>').should ==
|
386
|
-
'parameter merge: <p>a <b name="small">foo</b> word</p>'
|
387
|
-
|
388
|
-
end
|
389
|
-
|
390
|
-
it "should allow parameter bodies to be restored with static tag params" do
|
391
|
-
eval_with_templates("<StaticMerge><b>very <default_tagbody/></b></StaticMerge>").should ==
|
392
|
-
'<p>a <b name="big">very bold</b> word</p>'
|
393
|
-
end
|
394
|
-
|
395
|
-
it "should allow parameter bodies to be restored with defined tag params" do
|
396
|
-
eval_with_templates("<DefTagMerge><defined>hum<default_tagbody/></defined></DefTagMerge>").should ==
|
397
|
-
'foo a is , b is 3, body is humbaa!'
|
398
|
-
end
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
# --- Replacing Template Parameters --- #
|
403
|
-
|
404
|
-
it "should allow template parameters to be replaced" do
|
405
|
-
eval_with_templates('<StaticMerge><b replace>short</b></StaticMerge>').should ==
|
406
|
-
'<p>a short word</p>'
|
407
|
-
end
|
408
|
-
|
409
|
-
it "should allow template parameters to be replaced and then re-instated" do
|
410
|
-
eval_with_templates('<StaticMerge><b replace>short <b restore/></b></StaticMerge>').should ==
|
411
|
-
'<p>a short <b name="big">bold</b> word</p>'
|
412
|
-
end
|
413
|
-
|
414
|
-
it "should allow template parameters to be replaced and then re-instated with different attributes" do
|
415
|
-
eval_with_templates('<StaticMerge><b replace>short <b restore name="small"/></b></StaticMerge>').should ==
|
416
|
-
'<p>a short <b name="small">bold</b> word</p>'
|
417
|
-
end
|
418
|
-
|
419
|
-
it "should allow template parameters to be replaced and then re-instated with a different tagbody" do
|
420
|
-
eval_with_templates('<StaticMerge><b replace>short <b restore>big</b></b></StaticMerge>').should ==
|
421
|
-
'<p>a short <b name="big">big</b> word</p>'
|
422
|
-
end
|
423
|
-
|
424
|
-
# --- Merge Params --- #
|
425
|
-
|
426
|
-
|
427
|
-
it "should support merge_param on template calls" do
|
428
|
-
tags = %(<def tag="Page"><h1 param='title'/><div param='footer'/></def>
|
429
|
-
<def tag="MyPage"><Page merge_params><footer>the footer</footer></Page></def>)
|
430
|
-
|
431
|
-
eval_dryml(tags + "<MyPage><title>Hi!</title></MyPage>").should == '<h1>Hi!</h1><div>the footer</div>'
|
432
|
-
end
|
433
|
-
|
434
|
-
|
435
|
-
# --- Polymorphic Tags --- #
|
436
|
-
|
437
|
-
it "should allow tags to be selected based on types" do
|
438
|
-
tags = %(<def tag="do"><tagbody/></def>
|
439
|
-
<def tag="t" for="String">A string</def>
|
440
|
-
<def tag="t" for="TrueClass">A boolean</def>)
|
441
|
-
|
442
|
-
eval_dryml(tags + '<do with="&\'foo\'"><%= call_polymorphic_tag(:t) %></do>').should == "A string"
|
443
|
-
eval_dryml(tags + '<do with="&false"><%= call_polymorphic_tag(:t) %></do>').should == "A boolean"
|
444
|
-
end
|
445
|
-
|
446
|
-
# --- The Context --- #
|
447
|
-
|
448
|
-
def context_eval(context, src)
|
449
|
-
eval_dryml(src, :context => context)
|
450
|
-
end
|
451
|
-
|
452
|
-
def a_user
|
453
|
-
Struct.new(:name, :email).new("Tom", "tom@foo.net")
|
454
|
-
end
|
455
|
-
|
456
|
-
def show_tag
|
457
|
-
'<def tag="show"><%= this %></def>'
|
458
|
-
end
|
459
|
-
|
460
|
-
it "should make the initial context available as `this`" do
|
461
|
-
context_eval('hello', "<%= this %>").should == "hello"
|
462
|
-
end
|
463
|
-
|
464
|
-
it "should allow the context to be changed with the :<field-name> syntax" do
|
465
|
-
context_eval(a_user, show_tag + '<show:name/>').should == "Tom"
|
466
|
-
end
|
467
|
-
|
468
|
-
it "should allow the :<field-name> to be ommitted from the close tag" do
|
469
|
-
context_eval(a_user, show_tag + '<show:name></show:name>').should == "Tom"
|
470
|
-
context_eval(a_user, show_tag + '<show:name></show>').should == "Tom"
|
471
|
-
end
|
472
|
-
|
473
|
-
|
474
|
-
it "should allow the context to be changed with a 'with' attribute" do
|
475
|
-
eval_dryml(show_tag + %(<show with="&'hello'"/>)).should == 'hello'
|
476
|
-
end
|
477
|
-
|
478
|
-
it "should allow the context to be changed with a 'field' attribute" do
|
479
|
-
context_eval(a_user, show_tag + '<show field="name"/>').should == "Tom"
|
480
|
-
end
|
481
|
-
|
482
|
-
it "should allow the context to be changed inside template parameters" do
|
483
|
-
tags = %(<def tag="do"><tagbody/></def>
|
484
|
-
<def tag="Template"><do:name><p param/></do></def>)
|
485
|
-
context_eval(a_user, tags + '<Template><p><%= this %></p></Template>').should == '<p>Tom</p>'
|
486
|
-
end
|
487
|
-
|
488
|
-
|
489
|
-
# --- <set> --- #
|
490
|
-
|
491
|
-
it "should provide <set> to create local variables" do
|
492
|
-
eval_dryml("<set x='&1' y='&2'/><%= x + y %>").should == '3'
|
493
|
-
end
|
494
|
-
|
495
|
-
it 'should interpolate #{...} blocks in attributes of any tag' do
|
496
|
-
tag = '<def tag="t" attrs="x"><%= x %></def>'
|
497
|
-
|
498
|
-
eval_dryml(tag + "<t x='#{1+2}'/>").should == '3'
|
499
|
-
eval_dryml(tag + "<t x='hey #{1+2} ho'/>").should == 'hey 3 ho'
|
500
|
-
|
501
|
-
eval_dryml(tag + "<p class='#{1+2}'/>").should == "<p class='3'/>"
|
502
|
-
eval_dryml(tag + "<p class='hey #{1+2} ho'/>").should == "<p class='hey 3 ho'/>"
|
503
|
-
end
|
504
|
-
|
505
|
-
|
506
|
-
# --- <set_scoped> --- #
|
507
|
-
|
508
|
-
it "should support scoped variables" do
|
509
|
-
tags =
|
510
|
-
"<def tag='t1'><set_scoped x='ping'><tagbody/></set_scoped></def>" +
|
511
|
-
"<def tag='t2'><set_scoped x='pong'><tagbody/></set_scoped></def>"
|
512
|
-
eval_dryml(tags + "<t1><%= scope.x %></t1>").should == 'ping'
|
513
|
-
eval_dryml(tags + "<t1><t2><%= scope.x %></t2> <%= scope.x %></t1>").should == 'pong ping'
|
514
|
-
end
|
515
|
-
|
516
|
-
|
517
|
-
# --- Taglibs --- #
|
518
|
-
|
519
|
-
it "should import tags from taglibs with the <include> tag" do
|
520
|
-
eval_dryml("<include src='taglibs/simple'/> <foo/>").should == "I am the foo tag"
|
521
|
-
end
|
522
|
-
|
523
|
-
it "should import tags from taglibs into a namespace with <include as/>" do
|
524
|
-
proc { eval_dryml("<include src='taglibs/simple' as='a'/> <foo/>") }.should raise_error
|
525
|
-
eval_dryml("<include src='taglibs/simple' as='a'/> <a.foo/>").should == "I am the foo tag"
|
526
|
-
end
|
527
|
-
|
528
|
-
|
529
|
-
# --- Control Attributes --- #
|
530
|
-
|
531
|
-
it "should alow static tags to be conditional with the 'if' attribute" do
|
532
|
-
eval_dryml("<p if='&false'/>").should == ""
|
533
|
-
eval_dryml("<p if='&true'/>").should == "<p />"
|
534
|
-
|
535
|
-
eval_dryml("<p if='&false'>hello</p>").should == ""
|
536
|
-
eval_dryml("<p if='&true'>hello</p>").should == "<p>hello</p>"
|
537
|
-
end
|
538
|
-
|
539
|
-
it "should alow static tags to be repeated with the 'repeat' attribute" do
|
540
|
-
eval_dryml('<img repeat="&[1,2,3]" src="#{this}" />').should ==
|
541
|
-
'<img src="1" /><img src="2" /><img src="3" />'
|
542
|
-
|
543
|
-
# Make sure <%= %> doesn't break
|
544
|
-
eval_dryml('<img repeat="&[1,2,3]" src="<%= this %>" />').should ==
|
545
|
-
'<img src="1" /><img src="2" /><img src="3" />'
|
546
|
-
end
|
547
|
-
|
548
|
-
it "should alow templates to be repeated with the 'repeat' attribute" do
|
549
|
-
eval_dryml('<def tag="T"><%= this %></def><T repeat="&[1,2,3]"/>').should == '123'
|
550
|
-
end
|
551
|
-
|
552
|
-
it "should allow <else> to be used with the if attribute" do
|
553
|
-
eval_dryml("<p if='&false'/><%= Hobo::Dryml.last_if %>").should == "false"
|
554
|
-
end
|
555
|
-
|
556
|
-
|
557
|
-
# --- Test Helpers --- #
|
558
|
-
|
559
|
-
def prepare_template(src, options)
|
560
|
-
options.reverse_merge!(:template_path => "TEST")
|
561
|
-
|
562
|
-
Hobo::Dryml::Template.clear_build_cache
|
563
|
-
@env = Class.new(Hobo::Dryml::TemplateEnvironment)
|
564
|
-
template = Template.new(src, @env, options[:template_path])
|
565
|
-
|
566
|
-
template.instance_variable_set("@builder", options[:builder]) if options[:builder]
|
567
|
-
template
|
568
|
-
end
|
569
|
-
|
570
|
-
|
571
|
-
def eval_dryml(src, options={})
|
572
|
-
options.reverse_merge!(:locals => {}, :implicit_imports => [])
|
573
|
-
|
574
|
-
template = prepare_template(src, options)
|
575
|
-
template.compile(options[:locals].keys, options[:implicit_imports])
|
576
|
-
new_renderer.render_page(options[:context], options[:locals]).strip
|
577
|
-
end
|
578
|
-
|
579
|
-
def compile_dryml(src, options={})
|
580
|
-
template = prepare_template(src, options)
|
581
|
-
CompiledDryml.new(template.process_src)
|
582
|
-
end
|
583
|
-
|
584
|
-
def new_renderer
|
585
|
-
@env.new("test-view", nil)
|
586
|
-
end
|
587
|
-
|
588
|
-
def compile_in_template(src)
|
589
|
-
builder = mock("builder", :null_object => true)
|
590
|
-
def_src = nil
|
591
|
-
builder.should_receive(:add_build_instruction) do |type, args|
|
592
|
-
def_src = args[:src]
|
593
|
-
end
|
594
|
-
compile_dryml("<def tag='MyTemplate'>#{src}</def>", :builder => builder)
|
595
|
-
|
596
|
-
# get rid of first and last scriptlets - they're to do with the method declaration
|
597
|
-
def_src.to_s.sub(/^\<\%.*?\%\>/, "").sub(/<% _erbout; end; end %><% _register_tag_attrs.*$/, "")
|
598
|
-
end
|
599
|
-
|
600
|
-
def compile_def(src)
|
601
|
-
builder = mock("builder", :null_object => true)
|
602
|
-
def_src = nil
|
603
|
-
builder.should_receive(:add_build_instruction) do |type, args|
|
604
|
-
def_src = args[:src]
|
605
|
-
end
|
606
|
-
compile_dryml(src, :builder => builder)
|
607
|
-
|
608
|
-
def_src.sub(/<% _register_tag_attrs.*/, "")
|
609
|
-
end
|
610
|
-
|
611
|
-
end
|
612
|
-
|
613
|
-
class CompiledDryml < String
|
614
|
-
|
615
|
-
def ==(other)
|
616
|
-
self.to_s.gsub(/\s+/, ' ').strip == other.gsub(/\s+/, ' ').strip
|
617
|
-
end
|
618
|
-
|
619
|
-
end
|
620
|
-
|
621
|
-
|
622
|
-
module Spec
|
623
|
-
module Matchers
|
624
|
-
|
625
|
-
class BeDomEqualTo #:nodoc:
|
626
|
-
def initialize(expected)
|
627
|
-
@expected = expected
|
628
|
-
end
|
629
|
-
|
630
|
-
def matches?(actual)
|
631
|
-
@actual = actual
|
632
|
-
expected_dom = HTML::Document.new(@expected).root
|
633
|
-
actual_dom = HTML::Document.new(@actual).root
|
634
|
-
expected_dom == actual_dom
|
635
|
-
end
|
636
|
-
|
637
|
-
def failure_message
|
638
|
-
"#{@expected}\nexpected to be == (by DOM) to\n#{@actual}"
|
639
|
-
end
|
640
|
-
|
641
|
-
def description
|
642
|
-
"be DOM equal to\n#{@expected}"
|
643
|
-
end
|
644
|
-
end
|
645
|
-
|
646
|
-
def be_dom_equal_to(expected)
|
647
|
-
Matchers::BeDomEqualTo.new(expected)
|
648
|
-
end
|
649
|
-
end
|
650
|
-
end
|