zena 1.0.0.rc2 → 1.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (274) hide show
  1. data/History.txt +23 -0
  2. data/README.rdoc +1 -1
  3. data/app/controllers/columns_controller.rb +3 -31
  4. data/app/controllers/comments_controller.rb +8 -3
  5. data/app/controllers/data_entries_controller.rb +1 -1
  6. data/app/controllers/documents_controller.rb +2 -2
  7. data/app/controllers/nodes_controller.rb +29 -12
  8. data/app/controllers/relations_controller.rb +2 -2
  9. data/app/controllers/sites_controller.rb +1 -1
  10. data/app/controllers/user_sessions_controller.rb +6 -3
  11. data/app/controllers/users_controller.rb +18 -16
  12. data/app/controllers/versions_controller.rb +20 -18
  13. data/app/controllers/virtual_classes_controller.rb +103 -17
  14. data/app/helpers/users_helper.rb +1 -1
  15. data/app/models/column.rb +19 -50
  16. data/app/models/comment.rb +2 -1
  17. data/app/models/node.rb +45 -22
  18. data/app/models/relation.rb +13 -0
  19. data/app/models/relation_proxy.rb +3 -2
  20. data/app/models/role.rb +213 -4
  21. data/app/models/site.rb +18 -11
  22. data/app/models/template.rb +37 -35
  23. data/app/models/version.rb +1 -1
  24. data/app/models/virtual_class.rb +154 -86
  25. data/app/views/columns/_li.html.erb +1 -1
  26. data/app/views/columns/index.html.erb +1 -9
  27. data/app/views/comments/index.rhtml +10 -8
  28. data/app/views/documents/_crop.rhtml +5 -6
  29. data/app/views/documents/crop_form.rjs +3 -2
  30. data/app/views/groups/index.rhtml +1 -1
  31. data/app/views/iformats/index.rhtml +1 -1
  32. data/app/views/nodes/_import_results.rhtml +1 -1
  33. data/app/views/nodes/_parent.rhtml +1 -2
  34. data/app/views/nodes/update.rjs +3 -4
  35. data/app/views/relations/index.erb +1 -1
  36. data/app/views/sites/index.erb +1 -1
  37. data/app/views/templates/drive_tabs/_drive.rhtml +0 -2
  38. data/app/views/templates/edit_tabs/_image.rhtml +1 -1
  39. data/app/views/templates/edit_tabs/_title.rhtml +0 -6
  40. data/app/views/users/index.rhtml +1 -1
  41. data/app/views/users/preferences.html.erb +2 -2
  42. data/app/views/versions/backup.rjs +1 -1
  43. data/app/views/versions/custom_tab.rhtml +9 -4
  44. data/app/views/versions/destroy.rjs +2 -2
  45. data/app/views/versions/update.rjs +2 -9
  46. data/app/views/virtual_classes/_form.erb +3 -2
  47. data/app/views/virtual_classes/import_prepare.html.erb +13 -0
  48. data/app/views/virtual_classes/index.erb +28 -8
  49. data/app/views/zafu/default/Node-+adminLayout.zafu +1 -13
  50. data/app/views/zafu/default/Node-+login.zafu +1 -0
  51. data/app/views/zafu/default/Node-+notFound.zafu +1 -1
  52. data/app/views/zafu/default/Node-+popupLayout.zafu +1 -2
  53. data/app/views/zafu/default/Node-+search.zafu +1 -1
  54. data/app/views/zafu/default/Node-admin.zafu +205 -0
  55. data/app/views/zafu/default/Node.zafu +11 -11
  56. data/bricks/captcha/lib/bricks/captcha.rb +3 -2
  57. data/bricks/mongrel/zena/init.rb +2 -1
  58. data/bricks/pdf/README +5 -5
  59. data/bricks/pdf/lib/bricks/pdf/engine/prince.rb +2 -2
  60. data/bricks/pdf/lib/bricks/pdf/engine/xhtml2pdf.rb +2 -2
  61. data/bricks/pdf/lib/bricks/pdf/install.rb +5 -5
  62. data/bricks/pdf/lib/bricks/pdf.rb +11 -11
  63. data/bricks/pdf/test/engines/test_prince.rb +4 -4
  64. data/bricks/pdf/test/engines/test_xhtml2pdf.rb +4 -4
  65. data/bricks/pdf/test/shoulda_macros/shoulda_pdf.rb +2 -2
  66. data/bricks/pdf/zena/init.rb +2 -2
  67. data/bricks/pdf/zena/tasks.rb +2 -2
  68. data/bricks/sphinx/lib/bricks/sphinx.rb +6 -2
  69. data/bricks/sphinx/zena/{sphinx.yml → sphinx.yml.erb} +2 -2
  70. data/bricks/sphinx/zena/tasks.rb +28 -2
  71. data/bricks/tags/lib/bricks/tags.rb +16 -1
  72. data/bricks/tags/zena/test/unit/tags_test.rb +15 -0
  73. data/bricks/tags/zena/test/zafu/tags.yml +5 -1
  74. data/bricks/worker/lib/bricks/worker.rb +39 -0
  75. data/bricks/worker/zena/deploy.rb +0 -2
  76. data/bricks/worker/zena/init.rb +1 -0
  77. data/bricks/worker/zena/test/sites/zena/delayed_jobs.yml +16 -0
  78. data/bricks/worker/zena/test/zafu/worker.yml +8 -0
  79. data/bricks/zena/zena/migrate/01_base.rb +36 -60
  80. data/bricks/zena/zena/migrate/02_zerox1_schema.rb +388 -0
  81. data/bricks/zena/zena/migrate/03_zerox1_data.rb +380 -0
  82. data/bricks/zena/zena/migrate/20110315161158_add_reverse_scope_to_roles.rb +9 -0
  83. data/config/database_example.yml +1 -1
  84. data/config/environment.rb +1 -1
  85. data/config/gems.yml +17 -14
  86. data/db/init/base/skins/default/Node-+index.zafu +8 -1
  87. data/db/init/base/skins/default/Node-+login.zafu +1 -0
  88. data/db/init/base/skins/default/Node-+popupLayout.zafu +1 -2
  89. data/db/init/base/skins/default/Node-+search.zafu +2 -2
  90. data/db/init/base/skins/default/Node.zafu +9 -9
  91. data/db/init/base/skins/default/{favicon.png → img/favicon.png} +0 -0
  92. data/db/init/base/skins/default/{style.css → img/style.css} +0 -0
  93. data/db/init/base/skins/default/img/translations.yml +11 -0
  94. data/db/init/base/skins/default/notes.zafu +7 -9
  95. data/doc/zafu_changes.yml +12 -0
  96. data/lib/bricks/loader.rb +38 -15
  97. data/lib/tasks/zena.rake +74 -24
  98. data/lib/zena/acts/enrollable.rb +4 -1
  99. data/lib/zena/acts/secure.rb +2 -48
  100. data/lib/zena/acts/serializable.rb +13 -1
  101. data/lib/zena/app.rb +9 -0
  102. data/lib/zena/code_syntax.rb +154 -151
  103. data/lib/zena/console.rb +141 -0
  104. data/lib/zena/controller/test_case.rb +1 -1
  105. data/lib/zena/db_helper/abstract_db.rb +17 -5
  106. data/lib/zena/db_helper/mysql.rb +14 -12
  107. data/lib/zena/db_helper/postgresql.rb +1 -2
  108. data/lib/zena/db_helper/sqlite3.rb +6 -6
  109. data/lib/zena/deploy/awstats.conf.rhtml +1 -1
  110. data/lib/zena/deploy/httpd.rhtml +6 -1
  111. data/lib/zena/deploy/vhost.rhtml +9 -1
  112. data/lib/zena/deploy.rb +12 -7
  113. data/lib/zena/foxy_parser.rb +3 -1
  114. data/lib/zena/info.rb +1 -1
  115. data/lib/zena/parser/zafu_tags.rb +1 -0
  116. data/lib/zena/parser/zazen_rules.rb +1 -1
  117. data/lib/zena/remote/node.rb +15 -3
  118. data/lib/zena/remote/serializable_array.rb +19 -0
  119. data/lib/zena/remote.rb +1 -0
  120. data/lib/zena/routes.rb +7 -2
  121. data/lib/zena/site_worker.rb +11 -1
  122. data/lib/zena/unit/test_case.rb +68 -0
  123. data/lib/zena/use/action.rb +6 -2
  124. data/lib/zena/use/ajax.rb +127 -53
  125. data/lib/zena/use/ancestry.rb +11 -8
  126. data/lib/zena/use/calendar.rb +265 -129
  127. data/lib/zena/use/conditional.rb +1 -1
  128. data/lib/zena/use/context.rb +5 -5
  129. data/lib/zena/use/dates.rb +172 -60
  130. data/lib/zena/use/display.rb +70 -39
  131. data/lib/zena/use/error_rendering.rb +1 -3
  132. data/lib/zena/use/field_index.rb +4 -1
  133. data/lib/zena/use/forms.rb +94 -72
  134. data/lib/zena/use/fulltext.rb +16 -24
  135. data/lib/zena/use/html_tags.rb +20 -12
  136. data/lib/zena/use/i18n.rb +37 -37
  137. data/lib/zena/use/image_builder.rb +8 -1
  138. data/lib/zena/use/ml_index.rb +16 -16
  139. data/lib/zena/use/prop_eval.rb +10 -5
  140. data/lib/zena/use/query_builder.rb +55 -23
  141. data/lib/zena/use/query_node.rb +51 -25
  142. data/lib/zena/use/refactor.rb +2 -28
  143. data/lib/zena/use/relations.rb +1 -1
  144. data/lib/zena/use/rendering.rb +29 -0
  145. data/lib/zena/use/scope_index.rb +75 -14
  146. data/lib/zena/use/search.rb +5 -10
  147. data/lib/zena/use/test_helper.rb +2 -2
  148. data/lib/zena/use/urls.rb +125 -104
  149. data/lib/zena/use/workflow.rb +2 -1
  150. data/lib/zena/use/zafu_attributes.rb +2 -2
  151. data/lib/zena/use/zafu_safe_definitions.rb +20 -0
  152. data/lib/zena/use/zafu_templates.rb +20 -6
  153. data/lib/zena/use/zazen.rb +31 -20
  154. data/lib/zena/view/test_case.rb +5 -0
  155. data/lib/zena/zafu_compiler.rb +24 -2
  156. data/lib/zena.rb +12 -6
  157. data/locale/de/LC_MESSAGES/zena.mo +0 -0
  158. data/locale/de/zena.po +1345 -1164
  159. data/locale/en/LC_MESSAGES/zena.mo +0 -0
  160. data/locale/en/zena.po +1275 -1129
  161. data/locale/fr/LC_MESSAGES/zena.mo +0 -0
  162. data/locale/fr/zena.mo +0 -0
  163. data/locale/fr/zena.po +1617 -1441
  164. data/locale/log.txt +9 -0
  165. data/locale/zena.pot +957 -748
  166. data/public/javascripts/prototype.js +1 -1
  167. data/public/javascripts/zena.js +99 -44
  168. data/public/stylesheets/admin.css +6 -4
  169. data/public/stylesheets/backend.css +71 -0
  170. data/public/stylesheets/calendar.css +24 -25
  171. data/public/stylesheets/code.css +11 -6
  172. data/public/stylesheets/comment.css +2 -1
  173. data/public/stylesheets/popup.css +7 -8
  174. data/test/custom_queries/complex.host.yml +15 -1
  175. data/test/fixtures/files/Node-test.zafu +29 -28
  176. data/test/fixtures/files/translations_de.yml +12 -1
  177. data/test/fixtures/files/translations_fr.yml +12 -1
  178. data/test/functional/comments_controller_test.rb +9 -0
  179. data/test/functional/iformats_controller_test.rb +1 -1
  180. data/test/functional/nodes_controller_test.rb +124 -35
  181. data/test/functional/users_controller_test.rb +132 -3
  182. data/test/functional/virtual_classes_controller_test.rb +75 -4
  183. data/test/integration/navigation_test.rb +51 -9
  184. data/test/integration/query_node/basic.yml +19 -7
  185. data/test/integration/query_node/complex.yml +1 -1
  186. data/test/integration/query_node/dates.yml +27 -1
  187. data/test/integration/query_node/filters.yml +1 -1
  188. data/test/integration/query_node/relations.yml +13 -4
  189. data/test/integration/query_node_test.rb +4 -0
  190. data/test/integration/xml_api_test.rb +6 -1
  191. data/test/integration/zafu_compiler/action.yml +3 -3
  192. data/test/integration/zafu_compiler/ajax.yml +103 -22
  193. data/test/integration/zafu_compiler/basic.yml +0 -52
  194. data/test/integration/zafu_compiler/calendar.yml +44 -20
  195. data/test/integration/zafu_compiler/comments.yml +53 -0
  196. data/test/integration/zafu_compiler/complex.yml +11 -11
  197. data/test/integration/zafu_compiler/complex_ok.yml +16 -3
  198. data/test/integration/zafu_compiler/conditional.yml +15 -5
  199. data/test/integration/zafu_compiler/context.yml +9 -0
  200. data/test/integration/zafu_compiler/dates.yml +43 -15
  201. data/test/integration/zafu_compiler/display.yml +60 -6
  202. data/test/integration/zafu_compiler/errors.yml +6 -2
  203. data/test/integration/zafu_compiler/forms.yml +45 -6
  204. data/test/integration/zafu_compiler/i18n.yml +8 -1
  205. data/test/integration/zafu_compiler/meta.yml +38 -0
  206. data/test/integration/zafu_compiler/query.yml +43 -4
  207. data/test/integration/zafu_compiler/relations.yml +26 -33
  208. data/test/integration/zafu_compiler/rubyless.yml +10 -0
  209. data/test/integration/zafu_compiler/safe_definitions.yml +21 -1
  210. data/test/integration/zafu_compiler/urls.yml +75 -5
  211. data/test/integration/zafu_compiler/version.yml +2 -2
  212. data/test/integration/zafu_compiler/zafu_attributes.yml +5 -1
  213. data/test/integration/zafu_compiler/zazen.yml +14 -6
  214. data/test/integration/zafu_compiler_test.rb +5 -1
  215. data/test/sites/complex/columns.yml +5 -0
  216. data/test/sites/complex/roles.yml +4 -0
  217. data/test/sites/zena/nodes.yml +13 -2
  218. data/test/sites/zena/roles.yml +13 -5
  219. data/test/sites/zena/versions.yml +27 -9
  220. data/test/unit/column_test.rb +51 -5
  221. data/test/unit/iformat_test.rb +2 -2
  222. data/test/unit/node_test.rb +29 -17
  223. data/test/unit/note_test.rb +1 -1
  224. data/test/unit/relation_proxy_test.rb +4 -5
  225. data/test/unit/relation_test.rb +16 -0
  226. data/test/unit/remote_test.rb +2 -2
  227. data/test/unit/role_test.rb +292 -4
  228. data/test/unit/site_test.rb +12 -0
  229. data/test/unit/template_test.rb +1 -1
  230. data/test/unit/text_document_test.rb +1 -1
  231. data/test/unit/virtual_class_test.rb +200 -83
  232. data/test/unit/zena/acts/enrollable_test.rb +26 -31
  233. data/test/unit/zena/use/calendar_test.rb +90 -37
  234. data/test/unit/zena/use/field_index_test.rb +28 -0
  235. data/test/unit/zena/use/html_tags_test.rb +7 -3
  236. data/test/unit/zena/use/ml_index_test.rb +2 -16
  237. data/test/unit/zena/use/nested_attributes_alias_view_test.rb +2 -2
  238. data/test/unit/zena/use/prop_eval_test.rb +50 -8
  239. data/test/unit/zena/use/query_node_test.rb +11 -0
  240. data/test/unit/zena/use/rendering_test.rb +72 -0
  241. data/test/unit/zena/use/scope_index_test.rb +37 -2
  242. data/test/unit/zena/use/urls_test.rb +10 -0
  243. data/test/unit/zena/use/zazen_test.rb +3 -3
  244. data/vendor/plugins/gettext_i18n_rails/Gemfile +11 -0
  245. data/vendor/plugins/gettext_i18n_rails/Gemfile.lock +92 -0
  246. data/vendor/plugins/gettext_i18n_rails/Rakefile +12 -17
  247. data/vendor/plugins/gettext_i18n_rails/Readme.md +215 -0
  248. data/vendor/plugins/gettext_i18n_rails/VERSION +1 -1
  249. data/vendor/plugins/gettext_i18n_rails/gettext_i18n_rails.gemspec +38 -34
  250. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/active_record.rb +1 -1
  251. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/backend.rb +30 -14
  252. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/haml_parser.rb +1 -1
  253. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/html_safe_translations.rb +29 -0
  254. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/i18n_hacks.rb +29 -1
  255. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/model_attributes_finder.rb +7 -1
  256. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/railtie.rb +10 -0
  257. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/ruby_gettext_extractor.rb +6 -2
  258. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/string_interpolate_fix.rb +20 -0
  259. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/tasks.rb +120 -0
  260. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails.rb +10 -3
  261. data/vendor/plugins/gettext_i18n_rails/lib/tasks/gettext_rails_i18n.rake +1 -74
  262. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/active_record_spec.rb +51 -20
  263. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/backend_spec.rb +12 -7
  264. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/string_interpolate_fix_spec.rb +32 -0
  265. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails_spec.rb +38 -1
  266. data/vendor/plugins/gettext_i18n_rails/spec/rails2/Gemfile +11 -0
  267. data/vendor/plugins/gettext_i18n_rails/spec/spec_helper.rb +1 -8
  268. data/zena.gemspec +2241 -2217
  269. metadata +123 -83
  270. data/.gitignore +0 -36
  271. data/app/views/nodes/_dates.rhtml +0 -13
  272. data/db/init/base/skins/default/Node-+adminLayout.zafu +0 -46
  273. data/db/init/base/skins/default/Node-tree.zafu +0 -19
  274. data/vendor/plugins/gettext_i18n_rails/README.markdown +0 -143
@@ -187,6 +187,85 @@ class VirtualClassTest < Zena::Unit::TestCase
187
187
  assert_equal 'NPU', vclass.kpath
188
188
  end
189
189
 
190
+ context 'Updating a VirtualClass' do
191
+ setup do
192
+ login(:lion)
193
+ end
194
+
195
+ subject do
196
+ roles(:Post)
197
+ end
198
+
199
+ should 'update kpaths in nodes' do
200
+ # kpath NNP => NO
201
+ assert subject.update_attributes(:superclass => 'Page')
202
+ assert_equal 'NPO', subject.kpath
203
+ n = nodes(:opening)
204
+ assert_equal 'NPO', n.kpath
205
+ end
206
+
207
+ context 'with a related template' do
208
+ setup do
209
+ @template = secure(Template) { Template.create(:parent_id => nodes_id(:default), :title => 'Post-foobar.zafu') }
210
+ assert !@template.new_record?
211
+ end
212
+
213
+ should 'update kpaths in templates' do
214
+ # kpath NNP => NO
215
+ assert subject.update_attributes(:superclass => 'Page')
216
+ assert_equal 'NPO', subject.kpath
217
+ t = secure(Template) { Template.find(@template) }
218
+ assert_equal 'NPO', t.tkpath
219
+ idx = IdxTemplate.first(:conditions => {:node_id => t.id})
220
+ assert_equal 'NPO', idx.tkpath
221
+ end
222
+
223
+ should 'rename templates' do
224
+ # kpath NNP => NO
225
+ assert subject.update_attributes(:name => 'Fast')
226
+ assert_equal 'NNF', subject.kpath
227
+ t = secure(Template) { Template.find(@template) }
228
+ assert_equal 'NNF', t.tkpath
229
+ assert_equal 'Fast-foobar', t.title
230
+ idx = IdxTemplate.first(:conditions => {:node_id => t.id})
231
+ assert_equal 'NNF', idx.tkpath
232
+ end
233
+ end # with a related template
234
+
235
+ context 'with sub vclasses' do
236
+ setup do
237
+ @sub = secure(VirtualClass) { VirtualClass.create(:superclass => subject, :name => 'Dog') }
238
+ assert !@sub.new_record?
239
+ end
240
+
241
+ should 'update kpaths in sub vclass' do
242
+ # kpath NNP => NO
243
+ assert subject.update_attributes(:superclass => 'Page')
244
+ assert_equal 'NPO', subject.kpath
245
+ sub = VirtualClass.find(@sub)
246
+ assert_equal 'NPOD', sub.kpath
247
+ end
248
+ end # with a related template
249
+
250
+
251
+ context 'with linked role' do
252
+ setup do
253
+ @role = ::Role.create('name' => 'Foobar', 'superclass' => 'Post')
254
+ assert !@role.new_record?
255
+ assert_equal 'NNP', @role.kpath
256
+ end
257
+
258
+ should 'update linked role kpath' do
259
+ # kpath NNP => NO
260
+ assert subject.update_attributes(:superclass => 'Page')
261
+ assert_equal 'NPO', subject.kpath
262
+ role = ::Role.find(@role)
263
+ assert_equal 'NPO', role.kpath
264
+ end
265
+ end # with linked role
266
+
267
+ end # Updating a VirtualClass
268
+
190
269
  def test_update_name
191
270
  # add a sub class
192
271
  login(:lion)
@@ -655,7 +734,7 @@ class VirtualClassTest < Zena::Unit::TestCase
655
734
  assert_equal %w{reference reference_for set_tag}, subject.map(&:other_role).sort
656
735
  end
657
736
  end # on relations
658
-
737
+
659
738
  context 'on new_instance' do
660
739
  subject do
661
740
  VirtualClass['Letter'].new_instance(
@@ -774,108 +853,146 @@ class VirtualClassTest < Zena::Unit::TestCase
774
853
  end # on a node
775
854
  end # A visitor with write access
776
855
 
777
- context 'importing virtual class definitions' do
856
+
857
+ context 'An admin' do
778
858
  setup do
779
859
  login(:lion)
780
860
  end
781
861
 
782
- context 'with an existing superclass' do
862
+ context 'exporting a virtual class' do
783
863
  setup do
784
- @data = {"Foo" => {'superclass' => 'Page'}}
864
+ login(:lion)
785
865
  end
786
866
 
787
- should 'create a new virtual class with the given name' do
788
- res = nil
789
- assert_difference('VirtualClass.count', 1) do
790
- res = secure(VirtualClass) { VirtualClass.import(@data) }
791
- end
792
- assert_equal 'Foo', res.first.name
793
- assert_equal 'new', res.first.import_result
794
- assert_equal 'NPF', res.first.kpath
867
+ subject do
868
+ VirtualClass['Post'].export
795
869
  end
796
870
 
797
- context 'and an existing virtual class' do
798
- setup do
799
- @data = {'Post' => {'superclass' => 'Note'}}
871
+ should 'export attributes' do
872
+ assert_equal('VirtualClass', subject['type'])
873
+ end
874
+
875
+ should 'export columns' do
876
+ assert_equal({
877
+ 'date' => {'index' => '.idx_datetime1', 'ptype' => 'datetime'},
878
+ }, subject['columns'])
879
+ end
880
+
881
+ should 'export relations' do
882
+ assert_equal({
883
+ 'blogs' => {'target_kpath'=>'NPP', 'source_role'=>'added_note'}
884
+ }, subject['relations'])
885
+ end
886
+
887
+ should 'export sub classes' do
888
+ assert_equal(%w{Contact}, VirtualClass['Reference'].export.keys.select{|k| k=~/\A[A-Z]/})
889
+ end
890
+ end # exporting a virtual class
891
+
892
+ context 'exporting a real class' do
893
+ subject do
894
+ VirtualClass['Page'].export
895
+ end
896
+
897
+ should 'export type as Class' do
898
+ assert_equal('Class', subject['type'])
899
+ end
900
+
901
+ should 'export sub classes' do
902
+ assert_equal(%w{Tracker Project Section Tag}, subject.keys.select{|k| k=~/\A[A-Z]/})
903
+ assert_equal('VirtualClass', subject['Tracker']['type'])
904
+ assert_equal('Class', subject['Project']['type'])
905
+ end
906
+
907
+ context 'with relations' do
908
+ subject do
909
+ VirtualClass['Project'].export
800
910
  end
801
911
 
802
- should 'update the virtual class if the superclass match' do
803
- res = nil
804
- assert_difference('VirtualClass.count', 0) do
805
- res = secure(VirtualClass) { VirtualClass.import(@data) }
806
- end
807
- assert_equal 'Post', res.first.name
808
- assert_equal 'same', res.first.import_result
809
- assert_equal 'NNP', res.first.kpath
912
+ should 'export relations' do
913
+ assert_equal(%w{collaborators home hot}, subject['relations'].keys)
810
914
  end
915
+ end # with relations
811
916
 
812
- context 'if the superclasses do not match' do
813
- setup do
814
- @data['Post']['superclass'] = 'Page'
815
- end
816
917
 
817
- should 'return a conflict error' do
818
- res = nil
819
- assert_difference('VirtualClass.count', 0) do
820
- res = secure(VirtualClass) { VirtualClass.import(@data) }
821
- end
822
- assert_equal 'Post', res.first.name
823
- assert_equal 'conflict', res.first.import_result
824
- end
918
+ context 'with linked roles' do
919
+ setup do
920
+ secure(::Role) { ::Role.create('name' => 'Foo', 'superclass' => 'Page')}
921
+ end
825
922
 
826
- should 'propagate the conflict error to subclasses in the definitions' do
827
- @data['Foo'] = {'superclass' => 'Post'}
828
- @data['Bar'] = {'superclass' => 'Foo'}
829
- res = nil
830
- assert_difference('VirtualClass.count', 0) do
831
- res = secure(VirtualClass) { VirtualClass.import(@data) }
832
- end
833
- post = res.detect {|r| r.name == 'Post'}
834
- foo = res.detect {|r| r.name == 'Foo'}
835
- bar = res.detect {|r| r.name == 'Bar'}
836
- assert foo.new_record?
837
- assert_equal 'Foo', foo.name
838
- assert_equal 'conflict in superclass', foo.import_result
839
- assert_equal 'Post', post.name
840
- assert_equal 'conflict', post.import_result
841
- assert bar.new_record?
842
- assert_equal 'Bar', bar.name
843
- assert_equal 'conflict in superclass', bar.import_result
844
- end
923
+ should 'export linked roles' do
924
+ assert(subject.keys.include?('Foo'))
925
+ assert_equal('Role', subject['Foo']['type'])
845
926
  end
846
- end
847
- end # with an existing superclass
927
+ end # with linked roles
848
928
 
849
- context 'without an existing superclass' do
850
- setup do
851
- @data = {'Foo' => {'superclass' => 'Baz'}, 'Baz' => {'superclass' => 'Post'}}
852
- end
929
+ end # exporting a real class
853
930
 
854
- should 'create the superclass first if it is in the definitions' do
855
- res = nil
856
- assert_difference('VirtualClass.count', 2) do
857
- res = secure(VirtualClass) { VirtualClass.import(@data) }
931
+ context 'importing definitions' do
932
+ subject do
933
+ {'Note' => {
934
+ 'type' => 'Class',
935
+ 'Bar' => {
936
+ 'type' => 'Role',
937
+ },
938
+ 'Baz' => {
939
+ 'type' => 'VirtualClass',
940
+ 'Plop' => {
941
+ 'type' => 'VirtualClass',
942
+ },
943
+ },
944
+ }}
945
+ end
946
+
947
+ should 'create roles and VirtualClasses' do
948
+ assert_difference('Role.count', 3) do
949
+ assert_difference('VirtualClass.count', 2) do
950
+ VirtualClass.import(subject)
951
+ end
858
952
  end
859
- foo = res.detect {|r| r.name == 'Foo'}
860
- baz = res.detect {|r| r.name == 'Baz'}
861
- assert_equal 'Foo', foo.name
862
- assert_equal 'new', foo.import_result
863
- assert_equal 'NNPBF', foo.kpath
864
- assert_equal 'Baz', baz.name
865
- assert_equal 'new', baz.import_result
866
- assert_equal 'NNPB', baz.kpath
867
953
  end
868
954
 
869
- should 'return an error if the superclass is not in the definitions' do
870
- @data.delete('Baz')
871
- res = nil
872
- assert_difference('VirtualClass.count', 0) do
873
- res = secure(VirtualClass) { VirtualClass.import(@data) }
955
+ context 'with relations' do
956
+ subject do
957
+ s = Zafu::OrderedHash.new
958
+ s['Note'] = Zafu::OrderedHash.new
959
+ # created first with relations to next class
960
+ s['Note']['Foo'] = {
961
+ 'type' => 'VirtualClass',
962
+ 'relations' => {
963
+ 'babar' => {
964
+ 'target_kpath' => 'NNB',
965
+ 'target_unique' => true,
966
+ 'source_role' => 'fool',
967
+ 'rel_group' => 'foo.bar',
968
+ },
969
+ },
970
+ }
971
+
972
+ s['Note']['Bar'] = {
973
+ 'type' => 'VirtualClass',
974
+ }
975
+ s
976
+ end
977
+
978
+ should 'create or update relations after vclass creation' do
979
+ assert_difference('Relation.count', 1) do
980
+ assert_difference('Role.count', 2) do
981
+ VirtualClass.import(subject)
982
+ end
983
+ end
984
+ assert foo = VirtualClass['Foo']
985
+ assert bar = VirtualClass['Bar']
986
+ rel = Relation.first(
987
+ :conditions => ['source_kpath = ? AND target_role = ?', 'NNF', 'babar'])
988
+ assert_equal 'NNB', rel.target_kpath
989
+ assert_equal 'fools', rel.source_role
990
+ assert_equal 'babar', rel.target_role
991
+ assert_equal 'foo.bar', rel.rel_group
874
992
  end
875
- foo = res.first
876
- assert_equal 'Foo', foo.name
877
- assert_equal 'missing superclass', foo.import_result
878
- end
879
- end # without an existing superclass
880
- end # importing virtual class definitions
993
+ end # with relations
994
+
995
+ end
996
+ end # An admin
997
+
881
998
  end
@@ -16,7 +16,7 @@ class EnrollableTest < Zena::Unit::TestCase
16
16
  subject do
17
17
  secure(Node) { nodes(:letter) }
18
18
  end
19
-
19
+
20
20
  should 'add role on property set' do
21
21
  assert_difference('NodesRoles.count', 1) do
22
22
  assert subject.update_attributes('properties' => {'assigned' => 'flat Eric'})
@@ -24,7 +24,30 @@ class EnrollableTest < Zena::Unit::TestCase
24
24
  assert_equal [roles_id(:Task)], subject.cached_role_ids
25
25
  end
26
26
  end
27
-
27
+
28
+ context 'with new property index defined' do
29
+ setup do
30
+ column = secure(Column) { columns(:Letter_paper) }
31
+ column.update_attributes(:index => 'string')
32
+ end
33
+
34
+ should 'rebuild property index on rebuild_index' do
35
+ assert_difference('IdxNodesString.count', 1) do
36
+ # New key = paper
37
+ subject.rebuild_index!
38
+ end
39
+
40
+ indices = Hash[*IdxNodesString.find(:all, :conditions => {:node_id => subject.id}).map {|r| [r.key, r.value]}.flatten]
41
+ assert_equal Hash[
42
+ 'search_mono'=>'Kraft mono',
43
+ 'paper'=>'Kraft'], indices
44
+ end
45
+ end # with new property index defined in role
46
+
47
+ should 'respond to zafu_possible_roles' do
48
+ assert_equal %w{Original Task}, subject.zafu_possible_roles.map {|r| r.name}
49
+ end
50
+
28
51
  context 'with roles assigned' do
29
52
  subject do
30
53
  secure(Node) { nodes(:tree_jpg) }
@@ -87,39 +110,11 @@ class EnrollableTest < Zena::Unit::TestCase
87
110
  Role.connection.execute("DELETE FROM nodes_roles")
88
111
  assert_equal %w{Original}, subject.assigned_roles.map(&:name)
89
112
  end
90
-
91
- context 'with new property index defined in role' do
92
- setup do
93
- column = secure(Column) { columns(:Letter_paper) }
94
- column.update_attributes(:index => 'string')
95
- end
96
-
97
- subject do
98
- secure(Node) { nodes(:letter) }
99
- end
100
-
101
- should 'rebuild property index on rebuild_index' do
102
- # Makes sure that load_roles! is called before index rebuilt
103
- assert_difference('IdxNodesString.count', 1) do
104
- # New key = paper
105
- subject.rebuild_index!
106
- end
107
-
108
- indices = Hash[*IdxNodesString.find(:all, :conditions => {:node_id => subject.id}).map {|r| [r.key, r.value]}.flatten]
109
- assert_equal Hash[
110
- 'search_mono'=>'Kraft mono',
111
- 'paper'=>'Kraft'], indices
112
- end
113
- end # with new property index defined in role
114
113
  end # with roles assigned
115
114
 
116
-
117
- should 'respond to zafu_possible_roles' do
118
- assert_equal %w{Original Task}, subject.zafu_possible_roles.map {|r| r.name}
119
- end
120
115
  end # from a class with roles
121
116
  end # on a node
122
-
117
+
123
118
  context 'A safe method returning a sub-class of Node' do
124
119
  subject do
125
120
  ['section']
@@ -6,44 +6,97 @@ class CalendarTest < Zena::View::TestCase
6
6
  include Zena::Use::I18n::ViewMethods # _
7
7
  include Zena::Use::Urls::ViewMethods # data_path
8
8
 
9
- def test_cal_weeks
10
- login(:tiger)
11
- weeks = []
12
- event_hash = nil
13
- assert_equal "0", _('week_start_day') # week starts on Sunday
14
- start_date, end_date = cal_start_end(Time.utc(2006,3,18), :month)
15
- assert_equal Date.civil(2006,02,26), start_date
16
- assert_equal Date.civil(2006,04,01), end_date
17
- secure!(Note) { Note.create(:parent_id => nodes_id(:zena), :title => 'foobar', :event_at => Time.utc(2006,03,20))}
18
- nodes = secure!(Note) { Note.find(:all, :conditions => ["nodes.event_at >= ? AND nodes.event_at <= ?", start_date, end_date])}
19
- res = cal_weeks('event_at', nodes, start_date, end_date) do |week, hash|
20
- weeks << week
21
- event_hash = hash
22
- end
23
- assert_equal ["2006-03-18 00", "2006-03-20 00"], event_hash.keys.sort
24
- assert_equal ['parc opening'], event_hash["2006-03-18 00"].map{|r| r.title}
25
- assert_equal ['foobar'], event_hash["2006-03-20 00"].map{|r| r.title}
9
+ def fmt(date)
10
+ date.strftime('%Y-%m-%d %H:%M')
26
11
  end
27
12
 
28
- def test_cal_weeks_hours
29
- login(:tiger)
30
- weeks = []
31
- event_hash = nil
32
- hours = [0,12]
33
- assert_equal "0", _('week_start_day') # week starts on Sunday
34
- start_date, end_date = cal_start_end(Time.utc(2006,3,18), :month)
35
- assert_equal Date.civil(2006,02,26), start_date
36
- assert_equal Date.civil(2006,04,01), end_date
37
- secure!(Note) { Note.create(:parent_id => nodes_id(:zena), :title => 'morning', :event_at => Time.utc(2006,03,20,9))}
38
- secure!(Note) { Note.create(:parent_id => nodes_id(:zena), :title => 'afternoon', :event_at => Time.utc(2006,03,20,14))}
39
- nodes = secure!(Note) { Note.find(:all, :conditions => ["nodes.event_at >= ? AND nodes.event_at <= ?", start_date, end_date])}
40
- res = cal_weeks('event_at', nodes, start_date, end_date, hours) do |week, hash|
41
- weeks << week
42
- event_hash = hash
13
+ context 'With a timezone' do
14
+ setup do
15
+ login(:tiger)
16
+ @tz = TZInfo::Timezone.get('Asia/Jakarta')
43
17
  end
44
- assert_equal ["2006-03-18 12", "2006-03-20 00", "2006-03-20 12"], event_hash.keys.sort
45
- assert_equal ['parc opening'], event_hash["2006-03-18 12"].map{|r| r.title}
46
- assert_equal ['morning'], event_hash["2006-03-20 00"].map{|r| r.title}
47
- assert_equal ['afternoon'], event_hash["2006-03-20 12"].map{|r| r.title}
48
- end
18
+
19
+ should 'map start on first' do
20
+ # 1st of May, 2 hours in the morning for the visitor
21
+ # October 2000 is a month starting on a Sunday 1st
22
+ visitor_time = Time.utc(2000, 10, 1, 2)
23
+ # UTC = 2000-09-30 19:00
24
+ utc_time = @tz.local_to_utc(visitor_time)
25
+
26
+ # 0 = week starts on Sunday
27
+ start_date, end_date = cal_start_end(utc_time, :month, @tz, 0)
28
+ assert_equal '2000-09-30 17:00', fmt(start_date)
29
+ assert_equal '2000-11-04 17:00', fmt(end_date)
30
+
31
+ # This is what the visitor sees:
32
+ assert_equal '2000-10-01 00:00', fmt(@tz.utc_to_local(start_date))
33
+ assert_equal '2000-11-05 00:00', fmt(@tz.utc_to_local(end_date))
34
+ end
35
+
36
+ should 'map start on previous month' do
37
+ # 18st of May, 2 hours in the morning for the visitor
38
+ # March 2006 is a month starting on a Sunday 26th of February
39
+ visitor_time = Time.utc(2006, 03, 18)
40
+ # UTC = 2006-03-17 17:00
41
+ utc_time = @tz.local_to_utc(visitor_time)
42
+
43
+ start_date, end_date = cal_start_end(utc_time, :month, @tz, 0)
44
+ assert_equal '2006-02-25 17:00', fmt(start_date)
45
+ assert_equal '2006-04-01 17:00', fmt(end_date)
46
+
47
+ # This is what the visitor sees:
48
+ assert_equal '2006-02-26 00:00', fmt(@tz.utc_to_local(start_date))
49
+ assert_equal '2006-04-02 00:00', fmt(@tz.utc_to_local(end_date))
50
+ end
51
+
52
+ context 'with a date' do
53
+ setup do
54
+ assert_equal 0, _('week_start_day').to_i
55
+ # 18st of May, 2 hours in the morning for the visitor
56
+ # April 2011 is a month ending on Saturday 30th.
57
+ visitor_time = Time.utc(2011, 04, 21)
58
+ # UTC = 2006-03-17 17:00
59
+ @utc_time = @tz.local_to_utc(visitor_time)
60
+ end
61
+
62
+ subject do
63
+ cal_start_end(@utc_time, :month, @tz, 0)
64
+ end
65
+
66
+ should 'not overlap on next month' do
67
+ start_date, end_date = subject
68
+ assert_equal '2011-03-26 17:00', fmt(start_date)
69
+ assert_equal '2011-04-30 17:00', fmt(end_date)
70
+
71
+ # This is what the visitor sees:
72
+ assert_equal '2011-03-27 00:00', fmt(@tz.utc_to_local(start_date))
73
+ assert_equal '2011-05-01 00:00', fmt(@tz.utc_to_local(end_date))
74
+ end
75
+
76
+ should 'not include last date in cal_weeks' do
77
+ start_date, end_date = subject
78
+
79
+ sundays = []
80
+ cal_weeks('', [], start_date, end_date, @tz) do |week, list|
81
+ sundays << fmt(week)
82
+ end
83
+
84
+ assert_equal [
85
+ '2011-03-26 17:00',
86
+ '2011-04-02 17:00',
87
+ '2011-04-09 17:00',
88
+ '2011-04-16 17:00',
89
+ '2011-04-23 17:00'], sundays
90
+
91
+ end
92
+
93
+ should 'map week names starting Sunday' do
94
+ assert_equal "<th class='sun'>Sunday</th><th>Monday</th><th>Tuesday</th><th>Wednesday</th><th>Thursday</th><th>Friday</th><th class='sat'>Saturday</th>", cal_day_names('large', 0)
95
+ end
96
+
97
+ should 'map week names starting Monday' do
98
+ assert_equal "<th>Monday</th><th>Tuesday</th><th>Wednesday</th><th>Thursday</th><th>Friday</th><th class='sat'>Saturday</th><th class='sun'>Sunday</th>", cal_day_names('large', 1)
99
+ end
100
+ end # with a date
101
+ end # With a timezone
49
102
  end
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+
3
+ class FieldIndexTest < Zena::Unit::TestCase
4
+ context 'A visitor with write access' do
5
+ setup do
6
+ login(:lion)
7
+ end
8
+
9
+ context 'creating a node' do
10
+
11
+ context 'that is not published' do
12
+ # Post has 'date' as field index
13
+ subject do
14
+ secure(Node) { Node.create_node(
15
+ :title => 'Piksel',
16
+ :parent_id => nodes_zip(:cleanWater),
17
+ :class => 'Post',
18
+ :date => '2011-05-25'
19
+ )}
20
+ end
21
+
22
+ should 'write index in field' do
23
+ assert_equal '2011-05-25', subject.idx_datetime1.strftime('%Y-%m-%d')
24
+ end
25
+ end # that is not published
26
+ end # creating a node
27
+ end # A visitor with write access
28
+ end
@@ -113,7 +113,7 @@ class HtmlTagsTest < Zena::View::TestCase
113
113
 
114
114
  context 'receiving flash_messages' do
115
115
  should 'wrap flash messages in div' do
116
- assert_match 'div#messages', flash_messages(:show => 'both')
116
+ assert_match 'div#flash_messages', flash_messages(:show => 'both')
117
117
  end
118
118
 
119
119
  should 'not show notice or error divs' do
@@ -126,7 +126,11 @@ class HtmlTagsTest < Zena::View::TestCase
126
126
  end
127
127
 
128
128
  should 'wrap notices in div' do
129
- assert_match 'div#messages div#notice', flash_messages(:show => 'both')
129
+ assert_match 'div#flash_messages div.notice', flash_messages(:show => 'both')
130
+ end
131
+
132
+ should 'auto fade notices' do
133
+ assert_match 'div#flash_messages div.notice.auto_fade', flash_messages(:show => 'both')
130
134
  end
131
135
 
132
136
  should 'show notice' do
@@ -140,7 +144,7 @@ class HtmlTagsTest < Zena::View::TestCase
140
144
  end
141
145
 
142
146
  should 'wrap errors in div' do
143
- assert_match 'div#messages div#error', flash_messages(:show => 'both')
147
+ assert_match 'div#flash_messages div.error', flash_messages(:show => 'both')
144
148
  end
145
149
 
146
150
  should 'show error' do
@@ -28,12 +28,12 @@ class MLIndexTest < Zena::Unit::TestCase
28
28
  col = Column.create(:role_id => buz.id, :ptype => 'string', :name => 'foo', :index => 'string')
29
29
  assert !col.new_record?
30
30
  end
31
-
31
+
32
32
  teardown do
33
33
  # avoid test leakage
34
34
  VirtualClass.expire_cache!
35
35
  end
36
-
36
+
37
37
  subject do
38
38
  secure(Node) { Node.create_node(
39
39
  :class => 'Buz',
@@ -72,20 +72,6 @@ class MLIndexTest < Zena::Unit::TestCase
72
72
  assert_equal 'fabula', idx.value
73
73
  end
74
74
 
75
- context 'with std indices removed' do
76
- setup do
77
- IdxNodesString.connection.execute 'DELETE from idx_nodes_strings'
78
- end
79
-
80
- should 'not write std index on skip_std_index' do
81
- subject = secure(Node) { nodes(:ant) }
82
- subject.instance_variable_set(:@skip_std_index, true)
83
- assert_difference('IdxNodesString.count', 0) do
84
- subject.update_attributes(:name => 'New')
85
- end
86
- end
87
- end # with std indices removed
88
-
89
75
  context 'with multi lingual indices removed' do
90
76
  setup do
91
77
  IdxNodesMlString.connection.execute 'DELETE from idx_nodes_ml_strings'
@@ -39,13 +39,13 @@ class NestedAttributesAliasViewTest < Zena::View::TestCase
39
39
  end
40
40
 
41
41
  def link
42
- @link ||= returning(HashAsMethods.new) do |l|
42
+ @link ||= HashAsMethods.new.tap do |l|
43
43
  l.friend = HashAsMethods.new('other_id' => 1234)
44
44
  end
45
45
  end
46
46
 
47
47
  def version
48
- @version ||= returning(HashAsMethods.new('title' => 'version title')) do |v|
48
+ @version ||= HashAsMethods.new('title' => 'version title').tap do |v|
49
49
  v.content = HashAsMethods.new('width' => 33)
50
50
  end
51
51
  end