runo 0.1.0

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.
Files changed (149) hide show
  1. data/LICENSE +19 -0
  2. data/README.rdoc +120 -0
  3. data/bin/runo +35 -0
  4. data/lib/_error.rb +14 -0
  5. data/lib/_field.rb +260 -0
  6. data/lib/_i18n.rb +141 -0
  7. data/lib/_parser.rb +243 -0
  8. data/lib/_path.rb +86 -0
  9. data/lib/_storage/_storage.rb +213 -0
  10. data/lib/_storage/file.rb +200 -0
  11. data/lib/_storage/sequel.rb +174 -0
  12. data/lib/_storage/temp.rb +73 -0
  13. data/lib/_widget/action_create.rb +23 -0
  14. data/lib/_widget/action_login.rb +22 -0
  15. data/lib/_widget/action_signup.rb +16 -0
  16. data/lib/_widget/action_update.rb +16 -0
  17. data/lib/_widget/crumb.rb +24 -0
  18. data/lib/_widget/done.rb +16 -0
  19. data/lib/_widget/login.rb +25 -0
  20. data/lib/_widget/me.rb +31 -0
  21. data/lib/_widget/message.rb +51 -0
  22. data/lib/_widget/navi.rb +88 -0
  23. data/lib/_widget/submit.rb +49 -0
  24. data/lib/_widget/view_ym.rb +77 -0
  25. data/lib/_workflow/_workflow.rb +89 -0
  26. data/lib/_workflow/attachment.rb +50 -0
  27. data/lib/_workflow/blog.rb +28 -0
  28. data/lib/_workflow/contact.rb +23 -0
  29. data/lib/_workflow/forum.rb +26 -0
  30. data/lib/_workflow/register.rb +39 -0
  31. data/lib/meta/_meta.rb +20 -0
  32. data/lib/meta/group.rb +19 -0
  33. data/lib/meta/id.rb +59 -0
  34. data/lib/meta/owner.rb +21 -0
  35. data/lib/meta/timestamp.rb +118 -0
  36. data/lib/runo.rb +396 -0
  37. data/lib/scalar/checkbox.rb +68 -0
  38. data/lib/scalar/file.rb +144 -0
  39. data/lib/scalar/img.rb +112 -0
  40. data/lib/scalar/password.rb +58 -0
  41. data/lib/scalar/radio.rb +47 -0
  42. data/lib/scalar/select.rb +47 -0
  43. data/lib/scalar/text.rb +38 -0
  44. data/lib/scalar/textarea.rb +35 -0
  45. data/lib/scalar/textarea_pre.rb +14 -0
  46. data/lib/scalar/textarea_wiki.rb +173 -0
  47. data/lib/set/_set.rb +195 -0
  48. data/lib/set/dynamic.rb +177 -0
  49. data/lib/set/static.rb +102 -0
  50. data/lib/set/static_folder.rb +96 -0
  51. data/locale/en/index.po +242 -0
  52. data/locale/index.pot +243 -0
  53. data/locale/ja/index.po +242 -0
  54. data/locale/lazy_parser.rb +54 -0
  55. data/skel/config.ru +27 -0
  56. data/skel/skin/_users/00000000_frank-avatar.jpg +0 -0
  57. data/skel/skin/_users/00000000_frank-avatar_small.jpg +0 -0
  58. data/skel/skin/_users/00000000_frank.yaml +12 -0
  59. data/skel/skin/_users/00000000_root-avatar.jpg +0 -0
  60. data/skel/skin/_users/00000000_root-avatar_small.jpg +0 -0
  61. data/skel/skin/_users/00000000_root.yaml +11 -0
  62. data/skel/skin/_users/css/users.css +21 -0
  63. data/skel/skin/_users/css/users.less +25 -0
  64. data/skel/skin/_users/done.html +42 -0
  65. data/skel/skin/_users/index.html +46 -0
  66. data/skel/skin/_users/index.yaml +3 -0
  67. data/skel/skin/_users/summary.html +40 -0
  68. data/skel/skin/css/base.css +93 -0
  69. data/skel/skin/css/base.less +139 -0
  70. data/skel/skin/css/coax.css +199 -0
  71. data/skel/skin/css/coax.less +244 -0
  72. data/skel/skin/examples/blog/20091214_0001.yaml +8 -0
  73. data/skel/skin/examples/blog/20100630_0001.yaml +8 -0
  74. data/skel/skin/examples/blog/20100630_0002.yaml +14 -0
  75. data/skel/skin/examples/blog/20100701_0001.yaml +8 -0
  76. data/skel/skin/examples/blog/20100701_0002-a-20100701_0001-f.jpg +0 -0
  77. data/skel/skin/examples/blog/20100701_0002-a-20100701_0001-f_small.jpg +0 -0
  78. data/skel/skin/examples/blog/20100701_0002.yaml +19 -0
  79. data/skel/skin/examples/blog/frank/20100701_0001.yaml +10 -0
  80. data/skel/skin/examples/blog/frank/index.yaml +4 -0
  81. data/skel/skin/examples/blog/index.html +51 -0
  82. data/skel/skin/examples/blog/rss.xml +18 -0
  83. data/skel/skin/examples/contact/20100701_0001-file.txt +1 -0
  84. data/skel/skin/examples/contact/20100701_0001.yaml +15 -0
  85. data/skel/skin/examples/contact/20100701_0002.yaml +8 -0
  86. data/skel/skin/examples/contact/20100701_0003.yaml +9 -0
  87. data/skel/skin/examples/contact/index.html +47 -0
  88. data/skel/skin/examples/contact/js/contact.js +13 -0
  89. data/skel/skin/examples/contact/summary.html +54 -0
  90. data/skel/skin/examples/forum/20100701_0001.yaml +41 -0
  91. data/skel/skin/examples/forum/20100701_0002.yaml +25 -0
  92. data/skel/skin/examples/forum/index.html +68 -0
  93. data/skel/skin/examples/forum/summary.html +47 -0
  94. data/skel/skin/examples/index.html +75 -0
  95. data/skel/skin/index.html +41 -0
  96. data/skel/skin/js/base.js +50 -0
  97. data/t/locale/de/index.po +19 -0
  98. data/t/locale/en-GB/index.po +25 -0
  99. data/t/locale/ja/index.po +30 -0
  100. data/t/skin/_users/00000000_test.yaml +3 -0
  101. data/t/skin/_users/index.html +13 -0
  102. data/t/skin/foo/20091120_0001.yaml +7 -0
  103. data/t/skin/foo/bar/20091120_0001.yaml +5 -0
  104. data/t/skin/foo/bar/index.yaml +5 -0
  105. data/t/skin/foo/baz/css/baz.css +1 -0
  106. data/t/skin/foo/css/foo.css +1 -0
  107. data/t/skin/foo/index.html +14 -0
  108. data/t/skin/foo/index.yaml +7 -0
  109. data/t/skin/foo/not_css/foo.css +1 -0
  110. data/t/skin/foo/sub-20100306_0001.yaml +3 -0
  111. data/t/skin/index.yaml +3 -0
  112. data/t/skin/t_attachment/index.html +13 -0
  113. data/t/skin/t_contact/done.html +6 -0
  114. data/t/skin/t_contact/index.html +9 -0
  115. data/t/skin/t_file/index.html +16 -0
  116. data/t/skin/t_img/index.html +14 -0
  117. data/t/skin/t_img/test.jpg +0 -0
  118. data/t/skin/t_select/index.html +9 -0
  119. data/t/skin/t_store/index.html +9 -0
  120. data/t/skin/t_summary/20100326_0001.yaml +3 -0
  121. data/t/skin/t_summary/create.html +9 -0
  122. data/t/skin/t_summary/index.html +9 -0
  123. data/t/skin/t_summary/summary.html +9 -0
  124. data/t/t.rb +27 -0
  125. data/t/test_checkbox.rb +273 -0
  126. data/t/test_field.rb +330 -0
  127. data/t/test_file.rb +900 -0
  128. data/t/test_id.rb +215 -0
  129. data/t/test_img.rb +328 -0
  130. data/t/test_meta.rb +57 -0
  131. data/t/test_parser.rb +1266 -0
  132. data/t/test_password.rb +188 -0
  133. data/t/test_radio.rb +226 -0
  134. data/t/test_role.rb +249 -0
  135. data/t/test_runo.rb +742 -0
  136. data/t/test_runo_call.rb +1286 -0
  137. data/t/test_runo_i18n.rb +318 -0
  138. data/t/test_select.rb +182 -0
  139. data/t/test_set_complex.rb +527 -0
  140. data/t/test_set_dynamic.rb +1504 -0
  141. data/t/test_set_folder.rb +515 -0
  142. data/t/test_set_permit.rb +246 -0
  143. data/t/test_set_static.rb +445 -0
  144. data/t/test_storage.rb +915 -0
  145. data/t/test_text.rb +125 -0
  146. data/t/test_textarea.rb +138 -0
  147. data/t/test_timestamp.rb +473 -0
  148. data/t/test_workflow.rb +367 -0
  149. metadata +345 -0
@@ -0,0 +1,515 @@
1
+ # encoding: UTF-8
2
+
3
+ # Author:: Akira FUNAI
4
+ # Copyright:: Copyright (c) 2009 Akira FUNAI
5
+
6
+ require "#{::File.dirname __FILE__}/t"
7
+
8
+ class TC_Set_Folder < Test::Unit::TestCase
9
+
10
+ def setup
11
+ Runo.client = 'root'
12
+ Runo.current[:base] = nil
13
+ Runo.current[:uri] = nil
14
+ end
15
+
16
+ def teardown
17
+ end
18
+
19
+ def test_root
20
+ root = Runo::Set::Static::Folder.root
21
+ assert_instance_of(
22
+ Runo::Set::Static::Folder,
23
+ root,
24
+ 'Folder.root should return the root folder instance'
25
+ )
26
+ end
27
+
28
+ def test_initialize
29
+ folder = Runo::Set::Static::Folder.new(:id => 'foo', :parent => nil)
30
+ assert_match(
31
+ /^<html>/,
32
+ folder[:html],
33
+ 'Folder#initialize should load [:html] from [:dir]/index.html'
34
+ )
35
+ assert_instance_of(
36
+ Runo::Set::Dynamic,
37
+ folder.item('main'),
38
+ 'Folder#initialize should load the items according to [:html]'
39
+ )
40
+ end
41
+
42
+ def test_meta_html_dir
43
+ folder = Runo::Set::Static::Folder.root.item('foo')
44
+ assert_equal(
45
+ '/foo',
46
+ folder[:html_dir],
47
+ "Folder#meta_html_dir should return meta_dir if there is 'index.html'"
48
+ )
49
+
50
+ folder = Runo::Set::Static::Folder.root.item('foo', 'bar')
51
+ assert_equal(
52
+ '/foo',
53
+ folder[:html_dir],
54
+ "Folder#meta_html_dir should return parent[:html_dir] if there is no 'index.html' in [:dir]"
55
+ )
56
+ end
57
+
58
+ def test_meta_href
59
+ folder = Runo::Set::Static::Folder.root.item('t_summary')
60
+
61
+ Runo.current[:uri] = 'http://example.com'
62
+ assert_equal(
63
+ 'http://example.com/t_summary/',
64
+ folder[:href],
65
+ 'Folder#meta_href should return a full URI when Runo.uri is available'
66
+ )
67
+
68
+ Runo.current[:uri] = nil
69
+ assert_equal(
70
+ '/t_summary/',
71
+ folder[:href],
72
+ 'Folder#meta_href should return [:dir] when Runo.uri is not available'
73
+ )
74
+ end
75
+
76
+ def test_load_yaml
77
+ folder = Runo::Set::Static::Folder.new(:id => 'foo', :parent => nil)
78
+ assert_equal(
79
+ 'Foo Folder',
80
+ folder[:label],
81
+ 'Folder#initialize should load metas from index.yaml'
82
+ )
83
+ assert_equal(
84
+ 'frank',
85
+ folder[:admin],
86
+ 'Folder#initialize should load metas from index.yaml'
87
+ )
88
+ end
89
+
90
+ def test_load_yaml_child_folder
91
+ folder = Runo::Set::Static::Folder.new(:id => 'foo', :parent => nil)
92
+ child = folder.item('bar')
93
+ assert_instance_of(
94
+ Runo::Set::Static::Folder,
95
+ child,
96
+ 'Folder#item should look the real directory for the child item'
97
+ )
98
+ assert_equal(
99
+ 'Bar Folder',
100
+ child[:label],
101
+ 'Folder#initialize should load metas from index.yaml'
102
+ )
103
+ assert_equal(
104
+ nil,
105
+ child[:admin],
106
+ 'Folder#initialize should not inherit metas from [:parent]'
107
+ )
108
+ end
109
+
110
+ def test_item
111
+ folder = Runo::Set::Static::Folder.root.item('foo')
112
+ assert_instance_of(
113
+ Runo::Set::Static,
114
+ folder.item('main', '20091120_0001'),
115
+ 'Folder#item should work just like any other sets'
116
+ )
117
+ assert_instance_of(
118
+ Runo::Set::Static,
119
+ folder.item('20091120_0001'),
120
+ "Folder#item should delegate to item('main') if full-formatted :id is given"
121
+ )
122
+ end
123
+
124
+ def test_merge_tmpl
125
+ folder = Runo::Set::Static::Folder.root
126
+
127
+ index = {
128
+ :item => {
129
+ 'main' => {
130
+ :item => {
131
+ 'default' => {
132
+ :tmpl => {:index => '<li><ul>$(files)</ul></li>'},
133
+ :item => {
134
+ 'files' => {
135
+ :tmpl => {:index => '<ol>$()</ol>'},
136
+ :item => {
137
+ 'default' => {
138
+ :tmpl => {:index => '<li>$(file)</li>'},
139
+ :item => {'file' => {:klass => 'text'}},
140
+ },
141
+ },
142
+ },
143
+ },
144
+ },
145
+ },
146
+ :tmpl => {:index => '<ul>$()</ul>'},
147
+ },
148
+ },
149
+ :tmpl => {:index => '<html>$(main)</html>'},
150
+ }
151
+ summary = {
152
+ :item => {
153
+ 'main' => {
154
+ :foo => 'this should not be merged.',
155
+ :item => {
156
+ 'default' => {
157
+ :bar => 'this should not be merged.',
158
+ :tmpl => {:summary => '<li class ="s"><ul>$(files)</ul></li>'},
159
+ :item => {
160
+ 'files' => {
161
+ :baz => 'this should not be merged.',
162
+ :tmpl => {:summary => '<ol class ="s">$()</ol>'},
163
+ :item => {
164
+ 'default' => {
165
+ :qux => 'this should not be merged.',
166
+ :tmpl => {:summary => '<li class ="s">$(file)</li>'},
167
+ },
168
+ },
169
+ },
170
+ },
171
+ },
172
+ },
173
+ :tmpl => {:summary => '<ul class ="s">$()</ul>'},
174
+ },
175
+ },
176
+ :tmpl => {:summary => '<html class ="s">$(main)</html>'},
177
+ }
178
+
179
+ assert_equal(
180
+ {
181
+ :item => {
182
+ 'main' => {
183
+ :item => {
184
+ 'default' => {
185
+ :tmpl => {
186
+ :index => '<li><ul>$(files)</ul></li>',
187
+ :summary => '<li class ="s"><ul>$(files)</ul></li>',
188
+ },
189
+ :item => {
190
+ 'files' => {
191
+ :tmpl => {
192
+ :index => '<ol>$()</ol>',
193
+ :summary => '<ol class ="s">$()</ol>',
194
+ },
195
+ :item => {
196
+ 'default' => {
197
+ :tmpl => {
198
+ :index => '<li>$(file)</li>',
199
+ :summary => '<li class ="s">$(file)</li>',
200
+ },
201
+ :item => {'file' => {:klass => 'text'}},
202
+ },
203
+ },
204
+ },
205
+ },
206
+ },
207
+ },
208
+ :tmpl => {
209
+ :index => '<ul>$()</ul>',
210
+ :summary => '<ul class ="s">$()</ul>',
211
+ },
212
+ },
213
+ },
214
+ :tmpl => {
215
+ :index => '<html>$(main)</html>',
216
+ :summary => '<html class ="s">$(main)</html>',
217
+ },
218
+ },
219
+ folder.send(:merge_tmpl, index, summary),
220
+ 'Folder#merge_tmpl should merge parsed metas'
221
+ )
222
+ end
223
+
224
+ def test_tmpl_summary
225
+ folder = Runo::Set::Static::Folder.root.item('t_summary')
226
+ assert_equal(
227
+ <<'_html',
228
+ <html>
229
+ <head><base href="@(href)" /><title>index</title></head>
230
+ <body>
231
+ <h1>index</h1>
232
+ $(main.message)$(main)</body>
233
+ </html>
234
+ _html
235
+ folder[:tmpl][:index],
236
+ 'Folder#initialize should load [:tmpl][:index] from [:dir]/index.html'
237
+ )
238
+ assert_equal(
239
+ <<'_html',
240
+ <html>
241
+ <head><base href="@(href)" /><title>summary</title></head>
242
+ <body>
243
+ <h1>summary</h1>
244
+ $(main.message)$(main)</body>
245
+ </html>
246
+ _html
247
+ folder[:tmpl][:summary],
248
+ 'Folder#initialize should load [:tmpl][:summary] from [:dir]/summary.html'
249
+ )
250
+
251
+ assert_equal(
252
+ <<'_html'.chomp,
253
+ <ul id="@(name)" class="runo-blog">
254
+ $()</ul>
255
+ $(.navi)$(.submit)$(.action_create)
256
+ _html
257
+ folder[:item]['main'][:tmpl][:index],
258
+ 'Folder#initialize should load [:tmpl] of the child items'
259
+ )
260
+ assert_equal(
261
+ <<'_html'.chomp,
262
+ <table id="@(name)" class="runo-blog">
263
+ $()</table>
264
+ $(.navi)$(.submit)$(.action_create)
265
+ _html
266
+ folder[:item]['main'][:tmpl][:summary],
267
+ 'Folder#initialize should load [:tmpl][:summary] of the child items'
268
+ )
269
+
270
+ assert_equal(
271
+ <<'_html',
272
+ <li>$(.a_update)$(name)</a>: $(comment)$(.hidden)</li>
273
+ _html
274
+ folder[:item]['main'][:item]['default'][:tmpl][:index],
275
+ 'Folder#initialize should load [:tmpl] of all the decendant items'
276
+ )
277
+ assert_equal(
278
+ <<'_html',
279
+ <tr><td><a href="$(.uri_detail)">$(name)</a></td><td>$(comment)</td></tr>
280
+ _html
281
+ folder[:item]['main'][:item]['default'][:tmpl][:summary],
282
+ 'Folder#initialize should load [:tmpl][:summary] of all the decendant items'
283
+ )
284
+ end
285
+
286
+ def test_href
287
+ folder = Runo::Set::Static::Folder.root.item('t_summary')
288
+
289
+ assert_match(
290
+ '<base href="@(href)" />',
291
+ folder[:tmpl][:index],
292
+ 'Folder#initialize should supplement <base href=...> to [:tmpl][*]'
293
+ )
294
+ assert_match(
295
+ '<base href="@(href)" />',
296
+ folder[:tmpl][:summary],
297
+ 'Folder#initialize should supplement <base href=...> to [:tmpl][*]'
298
+ )
299
+ end
300
+
301
+ def test_get_summary
302
+ folder = Runo::Set::Static::Folder.root.item('t_summary')
303
+
304
+ assert_equal(
305
+ <<'_html',
306
+ <html>
307
+ <head><base href="/t_summary/" /><title>summary</title></head>
308
+ <body>
309
+ <h1>summary</h1>
310
+ <table id="main" class="runo-blog">
311
+ <tr><td><a href="/t_summary/20100326/1/read_detail.html">frank</a></td><td>hi.</td></tr>
312
+ </table>
313
+ <div class="action_create"><a href="/t_summary/create.html">create new entry...</a></div>
314
+ </body>
315
+ </html>
316
+ _html
317
+ folder.get(
318
+ 'main' => {:conds => {:p => 1}}
319
+ ),
320
+ 'Set#get should use [:tmpl][:summary] when available and appropriate'
321
+ )
322
+ assert_equal(
323
+ <<'_html',
324
+ <html>
325
+ <head><base href="/t_summary/" /><title>index</title></head>
326
+ <body>
327
+ <h1>index</h1>
328
+ <ul id="main" class="runo-blog">
329
+ <li><a href="/t_summary/20100326/1/update.html">frank</a>: hi.</li>
330
+ </ul>
331
+ <div class="action_create"><a href="/t_summary/create.html">create new entry...</a></div>
332
+ </body>
333
+ </html>
334
+ _html
335
+ folder.get(
336
+ :action => :read,
337
+ :sub_action => :detail,
338
+ 'main' => {:action => :read, :sub_action => :detail, :conds => {:p => 1}}
339
+ ),
340
+ 'Set#get should not use [:tmpl][:summary] for :read -> :detail'
341
+ )
342
+
343
+ Runo.client = 'root'
344
+ Runo.current[:base] = folder.item('main')
345
+ folder.item('main')[:tid] = '12345.012'
346
+ assert_equal(
347
+ <<_html,
348
+ <html>
349
+ <head><base href="/t_summary/" /><title>index</title></head>
350
+ <body>
351
+ <h1>index</h1>
352
+ <form id="form_main" method="post" enctype="multipart/form-data" action="/t_summary/12345.012/update.html">
353
+ <input name="_token" type="hidden" value="#{Runo.token}" />
354
+ <ul id="main" class="runo-blog">
355
+ <li><a><span class="text"><input type="text" name="20100326_0001-name" value="frank" size="32" /></span></a>: <span class="text"><input type="text" name="20100326_0001-comment" value="hi." size="64" /></span></li>
356
+ </ul>
357
+ <div class="submit">
358
+ <input name=".status-public" type="submit" value="update" />
359
+ <input name=".action-preview_delete" type="submit" value="delete..." />
360
+ </div>
361
+ </form>
362
+ </body>
363
+ </html>
364
+ _html
365
+ folder.get(
366
+ :action => :read,
367
+ :sub_action => :detail,
368
+ 'main' => {:action => :update, :sub_action => nil, :conds => {:p => 1}}
369
+ ),
370
+ 'Set#get should not use [:tmpl][:summary] for :update'
371
+ )
372
+ end
373
+
374
+ def test_tmpl_create
375
+ folder = Runo::Set::Static::Folder.root.item('t_summary')
376
+
377
+ assert_equal(
378
+ <<'_html',
379
+ <html>
380
+ <head><base href="/t_summary/" /><title>create</title></head>
381
+ <body>
382
+ <h1>create</h1>
383
+ <ul id="main" class="runo-blog">
384
+ <li>main-create</li>
385
+ </ul>
386
+ <div class="submit">
387
+ <input name="main.status-public" type="submit" value="create" />
388
+ </div>
389
+ </body>
390
+ </html>
391
+ _html
392
+ folder.get(
393
+ 'main' => {:action => :create}
394
+ ),
395
+ 'Set#get should use [:tmpl][:create] when available and appropriate'
396
+ )
397
+ end
398
+
399
+ def test_tmpl_done
400
+ folder = Runo::Set::Static::Folder.root.item('t_contact')
401
+ assert_equal(
402
+ <<'_html',
403
+ <html>
404
+ <head><base href="@(href)" /><title>@(label)</title></head>
405
+ <body>
406
+ <p>thank you!</p>
407
+ </body>
408
+ </html>
409
+ _html
410
+ folder[:tmpl][:done],
411
+ 'Folder#initialize should load [:tmpl][:done] from [:dir]/done.html'
412
+ )
413
+ end
414
+
415
+ def test_g_login
416
+ folder = Runo::Set::Static::Folder.root.item('t_contact')
417
+
418
+ Runo.client = nil
419
+ assert_equal(
420
+ <<'_html',
421
+ <div class="action_login"><a href="/t_contact/login.html">login</a></div>
422
+ _html
423
+ folder.get(:action => :action_login),
424
+ 'Folder#_g_login should return a link to login/logout according to the current client'
425
+ )
426
+
427
+ Runo.client = 'frank'
428
+ assert_equal(
429
+ <<_html,
430
+ <div class="action_logout"><a href="/t_contact/logout.html?_token=#{Runo.token}">logout</a></div>
431
+ _html
432
+ folder.get(:action => :action_login),
433
+ 'Folder#_g_login should return a link to login/logout according to the current client'
434
+ )
435
+ end
436
+
437
+ def test_g_signup
438
+ folder = Runo::Set::Static::Folder.root.item('t_contact')
439
+
440
+ Runo.client = nil
441
+ assert_equal(
442
+ <<'_html',
443
+ <div class="action_signup"><a href="/_users/create.html">signup</a></div>
444
+ _html
445
+ folder.get(:action => :action_signup),
446
+ 'Folder#_g_signup should return a link to sign-up if the current client is nobody'
447
+ )
448
+
449
+ Runo.client = 'frank'
450
+ assert_nil(
451
+ folder.get(:action => :action_signup),
452
+ 'Folder#_g_signup should return nil unless the current client is nobody'
453
+ )
454
+ end
455
+
456
+ def test_g_me
457
+ folder = Runo::Set::Static::Folder.root.item('t_contact')
458
+
459
+ Runo.client = nil
460
+ assert_equal(
461
+ <<'_html',
462
+ <div class="me">
463
+ <div class="action_login"><a href="/t_contact/login.html">login</a></div>
464
+ </div>
465
+ _html
466
+ folder.get(:action => :me),
467
+ 'Folder#_g_me should return a link to login if the current client is nobody'
468
+ )
469
+
470
+ Runo.client = 'test'
471
+ assert_equal(
472
+ <<_html,
473
+ <div class="me">
474
+ <a href="/_users/id=test/update.html">
475
+ <span class="dummy_img" style="width: 72px; height: 72px;"></span>
476
+ </a>
477
+ <div class="client">test</div>
478
+ <div class="roles">(user)</div>
479
+ <div class="action_logout"><a href="/t_contact/logout.html?_token=#{Runo.token}">logout</a></div>
480
+ </div>
481
+ _html
482
+ folder.get(:action => :me),
483
+ 'Folder#_g_me should return a thumbnail of the current client and a link to logout'
484
+ )
485
+ end
486
+
487
+ def test_g_crumb
488
+ folder = Runo::Set::Static::Folder.root.item('foo','bar')
489
+ assert_equal(
490
+ <<'_html',
491
+ <div class="crumb">
492
+ <a href="/">Root</a>
493
+ &raquo;
494
+ <a href="/foo/">Foo Folder</a>
495
+ &raquo;
496
+ <a href="/foo/bar/">Bar Folder</a>
497
+ </div>
498
+ _html
499
+ folder.get(:action => :crumb),
500
+ 'Folder#_g_crumb should return crumbs from the root to the current folder'
501
+ )
502
+
503
+ folder = Runo::Set::Static::Folder.root
504
+ assert_equal(
505
+ <<'_html',
506
+ <div class="crumb">
507
+ <a href="/">Root</a>
508
+ </div>
509
+ _html
510
+ folder.get(:action => :crumb),
511
+ 'Folder#_g_crumb should return crumbs from the root to the current folder'
512
+ )
513
+ end
514
+
515
+ end