kuji-mercury-rails 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. data/LICENSE +25 -0
  2. data/POST_INSTALL +15 -0
  3. data/app/controllers/mercury/images_controller.rb +19 -0
  4. data/app/controllers/mercury_controller.rb +34 -0
  5. data/app/models/mercury/image.rb +16 -0
  6. data/app/views/layouts/mercury.html.erb +33 -0
  7. data/app/views/mercury/lightviews/about.html +11 -0
  8. data/app/views/mercury/modals/character.html +255 -0
  9. data/app/views/mercury/modals/htmleditor.html +13 -0
  10. data/app/views/mercury/modals/link.html +75 -0
  11. data/app/views/mercury/modals/media.html +82 -0
  12. data/app/views/mercury/modals/table.html +84 -0
  13. data/app/views/mercury/palettes/backcolor.html +73 -0
  14. data/app/views/mercury/palettes/forecolor.html +73 -0
  15. data/app/views/mercury/panels/history.html +3 -0
  16. data/app/views/mercury/panels/notes.html +3 -0
  17. data/app/views/mercury/panels/snippets.html +12 -0
  18. data/app/views/mercury/selects/formatblock.html +11 -0
  19. data/app/views/mercury/selects/style.html +5 -0
  20. data/app/views/mercury/snippets/example/options.html.erb +34 -0
  21. data/app/views/mercury/snippets/example/preview.html.erb +1 -0
  22. data/config/engine.rb +41 -0
  23. data/db/migrate/20110526035601_create_mercury_images.rb +11 -0
  24. data/features/loading/loading.feature +22 -0
  25. data/features/loading/navigating.feature +77 -0
  26. data/features/loading/user_interface.feature +67 -0
  27. data/features/regions/editable/advanced_editing.feature +0 -0
  28. data/features/regions/editable/basic_editing.feature +195 -0
  29. data/features/regions/editable/inserting_links.feature +98 -0
  30. data/features/regions/editable/inserting_media.feature +110 -0
  31. data/features/regions/editable/inserting_snippets.feature +102 -0
  32. data/features/regions/editable/inserting_special_characters.feature +24 -0
  33. data/features/regions/editable/inserting_tables.feature +109 -0
  34. data/features/regions/editable/pasting.feature +0 -0
  35. data/features/regions/editable/uploading_images.feature +0 -0
  36. data/features/regions/image/uploading_images.feature +0 -0
  37. data/features/regions/markupable/advanced_editing.feature +0 -0
  38. data/features/regions/markupable/basic_editing.feature +0 -0
  39. data/features/regions/markupable/inserting_links.feature +0 -0
  40. data/features/regions/markupable/inserting_media.feature +0 -0
  41. data/features/regions/markupable/inserting_snippets.feature +0 -0
  42. data/features/regions/markupable/inserting_special_characters.feature +0 -0
  43. data/features/regions/markupable/inserting_tables.feature +0 -0
  44. data/features/regions/markupable/uploading_images.feature +0 -0
  45. data/features/regions/simple/basic_editing.feature +5 -0
  46. data/features/regions/snippetable/advanced_editing.feature +0 -0
  47. data/features/regions/snippetable/basic_editing.feature +0 -0
  48. data/features/regions/snippetable/inserting_snippets.feature +0 -0
  49. data/features/saving/saving.feature +33 -0
  50. data/features/step_definitions/debug_steps.rb +14 -0
  51. data/features/step_definitions/mercury_steps.rb +438 -0
  52. data/features/step_definitions/web_steps.rb +211 -0
  53. data/features/support/env.rb +46 -0
  54. data/features/support/mercury_contents.rb +25 -0
  55. data/features/support/mercury_selectors.rb +148 -0
  56. data/features/support/paths.rb +38 -0
  57. data/features/support/selectors.rb +44 -0
  58. data/lib/generators/mercury/install/install_generator.rb +49 -0
  59. data/lib/generators/mercury/install/templates/mongoid_paperclip_image.rb +17 -0
  60. data/lib/mercury-rails.rb +3 -0
  61. data/lib/mercury/authentication.rb +8 -0
  62. data/spec/javascripts/mercury/dialog_spec.js.coffee +281 -0
  63. data/spec/javascripts/mercury/dialogs/backcolor_spec.js.coffee +37 -0
  64. data/spec/javascripts/mercury/dialogs/forecolor_spec.js.coffee +37 -0
  65. data/spec/javascripts/mercury/dialogs/formatblock_spec.js.coffee +25 -0
  66. data/spec/javascripts/mercury/dialogs/snippetpanel_spec.js.coffee +30 -0
  67. data/spec/javascripts/mercury/dialogs/style_spec.js.coffee +25 -0
  68. data/spec/javascripts/mercury/history_buffer_spec.js.coffee +76 -0
  69. data/spec/javascripts/mercury/lightview_spec.js.coffee +497 -0
  70. data/spec/javascripts/mercury/mercury_spec.js.coffee +132 -0
  71. data/spec/javascripts/mercury/modal_spec.js.coffee +504 -0
  72. data/spec/javascripts/mercury/modals/htmleditor_spec.js.coffee +30 -0
  73. data/spec/javascripts/mercury/modals/insertcharacter_spec.js.coffee +29 -0
  74. data/spec/javascripts/mercury/modals/insertlink_spec.js.coffee +220 -0
  75. data/spec/javascripts/mercury/modals/insertmedia_spec.js.coffee +167 -0
  76. data/spec/javascripts/mercury/modals/insertsnippet_spec.js.coffee +52 -0
  77. data/spec/javascripts/mercury/modals/inserttable_spec.js.coffee +160 -0
  78. data/spec/javascripts/mercury/native_extensions_spec.js.coffee +60 -0
  79. data/spec/javascripts/mercury/page_editor_spec.js.coffee +757 -0
  80. data/spec/javascripts/mercury/palette_spec.js.coffee +49 -0
  81. data/spec/javascripts/mercury/panel_spec.js.coffee +183 -0
  82. data/spec/javascripts/mercury/region_spec.js.coffee +298 -0
  83. data/spec/javascripts/mercury/regions/editable_spec.js.coffee +561 -0
  84. data/spec/javascripts/mercury/regions/image_spec.js.coffee +34 -0
  85. data/spec/javascripts/mercury/regions/markupable_spec.js.coffee +367 -0
  86. data/spec/javascripts/mercury/regions/simple_spec.js.coffee +33 -0
  87. data/spec/javascripts/mercury/regions/snippetable_spec.js.coffee +370 -0
  88. data/spec/javascripts/mercury/select_spec.js.coffee +49 -0
  89. data/spec/javascripts/mercury/snippet_spec.js.coffee +253 -0
  90. data/spec/javascripts/mercury/snippet_toolbar_spec.js.coffee +184 -0
  91. data/spec/javascripts/mercury/statusbar_spec.js.coffee +150 -0
  92. data/spec/javascripts/mercury/table_editor_spec.js.coffee +194 -0
  93. data/spec/javascripts/mercury/toolbar.button_group_spec.js.coffee +90 -0
  94. data/spec/javascripts/mercury/toolbar.button_spec.js.coffee +360 -0
  95. data/spec/javascripts/mercury/toolbar.expander_spec.js.coffee +118 -0
  96. data/spec/javascripts/mercury/toolbar_spec.js.coffee +222 -0
  97. data/spec/javascripts/mercury/tooltip_spec.js.coffee +186 -0
  98. data/spec/javascripts/mercury/uploader_spec.js.coffee +530 -0
  99. data/spec/javascripts/spec_helper.js +513 -0
  100. data/spec/javascripts/templates/mercury/dialog.html +2 -0
  101. data/spec/javascripts/templates/mercury/dialogs/backcolor.html +5 -0
  102. data/spec/javascripts/templates/mercury/dialogs/forecolor.html +5 -0
  103. data/spec/javascripts/templates/mercury/dialogs/formatblock.html +3 -0
  104. data/spec/javascripts/templates/mercury/dialogs/snippetpanel.html +16 -0
  105. data/spec/javascripts/templates/mercury/dialogs/style.html +3 -0
  106. data/spec/javascripts/templates/mercury/lightview.html +13 -0
  107. data/spec/javascripts/templates/mercury/modal.html +13 -0
  108. data/spec/javascripts/templates/mercury/modals/htmleditor.html +5 -0
  109. data/spec/javascripts/templates/mercury/modals/insertcharacter.html +5 -0
  110. data/spec/javascripts/templates/mercury/modals/insertlink.html +30 -0
  111. data/spec/javascripts/templates/mercury/modals/insertmedia.html +35 -0
  112. data/spec/javascripts/templates/mercury/modals/insertsnippet.html +6 -0
  113. data/spec/javascripts/templates/mercury/modals/inserttable.html +27 -0
  114. data/spec/javascripts/templates/mercury/page_editor.html +35 -0
  115. data/spec/javascripts/templates/mercury/palette.html +16 -0
  116. data/spec/javascripts/templates/mercury/panel.html +16 -0
  117. data/spec/javascripts/templates/mercury/region.html +2 -0
  118. data/spec/javascripts/templates/mercury/regions/editable.html +3 -0
  119. data/spec/javascripts/templates/mercury/regions/image.html +1 -0
  120. data/spec/javascripts/templates/mercury/regions/simple.html +3 -0
  121. data/spec/javascripts/templates/mercury/regions/snippetable.html +4 -0
  122. data/spec/javascripts/templates/mercury/select.html +16 -0
  123. data/spec/javascripts/templates/mercury/snippet.html +1 -0
  124. data/spec/javascripts/templates/mercury/snippet_toolbar.html +16 -0
  125. data/spec/javascripts/templates/mercury/statusbar.html +8 -0
  126. data/spec/javascripts/templates/mercury/table_editor.html +65 -0
  127. data/spec/javascripts/templates/mercury/toolbar.button.html +64 -0
  128. data/spec/javascripts/templates/mercury/toolbar.button_group.html +9 -0
  129. data/spec/javascripts/templates/mercury/toolbar.expander.html +18 -0
  130. data/spec/javascripts/templates/mercury/toolbar.html +11 -0
  131. data/spec/javascripts/templates/mercury/tooltip.html +12 -0
  132. data/spec/javascripts/templates/mercury/uploader.html +11 -0
  133. data/vendor/assets/images/mercury/button.png +0 -0
  134. data/vendor/assets/images/mercury/close.png +0 -0
  135. data/vendor/assets/images/mercury/default-snippet.png +0 -0
  136. data/vendor/assets/images/mercury/loading-dark.gif +0 -0
  137. data/vendor/assets/images/mercury/loading-light.gif +0 -0
  138. data/vendor/assets/images/mercury/missing-image.png +0 -0
  139. data/vendor/assets/images/mercury/search-icon.png +0 -0
  140. data/vendor/assets/images/mercury/temp-logo.png +0 -0
  141. data/vendor/assets/images/mercury/toolbar/editable/buttons.png +0 -0
  142. data/vendor/assets/images/mercury/toolbar/primary/_expander.png +0 -0
  143. data/vendor/assets/images/mercury/toolbar/primary/_pressed.png +0 -0
  144. data/vendor/assets/images/mercury/toolbar/primary/historypanel.png +0 -0
  145. data/vendor/assets/images/mercury/toolbar/primary/insertcharacter.png +0 -0
  146. data/vendor/assets/images/mercury/toolbar/primary/insertlink.png +0 -0
  147. data/vendor/assets/images/mercury/toolbar/primary/insertmedia.png +0 -0
  148. data/vendor/assets/images/mercury/toolbar/primary/inserttable.png +0 -0
  149. data/vendor/assets/images/mercury/toolbar/primary/inspectorpanel.png +0 -0
  150. data/vendor/assets/images/mercury/toolbar/primary/notespanel.png +0 -0
  151. data/vendor/assets/images/mercury/toolbar/primary/preview.png +0 -0
  152. data/vendor/assets/images/mercury/toolbar/primary/redo.png +0 -0
  153. data/vendor/assets/images/mercury/toolbar/primary/save.png +0 -0
  154. data/vendor/assets/images/mercury/toolbar/primary/snippetpanel.png +0 -0
  155. data/vendor/assets/images/mercury/toolbar/primary/undo.png +0 -0
  156. data/vendor/assets/images/mercury/toolbar/snippetable/buttons.png +0 -0
  157. data/vendor/assets/javascripts/mercury.js +479 -0
  158. data/vendor/assets/javascripts/mercury/dependencies/jquery-1.7.js +9300 -0
  159. data/vendor/assets/javascripts/mercury/dependencies/jquery-ui-1.8.13.custom.js +1328 -0
  160. data/vendor/assets/javascripts/mercury/dependencies/jquery.additions.js +206 -0
  161. data/vendor/assets/javascripts/mercury/dependencies/jquery.htmlClean.js +527 -0
  162. data/vendor/assets/javascripts/mercury/dependencies/liquidmetal.js +88 -0
  163. data/vendor/assets/javascripts/mercury/dependencies/showdown.js +1340 -0
  164. data/vendor/assets/javascripts/mercury/dialog.js.coffee +159 -0
  165. data/vendor/assets/javascripts/mercury/dialogs/backcolor.js.coffee +6 -0
  166. data/vendor/assets/javascripts/mercury/dialogs/forecolor.js.coffee +6 -0
  167. data/vendor/assets/javascripts/mercury/dialogs/formatblock.js.coffee +4 -0
  168. data/vendor/assets/javascripts/mercury/dialogs/snippetpanel.js.coffee +10 -0
  169. data/vendor/assets/javascripts/mercury/dialogs/style.js.coffee +4 -0
  170. data/vendor/assets/javascripts/mercury/finalize.js.coffee +3 -0
  171. data/vendor/assets/javascripts/mercury/history_buffer.js.coffee +30 -0
  172. data/vendor/assets/javascripts/mercury/lightview.js.coffee +205 -0
  173. data/vendor/assets/javascripts/mercury/locales/ar.locale.js.coffee +207 -0
  174. data/vendor/assets/javascripts/mercury/locales/da.locale.js.coffee +211 -0
  175. data/vendor/assets/javascripts/mercury/locales/de.locale.js.coffee +206 -0
  176. data/vendor/assets/javascripts/mercury/locales/es.locale.js.coffee +211 -0
  177. data/vendor/assets/javascripts/mercury/locales/example.local.js.coffee +211 -0
  178. data/vendor/assets/javascripts/mercury/locales/fr.locale.js.coffee +211 -0
  179. data/vendor/assets/javascripts/mercury/locales/it.locale.js.coffee +208 -0
  180. data/vendor/assets/javascripts/mercury/locales/ko.local.js.coffee +206 -0
  181. data/vendor/assets/javascripts/mercury/locales/nl.locale.js.coffee +206 -0
  182. data/vendor/assets/javascripts/mercury/locales/pt.locale.js.coffee +211 -0
  183. data/vendor/assets/javascripts/mercury/locales/sv.local.js.coffee +209 -0
  184. data/vendor/assets/javascripts/mercury/locales/swedish_chef.locale.js.coffee +213 -0
  185. data/vendor/assets/javascripts/mercury/mercury.js.coffee +109 -0
  186. data/vendor/assets/javascripts/mercury/modal.js.coffee +198 -0
  187. data/vendor/assets/javascripts/mercury/modals/htmleditor.js.coffee +11 -0
  188. data/vendor/assets/javascripts/mercury/modals/insertcharacter.js.coffee +4 -0
  189. data/vendor/assets/javascripts/mercury/modals/insertlink.js.coffee +92 -0
  190. data/vendor/assets/javascripts/mercury/modals/insertmedia.js.coffee +81 -0
  191. data/vendor/assets/javascripts/mercury/modals/insertsnippet.js.coffee +12 -0
  192. data/vendor/assets/javascripts/mercury/modals/inserttable.js.coffee +54 -0
  193. data/vendor/assets/javascripts/mercury/native_extensions.js.coffee +55 -0
  194. data/vendor/assets/javascripts/mercury/page_editor.js.coffee +225 -0
  195. data/vendor/assets/javascripts/mercury/palette.js.coffee +29 -0
  196. data/vendor/assets/javascripts/mercury/panel.js.coffee +115 -0
  197. data/vendor/assets/javascripts/mercury/plugins/save_as_xml/mercury/page_editor.js.coffee +28 -0
  198. data/vendor/assets/javascripts/mercury/plugins/save_as_xml/plugin.js +9 -0
  199. data/vendor/assets/javascripts/mercury/region.js.coffee +107 -0
  200. data/vendor/assets/javascripts/mercury/regions/editable.js.coffee +600 -0
  201. data/vendor/assets/javascripts/mercury/regions/image.js.coffee +114 -0
  202. data/vendor/assets/javascripts/mercury/regions/markupable.js.coffee +398 -0
  203. data/vendor/assets/javascripts/mercury/regions/simple.js.coffee +325 -0
  204. data/vendor/assets/javascripts/mercury/regions/snippetable.js.coffee +124 -0
  205. data/vendor/assets/javascripts/mercury/select.js.coffee +44 -0
  206. data/vendor/assets/javascripts/mercury/snippet.js.coffee +106 -0
  207. data/vendor/assets/javascripts/mercury/snippet_toolbar.js.coffee +72 -0
  208. data/vendor/assets/javascripts/mercury/statusbar.js.coffee +51 -0
  209. data/vendor/assets/javascripts/mercury/support/history.js +1 -0
  210. data/vendor/assets/javascripts/mercury/table_editor.js.coffee +265 -0
  211. data/vendor/assets/javascripts/mercury/toolbar.button.js.coffee +173 -0
  212. data/vendor/assets/javascripts/mercury/toolbar.button_group.js.coffee +42 -0
  213. data/vendor/assets/javascripts/mercury/toolbar.expander.js.coffee +56 -0
  214. data/vendor/assets/javascripts/mercury/toolbar.js.coffee +86 -0
  215. data/vendor/assets/javascripts/mercury/tooltip.js.coffee +74 -0
  216. data/vendor/assets/javascripts/mercury/uploader.js.coffee +244 -0
  217. data/vendor/assets/javascripts/mercury_loader.js +193 -0
  218. data/vendor/assets/javascripts/mercury_overrides.js +6 -0
  219. data/vendor/assets/stylesheets/mercury.css +28 -0
  220. data/vendor/assets/stylesheets/mercury/all_images.css.erb +89 -0
  221. data/vendor/assets/stylesheets/mercury/dialog.css +212 -0
  222. data/vendor/assets/stylesheets/mercury/form.css +118 -0
  223. data/vendor/assets/stylesheets/mercury/lightview.css +151 -0
  224. data/vendor/assets/stylesheets/mercury/mercury.css +37 -0
  225. data/vendor/assets/stylesheets/mercury/modal.css +183 -0
  226. data/vendor/assets/stylesheets/mercury/statusbar.css +32 -0
  227. data/vendor/assets/stylesheets/mercury/toolbar.css +304 -0
  228. data/vendor/assets/stylesheets/mercury/tooltip.css +26 -0
  229. data/vendor/assets/stylesheets/mercury/uploader.css +111 -0
  230. data/vendor/assets/stylesheets/mercury_overrides.css +17 -0
  231. metadata +572 -0
@@ -0,0 +1,110 @@
1
+ @javascript
2
+ Feature:
3
+ As a content editor type person
4
+ In order to manage content
5
+ I should be able to insert different types of media
6
+
7
+ Background:
8
+ Given I am on an editable page
9
+ And the editor won't prompt when leaving the page
10
+
11
+ Scenario: A user can expect all this!
12
+
13
+
14
+ # Scenario: A user can insert and edit an image
15
+ Given the content of the editable region is simple content
16
+ And I make a selection
17
+
18
+ When I click on the "Insert Media" button
19
+ Then the modal window should be visible
20
+ And I should see "Insert Media (images and videos)" within the modal title
21
+
22
+ When I fill in "URL" with "/assets/mercury/temp-logo.png"
23
+ And press "Insert Media"
24
+ Then the contents of the editable region should be "this is <img src='/assets/mercury/temp-logo.png'> <b>content</b>"
25
+ And the modal window should not be visible
26
+
27
+ When I make a selection for "img"
28
+ And click on the "Insert Media" button
29
+ Then the "media_image_url" field should contain "/assets/mercury/temp-logo.png"
30
+
31
+ When I fill in "URL" with "/assets/mercury/default-snippet.png"
32
+ And press "Insert Media"
33
+ Then the contents of the editable region should be "this is <img src='/assets/mercury/default-snippet.png'> <b>content</b>"
34
+
35
+
36
+ # Scenario: A user can insert and edit an image with an alignment set
37
+ Given the content of the editable region is simple content
38
+ And I make a selection
39
+
40
+ When I click on the "Insert Media" button
41
+ When I fill in "media_image_url" with "/assets/mercury/temp-logo.png"
42
+ And select "Right" from "Alignment"
43
+ And press "Insert Media"
44
+ Then the contents of the editable region should be "this is <img src='/assets/mercury/temp-logo.png' align='right'> <b>content</b>"
45
+
46
+ When I make a selection for "img"
47
+ And click on the "Insert Media" button
48
+ And select "Absolute Middle" from "Alignment"
49
+ And press "Insert Media"
50
+ Then the contents of the editable region should be "this is <img src='/assets/mercury/temp-logo.png' align='absmiddle'> <b>content</b>"
51
+
52
+
53
+ Scenario: A user can edit an image by double clicking it
54
+ Given the content of the editable region has an image
55
+
56
+ When I double click on the first image in the editable region
57
+ Then the modal window should be visible
58
+ And I should see "Insert Media (images and videos)" within the modal title
59
+ And the "media_image_url" field should contain "/assets/mercury/temp-logo.png"
60
+
61
+ When I fill in "URL" with "/assets/mercury/default-snippet.png"
62
+ And select "Absolute Middle" from "Alignment"
63
+ And press "Insert Media"
64
+ Then the contents of the editable region should be "this is <img src='/assets/mercury/default-snippet.png' align='absmiddle'> <b>content</b>"
65
+
66
+
67
+ Scenario: A user can embed and edit a youtube video
68
+ Given the content of the editable region is simple content
69
+ And I make a selection
70
+
71
+ When I click on the "Insert Media" button
72
+ And choose "YouTube Share URL"
73
+ And fill in "YouTube Share URL" with "http://youtu.be/Pny4hoN8eII"
74
+ And fill in "Width" with "400"
75
+ And fill in "Height" with "200"
76
+ And press "Insert Media"
77
+ Then the contents of the editable region should be "this is <iframe allowfullscreen='true' src='http://www.youtube.com/embed/Pny4hoN8eII?wmode=transparent' style='width: 400px; height: 200px;' frameborder='0'></iframe> <b>content</b>"
78
+
79
+ When I make a selection for "iframe"
80
+ And click on the "Insert Media" button
81
+ Then the "media_youtube_url" field should contain "http://youtu.be/Pny4hoN8eII"
82
+
83
+ When I fill in "YouTube Share URL" with "http://youtu.be/Pny4hoN8eI"
84
+ And fill in "Width" with "500"
85
+ And fill in "Height" with "300"
86
+ And press "Insert Media"
87
+ Then the contents of the editable region should be "this is <iframe allowfullscreen='true' src='http://www.youtube.com/embed/Pny4hoN8eI?wmode=transparent' style='width: 500px; height: 300px;' frameborder='0'></iframe> <b>content</b>"
88
+
89
+
90
+ # Scenario: A user can embed and edit a vimeo video
91
+ Given the content of the editable region is simple content
92
+ And I make a selection
93
+
94
+ When I click on the "Insert Media" button
95
+ And choose "Vimeo URL"
96
+ And fill in "Vimeo URL" with "http://vimeo.com/25708134"
97
+ And fill in "Width" with "400"
98
+ And fill in "Height" with "200"
99
+ And press "Insert Media"
100
+ Then the contents of the editable region should be "this is <iframe src='http://player.vimeo.com/video/25708134?title=1&amp;byline=1&amp;portrait=0&amp;color=ffffff' style='width: 400px; height: 200px;' frameborder='0'></iframe> <b>content</b>"
101
+
102
+ When I make a selection for "iframe"
103
+ And click on the "Insert Media" button
104
+ Then the "media_vimeo_url" field should contain "http://vimeo.com/25708134"
105
+
106
+ When I fill in "Vimeo URL" with "http://vimeo.com/2570813"
107
+ And fill in "Width" with "500"
108
+ And fill in "Height" with "300"
109
+ And press "Insert Media"
110
+ Then the contents of the editable region should be "this is <iframe src='http://player.vimeo.com/video/2570813?title=1&amp;byline=1&amp;portrait=0&amp;color=ffffff' style='width: 500px; height: 300px;' frameborder='0'></iframe> <b>content</b>"
@@ -0,0 +1,102 @@
1
+ @javascript
2
+ Feature:
3
+ As a content editor type person
4
+ In order to reuse content chunks
5
+ I should be able to put snippets into regions
6
+
7
+ Background:
8
+ Given I am on an editable page
9
+ And the editor won't prompt when leaving the page
10
+
11
+ Scenario: A user can expect all this!
12
+
13
+
14
+ # todo: these can't be one scenario because snippet.load doesn't find/replace existing ones
15
+ Scenario: A user can drag and drop snippets into an editable region
16
+ Given the content of the editable region is simple content
17
+ And I make a selection
18
+
19
+ When I open the snippet panel
20
+ And I drag the example snippet into the editable region
21
+ Then the modal window should be visible
22
+ And I should see "Snippet Options" within the modal title
23
+
24
+ When I fill in "First Name" with "Jeremy"
25
+ And fill in "Favorite Beer" with "Stella"
26
+ And press "Insert Snippet"
27
+ Then the modal window should not be visible
28
+ And the contents of the editable region should be "this is <div data-version='1' data-snippet='snippet_14' class='mercury-snippet example-snippet' contenteditable='false'><strong>Jeremy</strong> likes Stella</div><span>simple</span> <b>content</b>"
29
+
30
+
31
+ Scenario: A user can use the snippet toolbar to remove a snippet
32
+ Given the options for the example snippet "snippet_42" are first_name: "Jeremy", favorite_beer: "Stella"
33
+ And the content of the editable region has that snippet
34
+
35
+ When I hover over the snippet
36
+ Then the snippet toolbar should be visible
37
+
38
+ When I click on the remove snippet toolbar button
39
+ Then the contents of the editable region should be " <b>content</b>"
40
+
41
+
42
+ Scenario: A user can use the snippet toolbar to edit the options of a snippet
43
+ Given the options for the example snippet "snippet_42" are first_name: "Hipsters", favorite_beer: "PBR"
44
+ And the content of the editable region has that snippet
45
+
46
+ When I hover over the snippet
47
+ And click on the edit snippet settings toolbar button
48
+ Then the modal window should be visible
49
+ And the "First Name" field should contain "Hipsters"
50
+ And the "Favorite Beer" field should contain "PBR"
51
+
52
+ When I fill in "First Name" with "Jeremy"
53
+ And fill in "Favorite Beer" with "Stella"
54
+ And press "Insert Snippet"
55
+ Then the contents of the editable region should be "<div data-version='2' data-snippet='snippet_42' class='mercury-snippet example-snippet' contenteditable='false'><strong>Jeremy</strong> likes Stella</div> <b>content</b>"
56
+
57
+
58
+ Scenario: A user can make changes to a snippets options, and they'll be versioned for undo and redo
59
+ Given the options for the example snippet "snippet_42" are first_name: "Hipsters", favorite_beer: "PBR"
60
+ And the content of the editable region has that snippet
61
+
62
+ When I edit the snippet
63
+ And I fill in "First Name" with "Jeremy"
64
+ And fill in "Favorite Beer" with "Stella"
65
+ And press "Insert Snippet"
66
+ Then the contents of the editable region should be "<div data-version='2' data-snippet='snippet_42' class='mercury-snippet example-snippet' contenteditable='false'><strong>Jeremy</strong> likes Stella</div> <b>content</b>"
67
+
68
+ When I edit the snippet
69
+ Then the "First Name" field should contain "Jeremy"
70
+ And the "Favorite Beer" field should contain "Stella"
71
+
72
+ When fill in "First Name" with "Diesel"
73
+ And fill in "Favorite Beer" with "Bells Hopslam"
74
+ And press "Insert Snippet"
75
+ Then the content of the editable region should be "<div data-version='3' data-snippet='snippet_42' class='mercury-snippet example-snippet' contenteditable='false'><strong>Diesel</strong> likes Bells Hopslam</div> <b>content</b>"
76
+
77
+ When I click on the "Undo" button
78
+ Then the contents of the editable region should be "<div data-version='2' data-snippet='snippet_42' class='mercury-snippet example-snippet' contenteditable='false'><strong>Jeremy</strong> likes Stella</div> <b>content</b>"
79
+
80
+ When I edit the snippet
81
+ # todo: this is a bug
82
+ # Then the "First Name" field should contain "Jeremy"
83
+ # And the "Favorite Beer" field should contain "Stella"
84
+
85
+ When I close the modal
86
+ When I click on the "Redo" button
87
+ Then the contents of the editable region should be "<div data-version='3' data-snippet='snippet_42' class='mercury-snippet example-snippet' contenteditable='false'><strong>Diesel</strong> likes Bells Hopslam</div> <b>content</b>"
88
+
89
+ When I edit the snippet
90
+ Then the "First Name" field should contain "Diesel"
91
+ And the "Favorite Beer" field should contain "Bells Hopslam"
92
+
93
+ When I fill in "First Name" with "Jen"
94
+ And fill in "Favorite Beer" with "Miller High Life"
95
+ And press "Insert Snippet"
96
+ Then the contents of the editable region should be "<div data-version='4' data-snippet='snippet_42' class='mercury-snippet example-snippet' contenteditable='false'><strong>Jen</strong> likes Miller High Life</div> <b>content</b>"
97
+
98
+
99
+ # Scenario: When a user saves, the snippets should be gone from the html, but the options are serialized
100
+ # Given the options for the example snippet "snippet_42" are first_name: "Hipsters", favorite_beer: "PBR"
101
+ # And the content of the editable region has that snippet
102
+ # When I click on the "Save" button
@@ -0,0 +1,24 @@
1
+ @javascript
2
+ Feature:
3
+ As a content editor type person
4
+ In order to manage content
5
+ I should be able to insert characters that are otherwise hard
6
+
7
+ Background:
8
+ Given I am on an editable page
9
+ And the editor won't prompt when leaving the page
10
+
11
+ Scenario: A user can expect all this!
12
+
13
+
14
+ # Scenario: A user can insert special characters
15
+ Given the content of the editable region is simple content
16
+ And I make a selection
17
+
18
+ When I click on the "Insert Character" button
19
+ Then the modal window should be visible
20
+ And I should see "Special Characters" within the modal title
21
+
22
+ When I click on the sweet snowman
23
+ Then the modal window should not be visible
24
+ And the contents of the editable region should be "this is ☃ <b>content</b>"
@@ -0,0 +1,109 @@
1
+ @javascript
2
+ Feature:
3
+ As a content editor type person
4
+ In order to manage content
5
+ I should be able to insert and edit complex tables
6
+
7
+ Background:
8
+ Given I am on an editable page
9
+ And the editor won't prompt when leaving the page
10
+
11
+ Scenario: A user can expect all this!
12
+
13
+
14
+ # Scenario: A user can insert a table
15
+ Given the content of the editable region is simple content
16
+ And I make a selection
17
+
18
+ When I click on the "Insert Table" button
19
+ Then the modal window should be visible
20
+ And I should see "Insert Table" within the modal title
21
+
22
+ When I click on the third cell in the first row
23
+ And I add a column before it
24
+ Then the table column count should be 4
25
+ And the selected cell should be the forth cell in the first row
26
+
27
+ When I add a column after
28
+ Then the table column count should be 5
29
+ And the selected cell should be the forth cell in the first row
30
+
31
+ When I add a row after
32
+ Then the table row count should be 3
33
+ And the selected cell should be the forth cell in the first row
34
+
35
+ When I add a row before
36
+ Then the table row count should be 4
37
+ And the selected cell should be the forth cell in the second row
38
+
39
+ When I delete the column
40
+ Then the table column count should be 4
41
+ And a selected cell should not be visible
42
+
43
+ When I click on the second cell in the second row
44
+ And delete the row
45
+ Then the table row count should be 3
46
+ And a selected cell should not be visible
47
+
48
+ When I click on the second cell in the second row
49
+ And increase the colspan
50
+ And click on the first cell in the first row
51
+ And increase the rowspan
52
+ And select "Right" from "Alignment"
53
+ And fill in "Border" with "2"
54
+ And fill in "Spacing" with "2"
55
+ And press "Insert Table"
56
+ Then the contents of the editable region should be "this is&nbsp;<table align='right' border='2' cellspacing='2'><tbody><tr><td rowspan='2'><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td colspan='2'><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table> <b>content</b>"
57
+ And the modal window should not be visible
58
+
59
+
60
+ # Scenario: A user can edit a table after inserting one (in an editable region)
61
+ Given the content of the editable region has a table
62
+ And I make a selection
63
+
64
+ When I click on the add row before editor button
65
+ Then the table row count should be 3
66
+ And the contents of the editable region should be "this is a <table><tbody><tr><td><br></td><td><br></td></tr><tr><td><span>1</span></td><td><span>2</span></td></tr><tr><td><span>3</span></td><td><span>4</span></td></tr></tbody></table> <b>content</b>"
67
+
68
+ When I click on the add row after editor button
69
+ Then the table row count should be 4
70
+ And the contents of the editable region should be "this is a <table><tbody><tr><td><br></td><td><br></td></tr><tr><td><span>1</span></td><td><span>2</span></td></tr><tr><td><br></td><td><br></td></tr><tr><td><span>3</span></td><td><span>4</span></td></tr></tbody></table> <b>content</b>"
71
+
72
+ When I click on the add column before editor button
73
+ Then the column count should be 3
74
+ And the contents of the editable region should be "this is a <table><tbody><tr><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><span>1</span></td><td><span>2</span></td></tr><tr><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><span>3</span></td><td><span>4</span></td></tr></tbody></table> <b>content</b>"
75
+
76
+ When I click on the add column after editor button
77
+ Then the column count should be 4
78
+ And the contents of the editable region should be "this is a <table><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><span>1</span></td><td><br></td><td><span>2</span></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><span>3</span></td><td><br></td><td><span>4</span></td></tr></tbody></table> <b>content</b>"
79
+
80
+ When I click on the delete row editor button
81
+ Then the table row count should be 3
82
+ And the contents of the editable region should be "this is a <table><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><span>3</span></td><td><br></td><td><span>4</span></td></tr></tbody></table> <b>content</b>"
83
+
84
+ When I make a selection
85
+ And click on the delete column editor button
86
+ Then the table column count should be 3
87
+ And the contents of the editable region should be "this is a <table><tbody><tr><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><span>4</span></td></tr></tbody></table> <b>content</b>"
88
+
89
+
90
+ # Scenario: A user can adjust the colspans of a table (in an editable region)
91
+ Given the content of the editable region has a table
92
+ And I make a selection
93
+
94
+ When I click on the increase colspan editor button
95
+ Then the contents of the editable region should be "this is a <table><tbody><tr><td colspan='2'><span>1</span></td></tr><tr><td><span>3</span></td><td><span>4</span></td></tr></tbody></table> <b>content</b>"
96
+
97
+ When I click on the decrease colspan editor button
98
+ Then the contents of the editable region should be "this is a <table><tbody><tr><td><span>1</span></td><td><br></td></tr><tr><td><span>3</span></td><td><span>4</span></td></tr></tbody></table> <b>content</b>"
99
+
100
+
101
+ # Scenario: A user can adjust the rowspans of a table (in an editable region)
102
+ Given the content of the editable region has a table
103
+ And I make a selection
104
+
105
+ When I click on the increase rowspan editor button
106
+ Then the contents of the editable region should be "this is a <table><tbody><tr><td rowspan='2'><span>1</span></td><td><span>2</span></td></tr><tr><td><span>4</span></td></tr></tbody></table> <b>content</b>"
107
+
108
+ When I click on the decrease rowspan editor button
109
+ Then the contents of the editable region should be "this is a <table><tbody><tr><td><span>1</span></td><td><span>2</span></td></tr><tr><td><br></td><td><span>4</span></td></tr></tbody></table> <b>content</b>"
File without changes
File without changes
File without changes
@@ -0,0 +1,5 @@
1
+ @javascript
2
+ Feature:
3
+ As a content editor type person
4
+ In order to manage content
5
+ I should be able to manipulate text
@@ -0,0 +1,33 @@
1
+ @javascript
2
+ Feature:
3
+ As a content editor type person
4
+ In order to manage content
5
+ I should be able to save the content
6
+
7
+ Background:
8
+ Given I am on an editable page
9
+ And save results will be cached
10
+
11
+
12
+ Scenario: A user can change content in an editable region and save those changes
13
+ When I set the content of the editable region to "new content"
14
+ And I click on the "Save" button
15
+ Then the save should have "new content" for the editable region
16
+
17
+
18
+ Scenario: A user can change content in a markupable region and save those changes
19
+ When I set the content of the markupable region to "new content"
20
+ And I click on the "Save" button
21
+ Then the save should have "new content" for the markupable region
22
+
23
+
24
+ Scenario: A user can put snippets into an editable region and get the options on save
25
+ # todo: finish
26
+
27
+
28
+ Scenario: A user can expect the right version of the snippet options to be saved
29
+ # todo: finish
30
+
31
+
32
+ Scenario: A user can put snippets into a markupable region and get the options on save
33
+ # todo: finish
@@ -0,0 +1,14 @@
1
+ # DEBUG / DELAY STEPS
2
+ #------------------------------------------------------------------------------
3
+
4
+ When /^(?:|I )sleep for (\d+) seconds?$/ do |seconds|
5
+ sleep(seconds.to_i)
6
+ end
7
+
8
+ When /^I debug$/ do
9
+ puts 'Debugging...'
10
+ unless ENV['RUBYMINE'].present?
11
+ require 'debug'
12
+ debugger
13
+ end
14
+ end
@@ -0,0 +1,438 @@
1
+ ## Generic web steps
2
+ #------------------------------------------------------------------------------
3
+ When /^(?:|I )click on (.+)$/ do |locator|
4
+ selector = selector_for(locator)
5
+ find(selector, :message => "Unable to locate the element '#{selector}' to click on").click
6
+ end
7
+
8
+ Then /^(.+) should (not )?be visible$/ do |locator, boolean|
9
+ selector = selector_for(locator)
10
+ if boolean == 'not '
11
+ page.has_no_css?("#{selector}")
12
+ else
13
+ page.has_css?("#{selector}", :visible => true)
14
+ end
15
+ end
16
+
17
+ # scoping step for different windows
18
+ When /^(.*) in the "([^"]*)" window$/ do |s, window|
19
+ page.driver.within_window(window) do
20
+ step(s)
21
+ end
22
+ end
23
+
24
+
25
+ ## Mercury general steps
26
+ #------------------------------------------------------------------------------
27
+ Given /^(?:|I )adjust the configuration to have: \{([^\}]*)\}$/ do |javascript|
28
+ Rails.application.config.mercury_config = JSON.parse("{#{javascript}}")
29
+ end
30
+
31
+ # scoping step for the mercury content frame
32
+ When /^(.*) in the content frame$/ do |s|
33
+ page.driver.within_frame('mercury_iframe') do
34
+ step(s)
35
+ end
36
+ end
37
+
38
+ # silence mercury's onbeforeunload confirmation
39
+ Given /^the editor won't prompt when leaving the page$/ do
40
+ page.driver.execute_script('Mercury.silent = true;')
41
+ end
42
+
43
+
44
+ ## Toolbar specific steps
45
+ #------------------------------------------------------------------------------
46
+ # for the select dropdowns
47
+ When /^(?:|I )select (.*?) from the dropdown$/ do |locator|
48
+ selector = selector_for(locator)
49
+ find(selector, :message => "Unable to locate the element '#{selector}' to click on").click
50
+ end
51
+
52
+
53
+ ## Panel specific steps
54
+ #------------------------------------------------------------------------------
55
+ When /^(?:I )(?:open|close|toggle) the (.*?) panel$/ do |panel_locator|
56
+ step(%Q{I click on the "#{panel_locator}" button})
57
+ end
58
+
59
+
60
+ ## Modal specific steps
61
+ #------------------------------------------------------------------------------
62
+ When /^(?:I )close the modal(?: window)?$/ do
63
+ step(%Q{I click on the modal close button})
64
+ end
65
+
66
+
67
+ ## Region specific steps
68
+ #------------------------------------------------------------------------------
69
+ # setting content
70
+ Given /^the content of (.*?) (?:is|are|has|includes) (.*?)$/ do |region_locator, contents|
71
+ step(%Q{I set the contents of #{region_locator} to #{contents}})
72
+ end
73
+
74
+ When /^(?:|I )(?:change|set) the contents? of (.*?) to (.*?)$/ do |region_locator, contents|
75
+ region_id = region_selector_for(region_locator).gsub('#', '')
76
+ content = contents[0] == '"' ? contents : "\"#{contents_for(contents)}\""
77
+ page.driver.within_frame('mercury_iframe') do
78
+ find("##{region_id}", :message => "Unable to locate a region matching '##{region_id}'")
79
+ page.driver.execute_script <<-JAVASCRIPT
80
+ var element = top.jQuery(document).find('##{region_id}');
81
+ if (element.data('type') == 'markupable') {
82
+ element.find('textarea').val(#{content});
83
+ } else {
84
+ var region = top.mercuryInstance.getRegionByName('#{region_id}');
85
+ region.content(#{content});
86
+ }
87
+ JAVASCRIPT
88
+ end
89
+ end
90
+
91
+ # setting/making selections
92
+ When /^(?:|I )(?:make|have) a selection$/ do
93
+ step(%Q{I have a selection for "span"})
94
+ end
95
+
96
+ When /^(?:|I )(?:make|have) a selection (?:in (.*?) )?for "([^"]*)"$/ do |region_locator, selector|
97
+ step(%Q{I can simulate complex javascript events})
98
+ # assume the first editable region if one wasn't provided'
99
+ region_selector = region_selector_for(region_locator || 'the editable region')
100
+ page.driver.within_frame('mercury_iframe') do
101
+ find("#{region_selector}", :message => "Unable to locate a region matching '#{region_selector}'")
102
+ find("#{region_selector} #{selector}", :message => "Unable to locate a match for '#{selector}' inside '#{region_locator}'")
103
+ page.driver.execute_script <<-JAVASCRIPT
104
+ var element = top.jQuery(document).find('#{region_selector}');
105
+ if (element.data('type') == 'markupable') {
106
+ alert('unimplemented');
107
+ throw('unimplemented');
108
+ } else {
109
+ var selectedElement = element.find('#{selector}');
110
+ var selection = new top.Mercury.Regions.Editable.Selection(window.getSelection(), document);
111
+ selection.selectNode(selectedElement.get(0));
112
+ selectedElement.simulate('mouseup');
113
+ }
114
+ JAVASCRIPT
115
+ end
116
+ end
117
+
118
+ # other events
119
+ When /^(?:|I )double click on (.*?) in (.*?)$/ do |locator, region_locator|
120
+ step(%Q{I can simulate complex javascript events})
121
+ selector = selector_for(locator)
122
+ # assume the first editable region if one wasn't provided'
123
+ region_selector = region_selector_for(region_locator || 'the editable region')
124
+ page.driver.within_frame('mercury_iframe') do
125
+ find("#{region_selector}", :message => "Unable to locate a region matching '#{region_selector}'")
126
+ find("#{region_selector} #{selector}", :message => "Unable to locate a match for '#{selector}' inside '#{region_locator}'")
127
+ page.driver.execute_script <<-JAVASCRIPT
128
+ top.jQuery(document).find('#{region_selector} #{selector}').simulate('dblclick');
129
+ JAVASCRIPT
130
+ end
131
+ end
132
+
133
+ # getting contents
134
+ Then /^the contents? of (.*?) should be "([^"]*)"$/ do |region_locator, content|
135
+ region_selector = region_selector_for(region_locator)
136
+ page.driver.within_frame('mercury_iframe') do
137
+ find("#{region_selector}", :message => "Unable to locate a region matching '#{region_selector}'")
138
+ results = page.driver.execute_script <<-JAVASCRIPT
139
+ var element = top.jQuery(document).find('#{region_selector}');
140
+ if (element.data('type') == 'markupable') {
141
+ return element.find('textarea').val();
142
+ } else {
143
+ return element.html();
144
+ }
145
+ JAVASCRIPT
146
+ assert_equal content, results.gsub('"', "'").gsub("\n", '')
147
+ end
148
+ end
149
+
150
+
151
+ ## Saving specific steps
152
+ #------------------------------------------------------------------------------
153
+ # caching for the last save -- a request will still be made
154
+ Given /^save results will be cached$/ do
155
+ page.driver.execute_script <<-JAVASCRIPT
156
+ Mercury.PageEditor.prototype.save = function() {
157
+ window.cachedResults = this.serialize();
158
+ }
159
+ JAVASCRIPT
160
+ end
161
+
162
+ # check for the last save cached results
163
+ Then /^the save should have (.*?) for (.*?)$/ do |contents, region_locator|
164
+ region_id = region_selector_for(region_locator).gsub('#', '')
165
+ content = contents[0] == '"' ? contents : "\"#{contents_for(contents)}\""
166
+ results = page.driver.execute_script <<-JAVASCRIPT
167
+ return (window.cachedResults['#{region_id}']) ?
168
+ window.cachedResults['#{region_id}']['value'] : null;
169
+ JAVASCRIPT
170
+ assert_equal content, "\"#{results}\""
171
+ end
172
+
173
+
174
+ ## Table editing specific steps
175
+ #------------------------------------------------------------------------------
176
+ # in the modal window
177
+ When /^(?:|I )(?:add|insert) a (row|column) (before|after)(?: it)?$/ do |row_or_column, before_or_after|
178
+ name = "insert_#{row_or_column}_#{before_or_after}".camelcase(:lower)
179
+ step(%Q{I click on ".mercury-modal-content input[name=#{name}]"})
180
+ end
181
+
182
+ When /^(?:|I )delete the(?: current)? (row|column)$/ do |row_or_column|
183
+ name = "delete_#{row_or_column}".camelcase(:lower)
184
+ step(%Q{I click on ".mercury-modal-content input[name=#{name}]"})
185
+ end
186
+
187
+ When /^(?:|I )(increase|decrease) the (rowspan|colspan)$/ do |increase_or_decrease, rowspan_or_colspan|
188
+ name = "#{increase_or_decrease}_#{rowspan_or_colspan}".camelcase(:lower)
189
+ step(%Q{I click on ".mercury-modal-content input[name=#{name}]"})
190
+ end
191
+
192
+ Then /^the selected cell should be (.*?)$/ do |locator|
193
+ selector = selector_for(locator).gsub('td:', 'td.selected:')
194
+ find("#{selector}", :message => "Unable to locate the selected cell for '#{selector}'")
195
+ end
196
+
197
+ # in general
198
+ Then /^the(?: table)? (row|column) count should be (\d+)$/ do |row_or_column, expected_count|
199
+ method = "get_#{row_or_column}_count".camelcase(:lower)
200
+ actual_count = page.driver.execute_script("return Mercury.tableEditor.#{method}()")
201
+ assert_equal expected_count.to_i, actual_count.to_i
202
+ end
203
+
204
+
205
+ ## Snippet specific steps
206
+ #------------------------------------------------------------------------------
207
+ # setting snippet options
208
+ Given /^the options for the (.*?) snippet "([^"]*)" are (.*?)$/ do |snippet_name, snippet_id, options|
209
+ @snippet_id = snippet_id
210
+ options_json = parse_snippet_options_from(options)
211
+ page.driver.execute_script <<-JAVASCRIPT
212
+ Mercury.Snippet.load({#{snippet_id}: {name: '#{snippet_name}', options: #{options_json}}});
213
+ JAVASCRIPT
214
+ end
215
+
216
+ # dragging/dropping
217
+ When /^(?:|I )(?:drag|drop) (.*?) (?:into|on) (.*?)$/ do |snippet_locator, region_locator|
218
+ snippet_name = snippet_name_for(snippet_locator)
219
+ region_id = region_selector_for(region_locator).gsub('#', '')
220
+ page.driver.within_frame('mercury_iframe') do
221
+ find("##{region_id}", :message => "Unable to locate a region matching '##{region_id}'")
222
+ page.driver.execute_script <<-JAVASCRIPT
223
+ var element = top.jQuery(document).find('##{region_id}');
224
+ if (element.data('type') == 'markupable') {
225
+ alert('unimplemented');
226
+ throw('unimplemented');
227
+ } else {
228
+ var region = top.mercuryInstance.getRegionByName('#{region_id}');
229
+ region.selection().range.collapse(true);
230
+ document.execCommand('insertHTML', false, '<img data-snippet="#{snippet_name}" src="/assets/mercury/default-snippet.png">');
231
+ element.trigger('possible:drop');
232
+ }
233
+ JAVASCRIPT
234
+ end
235
+ end
236
+
237
+ When /^(?:|I )hover over (.*?)(?: in (.*?))?$/ do |locator, region_locator|
238
+ step(%Q{I can simulate complex javascript events})
239
+ selector = selector_for(locator)
240
+ region_selector = region_selector_for(region_locator || 'the editable region')
241
+ page.driver.within_frame('mercury_iframe') do
242
+ find("#{region_selector}", :message => "Unable to locate a region matching '#{region_selector}'")
243
+ page.driver.execute_script <<-JAVASCRIPT
244
+ var element = top.jQuery(document).find('#{region_selector}');
245
+ if (element.data('type') == 'markupable') {
246
+ alert('unimplemented');
247
+ throw('unimplemented');
248
+ } else {
249
+ element.find('#{selector}').simulate('mousemove');
250
+ }
251
+ JAVASCRIPT
252
+ end
253
+ end
254
+
255
+ When /^(?:|I )edit the snippet$/ do
256
+ step(%{I hover over the snippet})
257
+ step(%{click on the edit snippet settings toolbar button})
258
+ end
259
+
260
+
261
+ ## Dropping image specific steps
262
+ #------------------------------------------------------------------------------
263
+ #When /^(?:|I )drop an image into (.*?) from a different browser/ do |region_locator|
264
+ # Given(%Q{I can simulate complex javascript events})
265
+ # region_selector = region_selector_for(region_locator || 'the editable region')
266
+ # page.driver.within_frame('mercury_iframe') do
267
+ # find("#{region_selector}", :message => "Unable to locate a region matching '#{region_selector}'")
268
+ # page.driver.execute_script <<-JAVASCRIPT
269
+ # var element = top.jQuery(document).find('#{region_selector}');
270
+ # if (element.data('type') == 'markupable') {
271
+ # alert('unimplemented');
272
+ # throw('unimplemented');
273
+ # } else {
274
+ # element.find('#{region_selector}').simulate('drop', {'text/html': '<img src="testing.gif"/>'});
275
+ # }
276
+ # JAVASCRIPT
277
+ # end
278
+ #end
279
+
280
+
281
+ ## Javascript event simulation steps
282
+ #------------------------------------------------------------------------------
283
+ Given /^(?:|I )can simulate complex javascript events$/ do
284
+ page.driver.execute_script(EVENT_SIMULATION_JAVASCRIPT)
285
+ end
286
+
287
+ #------------------------------------------------------------------------------
288
+
289
+ EVENT_SIMULATION_JAVASCRIPT = <<-JAVASCRIPT
290
+ /*
291
+ * jquery.simulate - simulate browser mouse and keyboard events
292
+ *
293
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
294
+ * Dual licensed under the MIT or GPL Version 2 licenses.
295
+ * http://jquery.org/license
296
+ *
297
+ */
298
+ ;(function($) {
299
+
300
+ $.fn.extend({
301
+ simulate: function(type, options) {
302
+ return this.each(function() {
303
+ var opt = $.extend({}, $.simulate.defaults, options || {});
304
+ new $.simulate(this, type, opt);
305
+ });
306
+ }
307
+ });
308
+
309
+ $.simulate = function(el, type, options) {
310
+ this.target = el;
311
+ this.options = options;
312
+
313
+ if (/^drag$/.test(type)) {
314
+ this[type].apply(this, [this.target, options]);
315
+ } else {
316
+ this.simulateEvent(el, type, options);
317
+ }
318
+ }
319
+
320
+ $.extend($.simulate.prototype, {
321
+ simulateEvent: function(el, type, options) {
322
+ var evt = this.createEvent(type, options);
323
+ this.dispatchEvent(el, type, evt, options);
324
+ return evt;
325
+ },
326
+ createEvent: function(type, options) {
327
+ if (/^mouse(over|out|down|up|move)|(dbl)?click$/.test(type)) {
328
+ return this.mouseEvent(type, options);
329
+ } else if (/^key(up|down|press)$/.test(type)) {
330
+ return this.keyboardEvent(type, options);
331
+ }
332
+ },
333
+ mouseEvent: function(type, options) {
334
+ var evt;
335
+ var e = $.extend({
336
+ bubbles: true, cancelable: (type != "mousemove"), view: window, detail: 0,
337
+ screenX: 0, screenY: 0, clientX: 0, clientY: 0,
338
+ ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
339
+ button: 0, relatedTarget: undefined
340
+ }, options);
341
+
342
+ var relatedTarget = $(e.relatedTarget)[0];
343
+
344
+ if ($.isFunction(document.createEvent)) {
345
+ evt = document.createEvent("MouseEvents");
346
+ evt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail,
347
+ e.screenX, e.screenY, e.clientX, e.clientY,
348
+ e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
349
+ e.button, e.relatedTarget || document.body.parentNode);
350
+ } else if (document.createEventObject) {
351
+ evt = document.createEventObject();
352
+ $.extend(evt, e);
353
+ evt.button = { 0:1, 1:4, 2:2 }[evt.button] || evt.button;
354
+ }
355
+ return evt;
356
+ },
357
+ keyboardEvent: function(type, options) {
358
+ var evt;
359
+
360
+ var e = $.extend({ bubbles: true, cancelable: true, view: window,
361
+ ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
362
+ keyCode: 0, charCode: 0
363
+ }, options);
364
+
365
+ if ($.isFunction(document.createEvent)) {
366
+ try {
367
+ evt = document.createEvent("KeyEvents");
368
+ evt.initKeyEvent(type, e.bubbles, e.cancelable, e.view,
369
+ e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
370
+ e.keyCode, e.charCode);
371
+ } catch(err) {
372
+ evt = document.createEvent("Events");
373
+ evt.initEvent(type, e.bubbles, e.cancelable);
374
+ $.extend(evt, { view: e.view,
375
+ ctrlKey: e.ctrlKey, altKey: e.altKey, shiftKey: e.shiftKey, metaKey: e.metaKey,
376
+ keyCode: e.keyCode, charCode: e.charCode
377
+ });
378
+ }
379
+ } else if (document.createEventObject) {
380
+ evt = document.createEventObject();
381
+ $.extend(evt, e);
382
+ }
383
+ if ($.browser.msie || $.browser.opera) {
384
+ evt.keyCode = (e.charCode > 0) ? e.charCode : e.keyCode;
385
+ evt.charCode = undefined;
386
+ }
387
+ return evt;
388
+ },
389
+ dispatchEvent: function(el, type, evt) {
390
+ if (el.dispatchEvent) {
391
+ el.dispatchEvent(evt);
392
+ } else if (el.fireEvent) {
393
+ el.fireEvent('on' + type, evt);
394
+ }
395
+ return evt;
396
+ },
397
+ drag: function(el) {
398
+ var self = this, center = this.findCenter(this.target),
399
+ options = this.options, x = Math.floor(center.x), y = Math.floor(center.y),
400
+ dx = options.dx || 0, dy = options.dy || 0, target = this.target;
401
+ var coord = { clientX: x, clientY: y };
402
+ this.simulateEvent(target, "mousedown", coord);
403
+ coord = { clientX: x + 1, clientY: y + 1 };
404
+ this.simulateEvent(document, "mousemove", coord);
405
+ coord = { clientX: x + dx, clientY: y + dy };
406
+ this.simulateEvent(document, "mousemove", coord);
407
+ this.simulateEvent(document, "mousemove", coord);
408
+ this.simulateEvent(target, "mouseup", coord);
409
+ this.simulateEvent(target, "click", coord);
410
+ },
411
+ findCenter: function(el) {
412
+ var el = $(this.target), o = el.offset(), d = $(document);
413
+ return {
414
+ x: o.left + el.outerWidth() / 2 - d.scrollLeft(),
415
+ y: o.top + el.outerHeight() / 2 - d.scrollTop()
416
+ };
417
+ }
418
+ });
419
+
420
+ $.extend($.simulate, {
421
+ defaults: {
422
+ speed: 'sync'
423
+ },
424
+ VK_TAB: 9,
425
+ VK_ENTER: 13,
426
+ VK_ESC: 27,
427
+ VK_PGUP: 33,
428
+ VK_PGDN: 34,
429
+ VK_END: 35,
430
+ VK_HOME: 36,
431
+ VK_LEFT: 37,
432
+ VK_UP: 38,
433
+ VK_RIGHT: 39,
434
+ VK_DOWN: 40
435
+ });
436
+
437
+ })(jQuery);
438
+ JAVASCRIPT