Renamed helpers to correspond to renamed Controller classes.
[merb_radiant.git] / radiant_specs / spec / models / .svn / text-base / standard_tags_spec.rb.svn-base
blobad9c0babf5b89533d50d850ce2f29d80026410e2
1 require File.dirname(__FILE__) + '/../spec_helper'
3 describe "Standard Tags" do
4   scenario :users_and_pages, :file_not_found, :snippets
5   
6   specify '<r:page> should allow access to the current page' do
7     page(:home)
8     page.should render('<r:page:title />').as('Home')
9     page.should render(%{<r:find url="/radius"><r:title /> | <r:page:title /></r:find>}).as('Radius | Home')
10   end
11   
12   specify '<r:breadcrumb>, <r:slug>, <r:title>, and <r:url>' do
13     page(:home)
14     [:breadcrumb, :slug, :title, :url].each do |attr|
15       value = page.send(attr)
16       page.should render("<r:#{attr} />").as(value.to_s)
17     end
18   end
19   
20   specify '<r:parent>' do
21     page(:parent)
22     page.should render('<r:parent><r:title /></r:parent>').as(pages(:home).title)
23     page.should render('<r:parent><r:children:each by="title"><r:title /></r:children:each></r:parent>').as(page_eachable_children(pages(:home)).collect(&:title).join(""))
24     page.should render('<r:children:each><r:parent:title /></r:children:each>').as(@page.title * page.children.count)
25   end
26   
27   specify '<r:if_parent>' do
28     page.should render('<r:if_parent>true</r:if_parent>').as('true')
29     page(:home).should render('<r:if_parent>true</r:if_parent>').as('')
30   end
31   
32   specify '<r:unless_parent>' do
33     page.should render('<r:unless_parent>true</r:unless_parent>').as('')
34     page(:home).should render('<r:unless_parent>true</r:unless_parent>').as('true')
35   end
36   
37   specify '<r:if_children>' do
38     page(:home).should render('<r:if_children>true</r:if_children>').as('true')
39     page(:childless).should render('<r:if_children>true</r:if_children>').as('')
40   end
41   
42   specify '<r:unless_children>' do
43     page(:home).should render('<r:unless_children>true</r:unless_children>').as('')
44     page(:childless).should render('<r:unless_children>true</r:unless_children>').as('true')
45   end
46   
47   specify '<r:children:each>' do
48     page(:parent)
49     page.should render('<r:children:each><r:title /> </r:children:each>').as('Child Child 2 Child 3 ')
50     page.should render('<r:children:each><r:page><r:slug />/<r:child:slug /> </r:page></r:children:each>').as('parent/child parent/child-2 parent/child-3 ')    
51   end
52   specify '<r:children:each> order attributes' do
53     page.should render(page_children_each_tags).as('a b c d e f g h i j ')
54     page.should render(page_children_each_tags(%{limit="5"})).as('a b c d e ')
55     page.should render(page_children_each_tags(%{offset="3" limit="5"})).as('d e f g h ')
56     page.should render(page_children_each_tags(%{order="desc"})).as('j i h g f e d c b a ')
57     page.should render(page_children_each_tags(%{by="breadcrumb"})).as('f e d c b a j i h g ')
58     page.should render(page_children_each_tags(%{by="breadcrumb" order="desc"})).as('g h i j a b c d e f ')
59   end
60   specify '<r:children:each> with "status" attribute' do
61     page.should render(page_children_each_tags(%{status="all"})).as("a b c d e f g h i j draft ")
62     page.should render(page_children_each_tags(%{status="draft"})).as('draft ')
63     page.should render(page_children_each_tags(%{status="published"})).as('a b c d e f g h i j ')
64     page.should render(page_children_each_tags(%{status="askdf"})).with_error("`status' attribute of `each' tag must be set to a valid status")
65   end
66   specify '<r:children:each> should not list virtual pages' do
67     page.should render('<r:children:each><r:slug /> </r:children:each>').as('a b c d e f g h i j ') 
68     page.should render('<r:children:each status="all"><r:slug /> </r:children:each>').as('a b c d e f g h i j draft ')
69   end
70   specify '<r:children:each> should error with invalid "limit" attribute' do
71     message = "`limit' attribute of `each' tag must be a positive number between 1 and 4 digits"
72     page.should render(page_children_each_tags(%{limit="a"})).with_error(message)
73     page.should render(page_children_each_tags(%{limit="-10"})).with_error(message)
74     page.should render(page_children_each_tags(%{limit="50000"})).with_error(message)
75   end
76   specify '<r:children:each> should error with invalid "offset" attribute' do
77     message = "`offset' attribute of `each' tag must be a positive number between 1 and 4 digits"
78     page.should render(%{offset="a"}).with_error(message)
79     page.should render(%{offset="-10"}).with_error(message)
80     page.should render(%{offset="50000"}).with_error(message)
81   end
82   specify '<r:children:each> should error with invalid "by" attribute' do
83     message = "`by' attribute of `each' tag must be set to a valid field name"
84     page.should render(page_children_each_tags(%{by="non-existant-field"})).with_error(message)
85   end
86   specify '<r:children:each> should error with invalid "order" attribute' do
87     message = %{`order' attribute of `each' tag must be set to either "asc" or "desc"}
88     page.should render(page_children_each_tags(%{order="asdf"})).with_error(message)
89   end
90   
91   specify '<r:children:each:header>' do
92     tags = '<r:children:each><r:header>[<r:date format="%b/%y" />] </r:header><r:slug /> </r:children:each>'
93     expected = "[Dec/00] article [Feb/01] article-2 article-3 [Mar/01] article-4 "
94     page(:news).should render(tags).as(expected)
95   end
96   specify '<r:children:each:header> with "name" attribute' do
97     tags = %{<r:children:each><r:header name="year">[<r:date format='%Y' />] </r:header><r:header name="month">(<r:date format="%b" />) </r:header><r:slug /> </r:children:each>}
98     expected = "[2000] (Dec) article [2001] (Feb) article-2 article-3 (Mar) article-4 "
99     page(:news).should render(tags).as(expected)
100   end
101   specify '<r:children:each:header> with "restart" attribute set to one name' do
102     tags = %{<r:children:each><r:header name="year" restart="month">[<r:date format='%Y' />] </r:header><r:header name="month">(<r:date format="%b" />) </r:header><r:slug /> </r:children:each>}
103     expected = "[2000] (Dec) article [2001] (Feb) article-2 article-3 (Mar) article-4 "
104     page(:news).should render(tags).as(expected)
105   end
106   specify '<r:children:each:header> with "restart" attribute set to two names' do
107     tags = %{<r:children:each><r:header name="year" restart="month;day">[<r:date format='%Y' />] </r:header><r:header name="month" restart="day">(<r:date format="%b" />) </r:header><r:header name="day"><<r:date format='%d' />> </r:header><r:slug /> </r:children:each>}
108     expected = "[2000] (Dec) <01> article [2001] (Feb) <09> article-2 <24> article-3 (Mar) <06> article-4 "
109     page(:news).should render(tags).as(expected)
110   end
111   
112   specify '<r:children:count>' do
113     page(:parent).should render('<r:children:count />').as('3')
114   end
115   
116   specify '<r:children:first>' do
117     page(:parent).should render('<r:children:first:title />').as('Child') 
118   end  
119   specify '<r:children:first> with attributes' do
120     page.should render(page_children_first_tags).as('a') 
121     page.should render(page_children_first_tags(%{limit="5"})).as('a')
122     page.should render(page_children_first_tags(%{offset="3" limit="5"})).as('d')
123     page.should render(page_children_first_tags(%{order="desc"})).as('j')
124     page.should render(page_children_first_tags(%{by="breadcrumb"})).as('f')
125     page.should render(page_children_first_tags(%{by="breadcrumb" order="desc"})).as('g')
126   end
127   specify '<r:children:first> when no children exist' do
128     page(:first).should render('<r:children:first:title />').as('')
129   end
130   
131   specify '<r:children:last>' do
132     page(:parent).should render('<r:children:last:title />').as('Child 3')
133   end
134   specify '<r:children:last> with attributes' do
135     page.should render(page_children_last_tags).as('j')
136     page.should render(page_children_last_tags(%{limit="5"})).as('e')
137     page.should render(page_children_last_tags(%{offset="3" limit="5"})).as('h')
138     page.should render(page_children_last_tags(%{order="desc"})).as('a')
139     page.should render(page_children_last_tags(%{by="breadcrumb"})).as('g')
140     page.should render(page_children_last_tags(%{by="breadcrumb" order="desc"})).as('f')
141   end
142   specify '<r:children:last> when no children exist' do
143     page(:first).should render('<r:children:last:title />').as('')
144   end
145   
146   specify '<r:content>' do
147     page.should render('<r:content />').as('Assorted body.')
148   end
149   specify '<r:content> with "part" attribute' do
150     page(:home).should render('<r:content part="extended" />').as("Just a test.")
151   end
152   specify '<r:content> with inherit attribute' do
153     page.should render('<r:content part="sidebar" />').as('')
154     page.should render('<r:content part="sidebar" inherit="false" />').as('')
155     page.should render('<r:content part="sidebar" inherit="true" />').as('Assorted sidebar.')
156     page.should render('<r:content part="sidebar" inherit="weird value" />').with_error(%{`inherit' attribute of `content' tag must be set to either "true" or "false"})
157     page.should render('<r:content part="part_that_doesnt_exist" inherit="true" />').as('')
158   end
159   specify '<r:content> with inherit and contextual attributes' do
160     page(:parent)
161     page.should render('<r:content part="sidebar" inherit="true" contextual="true" />').as('Parent sidebar.')
162     page.should render('<r:content part="sidebar" inherit="true" contextual="false" />').as('Home sidebar.')
163     page(:child).should render('<r:content part="sidebar" inherit="true" contextual="true" />').as('Child sidebar.')
164     page(:grandchild).should render('<r:content part="sidebar" inherit="true" contextual="true" />').as('Grandchild sidebar.')
165   end
166   specify '<r:content> with global page propagation' do
167     page(:first)
168     page.should render('<r:content part="titles" inherit="true" contextual="true"/>').as('First First')
169     page.should render('<r:content part="titles" inherit="true" contextual="false"/>').as('Home First')
170   end
171   specify '<r:content /> for children' do
172     expected = "Child body. Child 2 body. Child 3 body. "
173     page(:parent).should render('<r:children:each><r:content /> </r:children:each>').as(expected)
174   end
175   
176   specify '<r:if_content> without "part" attribute' do
177     page.should render('<r:if_content>true</r:if_content>').as('true')
178   end
179   specify '<r:if_content> with "part" attribute' do
180     page.should render('<r:if_content part="body">true</r:if_content>').as('true')
181   end
182   specify '<r:if_content> with nonexistant "part" attribute' do
183     page.should render('<r:if_content part="asdf">true</r:if_content>').as('')
184   end
185   
186   specify '<r:unless_content> without "part" attribute' do
187     page.should render('<r:unless_content>false</r:unless_content>').as('')
188   end
189   specify '<r:unless_content> with "part" attribute' do
190     page.should render('<r:unless_content part="body">false</r:unless_content>').as('')
191   end
192   specify '<r:unless_content> with nonexistant "part" attribute' do
193     page.should render('<r:unless_content part="asdf">false</r:unless_content>').as('false')
194   end
195   
196   specify '<r:author>' do
197     page.should render('<r:author />').as('Admin')
198   end
199   specify '<r:author> nil' do
200     page(:no_user).should render('<r:author />').as('')
201   end
202   
203   specify '<r:date>' do
204     page(:dated)
205     page.should render('<r:date />').as('Wednesday, January 11, 2006')
206   end
207   specify '<r:date> with "format" attribute' do
208     page(:dated)
209     page.should render('<r:date format="%d %b %Y" />').as('11 Jan 2006')
210   end
211   specify '<r:date> with "for" attribute' do
212     page(:dated)
213     page.should render('<r:date for="now" />').as(Time.now.strftime("%A, %B %d, %Y"))
214     page.should render('<r:date for="created_at" />').as('Tuesday, January 10, 2006')
215     page.should render('<r:date for="updated_at" />').as('Thursday, January 12, 2006')
216     page.should render('<r:date for="published_at" />').as('Wednesday, January 11, 2006')
217     page.should render('<r:date for="blah" />').with_error("Invalid value for 'for' attribute.")
218   end
219   specify '<r:date> should use local timezone' do
220     page(:dated)
221     Radiant::Config["local.timezone"] = "Tokyo"
222     format = "%H:%m"
223     expected = TimeZone["Tokyo"].adjust(page.published_at).strftime(format)
224     page.should render(%Q(<r:date format="#{format}" />) ).as(expected)
225   end
226   
227   specify '<r:link>' do
228     page.should render('<r:link />').as('<a href="/assorted/">Assorted</a>')
229   end
230   specify '<r:link> in block form' do
231     page.should render('<r:link>Test</r:link>').as('<a href="/assorted/">Test</a>')
232   end
233   specify '<r:link> with HTML attributes' do
234     expected = '<a href="/assorted/" class="test" id="assorted">Assorted</a>'
235     page.should render('<r:link class="test" id="assorted" />').as(expected)
236   end
237   specify '<r:link> with "anchor" attribute' do
238     page.should render('<r:link anchor="test">Test</r:link>').as('<a href="/assorted/#test">Test</a>')
239   end
240   specify '<r:link> should work for children' do
241     expected = %{<a href="/parent/child/">Child</a> <a href="/parent/child-2/">Child 2</a> <a href="/parent/child-3/">Child 3</a> }
242     page(:parent).should render('<r:children:each><r:link /> </r:children:each>' ).as(expected)
243   end
244   
245   specify '<r:snippet>' do
246     page.should render('<r:snippet name="first" />').as('test')
247   end
248   specify '<r:snippet> not found' do
249     page.should render('<r:snippet name="non-existant" />').with_error('snippet not found')
250   end
251   specify '<r:snippet> without name' do
252     page.should render('<r:snippet />').with_error("`snippet' tag must contain `name' attribute")
253   end
254   specify '<r:snippet> with markdown' do
255     page.should render('<r:page><r:snippet name="markdown" /></r:page>').as('<p><strong>markdown</strong></p>')
256   end
257   specify '<r:snippet> with global page propagation' do
258     page(:parent).should render('<r:snippet name="global_page_cascade" />').as("#{@page.title} " * @page.children.count)
259   end
260   specify '<r:snippet> with recursion global page propagation' do
261     page(:child).should render('<r:snippet name="recursive" />').as("Great GrandchildGrandchildChild")
262   end
263   
264   specify '<r:random>' do
265     page.should render("<r:random> <r:option>1</r:option> <r:option>2</r:option> <r:option>3</r:option> </r:random>").matching(/^(1|2|3)$/) 
266   end
267   
268   specify '<r:comment>' do
269     page.should render('just a <r:comment>small </r:comment>test').as('just a test')
270   end
271   
272   specify '<r:navigation> simple case' do
273     tags = %{<r:navigation urls="Home: / | Assorted: /assorted/ | Parent: /parent/">
274                <r:normal><r:title /></r:normal>
275              </r:navigation>}
276     expected = %{Home Assorted Parent}
277     page.should render(tags).as(expected)
278   end
279   specify '<r:navigation> more complex' do
280     tags = %{<r:navigation urls="Home: / | Assorted: /assorted/ | Parent: /parent/ | Radius: /radius/">
281                <r:normal><r:title /></r:normal>
282                <r:selected><strong><r:title/></strong></r:selected>
283              </r:navigation>}
284     expected = %{<strong>Home</strong> Assorted <strong>Parent</strong> Radius}
285     page(:parent).should render(tags).as(expected)
286   end
287   specify '<r:navigation> very complex' do
288     tags = %{<r:navigation urls="Home: Boy: / | Assorted: /assorted/ | Parent: /parent/">
289                <r:normal><a href="<r:url />"><r:title /></a></r:normal>
290                <r:here><strong><r:title /></strong></r:here>
291                <r:selected><strong><a href="<r:url />"><r:title /></a></strong></r:selected>
292                <r:between> | </r:between>
293              </r:navigation>}
294     expected = %{<strong><a href="/">Home: Boy</a></strong> | <strong>Assorted</strong> | <a href="/parent/">Parent</a>}
295     page.should render(tags).as(expected)
296   end
297   specify '<r:navigation> without urls' do
298     page.should render(%{<r:navigation><r:normal /></r:navigation>}).as('')
299   end
300   specify '<r:navigation> without normal tag' do
301     page.should render(%{<r:navigation urls="something:here"></r:navigation>}).with_error( "`navigation' tag must include a `normal' tag")
302   end
303   specify '<r:navigation> with urls without slashes' do
304     tags = %{<r:navigation urls="Home: / | Assorted: /assorted/ | Parent: /parent/ | Radius: /radius/">
305                <r:normal><r:title /></r:normal>
306                <r:here><strong><r:title /></strong></r:here>
307              </r:navigation>}
308     expected = %{Home <strong>Assorted</strong> Parent Radius}
309     page.should render(tags).as(expected)
310   end
311   
312   specify '<r:find>' do
313     page.should render(%{<r:find url="/parent/child/"><r:title /></r:find>}).as('Child')
314   end
315   specify '<r:find> without url' do
316     page.should render(%{<r:find />}).with_error("`find' tag must contain `url' attribute")
317   end
318   specify '<r:find> with nonexistant url' do
319     page.should render(%{<r:find url="/asdfsdf/"><r:title /></r:find>}).as('')
320   end
321   specify '<r:find> with nonexistant url and file not found' do
322     page.should render(%{<r:find url="/gallery/asdfsdf/"><r:title /></r:find>}).as('')
323   end
324   specify '<r:find> with children' do
325     page.should render(%{<r:find url="/parent/"><r:children:each><r:slug /> </r:children:each></r:find>}).as('child child-2 child-3 ')
326   end
327   
328   specify '<r:escape_html>' do
329     page.should render('<r:escape_html><strong>a bold move</strong></r:escape_html>').as('&lt;strong&gt;a bold move&lt;/strong&gt;')
330   end
331   
332   specify '<r:rfc1123_date>' do
333     page(:dated).should render('<r:rfc1123_date />').as('Wed, 11 Jan 2006 00:00:00 GMT')
334   end
335   
336   specify '<r:breadcrumbs>' do
337     expected = %{<a href="/">Home</a> &gt; <a href="/parent/">Parent</a> &gt; <a href="/parent/child/">Child</a> &gt; <a href="/parent/child/grandchild/">Grandchild</a> &gt; Great Grandchild}
338     page(:great_grandchild).should render('<r:breadcrumbs />').as(expected)
339   end
340   specify '<r:breadcrumbs> with separator attribute' do
341     expected = %{<a href="/">Home</a> :: Parent}
342     page(:parent).should render('<r:breadcrumbs separator=" :: " />').as(expected)
343   end
344   
345   specify '<r:if_url> with "matches" attribute' do
346     page.should render('<r:if_url matches="a.sorted/$">true</r:if_url>').as('true')
347   end
348   specify '<r:if_url> with "matches" attribute that does not match' do
349     page.should render('<r:if_url matches="fancypants">true</r:if_url>').as('')
350   end
351   specify '<r:if_url> with "matches" attribute set to a malformatted regexp' do
352     page.should render('<r:if_url matches="as(sorted/$">true</r:if_url>').with_error("Malformed regular expression in `matches' argument of `if_url' tag: unmatched (: /as(sorted\\/$/")
353   end
354   specify '<r:if_url> without "ignore_case" attribute' do
355     page.should render('<r:if_url matches="asSorted/$">true</r:if_url>').as('true')
356   end
357   specify '<r:if_url> with "ignore_case" attribute set to "true"' do
358     page.should render('<r:if_url matches="asSorted/$" ignore_case="true">true</r:if_url>').as('true')
359   end
360   specify '<r:if_url> with "ignore_case" attribute set to "false"' do
361     page.should render('<r:if_url matches="asSorted/$" ignore_case="false">true</r:if_url>').as('')
362   end
363   specify '<r:if_url> with no attributes' do
364     page.should render('<r:if_url>test</r:if_url>').with_error("`if_url' tag must contain a `matches' attribute.")
365   end
366   
367   specify '<r:unless_url> with "matches" attribute' do
368     page.should render('<r:unless_url matches="a.sorted/$">true</r:unless_url>').as('')
369   end
370   specify '<r:unless_url> with "matches" attribute that does not match' do
371     page.should render('<r:unless_url matches="fancypants">true</r:unless_url>').as('true')
372   end
373   specify '<r:unless_url> with "matches" attribute set to a malformatted regexp' do
374     page.should render('<r:unless_url matches="as(sorted/$">true</r:unless_url>').with_error("Malformed regular expression in `matches' argument of `unless_url' tag: unmatched (: /as(sorted\\/$/")
375   end
376   specify '<r:unless_url> without "ignore_case" attribute' do
377     page.should render('<r:unless_url matches="asSorted/$">true</r:unless_url>').as('')
378   end
379   specify '<r:unless_url> with "ignore_case" attribute set to "true"' do
380     page.should render('<r:unless_url matches="asSorted/$" ignore_case="true">true</r:unless_url>').as('')
381   end
382   specify '<r:unless_url> with "ignore_case" attribute set to "false"' do
383     page.should render('<r:unless_url matches="asSorted/$" ignore_case="false">true</r:unless_url>').as('true')
384   end
385   specify '<r:unless_url> with no attributes' do
386     page.should render('<r:unless_url>test</r:unless_url>').with_error("`unless_url' tag must contain a `matches' attribute.")
387   end
388   
389   specify '<r:cycle>' do
390     page.should render('<r:cycle values="first, second" /> <r:cycle values="first, second" />').as('first second')
391   end
392   specify '<r:cycle> returns to beginning' do
393     page.should render('<r:cycle values="first, second" /> <r:cycle values="first, second" /> <r:cycle values="first, second" />').as('first second first')
394   end
395   specify '<r:cycle> default name' do
396     page.should render('<r:cycle values="first, second" /> <r:cycle values="first, second" name="cycle" />').as('first second')
397   end
398   specify '<r:cycle> keeps separate counters' do
399     page.should render('<r:cycle values="first, second" /> <r:cycle values="one, two" name="numbers" /> <r:cycle values="first, second" /> <r:cycle values="one, two" name="numbers" />').as('first one second two')
400   end
401   specify '<r:cycle> resets counter' do
402     page.should render('<r:cycle values="first, second" /> <r:cycle values="first, second" reset="true"/>').as('first first')
403   end
404   specify '<r:cycle> names empty' do
405     page.should render('<r:cycle />').with_error("`cycle' tag must contain a `values' attribute.")
406   end
407   
408   specify '<r:if_dev>' do
409     page.should render('-<r:if_dev>dev</r:if_dev>-').as('-dev-').on('dev.site.com')
410     page.should render('-<r:if_dev>dev</r:if_dev>-').as('--')
411   end
412   specify '<r:if_dev> on included page' do
413     page.should render('-<r:find url="/devtags/"><r:content part="if_dev" /></r:find>-').as('-dev-').on('dev.site.com')
414     page.should render('-<r:find url="/devtags/"><r:content part="if_dev" /></r:find>-').as('--')
415   end
416   
417   specify '<r:unless_dev>' do
418     page.should render('-<r:unless_dev>not dev</r:unless_dev>-').as('--').on('dev.site.com')
419     page.should render('-<r:unless_dev>not dev</r:unless_dev>-').as('-not dev-')
420   end
421   specify '<r:unless_dev> on included page' do
422     page.should render('-<r:find url="/devtags/"><r:content part="unless_dev" /></r:find>-').as('--').on('dev.site.com')
423     page.should render('-<r:find url="/devtags/"><r:content part="unless_dev" /></r:find>-').as('-not dev-')
424   end
425   
426   private
427     
428     def page(symbol = nil)
429       if symbol.nil?
430         @page ||= pages(:assorted)
431       else
432         @page = pages(symbol)
433       end
434     end
435     
436     def page_children_each_tags(attr = nil)
437       attr = ' ' + attr unless attr.nil?
438       "<r:children:each#{attr}><r:slug /> </r:children:each>"
439     end
440     
441     def page_children_first_tags(attr = nil)
442       attr = ' ' + attr unless attr.nil?
443       "<r:children:first#{attr}><r:slug /></r:children:first>"
444     end
445     
446     def page_children_last_tags(attr = nil)
447       attr = ' ' + attr unless attr.nil?
448       "<r:children:last#{attr}><r:slug /></r:children:last>"
449     end
450     
451     def page_eachable_children(page)
452       page.children.select(&:published?).reject(&:virtual)
453     end