| 51 | | specify '<r:children:each>' do |
|---|
| 52 | | page(:parent) |
|---|
| 53 | | page.should render('<r:children:each><r:title /> </r:children:each>').as('Child Child 2 Child 3 ') |
|---|
| 54 | | 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 ') |
|---|
| 55 | | end |
|---|
| 56 | | specify '<r:children:each> order attributes' do |
|---|
| 57 | | page.should render(page_children_each_tags).as('a b c d e f g h i j ') |
|---|
| 58 | | page.should render(page_children_each_tags(%{limit="5"})).as('a b c d e ') |
|---|
| 59 | | page.should render(page_children_each_tags(%{offset="3" limit="5"})).as('d e f g h ') |
|---|
| 60 | | page.should render(page_children_each_tags(%{order="desc"})).as('j i h g f e d c b a ') |
|---|
| 61 | | page.should render(page_children_each_tags(%{by="breadcrumb"})).as('f e d c b a j i h g ') |
|---|
| 62 | | page.should render(page_children_each_tags(%{by="breadcrumb" order="desc"})).as('g h i j a b c d e f ') |
|---|
| 63 | | end |
|---|
| 64 | | specify '<r:children:each> with "status" attribute' do |
|---|
| 65 | | page.should render(page_children_each_tags(%{status="all"})).as("a b c d e f g h i j draft ") |
|---|
| 66 | | page.should render(page_children_each_tags(%{status="draft"})).as('draft ') |
|---|
| 67 | | page.should render(page_children_each_tags(%{status="published"})).as('a b c d e f g h i j ') |
|---|
| 68 | | page.should render(page_children_each_tags(%{status="askdf"})).with_error("`status' attribute of `each' tag must be set to a valid status") |
|---|
| 69 | | end |
|---|
| 70 | | specify '<r:children:each> should not list virtual pages' do |
|---|
| 71 | | page.should render('<r:children:each><r:slug /> </r:children:each>').as('a b c d e f g h i j ') |
|---|
| 72 | | 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 ') |
|---|
| 73 | | end |
|---|
| 74 | | specify '<r:children:each> should error with invalid "limit" attribute' do |
|---|
| 75 | | message = "`limit' attribute of `each' tag must be a positive number between 1 and 4 digits" |
|---|
| 76 | | page.should render(page_children_each_tags(%{limit="a"})).with_error(message) |
|---|
| 77 | | page.should render(page_children_each_tags(%{limit="-10"})).with_error(message) |
|---|
| 78 | | page.should render(page_children_each_tags(%{limit="50000"})).with_error(message) |
|---|
| 79 | | end |
|---|
| 80 | | specify '<r:children:each> should error with invalid "offset" attribute' do |
|---|
| 81 | | message = "`offset' attribute of `each' tag must be a positive number between 1 and 4 digits" |
|---|
| 82 | | page.should render(%{offset="a"}).with_error(message) |
|---|
| 83 | | page.should render(%{offset="-10"}).with_error(message) |
|---|
| 84 | | page.should render(%{offset="50000"}).with_error(message) |
|---|
| 85 | | end |
|---|
| 86 | | specify '<r:children:each> should error with invalid "by" attribute' do |
|---|
| 87 | | message = "`by' attribute of `each' tag must be set to a valid field name" |
|---|
| 88 | | page.should render(page_children_each_tags(%{by="non-existant-field"})).with_error(message) |
|---|
| 89 | | end |
|---|
| 90 | | specify '<r:children:each> should error with invalid "order" attribute' do |
|---|
| 91 | | message = %{`order' attribute of `each' tag must be set to either "asc" or "desc"} |
|---|
| 92 | | page.should render(page_children_each_tags(%{order="asdf"})).with_error(message) |
|---|
| 93 | | end |
|---|
| 94 | | |
|---|
| 95 | | specify '<r:children:each:header>' do |
|---|
| 96 | | tags = '<r:children:each><r:header>[<r:date format="%b/%y" />] </r:header><r:slug /> </r:children:each>' |
|---|
| 97 | | expected = "[Dec/00] article [Feb/01] article-2 article-3 [Mar/01] article-4 " |
|---|
| 98 | | page(:news).should render(tags).as(expected) |
|---|
| 99 | | end |
|---|
| 100 | | specify '<r:children:each:header> with "name" attribute' do |
|---|
| 101 | | 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>} |
|---|
| 102 | | expected = "[2000] (Dec) article [2001] (Feb) article-2 article-3 (Mar) article-4 " |
|---|
| 103 | | page(:news).should render(tags).as(expected) |
|---|
| 104 | | end |
|---|
| 105 | | specify '<r:children:each:header> with "restart" attribute set to one name' do |
|---|
| 106 | | 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>} |
|---|
| 107 | | expected = "[2000] (Dec) article [2001] (Feb) article-2 article-3 (Mar) article-4 " |
|---|
| 108 | | page(:news).should render(tags).as(expected) |
|---|
| 109 | | end |
|---|
| 110 | | specify '<r:children:each:header> with "restart" attribute set to two names' do |
|---|
| 111 | | 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>} |
|---|
| 112 | | expected = "[2000] (Dec) <01> article [2001] (Feb) <09> article-2 <24> article-3 (Mar) <06> article-4 " |
|---|
| 113 | | page(:news).should render(tags).as(expected) |
|---|
| 114 | | end |
|---|
| 115 | | |
|---|
| 116 | | specify '<r:children:count>' do |
|---|
| | 50 | describe "<r:children:each>" do |
|---|
| | 51 | it "should iterate through the children of the current page" do |
|---|
| | 52 | page(:parent) |
|---|
| | 53 | page.should render('<r:children:each><r:title /> </r:children:each>').as('Child Child 2 Child 3 ') |
|---|
| | 54 | 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 ') |
|---|
| | 55 | page(:assorted).should render(page_children_each_tags).as('a b c d e f g h i j ') |
|---|
| | 56 | end |
|---|
| | 57 | |
|---|
| | 58 | it 'should not list virtual pages' do |
|---|
| | 59 | page.should render('<r:children:each><r:slug /> </r:children:each>').as('a b c d e f g h i j ') |
|---|
| | 60 | 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 ') |
|---|
| | 61 | end |
|---|
| | 62 | |
|---|
| | 63 | it 'should error with invalid "limit" attribute' do |
|---|
| | 64 | message = "`limit' attribute of `each' tag must be a positive number between 1 and 4 digits" |
|---|
| | 65 | page.should render(page_children_each_tags(%{limit="a"})).with_error(message) |
|---|
| | 66 | page.should render(page_children_each_tags(%{limit="-10"})).with_error(message) |
|---|
| | 67 | page.should render(page_children_each_tags(%{limit="50000"})).with_error(message) |
|---|
| | 68 | end |
|---|
| | 69 | |
|---|
| | 70 | it 'should error with invalid "offset" attribute' do |
|---|
| | 71 | message = "`offset' attribute of `each' tag must be a positive number between 1 and 4 digits" |
|---|
| | 72 | page.should render(%{offset="a"}).with_error(message) |
|---|
| | 73 | page.should render(%{offset="-10"}).with_error(message) |
|---|
| | 74 | page.should render(%{offset="50000"}).with_error(message) |
|---|
| | 75 | end |
|---|
| | 76 | |
|---|
| | 77 | it 'should error with invalid "by" attribute' do |
|---|
| | 78 | message = "`by' attribute of `each' tag must be set to a valid field name" |
|---|
| | 79 | page.should render(page_children_each_tags(%{by="non-existant-field"})).with_error(message) |
|---|
| | 80 | end |
|---|
| | 81 | |
|---|
| | 82 | it 'should error with invalid "order" attribute' do |
|---|
| | 83 | message = %{`order' attribute of `each' tag must be set to either "asc" or "desc"} |
|---|
| | 84 | page.should render(page_children_each_tags(%{order="asdf"})).with_error(message) |
|---|
| | 85 | end |
|---|
| | 86 | |
|---|
| | 87 | it "should limit the number of children when given a 'limit' attribute" do |
|---|
| | 88 | page.should render(page_children_each_tags(%{limit="5"})).as('a b c d e ') |
|---|
| | 89 | end |
|---|
| | 90 | |
|---|
| | 91 | it "should limit and offset the children when given 'limit' and 'offset' attributes" do |
|---|
| | 92 | page.should render(page_children_each_tags(%{offset="3" limit="5"})).as('d e f g h ') |
|---|
| | 93 | end |
|---|
| | 94 | |
|---|
| | 95 | it "should change the sort order when given an 'order' attribute" do |
|---|
| | 96 | page.should render(page_children_each_tags(%{order="desc"})).as('j i h g f e d c b a ') |
|---|
| | 97 | end |
|---|
| | 98 | |
|---|
| | 99 | it "should sort by the 'by' attribute" do |
|---|
| | 100 | page.should render(page_children_each_tags(%{by="breadcrumb"})).as('f e d c b a j i h g ') |
|---|
| | 101 | end |
|---|
| | 102 | |
|---|
| | 103 | it "should sort by the 'by' attribute according to the 'order' attribute" do |
|---|
| | 104 | page.should render(page_children_each_tags(%{by="breadcrumb" order="desc"})).as('g h i j a b c d e f ') |
|---|
| | 105 | end |
|---|
| | 106 | |
|---|
| | 107 | describe 'with "status" attribute' do |
|---|
| | 108 | it "set to 'all' should list all children" do |
|---|
| | 109 | page.should render(page_children_each_tags(%{status="all"})).as("a b c d e f g h i j draft ") |
|---|
| | 110 | end |
|---|
| | 111 | |
|---|
| | 112 | it "set to 'draft' should list only children with 'draft' status" do |
|---|
| | 113 | page.should render(page_children_each_tags(%{status="draft"})).as('draft ') |
|---|
| | 114 | end |
|---|
| | 115 | |
|---|
| | 116 | it "set to 'published' should list only children with 'draft' status" do |
|---|
| | 117 | page.should render(page_children_each_tags(%{status="published"})).as('a b c d e f g h i j ') |
|---|
| | 118 | end |
|---|
| | 119 | |
|---|
| | 120 | it "set to an invalid status should render an error" do |
|---|
| | 121 | page.should render(page_children_each_tags(%{status="askdf"})).with_error("`status' attribute of `each' tag must be set to a valid status") |
|---|
| | 122 | end |
|---|
| | 123 | end |
|---|
| | 124 | end |
|---|
| | 125 | |
|---|
| | 126 | |
|---|
| | 127 | describe "<r:children:each:header>" do |
|---|
| | 128 | it "should render the header when it changes" do |
|---|
| | 129 | tags = '<r:children:each><r:header>[<r:date format="%b/%y" />] </r:header><r:slug /> </r:children:each>' |
|---|
| | 130 | expected = "[Dec/00] article [Feb/01] article-2 article-3 [Mar/01] article-4 " |
|---|
| | 131 | page(:news).should render(tags).as(expected) |
|---|
| | 132 | end |
|---|
| | 133 | |
|---|
| | 134 | it 'with "name" attribute should maintain a separate header' do |
|---|
| | 135 | 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>} |
|---|
| | 136 | expected = "[2000] (Dec) article [2001] (Feb) article-2 article-3 (Mar) article-4 " |
|---|
| | 137 | page(:news).should render(tags).as(expected) |
|---|
| | 138 | end |
|---|
| | 139 | |
|---|
| | 140 | it 'with "restart" attribute set to one name should restart that header' do |
|---|
| | 141 | 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>} |
|---|
| | 142 | expected = "[2000] (Dec) article [2001] (Feb) article-2 article-3 (Mar) article-4 " |
|---|
| | 143 | page(:news).should render(tags).as(expected) |
|---|
| | 144 | end |
|---|
| | 145 | |
|---|
| | 146 | it 'with "restart" attribute set to two names should restart both headers' do |
|---|
| | 147 | 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>} |
|---|
| | 148 | expected = "[2000] (Dec) <01> article [2001] (Feb) <09> article-2 <24> article-3 (Mar) <06> article-4 " |
|---|
| | 149 | page(:news).should render(tags).as(expected) |
|---|
| | 150 | end |
|---|
| | 151 | end |
|---|
| | 152 | |
|---|
| | 153 | it '<r:children:count> should render the number of children of the current page' do |
|---|
| 120 | | specify '<r:children:first>' do |
|---|
| 121 | | page(:parent).should render('<r:children:first:title />').as('Child') |
|---|
| 122 | | end |
|---|
| 123 | | specify '<r:children:first> with attributes' do |
|---|
| 124 | | page.should render(page_children_first_tags).as('a') |
|---|
| 125 | | page.should render(page_children_first_tags(%{limit="5"})).as('a') |
|---|
| 126 | | page.should render(page_children_first_tags(%{offset="3" limit="5"})).as('d') |
|---|
| 127 | | page.should render(page_children_first_tags(%{order="desc"})).as('j') |
|---|
| 128 | | page.should render(page_children_first_tags(%{by="breadcrumb"})).as('f') |
|---|
| 129 | | page.should render(page_children_first_tags(%{by="breadcrumb" order="desc"})).as('g') |
|---|
| 130 | | end |
|---|
| 131 | | specify '<r:children:first> when no children exist' do |
|---|
| 132 | | page(:first).should render('<r:children:first:title />').as('') |
|---|
| 133 | | end |
|---|
| 134 | | |
|---|
| 135 | | specify '<r:children:last>' do |
|---|
| 136 | | page(:parent).should render('<r:children:last:title />').as('Child 3') |
|---|
| 137 | | end |
|---|
| 138 | | specify '<r:children:last> with attributes' do |
|---|
| 139 | | page.should render(page_children_last_tags).as('j') |
|---|
| 140 | | page.should render(page_children_last_tags(%{limit="5"})).as('e') |
|---|
| 141 | | page.should render(page_children_last_tags(%{offset="3" limit="5"})).as('h') |
|---|
| 142 | | page.should render(page_children_last_tags(%{order="desc"})).as('a') |
|---|
| 143 | | page.should render(page_children_last_tags(%{by="breadcrumb"})).as('g') |
|---|
| 144 | | page.should render(page_children_last_tags(%{by="breadcrumb" order="desc"})).as('f') |
|---|
| 145 | | end |
|---|
| 146 | | specify '<r:children:last> when no children exist' do |
|---|
| 147 | | page(:first).should render('<r:children:last:title />').as('') |
|---|
| 148 | | end |
|---|
| 149 | | |
|---|
| 150 | | specify '<r:content>' do |
|---|
| 151 | | page.should render('<r:content />').as('Assorted body.') |
|---|
| 152 | | end |
|---|
| 153 | | specify '<r:content> with "part" attribute' do |
|---|
| 154 | | page(:home).should render('<r:content part="extended" />').as("Just a test.") |
|---|
| 155 | | end |
|---|
| 156 | | specify '<r:content> with inherit attribute' do |
|---|
| 157 | | page.should render('<r:content part="sidebar" />').as('') |
|---|
| 158 | | page.should render('<r:content part="sidebar" inherit="false" />').as('') |
|---|
| 159 | | page.should render('<r:content part="sidebar" inherit="true" />').as('Assorted sidebar.') |
|---|
| 160 | | 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"}) |
|---|
| 161 | | page.should render('<r:content part="part_that_doesnt_exist" inherit="true" />').as('') |
|---|
| 162 | | end |
|---|
| 163 | | specify '<r:content> with inherit and contextual attributes' do |
|---|
| 164 | | page(:parent) |
|---|
| 165 | | page.should render('<r:content part="sidebar" inherit="true" contextual="true" />').as('Parent sidebar.') |
|---|
| 166 | | page.should render('<r:content part="sidebar" inherit="true" contextual="false" />').as('Home sidebar.') |
|---|
| 167 | | page(:child).should render('<r:content part="sidebar" inherit="true" contextual="true" />').as('Child sidebar.') |
|---|
| 168 | | page(:grandchild).should render('<r:content part="sidebar" inherit="true" contextual="true" />').as('Grandchild sidebar.') |
|---|
| 169 | | end |
|---|
| 170 | | specify '<r:content> with global page propagation' do |
|---|
| 171 | | page(:first) |
|---|
| 172 | | page.should render('<r:content part="titles" inherit="true" contextual="true"/>').as('First First') |
|---|
| 173 | | page.should render('<r:content part="titles" inherit="true" contextual="false"/>').as('Home First') |
|---|
| 174 | | end |
|---|
| 175 | | specify '<r:content /> for children' do |
|---|
| 176 | | expected = "Child body. Child 2 body. Child 3 body. " |
|---|
| 177 | | page(:parent).should render('<r:children:each><r:content /> </r:children:each>').as(expected) |
|---|
| 178 | | end |
|---|
| 179 | | |
|---|
| 180 | | specify '<r:if_content> without "part" attribute' do |
|---|
| 181 | | page.should render('<r:if_content>true</r:if_content>').as('true') |
|---|
| 182 | | end |
|---|
| 183 | | specify '<r:if_content> with "part" attribute' do |
|---|
| 184 | | page.should render('<r:if_content part="body">true</r:if_content>').as('true') |
|---|
| 185 | | end |
|---|
| 186 | | specify '<r:if_content> with nonexistant "part" attribute' do |
|---|
| 187 | | page.should render('<r:if_content part="asdf">true</r:if_content>').as('') |
|---|
| 188 | | end |
|---|
| 189 | | |
|---|
| 190 | | specify '<r:unless_content> without "part" attribute' do |
|---|
| 191 | | page.should render('<r:unless_content>false</r:unless_content>').as('') |
|---|
| 192 | | end |
|---|
| 193 | | specify '<r:unless_content> with "part" attribute' do |
|---|
| 194 | | page.should render('<r:unless_content part="body">false</r:unless_content>').as('') |
|---|
| 195 | | end |
|---|
| 196 | | specify '<r:unless_content> with nonexistant "part" attribute' do |
|---|
| 197 | | page.should render('<r:unless_content part="asdf">false</r:unless_content>').as('false') |
|---|
| 198 | | end |
|---|
| 199 | | |
|---|
| 200 | | specify '<r:author>' do |
|---|
| 201 | | page.should render('<r:author />').as('Admin') |
|---|
| 202 | | end |
|---|
| 203 | | specify '<r:author> nil' do |
|---|
| 204 | | page(:no_user).should render('<r:author />').as('') |
|---|
| 205 | | end |
|---|
| 206 | | |
|---|
| 207 | | specify '<r:date>' do |
|---|
| 208 | | page(:dated) |
|---|
| 209 | | page.should render('<r:date />').as('Wednesday, January 11, 2006') |
|---|
| 210 | | end |
|---|
| 211 | | specify '<r:date> with "format" attribute' do |
|---|
| 212 | | page(:dated) |
|---|
| 213 | | page.should render('<r:date format="%d %b %Y" />').as('11 Jan 2006') |
|---|
| 214 | | end |
|---|
| 215 | | specify '<r:date> with "for" attribute' do |
|---|
| 216 | | page(:dated) |
|---|
| 217 | | page.should render('<r:date for="now" />').as(Time.now.strftime("%A, %B %d, %Y")) |
|---|
| 218 | | page.should render('<r:date for="created_at" />').as('Tuesday, January 10, 2006') |
|---|
| 219 | | page.should render('<r:date for="updated_at" />').as('Thursday, January 12, 2006') |
|---|
| 220 | | page.should render('<r:date for="published_at" />').as('Wednesday, January 11, 2006') |
|---|
| 221 | | page.should render('<r:date for="blah" />').with_error("Invalid value for 'for' attribute.") |
|---|
| 222 | | end |
|---|
| 223 | | specify '<r:date> should use local timezone' do |
|---|
| 224 | | page(:dated) |
|---|
| 225 | | Radiant::Config["local.timezone"] = "Tokyo" |
|---|
| 226 | | format = "%H:%m" |
|---|
| 227 | | expected = TimeZone["Tokyo"].adjust(page.published_at).strftime(format) |
|---|
| 228 | | page.should render(%Q(<r:date format="#{format}" />) ).as(expected) |
|---|
| 229 | | end |
|---|
| 230 | | |
|---|
| 231 | | specify '<r:link>' do |
|---|
| 232 | | page.should render('<r:link />').as('<a href="/assorted/">Assorted</a>') |
|---|
| 233 | | end |
|---|
| 234 | | specify '<r:link> in block form' do |
|---|
| 235 | | page.should render('<r:link>Test</r:link>').as('<a href="/assorted/">Test</a>') |
|---|
| 236 | | end |
|---|
| 237 | | specify '<r:link> with HTML attributes' do |
|---|
| 238 | | expected = '<a href="/assorted/" class="test" id="assorted">Assorted</a>' |
|---|
| 239 | | page.should render('<r:link class="test" id="assorted" />').as(expected) |
|---|
| 240 | | end |
|---|
| 241 | | specify '<r:link> with "anchor" attribute' do |
|---|
| 242 | | page.should render('<r:link anchor="test">Test</r:link>').as('<a href="/assorted/#test">Test</a>') |
|---|
| 243 | | end |
|---|
| 244 | | specify '<r:link> should work for children' do |
|---|
| 245 | | expected = %{<a href="/parent/child/">Child</a> <a href="/parent/child-2/">Child 2</a> <a href="/parent/child-3/">Child 3</a> } |
|---|
| 246 | | page(:parent).should render('<r:children:each><r:link /> </r:children:each>' ).as(expected) |
|---|
| 247 | | end |
|---|
| 248 | | specify '<r:link> with a relative URL root should scope to the relative root' do |
|---|
| 249 | | page(:assorted).should render('<r:link />').with_relative_root('/foo').as('<a href="/foo/assorted/">Assorted</a>') |
|---|
| 250 | | end |
|---|
| 251 | | |
|---|
| 252 | | specify '<r:snippet>' do |
|---|
| 253 | | page.should render('<r:snippet name="first" />').as('test') |
|---|
| 254 | | end |
|---|
| 255 | | specify '<r:snippet> not found' do |
|---|
| 256 | | page.should render('<r:snippet name="non-existant" />').with_error('snippet not found') |
|---|
| 257 | | end |
|---|
| 258 | | specify '<r:snippet> without name' do |
|---|
| 259 | | page.should render('<r:snippet />').with_error("`snippet' tag must contain `name' attribute") |
|---|
| 260 | | end |
|---|
| 261 | | specify '<r:snippet> with markdown' do |
|---|
| 262 | | page.should render('<r:page><r:snippet name="markdown" /></r:page>').as('<p><strong>markdown</strong></p>') |
|---|
| 263 | | end |
|---|
| 264 | | specify '<r:snippet> with global page propagation' do |
|---|
| 265 | | page(:parent).should render('<r:snippet name="global_page_cascade" />').as("#{@page.title} " * @page.children.count) |
|---|
| 266 | | end |
|---|
| 267 | | specify '<r:snippet> with recursion global page propagation' do |
|---|
| 268 | | page(:child).should render('<r:snippet name="recursive" />').as("Great GrandchildGrandchildChild") |
|---|
| | 157 | describe "<r:children:first>" do |
|---|
| | 158 | it 'should render its contents in the context of the first child page' do |
|---|
| | 159 | page(:parent).should render('<r:children:first:title />').as('Child') |
|---|
| | 160 | end |
|---|
| | 161 | |
|---|
| | 162 | it 'should accept the same scoping attributes as <r:children:each>' do |
|---|
| | 163 | page.should render(page_children_first_tags).as('a') |
|---|
| | 164 | page.should render(page_children_first_tags(%{limit="5"})).as('a') |
|---|
| | 165 | page.should render(page_children_first_tags(%{offset="3" limit="5"})).as('d') |
|---|
| | 166 | page.should render(page_children_first_tags(%{order="desc"})).as('j') |
|---|
| | 167 | page.should render(page_children_first_tags(%{by="breadcrumb"})).as('f') |
|---|
| | 168 | page.should render(page_children_first_tags(%{by="breadcrumb" order="desc"})).as('g') |
|---|
| | 169 | end |
|---|
| | 170 | |
|---|
| | 171 | it "should render nothing when no children exist" do |
|---|
| | 172 | page(:first).should render('<r:children:first:title />').as('') |
|---|
| | 173 | end |
|---|
| | 174 | end |
|---|
| | 175 | |
|---|
| | 176 | describe "<r:children:last>" do |
|---|
| | 177 | it 'should render its contents in the context of the last child page' do |
|---|
| | 178 | page(:parent).should render('<r:children:last:title />').as('Child 3') |
|---|
| | 179 | end |
|---|
| | 180 | |
|---|
| | 181 | it 'should accept the same scoping attributes as <r:children:each>' do |
|---|
| | 182 | page.should render(page_children_last_tags).as('j') |
|---|
| | 183 | page.should render(page_children_last_tags(%{limit="5"})).as('e') |
|---|
| | 184 | page.should render(page_children_last_tags(%{offset="3" limit="5"})).as('h') |
|---|
| | 185 | page.should render(page_children_last_tags(%{order="desc"})).as('a') |
|---|
| | 186 | page.should render(page_children_last_tags(%{by="breadcrumb"})).as('g') |
|---|
| | 187 | page.should render(page_children_last_tags(%{by="breadcrumb" order="desc"})).as('f') |
|---|
| | 188 | end |
|---|
| | 189 | |
|---|
| | 190 | it "should render nothing when no children exist" do |
|---|
| | 191 | page(:first).should render('<r:children:last:title />').as('') |
|---|
| | 192 | end |
|---|
| | 193 | end |
|---|
| | 194 | |
|---|
| | 195 | describe "<r:content>" do |
|---|
| | 196 | it "should render the 'body' part by default" do |
|---|
| | 197 | page.should render('<r:content />').as('Assorted body.') |
|---|
| | 198 | end |
|---|
| | 199 | |
|---|
| | 200 | it "with 'part' attribute should render the specified part" do |
|---|
| | 201 | page(:home).should render('<r:content part="extended" />').as("Just a test.") |
|---|
| | 202 | end |
|---|
| | 203 | |
|---|
| | 204 | describe "with inherit attribute" do |
|---|
| | 205 | it "missing or set to 'false' should render the current page's part" do |
|---|
| | 206 | page.should render('<r:content part="sidebar" />').as('') |
|---|
| | 207 | page.should render('<r:content part="sidebar" inherit="false" />').as('') |
|---|
| | 208 | end |
|---|
| | 209 | |
|---|
| | 210 | describe "set to 'true'" do |
|---|
| | 211 | it "should render an ancestor's part" do |
|---|
| | 212 | page.should render('<r:content part="sidebar" inherit="true" />').as('Assorted sidebar.') |
|---|
| | 213 | end |
|---|
| | 214 | it "should render nothing when no ancestor has the part" do |
|---|
| | 215 | page.should render('<r:content part="part_that_doesnt_exist" inherit="true" />').as('') |
|---|
| | 216 | end |
|---|
| | 217 | |
|---|
| | 218 | describe "and contextual attribute" do |
|---|
| | 219 | it "set to 'true' should render the part in the context of the current page" do |
|---|
| | 220 | page(:parent).should render('<r:content part="sidebar" inherit="true" contextual="true" />').as('Parent sidebar.') |
|---|
| | 221 | page(:child).should render('<r:content part="sidebar" inherit="true" contextual="true" />').as('Child sidebar.') |
|---|
| | 222 | page(:grandchild).should render('<r:content part="sidebar" inherit="true" contextual="true" />').as('Grandchild sidebar.') |
|---|
| | 223 | end |
|---|
| | 224 | |
|---|
| | 225 | it "set to 'false' should render the part in the context of its containing page" do |
|---|
| | 226 | page(:parent).should render('<r:content part="sidebar" inherit="true" contextual="false" />').as('Home sidebar.') |
|---|
| | 227 | end |
|---|
| | 228 | |
|---|
| | 229 | it "should maintain the global page" do |
|---|
| | 230 | page(:first) |
|---|
| | 231 | page.should render('<r:content part="titles" inherit="true" contextual="true"/>').as('First First') |
|---|
| | 232 | page.should render('<r:content part="titles" inherit="true" contextual="false"/>').as('Home First') |
|---|
| | 233 | end |
|---|
| | 234 | end |
|---|
| | 235 | end |
|---|
| | 236 | |
|---|
| | 237 | it "set to an erroneous value should render an error" do |
|---|
| | 238 | 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"}) |
|---|
| | 239 | end |
|---|
| | 240 | |
|---|
| | 241 | it "should render parts with respect to the current contextual page" do |
|---|
| | 242 | expected = "Child body. Child 2 body. Child 3 body. " |
|---|
| | 243 | page(:parent).should render('<r:children:each><r:content /> </r:children:each>').as(expected) |
|---|
| | 244 | end |
|---|
| | 245 | end |
|---|
| | 246 | end |
|---|
| | 247 | |
|---|
| | 248 | describe "<r:if_content>" do |
|---|
| | 249 | it "without 'part' attribute should render the contained block if the 'body' part exists" do |
|---|
| | 250 | page.should render('<r:if_content>true</r:if_content>').as('true') |
|---|
| | 251 | end |
|---|
| | 252 | |
|---|
| | 253 | it "should render the contained block if the specified part exists" do |
|---|
| | 254 | page.should render('<r:if_content part="body">true</r:if_content>').as('true') |
|---|
| | 255 | end |
|---|
| | 256 | |
|---|
| | 257 | it "should not render the contained block if the specified part does not exist" do |
|---|
| | 258 | page.should render('<r:if_content part="asdf">true</r:if_content>').as('') |
|---|
| | 259 | end |
|---|
| | 260 | end |
|---|
| | 261 | |
|---|
| | 262 | describe "<r:unless_content>" do |
|---|
| | 263 | it "without 'part' attribute should not render the contained block if the 'body' part exists" do |
|---|
| | 264 | page.should render('<r:unless_content>false</r:unless_content>').as('') |
|---|
| | 265 | end |
|---|
| | 266 | |
|---|
| | 267 | it "should not render the contained block if the specified part exists" do |
|---|
| | 268 | page.should render('<r:unless_content part="body">false</r:unless_content>').as('') |
|---|
| | 269 | end |
|---|
| | 270 | |
|---|
| | 271 | it "should render the contained block if the specified part does not exist" do |
|---|
| | 272 | page.should render('<r:unless_content part="asdf">false</r:unless_content>').as('false') |
|---|
| | 273 | end |
|---|
| | 274 | end |
|---|
| | 275 | |
|---|
| | 276 | describe "<r:author>" do |
|---|
| | 277 | it "should render the author of the current page" do |
|---|
| | 278 | page.should render('<r:author />').as('Admin') |
|---|
| | 279 | end |
|---|
| | 280 | |
|---|
| | 281 | it "should render nothing when the page has no author" do |
|---|
| | 282 | page(:no_user).should render('<r:author />').as('') |
|---|
| | 283 | end |
|---|
| | 284 | end |
|---|
| | 285 | |
|---|
| | 286 | describe "<r:date>" do |
|---|
| | 287 | before :each do |
|---|
| | 288 | page(:dated) |
|---|
| | 289 | end |
|---|
| | 290 | |
|---|
| | 291 | it "should render the published date of the page" do |
|---|
| | 292 | page.should render('<r:date />').as('Wednesday, January 11, 2006') |
|---|
| | 293 | end |
|---|
| | 294 | |
|---|
| | 295 | it "should format the published date according to the 'format' attribute" do |
|---|
| | 296 | page.should render('<r:date format="%d %b %Y" />').as('11 Jan 2006') |
|---|
| | 297 | end |
|---|
| | 298 | |
|---|
| | 299 | describe "with 'for' attribute" do |
|---|
| | 300 | it "set to 'now' should render the current date" do |
|---|
| | 301 | page.should render('<r:date for="now" />').as(Time.now.strftime("%A, %B %d, %Y")) |
|---|
| | 302 | end |
|---|
| | 303 | |
|---|
| | 304 | it "set to 'created_at' should render the creation date" do |
|---|
| | 305 | page.should render('<r:date for="created_at" />').as('Tuesday, January 10, 2006') |
|---|
| | 306 | end |
|---|
| | 307 | |
|---|
| | 308 | it "set to 'updated_at' should render the update date" do |
|---|
| | 309 | page.should render('<r:date for="updated_at" />').as('Thursday, January 12, 2006') |
|---|
| | 310 | end |
|---|
| | 311 | |
|---|
| | 312 | it "set to 'published_at' should render the publish date" do |
|---|
| | 313 | page.should render('<r:date for="published_at" />').as('Wednesday, January 11, 2006') |
|---|
| | 314 | end |
|---|
| | 315 | |
|---|
| | 316 | it "set to an invalid attribute should render an error" do |
|---|
| | 317 | page.should render('<r:date for="blah" />').with_error("Invalid value for 'for' attribute.") |
|---|
| | 318 | end |
|---|
| | 319 | end |
|---|
| | 320 | |
|---|
| | 321 | it "should use the configured local timezone" do |
|---|
| | 322 | Radiant::Config["local.timezone"] = "Tokyo" |
|---|
| | 323 | format = "%H:%m" |
|---|
| | 324 | expected = TimeZone["Tokyo"].adjust(page.published_at).strftime(format) |
|---|
| | 325 | page.should render(%Q(<r:date format="#{format}" />) ).as(expected) |
|---|
| | 326 | end |
|---|
| | 327 | end |
|---|
| | 328 | |
|---|
| | 329 | describe "<r:link>" do |
|---|
| | 330 | it "should render a link to the current page" do |
|---|
| | 331 | page.should render('<r:link />').as('<a href="/assorted/">Assorted</a>') |
|---|
| | 332 | end |
|---|
| | 333 | |
|---|
| | 334 | it "should render its contents as the text of the link" do |
|---|
| | 335 | page.should render('<r:link>Test</r:link>').as('<a href="/assorted/">Test</a>') |
|---|
| | 336 | end |
|---|
| | 337 | |
|---|
| | 338 | it "should pass HTML attributes to the <a> tag" do |
|---|
| | 339 | expected = '<a href="/assorted/" class="test" id="assorted">Assorted</a>' |
|---|
| | 340 | page.should render('<r:link class="test" id="assorted" />').as(expected) |
|---|
| | 341 | end |
|---|
| | 342 | |
|---|
| | 343 | it "should add the anchor attribute to the link as a URL anchor" do |
|---|
| | 344 | page.should render('<r:link anchor="test">Test</r:link>').as('<a href="/assorted/#test">Test</a>') |
|---|
| | 345 | end |
|---|
| | 346 | |
|---|
| | 347 | it "should render a link for the current contextual page" do |
|---|
| | 348 | expected = %{<a href="/parent/child/">Child</a> <a href="/parent/child-2/">Child 2</a> <a href="/parent/child-3/">Child 3</a> } |
|---|
| | 349 | page(:parent).should render('<r:children:each><r:link /> </r:children:each>' ).as(expected) |
|---|
| | 350 | end |
|---|
| | 351 | |
|---|
| | 352 | it "should scope the link within the relative URL root" do |
|---|
| | 353 | page(:assorted).should render('<r:link />').with_relative_root('/foo').as('<a href="/foo/assorted/">Assorted</a>') |
|---|
| | 354 | end |
|---|
| | 355 | end |
|---|
| | 356 | |
|---|
| | 357 | describe "<r:snippet>" do |
|---|
| | 358 | it "should the contents of the specified snippet" do |
|---|
| | 359 | page.should render('<r:snippet name="first" />').as('test') |
|---|
| | 360 | end |
|---|
| | 361 | |
|---|
| | 362 | it "should render an error when the snippet does not exist" do |
|---|
| | 363 | page.should render('<r:snippet name="non-existant" />').with_error('snippet not found') |
|---|
| | 364 | end |
|---|
| | 365 | |
|---|
| | 366 | it "should render an error when not given a 'name' attribute" do |
|---|
| | 367 | page.should render('<r:snippet />').with_error("`snippet' tag must contain `name' attribute") |
|---|
| | 368 | end |
|---|
| | 369 | |
|---|
| | 370 | it "should filter the snippet with its assigned filter" do |
|---|
| | 371 | page.should render('<r:page><r:snippet name="markdown" /></r:page>').as('<p><strong>markdown</strong></p>') |
|---|
| | 372 | end |
|---|
| | 373 | |
|---|
| | 374 | it "should maintain the global page inside the snippet" do |
|---|
| | 375 | page(:parent).should render('<r:snippet name="global_page_cascade" />').as("#{@page.title} " * @page.children.count) |
|---|
| | 376 | end |
|---|
| | 377 | |
|---|
| | 378 | it "should maintain the global page when the snippet renders recursively" do |
|---|
| | 379 | page(:child).should render('<r:snippet name="recursive" />').as("Great GrandchildGrandchildChild") |
|---|
| | 380 | end |
|---|
| 279 | | specify '<r:navigation> simple case' do |
|---|
| 280 | | tags = %{<r:navigation urls="Home: / | Assorted: /assorted/ | Parent: /parent/"> |
|---|
| 281 | | <r:normal><r:title /></r:normal> |
|---|
| 282 | | </r:navigation>} |
|---|
| 283 | | expected = %{Home Assorted Parent} |
|---|
| 284 | | page.should render(tags).as(expected) |
|---|
| 285 | | end |
|---|
| 286 | | specify '<r:navigation> more complex' do |
|---|
| 287 | | tags = %{<r:navigation urls="Home: / | Assorted: /assorted/ | Parent: /parent/ | Radius: /radius/"> |
|---|
| 288 | | <r:normal><r:title /></r:normal> |
|---|
| 289 | | <r:selected><strong><r:title/></strong></r:selected> |
|---|
| 290 | | </r:navigation>} |
|---|
| 291 | | expected = %{<strong>Home</strong> Assorted <strong>Parent</strong> Radius} |
|---|
| 292 | | page(:parent).should render(tags).as(expected) |
|---|
| 293 | | end |
|---|
| 294 | | specify '<r:navigation> very complex' do |
|---|
| 295 | | tags = %{<r:navigation urls="Home: Boy: / | Assorted: /assorted/ | Parent: /parent/"> |
|---|
| 296 | | <r:normal><a href="<r:url />"><r:title /></a></r:normal> |
|---|
| 297 | | <r:here><strong><r:title /></strong></r:here> |
|---|
| 298 | | <r:selected><strong><a href="<r:url />"><r:title /></a></strong></r:selected> |
|---|
| 299 | | <r:between> | </r:between> |
|---|
| 300 | | </r:navigation>} |
|---|
| 301 | | expected = %{<strong><a href="/">Home: Boy</a></strong> | <strong>Assorted</strong> | <a href="/parent/">Parent</a>} |
|---|
| 302 | | page.should render(tags).as(expected) |
|---|
| 303 | | end |
|---|
| 304 | | specify '<r:navigation> without urls' do |
|---|
| 305 | | page.should render(%{<r:navigation><r:normal /></r:navigation>}).as('') |
|---|
| 306 | | end |
|---|
| 307 | | specify '<r:navigation> without normal tag' do |
|---|
| 308 | | page.should render(%{<r:navigation urls="something:here"></r:navigation>}).with_error( "`navigation' tag must include a `normal' tag") |
|---|
| 309 | | end |
|---|
| 310 | | specify '<r:navigation> with urls without slashes' do |
|---|
| 311 | | tags = %{<r:navigation urls="Home: / | Assorted: /assorted/ | Parent: /parent/ | Radius: /radius/"> |
|---|
| 312 | | <r:normal><r:title /></r:normal> |
|---|
| 313 | | <r:here><strong><r:title /></strong></r:here> |
|---|
| 314 | | </r:navigation>} |
|---|
| 315 | | expected = %{Home <strong>Assorted</strong> Parent Radius} |
|---|
| 316 | | page.should render(tags).as(expected) |
|---|
| 317 | | end |
|---|
| 318 | | specify '<r:navigation> with empty nodes' do |
|---|
| 319 | | tags = %{<r:navigation urls="Home: Boy: / | Archives: /archive/ | Radius: /radius/ | Docs: /documentation/"> |
|---|
| 320 | | <r:normal><a href="<r:url />"><r:title /></a></r:normal> |
|---|
| 321 | | <r:here></r:here> |
|---|
| 322 | | <r:selected><strong><a href="<r:url />"><r:title /></a></strong></r:selected> |
|---|
| 323 | | <r:between> | </r:between> |
|---|
| 324 | | </r:navigation>} |
|---|
| 325 | | expected = %{<strong><a href="/">Home: Boy</a></strong> | <a href="/archive/">Archives</a> | <a href="/documentation/">Docs</a>} |
|---|
| 326 | | page(:radius).should render(tags).as(expected) |
|---|
| | 391 | describe "<r:navigation>" do |
|---|
| | 392 | it "should render the nested <r:normal> tag by default" do |
|---|
| | 393 | tags = %{<r:navigation urls="Home: / | Assorted: /assorted/ | Parent: /parent/"> |
|---|
| | 394 | <r:normal><r:title /></r:normal> |
|---|
| | 395 | </r:navigation>} |
|---|
| | 396 | expected = %{Home Assorted Parent} |
|---|
| | 397 | page.should render(tags).as(expected) |
|---|
| | 398 | end |
|---|
| | 399 | |
|---|
| | 400 | it "should render the nested <r:selected> tag for URLs that match the current page" do |
|---|
| | 401 | tags = %{<r:navigation urls="Home: / | Assorted: /assorted/ | Parent: /parent/ | Radius: /radius/"> |
|---|
| | 402 | <r:normal><r:title /></r:normal> |
|---|
| | 403 | <r:selected><strong><r:title/></strong></r:selected> |
|---|
| | 404 | </r:navigation>} |
|---|
| | 405 | expected = %{<strong>Home</strong> Assorted <strong>Parent</strong> Radius} |
|---|
| | 406 | page(:parent).should render(tags).as(expected) |
|---|
| | 407 | end |
|---|
| | 408 | |
|---|
| | 409 | it "should render the nested <r:here> tag for URLs that exactly match the current page" do |
|---|
| | 410 | tags = %{<r:navigation urls="Home: Boy: / | Assorted: /assorted/ | Parent: /parent/"> |
|---|
| | 411 | <r:normal><a href="<r:url />"><r:title /></a></r:normal> |
|---|
| | 412 | <r:here><strong><r:title /></strong></r:here> |
|---|
| | 413 | <r:selected><strong><a href="<r:url />"><r:title /></a></strong></r:selected> |
|---|
| | 414 | <r:between> | </r:between> |
|---|
| | 415 | </r:navigation>} |
|---|
| | 416 | expected = %{<strong><a href="/">Home: Boy</a></strong> | <strong>Assorted</strong> | <a href="/parent/">Parent</a>} |
|---|
| | 417 | page.should render(tags).as(expected) |
|---|
| | 418 | end |
|---|
| | 419 | |
|---|
| | 420 | it "should render the nested <r:between> tag between each link" do |
|---|
| | 421 | tags = %{<r:navigation urls="Home: / | Assorted: /assorted/ | Parent: /parent/"> |
|---|
| | 422 | <r:normal><r:title /></r:normal> |
|---|
| | 423 | <r:between> :: </r:between> |
|---|
| | 424 | </r:navigation>} |
|---|
| | 425 | expected = %{Home :: Assorted :: Parent} |
|---|
| | 426 | page.should render(tags).as(expected) |
|---|
| | 427 | end |
|---|
| | 428 | |
|---|
| | 429 | it 'without urls should render nothing' do |
|---|
| | 430 | page.should render(%{<r:navigation><r:normal /></r:navigation>}).as('') |
|---|
| | 431 | end |
|---|
| | 432 | |
|---|
| | 433 | it 'without a nested <r:normal> tag should render an error' do |
|---|
| | 434 | page.should render(%{<r:navigation urls="something:here"></r:navigation>}).with_error( "`navigation' tag must include a `normal' tag") |
|---|
| | 435 | end |
|---|
| | 436 | |
|---|
| | 437 | it 'with urls without trailing slashes should match corresponding pages' do |
|---|
| | 438 | tags = %{<r:navigation urls="Home: / | Assorted: /assorted | Parent: /parent | Radius: /radius"> |
|---|
| | 439 | <r:normal><r:title /></r:normal> |
|---|
| | 440 | <r:here><strong><r:title /></strong></r:here> |
|---|
| | 441 | </r:navigation>} |
|---|
| | 442 | expected = %{Home <strong>Assorted</strong> Parent Radius} |
|---|
| | 443 | page.should render(tags).as(expected) |
|---|
| | 444 | end |
|---|
| | 445 | |
|---|
| | 446 | it 'should prune empty blocks' do |
|---|
| | 447 | tags = %{<r:navigation urls="Home: Boy: / | Archives: /archive/ | Radius: /radius/ | Docs: /documentation/"> |
|---|
| | 448 | <r:normal><a href="<r:url />"><r:title /></a></r:normal> |
|---|
| | 449 | <r:here></r:here> |
|---|
| | 450 | <r:selected><strong><a href="<r:url />"><r:title /></a></strong></r:selected> |
|---|
| | 451 | <r:between> | </r:between> |
|---|
| | 452 | </r:navigation>} |
|---|
| | 453 | expected = %{<strong><a href="/">Home: Boy</a></strong> | <a href="/archive/">Archives</a> | <a href="/documentation/">Docs</a>} |
|---|
| | 454 | page(:radius).should render(tags).as(expected) |
|---|
| | 455 | end |
|---|