onlyoffice_webdriver_wrapper 0.6.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.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/lib/onlyoffice_webdriver_wrapper.rb +7 -0
  3. data/lib/onlyoffice_webdriver_wrapper/dimensions.rb +22 -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 +66 -0
  8. data/lib/onlyoffice_webdriver_wrapper/helpers/firefox_helper.rb +37 -0
  9. data/lib/onlyoffice_webdriver_wrapper/helpers/firefox_helper/save_to_disk_files.list +35 -0
  10. data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper.rb +86 -0
  11. data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/headless_screenshot_patch.rb +18 -0
  12. data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/headless_video_recorder.rb +36 -0
  13. data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/real_display_tools.rb +21 -0
  14. data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/ruby_helper.rb +16 -0
  15. data/lib/onlyoffice_webdriver_wrapper/helpers/os_helper.rb +11 -0
  16. data/lib/onlyoffice_webdriver_wrapper/name.rb +7 -0
  17. data/lib/onlyoffice_webdriver_wrapper/version.rb +7 -0
  18. data/lib/onlyoffice_webdriver_wrapper/webdriver.rb +424 -0
  19. data/lib/onlyoffice_webdriver_wrapper/webdriver/click_methods.rb +125 -0
  20. data/lib/onlyoffice_webdriver_wrapper/webdriver/wait_until_methods.rb +71 -0
  21. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_alert_helper.rb +25 -0
  22. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_attributes_helper.rb +63 -0
  23. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_browser_info_helper.rb +22 -0
  24. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_browser_log_helper.rb +12 -0
  25. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_exceptions.rb +5 -0
  26. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_helper.rb +37 -0
  27. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_js_methods.rb +100 -0
  28. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_screenshot_helper.rb +68 -0
  29. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_style_helper.rb +32 -0
  30. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_tab_helper.rb +70 -0
  31. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_type_helper.rb +121 -0
  32. data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_user_agent_helper.rb +51 -0
  33. metadata +278 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 01e7c8a03fdec74828c4f660d287be5729f56f29ce49b91f74005e29a666942e
4
+ data.tar.gz: bd3f969c07b3c5043b6329c07fff8e02d9576dfa373eef527af6738db1be9acd
5
+ SHA512:
6
+ metadata.gz: e5a02e944fd3b617209598f54274dcec25776695ed050576e9f7b92371de8c8bb72632ef8460c1bf0390a338f0e910f8610d590b59b449f29c08a93618440e99
7
+ data.tar.gz: dd7151ef729280ba654f37a5c4842f62b10c3d6c4b47f64df0e02e9a0d9658ad1a8c7c6c8ad4e44b2b9a87ea2a1e4092913ee290165006dd5ad00745f7bbd755
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'onlyoffice_logger_helper'
4
+ require_relative 'onlyoffice_webdriver_wrapper/helpers/headless_helper'
5
+ require_relative 'onlyoffice_webdriver_wrapper/helpers/os_helper'
6
+ require_relative 'onlyoffice_webdriver_wrapper/dimensions'
7
+ require_relative 'onlyoffice_webdriver_wrapper/webdriver'
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeWebdriverWrapper
4
+ # Class for working with cursor coordinates
5
+ class Dimensions
6
+ attr_accessor :left, :top
7
+
8
+ def initialize(left, top)
9
+ @left = left
10
+ @top = top
11
+ end
12
+
13
+ alias width left
14
+ alias height top
15
+ alias x left
16
+ alias y top
17
+
18
+ def to_s
19
+ "Dimensions(left: #{@left}, top: #{@top})"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeWebdriverWrapper
4
+ # Class for working with Chrome
5
+ module ChromeHelper
6
+ DEFAULT_CHROME_SWITCHES = %w[--kiosk-printing
7
+ --disable-popup-blocking
8
+ --disable-infobars
9
+ --no-sandbox
10
+ test-type].freeze
11
+
12
+ # @return [String] path to chromedriver
13
+ def chromedriver_path
14
+ driver_name = 'bin/chromedriver'
15
+ driver_name = 'bin/chromedriver_mac' if OSHelper.mac?
16
+ File.join(File.dirname(__FILE__), driver_name)
17
+ end
18
+
19
+ def chrome_service
20
+ @chrome_service ||= Selenium::WebDriver::Chrome::Service.new(path: chromedriver_path)
21
+ end
22
+
23
+ # @return [Webdriver::Chrome] Chrome webdriver
24
+ def start_chrome_driver
25
+ prefs = {
26
+ download: {
27
+ 'prompt_for_download' => false,
28
+ 'default_directory' => download_directory
29
+ },
30
+ profile: {
31
+ 'default_content_setting_values' => {
32
+ 'automatic_downloads' => 1
33
+ }
34
+ },
35
+ credentials_enable_service: false
36
+ }
37
+ caps = Selenium::WebDriver::Remote::Capabilities.chrome
38
+ caps[:logging_prefs] = { browser: 'ALL' }
39
+ caps[:proxy] = Selenium::WebDriver::Proxy.new(ssl: "#{@proxy.proxy_address}:#{@proxy.proxy_port}") if @proxy
40
+ switches = add_useragent_to_switches(DEFAULT_CHROME_SWITCHES)
41
+ options = Selenium::WebDriver::Chrome::Options.new(args: switches,
42
+ prefs: prefs)
43
+ webdriver_options = { options: options,
44
+ desired_capabilities: caps,
45
+ service: chrome_service }
46
+ driver = Selenium::WebDriver.for :chrome, webdriver_options
47
+ maximize_chrome(driver)
48
+ driver
49
+ end
50
+
51
+ private
52
+
53
+ # Maximize chrome
54
+ # @param driver [Selenium::WebDriver] driver to use
55
+ # @return [Void]
56
+ def maximize_chrome(driver)
57
+ if headless.running?
58
+ # Cannot use `driver.manage.window.maximize` in xvfb session
59
+ # according to https://bugs.chromium.org/p/chromedriver/issues/detail?id=1901#c16
60
+ driver.manage.window.size = Selenium::WebDriver::Dimension.new(headless.resolution_x, headless.resolution_y)
61
+ else
62
+ driver.manage.window.maximize
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeWebdriverWrapper
4
+ # Module for working with firefox
5
+ module FirefoxHelper
6
+ def firefox_service
7
+ geckodriver = File.join(File.dirname(__FILE__), 'bin/geckodriver')
8
+ @firefox_service ||= Selenium::WebDriver::Firefox::Service.new(path: geckodriver)
9
+ end
10
+
11
+ # @return [Webdriver::Firefox] firefox webdriver
12
+ def start_firefox_driver
13
+ profile = Selenium::WebDriver::Firefox::Profile.new
14
+ profile['browser.download.folderList'] = 2
15
+ profile['browser.helperApps.neverAsk.saveToDisk'] = read_firefox_files_to_save
16
+ profile['browser.download.dir'] = @download_directory
17
+ profile['browser.download.manager.showWhenStarting'] = false
18
+ profile['dom.disable_window_move_resize'] = false
19
+ options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
20
+ caps = Selenium::WebDriver::Remote::Capabilities.firefox
21
+ caps[:proxy] = Selenium::WebDriver::Proxy.new(ssl: "#{@proxy.proxy_address}:#{@proxy.proxy_port}") if @proxy
22
+ driver = Selenium::WebDriver.for :firefox, options: options, service: firefox_service, desired_capabilities: caps
23
+ driver.manage.window.size = Selenium::WebDriver::Dimension.new(headless.resolution_x, headless.resolution_y) if headless.running?
24
+ driver
25
+ end
26
+
27
+ private
28
+
29
+ # @return [Array<String>] list of formats to save
30
+ def read_firefox_files_to_save
31
+ path_to_file = "#{Dir.pwd}/lib/onlyoffice_webdriver_wrapper/"\
32
+ 'helpers/firefox_helper/save_to_disk_files.list'
33
+ OnlyofficeFileHelper::FileHelper.read_array_from_file(path_to_file)
34
+ .join(', ')
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,35 @@
1
+ application/doct
2
+ application/mspowerpoint
3
+ application/msword
4
+ application/octet-stream
5
+ application/oleobject
6
+ application/pdf
7
+ application/powerpoint
8
+ application/pptt
9
+ application/rtf
10
+ application/vnd.ms-excel
11
+ application/vnd.ms-powerpoint
12
+ application/vnd.oasis.opendocument.spreadsheet
13
+ application/vnd.oasis.opendocument.text
14
+ application/vnd.openxmlformats-officedocument.presentationml.presentation
15
+ application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
16
+ application/vnd.openxmlformats-officedocument.wordprocessingml.document
17
+ application/x-compressed
18
+ application/x-excel
19
+ application/xlst
20
+ application/x-msexcel
21
+ application/x-mspowerpoint
22
+ application/x-rtf
23
+ application/x-zip-compressed
24
+ application/zip
25
+ image/jpeg
26
+ image/pjpeg
27
+ image/pjpeg
28
+ image/x-jps
29
+ message/rfc822
30
+ multipart/x-zip
31
+ text/csv
32
+ text/html
33
+ text/html
34
+ text/plain
35
+ text/richtext
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'headless_helper/real_display_tools'
4
+ require_relative 'headless_helper/ruby_helper'
5
+ require 'headless'
6
+ require_relative 'headless_helper/headless_screenshot_patch'
7
+ require_relative 'headless_helper/headless_video_recorder'
8
+
9
+ module OnlyofficeWebdriverWrapper
10
+ # Class for using headless gem
11
+ class HeadlessHelper
12
+ include HeadlessVideoRecorder
13
+ include RealDisplayTools
14
+ include RubyHelper
15
+ # @return [Headless] instance of headless object
16
+ attr_accessor :headless_instance
17
+ # @return [Integer] x resolution of virtual screen
18
+ attr_accessor :resolution_x
19
+ # @return [Integer] y resolution of virtual screen
20
+ attr_accessor :resolution_y
21
+ # @return [True, False] is video should be recorded
22
+ attr_reader :record_video
23
+
24
+ def initialize(resolution_x = 1680,
25
+ resolution_y = 1050,
26
+ record_video: true)
27
+ @resolution_x = resolution_x
28
+ @resolution_y = resolution_y
29
+ @record_video = record_video
30
+ end
31
+
32
+ # Check if should start headless
33
+ # @return [True, False] result
34
+ def should_start?
35
+ return false if debug?
36
+ return false if OSHelper.mac?
37
+
38
+ true
39
+ end
40
+
41
+ def start
42
+ create_session = if real_display_connected?
43
+ should_start?
44
+ else
45
+ true
46
+ end
47
+ return unless create_session
48
+
49
+ OnlyofficeLoggerHelper.log('Starting Headless Session')
50
+ begin
51
+ @headless_instance = Headless.new(reuse: false,
52
+ destroy_at_exit: true,
53
+ dimensions: "#{@resolution_x + 1}x#{@resolution_y + 1}x24",
54
+ video: { provider: :ffmpeg })
55
+ rescue Exception => e
56
+ OnlyofficeLoggerHelper.log("xvfb not started with problem #{e}")
57
+ WebDriver.clean_up(true)
58
+ @headless_instance = Headless.new(reuse: false,
59
+ destroy_at_exit: true,
60
+ dimensions: "#{@resolution_x + 1}x#{@resolution_y + 1}x24",
61
+ video: { provider: :ffmpeg })
62
+ end
63
+ headless_instance.start
64
+ start_capture
65
+ end
66
+
67
+ def stop
68
+ return unless running?
69
+
70
+ OnlyofficeLoggerHelper.log('Stopping Headless Session')
71
+ stop_capture
72
+ headless_instance.destroy
73
+ end
74
+
75
+ def running?
76
+ !headless_instance.nil?
77
+ end
78
+
79
+ def take_screenshot(scr_path = '/tmp/screenshot.png')
80
+ return unless running?
81
+
82
+ headless_instance.take_screenshot(scr_path)
83
+ OnlyofficeLoggerHelper.log("Took Screenshot to file: #{scr_path}")
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,18 @@
1
+ class Headless
2
+ def take_screenshot(file_path, options={})
3
+ using = options.fetch(:using, :imagemagick)
4
+ case using
5
+ when :imagemagick
6
+ CliUtil.ensure_application_exists!('import', "imagemagick is not found on your system. Please install it using sudo apt-get install imagemagick")
7
+ system "#{CliUtil.path_to('import')} -display :#{display} -window root #{file_path}"
8
+ when :xwd
9
+ CliUtil.ensure_application_exists!('xwd', "xwd is not found on your system. Please install it using sudo apt-get install X11-apps")
10
+ system "#{CliUtil.path_to('xwd')} -display localhost:#{display} -silent -root -out #{file_path}"
11
+ when :graphicsmagick, :gm
12
+ CliUtil.ensure_application_exists!('gm', "graphicsmagick is not found on your system. Please install it.")
13
+ system "#{CliUtil.path_to('gm')} import -display localhost:#{display} -window root #{file_path}"
14
+ else
15
+ raise Headless::Exception.new('Unknown :using option value')
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeWebdriverWrapper
4
+ # Methods to record video
5
+ module HeadlessVideoRecorder
6
+ # @return [String] uniq file path to recorded file
7
+ def recorded_video_file
8
+ return @recorded_video_file if @recorded_video_file
9
+
10
+ file_pattern = 'onlyoffice_webdriver_wrapper_video_file'
11
+ temp_file = Tempfile.new([file_pattern, '.mp4'])
12
+ @recorded_video_file = temp_file.path
13
+ temp_file.unlink
14
+ @recorded_video_file
15
+ end
16
+
17
+ # @return [nil] start capture of file
18
+ def start_capture
19
+ headless_instance.video.start_capture if record_video
20
+ rescue Headless::Exception => e
21
+ OnlyofficeLoggerHelper.log("Cannot start video capture: #{e}")
22
+ @record_video = false
23
+ end
24
+
25
+ # @return [nil] stop catpure of file
26
+ def stop_capture
27
+ return unless record_video
28
+
29
+ headless_instance.video.stop_and_save(recorded_video_file)
30
+ OnlyofficeLoggerHelper.log("Video is saved to #{recorded_video_file}")
31
+ rescue Headless::Exception => e
32
+ OnlyofficeLoggerHelper.log("Saving recorded video failed: #{e}")
33
+ @record_video = false
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeWebdriverWrapper
4
+ # module for getting info about real display
5
+ module RealDisplayTools
6
+ def xrandr_result
7
+ result = `xrandr 2>&1`
8
+ OnlyofficeLoggerHelper.log("xrandr answer: #{result}".delete("\n"))
9
+ result
10
+ end
11
+
12
+ def real_display_connected?
13
+ return true if OSHelper.mac?
14
+
15
+ result = xrandr_result
16
+ exists = result.include?(' connected') && !result.include?('Failed')
17
+ OnlyofficeLoggerHelper.log("Real Display Exists: #{exists}")
18
+ exists
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeWebdriverWrapper
4
+ # Module for check ruby info
5
+ module RubyHelper
6
+ def debug?
7
+ ENV['RUBYLIB'].to_s.include?('ruby-debug')
8
+ end
9
+
10
+ # Check if current os is 64 bit
11
+ # @return [True, False] result of comparision
12
+ def os_64_bit?
13
+ RUBY_PLATFORM.include?('_64')
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeWebdriverWrapper
4
+ # Stuff for working with OS families
5
+ class OSHelper
6
+ # @return [True, False] Check if current platform is mac
7
+ def self.mac?
8
+ RUBY_PLATFORM.include?('darwin')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeWebdriverWrapper
4
+ module Name
5
+ STRING = 'onlyoffice_webdriver_wrapper'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeWebdriverWrapper
4
+ module Version
5
+ STRING = '0.6.0'
6
+ end
7
+ end
@@ -0,0 +1,424 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'onlyoffice_file_helper'
4
+ require 'page-object'
5
+ require 'securerandom'
6
+ require 'selenium-webdriver'
7
+ require 'uri'
8
+ require_relative 'helpers/chrome_helper'
9
+ require_relative 'helpers/firefox_helper'
10
+ require_relative 'webdriver/click_methods'
11
+ require_relative 'webdriver/wait_until_methods'
12
+ require_relative 'webdriver/webdriver_alert_helper'
13
+ require_relative 'webdriver/webdriver_attributes_helper'
14
+ require_relative 'webdriver/webdriver_browser_info_helper'
15
+ require_relative 'webdriver/webdriver_type_helper'
16
+ require_relative 'webdriver/webdriver_exceptions'
17
+ require_relative 'webdriver/webdriver_helper'
18
+ require_relative 'webdriver/webdriver_js_methods'
19
+ require_relative 'webdriver/webdriver_screenshot_helper'
20
+ require_relative 'webdriver/webdriver_style_helper'
21
+ require_relative 'webdriver/webdriver_tab_helper'
22
+ require_relative 'webdriver/webdriver_user_agent_helper'
23
+ require_relative 'webdriver/webdriver_browser_log_helper'
24
+
25
+ module OnlyofficeWebdriverWrapper
26
+ # noinspection RubyTooManyMethodsInspection, RubyInstanceMethodNamingConvention, RubyParameterNamingConvention
27
+ class WebDriver
28
+ include ChromeHelper
29
+ include ClickMethods
30
+ include FirefoxHelper
31
+ include RubyHelper
32
+ include WaitUntilMethods
33
+ include WebdriverAlertHelper
34
+ include WebdriverAttributesHelper
35
+ include WebdriverBrowserInfo
36
+ include WebdriverTypeHelper
37
+ include WebdriverHelper
38
+ include WebdriverJsMethods
39
+ include WebdriverScreenshotHelper
40
+ include WebdriverStyleHelper
41
+ include WebdriverTabHelper
42
+ include WebdriverUserAgentHelper
43
+ include WebdriverBrowserLogHelper
44
+ TIMEOUT_FILE_DOWNLOAD = 100
45
+ # @return [Array, String] default switches for chrome
46
+ attr_accessor :driver
47
+ # @return [Symbol] browser to use
48
+ attr_accessor :browser
49
+ # @return [True, False] is browser currently running
50
+ attr_reader :browser_running
51
+ # @return [Symbol] device of which we try to simulate, default - :desktop_linux
52
+ attr_accessor :device
53
+ # @return [String] directory to which file is downloaded
54
+ attr_accessor :download_directory
55
+ # @return [HeadlessHelper] headless wrapper
56
+ attr_accessor :headless
57
+ # @return [Net::HTTP::Proxy] connection proxy
58
+ attr_accessor :proxy
59
+
60
+ def initialize(browser = :firefox,
61
+ _remote_server = nil,
62
+ device: :desktop_linux,
63
+ proxy: nil)
64
+ raise WebdriverSystemNotSupported, 'Your OS is not 64 bit. It is not supported' unless os_64_bit?
65
+
66
+ @device = device
67
+ @headless = HeadlessHelper.new
68
+ @headless.start
69
+
70
+ @download_directory = Dir.mktmpdir('webdriver-download')
71
+ @browser = browser
72
+ @proxy = proxy
73
+ case browser
74
+ when :firefox
75
+ @driver = start_firefox_driver
76
+ when :chrome
77
+ @driver = start_chrome_driver
78
+ else
79
+ raise("Unknown Browser: #{browser}")
80
+ end
81
+ @browser_running = true
82
+ end
83
+
84
+ def open(url)
85
+ url = "http://#{url}" unless url.include?('http') || url.include?('file://')
86
+ loop do
87
+ @driver.navigate.to url
88
+ break
89
+ rescue Timeout::Error
90
+ @driver.navigate.refresh
91
+ end
92
+ sleep(1) # Correct wait for Page to init focus
93
+ OnlyofficeLoggerHelper.log("Opened page: #{url}")
94
+ end
95
+
96
+ def quit
97
+ return unless browser_running
98
+
99
+ begin
100
+ @driver.execute_script('window.onbeforeunload = null') # off popup window
101
+ rescue StandardError
102
+ Exception
103
+ end
104
+ begin
105
+ @driver.quit
106
+ rescue Exception => e
107
+ OnlyofficeLoggerHelper.log("Some error happened on webdriver.quit #{e.backtrace}")
108
+ end
109
+ alert_confirm
110
+ @headless.stop
111
+ cleanup_download_folder
112
+ @browser_running = false
113
+ end
114
+
115
+ def get_element(object_identification)
116
+ return object_identification unless object_identification.is_a?(String)
117
+
118
+ @driver.find_element(:xpath, object_identification)
119
+ rescue StandardError
120
+ nil
121
+ end
122
+
123
+ # Get text from all elements with specified xpath
124
+ # @param array_elements [String] xpath of elements
125
+ # @return [Array<String>] values of elements
126
+ def get_text_array(array_elements)
127
+ get_elements(array_elements).map { |current_element| get_text(current_element) }
128
+ end
129
+
130
+ def select_from_list_elements(value, elements_value)
131
+ index = get_element_index(value, elements_value)
132
+ elements_value[index].click
133
+ end
134
+
135
+ def get_element_index(title, list_elements)
136
+ list_elements.each_with_index do |current, i|
137
+ return i if get_text(current) == title
138
+ end
139
+ nil
140
+ end
141
+
142
+ def get_all_combo_box_values(xpath_name)
143
+ @driver.find_element(:xpath, xpath_name).find_elements(tag_name: 'option').map { |el| el.attribute('value') }
144
+ end
145
+
146
+ # @return [String] url of current frame, or browser url if
147
+ # it is a root frame
148
+ def get_url
149
+ execute_javascript('return window.location.href')
150
+ rescue Selenium::WebDriver::Error::NoSuchDriverError
151
+ raise 'Browser is crushed or hangup'
152
+ end
153
+
154
+ def refresh
155
+ @driver.navigate.refresh
156
+ OnlyofficeLoggerHelper.log('Refresh page')
157
+ end
158
+
159
+ def go_back
160
+ @driver.navigate.back
161
+ OnlyofficeLoggerHelper.log('Go back to previous page')
162
+ end
163
+
164
+ # Perform drag'n'drop action in one element (for example on big canvas area)
165
+ # for drag'n'drop one whole element use 'drag_and_drop_by'
166
+ # ==== Attributes
167
+ #
168
+ # * +xpath+ - xpath of element on which drag and drop performed
169
+ # * +x1+ - x coordinate on element to start drag'n'drop
170
+ # * +y1+ - y coordinate on element to start drag'n'drop
171
+ # * +x2+ - shift vector x coordinate
172
+ # * +y2+ - shift vector y coordinate
173
+ # * +mouse_release+ - release mouse after move
174
+ def drag_and_drop(xpath, x1, y1, x2, y2, mouse_release: true)
175
+ canvas = get_element(xpath)
176
+
177
+ move_action = @driver.action
178
+ .move_to(canvas, x1.to_i, y1.to_i)
179
+ .click_and_hold
180
+ .move_by(x2, y2)
181
+ move_action = move_action.release if mouse_release
182
+
183
+ move_action.perform
184
+ end
185
+
186
+ # Perform drag'n'drop one whole element
187
+ # for drag'n'drop inside one element (f.e. canvas) use drag_and_drop
188
+ # ==== Attributes
189
+ #
190
+ # * +source+ - xpath of element on which drag and drop performed
191
+ # * +right_by+ - shift vector x coordinate
192
+ # * +down_by+ - shift vector y coordinate
193
+ def drag_and_drop_by(source, right_by, down_by = 0)
194
+ @driver.action.drag_and_drop_by(get_element(source), right_by, down_by).perform
195
+ end
196
+
197
+ def scroll_list_to_element(list_xpath, element_xpath)
198
+ execute_javascript("$(document.evaluate(\"#{list_xpath}\", document, null, XPathResult.ANY_TYPE, null).
199
+ iterateNext()).jScrollPane().data('jsp').scrollToElement(document.evaluate(\"#{element_xpath}\",
200
+ document, null, XPathResult.ANY_TYPE, null).iterateNext());")
201
+ end
202
+
203
+ def scroll_list_by_pixels(list_xpath, pixels)
204
+ execute_javascript("$(document.evaluate(\"#{list_xpath.tr('"', "'")}\", document, null, XPathResult.ANY_TYPE, null).iterateNext()).scrollTop(#{pixels})")
205
+ end
206
+
207
+ # Open dropdown selector, like 'Color Selector', which has no element id
208
+ # @param [String] xpath_name name of dropdown list
209
+ def open_dropdown_selector(xpath_name, horizontal_shift = 30, vertical_shift = 0)
210
+ element = get_element(xpath_name)
211
+ if @browser == :firefox || @browser == :safari
212
+ set_style_attribute("#{xpath_name}/button", 'display', 'none')
213
+ set_style_attribute(xpath_name, 'display', 'inline')
214
+ element.click
215
+ set_style_attribute("#{xpath_name}/button", 'display', 'inline-block')
216
+ set_style_attribute(xpath_name, 'display', 'block')
217
+ else
218
+ @driver.action.move_to(element, horizontal_shift, vertical_shift).click.perform
219
+ end
220
+ end
221
+
222
+ def action_on_locator_coordinates(xpath_name, right_by, down_by, action = :click, times = 1)
223
+ wait_until_element_visible(xpath_name)
224
+ element = @driver.find_element(:xpath, xpath_name)
225
+ (0...times).inject(@driver.action.move_to(element, right_by.to_i, down_by.to_i)) { |acc, _elem| acc.send(action) }.perform
226
+ end
227
+
228
+ def move_to_element(element)
229
+ element = get_element(element) if element.is_a?(String)
230
+ @driver.action.move_to(element).perform
231
+ end
232
+
233
+ def move_to_element_by_locator(xpath_name)
234
+ element = get_element(xpath_name)
235
+ @driver.action.move_to(element).perform
236
+ OnlyofficeLoggerHelper.log("Moved mouse to element: #{xpath_name}")
237
+ end
238
+
239
+ def mouse_over(xpath_name, x_coordinate = 0, y_coordinate = 0)
240
+ wait_until_element_present(xpath_name)
241
+ @driver.action.move_to(@driver.find_element(:xpath, xpath_name), x_coordinate.to_i, y_coordinate.to_i).perform
242
+ end
243
+
244
+ def element_present?(xpath_name)
245
+ case xpath_name
246
+ when PageObject::Elements::Element
247
+ xpath_name.present?
248
+ when Selenium::WebDriver::Element
249
+ xpath_name.displayed?
250
+ else
251
+ @driver.find_element(:xpath, xpath_name)
252
+ true
253
+ end
254
+ rescue Exception
255
+ false
256
+ end
257
+
258
+ def get_element_by_display(xpath_name)
259
+ @driver.find_elements(:xpath, xpath_name).each do |element|
260
+ return element if element.displayed?
261
+ end
262
+ rescue Selenium::WebDriver::Error::InvalidSelectorError
263
+ webdriver_error("get_element_by_display(#{xpath_name}): invalid selector: Unable to locate an element with the xpath expression")
264
+ end
265
+
266
+ # Return count of elements (visible and not visible)
267
+ # @param xpath_name [String] xpath to find
268
+ # @param only_visible [True, False] count only visible elements?
269
+ # @return [Integer] element count
270
+ def get_element_count(xpath_name, only_visible = true)
271
+ if element_present?(xpath_name)
272
+ elements = @driver.find_elements(:xpath, xpath_name)
273
+ only_visible ? elements.delete_if { |element| !element.displayed? }.length : elements.length
274
+ else
275
+ 0
276
+ end
277
+ end
278
+
279
+ def get_elements(objects_identification, only_visible = true)
280
+ return objects_identification if objects_identification.is_a?(Array)
281
+
282
+ elements = @driver.find_elements(:xpath, objects_identification)
283
+ if only_visible
284
+ elements.each do |current|
285
+ elements.delete(current) unless @browser == :firefox || current.displayed?
286
+ end
287
+ end
288
+ elements
289
+ end
290
+
291
+ def element_visible?(xpath_name)
292
+ if xpath_name.is_a?(PageObject::Elements::Element) # PageObject always visible
293
+ true
294
+ elsif element_present?(xpath_name)
295
+ element = get_element(xpath_name)
296
+ return false if element.nil?
297
+
298
+ begin
299
+ visible = element.displayed?
300
+ rescue Exception
301
+ visible = false
302
+ end
303
+ visible
304
+ else
305
+ false
306
+ end
307
+ end
308
+
309
+ # Check if any element of xpath is displayed
310
+ # @param xpath_several_elements [String] xpath to check
311
+ # @return [True, False] result of visibility
312
+ def one_of_several_elements_displayed?(xpath_several_elements)
313
+ @driver.find_elements(:xpath, xpath_several_elements).each do |current_element|
314
+ return true if current_element.displayed?
315
+ end
316
+ false
317
+ rescue Exception => e
318
+ webdriver_error("Raise unkwnown exception: #{e}")
319
+ end
320
+
321
+ def wait_element(xpath_name, period_of_wait = 1, critical_time = 3)
322
+ wait_until_element_present(xpath_name)
323
+ time = 0
324
+ until element_visible?(xpath_name)
325
+ sleep(period_of_wait)
326
+ time += 1
327
+ return if time == critical_time
328
+ end
329
+ end
330
+
331
+ # Select frame as current
332
+ # @param [String] xpath_name name of current xpath
333
+ def select_frame(xpath_name = '//iframe', count_of_frames = 1)
334
+ (0...count_of_frames).each do
335
+ frame = @driver.find_element(:xpath, xpath_name)
336
+ @driver.switch_to.frame frame
337
+ rescue Selenium::WebDriver::Error::NoSuchElementError
338
+ OnlyofficeLoggerHelper.log('Raise NoSuchElementError in the select_frame method')
339
+ rescue Exception => e
340
+ webdriver_error("Raise unkwnown exception: #{e}")
341
+ end
342
+ end
343
+
344
+ # Select top frame of browser (even if several subframes exists)
345
+ def select_top_frame
346
+ @driver.switch_to.default_content
347
+ rescue Timeout::Error
348
+ OnlyofficeLoggerHelper.log('Raise TimeoutError in the select_top_frame method')
349
+ rescue Exception => e
350
+ raise "Browser is crushed or hangup with error: #{e}"
351
+ end
352
+
353
+ # Get text of current element
354
+ # @param [String] xpath_name name of xpath
355
+ # @param [true, false] wait_until_visible wait until element visible [@default = true]
356
+ def get_text(xpath_name, wait_until_visible = true)
357
+ wait_until_element_visible(xpath_name) if wait_until_visible
358
+
359
+ element = get_element(xpath_name)
360
+ webdriver_error("get_text(#{xpath_name}, #{wait_until_visible}) not found element by xpath") if element.nil?
361
+ if element.tag_name == 'input' || element.tag_name == 'textarea'
362
+ element.attribute('value')
363
+ else
364
+ element.text
365
+ end
366
+ end
367
+
368
+ def get_text_of_several_elements(xpath_several_elements)
369
+ @driver.find_elements(:xpath, xpath_several_elements).map { |element| element.text unless element.text == '' }.compact
370
+ end
371
+
372
+ def select_combo_box(xpath_name, select_value, select_by = :value)
373
+ wait_until_element_visible(xpath_name)
374
+ option = Selenium::WebDriver::Support::Select.new(get_element(xpath_name))
375
+ begin
376
+ option.select_by(select_by, select_value)
377
+ rescue StandardError
378
+ option.select_by(:text, select_value)
379
+ end
380
+ end
381
+
382
+ # Get page source
383
+ # @return [String] all page source
384
+ def get_page_source
385
+ @driver.execute_script('return document.documentElement.innerHTML;')
386
+ end
387
+
388
+ def webdriver_error(exception, error_message = nil)
389
+ if exception.is_a?(String) # If there is no error_message
390
+ error_message = exception
391
+ exception = RuntimeError
392
+ end
393
+ select_top_frame
394
+ current_url = get_url
395
+ raise exception, "#{error_message}\n\nPage address: #{current_url}\n\nError #{webdriver_screenshot}"
396
+ end
397
+
398
+ def wait_file_for_download(file_name, timeout = TIMEOUT_FILE_DOWNLOAD)
399
+ full_file_name = "#{@download_directory}/#{file_name}"
400
+ full_file_name = file_name if file_name[0] == '/'
401
+ counter = 0
402
+ while !File.exist?(full_file_name) && counter < timeout
403
+ OnlyofficeLoggerHelper.log("Waiting for download file #{full_file_name} for #{counter} of #{timeout}")
404
+ sleep 1
405
+ counter += 1
406
+ end
407
+ webdriver_error("File #{full_file_name} not download for #{timeout} seconds") if counter >= timeout
408
+ full_file_name
409
+ end
410
+
411
+ # Perform cleanup if something went wrong during tests
412
+ # @param forced [True, False] should cleanup run in all cases
413
+ def self.clean_up(forced = false)
414
+ return unless OnlyofficeFileHelper::LinuxHelper.user_name.include?('nct-at') ||
415
+ OnlyofficeFileHelper::LinuxHelper.user_name.include?('ubuntu') ||
416
+ forced == true
417
+
418
+ OnlyofficeFileHelper::LinuxHelper.kill_all('chromedriver')
419
+ OnlyofficeFileHelper::LinuxHelper.kill_all('geckodriver')
420
+ OnlyofficeFileHelper::LinuxHelper.kill_all('Xvfb')
421
+ OnlyofficeFileHelper::LinuxHelper.kill_all_browsers
422
+ end
423
+ end
424
+ end