onlyoffice_webdriver_wrapper 0.21.0 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/onlyoffice_webdriver_wrapper/dimensions.rb +1 -0
- data/lib/onlyoffice_webdriver_wrapper/helpers/chrome_helper/chromedriver_bin/chromedriver_mac +0 -0
- data/lib/onlyoffice_webdriver_wrapper/helpers/chrome_helper.rb +2 -0
- data/lib/onlyoffice_webdriver_wrapper/helpers/firefox_helper.rb +1 -0
- data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/headless_screenshot_patch.rb +5 -0
- data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/headless_video_recorder.rb +1 -1
- data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/real_display_tools.rb +3 -0
- data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/ruby_helper.rb +2 -1
- data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper.rb +9 -0
- data/lib/onlyoffice_webdriver_wrapper/name.rb +2 -0
- data/lib/onlyoffice_webdriver_wrapper/version.rb +3 -1
- data/lib/onlyoffice_webdriver_wrapper/webdriver/wait_until_methods.rb +10 -0
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_alert_helper.rb +3 -1
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_attributes_helper.rb +18 -2
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_browser_log_helper.rb +1 -0
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_exceptions.rb +1 -0
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_frame_methods.rb +2 -2
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_helper.rb +4 -0
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_js_methods.rb +6 -1
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_navigation_methods.rb +18 -0
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_screenshot_helper.rb +10 -1
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_style_helper.rb +8 -0
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_tab_helper.rb +24 -3
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_type_helper.rb +46 -0
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_user_agent_helper.rb +6 -2
- data/lib/onlyoffice_webdriver_wrapper/webdriver.rb +69 -3
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ebf9c9735115888e5fbb9d4a696bb0c0fbaae159fd3d661b71ccc2e43bda1af
|
4
|
+
data.tar.gz: 0bd97159b92dff8cef5374cb6e26790b06781730c65ed3cd21df247c6df4593a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b87aef54b209ef19aec2e69ac64cba31a1c82421aa8df9259626dc770aa8a09c6a2eb24b168cf6d7763f938da2f8f7e12a3ca640a5e0fb633d330eaebb782a05
|
7
|
+
data.tar.gz: d83bd8c45ffc17d4a8ca4554b6af2ed73b739c9b6c936ec94037343dbb5712b6f66de16799af39bbbb56325cd81073053e897217947d2568f2934ff4f9d453b6
|
data/lib/onlyoffice_webdriver_wrapper/helpers/chrome_helper/chromedriver_bin/chromedriver_mac
CHANGED
Binary file
|
@@ -7,6 +7,7 @@ module OnlyofficeWebdriverWrapper
|
|
7
7
|
module ChromeHelper
|
8
8
|
include ChromeVersionHelper
|
9
9
|
|
10
|
+
# @return [String] list of default Chrome command line switches
|
10
11
|
DEFAULT_CHROME_SWITCHES = %w[--kiosk-printing
|
11
12
|
--disable-gpu
|
12
13
|
--disable-popup-blocking
|
@@ -14,6 +15,7 @@ module OnlyofficeWebdriverWrapper
|
|
14
15
|
--no-sandbox
|
15
16
|
test-type].freeze
|
16
17
|
|
18
|
+
# @return [Selenium::WebDriver::Chrome::Service] Instance of Chrome Service object
|
17
19
|
def chrome_service
|
18
20
|
@chrome_service ||= Selenium::WebDriver::Chrome::Service.new(path: chromedriver_path)
|
19
21
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module OnlyofficeWebdriverWrapper
|
4
4
|
# Module for working with firefox
|
5
5
|
module FirefoxHelper
|
6
|
+
# @return [Selenium::WebDriver::Firefox::Service] Instance of Firefox Service object
|
6
7
|
def firefox_service
|
7
8
|
geckodriver = File.join(File.dirname(__FILE__), 'bin/geckodriver')
|
8
9
|
@firefox_service ||= Selenium::WebDriver::Firefox::Service.new(path: geckodriver)
|
@@ -1,4 +1,9 @@
|
|
1
|
+
# Monkey-patching class from `headless` gem
|
1
2
|
class Headless
|
3
|
+
# Fix incorrect taking of screenshots
|
4
|
+
# @param [String] file_path Path to store screenshot
|
5
|
+
# @param [Hash] options Different options
|
6
|
+
# @return [void]
|
2
7
|
def take_screenshot(file_path, options={})
|
3
8
|
using = options.fetch(:using, :imagemagick)
|
4
9
|
case using
|
@@ -3,12 +3,15 @@
|
|
3
3
|
module OnlyofficeWebdriverWrapper
|
4
4
|
# module for getting info about real display
|
5
5
|
module RealDisplayTools
|
6
|
+
# @return [String] result of `xrandr` command output
|
6
7
|
def xrandr_result
|
7
8
|
result = `xrandr 2>&1`
|
8
9
|
OnlyofficeLoggerHelper.log("xrandr answer: #{result}".delete("\n"))
|
9
10
|
result
|
10
11
|
end
|
11
12
|
|
13
|
+
# Check if any real display connected to system
|
14
|
+
# @return [Boolean] result of this check
|
12
15
|
def real_display_connected?
|
13
16
|
return true if OSHelper.mac?
|
14
17
|
|
@@ -3,12 +3,13 @@
|
|
3
3
|
module OnlyofficeWebdriverWrapper
|
4
4
|
# Module for check ruby info
|
5
5
|
module RubyHelper
|
6
|
+
# @return [Boolean] If current ruby instance run in debug mode
|
6
7
|
def debug?
|
7
8
|
ENV['RUBYLIB'].to_s.include?('ruby-debug')
|
8
9
|
end
|
9
10
|
|
10
11
|
# Check if current os is 64 bit
|
11
|
-
# @return [True, False] result of
|
12
|
+
# @return [True, False] result of check
|
12
13
|
def os_64_bit?
|
13
14
|
RUBY_PLATFORM.include?('_64')
|
14
15
|
end
|
@@ -38,6 +38,8 @@ module OnlyofficeWebdriverWrapper
|
|
38
38
|
true
|
39
39
|
end
|
40
40
|
|
41
|
+
# Start headless session
|
42
|
+
# @return [void]
|
41
43
|
def start
|
42
44
|
create_session = if real_display_connected?
|
43
45
|
should_start?
|
@@ -64,6 +66,8 @@ module OnlyofficeWebdriverWrapper
|
|
64
66
|
start_capture
|
65
67
|
end
|
66
68
|
|
69
|
+
# Stop current headless session
|
70
|
+
# @return [void]
|
67
71
|
def stop
|
68
72
|
return unless running?
|
69
73
|
|
@@ -72,10 +76,15 @@ module OnlyofficeWebdriverWrapper
|
|
72
76
|
headless_instance.destroy
|
73
77
|
end
|
74
78
|
|
79
|
+
# Check if headless session currently running
|
80
|
+
# @return [Boolean] result of this check
|
75
81
|
def running?
|
76
82
|
!headless_instance.nil?
|
77
83
|
end
|
78
84
|
|
85
|
+
# Take a screenshot of current headless session
|
86
|
+
# @param [String] scr_path Path to store screenshot
|
87
|
+
# @return [void]
|
79
88
|
def take_screenshot(scr_path = '/tmp/screenshot.png')
|
80
89
|
return unless running?
|
81
90
|
|
@@ -6,6 +6,11 @@ module OnlyofficeWebdriverWrapper
|
|
6
6
|
# @return [Integer] default timeout for wait element
|
7
7
|
TIMEOUT_WAIT_ELEMENT = 15
|
8
8
|
|
9
|
+
# Wait until something happens
|
10
|
+
# @param [String] timeout How much to wait
|
11
|
+
# @param [String] message which message show if something happens
|
12
|
+
# @param [Boolean] wait_js should we wait for JavaScript actions
|
13
|
+
# @return [void]
|
9
14
|
def wait_until(timeout = ::PageObject.default_page_wait, message = nil, wait_js: true, &block)
|
10
15
|
tries ||= 3
|
11
16
|
wait = Object::Selenium::WebDriver::Wait.new(timeout: timeout, message: message)
|
@@ -22,6 +27,11 @@ module OnlyofficeWebdriverWrapper
|
|
22
27
|
webdriver_error('Wait until: rescuing from Stale Element error failed after 3 tries')
|
23
28
|
end
|
24
29
|
|
30
|
+
# Wait until element is visible
|
31
|
+
# @param [String] xpath_name to find object
|
32
|
+
# @param [Integer] timeout How much to wait
|
33
|
+
# @raise [StandardError] error if element not found for timeout
|
34
|
+
# @return [void]
|
25
35
|
def wait_until_element_visible(xpath_name, timeout = 15)
|
26
36
|
wait_until_element_present(xpath_name)
|
27
37
|
time = 0
|
@@ -3,12 +3,14 @@
|
|
3
3
|
module OnlyofficeWebdriverWrapper
|
4
4
|
# Methods for working with alerts
|
5
5
|
module WebdriverAlertHelper
|
6
|
+
# Confirm current alert
|
7
|
+
# @return [void]
|
6
8
|
def alert_confirm
|
7
9
|
@driver.switch_to.alert.accept if alert_exists?
|
8
10
|
end
|
9
11
|
|
10
12
|
# Check if alert exists
|
11
|
-
# @return [
|
13
|
+
# @return [Boolean]
|
12
14
|
def alert_exists?
|
13
15
|
@driver.switch_to.alert.text
|
14
16
|
true
|
@@ -3,9 +3,11 @@
|
|
3
3
|
module OnlyofficeWebdriverWrapper
|
4
4
|
# Module with methods to work with attributes
|
5
5
|
module WebdriverAttributesHelper
|
6
|
+
# Check if attribute of xpath is exists
|
7
|
+
# @param [String] xpath_name to find object
|
8
|
+
# @param [String] attribute name to check
|
9
|
+
# @return [Boolean] result of check
|
6
10
|
def attribute_exist?(xpath_name, attribute)
|
7
|
-
exist = false
|
8
|
-
|
9
11
|
element = xpath_name.is_a?(String) ? get_element(xpath_name) : xpath_name
|
10
12
|
begin
|
11
13
|
attribute_value = element.attribute(attribute)
|
@@ -16,6 +18,10 @@ module OnlyofficeWebdriverWrapper
|
|
16
18
|
exist
|
17
19
|
end
|
18
20
|
|
21
|
+
# Get attribute of element
|
22
|
+
# @param [String] xpath_name to find object
|
23
|
+
# @param [String] attribute to get
|
24
|
+
# @return [String] value of attribute
|
19
25
|
def get_attribute(xpath_name, attribute)
|
20
26
|
element = xpath_name.is_a?(Selenium::WebDriver::Element) ? xpath_name : get_element(xpath_name)
|
21
27
|
|
@@ -26,6 +32,10 @@ module OnlyofficeWebdriverWrapper
|
|
26
32
|
end
|
27
33
|
end
|
28
34
|
|
35
|
+
# Get attributes of several elements
|
36
|
+
# @param [String] xpath_several_elements to find objects
|
37
|
+
# @param [String] attribute to get
|
38
|
+
# @return [Array<String>] list of attributes
|
29
39
|
def get_attributes_of_several_elements(xpath_several_elements, attribute)
|
30
40
|
elements = @driver.find_elements(:xpath, xpath_several_elements)
|
31
41
|
|
@@ -34,6 +44,12 @@ module OnlyofficeWebdriverWrapper
|
|
34
44
|
end
|
35
45
|
end
|
36
46
|
|
47
|
+
# Get index of element from array with attribute value
|
48
|
+
# @param [String] xpath to find objects
|
49
|
+
# @param [String] attribute to check
|
50
|
+
# @param [String] value to compare
|
51
|
+
# @param [Boolean] only_visible ignore invisible elements unless only_visible
|
52
|
+
# @return [Integer] index of element or `0` if not found
|
37
53
|
def get_index_of_elements_with_attribute(xpath, attribute, value, only_visible = true)
|
38
54
|
get_elements(xpath, only_visible).each_with_index do |element, index|
|
39
55
|
return (index + 1) if get_attribute(element, attribute).include?(value)
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module OnlyofficeWebdriverWrapper
|
4
4
|
# Methods for working with browser console logs
|
5
5
|
module WebdriverBrowserLogHelper
|
6
|
+
# @return [Array] list of browser logs
|
6
7
|
def browser_logs
|
7
8
|
return [] if browser == :firefox # not implemented, see https://github.com/mozilla/geckodriver/issues/284
|
8
9
|
|
@@ -14,11 +14,11 @@ module OnlyofficeWebdriverWrapper
|
|
14
14
|
rescue Selenium::WebDriver::Error::NoSuchElementError
|
15
15
|
OnlyofficeLoggerHelper.log('Raise NoSuchElementError in the select_frame method')
|
16
16
|
rescue Exception => e
|
17
|
-
webdriver_error("Raise
|
17
|
+
webdriver_error("Raise unknown exception: #{e}")
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
# Select top frame of browser (even if several
|
21
|
+
# Select top frame of browser (even if several sub-frames exists)
|
22
22
|
# @return [nil]
|
23
23
|
def select_top_frame
|
24
24
|
@driver.switch_to.default_content
|
@@ -6,6 +6,10 @@ require 'tempfile'
|
|
6
6
|
module OnlyofficeWebdriverWrapper
|
7
7
|
# Some additional methods for webdriver
|
8
8
|
module WebdriverHelper
|
9
|
+
# Make screenshot by system methods
|
10
|
+
# Works only on Linux
|
11
|
+
# @param [String] file_name to export screenshot
|
12
|
+
# @return [String] result of screenshot command execution
|
9
13
|
def system_screenshot(file_name)
|
10
14
|
`import -window root #{file_name}`
|
11
15
|
end
|
@@ -29,6 +29,10 @@ module OnlyofficeWebdriverWrapper
|
|
29
29
|
"document.evaluate(\"#{escaped_xpath}\", document, null, XPathResult.ANY_TYPE, null).iterateNext()"
|
30
30
|
end
|
31
31
|
|
32
|
+
# Type to locator by javascript
|
33
|
+
# @param [String] xpath_name to find object where to type
|
34
|
+
# @param [String] text to type
|
35
|
+
# @return [void]
|
32
36
|
def type_to_locator_by_javascript(xpath_name, text)
|
33
37
|
escaped_text = text.gsub('\\', '\\\\\\\\').gsub('"', '\\"').gsub("\n", '\\n')
|
34
38
|
execute_javascript("document.evaluate('#{xpath_name}', document, null, XPathResult.ANY_TYPE, null).iterateNext().value=\"#{escaped_text}\";")
|
@@ -52,7 +56,7 @@ module OnlyofficeWebdriverWrapper
|
|
52
56
|
Dimensions.new(width, height)
|
53
57
|
end
|
54
58
|
|
55
|
-
# Get object absolute
|
59
|
+
# Get object absolute position from top left edge of screen
|
56
60
|
# @param xpath [Sting] xpath of object
|
57
61
|
# @return [CursorPoint] position of element
|
58
62
|
def object_absolute_position(xpath)
|
@@ -76,6 +80,7 @@ module OnlyofficeWebdriverWrapper
|
|
76
80
|
execute_javascript('return window.jQuery.active;').zero?
|
77
81
|
end
|
78
82
|
|
83
|
+
# @return [Boolean] Is document is ready, finished to be loading
|
79
84
|
def document_ready?
|
80
85
|
execute_javascript('return document.readyState;') == 'complete'
|
81
86
|
end
|
@@ -8,6 +8,7 @@ module OnlyofficeWebdriverWrapper
|
|
8
8
|
# @return [nil]
|
9
9
|
def open(url)
|
10
10
|
url = "http://#{url}" unless url.include?('http') || url.include?('file://')
|
11
|
+
ensure_url_available(url)
|
11
12
|
@driver.navigate.to url
|
12
13
|
sleep(1) # Correct wait for Page to init focus
|
13
14
|
OnlyofficeLoggerHelper.log("Opened page: #{url}")
|
@@ -59,5 +60,22 @@ module OnlyofficeWebdriverWrapper
|
|
59
60
|
cleanup_download_folder
|
60
61
|
@browser_running = false
|
61
62
|
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
# Fast check if url available
|
67
|
+
# @param [String] url to check
|
68
|
+
# @param [Integer] timeout for wait for page to load
|
69
|
+
# @raise [Net::ReadTimeout] exception if timeout happened
|
70
|
+
# @return [nil]
|
71
|
+
def ensure_url_available(url, timeout: 5)
|
72
|
+
return true unless url.start_with?('http://')
|
73
|
+
|
74
|
+
URI.parse(url).open(read_timeout: timeout,
|
75
|
+
open_timeout: timeout).read
|
76
|
+
rescue StandardError => e
|
77
|
+
OnlyofficeLoggerHelper.log("Url: #{url} is not available with error `#{e}`")
|
78
|
+
raise Net::ReadTimeout, e
|
79
|
+
end
|
62
80
|
end
|
63
81
|
end
|
@@ -18,6 +18,9 @@ module OnlyofficeWebdriverWrapper
|
|
18
18
|
'/tmp/screenshot/WebdriverError'
|
19
19
|
end
|
20
20
|
|
21
|
+
# Get screenshot of current windows and upload it to cloud storage
|
22
|
+
# @param [String] path_to_screenshot place to store local screenshot
|
23
|
+
# @return [String] url of public screenshot
|
21
24
|
def get_screenshot_and_upload(path_to_screenshot = "#{screenshot_folder}/#{StringHelper.generate_random_string}.png")
|
22
25
|
begin
|
23
26
|
get_screenshot(path_to_screenshot)
|
@@ -37,6 +40,9 @@ module OnlyofficeWebdriverWrapper
|
|
37
40
|
path_to_screenshot
|
38
41
|
end
|
39
42
|
|
43
|
+
# Get screenshot of current window
|
44
|
+
# @param [String] path_to_screenshot place to store local screenshot
|
45
|
+
# @return [void]
|
40
46
|
def get_screenshot(path_to_screenshot = "#{screenshot_folder}/#{StringHelper.generate_random_string}.png")
|
41
47
|
screenshot_folder = File.dirname(path_to_screenshot)
|
42
48
|
FileUtils.mkdir_p(screenshot_folder) unless File.directory?(screenshot_folder)
|
@@ -44,6 +50,9 @@ module OnlyofficeWebdriverWrapper
|
|
44
50
|
OnlyofficeLoggerHelper.log("get_screenshot(#{path_to_screenshot})")
|
45
51
|
end
|
46
52
|
|
53
|
+
# Make a screenshot by webdriver methods
|
54
|
+
# @param [String] screenshot_name random name for file
|
55
|
+
# @return [String] text string with screenshot file location
|
47
56
|
def webdriver_screenshot(screenshot_name = SecureRandom.uuid)
|
48
57
|
begin
|
49
58
|
link = get_screenshot_and_upload("#{screenshot_folder}/#{screenshot_name}.png")
|
@@ -72,7 +81,7 @@ module OnlyofficeWebdriverWrapper
|
|
72
81
|
|
73
82
|
# Publish screenshot
|
74
83
|
# @param [String] path to file
|
75
|
-
# @return [String]
|
84
|
+
# @return [String] public internet link to file
|
76
85
|
def publish_screenshot(path)
|
77
86
|
amazon_s3_wrapper.upload_file_and_make_public(path,
|
78
87
|
nil,
|
@@ -3,6 +3,10 @@
|
|
3
3
|
module OnlyofficeWebdriverWrapper
|
4
4
|
# Webdriver style helper
|
5
5
|
module WebdriverStyleHelper
|
6
|
+
# Get style parameter of object
|
7
|
+
# @param [String] xpath to find object
|
8
|
+
# @param [String] parameter_name which parameter to get
|
9
|
+
# @return [String, nil] nil if there is no such param
|
6
10
|
def get_style_parameter(xpath, parameter_name)
|
7
11
|
get_attribute(xpath, 'style').split(';').each do |current_param|
|
8
12
|
return /:\s(.*);?$/.match(current_param)[1] if current_param.include?(parameter_name)
|
@@ -21,6 +25,10 @@ module OnlyofficeWebdriverWrapper
|
|
21
25
|
|
22
26
|
alias set_style_parameter set_style_attribute
|
23
27
|
|
28
|
+
# Show element by changing it css style
|
29
|
+
# @param [String] xpath to find object
|
30
|
+
# @param [Boolean] move_to_center should object be moved to center of screen
|
31
|
+
# @return [void]
|
24
32
|
def set_style_show_by_xpath(xpath, move_to_center = false)
|
25
33
|
execute_javascript("#{dom_element_by_xpath(xpath)}.style.display = 'block';")
|
26
34
|
return unless move_to_center
|
@@ -3,19 +3,28 @@
|
|
3
3
|
module OnlyofficeWebdriverWrapper
|
4
4
|
# Module for work with tabs
|
5
5
|
module WebdriverTabHelper
|
6
|
+
# @return [Integer] Default timeout for waiting for element
|
6
7
|
TIMEOUT_WAIT_ELEMENT = 15
|
7
8
|
|
9
|
+
# Create new tab
|
10
|
+
# @return [void]
|
8
11
|
def new_tab
|
9
12
|
execute_javascript('window.open()')
|
10
13
|
end
|
11
14
|
|
15
|
+
# Resize current tab to specific size
|
16
|
+
# @param [Integer] width to set
|
17
|
+
# @param [Integer] height to set
|
18
|
+
# @return [void]
|
12
19
|
def resize_tab(width, height)
|
13
20
|
@driver.manage.window.resize_to(width, height)
|
14
21
|
OnlyofficeLoggerHelper.log("Resize current window to #{width}x#{height}")
|
15
22
|
end
|
16
23
|
|
24
|
+
# Switch to popup window
|
17
25
|
# @param after_switch_timeout [Integer] wait after switch to window
|
18
26
|
# non-zero to workaround bug with page load hanging up after switch
|
27
|
+
# @return [void]
|
19
28
|
def switch_to_popup(after_switch_timeout: 3)
|
20
29
|
counter = 0
|
21
30
|
while tab_count < 2 && counter < 30
|
@@ -37,32 +46,44 @@ module OnlyofficeWebdriverWrapper
|
|
37
46
|
tab_count
|
38
47
|
end
|
39
48
|
|
40
|
-
|
49
|
+
# Choose tab by it's number
|
50
|
+
# @param [Integer] tab_number to choose
|
51
|
+
# @param [Integer] timeout how much for this tab
|
52
|
+
# @raise [RuntimeError] error if tab not found
|
53
|
+
# @return [void]
|
54
|
+
def choose_tab(tab_number, timeout: TIMEOUT_WAIT_ELEMENT)
|
41
55
|
counter = 0
|
42
|
-
while tab_count <
|
56
|
+
while tab_count < tab_number && counter < timeout
|
43
57
|
sleep 1
|
44
58
|
counter += 1
|
45
59
|
end
|
46
|
-
webdriver_error("choose_tab: Tab number = #{tab_number} not found") if counter >=
|
60
|
+
webdriver_error("choose_tab: Tab number = #{tab_number} not found") if counter >= timeout
|
47
61
|
@driver.switch_to.window(@driver.window_handles[tab_number - 1])
|
48
62
|
end
|
49
63
|
|
64
|
+
# Switch to first tab of chrome
|
65
|
+
# @return [void]
|
50
66
|
def switch_to_main_tab
|
51
67
|
@driver.switch_to.window(@driver.window_handles.first)
|
52
68
|
end
|
53
69
|
|
70
|
+
# Close current active tab and switch to first one
|
71
|
+
# @return [void]
|
54
72
|
def close_tab
|
55
73
|
@driver.close
|
56
74
|
sleep 1
|
57
75
|
switch_to_main_tab
|
58
76
|
end
|
59
77
|
|
78
|
+
# Wait for popup window, close it and return to first tab
|
79
|
+
# @return [void]
|
60
80
|
def close_popup_and_switch_to_main_tab
|
61
81
|
switch_to_popup
|
62
82
|
close_tab
|
63
83
|
switch_to_main_tab
|
64
84
|
end
|
65
85
|
|
86
|
+
# @return [String] title of current tab
|
66
87
|
def get_title_of_current_tab
|
67
88
|
@driver.title
|
68
89
|
end
|
@@ -3,17 +3,35 @@
|
|
3
3
|
module OnlyofficeWebdriverWrapper
|
4
4
|
# Class for helping with type stuff
|
5
5
|
module WebdriverTypeHelper
|
6
|
+
# Type text to element
|
7
|
+
# @param [String] element to find object
|
8
|
+
# @param [String] text_to_send text to type
|
9
|
+
# @param [Boolean] clear_area should area be cleared
|
10
|
+
# @return [void]
|
6
11
|
def type_text(element, text_to_send, clear_area = false)
|
7
12
|
element = get_element(element)
|
8
13
|
element.clear if clear_area
|
9
14
|
element.send_keys(text_to_send)
|
10
15
|
end
|
11
16
|
|
17
|
+
# Type text to element and select it
|
18
|
+
# @param [String] element to find object
|
19
|
+
# @param [String] text_to_send text to type
|
20
|
+
# @param [Boolean] clear_area should area be cleared
|
21
|
+
# @return [void]
|
12
22
|
def type_text_and_select_it(element, text_to_send, clear_area = false)
|
13
23
|
type_text(element, text_to_send, clear_area)
|
14
24
|
text_to_send.length.times { element.send_keys %i[shift left] }
|
15
25
|
end
|
16
26
|
|
27
|
+
# Type text to object
|
28
|
+
# @param [String] xpath_name to find object
|
29
|
+
# @param [String] text_to_send text to type
|
30
|
+
# @param [Boolean] clear_content should content be cleared
|
31
|
+
# @param [Boolean] click_on_it should object be clicked
|
32
|
+
# @param [Boolean] by_action type by `@driver.action` if true
|
33
|
+
# @param [Boolean] by_element_send_key use `element.send_keys` if true
|
34
|
+
# @return [void]
|
17
35
|
def type_to_locator(xpath_name, text_to_send, clear_content = true, click_on_it = false, by_action = false, by_element_send_key = false)
|
18
36
|
element = get_element(xpath_name)
|
19
37
|
if clear_content
|
@@ -45,6 +63,12 @@ module OnlyofficeWebdriverWrapper
|
|
45
63
|
end
|
46
64
|
end
|
47
65
|
|
66
|
+
# Type text to input
|
67
|
+
# @param [String] xpath_name to find object
|
68
|
+
# @param [String] text_to_send text to type
|
69
|
+
# @param [Boolean] clear_content should content be cleared
|
70
|
+
# @param [Boolean] click_on_it should object be clicked
|
71
|
+
# @return [void]
|
48
72
|
def type_to_input(xpath_name, text_to_send, clear_content = false, click_on_it = true)
|
49
73
|
element = get_element(xpath_name)
|
50
74
|
if element.nil?
|
@@ -65,6 +89,11 @@ module OnlyofficeWebdriverWrapper
|
|
65
89
|
element.send_keys text_to_send
|
66
90
|
end
|
67
91
|
|
92
|
+
# Send keys to object
|
93
|
+
# @param [String] xpath_name to find object
|
94
|
+
# @param [String] text_to_send text to type
|
95
|
+
# @param [Boolean] by_action type by `@driver.action` if true
|
96
|
+
# @return [void]
|
68
97
|
def send_keys(xpath_name, text_to_send, by_action = true)
|
69
98
|
element = get_element(xpath_name)
|
70
99
|
@driver.action.click(element).perform if @browser == :firefox
|
@@ -75,21 +104,36 @@ module OnlyofficeWebdriverWrapper
|
|
75
104
|
end
|
76
105
|
end
|
77
106
|
|
107
|
+
# Type text to currently focused element
|
108
|
+
# @param [Array<String, Symbol>, String, Symbol] keys to send
|
109
|
+
# @param [Integer] count_of_times how much times to repeat
|
110
|
+
# @return [void]
|
78
111
|
def send_keys_to_focused_elements(keys, count_of_times = 1)
|
79
112
|
command = @driver.action.send_keys(keys)
|
80
113
|
(count_of_times - 1).times { command = command.send_keys(keys) }
|
81
114
|
command.perform
|
82
115
|
end
|
83
116
|
|
117
|
+
# Press some specific key
|
118
|
+
# @param [String, Symbol] key to press
|
119
|
+
# @return [void]
|
84
120
|
def press_key(key)
|
85
121
|
@driver.action.send_keys(key).perform
|
86
122
|
end
|
87
123
|
|
124
|
+
# Simulate pressed down key on object
|
125
|
+
# @param [String] xpath to find object
|
126
|
+
# @param [String, Symbol] key to press
|
127
|
+
# @return [void]
|
88
128
|
def key_down(xpath, key)
|
89
129
|
@driver.action.key_down(get_element(xpath), key).perform
|
90
130
|
sleep(1) # for some reason quick key_down select text in control
|
91
131
|
end
|
92
132
|
|
133
|
+
# Release pressed key from object
|
134
|
+
# @param [String] xpath to find object
|
135
|
+
# @param [String, Symbol] key to release
|
136
|
+
# @return [void]
|
93
137
|
def key_up(xpath, key)
|
94
138
|
@driver.action.key_up(get_element(xpath), key).perform
|
95
139
|
end
|
@@ -99,6 +143,8 @@ module OnlyofficeWebdriverWrapper
|
|
99
143
|
# Workaround for bug with typing with :control
|
100
144
|
# See https://github.com/SeleniumHQ/selenium/issues/8179
|
101
145
|
# for more details
|
146
|
+
# @param [String] text_to_send text to type
|
147
|
+
# @return [void]
|
102
148
|
def webdriver_bug_8179_workaround(text_to_send)
|
103
149
|
text_to_send = [text_to_send].flatten
|
104
150
|
|
@@ -1,22 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module OnlyofficeWebdriverWrapper
|
4
|
-
# Module for
|
4
|
+
# Module for working with webdriver useragent
|
5
5
|
module WebdriverUserAgentHelper
|
6
|
+
# @return [String] useragent for Android phone browser
|
6
7
|
USERAGENT_ANDROID_PHONE = 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MDB08M) '\
|
7
8
|
'AppleWebKit/537.36 (KHTML, like Gecko) '\
|
8
9
|
'Chrome/51.0.2704.81 Mobile Safari/537.36'
|
10
|
+
# @return [String] useragent for iPhone browser
|
9
11
|
USERAGENT_IPHONE = 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X) '\
|
10
12
|
'AppleWebKit/601.1.46 (KHTML, like Gecko) '\
|
11
13
|
'Version/9.0 Mobile/13F69 Safari/601.1'
|
14
|
+
# @return [String] useragent for iPad Air 2 Safari browser
|
12
15
|
USERAGENT_IPAD_AIR_2_SAFARI = 'Mozilla/5.0 (iPad; CPU OS 10_0 like Mac OS X) '\
|
13
16
|
'AppleWebKit/602.1.50 (KHTML, like Gecko) '\
|
14
17
|
'Version/10.0 Mobile/14A5346a Safari/602.1'
|
18
|
+
# @return [String] useragent for Nexus 10 Chrome browser
|
15
19
|
USERAGENT_NEXUS_10_CHROME = 'Mozilla/5.0 (Linux; Android 4.3; Nexus 10 Build/JSS15Q) '\
|
16
20
|
'AppleWebKit/537.36 (KHTML, like Gecko) '\
|
17
21
|
'Chrome/48.0.2564.23 Safari/537.36'
|
18
22
|
|
19
|
-
# @return [String] user agent string for current device
|
23
|
+
# @return [String, nil] user agent string for current device
|
20
24
|
def user_agent_for_device
|
21
25
|
case @device
|
22
26
|
when :desktop_linux
|
@@ -25,6 +25,7 @@ require_relative 'webdriver/webdriver_tab_helper'
|
|
25
25
|
require_relative 'webdriver/webdriver_user_agent_helper'
|
26
26
|
require_relative 'webdriver/webdriver_browser_log_helper'
|
27
27
|
|
28
|
+
# Namespace of this gem
|
28
29
|
module OnlyofficeWebdriverWrapper
|
29
30
|
# noinspection RubyTooManyMethodsInspection, RubyInstanceMethodNamingConvention, RubyParameterNamingConvention
|
30
31
|
class WebDriver
|
@@ -47,6 +48,7 @@ module OnlyofficeWebdriverWrapper
|
|
47
48
|
include WebdriverTabHelper
|
48
49
|
include WebdriverUserAgentHelper
|
49
50
|
include WebdriverBrowserLogHelper
|
51
|
+
# @return [Integer] Default timeout for waiting to file to download
|
50
52
|
TIMEOUT_FILE_DOWNLOAD = 100
|
51
53
|
# @return [Array, String] default switches for chrome
|
52
54
|
attr_accessor :driver
|
@@ -89,6 +91,9 @@ module OnlyofficeWebdriverWrapper
|
|
89
91
|
@browser_running = true
|
90
92
|
end
|
91
93
|
|
94
|
+
# Get element by it's xpath
|
95
|
+
# @param [String] object_identification xpath of object to find
|
96
|
+
# @return [Object, nil] nil if nothing found
|
92
97
|
def get_element(object_identification)
|
93
98
|
return object_identification unless object_identification.is_a?(String)
|
94
99
|
|
@@ -104,11 +109,19 @@ module OnlyofficeWebdriverWrapper
|
|
104
109
|
get_elements(array_elements).map { |current_element| get_text(current_element) }
|
105
110
|
end
|
106
111
|
|
112
|
+
# Select from list elements
|
113
|
+
# @param [String] value value to find object
|
114
|
+
# @param [Array<Object>] elements_value elements to check
|
115
|
+
# @return [void]
|
107
116
|
def select_from_list_elements(value, elements_value)
|
108
117
|
index = get_element_index(value, elements_value)
|
109
118
|
elements_value[index].click
|
110
119
|
end
|
111
120
|
|
121
|
+
# Get index of element by it's text
|
122
|
+
# @param [String] title to compare text
|
123
|
+
# @param [Array<Objects>] list_elements to find in which
|
124
|
+
# @return [Object, nil] nil if nothing found
|
112
125
|
def get_element_index(title, list_elements)
|
113
126
|
list_elements.each_with_index do |current, i|
|
114
127
|
return i if get_text(current) == title
|
@@ -116,22 +129,36 @@ module OnlyofficeWebdriverWrapper
|
|
116
129
|
nil
|
117
130
|
end
|
118
131
|
|
132
|
+
# Get all options for combo box
|
133
|
+
# @param [String] xpath_name to find combobox
|
134
|
+
# @return [Array<String>] values
|
119
135
|
def get_all_combo_box_values(xpath_name)
|
120
136
|
@driver.find_element(:xpath, xpath_name).find_elements(tag_name: 'option').map { |el| el.attribute('value') }
|
121
137
|
end
|
122
138
|
|
139
|
+
# Scroll list to specific element
|
140
|
+
# @param [String] list_xpath how to find this list
|
141
|
+
# @param [String] element_xpath to which we should scrolled
|
142
|
+
# @return [void]
|
123
143
|
def scroll_list_to_element(list_xpath, element_xpath)
|
124
144
|
execute_javascript("$(document.evaluate(\"#{list_xpath}\", document, null, XPathResult.ANY_TYPE, null).
|
125
145
|
iterateNext()).jScrollPane().data('jsp').scrollToElement(document.evaluate(\"#{element_xpath}\",
|
126
146
|
document, null, XPathResult.ANY_TYPE, null).iterateNext());")
|
127
147
|
end
|
128
148
|
|
149
|
+
# Scroll list by pixel count
|
150
|
+
# @param [String] list_xpath how to detect this list
|
151
|
+
# @param [Integer] pixels how much to scroll
|
152
|
+
# @return [void]
|
129
153
|
def scroll_list_by_pixels(list_xpath, pixels)
|
130
154
|
execute_javascript("$(document.evaluate(\"#{list_xpath.tr('"', "'")}\", document, null, XPathResult.ANY_TYPE, null).iterateNext()).scrollTop(#{pixels})")
|
131
155
|
end
|
132
156
|
|
133
157
|
# Open dropdown selector, like 'Color Selector', which has no element id
|
134
158
|
# @param [String] xpath_name name of dropdown list
|
159
|
+
# @param [Integer] horizontal_shift x value
|
160
|
+
# @param [Integer] vertical_shift y value
|
161
|
+
# @return [void]
|
135
162
|
def open_dropdown_selector(xpath_name, horizontal_shift = 30, vertical_shift = 0)
|
136
163
|
element = get_element(xpath_name)
|
137
164
|
if @browser == :firefox || @browser == :safari
|
@@ -145,12 +172,22 @@ module OnlyofficeWebdriverWrapper
|
|
145
172
|
end
|
146
173
|
end
|
147
174
|
|
175
|
+
# Perform an action on coordinate
|
176
|
+
# @param [String] xpath_name to find element
|
177
|
+
# @param [Integer] right_by x coordinate
|
178
|
+
# @param [Integer] down_by y coordinate
|
179
|
+
# @param [Symbol] action to perform
|
180
|
+
# @param [Integer] times how much times to repeat
|
181
|
+
# @return [void]
|
148
182
|
def action_on_locator_coordinates(xpath_name, right_by, down_by, action = :click, times = 1)
|
149
183
|
wait_until_element_visible(xpath_name)
|
150
184
|
element = @driver.find_element(:xpath, xpath_name)
|
151
185
|
(0...times).inject(@driver.action.move_to(element, right_by.to_i, down_by.to_i)) { |acc, _elem| acc.send(action) }.perform
|
152
186
|
end
|
153
187
|
|
188
|
+
# Check if element present on page
|
189
|
+
# @param [String] xpath_name to find element
|
190
|
+
# @return [Boolean] result of check
|
154
191
|
def element_present?(xpath_name)
|
155
192
|
case xpath_name
|
156
193
|
when PageObject::Elements::Element
|
@@ -165,6 +202,9 @@ module OnlyofficeWebdriverWrapper
|
|
165
202
|
false
|
166
203
|
end
|
167
204
|
|
205
|
+
# Get first visible element from several
|
206
|
+
# @param [String] xpath_name to find several objects
|
207
|
+
# @return [Object] first visible element
|
168
208
|
def get_element_by_display(xpath_name)
|
169
209
|
@driver.find_elements(:xpath, xpath_name).each do |element|
|
170
210
|
return element if element.displayed?
|
@@ -186,6 +226,10 @@ module OnlyofficeWebdriverWrapper
|
|
186
226
|
end
|
187
227
|
end
|
188
228
|
|
229
|
+
# Get array of webdriver object by xpath
|
230
|
+
# @param [String] objects_identification object to find
|
231
|
+
# @param [Boolean] only_visible return invisible if true
|
232
|
+
# @return [Array, Object] list of objects
|
189
233
|
def get_elements(objects_identification, only_visible = true)
|
190
234
|
return objects_identification if objects_identification.is_a?(Array)
|
191
235
|
|
@@ -198,6 +242,9 @@ module OnlyofficeWebdriverWrapper
|
|
198
242
|
elements
|
199
243
|
end
|
200
244
|
|
245
|
+
# Check if element visible on page
|
246
|
+
# @param [String] xpath_name element to find
|
247
|
+
# @return [Boolean] result of check
|
201
248
|
def element_visible?(xpath_name)
|
202
249
|
if xpath_name.is_a?(PageObject::Elements::Element) # PageObject always visible
|
203
250
|
true
|
@@ -225,12 +272,13 @@ module OnlyofficeWebdriverWrapper
|
|
225
272
|
end
|
226
273
|
false
|
227
274
|
rescue Exception => e
|
228
|
-
webdriver_error("Raise
|
275
|
+
webdriver_error("Raise unknown exception: #{e}")
|
229
276
|
end
|
230
277
|
|
231
278
|
# Get text of current element
|
232
279
|
# @param [String] xpath_name name of xpath
|
233
|
-
# @param [
|
280
|
+
# @param [Boolean] wait_until_visible wait until element visible
|
281
|
+
# @return [String] result string
|
234
282
|
def get_text(xpath_name, wait_until_visible = true)
|
235
283
|
wait_until_element_visible(xpath_name) if wait_until_visible
|
236
284
|
|
@@ -243,10 +291,18 @@ module OnlyofficeWebdriverWrapper
|
|
243
291
|
end
|
244
292
|
end
|
245
293
|
|
294
|
+
# Get text from several elements
|
295
|
+
# @param [String] xpath_several_elements to find objects
|
296
|
+
# @return [Array<String>] text of those elements
|
246
297
|
def get_text_of_several_elements(xpath_several_elements)
|
247
298
|
@driver.find_elements(:xpath, xpath_several_elements).map { |element| element.text unless element.text == '' }.compact
|
248
299
|
end
|
249
300
|
|
301
|
+
# Select value of combo box
|
302
|
+
# @param [String] xpath_name to find combobox
|
303
|
+
# @param [String] select_value to select
|
304
|
+
# @param [Symbol] select_by select type
|
305
|
+
# @return [void]
|
250
306
|
def select_combo_box(xpath_name, select_value, select_by = :value)
|
251
307
|
wait_until_element_visible(xpath_name)
|
252
308
|
option = Selenium::WebDriver::Support::Select.new(get_element(xpath_name))
|
@@ -263,6 +319,11 @@ module OnlyofficeWebdriverWrapper
|
|
263
319
|
@driver.execute_script('return document.documentElement.innerHTML;')
|
264
320
|
end
|
265
321
|
|
322
|
+
# Raise an error, making a screenshot before it
|
323
|
+
# @param [String, Object] exception class to raise
|
324
|
+
# @param [String] error_message to raise
|
325
|
+
# @raise [Object] specified exception
|
326
|
+
# @return [void]
|
266
327
|
def webdriver_error(exception, error_message = nil)
|
267
328
|
if exception.is_a?(String) # If there is no error_message
|
268
329
|
error_message = exception
|
@@ -273,6 +334,11 @@ module OnlyofficeWebdriverWrapper
|
|
273
334
|
raise exception, "#{error_message}\n\nPage address: #{current_url}\n\nError #{webdriver_screenshot}"
|
274
335
|
end
|
275
336
|
|
337
|
+
# Wait for file to be downloaded
|
338
|
+
# @param [String] file_name to wait for download
|
339
|
+
# @param [Integer] timeout to wait for file to download
|
340
|
+
# @raise [StandardError] error if something happened and file not downloaded
|
341
|
+
# @return [String] full file name of downloaded file
|
276
342
|
def wait_file_for_download(file_name, timeout = TIMEOUT_FILE_DOWNLOAD)
|
277
343
|
full_file_name = "#{@download_directory}/#{file_name}"
|
278
344
|
full_file_name = file_name if file_name[0] == '/'
|
@@ -291,7 +357,7 @@ module OnlyofficeWebdriverWrapper
|
|
291
357
|
def self.clean_up(forced = false)
|
292
358
|
return unless OnlyofficeFileHelper::LinuxHelper.user_name.include?('nct-at') ||
|
293
359
|
OnlyofficeFileHelper::LinuxHelper.user_name.include?('ubuntu') ||
|
294
|
-
forced
|
360
|
+
forced
|
295
361
|
|
296
362
|
OnlyofficeFileHelper::LinuxHelper.kill_all('chromedriver')
|
297
363
|
OnlyofficeFileHelper::LinuxHelper.kill_all('geckodriver')
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: onlyoffice_webdriver_wrapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ONLYOFFICE
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2021-12-
|
14
|
+
date: 2021-12-13 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: headless
|
@@ -243,6 +243,26 @@ dependencies:
|
|
243
243
|
- - "~>"
|
244
244
|
- !ruby/object:Gem::Version
|
245
245
|
version: '2'
|
246
|
+
- !ruby/object:Gem::Dependency
|
247
|
+
name: yard
|
248
|
+
requirement: !ruby/object:Gem::Requirement
|
249
|
+
requirements:
|
250
|
+
- - "~>"
|
251
|
+
- !ruby/object:Gem::Version
|
252
|
+
version: '0'
|
253
|
+
- - ">="
|
254
|
+
- !ruby/object:Gem::Version
|
255
|
+
version: 0.9.20
|
256
|
+
type: :development
|
257
|
+
prerelease: false
|
258
|
+
version_requirements: !ruby/object:Gem::Requirement
|
259
|
+
requirements:
|
260
|
+
- - "~>"
|
261
|
+
- !ruby/object:Gem::Version
|
262
|
+
version: '0'
|
263
|
+
- - ">="
|
264
|
+
- !ruby/object:Gem::Version
|
265
|
+
version: 0.9.20
|
246
266
|
description: ONLYOFFICE Webdriver Wrapper Gem. Used in QA
|
247
267
|
email:
|
248
268
|
- shockwavenn@gmail.com
|