mercury-rails 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/app/assets/images/mercury/toolbar/primary/tools.png +0 -0
  2. data/app/assets/images/mercury/toolbar/primary/user.png +0 -0
  3. data/app/assets/javascripts/mercury/dialogs/snippetpanel.js.coffee +1 -1
  4. data/app/assets/javascripts/mercury/lightview.js.coffee +11 -4
  5. data/app/assets/javascripts/mercury/locales/ar.locale.js.coffee +0 -4
  6. data/app/assets/javascripts/mercury/locales/da.locale.js.coffee +0 -4
  7. data/app/assets/javascripts/mercury/locales/de.locale.js.coffee +0 -4
  8. data/app/assets/javascripts/mercury/locales/es.locale.js.coffee +0 -4
  9. data/app/assets/javascripts/mercury/locales/example.local.js.coffee +0 -4
  10. data/app/assets/javascripts/mercury/locales/fr.locale.js.coffee +0 -4
  11. data/app/assets/javascripts/mercury/locales/hu.locale.js.coffee +209 -0
  12. data/app/assets/javascripts/mercury/locales/it.locale.js.coffee +0 -4
  13. data/app/assets/javascripts/mercury/locales/ko.local.js.coffee +0 -4
  14. data/app/assets/javascripts/mercury/locales/nl.locale.js.coffee +0 -4
  15. data/app/assets/javascripts/mercury/locales/pt.locale.js.coffee +0 -4
  16. data/app/assets/javascripts/mercury/locales/ru.locale.js.coffee +200 -0
  17. data/app/assets/javascripts/mercury/locales/sv.local.js.coffee +0 -4
  18. data/app/assets/javascripts/mercury/locales/swedish_chef.locale.js.coffee +0 -4
  19. data/app/assets/javascripts/mercury/locales/zh.local.js.coffee +0 -4
  20. data/app/assets/javascripts/mercury/mercury-compiled.js +10720 -0
  21. data/app/assets/javascripts/mercury/mercury.js.coffee +1 -1
  22. data/app/assets/javascripts/mercury/modal.js.coffee +14 -7
  23. data/app/assets/javascripts/mercury/modals/htmleditor.js.coffee +1 -1
  24. data/app/assets/javascripts/mercury/modals/insertmedia.js.coffee +2 -0
  25. data/app/assets/javascripts/mercury/modals/inserttable.js.coffee +10 -4
  26. data/app/assets/javascripts/mercury/page_editor.js.coffee +9 -9
  27. data/app/assets/javascripts/mercury/palette.js.coffee +1 -1
  28. data/app/assets/javascripts/mercury/panel.js.coffee +1 -0
  29. data/app/assets/javascripts/mercury/region.js.coffee +3 -3
  30. data/app/assets/javascripts/mercury/regions/{full.coffee → full.js.coffee} +2 -2
  31. data/app/assets/javascripts/mercury/regions/{markdown.coffee → markdown.js.coffee} +7 -1
  32. data/app/assets/javascripts/mercury/regions/snippets.js.coffee +1 -1
  33. data/app/assets/javascripts/mercury/select.js.coffee +1 -1
  34. data/app/assets/javascripts/mercury/snippet.js.coffee +40 -21
  35. data/app/assets/javascripts/mercury/toolbar.button.js.coffee +35 -20
  36. data/app/assets/javascripts/mercury/toolbar.expander.js.coffee +4 -3
  37. data/app/assets/javascripts/mercury/toolbar.js.coffee +6 -2
  38. data/app/assets/stylesheets/_mercury-bootstrap-overrides.scss +61 -0
  39. data/app/assets/stylesheets/_mercury-sass.scss +33 -0
  40. data/app/assets/stylesheets/mercury.css +1 -0
  41. data/app/assets/stylesheets/mercury/all_images.css.erb +4 -0
  42. data/app/assets/stylesheets/mercury/dialog.css +5 -2
  43. data/app/assets/stylesheets/mercury/mercury.css +0 -1
  44. data/app/assets/stylesheets/mercury/toolbar.css +3 -0
  45. data/app/assets/stylesheets/mercury/uploader.css +1 -1
  46. data/app/views/mercury/modals/media.html +10 -0
  47. data/app/views/mercury/panels/snippets.html +6 -1
  48. data/app/views/mercury/snippets/example/options.html.erb +1 -1
  49. data/app/views/mercury/snippets/no_options/preview.html.erb +1 -0
  50. data/features/loading/loading.feature +1 -1
  51. data/features/regions/full/basic_editing.feature +2 -2
  52. data/features/regions/full/inserting_media.feature +18 -0
  53. data/features/regions/full/inserting_snippets.feature +11 -0
  54. data/features/step_definitions/custom_web_steps.rb +22 -0
  55. data/features/step_definitions/mercury_steps.rb +1 -439
  56. data/features/support/selectors.rb +23 -0
  57. data/lib/generators/mercury/install/images/templates/ar_paperclip_image.rb +2 -0
  58. data/lib/mercury/cucumber/step_definitions.rb +13 -0
  59. data/lib/mercury/cucumber/step_definitions/mercury_steps.rb +408 -0
  60. data/{features → lib/mercury/cucumber}/support/mercury_contents.rb +1 -1
  61. data/{features → lib/mercury/cucumber}/support/mercury_selectors.rb +0 -20
  62. data/lib/mercury/rails.rb +1 -0
  63. data/lib/mercury/version.rb +1 -1
  64. data/spec/dummy/config/application.rb +4 -1
  65. data/spec/dummy/config/database.yml +10 -0
  66. data/spec/dummy/db/.gitkeep +0 -0
  67. data/spec/dummy/public/index.html +13 -2
  68. data/spec/javascripts/mercury/lightview_spec.js.coffee +33 -1
  69. data/spec/javascripts/mercury/modal_spec.js.coffee +35 -3
  70. data/spec/javascripts/mercury/modals/htmleditor_spec.js.coffee +1 -1
  71. data/spec/javascripts/mercury/modals/insertmedia_spec.js.coffee +6 -2
  72. data/spec/javascripts/mercury/modals/inserttable_spec.js.coffee +10 -0
  73. data/spec/javascripts/mercury/page_editor_spec.js.coffee +6 -5
  74. data/spec/javascripts/mercury/region_spec.js.coffee +4 -0
  75. data/spec/javascripts/mercury/snippet_spec.js.coffee +65 -21
  76. data/spec/javascripts/mercury/toolbar_spec.js.coffee +22 -0
  77. data/spec/javascripts/templates/mercury/modals/insertmedia.html +10 -0
  78. metadata +26 -16
  79. data/spec/dummy/config/database.example.yml +0 -25
  80. data/spec/dummy/config/database.travisci.yml +0 -4
@@ -2,13 +2,14 @@ class @Mercury.Toolbar.Expander extends Mercury.Palette
2
2
 
3
3
  constructor: (@name, @options) ->
4
4
  @container = @options.for
5
- @containerWidth = @container.outerWidth()
6
5
  super(null, @name, @options)
7
6
  return @element
8
7
 
9
8
 
10
9
  build: ->
11
- @container.css({whiteSpace: 'normal'})
10
+ @container.css({whiteSpace: 'normal', visibility: 'hidden', display: 'block'})
11
+ @containerWidth = @container.outerWidth()
12
+ @container.css({visibility: 'visible'})
12
13
  @trigger = jQuery('<div>', {class: 'mercury-toolbar-expander'}).appendTo(jQuery(@options.appendTo).get(0) ? 'body')
13
14
  @element = jQuery('<div>', {class: "mercury-palette mercury-expander mercury-#{@name}-expander", style: 'display:none'})
14
15
  @windowResize()
@@ -43,7 +44,7 @@ class @Mercury.Toolbar.Expander extends Mercury.Palette
43
44
 
44
45
  position: (keepVisible) ->
45
46
  @element.css({top: 0, left: 0, display: 'block', visibility: 'hidden'})
46
- position = @trigger.offset()
47
+ position = @trigger.position()
47
48
  width = @element.width()
48
49
 
49
50
  position.left = position.left - width + @trigger.width() if position.left + width > jQuery(window).width()
@@ -8,7 +8,7 @@ class @Mercury.Toolbar
8
8
 
9
9
  build: ->
10
10
  @element = jQuery('<div>', {class: 'mercury-toolbar-container', style: 'width:10000px'})
11
- @element.css({display: 'none'}) unless @visible
11
+ @element.css({width: '100%'})
12
12
  @element.appendTo(jQuery(@options.appendTo).get(0) ? 'body')
13
13
 
14
14
  for own toolbarName, buttons of Mercury.config.toolbars
@@ -28,7 +28,7 @@ class @Mercury.Toolbar
28
28
 
29
29
  toolbar.addClass('disabled') if Mercury.config.toolbars['primary'] && toolbarName != 'primary'
30
30
 
31
- @element.css({width: '100%'})
31
+ @element.css({display: 'none'}) unless @visible
32
32
 
33
33
 
34
34
  buildButton: (name, options) ->
@@ -75,6 +75,10 @@ class @Mercury.Toolbar
75
75
  if @visible || force then @element.outerHeight() else 0
76
76
 
77
77
 
78
+ top: ->
79
+ if @visible then @element.offset().top else 0
80
+
81
+
78
82
  show: ->
79
83
  @visible = true
80
84
  @element.css({top: -@element.outerHeight(), display: 'block'})
@@ -0,0 +1,61 @@
1
+ /*
2
+ * Bootsrap Overrides (overrides what's in bootstrap-ish)
3
+ *---------------------------------------------------------------------------*/
4
+ .btn-group > .btn {
5
+ margin-right: 0;
6
+ }
7
+ form {
8
+ margin-bottom: 0;
9
+ }
10
+ fieldset {
11
+ margin-bottom: 15px;
12
+ background: #F6F6F6;
13
+ border: 1px solid #CCC;
14
+ border-radius: 7px;
15
+ padding: 10px;
16
+ }
17
+ legend {
18
+ display: block;
19
+ position: relative;
20
+ margin-left: 10px;
21
+ margin-bottom: 0;
22
+ font-weight: bold;
23
+ width: auto;
24
+ padding: 0;
25
+ font-size: 12px;
26
+ color: #333333;
27
+ border: 0;
28
+ line-height: 1px;
29
+ }
30
+ select {
31
+ width: auto;
32
+ }
33
+ .form-actions {
34
+ margin-top: 0;
35
+ margin-bottom: 0;
36
+ background-color: transparent;
37
+ }
38
+ .control-group {
39
+ margin-bottom: 0;
40
+ }
41
+ legend + .control-group {
42
+ margin-top: 0;
43
+ -webkit-margin-top-collapse: separate;
44
+ }
45
+ .form-horizontal .control-group {
46
+ margin-bottom: 0;
47
+ }
48
+ .form-horizontal .controls {
49
+ margin-left: 150px;
50
+ }
51
+ .form-horizontal hr {
52
+ margin-left: 150px;
53
+ border: 0;
54
+ border-top: 1px solid #ccc;
55
+ }
56
+ label input[type=radio] {
57
+ margin-right: 5px;
58
+ }
59
+ .form-actions {
60
+ padding-bottom: 0;
61
+ }
@@ -0,0 +1,33 @@
1
+ /*!
2
+ * Mercury Editor is a Coffeescript and jQuery based WYSIWYG editor. Documentation and other useful information can be
3
+ * found at https://github.com/jejacks0n/mercury
4
+ *
5
+ * Copyright (c) 2011 Jeremy Jackson
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
8
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
9
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
10
+ * persons to whom the Software is furnished to do so, subject to the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
13
+ * Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
16
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+ *
20
+ */
21
+
22
+ $linkColor: #09F !default;
23
+ $linkColorHover: darken($linkColor, 15%) !default;
24
+
25
+ @import '/assets/mercury/mercury.css';
26
+ @import 'mercury-bootstrap-overrides';
27
+
28
+ #mercury_about a { color: $linkColor; }
29
+ #mercury_table #table_display .selected { background: $linkColor; }
30
+ .mercury-uploader .mercury-uploader-progress div.mercury-uploader-indicator div {
31
+ background-color: $linkColor;
32
+ border: 1px solid $linkColorHover;
33
+ }
@@ -18,6 +18,7 @@
18
18
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
19
  *
20
20
  *= require_self
21
+ *= require mercury/bootstrap-ish
21
22
  *= require mercury/mercury
22
23
  */
23
24
 
@@ -74,6 +74,10 @@ form fieldset.buttons .commit input {
74
74
  .mercury-expander-button[data-button=historyPanel] em { background-image: url(<%= asset_path 'mercury/toolbar/primary/historypanel.png' %>) }
75
75
  .mercury-primary-toolbar .mercury-notesPanel-button em,
76
76
  .mercury-expander-button[data-button=notesPanel] em { background-image: url(<%= asset_path 'mercury/toolbar/primary/notespanel.png' %>) }
77
+ .mercury-primary-toolbar .mercury-userPanel-button em,
78
+ .mercury-expander-button[data-button=userPanel] em { background-image: url(<%= asset_path 'mercury/toolbar/primary/user.png' %>) }
79
+ .mercury-primary-toolbar .mercury-toolsPanel-button em,
80
+ .mercury-expander-button[data-button=toolsPanel] em { background-image: url(<%= asset_path 'mercury/toolbar/primary/tools.png' %>) }
77
81
  .mercury-editable-toolbar .mercury-button {
78
82
  background-image: url(<%= asset_path 'mercury/toolbar/editable/buttons.png' %>);
79
83
  }
@@ -15,11 +15,12 @@
15
15
  border-radius: 2px;
16
16
  -moz-border-radius: 2px;
17
17
  margin-top: -1px;
18
- background-color: #E2E1E2;
18
+ background-color: #FFFFFF;
19
19
  box-shadow: 1px 1px 4px rgba(0,0,0, .5);
20
20
  -moz-box-shadow: 1px 1px 4px rgba(0,0,0, .5);
21
21
  font-family: Helvetica, Tahoma, Arial, sans-serif;
22
22
  font-size: 8.5pt;
23
+ color: #333;
23
24
  }
24
25
  .mercury-dialog.loading,
25
26
  .mercury-select.loading,
@@ -40,7 +41,7 @@
40
41
  * Panels
41
42
  *----------------------------------------------------------------------------*/
42
43
  .mercury-panel {
43
- position: absolute;
44
+ position: fixed;
44
45
  z-index: 10011;
45
46
  background-color: #f5f5f5;
46
47
  opacity: .9;
@@ -64,6 +65,7 @@
64
65
  margin: 0;
65
66
  background: #333;
66
67
  white-space: nowrap;
68
+ line-height: normal;
67
69
  }
68
70
  .mercury-panel h1 {
69
71
  -webkit-user-select: none;
@@ -185,6 +187,7 @@
185
187
  -moz-box-sizing: border-box;
186
188
  -webkit-box-sizing: border-box;
187
189
  width: 100%;
190
+ height: auto;
188
191
  padding-left: 20px;
189
192
  background-color: #FFF;
190
193
  background-repeat: no-repeat;
@@ -1,6 +1,5 @@
1
1
  /*
2
2
  *= require_self
3
- *= require ./bootstrap-ish
4
3
  *= require ./bootstrap-overrides
5
4
  *= require ./dialog
6
5
  *= require ./lightview
@@ -46,6 +46,9 @@
46
46
  width: 1px;
47
47
  background: #727272;
48
48
  }
49
+ .mercury-button {
50
+ cursor: pointer;
51
+ }
49
52
  .mercury-button em {
50
53
  display: block;
51
54
  font-style: normal;
@@ -95,9 +95,9 @@
95
95
  background: -moz-repeating-linear-gradient(top left -30deg, rgba(255,255,255, 0.17), rgba(255,255,255, 0.17) 15px, rgba(255,255,255, 0) 15px, rgba(255,255,255, 0) 30px),
96
96
  -moz-linear-gradient(rgba(255,255,255, 0.1) 0%, rgba(255,255,255, 0.37) 100%);
97
97
  background-color: #09F;
98
+ border: 1px solid #0083DA;
98
99
  box-shadow: inset 0 1px 0 0 rgba(255,255,255, 0.4), inset 0 -1px 1px rgba(0,0,0, 0.2);
99
100
  -moz-box-shadow: inset 0 1px 0 0 rgba(255,255,255, 0.4), inset 0 -1px 1px rgba(0,0,0, 0.2);
100
- border: 1px solid #0083DA;
101
101
  }
102
102
  .mercury-uploader .mercury-uploader-progress div.mercury-uploader-indicator div b {
103
103
  display: none;
@@ -51,6 +51,16 @@
51
51
  <option value="absbottom">Absolute Bottom</option>
52
52
  </select>
53
53
  </div>
54
+ <label class="select optional control-label" for="media_image_float">Float</label>
55
+ <div class="controls">
56
+ <select class="select optional" id="media_image_float" name="media[image_float]">
57
+ <option value="">None</option>
58
+ <option value="left">Left</option>
59
+ <option value="right">Right</option>
60
+ <option value="none">None</option>
61
+ <option value="inherit">Inherit</option>
62
+ </select>
63
+ </div>
54
64
  </div>
55
65
  </div>
56
66
  <div class="media-options" id="youtube_url_options" style="display:none">
@@ -1,6 +1,6 @@
1
1
  <div class="mercury-snippet-panel">
2
2
  <div class="filter">
3
- <input class="filter" type="text">
3
+ <input class="filter focusable" type="text">
4
4
  </div>
5
5
  <ul>
6
6
  <li data-filter="example, snippet, favorite, beer">
@@ -8,5 +8,10 @@
8
8
  <h4>Snippet Name</h4>
9
9
  <div class="description">A one or two line long description of what this snippet does.</div>
10
10
  </li>
11
+ <li data-filter="no options, snippet">
12
+ <img alt="No Option Snippet" data-snippet="no_options" data-options="false" src="/assets/mercury/default-snippet.png"/>
13
+ <h4>No Options Snippet</h4>
14
+ <div class="description">This snippet doesn't have options.</div>
15
+ </li>
11
16
  </ul>
12
17
  </div>
@@ -1,4 +1,4 @@
1
- <%= form_for 'options', {html: {class: 'form-horizontal', style: 'width:615px'}} do |f| %>
1
+ <%= form_for 'options', {url: '', html: {class: 'form-horizontal', style: 'width:615px'}} do |f| %>
2
2
 
3
3
  <div class="form-inputs mercury-display-pane-container">
4
4
 
@@ -0,0 +1 @@
1
+ <strong>No Option Snippet</strong>
@@ -21,5 +21,5 @@ Feature:
21
21
  # Latest selenium webdriver seems to consider the lightview hidden
22
22
  @use_hidden_elements
23
23
  Scenario: A user can expect to see the status bar
24
- Then I should see "Mercury Editor v0.8.0" within the statusbar
24
+ Then I should see "Mercury Editor v0.9.0" within the statusbar
25
25
 
@@ -147,10 +147,10 @@ Feature:
147
147
  And I make a selection
148
148
 
149
149
  When I click on the insert hr editor button
150
- Then the contents of the full region should be "this is&nbsp;<hr size='2' width='100%'> <b>content</b>"
150
+ Then the contents of the full region should be "this is&nbsp;<hr> <b>content</b>"
151
151
 
152
152
  When I click on the insert hr editor button
153
- Then the contents of the full region should be "this is&nbsp;<hr size='2' width='100%'><hr size='2' width='100%'> <b>content</b>"
153
+ Then the contents of the full region should be "this is&nbsp;<hr><hr> <b>content</b>"
154
154
 
155
155
 
156
156
  Scenario: A user can clean/remove formatting on their selection
@@ -49,6 +49,24 @@ Feature:
49
49
  And press "Insert Media"
50
50
  Then the contents of the full region should be "this is <img src='/assets/mercury/temp-logo.png' align='absmiddle'> <b>content</b>"
51
51
 
52
+ # Scenario: A user can insert and edit an image with an explicit float setting
53
+ Given the content of the full region is simple content
54
+ And I make a selection
55
+
56
+ When I click on the "Insert Media" button
57
+ When I fill in "media_image_url" with "/assets/mercury/temp-logo.png"
58
+ And select "Right" from "Float"
59
+ And press "Insert Media"
60
+ Then the contents of the full region should be "this is <img style='float: right;' src='/assets/mercury/temp-logo.png'> <b>content</b>"
61
+
62
+ When I make a selection for "img"
63
+ And click on the "Insert Media" button
64
+ And select "Absolute Middle" from "Alignment"
65
+ And select "None" from "Float"
66
+ And press "Insert Media"
67
+ Then the contents of the full region should be "this is <img src='/assets/mercury/temp-logo.png' align='absmiddle'> <b>content</b>"
68
+
69
+
52
70
 
53
71
  Scenario: A user can edit an image by double clicking it
54
72
  Given the content of the full region has an image
@@ -28,6 +28,17 @@ Feature:
28
28
  And the contents of the full region should be "this is <div data-version='1' data-snippet='snippet_14' class='example-snippet' contenteditable='false'><strong>Jeremy</strong> likes Stella</div><span>simple</span> <b>content</b>"
29
29
 
30
30
 
31
+ Scenario: A user can drag and drop snippets with no options into a full region
32
+ Given the content of the full region is simple content
33
+ And I make a selection
34
+
35
+ When I open the snippet panel
36
+ And I drag the snippet with no options into the full region
37
+ Then the modal window should not be visible
38
+
39
+ And the contents of the full region should be "this is <div data-version='1' data-snippet='snippet_14' class='no_options-snippet' contenteditable='false'><strong>No Option Snippet</strong></div><span>simple</span> <b>content</b>"
40
+
41
+
31
42
  Scenario: A user can use the snippet toolbar to remove a snippet
32
43
  Given the options for the example snippet "snippet_42" are first_name: "Jeremy", favorite_beer: "Stella"
33
44
  And the content of the full region has that snippet
@@ -0,0 +1,22 @@
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
@@ -1,439 +1 @@
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') == 'markdown') {
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 full region if one wasn't provided'
99
- region_selector = region_selector_for(region_locator || 'the full 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') == 'markdown') {
106
- alert('unimplemented');
107
- throw('unimplemented');
108
- } else {
109
- var selectedElement = element.find('#{selector}');
110
- var selection = new top.Mercury.Regions.Full.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 full region if one wasn't provided'
123
- region_selector = region_selector_for(region_locator || 'the full 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') == 'markdown') {
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
- Mercury.changes = false;
159
- }
160
- JAVASCRIPT
161
- end
162
-
163
- # check for the last save cached results
164
- Then /^the save should have (.*?) for (.*?)$/ do |contents, region_locator|
165
- region_id = region_selector_for(region_locator).gsub('#', '')
166
- content = contents[0] == '"' ? contents : "\"#{contents_for(contents)}\""
167
- results = page.driver.execute_script <<-JAVASCRIPT
168
- return (window.cachedResults['#{region_id}']) ?
169
- window.cachedResults['#{region_id}']['value'] : null;
170
- JAVASCRIPT
171
- assert_equal content, "\"#{results}\""
172
- end
173
-
174
-
175
- ## Table editing specific steps
176
- #------------------------------------------------------------------------------
177
- # in the modal window
178
- When /^(?:|I )(?:add|insert) a (row|column) (before|after)(?: it)?$/ do |row_or_column, before_or_after|
179
- name = "add_#{row_or_column}_#{before_or_after}".camelcase(:lower)
180
- step(%Q{I click on ".mercury-modal-content button[data-action='#{name}']"})
181
- end
182
-
183
- When /^(?:|I )delete the(?: current)? (row|column)$/ do |row_or_column|
184
- name = "remove_#{row_or_column}".camelcase(:lower)
185
- step(%Q{I click on ".mercury-modal-content button[data-action='#{name}']"})
186
- end
187
-
188
- When /^(?:|I )(increase|decrease) the (rowspan|colspan)$/ do |increase_or_decrease, rowspan_or_colspan|
189
- name = "#{increase_or_decrease}_#{rowspan_or_colspan}".camelcase(:lower)
190
- step(%Q{I click on ".mercury-modal-content button[data-action=#{name}]"})
191
- end
192
-
193
- Then /^the selected cell should be (.*?)$/ do |locator|
194
- selector = selector_for(locator).gsub('td:', 'td.selected:')
195
- find("#{selector}", :message => "Unable to locate the selected cell for '#{selector}'")
196
- end
197
-
198
- # in general
199
- Then /^the(?: table)? (row|column) count should be (\d+)$/ do |row_or_column, expected_count|
200
- method = "get_#{row_or_column}_count".camelcase(:lower)
201
- actual_count = page.driver.execute_script("return Mercury.tableEditor.#{method}()")
202
- assert_equal expected_count.to_i, actual_count.to_i
203
- end
204
-
205
-
206
- ## Snippet specific steps
207
- #------------------------------------------------------------------------------
208
- # setting snippet options
209
- Given /^the options for the (.*?) snippet "([^"]*)" are (.*?)$/ do |snippet_name, snippet_id, options|
210
- @snippet_id = snippet_id
211
- options_json = parse_snippet_options_from(options)
212
- page.driver.execute_script <<-JAVASCRIPT
213
- Mercury.Snippet.load({#{snippet_id}: {name: '#{snippet_name}', options: #{options_json}}});
214
- JAVASCRIPT
215
- end
216
-
217
- # dragging/dropping
218
- When /^(?:|I )(?:drag|drop) (.*?) (?:into|on) (.*?)$/ do |snippet_locator, region_locator|
219
- snippet_name = snippet_name_for(snippet_locator)
220
- region_id = region_selector_for(region_locator).gsub('#', '')
221
- page.driver.within_frame('mercury_iframe') do
222
- find("##{region_id}", :message => "Unable to locate a region matching '##{region_id}'")
223
- page.driver.execute_script <<-JAVASCRIPT
224
- var element = top.jQuery(document).find('##{region_id}');
225
- if (element.data('type') == 'markdown') {
226
- alert('unimplemented');
227
- throw('unimplemented');
228
- } else {
229
- var region = top.mercuryInstance.getRegionByName('#{region_id}');
230
- region.selection().range.collapse(true);
231
- document.execCommand('insertHTML', false, '<img data-snippet="#{snippet_name}" src="/assets/mercury/default-snippet.png">');
232
- element.trigger('possible:drop');
233
- }
234
- JAVASCRIPT
235
- end
236
- end
237
-
238
- When /^(?:|I )hover over (.*?)(?: in (.*?))?$/ do |locator, region_locator|
239
- step(%Q{I can simulate complex javascript events})
240
- selector = selector_for(locator)
241
- region_selector = region_selector_for(region_locator || 'the full region')
242
- page.driver.within_frame('mercury_iframe') do
243
- find("#{region_selector}", :message => "Unable to locate a region matching '#{region_selector}'")
244
- page.driver.execute_script <<-JAVASCRIPT
245
- var element = top.jQuery(document).find('#{region_selector}');
246
- if (element.data('type') == 'markdown') {
247
- alert('unimplemented');
248
- throw('unimplemented');
249
- } else {
250
- element.find('#{selector}').simulate('mousemove');
251
- }
252
- JAVASCRIPT
253
- end
254
- end
255
-
256
- When /^(?:|I )edit the snippet$/ do
257
- step(%{I hover over the snippet})
258
- step(%{click on the edit snippet settings toolbar button})
259
- end
260
-
261
-
262
- ## Dropping image specific steps
263
- #------------------------------------------------------------------------------
264
- #When /^(?:|I )drop an image into (.*?) from a different browser/ do |region_locator|
265
- # Given(%Q{I can simulate complex javascript events})
266
- # region_selector = region_selector_for(region_locator || 'the full region')
267
- # page.driver.within_frame('mercury_iframe') do
268
- # find("#{region_selector}", :message => "Unable to locate a region matching '#{region_selector}'")
269
- # page.driver.execute_script <<-JAVASCRIPT
270
- # var element = top.jQuery(document).find('#{region_selector}');
271
- # if (element.data('type') == 'markdown') {
272
- # alert('unimplemented');
273
- # throw('unimplemented');
274
- # } else {
275
- # element.find('#{region_selector}').simulate('drop', {'text/html': '<img src="testing.gif"/>'});
276
- # }
277
- # JAVASCRIPT
278
- # end
279
- #end
280
-
281
-
282
- ## Javascript event simulation steps
283
- #------------------------------------------------------------------------------
284
- Given /^(?:|I )can simulate complex javascript events$/ do
285
- page.driver.execute_script(EVENT_SIMULATION_JAVASCRIPT)
286
- end
287
-
288
- #------------------------------------------------------------------------------
289
-
290
- EVENT_SIMULATION_JAVASCRIPT = <<-JAVASCRIPT
291
- /*
292
- * jquery.simulate - simulate browser mouse and keyboard events
293
- *
294
- * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
295
- * Dual licensed under the MIT or GPL Version 2 licenses.
296
- * http://jquery.org/license
297
- *
298
- */
299
- ;(function($) {
300
-
301
- $.fn.extend({
302
- simulate: function(type, options) {
303
- return this.each(function() {
304
- var opt = $.extend({}, $.simulate.defaults, options || {});
305
- new $.simulate(this, type, opt);
306
- });
307
- }
308
- });
309
-
310
- $.simulate = function(el, type, options) {
311
- this.target = el;
312
- this.options = options;
313
-
314
- if (/^drag$/.test(type)) {
315
- this[type].apply(this, [this.target, options]);
316
- } else {
317
- this.simulateEvent(el, type, options);
318
- }
319
- }
320
-
321
- $.extend($.simulate.prototype, {
322
- simulateEvent: function(el, type, options) {
323
- var evt = this.createEvent(type, options);
324
- this.dispatchEvent(el, type, evt, options);
325
- return evt;
326
- },
327
- createEvent: function(type, options) {
328
- if (/^mouse(over|out|down|up|move)|(dbl)?click$/.test(type)) {
329
- return this.mouseEvent(type, options);
330
- } else if (/^key(up|down|press)$/.test(type)) {
331
- return this.keyboardEvent(type, options);
332
- }
333
- },
334
- mouseEvent: function(type, options) {
335
- var evt;
336
- var e = $.extend({
337
- bubbles: true, cancelable: (type != "mousemove"), view: window, detail: 0,
338
- screenX: 0, screenY: 0, clientX: 0, clientY: 0,
339
- ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
340
- button: 0, relatedTarget: undefined
341
- }, options);
342
-
343
- var relatedTarget = $(e.relatedTarget)[0];
344
-
345
- if ($.isFunction(document.createEvent)) {
346
- evt = document.createEvent("MouseEvents");
347
- evt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail,
348
- e.screenX, e.screenY, e.clientX, e.clientY,
349
- e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
350
- e.button, e.relatedTarget || document.body.parentNode);
351
- } else if (document.createEventObject) {
352
- evt = document.createEventObject();
353
- $.extend(evt, e);
354
- evt.button = { 0:1, 1:4, 2:2 }[evt.button] || evt.button;
355
- }
356
- return evt;
357
- },
358
- keyboardEvent: function(type, options) {
359
- var evt;
360
-
361
- var e = $.extend({ bubbles: true, cancelable: true, view: window,
362
- ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
363
- keyCode: 0, charCode: 0
364
- }, options);
365
-
366
- if ($.isFunction(document.createEvent)) {
367
- try {
368
- evt = document.createEvent("KeyEvents");
369
- evt.initKeyEvent(type, e.bubbles, e.cancelable, e.view,
370
- e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
371
- e.keyCode, e.charCode);
372
- } catch(err) {
373
- evt = document.createEvent("Events");
374
- evt.initEvent(type, e.bubbles, e.cancelable);
375
- $.extend(evt, { view: e.view,
376
- ctrlKey: e.ctrlKey, altKey: e.altKey, shiftKey: e.shiftKey, metaKey: e.metaKey,
377
- keyCode: e.keyCode, charCode: e.charCode
378
- });
379
- }
380
- } else if (document.createEventObject) {
381
- evt = document.createEventObject();
382
- $.extend(evt, e);
383
- }
384
- if ($.browser.msie || $.browser.opera) {
385
- evt.keyCode = (e.charCode > 0) ? e.charCode : e.keyCode;
386
- evt.charCode = undefined;
387
- }
388
- return evt;
389
- },
390
- dispatchEvent: function(el, type, evt) {
391
- if (el.dispatchEvent) {
392
- el.dispatchEvent(evt);
393
- } else if (el.fireEvent) {
394
- el.fireEvent('on' + type, evt);
395
- }
396
- return evt;
397
- },
398
- drag: function(el) {
399
- var self = this, center = this.findCenter(this.target),
400
- options = this.options, x = Math.floor(center.x), y = Math.floor(center.y),
401
- dx = options.dx || 0, dy = options.dy || 0, target = this.target;
402
- var coord = { clientX: x, clientY: y };
403
- this.simulateEvent(target, "mousedown", coord);
404
- coord = { clientX: x + 1, clientY: y + 1 };
405
- this.simulateEvent(document, "mousemove", coord);
406
- coord = { clientX: x + dx, clientY: y + dy };
407
- this.simulateEvent(document, "mousemove", coord);
408
- this.simulateEvent(document, "mousemove", coord);
409
- this.simulateEvent(target, "mouseup", coord);
410
- this.simulateEvent(target, "click", coord);
411
- },
412
- findCenter: function(el) {
413
- var el = $(this.target), o = el.offset(), d = $(document);
414
- return {
415
- x: o.left + el.outerWidth() / 2 - d.scrollLeft(),
416
- y: o.top + el.outerHeight() / 2 - d.scrollTop()
417
- };
418
- }
419
- });
420
-
421
- $.extend($.simulate, {
422
- defaults: {
423
- speed: 'sync'
424
- },
425
- VK_TAB: 9,
426
- VK_ENTER: 13,
427
- VK_ESC: 27,
428
- VK_PGUP: 33,
429
- VK_PGDN: 34,
430
- VK_END: 35,
431
- VK_HOME: 36,
432
- VK_LEFT: 37,
433
- VK_UP: 38,
434
- VK_RIGHT: 39,
435
- VK_DOWN: 40
436
- });
437
-
438
- })(jQuery);
439
- JAVASCRIPT
1
+ require 'mercury/cucumber/step_definitions'