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.
- data/app/assets/images/mercury/toolbar/primary/tools.png +0 -0
- data/app/assets/images/mercury/toolbar/primary/user.png +0 -0
- data/app/assets/javascripts/mercury/dialogs/snippetpanel.js.coffee +1 -1
- data/app/assets/javascripts/mercury/lightview.js.coffee +11 -4
- data/app/assets/javascripts/mercury/locales/ar.locale.js.coffee +0 -4
- data/app/assets/javascripts/mercury/locales/da.locale.js.coffee +0 -4
- data/app/assets/javascripts/mercury/locales/de.locale.js.coffee +0 -4
- data/app/assets/javascripts/mercury/locales/es.locale.js.coffee +0 -4
- data/app/assets/javascripts/mercury/locales/example.local.js.coffee +0 -4
- data/app/assets/javascripts/mercury/locales/fr.locale.js.coffee +0 -4
- data/app/assets/javascripts/mercury/locales/hu.locale.js.coffee +209 -0
- data/app/assets/javascripts/mercury/locales/it.locale.js.coffee +0 -4
- data/app/assets/javascripts/mercury/locales/ko.local.js.coffee +0 -4
- data/app/assets/javascripts/mercury/locales/nl.locale.js.coffee +0 -4
- data/app/assets/javascripts/mercury/locales/pt.locale.js.coffee +0 -4
- data/app/assets/javascripts/mercury/locales/ru.locale.js.coffee +200 -0
- data/app/assets/javascripts/mercury/locales/sv.local.js.coffee +0 -4
- data/app/assets/javascripts/mercury/locales/swedish_chef.locale.js.coffee +0 -4
- data/app/assets/javascripts/mercury/locales/zh.local.js.coffee +0 -4
- data/app/assets/javascripts/mercury/mercury-compiled.js +10720 -0
- data/app/assets/javascripts/mercury/mercury.js.coffee +1 -1
- data/app/assets/javascripts/mercury/modal.js.coffee +14 -7
- data/app/assets/javascripts/mercury/modals/htmleditor.js.coffee +1 -1
- data/app/assets/javascripts/mercury/modals/insertmedia.js.coffee +2 -0
- data/app/assets/javascripts/mercury/modals/inserttable.js.coffee +10 -4
- data/app/assets/javascripts/mercury/page_editor.js.coffee +9 -9
- data/app/assets/javascripts/mercury/palette.js.coffee +1 -1
- data/app/assets/javascripts/mercury/panel.js.coffee +1 -0
- data/app/assets/javascripts/mercury/region.js.coffee +3 -3
- data/app/assets/javascripts/mercury/regions/{full.coffee → full.js.coffee} +2 -2
- data/app/assets/javascripts/mercury/regions/{markdown.coffee → markdown.js.coffee} +7 -1
- data/app/assets/javascripts/mercury/regions/snippets.js.coffee +1 -1
- data/app/assets/javascripts/mercury/select.js.coffee +1 -1
- data/app/assets/javascripts/mercury/snippet.js.coffee +40 -21
- data/app/assets/javascripts/mercury/toolbar.button.js.coffee +35 -20
- data/app/assets/javascripts/mercury/toolbar.expander.js.coffee +4 -3
- data/app/assets/javascripts/mercury/toolbar.js.coffee +6 -2
- data/app/assets/stylesheets/_mercury-bootstrap-overrides.scss +61 -0
- data/app/assets/stylesheets/_mercury-sass.scss +33 -0
- data/app/assets/stylesheets/mercury.css +1 -0
- data/app/assets/stylesheets/mercury/all_images.css.erb +4 -0
- data/app/assets/stylesheets/mercury/dialog.css +5 -2
- data/app/assets/stylesheets/mercury/mercury.css +0 -1
- data/app/assets/stylesheets/mercury/toolbar.css +3 -0
- data/app/assets/stylesheets/mercury/uploader.css +1 -1
- data/app/views/mercury/modals/media.html +10 -0
- data/app/views/mercury/panels/snippets.html +6 -1
- data/app/views/mercury/snippets/example/options.html.erb +1 -1
- data/app/views/mercury/snippets/no_options/preview.html.erb +1 -0
- data/features/loading/loading.feature +1 -1
- data/features/regions/full/basic_editing.feature +2 -2
- data/features/regions/full/inserting_media.feature +18 -0
- data/features/regions/full/inserting_snippets.feature +11 -0
- data/features/step_definitions/custom_web_steps.rb +22 -0
- data/features/step_definitions/mercury_steps.rb +1 -439
- data/features/support/selectors.rb +23 -0
- data/lib/generators/mercury/install/images/templates/ar_paperclip_image.rb +2 -0
- data/lib/mercury/cucumber/step_definitions.rb +13 -0
- data/lib/mercury/cucumber/step_definitions/mercury_steps.rb +408 -0
- data/{features → lib/mercury/cucumber}/support/mercury_contents.rb +1 -1
- data/{features → lib/mercury/cucumber}/support/mercury_selectors.rb +0 -20
- data/lib/mercury/rails.rb +1 -0
- data/lib/mercury/version.rb +1 -1
- data/spec/dummy/config/application.rb +4 -1
- data/spec/dummy/config/database.yml +10 -0
- data/spec/dummy/db/.gitkeep +0 -0
- data/spec/dummy/public/index.html +13 -2
- data/spec/javascripts/mercury/lightview_spec.js.coffee +33 -1
- data/spec/javascripts/mercury/modal_spec.js.coffee +35 -3
- data/spec/javascripts/mercury/modals/htmleditor_spec.js.coffee +1 -1
- data/spec/javascripts/mercury/modals/insertmedia_spec.js.coffee +6 -2
- data/spec/javascripts/mercury/modals/inserttable_spec.js.coffee +10 -0
- data/spec/javascripts/mercury/page_editor_spec.js.coffee +6 -5
- data/spec/javascripts/mercury/region_spec.js.coffee +4 -0
- data/spec/javascripts/mercury/snippet_spec.js.coffee +65 -21
- data/spec/javascripts/mercury/toolbar_spec.js.coffee +22 -0
- data/spec/javascripts/templates/mercury/modals/insertmedia.html +10 -0
- metadata +26 -16
- data/spec/dummy/config/database.example.yml +0 -25
- 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.
|
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({
|
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({
|
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
|
+
}
|
@@ -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: #
|
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:
|
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;
|
@@ -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>
|
@@ -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.
|
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 <hr
|
150
|
+
Then the contents of the full region should be "this is <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 <hr
|
153
|
+
Then the contents of the full region should be "this is <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
|
-
|
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'
|