bike 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. data/LICENSE +19 -0
  2. data/README.rdoc +124 -0
  3. data/bin/bike +35 -0
  4. data/lib/_error.rb +14 -0
  5. data/lib/_field.rb +260 -0
  6. data/lib/_i18n.rb +144 -0
  7. data/lib/_parser.rb +256 -0
  8. data/lib/_path.rb +86 -0
  9. data/lib/_storage/_storage.rb +215 -0
  10. data/lib/_storage/file.rb +201 -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/bike.rb +396 -0
  32. data/lib/meta/_meta.rb +20 -0
  33. data/lib/meta/group.rb +19 -0
  34. data/lib/meta/id.rb +59 -0
  35. data/lib/meta/owner.rb +21 -0
  36. data/lib/meta/timestamp.rb +118 -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 +196 -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 +73 -0
  95. data/skel/skin/index.html +39 -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/qux/index.html +8 -0
  111. data/t/skin/foo/qux/moo/index.html +6 -0
  112. data/t/skin/foo/sub-20100306_0001.yaml +3 -0
  113. data/t/skin/index.yaml +3 -0
  114. data/t/skin/t_attachment/index.html +13 -0
  115. data/t/skin/t_contact/done.html +6 -0
  116. data/t/skin/t_contact/index.html +9 -0
  117. data/t/skin/t_file/index.html +16 -0
  118. data/t/skin/t_img/index.html +14 -0
  119. data/t/skin/t_img/test.jpg +0 -0
  120. data/t/skin/t_select/index.html +9 -0
  121. data/t/skin/t_store/index.html +9 -0
  122. data/t/skin/t_summary/20100326_0001.yaml +3 -0
  123. data/t/skin/t_summary/create.html +9 -0
  124. data/t/skin/t_summary/index.html +9 -0
  125. data/t/skin/t_summary/summary.html +9 -0
  126. data/t/t.rb +27 -0
  127. data/t/test_bike.rb +768 -0
  128. data/t/test_call.rb +1281 -0
  129. data/t/test_checkbox.rb +273 -0
  130. data/t/test_field.rb +330 -0
  131. data/t/test_file.rb +900 -0
  132. data/t/test_i18n.rb +325 -0
  133. data/t/test_id.rb +215 -0
  134. data/t/test_img.rb +328 -0
  135. data/t/test_meta.rb +57 -0
  136. data/t/test_parser.rb +1516 -0
  137. data/t/test_password.rb +188 -0
  138. data/t/test_radio.rb +226 -0
  139. data/t/test_role.rb +249 -0
  140. data/t/test_select.rb +182 -0
  141. data/t/test_set_complex.rb +527 -0
  142. data/t/test_set_dynamic.rb +1504 -0
  143. data/t/test_set_folder.rb +515 -0
  144. data/t/test_set_permit.rb +246 -0
  145. data/t/test_set_static.rb +468 -0
  146. data/t/test_storage.rb +915 -0
  147. data/t/test_text.rb +125 -0
  148. data/t/test_textarea.rb +138 -0
  149. data/t/test_timestamp.rb +473 -0
  150. data/t/test_workflow.rb +367 -0
  151. metadata +347 -0
@@ -0,0 +1,246 @@
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_Permit < Test::Unit::TestCase
9
+
10
+ class Bike::Workflow::Test_set_permit < Bike::Workflow
11
+ DEFAULT_SUB_ITEMS = {
12
+ '_owner' => {:klass => 'meta-owner'},
13
+ }
14
+ PERM = {
15
+ :create => 0b11110,
16
+ :read => 0b11100,
17
+ :update => 0b11100,
18
+ :delete => 0b11100,
19
+ }
20
+ end
21
+
22
+ def setup
23
+ @sd = Bike::Set::Dynamic.new(
24
+ :workflow => 'test_set_permit',
25
+ :item_arg => {
26
+ :item => {'foo' => {:klass => 'text'}}
27
+ }
28
+ ).load(
29
+ '20100228_0001' => {'_owner' => 'frank', 'foo' => 'abc'},
30
+ '20100228_0002' => {'_owner' => 'carl', 'foo' => 'def'}
31
+ )
32
+ @sd[:owner] = 'frank'
33
+ @sd.send(:item_instance, '_0001') # create a new pending item
34
+ end
35
+
36
+ def teardown
37
+ end
38
+
39
+ def test_permit_get_by_frank
40
+ Bike.client = 'frank'
41
+ assert_equal(
42
+ 0b00110,
43
+ @sd[:roles],
44
+ 'frank should be the owner of the set and a logged-in user'
45
+ )
46
+ assert(
47
+ @sd.send(
48
+ :'permit_get?',
49
+ {
50
+ :action => :update,
51
+ :conds => {:id => '20100228_0001'},
52
+ }
53
+ ),
54
+ 'Set#permit_get? should allow frank to get an update form of his own item'
55
+ )
56
+ assert(
57
+ @sd.send(
58
+ :'permit_get?',
59
+ {
60
+ :action => :update,
61
+ }
62
+ ),
63
+ 'Set#permit_get? should allow frank to get an update form of any items in his set'
64
+ )
65
+
66
+ assert(
67
+ @sd.send(
68
+ :'permit_get?',
69
+ {
70
+ :action => :update,
71
+ :conds => {:id => '_0001'},
72
+ }
73
+ ),
74
+ 'Set#permit_get? should allow frank to get an update form of a new pending item'
75
+ )
76
+ assert(
77
+ @sd.item('_0001').send(
78
+ :'permit_get?',
79
+ {
80
+ :action => :update,
81
+ }
82
+ ),
83
+ 'frank should be allowed to get a sub-item of the pending item'
84
+ )
85
+ end
86
+
87
+ def test_permit_get_by_carl
88
+ Bike.client = 'carl'
89
+ assert_equal(
90
+ 0b00010,
91
+ @sd[:roles],
92
+ 'carl should be a logged-in user'
93
+ )
94
+ assert(
95
+ !@sd.send(
96
+ :'permit_get?',
97
+ {
98
+ :action => :update,
99
+ :conds => {:id => '20100228_0001'},
100
+ }
101
+ ),
102
+ "Set#permit_get? should not allow carl to get an update form of frank's item"
103
+ )
104
+ assert(
105
+ !@sd.item('20100228_0001').send(
106
+ :'permit_get?',
107
+ {
108
+ :action => :update,
109
+ }
110
+ ),
111
+ "carl should not be allowed to get a sub-item of frank's item"
112
+ )
113
+ assert(
114
+ @sd.send(
115
+ :'permit_get?',
116
+ {
117
+ :action => :update,
118
+ :conds => {:id => '20100228_0002'},
119
+ }
120
+ ),
121
+ 'Set#permit_get? should allow carl to get an update form of his own item'
122
+ )
123
+
124
+ assert(
125
+ @sd.send(
126
+ :'permit_get?',
127
+ {
128
+ :action => :update,
129
+ :conds => {:id => '_0001'},
130
+ }
131
+ ),
132
+ 'Set#permit_get? should allow carl to get an update form of a new pending item'
133
+ )
134
+ assert(
135
+ @sd.item('_0001').send(
136
+ :'permit_get?',
137
+ {
138
+ :action => :update,
139
+ }
140
+ ),
141
+ 'carl should be allowed to get a sub-item of the pending item'
142
+ )
143
+ end
144
+
145
+ def test_permit_post_by_frank
146
+ Bike.client = 'frank'
147
+ assert_equal(
148
+ 0b00110,
149
+ @sd[:roles],
150
+ 'frank should be the owner of the set and a logged-in user'
151
+ )
152
+ assert(
153
+ @sd.send(
154
+ :'permit_post?',
155
+ :update,
156
+ {
157
+ :action => :update,
158
+ '20100228_0001' => {},
159
+ }
160
+ ),
161
+ 'Set#permit_post? should allow frank to update his own item'
162
+ )
163
+ assert(
164
+ @sd.send(
165
+ :'permit_post?',
166
+ :update,
167
+ {
168
+ :action => :update,
169
+ '20100228_0002' => {},
170
+ }
171
+ ),
172
+ 'Set#permit_post? should allow frank to update any item in his set'
173
+ )
174
+ assert(
175
+ @sd.send(
176
+ :'permit_post?',
177
+ :update,
178
+ {
179
+ :action => :update,
180
+ '_0001' => {'foo' => 'FOO'},
181
+ }
182
+ ),
183
+ 'Set#permit_post? should allow frank to create/update a new item'
184
+ )
185
+ end
186
+
187
+ def test_permit_post_by_carl
188
+ Bike.client = 'carl'
189
+ assert_equal(
190
+ 0b00010,
191
+ @sd[:roles],
192
+ 'carl should be a logged-in user'
193
+ )
194
+ assert(
195
+ !@sd.send(
196
+ :'permit_post?',
197
+ :update,
198
+ {
199
+ :action => :update,
200
+ '20100228_0001' => {},
201
+ }
202
+ ),
203
+ "Set#permit_post? should not allow carl to update frank's item"
204
+ )
205
+ assert(
206
+ !@sd.item('20100228_0001').send(
207
+ :'permit_post?',
208
+ :update,
209
+ {'foo' => 'updated'}
210
+ ),
211
+ "carl should not be allowed to post a sub-item of frank's item"
212
+ )
213
+
214
+ assert(
215
+ @sd.send(
216
+ :'permit_post?',
217
+ :update,
218
+ {
219
+ :action => :update,
220
+ '20100228_0002' => {},
221
+ }
222
+ ),
223
+ 'Set#permit_post? should allow carl to update his own item'
224
+ )
225
+ assert(
226
+ @sd.send(
227
+ :'permit_post?',
228
+ :update,
229
+ {
230
+ :action => :update,
231
+ '_0001' => {'foo' => 'FOO'},
232
+ }
233
+ ),
234
+ 'Set#permit_post? should allow carl to create/update a new item'
235
+ )
236
+ assert(
237
+ @sd.item('_0001').send(
238
+ :'permit_post?',
239
+ :update,
240
+ {'foo' => 'updated'}
241
+ ),
242
+ 'carl should be allowed to post a sub-item of the new item'
243
+ )
244
+ end
245
+
246
+ end
@@ -0,0 +1,468 @@
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_Static < Test::Unit::TestCase
9
+
10
+ def setup
11
+ end
12
+
13
+ def teardown
14
+ end
15
+
16
+ def test_initialize
17
+ ss = Bike::Set::Static.new(:html => <<'_html')
18
+ <html>
19
+ <h1>$(title text 32)</h1>
20
+ <ul id="foo" class="app-blog">
21
+ <li title="Diary">
22
+ $(subject text 64)
23
+ $(body textarea 72*10)
24
+ <ul><li>qux</li></ul>
25
+ </li>
26
+ </ul>
27
+ </html>
28
+ _html
29
+ assert_equal(
30
+ {
31
+ 'title' => {:klass => 'text', :tokens => ['32']},
32
+ 'foo' => {
33
+ :klass => 'set-dynamic',
34
+ :workflow => 'blog',
35
+ :tmpl => {
36
+ :index => <<'_tmpl'.chomp,
37
+ <ul id="@(name)" class="app-blog">
38
+ $() </ul>
39
+ $(.navi)$(.submit)$(.action_create)
40
+ _tmpl
41
+ },
42
+ :item => {
43
+ 'default' => {
44
+ :label => 'Diary',
45
+ :tmpl => {
46
+ :index => <<'_tmpl',
47
+ <li title="">
48
+ $(.a_update)$(subject)</a>
49
+ $(body)$(.hidden)
50
+ <ul><li>qux</li></ul>
51
+ </li>
52
+ _tmpl
53
+ },
54
+ :item => {
55
+ 'body' => {
56
+ :width => 72,
57
+ :height => 10,
58
+ :klass => 'textarea',
59
+ },
60
+ 'subject' => {
61
+ :klass => 'text',
62
+ :tokens => ['64'],
63
+ },
64
+ },
65
+ },
66
+ },
67
+ },
68
+ },
69
+ ss[:item],
70
+ 'Set::Static#initialize should load @meta'
71
+ )
72
+ end
73
+
74
+ def test_meta_href
75
+ Bike.current[:uri] = nil
76
+
77
+ ss = Bike::Set::Static::Folder.root.item('foo','main','20091120_0001','replies','20091201_0001')
78
+ assert_equal(
79
+ '/foo/20091120_0001/replies/id=20091201_0001/',
80
+ ss[:href],
81
+ 'Set::Static#meta_href should return parent[:href] + an id cond'
82
+ )
83
+ end
84
+
85
+ def test_empty?
86
+ ss = Bike::Set::Static.new(:html => <<'_html')
87
+ <html>
88
+ <h1>$(title = text 32)</h1>
89
+ </html>
90
+ _html
91
+ ss.load 'title' => 'foo'
92
+ assert(
93
+ !ss.empty?,
94
+ 'Set::Static#empty? should return false if any item has a value'
95
+ )
96
+
97
+ ss.load 'title' => nil
98
+ assert(
99
+ ss.empty?,
100
+ 'Set::Static#empty? should return true if the all items do not have a value'
101
+ )
102
+
103
+ ss.load 'title' => ''
104
+ assert(
105
+ ss.empty?,
106
+ 'Set::Static#empty? should return true if the all items do not have a value'
107
+ )
108
+ end
109
+
110
+ def test_item
111
+ ss = Bike::Set::Static.new(:html => <<'_html')
112
+ <html>
113
+ <h1>$(title = text 32)</h1>
114
+ <ul id="main" class="app-attachment">
115
+ <li>hi</li>
116
+ </ul>
117
+ </html>
118
+ _html
119
+ title = ss.item('title')
120
+ assert_instance_of(
121
+ Bike::Text,
122
+ title,
123
+ 'Set::Static#item() should return the child item on the fly'
124
+ )
125
+ assert_equal(
126
+ title.object_id,
127
+ ss.item('title').object_id,
128
+ 'Set::Static#item() should cache the loaded items'
129
+ )
130
+ assert_equal(
131
+ 32,
132
+ title[:size],
133
+ 'Set::Static#item() should load the metas of child items'
134
+ )
135
+
136
+ main = ss.item('main')
137
+ assert_instance_of(
138
+ Bike::Set::Static::Dynamic,
139
+ main,
140
+ 'Set::Static#item() should return the child item on the fly'
141
+ )
142
+ assert_equal(
143
+ main.object_id,
144
+ ss.item('main').object_id,
145
+ 'Set::Static#item() should cache the loaded items'
146
+ )
147
+ assert_equal(
148
+ {
149
+ 'default' => {
150
+ :label => nil,
151
+ :tmpl => {:index => " <li>hi</li>\n"},
152
+ :item => {},
153
+ },
154
+ },
155
+ main[:item],
156
+ 'Set::Static#item() should load the metas of child items'
157
+ )
158
+
159
+ assert_nil(
160
+ ss.item('non-existent'),
161
+ 'Set::Static#item should return nil when the item is not in the storage'
162
+ )
163
+ assert_nil(
164
+ ss.item(''),
165
+ 'Set::Static#item should return nil when the item is not in the storage'
166
+ )
167
+ end
168
+
169
+ def test_val
170
+ ss = Bike::Set::Static.new(:html => <<'_html')
171
+ <li>
172
+ $(name text): $(comment text)
173
+ </li>
174
+ _html
175
+ ss.item('name').load 'foo'
176
+ assert_equal(
177
+ {'name' => 'foo'},
178
+ ss.val,
179
+ 'Set::Static#val should not include the value of the empty item'
180
+ )
181
+ ss.item('comment').load 'bar'
182
+ assert_equal(
183
+ {'name' => 'foo', 'comment' => 'bar'},
184
+ ss.val,
185
+ 'Set::Static#val should not include the value of the empty item'
186
+ )
187
+ end
188
+
189
+ def test_get
190
+ ss = Bike::Set::Static.new(:html => <<'_html')
191
+ <li>
192
+ $(name = text 32 :'nobody'): $(comment = text 128 :'peek a boo')
193
+ </li>
194
+ _html
195
+ ss.load_default
196
+ assert_equal(
197
+ <<'_html',
198
+ <li>
199
+ nobody: peek a boo
200
+ </li>
201
+ _html
202
+ ss.get,
203
+ 'Set::Static#get should return the html by [:tmpl]'
204
+ )
205
+
206
+ comment = ss.item('comment')
207
+ def comment._g_foo(arg)
208
+ 'foo foo'
209
+ end
210
+ assert_equal('foo foo', ss.item('comment').get(:action => 'foo'))
211
+ assert_equal(
212
+ <<'_html',
213
+ <li>
214
+ nobody: foo foo
215
+ </li>
216
+ _html
217
+ ss.get(:action => 'foo'),
218
+ 'Set::Static#get should pass :action to the child items'
219
+ )
220
+ end
221
+
222
+ def test_get_by_tmpl
223
+ ss = Bike::Set::Static.new(:html => '$(foo text)')
224
+ ss.item('foo').load 'hello'
225
+ assert_equal(
226
+ 'foo hello foo',
227
+ ss.send(:_get_by_tmpl, {}, 'foo $() foo'),
228
+ 'Set#_get_by_tmpl should replace %() with @val'
229
+ )
230
+
231
+ ss[:baz] = 1234
232
+ assert_equal(
233
+ 'foo 1234 foo',
234
+ ss.send(:_get_by_tmpl, {}, 'foo @(baz) foo'),
235
+ 'Set#_get_by_tmpl should replace @(...) with @meta[...]'
236
+ )
237
+
238
+ assert_equal(
239
+ 'foo baz foo',
240
+ ss.send(:_get_by_tmpl, {}, 'foo _(baz) foo'),
241
+ 'Set#_get_by_tmpl should evaluate _(...)'
242
+ )
243
+ end
244
+
245
+ def test_get_tmpl_non_existing_meta
246
+ ss = Bike::Set::Static.new(:html => '')
247
+ assert_equal(
248
+ 'foo @(foo-bar) foo',
249
+ ss.send(:_get_by_tmpl, {}, 'foo @(foo-bar) foo'),
250
+ 'Set#_get_by_tmpl should keep @() of non-existing item as is'
251
+ )
252
+ assert_equal(
253
+ 'foo foo',
254
+ ss.send(:_get_by_tmpl, {}, 'foo @(bar) foo'),
255
+ 'Set#_get_by_tmpl should evaluate non-existing @()'
256
+ )
257
+ end
258
+
259
+ def test_get_tmpl_non_existing_item
260
+ ss = Bike::Set::Static.new(:html => '')
261
+ assert_equal(
262
+ 'foo $(foo) foo',
263
+ ss.send(:_get_by_tmpl, {}, 'foo $(foo) foo'),
264
+ 'Set#_get_by_tmpl should keep non-existing $() as is'
265
+ )
266
+ end
267
+
268
+ def test_recursive_tmpl
269
+ ss = Bike::Set::Static.new(:html => <<'_html')
270
+ <li>$()</li>
271
+ _html
272
+ assert_nothing_raised(
273
+ 'Set::Static#get should avoid recursive reference to [:tmpl]'
274
+ ) {
275
+ ss.get
276
+ }
277
+ end
278
+
279
+ def test_g_a_update
280
+ ss = Bike::Set::Static.new(:html => '$(.a_update)', :parent => Bike::Set::Static.new)
281
+
282
+ def ss.permit_get?(arg)
283
+ true
284
+ end
285
+ assert_equal(
286
+ '<a href="/update.html">',
287
+ ss.get(:action => :read),
288
+ 'Set#_g_a_update should return href if the orig_action is :read and :update is permmited'
289
+ )
290
+ assert_equal(
291
+ '<a>',
292
+ ss.get(:action => :update),
293
+ 'Set#_g_a_update should omit href if the orig_action is not :read'
294
+ )
295
+
296
+ def ss.permit_get?(arg)
297
+ true if arg[:action] == :read
298
+ end
299
+ def ss.permit?(action)
300
+ true if action == :read
301
+ end
302
+ assert_equal(
303
+ '<a>',
304
+ ss.get(:action => :read),
305
+ 'Set#_g_a_update should omit href unless :update is permmited'
306
+ )
307
+
308
+ def ss.permit_get?(arg)
309
+ true unless arg[:action] == :update
310
+ end
311
+ def ss.permit?(action)
312
+ true unless action == :update
313
+ end
314
+ assert_equal(
315
+ '<a href="/preview_delete.html">',
316
+ ss.get(:action => :read),
317
+ 'Set#_g_a_update should return href to :preview_delete if only :delete is permmited'
318
+ )
319
+ end
320
+
321
+ def test_post
322
+ ss = Bike::Set::Static.new(:html => <<'_html')
323
+ <li>
324
+ $(name = text 32 :'nobody'): $(comment = text 128 :'peek a boo')
325
+ </li>
326
+ _html
327
+ ss.post(:create, 'name' => 'carl')
328
+ assert_equal(
329
+ :create,
330
+ ss.action,
331
+ 'Set::Static#post should set @action'
332
+ )
333
+
334
+ ss.commit
335
+ assert_equal(
336
+ :create,
337
+ ss.result,
338
+ 'Set::Static#commit should set @result'
339
+ )
340
+
341
+ ss.post(:update, 'name' => 'carl')
342
+ assert_nil(
343
+ ss.result,
344
+ 'Set::Static#post should reset @result'
345
+ )
346
+ end
347
+
348
+ def test_load_default
349
+ ss = Bike::Set::Static.new(:html => <<'_html')
350
+ <li>
351
+ $(name = text 32 :'nobody'): $(comment = text 128 :'peek a boo')
352
+ </li>
353
+ _html
354
+ ss.load_default
355
+ assert_equal(
356
+ 'nobody',
357
+ ss.item('name').val,
358
+ 'Set::Static#load_default should load all the child items with their [:default]'
359
+ )
360
+ assert_equal(
361
+ 'peek a boo',
362
+ ss.item('comment').val,
363
+ 'Set::Static#load_default should load all the child items with their [:default]'
364
+ )
365
+ end
366
+
367
+ def test_load
368
+ ss = Bike::Set::Static.new(:html => <<'_html')
369
+ <li>
370
+ $(name = text 32 :'nobody'): $(comment = text 128 :'peek a boo')
371
+ </li>
372
+ _html
373
+ ss.load('name' => 'carl')
374
+ assert_equal(
375
+ {'name' => 'carl'},
376
+ ss.val,
377
+ 'Set::Static#load should not touch the item for which value is not given'
378
+ )
379
+ ss.load('name' => 'frank', 'comment' => 'cut the schmuck some slack.')
380
+ assert_equal(
381
+ {'name' => 'frank', 'comment' => 'cut the schmuck some slack.'},
382
+ ss.val,
383
+ 'Set::Static#load should load the items at once'
384
+ )
385
+ ss.load('name' => 'carl')
386
+ assert_equal(
387
+ {'name' => 'carl', 'comment' => 'cut the schmuck some slack.'},
388
+ ss.val,
389
+ 'Set::Static#load should not touch the item for which value is not given'
390
+ )
391
+ end
392
+
393
+ def test_create
394
+ ss = Bike::Set::Static.new(:html => <<'_html')
395
+ <li>
396
+ $(name = text 32 :'nobody'): $(comment = text 128 :'peek a boo')
397
+ </li>
398
+ _html
399
+ ss.create('name' => 'carl')
400
+ assert_equal(
401
+ {'name' => 'carl'},
402
+ ss.val,
403
+ 'Set::Static#create should not touch the item for which value is not given'
404
+ )
405
+ end
406
+
407
+ def test_update
408
+ ss = Bike::Set::Static.new(:html => <<'_html')
409
+ <li>
410
+ $(name = text 32 :'nobody'): $(comment = text 128 :'peek a boo')
411
+ </li>
412
+ _html
413
+ ss.update('name' => 'carl')
414
+ assert_equal(
415
+ {'name' => 'carl'},
416
+ ss.val,
417
+ 'Set::Static#update should not touch the item for which value is not given'
418
+ )
419
+ ss.update('name' => 'frank', 'comment' => 'cut the schmuck some slack.')
420
+ assert_equal(
421
+ {'name' => 'frank', 'comment' => 'cut the schmuck some slack.'},
422
+ ss.val,
423
+ 'Set::Static#udpate should load the items at once'
424
+ )
425
+ ss.update('name' => 'carl')
426
+ assert_equal(
427
+ {'name' => 'carl', 'comment' => 'cut the schmuck some slack.'},
428
+ ss.val,
429
+ 'Set::Static#update should not touch the item for which value is not given'
430
+ )
431
+
432
+ assert_nil(
433
+ ss.result,
434
+ 'Set::Static#result should return nil before the commit'
435
+ )
436
+ ss.commit
437
+ assert_equal(
438
+ {
439
+ 'name' => ss.item('name'),
440
+ 'comment' => ss.item('comment'),
441
+ },
442
+ ss.result,
443
+ 'Set::Static#result should return a hash of the committed items when :update'
444
+ )
445
+ end
446
+
447
+ def test_delete
448
+ ss = Bike::Set::Static.new(:html => <<'_html')
449
+ <li>
450
+ $(name = text 32 :'nobody'): $(comment = text 128 :'peek a boo')
451
+ </li>
452
+ _html
453
+ ss.item('name').load 'foo'
454
+
455
+ ss.delete
456
+ assert_equal(
457
+ :delete,
458
+ ss.action,
459
+ 'Set::Static#delete should set @action'
460
+ )
461
+ assert_equal(
462
+ {'name' => 'foo'},
463
+ ss.val,
464
+ 'Set::Static#delete should not touch any item'
465
+ )
466
+ end
467
+
468
+ end