hobo 0.6.1 → 0.6.2
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.
- 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
|