pickles 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +196 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/cucumber/pickles.rb +6 -0
- data/lib/cucumber/pickles/check_in.rb +10 -0
- data/lib/cucumber/pickles/config.rb +61 -0
- data/lib/cucumber/pickles/errors/ambigious.rb +27 -0
- data/lib/cucumber/pickles/errors/node_find_error.rb +37 -0
- data/lib/cucumber/pickles/fill_in.rb +10 -0
- data/lib/cucumber/pickles/helpers.rb +40 -0
- data/lib/cucumber/pickles/helpers/extensions/chrome/.DS_Store +0 -0
- data/lib/cucumber/pickles/helpers/extensions/chrome/compiled.crx.base64 +1 -0
- data/lib/cucumber/pickles/helpers/extensions/chrome/manifest.json +15 -0
- data/lib/cucumber/pickles/helpers/extensions/chrome/src/.DS_Store +0 -0
- data/lib/cucumber/pickles/helpers/extensions/chrome/src/inject/inject.js +35 -0
- data/lib/cucumber/pickles/helpers/main.rb +88 -0
- data/lib/cucumber/pickles/helpers/node_finders.rb +125 -0
- data/lib/cucumber/pickles/helpers/regex.rb +6 -0
- data/lib/cucumber/pickles/helpers/waiter.rb +152 -0
- data/lib/cucumber/pickles/locator/equal.rb +26 -0
- data/lib/cucumber/pickles/locator/index.rb +20 -0
- data/lib/cucumber/pickles/refinements.rb +49 -0
- data/lib/cucumber/pickles/steps.rb +73 -0
- data/lib/cucumber/pickles/steps/can_see.rb +70 -0
- data/lib/cucumber/pickles/steps/check.rb +55 -0
- data/lib/cucumber/pickles/steps/check_in/complex_input.rb +17 -0
- data/lib/cucumber/pickles/steps/check_in/factory.rb +26 -0
- data/lib/cucumber/pickles/steps/check_in/input.rb +36 -0
- data/lib/cucumber/pickles/steps/check_in/text.rb +17 -0
- data/lib/cucumber/pickles/steps/click.rb +91 -0
- data/lib/cucumber/pickles/steps/fill.rb +72 -0
- data/lib/cucumber/pickles/steps/fill_in/complex_input.rb +19 -0
- data/lib/cucumber/pickles/steps/fill_in/factory.rb +25 -0
- data/lib/cucumber/pickles/steps/fill_in/input.rb +29 -0
- data/lib/cucumber/pickles/steps/fill_in/select.rb +30 -0
- data/lib/cucumber/pickles/steps/redirect.rb +3 -0
- data/lib/cucumber/pickles/transform.rb +13 -0
- data/lib/cucumber/pickles/version.rb +3 -0
- data/lib/pickles.rb +3 -0
- data/pickles.gemspec +36 -0
- data/spec/helpers/node_finders_spec.rb +155 -0
- data/spec/helpers/waiter_spec.rb +41 -0
- data/spec/locator_spec.rb +31 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/step_def_spec.rb +0 -0
- data/spec/steps/check_in/factory_spec.rb +52 -0
- data/spec/steps/fill_in/factory_spec.rb +51 -0
- metadata +153 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
unless defined?(SUPPORT_DIR)
|
2
|
+
in_features_dir = caller.select { |path| path =~ /features/ }.first
|
3
|
+
|
4
|
+
if in_features_dir
|
5
|
+
features_dir = in_features_dir.split('/')
|
6
|
+
|
7
|
+
2.times { features_dir.pop }
|
8
|
+
|
9
|
+
SUPPORT_DIR = File.join(features_dir,'support')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
require_relative 'refinements'
|
14
|
+
require_relative 'config'
|
15
|
+
require_relative 'errors/ambigious'
|
16
|
+
|
17
|
+
module Locator
|
18
|
+
|
19
|
+
_dir = 'cucumber/pickles/locator/'
|
20
|
+
|
21
|
+
autoload :Index, _dir + 'index'
|
22
|
+
autoload :Equal, _dir + 'equal'
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
module Helpers
|
27
|
+
|
28
|
+
_dir = 'cucumber/pickles/helpers/'
|
29
|
+
|
30
|
+
autoload :Main, _dir + 'main'
|
31
|
+
autoload :Regex, _dir + 'regex'
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
module Pickles
|
36
|
+
|
37
|
+
extend Helpers::Main
|
38
|
+
include Helpers::Main
|
39
|
+
|
40
|
+
end
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
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
|
@@ -0,0 +1,15 @@
|
|
1
|
+
{
|
2
|
+
"name": "Chrome driver Ajax shim",
|
3
|
+
"version": "0.0.1",
|
4
|
+
"manifest_version": 2,
|
5
|
+
"description": "Chrome driver testing vars to preserve Ajax requests sent status",
|
6
|
+
"content_scripts": [
|
7
|
+
{
|
8
|
+
"matches": ["<all_urls>"],
|
9
|
+
"js": [
|
10
|
+
"src/inject/inject.js"
|
11
|
+
],
|
12
|
+
"run_at": "document_start"
|
13
|
+
}
|
14
|
+
]
|
15
|
+
}
|
Binary file
|
@@ -0,0 +1,35 @@
|
|
1
|
+
chrome.extension.sendMessage({}, function(response) {
|
2
|
+
|
3
|
+
var elt = document.createElement("script");
|
4
|
+
|
5
|
+
elt.innerHTML = "var oldOpen=XMLHttpRequest.prototype.open;window.activeRequests=0,XMLHttpRequest.prototype.open=function(a,b,c,d,e){window.activeRequests++,this.addEventListener(\"readystatechange\",function(){4==this.readyState&&window.activeRequests--},!1),oldOpen.call(this,a,b,c,d,e)};";
|
6
|
+
|
7
|
+
|
8
|
+
document.head.appendChild(elt);
|
9
|
+
|
10
|
+
var style = document.createElement('style');
|
11
|
+
style.type = 'text/css';
|
12
|
+
style.innerHTML = '* {' +
|
13
|
+
'/*CSS transitions*/' +
|
14
|
+
' -o-transition-property: none !important;' +
|
15
|
+
' -moz-transition-property: none !important;' +
|
16
|
+
' -ms-transition-property: none !important;' +
|
17
|
+
' -webkit-transition-property: none !important;' +
|
18
|
+
' transition-property: none !important;' +
|
19
|
+
// '/*CSS transforms*/' +
|
20
|
+
// ' -o-transform: none !important;' +
|
21
|
+
// ' -moz-transform: none !important;' +
|
22
|
+
// ' -ms-transform: none !important;' +
|
23
|
+
// ' -webkit-transform: none !important;' +
|
24
|
+
// ' transform: none !important;' +
|
25
|
+
' /*CSS animations*/' +
|
26
|
+
' -webkit-animation: none !important;' +
|
27
|
+
' -moz-animation: none !important;' +
|
28
|
+
' -o-animation: none !important;' +
|
29
|
+
' -ms-animation: none !important;' +
|
30
|
+
' animation: none !important;}';
|
31
|
+
|
32
|
+
document.head.appendChild(style);
|
33
|
+
|
34
|
+
|
35
|
+
});
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require_relative 'node_finders'
|
2
|
+
require_relative 'waiter'
|
3
|
+
|
4
|
+
module Helpers::Main
|
5
|
+
|
6
|
+
include NodeFinders
|
7
|
+
include Waiter
|
8
|
+
|
9
|
+
#
|
10
|
+
# parent node of given
|
11
|
+
#
|
12
|
+
# @node - Capybara node
|
13
|
+
#
|
14
|
+
# returns Capybara node
|
15
|
+
#
|
16
|
+
def parent_node(node)
|
17
|
+
node.find(:xpath, '..', wait: 0, visible: false)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# trigger blur event on given node
|
22
|
+
#
|
23
|
+
# @node - Capybara node
|
24
|
+
#
|
25
|
+
def blur(node)
|
26
|
+
trigger(node, 'blur')
|
27
|
+
|
28
|
+
Capybara.current_session.execute_script("document.body.click()")
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Select checkbox | radio input
|
33
|
+
#
|
34
|
+
# @input - Capybara node with <input type="checkbox|radio">
|
35
|
+
# @value - optional - value to set to input, Defaults to input state switch
|
36
|
+
#
|
37
|
+
# returns: [void]
|
38
|
+
#
|
39
|
+
def select_input(input, value = nil)
|
40
|
+
case value
|
41
|
+
when "true", true
|
42
|
+
value = true
|
43
|
+
when "false", false
|
44
|
+
value = false
|
45
|
+
else
|
46
|
+
value = !input.checked?
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Hack:
|
51
|
+
# cant use input.set(#{value})
|
52
|
+
# because element can be hidden or covered by other eement
|
53
|
+
# in which case Selenium raises error
|
54
|
+
#
|
55
|
+
trigger(parent_node(input), 'click')
|
56
|
+
|
57
|
+
Capybara.current_session.execute_script("arguments[0].checked = #{value}", input)
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# Attach file from features/support/attachments/* to given file input
|
62
|
+
#
|
63
|
+
# @input - Capybara node with <input type="file">
|
64
|
+
# @file - file path relative to features/support/attachments/*
|
65
|
+
#
|
66
|
+
# returns [void]
|
67
|
+
#
|
68
|
+
def attach_file(input, file)
|
69
|
+
path = File.expand_path(File.join(SUPPORT_DIR,"attachments/#{file}"))
|
70
|
+
|
71
|
+
raise RuntimeError, "file '#{path}' does not exists" unless File.exists?(path)
|
72
|
+
|
73
|
+
input.set(path)
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Triggers event on node
|
78
|
+
# Usefull when Capybara raises error about element being covered by another
|
79
|
+
#
|
80
|
+
# @node - Capybara node
|
81
|
+
# @event - event to trigger
|
82
|
+
#
|
83
|
+
# returns: [void]
|
84
|
+
def trigger(node, event)
|
85
|
+
Capybara.current_session.execute_script("arguments[0].#{event}()", node)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module NodeFinders
|
2
|
+
|
3
|
+
using BlankMethod
|
4
|
+
|
5
|
+
#
|
6
|
+
# Finds text node by text locator
|
7
|
+
#
|
8
|
+
# @text - locator ( see locator docs in #Artifact )
|
9
|
+
# @within: - within block to limit search to
|
10
|
+
#
|
11
|
+
# returns Capybara node
|
12
|
+
#
|
13
|
+
def find_node(locator, within: nil)
|
14
|
+
within ||= Capybara.current_session
|
15
|
+
|
16
|
+
locator, index = Locator::Index.execute(locator)
|
17
|
+
locator, xpath = Locator::Equal.execute(locator)
|
18
|
+
|
19
|
+
if index
|
20
|
+
xpath = "(#{xpath})[#{index}]"
|
21
|
+
end
|
22
|
+
|
23
|
+
_rescued_find([:xpath, xpath, wait: 0, visible: false], locator, within: within, message: "find_node") do
|
24
|
+
raise Capybara::ElementNotFound,
|
25
|
+
"Unable to find node by locator #{locator}",
|
26
|
+
caller
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Does lookup based on provided in config maps
|
32
|
+
#
|
33
|
+
def detect_node(el_alias, locator = nil, within: nil)
|
34
|
+
return find_node(locator, within: within) if el_alias.blank?
|
35
|
+
|
36
|
+
within ||= Capybara.current_session
|
37
|
+
|
38
|
+
locator, index = Locator::Index.execute(locator)
|
39
|
+
|
40
|
+
if index.nil?
|
41
|
+
el_alias, index = Locator::Index.execute(el_alias.to_s)
|
42
|
+
end
|
43
|
+
|
44
|
+
el_alias = el_alias.to_sym
|
45
|
+
|
46
|
+
if xpath = Pickles.config.xpath_node_map[el_alias]
|
47
|
+
xpath = xpath.respond_to?(:call) ? xpath.call(locator) : xpath
|
48
|
+
|
49
|
+
search_params = [:xpath, xpath, wait: 0]
|
50
|
+
elsif css = Pickles.config.css_node_map[el_alias] || el_alias
|
51
|
+
css = css.respond_to?(:call) ? css.call(locator) : css
|
52
|
+
|
53
|
+
search_params = [:css, css, text: locator, wait: 0]
|
54
|
+
end
|
55
|
+
|
56
|
+
if index
|
57
|
+
within.all(*search_params)[index - 1]
|
58
|
+
else
|
59
|
+
_rescued_find(search_params, locator || el_alias, within: within, message: "Detecting by #{xpath || css}") do
|
60
|
+
raise Capybara::ElementNotFound,
|
61
|
+
"Unable to detect node by locator #{locator}",
|
62
|
+
caller
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# Similar to find_node, but looking for fillable fields for this cases:
|
69
|
+
# 1. label or span(as label) with input hint for input || textarea || @contenteditable
|
70
|
+
# 2. capybara lookup by label || plcaeholder || id || name || etc
|
71
|
+
# 3. @contenteditable with @placeholder = @locator
|
72
|
+
#
|
73
|
+
# @input_locator - string to identify input field by
|
74
|
+
#
|
75
|
+
# returns: Capybara node
|
76
|
+
#
|
77
|
+
def find_input(input_locator, within: nil, options: {})
|
78
|
+
within ||= Capybara.current_session
|
79
|
+
options[:wait] = 0
|
80
|
+
options[:visible] = false
|
81
|
+
|
82
|
+
locator, index = Locator::Index.execute(input_locator)
|
83
|
+
|
84
|
+
if index
|
85
|
+
index_xpath = "[#{index}]"
|
86
|
+
end
|
87
|
+
|
88
|
+
xpath = ".//*[@contenteditable and (@placeholder='#{locator}' or name='#{locator}')]#{index_xpath}"
|
89
|
+
|
90
|
+
# case 3
|
91
|
+
_rescued_find([:xpath, xpath, options], locator, within: within, message: "@contenteditable with placeholder = #{locator}") do
|
92
|
+
|
93
|
+
locator, label_xpath = Locator::Equal.execute(input_locator)
|
94
|
+
|
95
|
+
inputtable_field_xpath = "*[self::input or self::textarea or @contenteditable]"
|
96
|
+
|
97
|
+
xpath = "(#{label_xpath})#{index_xpath}/ancestor::*[.//#{inputtable_field_xpath}][position()=1]//#{inputtable_field_xpath}"
|
98
|
+
|
99
|
+
# case 1
|
100
|
+
_rescued_find([:xpath, xpath, options], locator, within: within, message: "find_node(#{locator}) => look for closest fillable field") do
|
101
|
+
|
102
|
+
# case 2
|
103
|
+
_rescued_find([:fillable_field, locator, options], locator, within: within, message: 'Capybara#fillable_input') do
|
104
|
+
|
105
|
+
# all cases failed => raise
|
106
|
+
raise Capybara::ElementNotFound,
|
107
|
+
"Unable to find fillable field by locator #{locator}",
|
108
|
+
caller
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def _rescued_find(params, locator, within:, message:)
|
118
|
+
within.find(*params)
|
119
|
+
rescue Capybara::Ambiguous => err # Capybara::Ambiguous < Capybara::ElementNotFound == true
|
120
|
+
raise Pickles::Ambiguous.new(locator, within, params, message), nil, caller
|
121
|
+
rescue Capybara::ElementNotFound
|
122
|
+
yield
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# original code:
|
2
|
+
#
|
3
|
+
# (function() {
|
4
|
+
# var oldOpen = XMLHttpRequest.prototype.open;
|
5
|
+
# window.openHTTPs = 0;
|
6
|
+
# XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
|
7
|
+
# window.openHTTPs++;
|
8
|
+
# this.addEventListener("readystatechange", function() {
|
9
|
+
# if(this.readyState == 4) {
|
10
|
+
# window.openHTTPs--;
|
11
|
+
# }
|
12
|
+
# }, false);
|
13
|
+
# oldOpen.call(this, method, url, async, user, pass);
|
14
|
+
# }
|
15
|
+
# })(XMLHttpRequest);
|
16
|
+
#
|
17
|
+
# module Capybara
|
18
|
+
# module Selenium
|
19
|
+
# class Driver
|
20
|
+
#
|
21
|
+
# class << self
|
22
|
+
# alias __pickles_redefined__new new
|
23
|
+
#
|
24
|
+
# #
|
25
|
+
# # Monkey patch initializer to load custom chrome extension in extensions/chrome
|
26
|
+
# #
|
27
|
+
# # It will add window.activeRequests to keep track of active AJAX requests in tests
|
28
|
+
# #
|
29
|
+
# # For source code of extension see extensions/chrome/src/inject/inject.js
|
30
|
+
# #
|
31
|
+
# # TODO: support all major browser drivers
|
32
|
+
# #
|
33
|
+
# def new(app, options={})
|
34
|
+
# if options[:browser].to_s == "chrome"
|
35
|
+
# options[:desired_capabilities] ||= {}
|
36
|
+
# options[:desired_capabilities]["chromeOptions"] ||= {}
|
37
|
+
# options[:desired_capabilities]["chromeOptions"]["extensions"] ||= []
|
38
|
+
#
|
39
|
+
# extension_path = File.expand_path('extensions/chrome/compiled.crx.base64', __dir__)
|
40
|
+
#
|
41
|
+
# options[:desired_capabilities]["chromeOptions"]["extensions"].unshift(File.read(extension_path))
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# __pickles_redefined__new(app, options)
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
|
53
|
+
def stub_xml_http_request(page)
|
54
|
+
page.evaluate_script <<-JAVASCRIPT
|
55
|
+
(function() {
|
56
|
+
|
57
|
+
if (window.ajaxRequestIsSet) { return; };
|
58
|
+
window.ajaxRequestIsSet = true;
|
59
|
+
|
60
|
+
var oldOpen = XMLHttpRequest.prototype.open;
|
61
|
+
window.activeRequests = 0;
|
62
|
+
XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
|
63
|
+
window.activeRequests++;
|
64
|
+
this.addEventListener("readystatechange", function() {
|
65
|
+
if (this.readyState == 4) {
|
66
|
+
window.activeRequests--;
|
67
|
+
|
68
|
+
#{
|
69
|
+
if Pickles.config.log_xhr_response
|
70
|
+
<<-LOG
|
71
|
+
if (parseInt(this.status, 10) >= 400) {
|
72
|
+
console.error("############## ERRRO RESPONSE START ################");
|
73
|
+
console.error(this.response);
|
74
|
+
console.error("############## ERRRO RESPONSE END ################");
|
75
|
+
}
|
76
|
+
LOG
|
77
|
+
end
|
78
|
+
}
|
79
|
+
|
80
|
+
}
|
81
|
+
}, false);
|
82
|
+
oldOpen.call(this, method, url, async, user, pass);
|
83
|
+
};
|
84
|
+
|
85
|
+
|
86
|
+
var style = document.createElement('style');
|
87
|
+
style.type = 'text/css';
|
88
|
+
style.innerHTML = '* {' +
|
89
|
+
'/*CSS transitions*/' +
|
90
|
+
' -o-transition-property: none !important;' +
|
91
|
+
' -moz-transition-property: none !important;' +
|
92
|
+
' -ms-transition-property: none !important;' +
|
93
|
+
' -webkit-transition-property: none !important;' +
|
94
|
+
' transition-property: none !important;' +
|
95
|
+
' /*CSS animations*/' +
|
96
|
+
' -webkit-animation: none !important;' +
|
97
|
+
' -moz-animation: none !important;' +
|
98
|
+
' -o-animation: none !important;' +
|
99
|
+
' -ms-animation: none !important;' +
|
100
|
+
' animation: none !important;}';
|
101
|
+
document.getElementsByTagName('head')[0].appendChild(style);
|
102
|
+
|
103
|
+
})();
|
104
|
+
JAVASCRIPT
|
105
|
+
end
|
106
|
+
|
107
|
+
module Capybara
|
108
|
+
class Session
|
109
|
+
|
110
|
+
alias __pickles_redefined__old_visit visit
|
111
|
+
|
112
|
+
def visit(*args)
|
113
|
+
__pickles_redefined__old_visit(*args)
|
114
|
+
|
115
|
+
stub_xml_http_request(Capybara.current_session)
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
module Waiter
|
122
|
+
|
123
|
+
module_function
|
124
|
+
|
125
|
+
def wait
|
126
|
+
wait_for_ajax
|
127
|
+
|
128
|
+
return unless block_given?
|
129
|
+
|
130
|
+
page.document.synchronize do
|
131
|
+
yield
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def page
|
136
|
+
Capybara.current_session
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# waits for all Ajax requests to finish
|
141
|
+
#
|
142
|
+
def wait_for_ajax
|
143
|
+
page.document.synchronize do
|
144
|
+
pending_ajax_requests_num.zero? || raise(Capybara::ElementNotFound)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def pending_ajax_requests_num
|
149
|
+
page.evaluate_script("window.activeRequests")
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|