mercury-rails 0.8.0 → 0.9.0

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 (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'