onlyoffice_webdriver_wrapper 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. checksums.yaml +7 -0
  2. data/lib/onlyoffice_webdriver_wrapper.rb +5 -0
  3. data/lib/onlyoffice_webdriver_wrapper/dimensions.rb +16 -0
  4. data/lib/onlyoffice_webdriver_wrapper/helpers/bin/chromedriver +0 -0
  5. data/lib/onlyoffice_webdriver_wrapper/helpers/bin/chromedriver_mac +0 -0
  6. data/lib/onlyoffice_webdriver_wrapper/helpers/bin/geckodriver +0 -0
  7. data/lib/onlyoffice_webdriver_wrapper/helpers/chrome_helper.rb +62 -0
  8. data/lib/onlyoffice_webdriver_wrapper/helpers/firefox_helper.rb +26 -0
  9. data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper.rb +65 -0
  10. data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/real_display_tools.rb +22 -0
  11. data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/ruby_helper.rb +14 -0
  12. data/lib/onlyoffice_webdriver_wrapper/helpers/os_helper.rb +9 -0
  13. data/lib/onlyoffice_webdriver_wrapper/version.rb +5 -0
  14. data/lib/onlyoffice_webdriver_wrapper/webdriver.rb +713 -0
  15. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_alert_helper.rb +25 -0
  16. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_attributes_helper.rb +53 -0
  17. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_browser_info_helper.rb +20 -0
  18. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_browser_log_helper.rb +9 -0
  19. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_exceptions.rb +3 -0
  20. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_extension.rb +2 -0
  21. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_helper.rb +22 -0
  22. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_js_methods.rb +56 -0
  23. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_screenshot_helper.rb +60 -0
  24. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_style_helper.rb +41 -0
  25. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_tab_helper.rb +74 -0
  26. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_type_helper.rb +104 -0
  27. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_user_agent_helper.rb +40 -0
  28. metadata +171 -0
@@ -0,0 +1,25 @@
1
+ module OnlyofficeWebdriverWrapper
2
+ # Methods for working with alerts
3
+ module WebdriverAlertHelper
4
+ def alert_confirm
5
+ @driver.switch_to.alert.accept
6
+ rescue StandardError
7
+ Selenium::WebDriver::Error::NoAlertOpenError
8
+ end
9
+
10
+ # Check if alert exists
11
+ # @return [True, false]
12
+ def alert_exists?
13
+ @driver.switch_to.alert.text
14
+ true
15
+ rescue Selenium::WebDriver::Error::NoAlertOpenError, Selenium::WebDriver::Error::NoSuchAlertError
16
+ false
17
+ end
18
+
19
+ # Get alert text
20
+ # @return [String] text inside alert
21
+ def alert_text
22
+ @driver.switch_to.alert.text
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,53 @@
1
+ module OnlyofficeWebdriverWrapper
2
+ # Module with methods to work with attributes
3
+ module WebdriverAttributesHelper
4
+ def attribute_exist?(xpath_name, attribute)
5
+ exist = false
6
+
7
+ element = xpath_name.is_a?(String) ? get_element(xpath_name) : xpath_name
8
+ begin
9
+ attribute_value = element.attribute(attribute)
10
+ exist = attribute_value.empty? || attribute_value.nil? ? false : true
11
+ rescue Exception
12
+ exist = false
13
+ end
14
+ exist
15
+ end
16
+
17
+ def get_attribute(xpath_name, attribute)
18
+ element = xpath_name.is_a?(Selenium::WebDriver::Element) ? xpath_name : get_element(xpath_name)
19
+
20
+ if element.nil?
21
+ webdriver_error("Webdriver.get_attribute(#{xpath_name}, #{attribute}) failed because element not found")
22
+ else
23
+ element.attribute(attribute)
24
+ end
25
+ end
26
+
27
+ def get_element_by_parameter(elements, parameter_name, value)
28
+ elements.find { |current_element| value == get_attribute(current_element, parameter_name) }
29
+ end
30
+
31
+ def get_attribute_from_displayed_element(xpath_name, attribute)
32
+ @driver.find_elements(:xpath, xpath_name).each do |current_element|
33
+ return current_element.attribute(attribute) if current_element.displayed?
34
+ end
35
+ false
36
+ end
37
+
38
+ def get_attributes_of_several_elements(xpath_several_elements, attribute)
39
+ elements = @driver.find_elements(:xpath, xpath_several_elements)
40
+
41
+ elements.map do |element|
42
+ element.attribute(attribute)
43
+ end
44
+ end
45
+
46
+ def get_index_of_elements_with_attribute(xpath, attribute, value, only_visible = true)
47
+ get_elements(xpath, only_visible).each_with_index do |element, index|
48
+ return (index + 1) if get_attribute(element, attribute).include?(value)
49
+ end
50
+ 0
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,20 @@
1
+ module OnlyofficeWebdriverWrapper
2
+ # Module for working with browser metadata
3
+ module WebdriverBrowserInfo
4
+ # @return [Dimensions] Size of browser window
5
+ def browser_size
6
+ size_struct = @driver.manage.window.size
7
+ size = Dimensions.new(size_struct.width, size_struct.height)
8
+ OnlyofficeLoggerHelper.log("browser_size: #{size}")
9
+ size
10
+ end
11
+
12
+ # @return [String] info about platform
13
+ def browser_metadata
14
+ caps = @driver.capabilities
15
+ platform = caps[:platform_name] || caps[:platform]
16
+ version = caps[:browser_version] || caps[:version]
17
+ "Platform: #{platform}, Browser: #{caps[:browser_name]}, Version: #{version}"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ module OnlyofficeWebdriverWrapper
2
+ # Methods for working with browser console logs
3
+ module WebdriverBrowserLogHelper
4
+ def browser_logs
5
+ return [] if browser == :firefox # not implemented, see https://github.com/mozilla/geckodriver/issues/284
6
+ @driver.manage.logs.get(:browser)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module OnlyofficeWebdriverWrapper
2
+ class WebdriverSystemNotSupported < StandardError; end
3
+ end
@@ -0,0 +1,2 @@
1
+ Selenium::WebDriver::Service::START_TIMEOUT = 120
2
+ Selenium::WebDriver::Service::STOP_TIMEOUT = 120
@@ -0,0 +1,22 @@
1
+ require 'open-uri'
2
+ require 'tempfile'
3
+
4
+ module OnlyofficeWebdriverWrapper
5
+ # Some additional methods for webdriver
6
+ module WebdriverHelper
7
+ def system_screenshot(file_name)
8
+ `import -window root #{file_name}`
9
+ end
10
+
11
+ # Download temp file and return it location
12
+ # @param file [String] url
13
+ # @return [String] path to file
14
+ def download(file_url)
15
+ data = Kernel.open(file_url, &:read)
16
+ file = Tempfile.new('onlyoffice-downloaded-file')
17
+ file.write(data)
18
+ file.close
19
+ file.path
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,56 @@
1
+ module OnlyofficeWebdriverWrapper
2
+ # Methods for webdriver for calling Javascript
3
+ module WebdriverJsMethods
4
+ def execute_javascript(script)
5
+ result = @driver.execute_script(script)
6
+ OnlyofficeLoggerHelper.log("Executed js: `#{script}` with result: `#{result}`")
7
+ result
8
+ rescue Exception => e
9
+ webdriver_error("Exception #{e} in execute_javascript: #{script}")
10
+ end
11
+
12
+ def type_to_locator_by_javascript(xpath_name, text)
13
+ escaped_text = text.gsub('\\', '\\\\\\\\').gsub('"', '\\"').gsub("\n", '\\n')
14
+ execute_javascript("document.evaluate('#{xpath_name}', document, null, XPathResult.ANY_TYPE, null).iterateNext().value=\"#{escaped_text}\";")
15
+ end
16
+
17
+ def get_text_by_js(xpath)
18
+ execute_javascript("return document.evaluate(\"#{xpath.tr('"', "'")}\",document, null, XPathResult.ANY_TYPE, null ).iterateNext().textContent")
19
+ end
20
+
21
+ # Calculate object size using Javascript
22
+ # @param xpath [Sting] xpath of object
23
+ # @return [Dimensions] size of element
24
+ def element_size_by_js(xpath)
25
+ width = execute_javascript("return document.evaluate(\"#{xpath.tr('"', "'")}\",document, null, XPathResult.ANY_TYPE, null ).iterateNext().offsetWidth")
26
+ height = execute_javascript("return document.evaluate(\"#{xpath.tr('"', "'")}\",document, null, XPathResult.ANY_TYPE, null ).iterateNext().offsetHeight")
27
+ Dimensions.new(width, height)
28
+ end
29
+
30
+ # Get object absolute postion from top left edge of screen
31
+ # @param xpath [Sting] xpath of object
32
+ # @return [CursorPoint] position of element
33
+ def object_absolute_position(xpath)
34
+ left = execute_javascript("return document.evaluate(\"#{xpath.tr('"', "'")}\",document, null, XPathResult.ANY_TYPE, null ).iterateNext().getBoundingClientRect().left")
35
+ top = execute_javascript("return document.evaluate(\"#{xpath.tr('"', "'")}\",document, null, XPathResult.ANY_TYPE, null ).iterateNext().getBoundingClientRect().top")
36
+ Dimensions.new(left, top)
37
+ end
38
+
39
+ # @return [True, False] is page have jquery loaded
40
+ def jquery_loaded?
41
+ loaded = execute_javascript('return !!window.jQuery')
42
+ OnlyofficeLoggerHelper.log("jquery_loaded? # #{loaded}")
43
+ loaded
44
+ end
45
+
46
+ # Checks for jQuery finished its job or not present
47
+ def jquery_finished?
48
+ return true unless jquery_loaded?
49
+ execute_javascript('return window.jQuery.active;').zero?
50
+ end
51
+
52
+ def document_ready?
53
+ execute_javascript('return document.readyState;') == 'complete'
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,60 @@
1
+ require 'onlyoffice_s3_wrapper'
2
+ module OnlyofficeWebdriverWrapper
3
+ # Working with screenshots
4
+ module WebdriverScreenshotHelper
5
+ # @return [String] location of screenshot to take
6
+ def screenshot_folder
7
+ '/tmp/screenshot/WebdriverError'
8
+ end
9
+
10
+ def get_screenshot_and_upload(path_to_screenshot = "#{screenshot_folder}/#{StringHelper.generate_random_string}.png")
11
+ begin
12
+ get_screenshot(path_to_screenshot)
13
+ cloud_screenshot = OnlyofficeS3Wrapper::AmazonS3Wrapper.new.upload_file_and_make_public(path_to_screenshot, 'screenshots')
14
+ File.delete(path_to_screenshot) if File.exist?(path_to_screenshot)
15
+ OnlyofficeLoggerHelper.log("upload screenshot: #{cloud_screenshot}")
16
+ return cloud_screenshot
17
+ rescue Errno::ENOENT => e
18
+ begin
19
+ @driver.save_screenshot(path_to_screenshot)
20
+ OnlyofficeLoggerHelper.log("Cant upload screenshot #{path_to_screenshot}. Error: #{e}")
21
+ rescue Errno::ENOENT => e
22
+ @driver.save_screenshot("tmp/#{File.basename(path_to_screenshot)}")
23
+ OnlyofficeLoggerHelper.log("Upload screenshot to tmp/#{File.basename(path_to_screenshot)}. Error: #{e}")
24
+ end
25
+ end
26
+ path_to_screenshot
27
+ end
28
+
29
+ def get_screenshot(path_to_screenshot = "#{screenshot_folder}/#{StringHelper.generate_random_string}.png")
30
+ screenshot_folder = File.dirname(path_to_screenshot)
31
+ FileUtils.mkdir_p(screenshot_folder) unless File.directory?(screenshot_folder)
32
+ @driver.save_screenshot(path_to_screenshot)
33
+ OnlyofficeLoggerHelper.log("get_screenshot(#{path_to_screenshot})")
34
+ end
35
+
36
+ def webdriver_screenshot(screenshot_name = SecureRandom.uuid)
37
+ begin
38
+ link = get_screenshot_and_upload("#{screenshot_folder}/#{screenshot_name}.png")
39
+ rescue Exception => e
40
+ OnlyofficeLoggerHelper.log("Error in get screenshot: #{e}. Trying to get headless screenshot")
41
+ if @headless.headless_instance.nil?
42
+ system_screenshot("/tmp/#{screenshot_name}.png")
43
+ begin
44
+ link = OnlyofficeS3Wrapper::AmazonS3Wrapper.new.upload_file_and_make_public("/tmp/#{screenshot_name}.png", 'screenshots')
45
+ rescue Exception => e
46
+ OnlyofficeLoggerHelper.log("Error in get screenshot: #{e}. System screenshot #{link}")
47
+ end
48
+ else
49
+ @headless.take_screenshot("/tmp/#{screenshot_name}.png")
50
+ begin
51
+ link = OnlyofficeS3Wrapper::AmazonS3Wrapper.new.upload_file_and_make_public("/tmp/#{screenshot_name}.png", 'screenshots')
52
+ rescue Exception => e
53
+ OnlyofficeLoggerHelper.log("Error in get screenshot: #{e}. Headless screenshot #{link}")
54
+ end
55
+ end
56
+ end
57
+ "screenshot: #{link}"
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,41 @@
1
+ module OnlyofficeWebdriverWrapper
2
+ # Webdriver style helper
3
+ module WebdriverStyleHelper
4
+ def get_style_parameter(xpath, parameter_name)
5
+ get_attribute(xpath, 'style').split(';').each do |current_param|
6
+ return /:\s(.*);?$/.match(current_param)[1] if current_param.include?(parameter_name)
7
+ end
8
+ end
9
+
10
+ def get_style_attributes_of_several_elements(xpath_several_elements, style)
11
+ @driver.find_elements(:xpath, xpath_several_elements).map do |element|
12
+ el_style = element.attribute('style')
13
+ unless el_style.empty?
14
+ found_style = el_style.split(';').find { |curr_param| curr_param.include?(style) }
15
+ found_style.gsub(/\s?#{ style }:/, '') unless found_style.nil?
16
+ end
17
+ end.compact
18
+ end
19
+
20
+ def set_style_parameter(xpath, attribute, attribute_value)
21
+ execute_javascript("document.evaluate(\"#{xpath.tr('"', "'")}\",document, null, XPathResult.ANY_TYPE, null ).iterateNext()." \
22
+ "style.#{attribute}=\"#{attribute_value}\"")
23
+ end
24
+
25
+ def set_style_attribute(xpath, attribute, attribute_value)
26
+ execute_javascript("document.evaluate('#{xpath}',document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)." \
27
+ "singleNodeValue.style.#{attribute}=\"#{attribute_value}\"")
28
+ end
29
+
30
+ def set_style_show_by_xpath(xpath, move_to_center = false)
31
+ xpath.tr!("'", '"')
32
+ execute_javascript('document.evaluate( \'' + xpath.to_s +
33
+ '\' ,document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue.style.display = "block";')
34
+ return unless move_to_center
35
+ execute_javascript('document.evaluate( \'' + xpath.to_s +
36
+ '\' ,document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue.style.left = "410px";')
37
+ execute_javascript('document.evaluate( \'' + xpath.to_s +
38
+ '\' ,document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue.style.top = "260px";')
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,74 @@
1
+ module OnlyofficeWebdriverWrapper
2
+ # Module for work with tabs
3
+ module WebdriverTabHelper
4
+ TIMEOUT_WAIT_ELEMENT = 15
5
+
6
+ def new_tab
7
+ execute_javascript('window.open()')
8
+ end
9
+
10
+ def maximize
11
+ @driver.manage.window.maximize
12
+ OnlyofficeLoggerHelper.log('Maximized current window')
13
+ end
14
+
15
+ def resize_tab(width, height)
16
+ @driver.manage.window.resize_to(width, height)
17
+ OnlyofficeLoggerHelper.log("Resize current window to #{width}x#{height}")
18
+ end
19
+
20
+ def switch_to_popup
21
+ counter = 0
22
+ while tab_count < 2 && counter < 30
23
+ sleep 1
24
+ counter += 1
25
+ end
26
+ webdriver_error('switch_to_popup: Popup window not found') if counter >= 30
27
+ list_of_handlers = @driver.window_handles
28
+ last_window_handler = list_of_handlers.last
29
+ @driver.switch_to.window(last_window_handler)
30
+ end
31
+
32
+ # Get tab count
33
+ # @return [Integer] count of tabs in opened session
34
+ def tab_count
35
+ tab_count = @driver.window_handles.length
36
+ OnlyofficeLoggerHelper.log("tab_count: #{tab_count}")
37
+ tab_count
38
+ end
39
+
40
+ def choose_tab(tab_number)
41
+ counter = 0
42
+ while tab_count < 2 && counter < TIMEOUT_WAIT_ELEMENT
43
+ sleep 1
44
+ counter += 1
45
+ end
46
+ webdriver_error("choose_tab: Tab number = #{tab_number} not found") if counter >= TIMEOUT_WAIT_ELEMENT
47
+ @driver.switch_to.window(@driver.window_handles[tab_number - 1])
48
+ end
49
+
50
+ def switch_to_main_tab
51
+ @driver.switch_to.window(@driver.window_handles.first)
52
+ end
53
+
54
+ def close_tab
55
+ @driver.close
56
+ sleep 1
57
+ switch_to_main_tab
58
+ end
59
+
60
+ def close_window
61
+ @driver.close
62
+ end
63
+
64
+ def close_popup_and_switch_to_main_tab
65
+ switch_to_popup
66
+ close_tab
67
+ switch_to_main_tab
68
+ end
69
+
70
+ def get_title_of_current_tab
71
+ @driver.title
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,104 @@
1
+ module OnlyofficeWebdriverWrapper
2
+ # Class for helping with type stuff
3
+ module WebdriverTypeHelper
4
+ def type_text(element, text_to_send, clear_area = false)
5
+ element = get_element(element)
6
+ element.clear if clear_area
7
+ element.send_keys(text_to_send)
8
+ end
9
+
10
+ def type_text_and_select_it(element, text_to_send, clear_area = false)
11
+ type_text(element, text_to_send, clear_area)
12
+ text_to_send.length.times { element.send_keys %i[shift left] }
13
+ end
14
+
15
+ def type_to_locator(xpath_name, text_to_send, clear_content = true, click_on_it = false, by_action = false, by_element_send_key = false)
16
+ element = get_element(xpath_name)
17
+ if clear_content
18
+ begin
19
+ element.clear
20
+ rescue Exception => e
21
+ webdriver_error("Error in element.clear #{e} for type_to_locator(#{xpath_name}, #{text_to_send}, #{clear_content}, #{click_on_it}, #{by_action}, #{by_element_send_key})")
22
+ end
23
+ end
24
+
25
+ if click_on_it
26
+ click_on_locator(xpath_name)
27
+ sleep 0.2
28
+ end
29
+
30
+ if (@browser != :chrome && !by_action) || by_element_send_key
31
+ element.send_keys text_to_send
32
+ elsif text_to_send != ''
33
+ if text_to_send.is_a?(String)
34
+ text_to_send.split(//).each do |symbol|
35
+ @driver.action.send_keys(symbol).perform
36
+ end
37
+ else
38
+ @driver.action.send_keys(text_to_send).perform
39
+ end
40
+ end
41
+ end
42
+
43
+ def type_to_input(xpath_name, text_to_send, clear_content = false, click_on_it = true)
44
+ element = get_element(xpath_name)
45
+ webdriver_error(Selenium::WebDriver::Error::NoSuchElementError, "type_to_input(#{xpath_name}, #{text_to_send}, #{clear_content}, #{click_on_it}): element not found") if element.nil?
46
+ element.clear if clear_content
47
+ sleep 0.2
48
+ if click_on_it
49
+ begin
50
+ element.click
51
+ rescue Exception => e
52
+ webdriver_error("type_to_input(#{xpath_name}, #{text_to_send}, #{clear_content}, #{click_on_it}) error in 'element.click' error: #{e}")
53
+ end
54
+ sleep 0.2
55
+ end
56
+ element.send_keys text_to_send
57
+ end
58
+
59
+ def type_text_by_symbol(xpath_name, text_to_send, clear_content = true, click_on_it = false, by_action = false, by_element_send_key = false)
60
+ click_on_locator(xpath_name) if click_on_it
61
+ element = get_element(xpath_name)
62
+ if clear_content
63
+ element.clear
64
+ click_on_locator(xpath_name) if click_on_it
65
+ end
66
+ text_to_send.scan(/./).each do |symbol|
67
+ sleep(0.3)
68
+ if (@browser != :chrome && !by_action) || by_element_send_key
69
+ send_keys(element, symbol, :element_send_key)
70
+ else
71
+ send_keys(element, symbol, by_action)
72
+ end
73
+ end
74
+ end
75
+
76
+ def send_keys(xpath_name, text_to_send, by_action = true)
77
+ element = get_element(xpath_name)
78
+ @driver.action.click(element).perform if @browser == :firefox
79
+ if by_action
80
+ @driver.action.send_keys(element, text_to_send).perform
81
+ else
82
+ element.send_keys text_to_send
83
+ end
84
+ end
85
+
86
+ def send_keys_to_focused_elements(keys, count_of_times = 1)
87
+ command = @driver.action.send_keys(keys)
88
+ (count_of_times - 1).times { command = command.send_keys(keys) }
89
+ command.perform
90
+ end
91
+
92
+ def press_key(key)
93
+ @driver.action.send_keys(key).perform
94
+ end
95
+
96
+ def key_down(xpath, key)
97
+ @driver.action.key_down(get_element(xpath), key).perform
98
+ end
99
+
100
+ def key_up(xpath, key)
101
+ @driver.action.key_up(get_element(xpath), key).perform
102
+ end
103
+ end
104
+ end