imagine_cms 3.0.0.beta6 → 3.0.0.beta7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (278) hide show
  1. data/README.rdoc +1 -1
  2. data/app/assets/images/codepress/line-numbers.png +0 -0
  3. data/app/assets/images/cropper/marqueeHoriz.gif +0 -0
  4. data/app/assets/images/cropper/marqueeVert.gif +0 -0
  5. data/app/assets/images/management/btn_add.gif +0 -0
  6. data/app/assets/images/management/btn_archive.gif +0 -0
  7. data/app/assets/images/management/btn_delete.gif +0 -0
  8. data/app/assets/images/management/btn_duplicate.gif +0 -0
  9. data/app/assets/images/management/btn_edit.gif +0 -0
  10. data/app/assets/images/management/btn_help.gif +0 -0
  11. data/app/assets/images/management/btn_new_page.gif +0 -0
  12. data/app/assets/images/management/btn_preview.gif +0 -0
  13. data/app/assets/images/management/btn_properties.gif +0 -0
  14. data/app/assets/images/management/btn_restore.gif +0 -0
  15. data/app/assets/images/management/btn_top_delete.gif +0 -0
  16. data/app/assets/images/management/btn_top_duplicate.gif +0 -0
  17. data/app/assets/images/management/btn_top_edit.gif +0 -0
  18. data/app/assets/images/management/btn_top_new.gif +0 -0
  19. data/app/assets/images/management/btn_top_preview.gif +0 -0
  20. data/app/assets/images/management/btn_top_properties.gif +0 -0
  21. data/app/assets/{manage → images/management}/bullet.gif +0 -0
  22. data/app/assets/images/management/cvv2_graphic.gif +0 -0
  23. data/app/assets/images/management/error.gif +0 -0
  24. data/app/assets/images/management/gallery_index.gif +0 -0
  25. data/app/assets/images/management/gallery_preview_overlay.png +0 -0
  26. data/app/assets/images/management/gallery_small_drag_overlay.png +0 -0
  27. data/app/assets/images/management/gallery_small_overlay.png +0 -0
  28. data/app/assets/images/management/gallery_sort.gif +0 -0
  29. data/app/assets/images/management/icon_download.gif +0 -0
  30. data/app/assets/images/management/icon_locked.png +0 -0
  31. data/app/assets/images/management/icon_page.gif +0 -0
  32. data/app/assets/images/management/icon_time.gif +0 -0
  33. data/app/assets/images/management/icon_unlocked.png +0 -0
  34. data/app/assets/images/management/page_loading.gif +0 -0
  35. data/app/assets/{manage → images/management}/start.gif +0 -0
  36. data/app/assets/images/management/vcard.gif +0 -0
  37. data/app/assets/javascripts/builder.js +101 -0
  38. data/app/assets/javascripts/codepress/codepress.html +36 -0
  39. data/app/assets/javascripts/codepress/codepress.js +130 -0
  40. data/app/assets/javascripts/codepress/engines/gecko.js +240 -0
  41. data/{vendor/gems/acts_as_tree/test/abstract_unit.rb → app/assets/javascripts/codepress/engines/khtml.js} +0 -0
  42. data/app/assets/javascripts/codepress/engines/msie.js +263 -0
  43. data/{vendor/gems/acts_as_tree/test/database.yml → app/assets/javascripts/codepress/engines/older.js} +0 -0
  44. data/app/assets/javascripts/codepress/engines/opera.js +259 -0
  45. data/app/assets/javascripts/codepress/languages/css.js +23 -0
  46. data/app/assets/javascripts/codepress/languages/generic.js +25 -0
  47. data/app/assets/javascripts/codepress/languages/html.js +63 -0
  48. data/app/assets/javascripts/codepress/languages/java.js +24 -0
  49. data/app/assets/javascripts/codepress/languages/javascript.js +30 -0
  50. data/app/assets/javascripts/codepress/languages/perl.js +27 -0
  51. data/app/assets/javascripts/codepress/languages/php.js +60 -0
  52. data/app/assets/javascripts/codepress/languages/ruby.js +26 -0
  53. data/app/assets/javascripts/codepress/languages/sql.js +30 -0
  54. data/app/assets/javascripts/codepress/languages/text.js +9 -0
  55. data/app/assets/javascripts/cropper.js +568 -0
  56. data/app/assets/javascripts/dojo/dojo.js +14155 -0
  57. data/app/assets/javascripts/dojo/src/html/images/shadowB.png +0 -0
  58. data/app/assets/javascripts/dojo/src/html/images/shadowBL.png +0 -0
  59. data/app/assets/javascripts/dojo/src/html/images/shadowBR.png +0 -0
  60. data/app/assets/javascripts/dojo/src/html/images/shadowL.png +0 -0
  61. data/app/assets/javascripts/dojo/src/html/images/shadowR.png +0 -0
  62. data/app/assets/javascripts/dojo/src/html/images/shadowT.png +0 -0
  63. data/app/assets/javascripts/dojo/src/html/images/shadowTL.png +0 -0
  64. data/app/assets/javascripts/dojo/src/html/images/shadowTR.png +0 -0
  65. data/app/assets/javascripts/dojo/src/widget/templates/Editor2/showtableborder_gecko.css +19 -0
  66. data/app/assets/javascripts/dojo/src/widget/templates/HslColorPicker.svg +30 -0
  67. data/app/assets/javascripts/dojo/src/widget/templates/buttons/aggregate.gif +0 -0
  68. data/app/assets/javascripts/dojo/src/widget/templates/buttons/aggregate.psd +0 -0
  69. data/app/assets/javascripts/dojo/src/widget/templates/buttons/backcolor.gif +0 -0
  70. data/app/assets/javascripts/dojo/src/widget/templates/buttons/bg-fade.png +0 -0
  71. data/app/assets/javascripts/dojo/src/widget/templates/buttons/bold.gif +0 -0
  72. data/app/assets/javascripts/dojo/src/widget/templates/buttons/cancel.gif +0 -0
  73. data/app/assets/javascripts/dojo/src/widget/templates/buttons/copy.gif +0 -0
  74. data/app/assets/javascripts/dojo/src/widget/templates/buttons/createlink.gif +0 -0
  75. data/app/assets/javascripts/dojo/src/widget/templates/buttons/cut.gif +0 -0
  76. data/app/assets/javascripts/dojo/src/widget/templates/buttons/delete.gif +0 -0
  77. data/app/assets/javascripts/dojo/src/widget/templates/buttons/forecolor.gif +0 -0
  78. data/app/assets/javascripts/dojo/src/widget/templates/buttons/hilitecolor.gif +0 -0
  79. data/app/assets/javascripts/dojo/src/widget/templates/buttons/indent.gif +0 -0
  80. data/app/assets/javascripts/dojo/src/widget/templates/buttons/inserthorizontalrule.gif +0 -0
  81. data/app/assets/javascripts/dojo/src/widget/templates/buttons/insertimage.gif +0 -0
  82. data/app/assets/javascripts/dojo/src/widget/templates/buttons/insertorderedlist.gif +0 -0
  83. data/app/assets/javascripts/dojo/src/widget/templates/buttons/inserttable.gif +0 -0
  84. data/app/assets/javascripts/dojo/src/widget/templates/buttons/insertunorderedlist.gif +0 -0
  85. data/app/assets/javascripts/dojo/src/widget/templates/buttons/italic.gif +0 -0
  86. data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifycenter.gif +0 -0
  87. data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifyfull.gif +0 -0
  88. data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifyleft.gif +0 -0
  89. data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifyright.gif +0 -0
  90. data/app/assets/javascripts/dojo/src/widget/templates/buttons/left_to_right.gif +0 -0
  91. data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_bullet_indent.gif +0 -0
  92. data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_bullet_outdent.gif +0 -0
  93. data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_num_indent.gif +0 -0
  94. data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_num_outdent.gif +0 -0
  95. data/app/assets/javascripts/dojo/src/widget/templates/buttons/outdent.gif +0 -0
  96. data/app/assets/javascripts/dojo/src/widget/templates/buttons/paste.gif +0 -0
  97. data/app/assets/javascripts/dojo/src/widget/templates/buttons/redo.gif +0 -0
  98. data/app/assets/javascripts/dojo/src/widget/templates/buttons/removeformat.gif +0 -0
  99. data/app/assets/javascripts/dojo/src/widget/templates/buttons/right_to_left.gif +0 -0
  100. data/app/assets/javascripts/dojo/src/widget/templates/buttons/save.gif +0 -0
  101. data/app/assets/javascripts/dojo/src/widget/templates/buttons/sep.gif +0 -0
  102. data/app/assets/javascripts/dojo/src/widget/templates/buttons/space.gif +0 -0
  103. data/app/assets/javascripts/dojo/src/widget/templates/buttons/strikethrough.gif +0 -0
  104. data/app/assets/javascripts/dojo/src/widget/templates/buttons/subscript.gif +0 -0
  105. data/app/assets/javascripts/dojo/src/widget/templates/buttons/superscript.gif +0 -0
  106. data/app/assets/javascripts/dojo/src/widget/templates/buttons/underline.gif +0 -0
  107. data/app/assets/javascripts/dojo/src/widget/templates/buttons/undo.gif +0 -0
  108. data/app/assets/javascripts/dojo/src/widget/templates/buttons/wikiword.gif +0 -0
  109. data/app/assets/javascripts/dojo/src/widget/templates/check.gif +0 -0
  110. data/app/assets/javascripts/dojo/src/widget/templates/decrementMonth.gif +0 -0
  111. data/app/assets/javascripts/dojo/src/widget/templates/decrementWeek.gif +0 -0
  112. data/app/assets/javascripts/dojo/src/widget/templates/grabCorner.gif +0 -0
  113. data/app/assets/javascripts/dojo/src/widget/templates/images/floatingPaneClose.gif +0 -0
  114. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaAccordionOff.gif +0 -0
  115. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaAccordionSelected.gif +0 -0
  116. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaActive-c.gif +0 -0
  117. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaActive-l.gif +0 -0
  118. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaActive-r.gif +0 -0
  119. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaBarBg.gif +0 -0
  120. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaButton-c.gif +0 -0
  121. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaButton-l.gif +0 -0
  122. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaButton-r.gif +0 -0
  123. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaDisabled-c.gif +0 -0
  124. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaDisabled-l.gif +0 -0
  125. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaDisabled-r.gif +0 -0
  126. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaMenuBg.gif +0 -0
  127. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaPressed-c.gif +0 -0
  128. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaPressed-l.gif +0 -0
  129. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaPressed-r.gif +0 -0
  130. data/app/assets/javascripts/dojo/src/widget/templates/images/tab_close.gif +0 -0
  131. data/app/assets/javascripts/dojo/src/widget/templates/images/toolbar-bg.gif +0 -0
  132. data/app/assets/javascripts/dojo/src/widget/templates/incrementMonth.gif +0 -0
  133. data/app/assets/javascripts/dojo/src/widget/templates/incrementWeek.gif +0 -0
  134. data/app/assets/javascripts/dojo/src/widget/templates/richtextframe.html +24 -0
  135. data/app/assets/javascripts/imagine.js +1385 -0
  136. data/app/assets/javascripts/jquery_no_conflict.js +9405 -0
  137. data/app/assets/stylesheets/codepress/codepress.css +7 -0
  138. data/app/assets/stylesheets/codepress/languages/css.css +10 -0
  139. data/app/assets/stylesheets/codepress/languages/generic.css +9 -0
  140. data/app/assets/stylesheets/codepress/languages/html.css +18 -0
  141. data/app/assets/stylesheets/codepress/languages/java.css +7 -0
  142. data/app/assets/stylesheets/codepress/languages/javascript.css +8 -0
  143. data/app/assets/stylesheets/codepress/languages/perl.css +11 -0
  144. data/app/assets/stylesheets/codepress/languages/php.css +12 -0
  145. data/app/assets/stylesheets/codepress/languages/ruby.css +10 -0
  146. data/app/assets/stylesheets/codepress/languages/sql.css +10 -0
  147. data/app/assets/stylesheets/codepress/languages/text.css +5 -0
  148. data/app/assets/stylesheets/cropper.css +182 -0
  149. data/app/assets/stylesheets/management.css +96 -0
  150. data/app/assets/stylesheets/reset.css +58 -0
  151. data/app/controllers/cms/content_controller.rb +318 -2
  152. data/app/controllers/management/cms_controller.rb +1669 -0
  153. data/app/controllers/management/user_controller.rb +4 -4
  154. data/app/controllers/management/users_controller.rb +18 -4
  155. data/app/controllers/util_controller.rb +45 -0
  156. data/app/helpers/cms_application_helper.rb +662 -15
  157. data/app/models/cms_content_sweeper.rb +21 -0
  158. data/app/models/cms_page.rb +126 -0
  159. data/app/models/cms_page_object.rb +23 -0
  160. data/app/models/cms_page_tag.rb +5 -0
  161. data/app/models/cms_page_version.rb +3 -0
  162. data/app/models/cms_snippet.rb +16 -0
  163. data/app/models/cms_template.rb +29 -0
  164. data/app/models/user.rb +6 -3
  165. data/app/views/management/cms/_complete_gallery.html.erb +5 -0
  166. data/app/views/management/cms/_create_file_link.html.erb +21 -0
  167. data/app/views/management/cms/_crop_feature_image.html.erb +188 -0
  168. data/app/views/management/cms/_crop_image.html.erb +188 -0
  169. data/app/views/management/cms/_crop_results.html.erb +1 -0
  170. data/app/views/management/cms/_crop_results_feature_image.html.erb +1 -0
  171. data/app/views/management/cms/_crop_results_thumb.html.erb +1 -0
  172. data/app/views/management/cms/_crop_thumb.html.erb +188 -0
  173. data/app/views/management/cms/_dialogs.html.erb +39 -0
  174. data/app/views/management/cms/_edit_page.html.erb +176 -0
  175. data/app/views/management/cms/_gallery_index.html.erb +10 -0
  176. data/app/views/management/cms/_gallery_setup.html.erb +22 -0
  177. data/app/views/management/cms/_image.html.erb +3 -0
  178. data/app/views/management/cms/_image_details.html.erb +26 -0
  179. data/app/views/management/cms/_image_draggable.html.erb +4 -0
  180. data/app/views/management/cms/_list_page.html.erb +8 -0
  181. data/app/views/management/cms/_list_page_select.html.erb +8 -0
  182. data/app/views/management/cms/_list_pages.html.erb +1 -0
  183. data/app/views/management/cms/_list_pages_select.html.erb +1 -0
  184. data/app/views/management/cms/_page_attribute.html.erb +6 -0
  185. data/app/views/management/cms/_page_list.html.erb +171 -0
  186. data/app/views/management/cms/_page_list_source_folder.html.erb +20 -0
  187. data/app/views/management/cms/_page_list_source_tag.html.erb +18 -0
  188. data/app/views/management/cms/_select_gallery.html.erb +117 -0
  189. data/app/views/management/cms/_snippet.html.erb +3 -0
  190. data/app/views/management/cms/_sort_images.html.erb +15 -0
  191. data/app/views/management/cms/_temp.html.erb +3 -0
  192. data/app/views/management/cms/_template_options.html.erb +21 -0
  193. data/app/views/management/cms/_template_reference.html.erb +42 -0
  194. data/app/views/management/cms/_upload_feature_image.html.erb +35 -0
  195. data/app/views/management/cms/_upload_file.html.erb +31 -0
  196. data/app/views/management/cms/_upload_image.html.erb +74 -0
  197. data/app/views/management/cms/_upload_thumb.html.erb +35 -0
  198. data/app/views/management/cms/edit_master.html.erb +48 -0
  199. data/app/views/management/cms/edit_page_content.html.erb +4 -0
  200. data/app/views/management/cms/edit_snippet.html.erb +47 -0
  201. data/app/views/management/cms/edit_template.html.erb +48 -0
  202. data/app/views/management/cms/gallery_management.html.erb +108 -0
  203. data/app/views/management/cms/index.html.erb +20 -0
  204. data/app/views/management/cms/page_tags_for_lookup.html.erb +5 -0
  205. data/app/views/management/cms/pages.html.erb +99 -0
  206. data/app/views/management/cms/permission_denied.html.erb +1 -0
  207. data/app/views/management/cms/select_page.html.erb +57 -0
  208. data/app/views/management/cms/snippets.html.erb +14 -0
  209. data/app/views/management/cms/templates.html.erb +14 -0
  210. data/app/views/management/cms/toolbar_edit.html.erb +269 -0
  211. data/app/views/management/cms/toolbar_preview.html.erb +109 -0
  212. data/app/views/util/_calendar_days.html.erb +72 -0
  213. data/app/views/util/_calendar_month_year.html.erb +1 -0
  214. data/app/views/util/_date_picker.html.erb +56 -0
  215. data/app/views/util/_message.html.erb +1 -0
  216. data/app/views/util/_show_message.js.erb +6 -0
  217. data/app/views/util/_tab.html.erb +4 -0
  218. data/config/routes.rb +4 -1
  219. data/imagine_cms.gemspec +4 -0
  220. data/{vendor/gems → lib}/acts_as_versioned/.document +0 -0
  221. data/{vendor/gems → lib}/acts_as_versioned/.gitignore +2 -0
  222. data/{vendor/gems → lib}/acts_as_versioned/CHANGELOG +0 -0
  223. data/lib/acts_as_versioned/Gemfile +7 -0
  224. data/{vendor/gems → lib}/acts_as_versioned/MIT-LICENSE +0 -0
  225. data/{vendor/gems → lib}/acts_as_versioned/README +0 -0
  226. data/{vendor/gems → lib}/acts_as_versioned/RUNNING_UNIT_TESTS +0 -0
  227. data/{vendor/gems → lib}/acts_as_versioned/Rakefile +1 -1
  228. data/{vendor/gems → lib}/acts_as_versioned/acts_as_versioned.gemspec +4 -4
  229. data/{vendor/gems → lib}/acts_as_versioned/init.rb +0 -0
  230. data/{vendor/gems → lib}/acts_as_versioned/lib/acts_as_versioned.rb +109 -107
  231. data/{vendor/gems → lib}/acts_as_versioned/test/abstract_unit.rb +0 -0
  232. data/{vendor/gems → lib}/acts_as_versioned/test/database.yml +0 -0
  233. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/authors.yml +0 -0
  234. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/landmark.rb +0 -0
  235. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/landmark_versions.yml +0 -0
  236. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/landmarks.yml +0 -0
  237. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/locked_pages.yml +0 -0
  238. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/locked_pages_revisions.yml +0 -0
  239. data/{vendor/gems/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb → lib/acts_as_versioned/test/fixtures/migrations/2_add_versioned_tables.rb} +0 -0
  240. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/page.rb +0 -0
  241. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/page_versions.yml +0 -0
  242. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/pages.yml +0 -0
  243. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/widget.rb +0 -0
  244. data/{vendor/gems → lib}/acts_as_versioned/test/migration_test.rb +0 -1
  245. data/{vendor/gems → lib}/acts_as_versioned/test/schema.rb +0 -0
  246. data/{vendor/gems → lib}/acts_as_versioned/test/versioned_test.rb +0 -0
  247. data/lib/extensions/action_controller.rb +154 -143
  248. data/lib/imagine_cms/engine.rb +33 -12
  249. data/lib/imagine_cms/version.rb +1 -1
  250. data/lib/imagine_cms.rb +30 -6
  251. data/lib/prototype_legacy_helper/README.markdown +13 -0
  252. data/lib/prototype_legacy_helper/init.rb +1 -0
  253. data/lib/prototype_legacy_helper/lib/prototype_legacy_helper.rb +430 -0
  254. data/lib/prototype_legacy_helper/test/test_prototype_helper.rb +297 -0
  255. data/lib/upload_progress/CHANGELOG +5 -0
  256. data/lib/upload_progress/MIT-LICENSE +20 -0
  257. data/lib/upload_progress/README +45 -0
  258. data/{vendor/gems/acts_as_tree → lib/upload_progress}/Rakefile +6 -5
  259. data/lib/upload_progress/init.rb +7 -0
  260. data/lib/upload_progress/lib/multipart_progress.rb +176 -0
  261. data/lib/upload_progress/lib/progress.rb +145 -0
  262. data/lib/upload_progress/lib/upload_progress.rb +303 -0
  263. data/lib/upload_progress/lib/upload_progress_helper.rb +425 -0
  264. data/lib/upload_progress/public/stylesheets/upload_progress.css +21 -0
  265. data/lib/upload_progress/test/multipart_progress_testx.rb +364 -0
  266. data/lib/upload_progress/test/upload_progress_helper_testx.rb +134 -0
  267. data/lib/upload_progress/test/upload_progress_testx.rb +88 -0
  268. metadata +305 -43
  269. data/app/assets/manage/btn_delete.gif +0 -0
  270. data/vendor/gems/.DS_Store +0 -0
  271. data/vendor/gems/acts_as_tree/README +0 -26
  272. data/vendor/gems/acts_as_tree/init.rb +0 -1
  273. data/vendor/gems/acts_as_tree/lib/active_record/acts/tree.rb +0 -96
  274. data/vendor/gems/acts_as_tree/test/acts_as_tree_test.rb +0 -219
  275. data/vendor/gems/acts_as_tree/test/fixtures/mixin.rb +0 -0
  276. data/vendor/gems/acts_as_tree/test/fixtures/mixins.yml +0 -0
  277. data/vendor/gems/acts_as_tree/test/schema.rb +0 -0
  278. data/vendor/gems/acts_as_versioned/Gemfile +0 -7
@@ -0,0 +1,364 @@
1
+ require 'logger'
2
+ require 'test/unit'
3
+ require 'cgi'
4
+ require 'stringio'
5
+
6
+ DEBUG=false
7
+
8
+ def test_logger
9
+ if DEBUG then ActionController::Base.logger = Logger.new(STDERR)
10
+ else ActionController::Base.logger = Logger.new(StringIO.new)
11
+ end
12
+ end
13
+
14
+ # Provide a static version of the Controllers module instead of the auto-loading version.
15
+ # We don't want these tests to fail when dependencies are to blame.
16
+ module Controllers
17
+ class EmptyController < ActionController::Base
18
+ end
19
+ class ApplicationController < ActionController::Base
20
+ end
21
+
22
+ class MockController < ActionController::Base
23
+ def initialize
24
+ super
25
+ @session = {:uploads => {}}
26
+ @params = {}
27
+ end
28
+ end
29
+
30
+ class SingleUploadController < ActionController::Base
31
+ upload_status_for :one
32
+
33
+ def one; end
34
+ end
35
+
36
+ class DoubleUploadController < ActionController::Base
37
+ upload_status_for :one, :two
38
+
39
+ def one; end
40
+ def two; end
41
+ end
42
+
43
+ class DoubleStatusUploadController < ActionController::Base
44
+ upload_status_for :one, :two, :status => :custom_status
45
+
46
+ def one; end
47
+ def two; end
48
+ end
49
+
50
+ class DoubleSeperateController < ActionController::Base
51
+ upload_status_for :one
52
+ upload_status_for :two
53
+
54
+ def one; end
55
+ def two; end
56
+ end
57
+
58
+ class UploadController < ActionController::Base
59
+ upload_status_for :norendered, :rendered, :redirected, :finish_param_dict, :finish_param_string, :finish_param_number
60
+
61
+ def norendered
62
+ end
63
+
64
+ def rendered
65
+ render_text("rendered")
66
+ end
67
+
68
+ def redirected
69
+ redirect_to "/redirected/"
70
+ end
71
+
72
+ def finish_param_dict
73
+ finish_upload_status "{a: 'b'}"
74
+ end
75
+
76
+ def finish_param_string
77
+ finish_upload_status "'a string'"
78
+ end
79
+
80
+ def finish_param_number
81
+ finish_upload_status 123
82
+ end
83
+
84
+ def finish_param_number_redirect
85
+ redirect_to "/redirected/"
86
+ finish_upload_status 123
87
+ end
88
+ end
89
+ end
90
+
91
+ class MockIO < StringIO
92
+ def initialize(data='', &block)
93
+ test_logger.debug("MockIO inializing data: #{data[0..20]}")
94
+
95
+ @block = block
96
+ super(data)
97
+ end
98
+
99
+ def write(data)
100
+ test_logger.debug("MockIO write #{data.size} data: #{data[0..20]}")
101
+ super
102
+ end
103
+ def read(size)
104
+ test_logger.debug("MockIO getting data from super")
105
+ data = super
106
+
107
+ test_logger.debug("Calling read callback")
108
+ @block.call
109
+
110
+ test_logger.debug("Returning data: #{data.size}")
111
+ data
112
+ end
113
+ end
114
+
115
+ class MockCGI < CGI
116
+ BOUNDARY = '----------0xKhTmLbOuNdArY'
117
+ FILENAME = 'dummy.nul'
118
+
119
+ attr_reader :upload_id, :session_options, :session_id
120
+
121
+ def initialize(size=1000, url='/test', &block)
122
+ @url = url
123
+ @env = {}
124
+ @sio = MockIO.new('') { block.call(self) if block_given? }
125
+
126
+ @upload_id = '1'
127
+
128
+ add_param('param1', 'value1')
129
+ add_data(size)
130
+ add_param('param1', 'value2')
131
+ add_end_boundary
132
+ init_env
133
+ @sio.rewind
134
+ super()
135
+ end
136
+
137
+ #def stdinput_without_progress
138
+ # @sio
139
+ #end
140
+
141
+ def stdinput
142
+ @sio
143
+ end
144
+
145
+ def env_table
146
+ @env
147
+ end
148
+
149
+ private
150
+ def init_env
151
+ @env['HTTP_HOST'] = 'localhost'
152
+ @env['SERVER_PORT'] = '80'
153
+ @env['REQUEST_METHOD'] = "POST"
154
+ @env['QUERY_STRING'] = @url.split('?')[1] || "upload_id=#{upload_id}&query_param=query_value"
155
+ @env['REQUEST_URI'] = @url
156
+ @env['SCRIPT_NAME'] = @url.split('?').first.split('/').last
157
+ @env['PATH_INFO'] = @url.split('?').first
158
+ @env['CONTENT_TYPE'] = "multipart/form-data; boundary=#{BOUNDARY}"
159
+ @env['CONTENT_LENGTH'] = @sio.tell - EOL.size
160
+
161
+ @session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.inject({}) { |options, pair|
162
+ options[pair.first.to_s] = pair.last; options
163
+ }
164
+ session = CGI::Session.new({}, @session_options.merge({'new_session' => true}))
165
+ @session_id = session.session_id
166
+ @env['COOKIE'] = "_session_id=#{session.session_id}"
167
+ session.close
168
+ end
169
+
170
+ def add_param(name, value)
171
+ add_boundary
172
+ @sio << "Content-Disposition: form-data; name=\"#{name}\"" << EOL << EOL
173
+ @sio << value.to_s << EOL
174
+ end
175
+
176
+ def add_data(size)
177
+ add_boundary
178
+ @sio << "Content-Disposition: form-data; name=\"file\"; filename=\"#{FILENAME}\"" << EOL
179
+ @sio << "Content-Type: application/octet-stream" << EOL << EOL
180
+ @sio << "." * size
181
+ @sio << EOL
182
+ end
183
+
184
+ def add_boundary
185
+ @sio << "--" << BOUNDARY << EOL
186
+ end
187
+
188
+ def add_end_boundary
189
+ @sio << "--" << BOUNDARY << "--" << EOL
190
+ end
191
+ end
192
+
193
+ class MultipartProgressTest < Test::Unit::TestCase
194
+
195
+ def test_domain_language_single
196
+ c = Controllers::SingleUploadController.new
197
+ assert_respond_to(c, :one)
198
+ assert_respond_to(c, :upload_status)
199
+ assert_respond_to(c, :finish_upload_status)
200
+ end
201
+
202
+ def test_domain_language_double
203
+ c = Controllers::DoubleUploadController.new
204
+ assert_respond_to(c, :one)
205
+ assert_respond_to(c, :two)
206
+ assert_respond_to(c, :upload_status)
207
+ assert_respond_to(c, :finish_upload_status)
208
+ end
209
+
210
+ def test_domain_language_double_status
211
+ c = Controllers::DoubleStatusUploadController.new
212
+ assert_respond_to(c, :one)
213
+ assert_respond_to(c, :two)
214
+ assert_respond_to(c, :custom_status)
215
+ assert_respond_to(c, :finish_upload_status)
216
+ end
217
+
218
+ def test_domain_language_double_seperate
219
+ c = Controllers::DoubleSeperateController.new
220
+ assert_respond_to(c, :one)
221
+ assert_respond_to(c, :two)
222
+ assert_respond_to(c, :upload_status)
223
+ assert_respond_to(c, :finish_upload_status)
224
+ end
225
+
226
+ def test_finish_status_norendered
227
+ # Fails to render the upload finish script because there is no view associated with this action
228
+ test_logger.debug('test_finish_status_norendered')
229
+
230
+ res = process(:action => 'norendered', :upload_id => 1)
231
+ assert_match(/ActionView::ActionViewError/s, res.body)
232
+
233
+ res = process(:action => :upload_status, :upload_id => 1)
234
+ assert_match(/Upload finished/s, res.body)
235
+
236
+ res = process(:action => :norendered)
237
+ assert_match(/ActionView::ActionViewError/s, res.body)
238
+ end
239
+
240
+ def test_finish_status_rendered
241
+ test_logger.debug('test_finish_status_rendered')
242
+
243
+ res = process(:action => :rendered, :upload_id => 1)
244
+ assert_match(/stop\(\)/s, res.body)
245
+ assert_no_match(/rendered/s, res.body)
246
+
247
+ res = process(:action => :upload_status, :upload_id => 1)
248
+ assert_match(/Upload finished/s, res.body)
249
+
250
+ res = process(:action => :rendered)
251
+ assert_no_match(/stop\(\)/s, res.body)
252
+ assert_match(/rendered/, res.body)
253
+ end
254
+
255
+ def test_finish_status_redirected
256
+ test_logger.debug('test_finish_status_redirected')
257
+
258
+ res = process(:action => :redirected, :upload_id => 1)
259
+ assert_match(/location\.replace/s, res.body)
260
+
261
+ res = process(:action => :redirected)
262
+ assert_no_match(/location\.replace/s, res.body)
263
+ assert_match(/\/redirected\//s, res.headers['location'])
264
+ assert_match(/302 .*$/, res.headers['Status'])
265
+
266
+ res = process(:action => :upload_status, :upload_id => 1)
267
+ assert_match(/Upload finished/s, res.body)
268
+ end
269
+
270
+ def test_finish_status_finish_param
271
+ test_logger.debug('test_finish_status_param')
272
+
273
+ res = process(:action => :finish_param_string, :upload_id => 1)
274
+ assert_match(/stop\('a string'\)/s, res.body)
275
+ assert_no_redirect res
276
+
277
+ res = process(:action => :finish_param_dict, :upload_id => 1)
278
+ assert_match(/stop\(\{a: 'b'\}\)/s, res.body)
279
+ assert_no_redirect res
280
+
281
+ res = process(:action => :finish_param_number, :upload_id => 1)
282
+ assert_match(/stop\(123\)/s, res.body)
283
+ assert_no_redirect res
284
+
285
+ res = process(:action => :finish_param_number_redirect, :upload_id => 1)
286
+ test_logger.debug('test_finish_status_param: ' + res.body)
287
+ assert_match(/stop\(123\)/s, res.body)
288
+ assert_match(/replace\('\http:\/\/localhost\/redirected\/'\).*?/s, res.body)
289
+ assert_no_redirect res
290
+ end
291
+
292
+ def test_basic_setup
293
+ test_logger.debug('test_basic_setup')
294
+
295
+ cgi, request, response = new_request(100000)
296
+ assert_not_nil(request.session)
297
+ assert_not_nil(request.session[:uploads], "uploads collection not set")
298
+ assert_not_nil(request.session[:uploads][cgi.upload_id], "upload id not set")
299
+ progress = request.session[:uploads][cgi.upload_id]
300
+ assert_equal(true, progress.finished?)
301
+ end
302
+
303
+ def test_params
304
+ test_logger.debug('test_params')
305
+
306
+ cgi, request, response = new_request(1000)
307
+ assert(!request.params.empty?)
308
+ assert(!request.params['param1'].empty?)
309
+ end
310
+
311
+ def test_share_session
312
+ cgi, request, response = new_request(100000) do |cgi, req|
313
+ if cgi.stdinput.tell > 50000
314
+ # force a save
315
+ cgi.stdinput.save_progress rescue flunk('Something else is wrong, our wrapper isnt setup, is ActionController::Base.logger set?')
316
+
317
+ other_session = CGI::Session.new(cgi, cgi.session_options.merge({'session_id' => cgi.session_id}))
318
+ assert_not_nil(other_session[:uploads])
319
+ assert_not_nil(other_session[:uploads][cgi.upload_id])
320
+ assert_in_delta(cgi.stdinput.session[:uploads][cgi.upload_id].bitrate, other_session[:uploads][cgi.upload_id].bitrate, 1000.0, "Seperate session does not share data from original session")
321
+
322
+ other_session.close
323
+ end
324
+ end
325
+ end
326
+
327
+ def test_upload_ids
328
+ c = Controllers::MockController.new
329
+ (1..222).each do |id|
330
+ c.params = {}
331
+
332
+ assert_equal((id-1).to_s, c.last_upload_id, "last_upload_id is out of sync")
333
+ assert_equal(id.to_s, c.next_upload_id, "next_upload_id is out of sync")
334
+ assert_equal(id.to_s, c.current_upload_id, "current_upload_id is out of sync")
335
+
336
+ c.params = {:upload_id => (id-1).to_s}
337
+ assert_equal((id-1).to_s, c.current_upload_id, "current_upload_id is out of sync")
338
+
339
+ c.session[:uploads][id] = {}
340
+ end
341
+ end
342
+
343
+ private
344
+ def new_request(size=1000, url='/test', &block)
345
+ test_logger.debug('Creating MockCGI')
346
+ cgi = MockCGI.new(size, url) do |cgi|
347
+ block.call(cgi) if block_given?
348
+ end
349
+
350
+ assert(cgi.private_methods.include?("read_multipart_with_progress"))
351
+ return [cgi, ActionController::CgiRequest.new(cgi), ActionController::CgiResponse.new(cgi)]
352
+ end
353
+
354
+ def process(options = {})
355
+ Controllers::UploadController.process(*(new_request(1000, '/upload?' + options.map {|k,v| "#{k}=#{v}"}.join('&'))[1..2]))
356
+ end
357
+
358
+ def assert_no_redirect(res)
359
+ assert_nil(res.redirected_to)
360
+ assert_nil(res.headers['location'])
361
+ assert_match(/200 .*$/, res.headers['Status'])
362
+ end
363
+
364
+ end
@@ -0,0 +1,134 @@
1
+ require File.dirname(__FILE__) + 'action_view/helpers/date_helper'
2
+ require File.dirname(__FILE__) + 'action_view/helpers/number_helper'
3
+ require File.dirname(__FILE__) + 'action_view/helpers/asset_tag_helper'
4
+ require File.dirname(__FILE__) + 'action_view/helpers/form_tag_helper'
5
+ require File.dirname(__FILE__) + 'action_view/helpers/tag_helper'
6
+ require File.dirname(__FILE__) + 'action_view/helpers/javascript_helper'
7
+ require File.dirname(__FILE__) + 'action_view/helpers/upload_progress_helper'
8
+ require File.dirname(__FILE__) + 'activesupport/lib/active_support/core_ext/hash' #for stringify keys
9
+
10
+ class MockProgress
11
+ def initialize(started, finished)
12
+ @started, @finished = [started, finished]
13
+ end
14
+
15
+ def started?
16
+ @started
17
+ end
18
+
19
+ def finished?
20
+ @finished
21
+ end
22
+
23
+ def message
24
+ "A message"
25
+ end
26
+
27
+ def method_missing(meth, *args)
28
+ # Just return some consitant number
29
+ meth.to_s.hash.to_i.abs + args.hash.to_i.abs
30
+ end
31
+ end
32
+
33
+ class UploadProgressHelperTest < Test::Unit::TestCase
34
+ include ActionView::Helpers::DateHelper
35
+ include ActionView::Helpers::NumberHelper
36
+ include ActionView::Helpers::AssetTagHelper
37
+ include ActionView::Helpers::FormTagHelper
38
+ include ActionView::Helpers::TagHelper
39
+ include ActionView::Helpers::UrlHelper
40
+ include ActionView::Helpers::JavaScriptHelper
41
+ include ActionView::Helpers::UploadProgressHelper
42
+
43
+ def next_upload_id; @upload_id = last_upload_id.succ; end
44
+ def last_upload_id; @upload_id ||= 0; end
45
+ def current_upload_id; last_upload_id; end
46
+ def upload_progress(upload_id = nil); @upload_progress ||= MockProgress.new(false, true); end
47
+
48
+ def setup
49
+ @controller = Class.new do
50
+ def url_for(options, *parameters_for_method_reference)
51
+ "http://www.example.com"
52
+ end
53
+ end
54
+ @controller = @controller.new
55
+ end
56
+
57
+ def test_upload_status_tag
58
+ assert_dom_equal(
59
+ '<div class="progressBar" id="UploadProgressBar0"><div class="border"><div class="background"><div class="foreground"></div></div></div></div><div class="uploadStatus" id="UploadStatus0"></div>',
60
+ upload_status_tag
61
+ )
62
+ end
63
+
64
+ def test_upload_status_text_tag
65
+ assert_dom_equal(
66
+ '<div class="my-upload" id="my-id">Starting</div>',
67
+ upload_status_text_tag('Starting', :class => 'my-upload', :id => 'my-id')
68
+ )
69
+ end
70
+
71
+
72
+ def test_upload_progress_text
73
+ @upload_progress = MockProgress.new(false, false)
74
+ assert_equal(
75
+ "Upload starting...",
76
+ upload_progress_text
77
+ )
78
+
79
+ @upload_progress = MockProgress.new(true, false)
80
+ assert_equal(
81
+ "828.7 MB of 456.2 MB at 990.1 MB/s; 10227 days remaining",
82
+ upload_progress_text
83
+ )
84
+
85
+ @upload_progress = MockProgress.new(true, true)
86
+ assert_equal(
87
+ "A message",
88
+ upload_progress_text
89
+ )
90
+ end
91
+
92
+ def test_upload_progress_update_bar_js
93
+ assert_equal(
94
+ "if($('UploadProgressBar0')){$('UploadProgressBar0').firstChild.firstChild.style.width='0%'}",
95
+ upload_progress_update_bar_js
96
+ )
97
+
98
+ assert_equal(
99
+ "if($('UploadProgressBar0')){$('UploadProgressBar0').firstChild.firstChild.style.width='50%'}",
100
+ upload_progress_update_bar_js(50)
101
+ )
102
+ end
103
+
104
+ def test_finish_upload_status
105
+ assert_dom_equal(
106
+ "<html><head><script language=\"javascript\" type=\"text/javascript\">function finish() { if (parent.document.uploadStatus0) { parent.document.uploadStatus0.stop();\n }\n }</script></head><body onload=\"finish()\"></body></html>",
107
+ finish_upload_status
108
+ )
109
+
110
+ assert_dom_equal(
111
+ "<html><head><script language=\"javascript\" type=\"text/javascript\">function finish() { if (parent.document.uploadStatus0) { parent.document.uploadStatus0.stop(123);\n }\n }</script></head><body onload=\"finish()\"></body></html>",
112
+ finish_upload_status(:client_js_argument => 123)
113
+ )
114
+
115
+ assert_dom_equal(
116
+ "<html><head><script language=\"javascript\" type=\"text/javascript\">function finish() { if (parent.document.uploadStatus0) { parent.document.uploadStatus0.stop();\nparent.location.replace('/redirected/');\n }\n }</script></head><body onload=\"finish()\"></body></html>",
117
+ finish_upload_status(:redirect_to => '/redirected/')
118
+ )
119
+ end
120
+
121
+ def test_form_tag_with_upload_progress
122
+ assert_dom_equal(
123
+ "<form action=\"http://www.example.com\" enctype=\"multipart/form-data\" method=\"post\" onsubmit=\"if (this.action.indexOf('upload_id') &lt; 0){ this.action += '?upload_id=1'; }this.target = 'UploadTarget1';$('UploadStatus1').innerHTML='Upload starting...'; if($('UploadProgressBar1')){$('UploadProgressBar1').firstChild.firstChild.style.width='0%'}; if (document.uploadStatus1) { document.uploadStatus1.stop(); }document.uploadStatus1 = new Ajax.PeriodicalUpdater('UploadStatus1','http://www.example.com', Object.extend({asynchronous:true, evalScripts:true, onComplete:function(request){$('UploadStatus1').innerHTML='A message';if($('UploadProgressBar1')){$('UploadProgressBar1').firstChild.firstChild.style.width='100%'};document.uploadStatus1 = null}},{decay:1.8,frequency:2.0})); return true\"><iframe id=\"UploadTarget1\" name=\"UploadTarget1\" src=\"\" style=\"width:0px;height:0px;border:0\"></iframe>",
124
+ form_tag_with_upload_progress
125
+ )
126
+ end
127
+
128
+ def test_form_tag_with_upload_progress_custom
129
+ assert_dom_equal(
130
+ "<form action=\"http://www.example.com\" enctype=\"multipart/form-data\" method=\"post\" onsubmit=\"if (this.action.indexOf('upload_id') &lt; 0){ this.action += '?upload_id=5'; }this.target = 'awindow';$('UploadStatus0').innerHTML='Upload starting...'; if($('UploadProgressBar0')){$('UploadProgressBar0').firstChild.firstChild.style.width='0%'}; alert('foo'); if (document.uploadStatus0) { document.uploadStatus0.stop(); }document.uploadStatus0 = new Ajax.PeriodicalUpdater('UploadStatus0','http://www.example.com', Object.extend({asynchronous:true, evalScripts:true, onComplete:function(request){$('UploadStatus0').innerHTML='A message';if($('UploadProgressBar0')){$('UploadProgressBar0').firstChild.firstChild.style.width='100%'};document.uploadStatus0 = null; alert('bar')}},{decay:7,frequency:6})); return true\" target=\"awindow\">",
131
+ form_tag_with_upload_progress({:upload_id => 5}, {:begin => "alert('foo')", :finish => "alert('bar')", :frequency => 6, :decay => 7, :target => 'awindow'})
132
+ )
133
+ end
134
+ end
@@ -0,0 +1,88 @@
1
+ require 'test/unit'
2
+ require 'cgi'
3
+ require 'stringio'
4
+
5
+ class UploadProgressTest < Test::Unit::TestCase
6
+ def test_remaining
7
+ progress = new_progress(20000)
8
+ assert_equal(0, progress.received_bytes)
9
+ assert_equal(20000, progress.remaining_bytes)
10
+ progress.update!(10000, 1.0)
11
+ assert_equal(10000, progress.remaining_bytes)
12
+ assert_equal(1.0, progress.remaining_seconds)
13
+ assert_equal(50, progress.completed_percent)
14
+ assert_equal(true, progress.started?)
15
+ assert_equal(false, progress.finished?)
16
+ assert_equal(false, progress.stalled?)
17
+ progress.update!(10000, 2.0)
18
+ assert_equal(true, progress.finished?)
19
+ assert_equal(0.0, progress.remaining_seconds)
20
+ end
21
+
22
+ def test_stalled
23
+ progress = new_progress(10000)
24
+ assert_equal(false, progress.stalled?)
25
+ progress.update!(100, 1.0)
26
+ assert_equal(false, progress.stalled?)
27
+ progress.update!(100, 20.0)
28
+ assert_equal(true, progress.stalled?)
29
+ assert_in_delta(0.0, progress.bitrate, 0.001)
30
+ progress.update!(100, 21.0)
31
+ assert_equal(false, progress.stalled?)
32
+ end
33
+
34
+ def test_elapsed
35
+ progress = new_progress(10000)
36
+ (1..5).each do |t|
37
+ progress.update!(1000, Float(t))
38
+ end
39
+ assert_in_delta(5.0, progress.elapsed_seconds, 0.001)
40
+ assert_equal(10000, progress.total_bytes)
41
+ assert_equal(5000, progress.received_bytes)
42
+ assert_equal(5000, progress.remaining_bytes)
43
+ end
44
+
45
+ def test_overflow
46
+ progress = new_progress(10000)
47
+ progress.update!(20000, 1.0)
48
+ assert_equal(10000, progress.received_bytes)
49
+ end
50
+
51
+ def test_zero
52
+ progress = new_progress(0)
53
+ assert_equal(0, progress.total_bytes)
54
+ assert_equal(0, progress.remaining_bytes)
55
+ assert_equal(false, progress.started?)
56
+ assert_equal(true, progress.finished?)
57
+ assert_equal(0, progress.bitrate)
58
+ assert_equal(0, progress.completed_percent)
59
+ assert_equal(0, progress.remaining_seconds)
60
+ end
61
+
62
+ def test_finished
63
+ progress = new_progress(10000)
64
+ (1..9).each do |t|
65
+ progress.update!(1000, Float(t))
66
+ assert_equal(false, progress.finished?)
67
+ assert_equal(1000.0, progress.bitrate)
68
+ assert_equal(false, progress.stalled?)
69
+ end
70
+ assert_equal(false, progress.finished?)
71
+ progress.update!(1000, 10.0)
72
+ assert_equal(true, progress.finished?)
73
+ end
74
+
75
+ def test_rapid_samples
76
+ progress = new_progress(10000)
77
+ (1..1000).each do |t|
78
+ progress.update!(10, t/100.0)
79
+ end
80
+ assert_in_delta(1000.0, progress.bitrate, 0.001)
81
+ assert_equal(true, progress.finished?)
82
+ end
83
+
84
+ private
85
+ def new_progress(total)
86
+ ActionController::UploadProgress::Progress.new(total)
87
+ end
88
+ end