onlyoffice_webdriver_wrapper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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