bike 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +19 -0
- data/README.rdoc +124 -0
- data/bin/bike +35 -0
- data/lib/_error.rb +14 -0
- data/lib/_field.rb +260 -0
- data/lib/_i18n.rb +144 -0
- data/lib/_parser.rb +256 -0
- data/lib/_path.rb +86 -0
- data/lib/_storage/_storage.rb +215 -0
- data/lib/_storage/file.rb +201 -0
- data/lib/_storage/sequel.rb +174 -0
- data/lib/_storage/temp.rb +73 -0
- data/lib/_widget/action_create.rb +23 -0
- data/lib/_widget/action_login.rb +22 -0
- data/lib/_widget/action_signup.rb +16 -0
- data/lib/_widget/action_update.rb +16 -0
- data/lib/_widget/crumb.rb +24 -0
- data/lib/_widget/done.rb +16 -0
- data/lib/_widget/login.rb +25 -0
- data/lib/_widget/me.rb +31 -0
- data/lib/_widget/message.rb +51 -0
- data/lib/_widget/navi.rb +88 -0
- data/lib/_widget/submit.rb +49 -0
- data/lib/_widget/view_ym.rb +77 -0
- data/lib/_workflow/_workflow.rb +89 -0
- data/lib/_workflow/attachment.rb +50 -0
- data/lib/_workflow/blog.rb +28 -0
- data/lib/_workflow/contact.rb +23 -0
- data/lib/_workflow/forum.rb +26 -0
- data/lib/_workflow/register.rb +39 -0
- data/lib/bike.rb +396 -0
- data/lib/meta/_meta.rb +20 -0
- data/lib/meta/group.rb +19 -0
- data/lib/meta/id.rb +59 -0
- data/lib/meta/owner.rb +21 -0
- data/lib/meta/timestamp.rb +118 -0
- data/lib/scalar/checkbox.rb +68 -0
- data/lib/scalar/file.rb +144 -0
- data/lib/scalar/img.rb +112 -0
- data/lib/scalar/password.rb +58 -0
- data/lib/scalar/radio.rb +47 -0
- data/lib/scalar/select.rb +47 -0
- data/lib/scalar/text.rb +38 -0
- data/lib/scalar/textarea.rb +35 -0
- data/lib/scalar/textarea_pre.rb +14 -0
- data/lib/scalar/textarea_wiki.rb +173 -0
- data/lib/set/_set.rb +196 -0
- data/lib/set/dynamic.rb +177 -0
- data/lib/set/static.rb +102 -0
- data/lib/set/static_folder.rb +96 -0
- data/locale/en/index.po +242 -0
- data/locale/index.pot +243 -0
- data/locale/ja/index.po +242 -0
- data/locale/lazy_parser.rb +54 -0
- data/skel/config.ru +27 -0
- data/skel/skin/_users/00000000_frank-avatar.jpg +0 -0
- data/skel/skin/_users/00000000_frank-avatar_small.jpg +0 -0
- data/skel/skin/_users/00000000_frank.yaml +12 -0
- data/skel/skin/_users/00000000_root-avatar.jpg +0 -0
- data/skel/skin/_users/00000000_root-avatar_small.jpg +0 -0
- data/skel/skin/_users/00000000_root.yaml +11 -0
- data/skel/skin/_users/css/users.css +21 -0
- data/skel/skin/_users/css/users.less +25 -0
- data/skel/skin/_users/done.html +42 -0
- data/skel/skin/_users/index.html +46 -0
- data/skel/skin/_users/index.yaml +3 -0
- data/skel/skin/_users/summary.html +40 -0
- data/skel/skin/css/base.css +93 -0
- data/skel/skin/css/base.less +139 -0
- data/skel/skin/css/coax.css +199 -0
- data/skel/skin/css/coax.less +244 -0
- data/skel/skin/examples/blog/20091214_0001.yaml +8 -0
- data/skel/skin/examples/blog/20100630_0001.yaml +8 -0
- data/skel/skin/examples/blog/20100630_0002.yaml +14 -0
- data/skel/skin/examples/blog/20100701_0001.yaml +8 -0
- data/skel/skin/examples/blog/20100701_0002-a-20100701_0001-f.jpg +0 -0
- data/skel/skin/examples/blog/20100701_0002-a-20100701_0001-f_small.jpg +0 -0
- data/skel/skin/examples/blog/20100701_0002.yaml +19 -0
- data/skel/skin/examples/blog/frank/20100701_0001.yaml +10 -0
- data/skel/skin/examples/blog/frank/index.yaml +4 -0
- data/skel/skin/examples/blog/index.html +51 -0
- data/skel/skin/examples/blog/rss.xml +18 -0
- data/skel/skin/examples/contact/20100701_0001-file.txt +1 -0
- data/skel/skin/examples/contact/20100701_0001.yaml +15 -0
- data/skel/skin/examples/contact/20100701_0002.yaml +8 -0
- data/skel/skin/examples/contact/20100701_0003.yaml +9 -0
- data/skel/skin/examples/contact/index.html +47 -0
- data/skel/skin/examples/contact/js/contact.js +13 -0
- data/skel/skin/examples/contact/summary.html +54 -0
- data/skel/skin/examples/forum/20100701_0001.yaml +41 -0
- data/skel/skin/examples/forum/20100701_0002.yaml +25 -0
- data/skel/skin/examples/forum/index.html +68 -0
- data/skel/skin/examples/forum/summary.html +47 -0
- data/skel/skin/examples/index.html +73 -0
- data/skel/skin/index.html +39 -0
- data/skel/skin/js/base.js +50 -0
- data/t/locale/de/index.po +19 -0
- data/t/locale/en-GB/index.po +25 -0
- data/t/locale/ja/index.po +30 -0
- data/t/skin/_users/00000000_test.yaml +3 -0
- data/t/skin/_users/index.html +13 -0
- data/t/skin/foo/20091120_0001.yaml +7 -0
- data/t/skin/foo/bar/20091120_0001.yaml +5 -0
- data/t/skin/foo/bar/index.yaml +5 -0
- data/t/skin/foo/baz/css/baz.css +1 -0
- data/t/skin/foo/css/foo.css +1 -0
- data/t/skin/foo/index.html +14 -0
- data/t/skin/foo/index.yaml +7 -0
- data/t/skin/foo/not_css/foo.css +1 -0
- data/t/skin/foo/qux/index.html +8 -0
- data/t/skin/foo/qux/moo/index.html +6 -0
- data/t/skin/foo/sub-20100306_0001.yaml +3 -0
- data/t/skin/index.yaml +3 -0
- data/t/skin/t_attachment/index.html +13 -0
- data/t/skin/t_contact/done.html +6 -0
- data/t/skin/t_contact/index.html +9 -0
- data/t/skin/t_file/index.html +16 -0
- data/t/skin/t_img/index.html +14 -0
- data/t/skin/t_img/test.jpg +0 -0
- data/t/skin/t_select/index.html +9 -0
- data/t/skin/t_store/index.html +9 -0
- data/t/skin/t_summary/20100326_0001.yaml +3 -0
- data/t/skin/t_summary/create.html +9 -0
- data/t/skin/t_summary/index.html +9 -0
- data/t/skin/t_summary/summary.html +9 -0
- data/t/t.rb +27 -0
- data/t/test_bike.rb +768 -0
- data/t/test_call.rb +1281 -0
- data/t/test_checkbox.rb +273 -0
- data/t/test_field.rb +330 -0
- data/t/test_file.rb +900 -0
- data/t/test_i18n.rb +325 -0
- data/t/test_id.rb +215 -0
- data/t/test_img.rb +328 -0
- data/t/test_meta.rb +57 -0
- data/t/test_parser.rb +1516 -0
- data/t/test_password.rb +188 -0
- data/t/test_radio.rb +226 -0
- data/t/test_role.rb +249 -0
- data/t/test_select.rb +182 -0
- data/t/test_set_complex.rb +527 -0
- data/t/test_set_dynamic.rb +1504 -0
- data/t/test_set_folder.rb +515 -0
- data/t/test_set_permit.rb +246 -0
- data/t/test_set_static.rb +468 -0
- data/t/test_storage.rb +915 -0
- data/t/test_text.rb +125 -0
- data/t/test_textarea.rb +138 -0
- data/t/test_timestamp.rb +473 -0
- data/t/test_workflow.rb +367 -0
- metadata +347 -0
data/t/test_select.rb
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
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_Select < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
def setup
|
|
11
|
+
meta = nil
|
|
12
|
+
Bike::Parser.gsub_scalar("$(foo select bar, baz, qux :'baz' mandatory)") {|id, m|
|
|
13
|
+
meta = m
|
|
14
|
+
''
|
|
15
|
+
}
|
|
16
|
+
@f = Bike::Field.instance meta
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def teardown
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_meta
|
|
23
|
+
assert_equal(
|
|
24
|
+
['bar', 'baz', 'qux'],
|
|
25
|
+
@f[:options],
|
|
26
|
+
'Select#initialize should set :options from the csv token'
|
|
27
|
+
)
|
|
28
|
+
assert_equal(
|
|
29
|
+
true,
|
|
30
|
+
@f[:mandatory],
|
|
31
|
+
'Select#initialize should set :mandatory from the misc token'
|
|
32
|
+
)
|
|
33
|
+
assert_equal(
|
|
34
|
+
'baz',
|
|
35
|
+
@f[:default],
|
|
36
|
+
'Select#initialize should set :default from the token'
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_meta_options_from_range
|
|
41
|
+
meta = nil
|
|
42
|
+
Bike::Parser.gsub_scalar("$(foo select 1..5)") {|id, m|
|
|
43
|
+
meta = m
|
|
44
|
+
''
|
|
45
|
+
}
|
|
46
|
+
f = Bike::Field.instance meta
|
|
47
|
+
assert_equal(
|
|
48
|
+
['1', '2', '3', '4', '5'],
|
|
49
|
+
f[:options],
|
|
50
|
+
'Select#initialize should set :options from the range token'
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
meta = nil
|
|
54
|
+
Bike::Parser.gsub_scalar("$(foo select ..5)") {|id, m|
|
|
55
|
+
meta = m
|
|
56
|
+
''
|
|
57
|
+
}
|
|
58
|
+
f = Bike::Field.instance meta
|
|
59
|
+
assert_equal(
|
|
60
|
+
['0', '1', '2', '3', '4', '5'],
|
|
61
|
+
f[:options],
|
|
62
|
+
'Select#initialize should set :options from the range token'
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
meta = nil
|
|
66
|
+
Bike::Parser.gsub_scalar("$(foo select 1..)") {|id, m|
|
|
67
|
+
meta = m
|
|
68
|
+
''
|
|
69
|
+
}
|
|
70
|
+
f = Bike::Field.instance meta
|
|
71
|
+
assert_equal(
|
|
72
|
+
nil,
|
|
73
|
+
f[:options],
|
|
74
|
+
'Select#initialize should not refer to the range token if there is no maximum'
|
|
75
|
+
)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_val_cast
|
|
79
|
+
assert_equal(
|
|
80
|
+
'',
|
|
81
|
+
@f.val,
|
|
82
|
+
'Select#val_cast should cast the given val to String'
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
@f.load 123
|
|
86
|
+
assert_equal(
|
|
87
|
+
'123',
|
|
88
|
+
@f.val,
|
|
89
|
+
'Select#val_cast should cast the given val to String'
|
|
90
|
+
)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_get
|
|
94
|
+
@f.load ''
|
|
95
|
+
assert_equal(
|
|
96
|
+
'',
|
|
97
|
+
@f.get,
|
|
98
|
+
'Select#get should return proper string'
|
|
99
|
+
)
|
|
100
|
+
assert_equal(
|
|
101
|
+
<<_html,
|
|
102
|
+
<span class="select">
|
|
103
|
+
<select name="">
|
|
104
|
+
<option value="">please select</option>
|
|
105
|
+
<option>bar</option>
|
|
106
|
+
<option>baz</option>
|
|
107
|
+
<option>qux</option>
|
|
108
|
+
</select>
|
|
109
|
+
</span>
|
|
110
|
+
_html
|
|
111
|
+
@f.get(:action => :create),
|
|
112
|
+
'Select#get should return proper string'
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
@f.load 'qux'
|
|
116
|
+
assert_equal(
|
|
117
|
+
'qux',
|
|
118
|
+
@f.get,
|
|
119
|
+
'Select#get should return proper string'
|
|
120
|
+
)
|
|
121
|
+
assert_equal(
|
|
122
|
+
<<_html,
|
|
123
|
+
<span class="select">
|
|
124
|
+
<select name="">
|
|
125
|
+
<option>bar</option>
|
|
126
|
+
<option>baz</option>
|
|
127
|
+
<option selected>qux</option>
|
|
128
|
+
</select>
|
|
129
|
+
</span>
|
|
130
|
+
_html
|
|
131
|
+
@f.get(:action => :update),
|
|
132
|
+
'Select#get should return proper string'
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def test_get_escape
|
|
137
|
+
@f[:options] = ['foo', '<bar>']
|
|
138
|
+
@f.load '<bar>'
|
|
139
|
+
assert_equal(
|
|
140
|
+
'<bar>',
|
|
141
|
+
@f.get,
|
|
142
|
+
'Select#get should escape the special characters'
|
|
143
|
+
)
|
|
144
|
+
assert_equal(
|
|
145
|
+
<<_html,
|
|
146
|
+
<span class="select">
|
|
147
|
+
<select name="">
|
|
148
|
+
<option>foo</option>
|
|
149
|
+
<option selected><bar></option>
|
|
150
|
+
</select>
|
|
151
|
+
</span>
|
|
152
|
+
_html
|
|
153
|
+
@f.get(:action => :update),
|
|
154
|
+
'Select#get should escape the special characters'
|
|
155
|
+
)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def test_errors
|
|
159
|
+
@f.load ''
|
|
160
|
+
@f[:mandatory] = nil
|
|
161
|
+
assert_equal(
|
|
162
|
+
[],
|
|
163
|
+
@f.errors,
|
|
164
|
+
'Select#errors should return the errors of the current val'
|
|
165
|
+
)
|
|
166
|
+
@f[:mandatory] = true
|
|
167
|
+
assert_equal(
|
|
168
|
+
['mandatory'],
|
|
169
|
+
@f.errors,
|
|
170
|
+
'Select#errors should return the errors of the current val'
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
@f.load 'boo'
|
|
174
|
+
@f[:mandatory] = nil
|
|
175
|
+
assert_equal(
|
|
176
|
+
['no such option'],
|
|
177
|
+
@f.errors,
|
|
178
|
+
'Select#errors should return the errors of the current val'
|
|
179
|
+
)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
end
|
|
@@ -0,0 +1,527 @@
|
|
|
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_Complex < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
class ::Bike::Set::Dynamic
|
|
11
|
+
def _g_vegetable(arg)
|
|
12
|
+
"'potato'"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class ::Bike::Workflow::Pipco < ::Bike::Workflow
|
|
17
|
+
DEFAULT_SUB_ITEMS = {
|
|
18
|
+
'_owner' => {:klass => 'meta-owner'},
|
|
19
|
+
}
|
|
20
|
+
PERM = {
|
|
21
|
+
:create => 0b11000,
|
|
22
|
+
:read => 0b11110,
|
|
23
|
+
:update => 0b11100,
|
|
24
|
+
:delete => 0b10100,
|
|
25
|
+
}
|
|
26
|
+
def _g_submit(arg)
|
|
27
|
+
'[pipco]'
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class ::Bike::Tomago < ::Bike::Field
|
|
32
|
+
def _get(arg)
|
|
33
|
+
args = arg.keys.collect {|k| "#{k}=#{arg[k]}" }.sort
|
|
34
|
+
"'#{val}'(#{args.join ', '})"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def setup
|
|
39
|
+
# Set::Dynamic of Set::Static of (Scalar and (Set::Dynamic of Set::Static of Scalar))
|
|
40
|
+
@sd = Bike::Set::Dynamic.new(
|
|
41
|
+
:id => 'main',
|
|
42
|
+
:klass => 'set-dynamic',
|
|
43
|
+
:workflow => 'pipco',
|
|
44
|
+
:group => ['roy', 'don'],
|
|
45
|
+
:tmpl => {
|
|
46
|
+
:index => <<'_tmpl'.chomp,
|
|
47
|
+
<ul id="@(name)" class="app-pipco">
|
|
48
|
+
$()</ul>
|
|
49
|
+
$(.navi)$(.submit)$(.action_create)
|
|
50
|
+
_tmpl
|
|
51
|
+
},
|
|
52
|
+
:item => {
|
|
53
|
+
'default' => Bike::Parser.parse_html(<<'_html')
|
|
54
|
+
<li id="@(name)">
|
|
55
|
+
$(name = tomago 32 :'nobody'): $(comment = tomago 64 :'hello.')
|
|
56
|
+
<ul id="files" class="app-attachment">
|
|
57
|
+
<li id="@(name)">$(file = tomago :'foo.jpg')</li>
|
|
58
|
+
</ul>
|
|
59
|
+
<ul id="replies" class="app-pipco">
|
|
60
|
+
<li id="@(name)">$(reply = tomago :'hi.')</li>
|
|
61
|
+
</ul>
|
|
62
|
+
$(replies.vegetable)
|
|
63
|
+
</li>
|
|
64
|
+
_html
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
@sd.load(
|
|
68
|
+
'20091123_0001' => {
|
|
69
|
+
'_owner' => 'carl',
|
|
70
|
+
'name' => 'CZ',
|
|
71
|
+
'comment' => 'oops',
|
|
72
|
+
'files' => {
|
|
73
|
+
'20091123_0001' => {'file' => 'carl1.jpg'},
|
|
74
|
+
'20091123_0002' => {'file' => 'carl2.jpg'},
|
|
75
|
+
},
|
|
76
|
+
'replies' => {
|
|
77
|
+
'20091125_0001' => {'_owner' => 'bobby', 'reply' => 'howdy.'},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
'20091123_0002' => {
|
|
81
|
+
'_owner' => 'roy',
|
|
82
|
+
'name' => 'RE',
|
|
83
|
+
'comment' => 'wee',
|
|
84
|
+
'files' => {
|
|
85
|
+
'20091123_0001' => {'file' => 'roy.png'},
|
|
86
|
+
},
|
|
87
|
+
'replies' => {
|
|
88
|
+
'20091125_0001' => {'_owner' => 'don', 'reply' => 'ho ho.'},
|
|
89
|
+
'20091125_0002' => {'_owner' => 'roy', 'reply' => 'oops.'},
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
[
|
|
95
|
+
@sd,
|
|
96
|
+
@sd.item('20091123_0001', 'files'),
|
|
97
|
+
@sd.item('20091123_0001', 'replies'),
|
|
98
|
+
@sd.item('20091123_0002', 'files'),
|
|
99
|
+
@sd.item('20091123_0002', 'replies'),
|
|
100
|
+
].each {|sd|
|
|
101
|
+
sd[:tmpl][:action_create] = ''
|
|
102
|
+
sd[:tmpl][:navi] = ''
|
|
103
|
+
sd[:tmpl][:submit_create] = '[c]'
|
|
104
|
+
sd[:tmpl][:submit_delete] = '[d]'
|
|
105
|
+
def sd._g_submit(arg)
|
|
106
|
+
"[#{my[:id]}-#{arg[:orig_action]}]\n"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
sd.each {|item|
|
|
110
|
+
item[:tmpl][:action_update] = ''
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def teardown
|
|
116
|
+
Bike.client = nil
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def test_get_default
|
|
120
|
+
Bike.client = 'root' #nil
|
|
121
|
+
result = @sd.get
|
|
122
|
+
|
|
123
|
+
assert_match(
|
|
124
|
+
/'potato'/,
|
|
125
|
+
result,
|
|
126
|
+
'Set#get should include $(foo.baz) whenever the action :baz is permitted'
|
|
127
|
+
)
|
|
128
|
+
assert_equal(
|
|
129
|
+
<<'_html',
|
|
130
|
+
<ul id="main" class="app-pipco">
|
|
131
|
+
<li id="main-20091123_0001">
|
|
132
|
+
'CZ'(action=read, p_action=read): 'oops'(action=read, p_action=read)
|
|
133
|
+
<ul id="main-20091123_0001-files" class="app-attachment">
|
|
134
|
+
<li id="main-20091123_0001-files-20091123_0001">'carl1.jpg'(action=read, p_action=read)</li>
|
|
135
|
+
<li id="main-20091123_0001-files-20091123_0002">'carl2.jpg'(action=read, p_action=read)</li>
|
|
136
|
+
</ul>
|
|
137
|
+
<ul id="main-20091123_0001-replies" class="app-pipco">
|
|
138
|
+
<li id="main-20091123_0001-replies-20091125_0001"><a href="/20091123_0001/replies/20091125/1/update.html">'howdy.'(action=read, p_action=read)</a></li>
|
|
139
|
+
</ul>
|
|
140
|
+
'potato'
|
|
141
|
+
</li>
|
|
142
|
+
<li id="main-20091123_0002">
|
|
143
|
+
'RE'(action=read, p_action=read): 'wee'(action=read, p_action=read)
|
|
144
|
+
<ul id="main-20091123_0002-files" class="app-attachment">
|
|
145
|
+
<li id="main-20091123_0002-files-20091123_0001">'roy.png'(action=read, p_action=read)</li>
|
|
146
|
+
</ul>
|
|
147
|
+
<ul id="main-20091123_0002-replies" class="app-pipco">
|
|
148
|
+
<li id="main-20091123_0002-replies-20091125_0001"><a href="/20091123_0002/replies/20091125/1/update.html">'ho ho.'(action=read, p_action=read)</a></li>
|
|
149
|
+
<li id="main-20091123_0002-replies-20091125_0002"><a href="/20091123_0002/replies/20091125/2/update.html">'oops.'(action=read, p_action=read)</a></li>
|
|
150
|
+
</ul>
|
|
151
|
+
'potato'
|
|
152
|
+
</li>
|
|
153
|
+
</ul>
|
|
154
|
+
_html
|
|
155
|
+
result,
|
|
156
|
+
'Set#get should work recursively as a part of the complex'
|
|
157
|
+
)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def test_get_with_parent_action
|
|
161
|
+
Bike.client = 'root'
|
|
162
|
+
result = @sd.get(:action => :update)
|
|
163
|
+
|
|
164
|
+
assert_match(
|
|
165
|
+
/id="main-20091123_0001-files"/,
|
|
166
|
+
result,
|
|
167
|
+
'Set::Dynamic#get(:action => :update) should include child attachments'
|
|
168
|
+
)
|
|
169
|
+
assert_no_match(
|
|
170
|
+
/id="main-20091123_0001-replies"/,
|
|
171
|
+
result,
|
|
172
|
+
'Set::Dynamic#get(:action => :update) should not include child apps'
|
|
173
|
+
)
|
|
174
|
+
assert_no_match(
|
|
175
|
+
/'potato'/,
|
|
176
|
+
result,
|
|
177
|
+
'Set::Dynamic#get(:action => :update) should not include any value of child apps'
|
|
178
|
+
)
|
|
179
|
+
assert_no_match(
|
|
180
|
+
/<form.+<form/m,
|
|
181
|
+
result,
|
|
182
|
+
'Set::Dynamic#get(:action => :update) should not return nested forms'
|
|
183
|
+
)
|
|
184
|
+
assert_equal(
|
|
185
|
+
<<'_html',
|
|
186
|
+
<ul id="main" class="app-pipco">
|
|
187
|
+
<li id="main-20091123_0001">
|
|
188
|
+
'CZ'(action=update, p_action=update): 'oops'(action=update, p_action=update)
|
|
189
|
+
<ul id="main-20091123_0001-files" class="app-attachment">
|
|
190
|
+
<li id="main-20091123_0001-files-20091123_0001">'carl1.jpg'(action=update, p_action=update)[d]</li>
|
|
191
|
+
<li id="main-20091123_0001-files-20091123_0002">'carl2.jpg'(action=update, p_action=update)[d]</li>
|
|
192
|
+
<li id="main-20091123_0001-files-_001">'foo.jpg'(action=create, p_action=create)[c]</li>
|
|
193
|
+
</ul>
|
|
194
|
+
</li>
|
|
195
|
+
<li id="main-20091123_0002">
|
|
196
|
+
'RE'(action=update, p_action=update): 'wee'(action=update, p_action=update)
|
|
197
|
+
<ul id="main-20091123_0002-files" class="app-attachment">
|
|
198
|
+
<li id="main-20091123_0002-files-20091123_0001">'roy.png'(action=update, p_action=update)[d]</li>
|
|
199
|
+
<li id="main-20091123_0002-files-_001">'foo.jpg'(action=create, p_action=create)[c]</li>
|
|
200
|
+
</ul>
|
|
201
|
+
</li>
|
|
202
|
+
</ul>
|
|
203
|
+
[main-update]
|
|
204
|
+
_html
|
|
205
|
+
result,
|
|
206
|
+
'Set#get should distribute the action to its items'
|
|
207
|
+
)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def test_get_with_partial_permission
|
|
211
|
+
Bike.client = 'carl' # can edit only his own item
|
|
212
|
+
|
|
213
|
+
assert_raise(
|
|
214
|
+
Bike::Error::Forbidden,
|
|
215
|
+
'Field#get should raise Error::Forbidden when an action is given but forbidden'
|
|
216
|
+
) {
|
|
217
|
+
@sd.get(:action => :update, :conds => {:id => '20091123_0002'})
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
@sd.item('20091123_0002', 'comment')[:owner] = 'carl' # enclave in roy's item
|
|
221
|
+
|
|
222
|
+
assert_raise(
|
|
223
|
+
Bike::Error::Forbidden,
|
|
224
|
+
'Field#get should not allow partially permitted get'
|
|
225
|
+
) {
|
|
226
|
+
@sd.get(:action => :update, :conds => {:id => '20091123_0002'})
|
|
227
|
+
}
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def test_get_with_partial_action
|
|
231
|
+
Bike.client = 'root'
|
|
232
|
+
|
|
233
|
+
Bike.current[:base] = @sd.item('20091123_0002', 'replies')
|
|
234
|
+
Bike.base[:tid] = '123.45'
|
|
235
|
+
|
|
236
|
+
result = @sd.get(
|
|
237
|
+
'20091123_0002' => {
|
|
238
|
+
'replies' => {
|
|
239
|
+
:action => :update,
|
|
240
|
+
:conds => {:id => '20091125_0002'},
|
|
241
|
+
},
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
assert_equal(
|
|
245
|
+
<<_html,
|
|
246
|
+
<ul id="main" class="app-pipco">
|
|
247
|
+
<li id="main-20091123_0001">
|
|
248
|
+
'CZ'(action=read, p_action=read): 'oops'(action=read, p_action=read)
|
|
249
|
+
<ul id="main-20091123_0001-files" class="app-attachment">
|
|
250
|
+
<li id="main-20091123_0001-files-20091123_0001">'carl1.jpg'(action=read, p_action=read)</li>
|
|
251
|
+
<li id="main-20091123_0001-files-20091123_0002">'carl2.jpg'(action=read, p_action=read)</li>
|
|
252
|
+
</ul>
|
|
253
|
+
<ul id="main-20091123_0001-replies" class="app-pipco">
|
|
254
|
+
<li id="main-20091123_0001-replies-20091125_0001"><a href="/20091123_0001/replies/20091125/1/update.html">'howdy.'(action=read, p_action=read)</a></li>
|
|
255
|
+
</ul>
|
|
256
|
+
'potato'
|
|
257
|
+
</li>
|
|
258
|
+
<li id="main-20091123_0002">
|
|
259
|
+
'RE'(action=read, p_action=read): 'wee'(action=read, p_action=read)
|
|
260
|
+
<ul id="main-20091123_0002-files" class="app-attachment">
|
|
261
|
+
<li id="main-20091123_0002-files-20091123_0001">'roy.png'(action=read, p_action=read)</li>
|
|
262
|
+
</ul>
|
|
263
|
+
<form id="form_main-20091123_0002-replies" method="post" enctype="multipart/form-data" action="/20091123_0002/replies/123.45/update.html">
|
|
264
|
+
<input name="_token" type="hidden" value="#{Bike.token}" />
|
|
265
|
+
<ul id="main-20091123_0002-replies" class="app-pipco">
|
|
266
|
+
<li id="main-20091123_0002-replies-20091125_0002"><a>'oops.'(action=update, p_action=update)</a></li>
|
|
267
|
+
</ul>
|
|
268
|
+
[replies-update]
|
|
269
|
+
</form>
|
|
270
|
+
'potato'
|
|
271
|
+
</li>
|
|
272
|
+
</ul>
|
|
273
|
+
_html
|
|
274
|
+
result,
|
|
275
|
+
'Field#get should be able to handle a partial action'
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
result = @sd.get(
|
|
279
|
+
:conds => {:id => '20091123_0002'},
|
|
280
|
+
'20091123_0002' => {
|
|
281
|
+
'replies' => {
|
|
282
|
+
:action => :update,
|
|
283
|
+
:conds => {:id => '20091125_0002'},
|
|
284
|
+
},
|
|
285
|
+
}
|
|
286
|
+
)
|
|
287
|
+
assert_equal(
|
|
288
|
+
<<_html,
|
|
289
|
+
<ul id="main" class="app-pipco">
|
|
290
|
+
<li id="main-20091123_0002">
|
|
291
|
+
'RE'(action=read, p_action=read): 'wee'(action=read, p_action=read)
|
|
292
|
+
<ul id="main-20091123_0002-files" class="app-attachment">
|
|
293
|
+
<li id="main-20091123_0002-files-20091123_0001">'roy.png'(action=read, p_action=read)</li>
|
|
294
|
+
</ul>
|
|
295
|
+
<form id="form_main-20091123_0002-replies" method="post" enctype="multipart/form-data" action="/20091123_0002/replies/123.45/update.html">
|
|
296
|
+
<input name="_token" type="hidden" value="#{Bike.token}" />
|
|
297
|
+
<ul id="main-20091123_0002-replies" class="app-pipco">
|
|
298
|
+
<li id="main-20091123_0002-replies-20091125_0002"><a>'oops.'(action=update, p_action=update)</a></li>
|
|
299
|
+
</ul>
|
|
300
|
+
[replies-update]
|
|
301
|
+
</form>
|
|
302
|
+
'potato'
|
|
303
|
+
</li>
|
|
304
|
+
</ul>
|
|
305
|
+
_html
|
|
306
|
+
result,
|
|
307
|
+
'Field#get should be able to handle a partial action'
|
|
308
|
+
)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def test_get_partial_forbidden
|
|
312
|
+
Bike.client = 'carl'
|
|
313
|
+
assert_match(
|
|
314
|
+
/\(action=update/,
|
|
315
|
+
@sd.item('20091123_0001', 'files').get(:action => :update)
|
|
316
|
+
)
|
|
317
|
+
assert_match(
|
|
318
|
+
/\(action=update/,
|
|
319
|
+
@sd.item('20091123_0001', 'files', '20091123_0001').get(:action => :update)
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
@sd.instance_variable_set(:@item_object, {}) # remove item('_001')
|
|
323
|
+
|
|
324
|
+
Bike.client = nil
|
|
325
|
+
assert_raise(
|
|
326
|
+
Bike::Error::Forbidden,
|
|
327
|
+
'Field#get should not show an inner attachment when the parent is forbidden'
|
|
328
|
+
) {
|
|
329
|
+
@sd.item('20091123_0001', 'files').get(:action => :update)
|
|
330
|
+
}
|
|
331
|
+
assert_raise(
|
|
332
|
+
Bike::Error::Forbidden,
|
|
333
|
+
'Field#get should not show an inner attachment when the parent is forbidden'
|
|
334
|
+
) {
|
|
335
|
+
@sd.item('20091123_0001', 'files', '20091123_0001').get(:action => :update)
|
|
336
|
+
}
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def test_post_partial
|
|
340
|
+
Bike.client = 'don'
|
|
341
|
+
original_val = YAML.load @sd.val.to_yaml
|
|
342
|
+
@sd.update(
|
|
343
|
+
'20091123_0002' => {
|
|
344
|
+
'replies' => {
|
|
345
|
+
'_0001' => {'reply' => 'yum.'},
|
|
346
|
+
},
|
|
347
|
+
}
|
|
348
|
+
)
|
|
349
|
+
assert_equal(
|
|
350
|
+
original_val,
|
|
351
|
+
@sd.val,
|
|
352
|
+
'Field#val should not change before the commit'
|
|
353
|
+
)
|
|
354
|
+
@sd.commit
|
|
355
|
+
assert_not_equal(
|
|
356
|
+
original_val,
|
|
357
|
+
@sd.val,
|
|
358
|
+
'Field#val should change after the commit'
|
|
359
|
+
)
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
def test_post_attachment_forbidden
|
|
363
|
+
Bike.client = nil
|
|
364
|
+
assert_raise(
|
|
365
|
+
Bike::Error::Forbidden,
|
|
366
|
+
'Field#post to an inner attachment w/o the perm of the parent should be forbidden'
|
|
367
|
+
) {
|
|
368
|
+
@sd.update(
|
|
369
|
+
'20091123_0002' => {
|
|
370
|
+
'files' => {
|
|
371
|
+
'_0001' => {'file' => 'evil.jpg'},
|
|
372
|
+
},
|
|
373
|
+
}
|
|
374
|
+
)
|
|
375
|
+
}
|
|
376
|
+
assert_raise(
|
|
377
|
+
Bike::Error::Forbidden,
|
|
378
|
+
'Field#post to an inner attachment w/o the perm of the parent should be forbidden'
|
|
379
|
+
) {
|
|
380
|
+
@sd.update(
|
|
381
|
+
'20091123_0002' => {
|
|
382
|
+
'files' => {
|
|
383
|
+
'20091123_0001' => {'file' => 'evil.png'},
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
)
|
|
387
|
+
}
|
|
388
|
+
assert_raise(
|
|
389
|
+
Bike::Error::Forbidden,
|
|
390
|
+
'Field#post to an inner attachment w/o the perm of the parent should be forbidden'
|
|
391
|
+
) {
|
|
392
|
+
@sd.item('20091123_0002', 'files', '20091123_0001').update('file' => 'evil.gif')
|
|
393
|
+
}
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def test_commit_partial
|
|
397
|
+
Bike.client = 'don'
|
|
398
|
+
@sd.update(
|
|
399
|
+
'20091123_0002' => {
|
|
400
|
+
'replies' => {
|
|
401
|
+
'_0001' => {'reply' => 'yum.'},
|
|
402
|
+
},
|
|
403
|
+
}
|
|
404
|
+
)
|
|
405
|
+
orig_val = @sd.val('20091123_0002', 'replies').dup
|
|
406
|
+
|
|
407
|
+
@sd.commit :temp
|
|
408
|
+
new_val = @sd.val('20091123_0002', 'replies').dup
|
|
409
|
+
assert_equal(
|
|
410
|
+
orig_val.size + 1,
|
|
411
|
+
new_val.size,
|
|
412
|
+
'Field#val should change after the commit :temp'
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
new_id = new_val.keys.find {|id| new_val[id] == {'_owner' => 'don', 'reply' => 'yum.'} }
|
|
416
|
+
@sd.update(
|
|
417
|
+
'20091123_0002' => {
|
|
418
|
+
'replies' => {
|
|
419
|
+
new_id => {
|
|
420
|
+
:action => :delete,
|
|
421
|
+
'reply' => 'yum.',
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
}
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
@sd.commit :temp
|
|
428
|
+
new_val = @sd.val('20091123_0002', 'replies').dup
|
|
429
|
+
assert_equal(
|
|
430
|
+
orig_val,
|
|
431
|
+
new_val,
|
|
432
|
+
'Field#val should change after the commit :temp'
|
|
433
|
+
)
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
def test_post_mixed
|
|
437
|
+
Bike.client = 'don'
|
|
438
|
+
|
|
439
|
+
# create a sub-item on the pending item
|
|
440
|
+
@sd.update(
|
|
441
|
+
'_1234' => {
|
|
442
|
+
'_owner' => 'don',
|
|
443
|
+
'replies' => {
|
|
444
|
+
'_0001' => {
|
|
445
|
+
'_owner' => 'don',
|
|
446
|
+
'reply' => 'yum.',
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
}
|
|
450
|
+
)
|
|
451
|
+
orig_val = @sd.val('_1234', 'replies').dup
|
|
452
|
+
assert_equal(
|
|
453
|
+
{},
|
|
454
|
+
orig_val,
|
|
455
|
+
'Field#val should change after the commit :temp'
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
orig_storage = @sd.storage
|
|
459
|
+
@sd.instance_variable_set(:@storage, nil) # pretend persistent
|
|
460
|
+
@sd.commit :temp
|
|
461
|
+
@sd.instance_variable_set(:@storage, orig_storage)
|
|
462
|
+
|
|
463
|
+
new_val = @sd.val('_1234', 'replies').dup
|
|
464
|
+
assert_equal(
|
|
465
|
+
{'_owner' => 'don', 'reply' => 'yum.'},
|
|
466
|
+
new_val.values.first,
|
|
467
|
+
'Field#val should change after the commit :temp'
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
# delete the sub-item
|
|
471
|
+
new_id = new_val.keys.find {|id| new_val[id] == {'_owner' => 'don', 'reply' => 'yum.'} }
|
|
472
|
+
@sd.update(
|
|
473
|
+
'_1234' => {
|
|
474
|
+
'replies' => {
|
|
475
|
+
new_id => {
|
|
476
|
+
:action => :delete,
|
|
477
|
+
'_owner' => 'don',
|
|
478
|
+
'reply' => 'yum.',
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
}
|
|
482
|
+
)
|
|
483
|
+
assert_equal(
|
|
484
|
+
:delete,
|
|
485
|
+
@sd.item('_1234', 'replies', new_id).action,
|
|
486
|
+
'Set::Dynamic#post should not overwrite the action of descendant'
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
orig_storage = @sd.storage
|
|
490
|
+
@sd.instance_variable_set(:@storage, nil) # pretend persistent
|
|
491
|
+
@sd.commit :temp
|
|
492
|
+
@sd.instance_variable_set(:@storage, orig_storage)
|
|
493
|
+
|
|
494
|
+
new_val = @sd.val('_1234', 'replies').dup
|
|
495
|
+
assert_equal(
|
|
496
|
+
{},
|
|
497
|
+
new_val,
|
|
498
|
+
'Field#val should change after the commit :temp'
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
# create an another sub-item
|
|
502
|
+
@sd.update(
|
|
503
|
+
'_1234' => {
|
|
504
|
+
'_owner' => 'don',
|
|
505
|
+
'replies' => {
|
|
506
|
+
'_0001' => {
|
|
507
|
+
'_owner' => 'don',
|
|
508
|
+
'reply' => 'yuck.',
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
}
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
orig_storage = @sd.storage
|
|
515
|
+
@sd.instance_variable_set(:@storage, nil) # pretend persistent
|
|
516
|
+
@sd.commit :temp
|
|
517
|
+
@sd.instance_variable_set(:@storage, orig_storage)
|
|
518
|
+
|
|
519
|
+
new_val = @sd.val('_1234', 'replies').dup
|
|
520
|
+
assert_equal(
|
|
521
|
+
{'_owner' => 'don', 'reply' => 'yuck.'},
|
|
522
|
+
new_val.values.first,
|
|
523
|
+
'Field#val should change after the commit :temp'
|
|
524
|
+
)
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
end
|