onlyoffice_webdriver_wrapper 0.1.2 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/onlyoffice_webdriver_wrapper/helpers/bin/chromedriver +0 -0
- data/lib/onlyoffice_webdriver_wrapper/helpers/bin/chromedriver_mac +0 -0
- data/lib/onlyoffice_webdriver_wrapper/helpers/chrome_helper.rb +13 -29
- data/lib/onlyoffice_webdriver_wrapper/helpers/firefox_helper.rb +14 -9
- data/lib/onlyoffice_webdriver_wrapper/helpers/firefox_helper/save_to_disk_files.list +35 -0
- data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper.rb +2 -1
- data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/headless_screenshot_patch.rb +18 -0
- data/lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/real_display_tools.rb +1 -5
- data/lib/onlyoffice_webdriver_wrapper/name.rb +7 -0
- data/lib/onlyoffice_webdriver_wrapper/version.rb +1 -1
- data/lib/onlyoffice_webdriver_wrapper/webdriver.rb +34 -303
- data/lib/onlyoffice_webdriver_wrapper/webdriver/click_methods.rb +125 -0
- data/lib/onlyoffice_webdriver_wrapper/webdriver/wait_until_methods.rb +71 -0
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_attributes_helper.rb +0 -7
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_helper.rb +14 -1
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_js_methods.rb +26 -8
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_style_helper.rb +2 -11
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_tab_helper.rb +0 -9
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_type_helper.rb +36 -4
- data/lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_user_agent_helper.rb +12 -4
- metadata +35 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f98ac75fa3bf47f7ada257812f98097c9dc65d183ca4f6da5d5b42b2c410d84d
|
4
|
+
data.tar.gz: 3cbcf38f96e27e4f8f9a71a08961b83a450c3d3da11fe970417e6ddc81bb6a07
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64f12991857161f2234fa7f0b3d22b1da3fdb7c0b8af45fb6a8554cc53fea1a9278635429a2fc3ea8395f64bd58a785c65ce9ea9677e5b9881c7c040cc9ffd6c
|
7
|
+
data.tar.gz: 6dc715859f6b85af142b13fa96d54ab0ca13bd221116076ad3a79eeeb599d2bb6a2c6bac613c4c4097b7f678a2f0441528a8c76532efe6ceb4a55fb006e048c1
|
Binary file
|
Binary file
|
@@ -24,12 +24,12 @@ module OnlyofficeWebdriverWrapper
|
|
24
24
|
def start_chrome_driver
|
25
25
|
prefs = {
|
26
26
|
download: {
|
27
|
-
prompt_for_download
|
28
|
-
default_directory
|
27
|
+
'prompt_for_download' => false,
|
28
|
+
'default_directory' => download_directory
|
29
29
|
},
|
30
30
|
profile: {
|
31
|
-
default_content_setting_values
|
32
|
-
'automatic_downloads'
|
31
|
+
'default_content_setting_values' => {
|
32
|
+
'automatic_downloads' => 1
|
33
33
|
}
|
34
34
|
},
|
35
35
|
credentials_enable_service: false
|
@@ -38,31 +38,15 @@ module OnlyofficeWebdriverWrapper
|
|
38
38
|
caps[:logging_prefs] = { browser: 'ALL' }
|
39
39
|
caps[:proxy] = Selenium::WebDriver::Proxy.new(ssl: "#{@proxy.proxy_address}:#{@proxy.proxy_port}") if @proxy
|
40
40
|
caps['chromeOptions'] = { w3c: false }
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
rescue Selenium::WebDriver::Error::WebDriverError,
|
51
|
-
Net::ReadTimeout,
|
52
|
-
Errno::ECONNREFUSED => e
|
53
|
-
OnlyofficeLoggerHelper.log("Starting chrome failed with error: #{e.backtrace}")
|
54
|
-
sleep 10
|
55
|
-
driver = Selenium::WebDriver.for :chrome, webdriver_options
|
56
|
-
end
|
57
|
-
maximize_chrome(driver)
|
58
|
-
driver
|
59
|
-
else
|
60
|
-
caps['chromeOptions'] = {
|
61
|
-
profile: data['zip'],
|
62
|
-
extensions: data['extensions']
|
63
|
-
}
|
64
|
-
Selenium::WebDriver.for(:remote, url: 'http://' + remote_server + ':4444/wd/hub', desired_capabilities: caps)
|
65
|
-
end
|
41
|
+
switches = add_useragent_to_switches(DEFAULT_CHROME_SWITCHES)
|
42
|
+
options = Selenium::WebDriver::Chrome::Options.new(args: switches,
|
43
|
+
prefs: prefs)
|
44
|
+
webdriver_options = { options: options,
|
45
|
+
desired_capabilities: caps,
|
46
|
+
service: chrome_service }
|
47
|
+
driver = Selenium::WebDriver.for :chrome, webdriver_options
|
48
|
+
maximize_chrome(driver)
|
49
|
+
driver
|
66
50
|
end
|
67
51
|
|
68
52
|
private
|
@@ -12,21 +12,26 @@ module OnlyofficeWebdriverWrapper
|
|
12
12
|
def start_firefox_driver
|
13
13
|
profile = Selenium::WebDriver::Firefox::Profile.new
|
14
14
|
profile['browser.download.folderList'] = 2
|
15
|
-
profile['browser.helperApps.neverAsk.saveToDisk'] =
|
15
|
+
profile['browser.helperApps.neverAsk.saveToDisk'] = read_firefox_files_to_save
|
16
16
|
profile['browser.download.dir'] = @download_directory
|
17
17
|
profile['browser.download.manager.showWhenStarting'] = false
|
18
18
|
profile['dom.disable_window_move_resize'] = false
|
19
19
|
options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
|
20
20
|
caps = Selenium::WebDriver::Remote::Capabilities.firefox
|
21
21
|
caps[:proxy] = Selenium::WebDriver::Proxy.new(ssl: "#{@proxy.proxy_address}:#{@proxy.proxy_port}") if @proxy
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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(', ')
|
30
35
|
end
|
31
36
|
end
|
32
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
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require_relative 'headless_helper/real_display_tools'
|
4
4
|
require_relative 'headless_helper/ruby_helper'
|
5
5
|
require 'headless'
|
6
|
+
require_relative 'headless_helper/headless_screenshot_patch'
|
6
7
|
|
7
8
|
module OnlyofficeWebdriverWrapper
|
8
9
|
# Class for using headless gem
|
@@ -42,7 +43,7 @@ module OnlyofficeWebdriverWrapper
|
|
42
43
|
dimensions: "#{@resolution_x + 1}x#{@resolution_y + 1}x24")
|
43
44
|
rescue Exception => e
|
44
45
|
OnlyofficeLoggerHelper.log("xvfb not started with problem #{e}")
|
45
|
-
|
46
|
+
WebDriver.clean_up(true)
|
46
47
|
@headless_instance = Headless.new(reuse: false,
|
47
48
|
destroy_at_exit: true,
|
48
49
|
dimensions: "#{@resolution_x + 1}x#{@resolution_y + 1}x24")
|
@@ -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
|
@@ -4,11 +4,7 @@ module OnlyofficeWebdriverWrapper
|
|
4
4
|
# module for getting info about real display
|
5
5
|
module RealDisplayTools
|
6
6
|
def xrandr_result
|
7
|
-
|
8
|
-
result = `xrandr 2>&1`
|
9
|
-
rescue Exception
|
10
|
-
result = 'xrandr throw an exception'
|
11
|
-
end
|
7
|
+
result = `xrandr 2>&1`
|
12
8
|
OnlyofficeLoggerHelper.log("xrandr answer: #{result}".delete("\n"))
|
13
9
|
result
|
14
10
|
end
|
@@ -7,6 +7,8 @@ require 'selenium-webdriver'
|
|
7
7
|
require 'uri'
|
8
8
|
require_relative 'helpers/chrome_helper'
|
9
9
|
require_relative 'helpers/firefox_helper'
|
10
|
+
require_relative 'webdriver/click_methods'
|
11
|
+
require_relative 'webdriver/wait_until_methods'
|
10
12
|
require_relative 'webdriver/webdriver_alert_helper'
|
11
13
|
require_relative 'webdriver/webdriver_attributes_helper'
|
12
14
|
require_relative 'webdriver/webdriver_browser_info_helper'
|
@@ -24,8 +26,10 @@ module OnlyofficeWebdriverWrapper
|
|
24
26
|
# noinspection RubyTooManyMethodsInspection, RubyInstanceMethodNamingConvention, RubyParameterNamingConvention
|
25
27
|
class WebDriver
|
26
28
|
include ChromeHelper
|
29
|
+
include ClickMethods
|
27
30
|
include FirefoxHelper
|
28
31
|
include RubyHelper
|
32
|
+
include WaitUntilMethods
|
29
33
|
include WebdriverAlertHelper
|
30
34
|
include WebdriverAttributesHelper
|
31
35
|
include WebdriverBrowserInfo
|
@@ -37,7 +41,6 @@ module OnlyofficeWebdriverWrapper
|
|
37
41
|
include WebdriverTabHelper
|
38
42
|
include WebdriverUserAgentHelper
|
39
43
|
include WebdriverBrowserLogHelper
|
40
|
-
TIMEOUT_WAIT_ELEMENT = 15
|
41
44
|
TIMEOUT_FILE_DOWNLOAD = 100
|
42
45
|
# @return [Array, String] default switches for chrome
|
43
46
|
attr_accessor :driver
|
@@ -46,17 +49,14 @@ module OnlyofficeWebdriverWrapper
|
|
46
49
|
attr_reader :browser_running
|
47
50
|
# @return [Symbol] device of which we try to simulate, default - :desktop_linux
|
48
51
|
attr_accessor :device
|
49
|
-
attr_accessor :ip_of_remote_server
|
50
52
|
attr_accessor :download_directory
|
51
53
|
attr_accessor :server_address
|
52
54
|
attr_accessor :headless
|
53
55
|
# @return [Net::HTTP::Proxy] connection proxy
|
54
56
|
attr_accessor :proxy
|
55
57
|
|
56
|
-
singleton_class.class_eval { attr_accessor :web_console_error }
|
57
|
-
|
58
58
|
def initialize(browser = :firefox,
|
59
|
-
|
59
|
+
_remote_server = nil,
|
60
60
|
device: :desktop_linux,
|
61
61
|
proxy: nil)
|
62
62
|
raise WebdriverSystemNotSupported, 'Your OS is not 64 bit. It is not supported' unless os_64_bit?
|
@@ -67,7 +67,6 @@ module OnlyofficeWebdriverWrapper
|
|
67
67
|
|
68
68
|
@download_directory = Dir.mktmpdir('webdriver-download')
|
69
69
|
@browser = browser
|
70
|
-
@ip_of_remote_server = remote_server
|
71
70
|
@proxy = proxy
|
72
71
|
case browser
|
73
72
|
when :firefox
|
@@ -80,10 +79,6 @@ module OnlyofficeWebdriverWrapper
|
|
80
79
|
@browser_running = true
|
81
80
|
end
|
82
81
|
|
83
|
-
def add_web_console_error(log)
|
84
|
-
WebDriver.web_console_error = log
|
85
|
-
end
|
86
|
-
|
87
82
|
def open(url)
|
88
83
|
url = 'http://' + url unless url.include?('http') || url.include?('file://')
|
89
84
|
loop do
|
@@ -112,7 +107,7 @@ module OnlyofficeWebdriverWrapper
|
|
112
107
|
end
|
113
108
|
alert_confirm
|
114
109
|
@headless.stop
|
115
|
-
|
110
|
+
cleanup_download_folder
|
116
111
|
@browser_running = false
|
117
112
|
end
|
118
113
|
|
@@ -124,40 +119,13 @@ module OnlyofficeWebdriverWrapper
|
|
124
119
|
nil
|
125
120
|
end
|
126
121
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
end
|
131
|
-
|
122
|
+
# Get text from all elements with specified xpath
|
123
|
+
# @param array_elements [String] xpath of elements
|
124
|
+
# @return [Array<String>] values of elements
|
132
125
|
def get_text_array(array_elements)
|
133
126
|
get_elements(array_elements).map { |current_element| get_text(current_element) }
|
134
127
|
end
|
135
128
|
|
136
|
-
def click(element)
|
137
|
-
element.click
|
138
|
-
end
|
139
|
-
|
140
|
-
def click_and_wait(element_to_click, element_to_wait)
|
141
|
-
element_to_click.click
|
142
|
-
count = 0
|
143
|
-
while !element_to_wait.present? && count < 30
|
144
|
-
sleep 1
|
145
|
-
count += 1
|
146
|
-
end
|
147
|
-
webdriver_error("click_and_wait: Wait for element: #{element_to_click} for 30 seconds") if count == 30
|
148
|
-
end
|
149
|
-
|
150
|
-
def select_from_list(xpath_value, value)
|
151
|
-
@driver.find_element(:xpath, xpath_value).find_elements(tag_name: 'li').each do |element|
|
152
|
-
next unless element.text == value.to_s
|
153
|
-
|
154
|
-
element.click
|
155
|
-
return true
|
156
|
-
end
|
157
|
-
|
158
|
-
webdriver_error("select_from_list: Option #{value} in list #{xpath_value} not found")
|
159
|
-
end
|
160
|
-
|
161
129
|
def select_from_list_elements(value, elements_value)
|
162
130
|
index = get_element_index(value, elements_value)
|
163
131
|
elements_value[index].click
|
@@ -206,11 +174,11 @@ module OnlyofficeWebdriverWrapper
|
|
206
174
|
end
|
207
175
|
|
208
176
|
def remove_class_by_jquery(selector, class_name)
|
209
|
-
execute_javascript("#{
|
177
|
+
execute_javascript("$(#{dom_element_by_xpath(selector)}).removeClass('#{class_name}');")
|
210
178
|
end
|
211
179
|
|
212
180
|
def add_class_by_jquery(selector, class_name)
|
213
|
-
execute_javascript("#{
|
181
|
+
execute_javascript("$(#{dom_element_by_xpath(selector)}).addClass('#{class_name}');")
|
214
182
|
end
|
215
183
|
|
216
184
|
# Perform drag'n'drop action in one element (for example on big canvas area)
|
@@ -271,172 +239,12 @@ module OnlyofficeWebdriverWrapper
|
|
271
239
|
end
|
272
240
|
end
|
273
241
|
|
274
|
-
# Click on locator
|
275
|
-
# @param count [Integer] count of clicks
|
276
|
-
def click_on_locator(xpath_name, by_javascript = false, count: 1)
|
277
|
-
element = get_element(xpath_name)
|
278
|
-
return webdriver_error("Element with xpath: #{xpath_name} not found") if element.nil?
|
279
|
-
|
280
|
-
if by_javascript
|
281
|
-
execute_javascript("document.evaluate(\"#{xpath_name}\", document, null, XPathResult.ANY_TYPE, null).iterateNext().click();")
|
282
|
-
else
|
283
|
-
begin
|
284
|
-
count.times { element.click }
|
285
|
-
rescue Selenium::WebDriver::Error::ElementNotVisibleError
|
286
|
-
webdriver_error("Selenium::WebDriver::Error::ElementNotVisibleError: element not visible for xpath: #{xpath_name}")
|
287
|
-
rescue Exception => e
|
288
|
-
webdriver_error(e.class, "UnknownError #{e.message} #{xpath_name}")
|
289
|
-
end
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
def left_mouse_click(xpath, x_coord, y_coord)
|
294
|
-
@driver.action.move_to(get_element(xpath), x_coord.to_i, y_coord.to_i).click.perform
|
295
|
-
end
|
296
|
-
|
297
|
-
# Context click on locator
|
298
|
-
# @param [String] xpath_name name of xpath to click
|
299
|
-
def context_click_on_locator(xpath_name)
|
300
|
-
wait_until_element_visible(xpath_name)
|
301
|
-
|
302
|
-
element = @driver.find_element(:xpath, xpath_name)
|
303
|
-
@driver.action.context_click(element).perform
|
304
|
-
end
|
305
|
-
|
306
|
-
def right_click(xpath_name)
|
307
|
-
@driver.action.context_click(@driver.find_element(:xpath, xpath_name)).perform
|
308
|
-
end
|
309
|
-
|
310
|
-
def context_click(xpath, x_coord, y_coord)
|
311
|
-
element = get_element(xpath)
|
312
|
-
if browser == :firefox
|
313
|
-
element.send_keys %i[shift f10]
|
314
|
-
else
|
315
|
-
@driver.action.move_to(element, x_coord.to_i, y_coord.to_i).context_click.perform
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
def click_on_displayed(xpath_name)
|
320
|
-
element = get_element_by_display(xpath_name)
|
321
|
-
begin
|
322
|
-
element.is_a?(Array) ? element.first.click : element.click
|
323
|
-
rescue Exception => e
|
324
|
-
webdriver_error("Exception #{e} in click_on_displayed(#{xpath_name})")
|
325
|
-
end
|
326
|
-
end
|
327
|
-
|
328
|
-
def click_on_locator_by_action(xpath)
|
329
|
-
@driver.action.move_to(get_element(xpath)).click.perform
|
330
|
-
end
|
331
|
-
|
332
|
-
def click_on_locator_coordinates(xpath_name, right_by, down_by)
|
333
|
-
wait_until_element_visible(xpath_name)
|
334
|
-
element = @driver.find_element(:xpath, xpath_name)
|
335
|
-
@driver.action.move_to(element, right_by.to_i, down_by.to_i).perform
|
336
|
-
@driver.action.move_to(element, right_by.to_i, down_by.to_i).click.perform
|
337
|
-
end
|
338
|
-
|
339
|
-
def right_click_on_locator_coordinates(xpath_name, right_by = nil, down_by = nil)
|
340
|
-
wait_until_element_visible(xpath_name)
|
341
|
-
element = @driver.find_element(:xpath, xpath_name)
|
342
|
-
@driver.action.move_to(element, right_by.to_i, down_by.to_i).perform
|
343
|
-
@driver.action.move_to(element, right_by.to_i, down_by.to_i).context_click.perform
|
344
|
-
end
|
345
|
-
|
346
|
-
def double_click(xpath_name)
|
347
|
-
wait_until_element_visible(xpath_name)
|
348
|
-
@driver.action.move_to(@driver.find_element(:xpath, xpath_name)).double_click.perform
|
349
|
-
end
|
350
|
-
|
351
|
-
def double_click_on_locator_coordinates(xpath_name, right_by, down_by)
|
352
|
-
wait_until_element_visible(xpath_name)
|
353
|
-
@driver.action.move_to(@driver.find_element(:xpath, xpath_name), right_by.to_i, down_by.to_i).double_click.perform
|
354
|
-
end
|
355
|
-
|
356
242
|
def action_on_locator_coordinates(xpath_name, right_by, down_by, action = :click, times = 1)
|
357
243
|
wait_until_element_visible(xpath_name)
|
358
244
|
element = @driver.find_element(:xpath, xpath_name)
|
359
245
|
(0...times).inject(@driver.action.move_to(element, right_by.to_i, down_by.to_i)) { |acc, _elem| acc.send(action) }.perform
|
360
246
|
end
|
361
247
|
|
362
|
-
def click_on_one_of_several_by_text(xpath_several_elements, text_to_click)
|
363
|
-
@driver.find_elements(:xpath, xpath_several_elements).each do |current_element|
|
364
|
-
next unless text_to_click.to_s == current_element.attribute('innerHTML')
|
365
|
-
|
366
|
-
begin
|
367
|
-
current_element.click
|
368
|
-
rescue Exception => e
|
369
|
-
webdriver_error("Error in click_on_one_of_several_by_text(#{xpath_several_elements}, #{text_to_click}): #{e.message}")
|
370
|
-
end
|
371
|
-
return true
|
372
|
-
end
|
373
|
-
false
|
374
|
-
end
|
375
|
-
|
376
|
-
def click_on_one_of_several_by_display(xpath_several_elements)
|
377
|
-
@driver.find_elements(:xpath, xpath_several_elements).each do |current_element|
|
378
|
-
if current_element.displayed?
|
379
|
-
current_element.click
|
380
|
-
return true
|
381
|
-
end
|
382
|
-
end
|
383
|
-
false
|
384
|
-
end
|
385
|
-
|
386
|
-
def click_on_one_of_several_with_display_by_text(xpath_several_elements, text_to_click)
|
387
|
-
@driver.find_elements(:xpath, xpath_several_elements).each do |current_element|
|
388
|
-
if current_element.displayed? && text_to_click == current_element.text
|
389
|
-
current_element.click
|
390
|
-
return true
|
391
|
-
end
|
392
|
-
end
|
393
|
-
false
|
394
|
-
end
|
395
|
-
|
396
|
-
def right_click_on_one_of_several_by_text(xpath_several_elements, text_to_click)
|
397
|
-
@driver.find_elements(:xpath, xpath_several_elements).each do |current_element|
|
398
|
-
if text_to_click == current_element.text
|
399
|
-
@driver.action.context_click(current_element).perform
|
400
|
-
return true
|
401
|
-
end
|
402
|
-
end
|
403
|
-
false
|
404
|
-
end
|
405
|
-
|
406
|
-
def click_on_one_of_several_with_display_by_number(xpath_several_elements, number)
|
407
|
-
@driver.find_elements(:xpath, "#{xpath_several_elements}[#{number}]").each do |current_element|
|
408
|
-
if current_element.displayed?
|
409
|
-
current_element.click
|
410
|
-
return true
|
411
|
-
end
|
412
|
-
end
|
413
|
-
false
|
414
|
-
end
|
415
|
-
|
416
|
-
def click_on_one_of_several_by_parameter(xpath_several_elements, parameter_name, parameter_value)
|
417
|
-
@driver.find_elements(:xpath, xpath_several_elements).each do |current_element|
|
418
|
-
if current_element.attribute(parameter_name).include? parameter_value
|
419
|
-
current_element.click
|
420
|
-
return true
|
421
|
-
end
|
422
|
-
end
|
423
|
-
false
|
424
|
-
end
|
425
|
-
|
426
|
-
def click_on_one_of_several_by_parameter_and_text(xpath_several_elements, parameter_name, parameter_value, text_to_click)
|
427
|
-
@driver.find_elements(:xpath, xpath_several_elements).each do |current_element|
|
428
|
-
if current_element.attribute(parameter_name).include?(parameter_value) && text_to_click == current_element.text
|
429
|
-
current_element.click
|
430
|
-
return true
|
431
|
-
end
|
432
|
-
end
|
433
|
-
false
|
434
|
-
end
|
435
|
-
|
436
|
-
def click_on_one_of_several_xpath_by_number(xpath, number_of_element)
|
437
|
-
click_on_locator("(#{xpath})[#{number_of_element}]")
|
438
|
-
end
|
439
|
-
|
440
248
|
def move_to_element(element)
|
441
249
|
element = get_element(element) if element.is_a?(String)
|
442
250
|
@driver.action.move_to(element).perform
|
@@ -448,16 +256,6 @@ module OnlyofficeWebdriverWrapper
|
|
448
256
|
OnlyofficeLoggerHelper.log("Moved mouse to element: #{xpath_name}")
|
449
257
|
end
|
450
258
|
|
451
|
-
def move_to_one_of_several_displayed_element(xpath_several_elements)
|
452
|
-
get_elements(xpath_several_elements).each do |current_element|
|
453
|
-
if current_element.displayed?
|
454
|
-
move_to_element(current_element)
|
455
|
-
return true
|
456
|
-
end
|
457
|
-
end
|
458
|
-
false
|
459
|
-
end
|
460
|
-
|
461
259
|
def mouse_over(xpath_name, x_coordinate = 0, y_coordinate = 0)
|
462
260
|
wait_until_element_present(xpath_name)
|
463
261
|
@driver.action.move_to(@driver.find_element(:xpath, xpath_name), x_coordinate.to_i, y_coordinate.to_i).perform
|
@@ -476,50 +274,6 @@ module OnlyofficeWebdriverWrapper
|
|
476
274
|
false
|
477
275
|
end
|
478
276
|
|
479
|
-
def wait_until_element_present(xpath_name)
|
480
|
-
wait = Selenium::WebDriver::Wait.new(timeout: TIMEOUT_WAIT_ELEMENT) # seconds
|
481
|
-
begin
|
482
|
-
wait.until { get_element(xpath_name) }
|
483
|
-
rescue Selenium::WebDriver::Error::TimeOutError
|
484
|
-
webdriver_error("wait_until_element_present(#{xpath_name}) Selenium::WebDriver::Error::TimeOutError: timed out after 15 seconds")
|
485
|
-
end
|
486
|
-
end
|
487
|
-
|
488
|
-
def wait_until_element_disappear(xpath_name)
|
489
|
-
wait = Selenium::WebDriver::Wait.new(timeout: TIMEOUT_WAIT_ELEMENT) # seconds
|
490
|
-
begin
|
491
|
-
wait.until { get_element(xpath_name) ? false : true }
|
492
|
-
rescue Selenium::WebDriver::Error::TimeOutError
|
493
|
-
webdriver_error("wait_until_element_present(#{xpath_name}) Selenium::WebDriver::Error::TimeOutError: timed out after 15 seconds")
|
494
|
-
end
|
495
|
-
end
|
496
|
-
|
497
|
-
def get_elements_from_array_before_some(xpath_several_elements, xpath_for_some)
|
498
|
-
elements = get_elements(xpath_several_elements)
|
499
|
-
result = []
|
500
|
-
some_element = get_element(xpath_for_some)
|
501
|
-
return result if some_element.nil?
|
502
|
-
|
503
|
-
elements.each do |current|
|
504
|
-
break if current == some_element
|
505
|
-
|
506
|
-
result << current
|
507
|
-
end
|
508
|
-
result
|
509
|
-
end
|
510
|
-
|
511
|
-
def get_elements_from_array_after_some(xpath_several_elements, xpath_for_some)
|
512
|
-
elements = get_elements(xpath_several_elements)
|
513
|
-
some_element = get_element(xpath_for_some)
|
514
|
-
return elements if some_element.nil?
|
515
|
-
|
516
|
-
elements.each do |current|
|
517
|
-
elements.delete(current)
|
518
|
-
break if current == some_element
|
519
|
-
end
|
520
|
-
elements
|
521
|
-
end
|
522
|
-
|
523
277
|
def get_element_by_display(xpath_name)
|
524
278
|
@driver.find_elements(:xpath, xpath_name).each do |element|
|
525
279
|
return element if element.displayed?
|
@@ -528,10 +282,14 @@ module OnlyofficeWebdriverWrapper
|
|
528
282
|
webdriver_error("get_element_by_display(#{xpath_name}): invalid selector: Unable to locate an element with the xpath expression")
|
529
283
|
end
|
530
284
|
|
285
|
+
# Return count of elements (visible and not visible)
|
286
|
+
# @param xpath_name [String] xpath to find
|
287
|
+
# @param only_visible [True, False] count only visible elements?
|
288
|
+
# @return [Integer] element count
|
531
289
|
def get_element_count(xpath_name, only_visible = true)
|
532
290
|
if element_present?(xpath_name)
|
533
291
|
elements = @driver.find_elements(:xpath, xpath_name)
|
534
|
-
only_visible ? elements.delete_if { |element|
|
292
|
+
only_visible ? elements.delete_if { |element| !element.displayed? }.length : elements.length
|
535
293
|
else
|
536
294
|
0
|
537
295
|
end
|
@@ -567,18 +325,9 @@ module OnlyofficeWebdriverWrapper
|
|
567
325
|
end
|
568
326
|
end
|
569
327
|
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
while !element_visible?(xpath_name) && time < timeout
|
574
|
-
sleep(1)
|
575
|
-
time += 1
|
576
|
-
end
|
577
|
-
return unless time >= timeout
|
578
|
-
|
579
|
-
webdriver_error("Element #{xpath_name} not visible for #{timeout} seconds")
|
580
|
-
end
|
581
|
-
|
328
|
+
# Check if any element of xpath is displayed
|
329
|
+
# @param xpath_several_elements [String] xpath to check
|
330
|
+
# @return [True, False] result of visibility
|
582
331
|
def one_of_several_elements_displayed?(xpath_several_elements)
|
583
332
|
@driver.find_elements(:xpath, xpath_several_elements).each do |current_element|
|
584
333
|
return true if current_element.displayed?
|
@@ -598,10 +347,6 @@ module OnlyofficeWebdriverWrapper
|
|
598
347
|
end
|
599
348
|
end
|
600
349
|
|
601
|
-
def remove_element(xpath)
|
602
|
-
execute_javascript("element = document.evaluate(\"#{xpath}\", document, null, XPathResult.ANY_TYPE, null).iterateNext();if (element !== null) {element.parentNode.removeChild(element);};")
|
603
|
-
end
|
604
|
-
|
605
350
|
# Select frame as current
|
606
351
|
# @param [String] xpath_name name of current xpath
|
607
352
|
def select_frame(xpath_name = '//iframe', count_of_frames = 1)
|
@@ -655,12 +400,6 @@ module OnlyofficeWebdriverWrapper
|
|
655
400
|
"singleNodeValue.removeAttribute('#{attribute}');")
|
656
401
|
end
|
657
402
|
|
658
|
-
def select_text_from_page(xpath_name)
|
659
|
-
wait_until_element_visible(xpath_name)
|
660
|
-
elem = get_element xpath_name
|
661
|
-
@driver.action.key_down(:control).click(elem).send_keys('a').key_up(:control).perform
|
662
|
-
end
|
663
|
-
|
664
403
|
def select_combo_box(xpath_name, select_value, select_by = :value)
|
665
404
|
wait_until_element_visible(xpath_name)
|
666
405
|
option = Selenium::WebDriver::Support::Select.new(get_element(xpath_name))
|
@@ -671,13 +410,8 @@ module OnlyofficeWebdriverWrapper
|
|
671
410
|
end
|
672
411
|
end
|
673
412
|
|
674
|
-
|
675
|
-
|
676
|
-
return index if element_text == current_element.attribute('innerHTML')
|
677
|
-
end
|
678
|
-
nil
|
679
|
-
end
|
680
|
-
|
413
|
+
# Get page source
|
414
|
+
# @return [String] all page source
|
681
415
|
def get_page_source
|
682
416
|
@driver.execute_script('return document.documentElement.innerHTML;')
|
683
417
|
end
|
@@ -692,22 +426,6 @@ module OnlyofficeWebdriverWrapper
|
|
692
426
|
raise exception, "#{error_message}\n\nPage address: #{current_url}\n\nError #{webdriver_screenshot}"
|
693
427
|
end
|
694
428
|
|
695
|
-
def wait_until(timeout = ::PageObject.default_page_wait, message = nil, wait_js: true, &block)
|
696
|
-
tries ||= 3
|
697
|
-
wait = Object::Selenium::WebDriver::Wait.new(timeout: timeout, message: message)
|
698
|
-
wait.until(&block)
|
699
|
-
if wait_js
|
700
|
-
wait.until { document_ready? }
|
701
|
-
wait.until { jquery_finished? }
|
702
|
-
end
|
703
|
-
rescue Selenium::WebDriver::Error::TimeOutError
|
704
|
-
webdriver_error("Wait until timeout: #{timeout} seconds in")
|
705
|
-
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
706
|
-
OnlyofficeLoggerHelper.log("Wait until: rescuing from Stale Element error, #{tries} attempts remaining")
|
707
|
-
retry unless (tries -= 1).zero?
|
708
|
-
webdriver_error('Wait until: rescuing from Stale Element error failed after 3 tries')
|
709
|
-
end
|
710
|
-
|
711
429
|
def wait_file_for_download(file_name, timeout = TIMEOUT_FILE_DOWNLOAD)
|
712
430
|
full_file_name = "#{@download_directory}/#{file_name}"
|
713
431
|
full_file_name = file_name if file_name[0] == '/'
|
@@ -725,5 +443,18 @@ module OnlyofficeWebdriverWrapper
|
|
725
443
|
source = get_page_source
|
726
444
|
source.include?('Error 503')
|
727
445
|
end
|
446
|
+
|
447
|
+
# Perform cleanup if something went wrong during tests
|
448
|
+
# @param forced [True, False] should cleanup run in all cases
|
449
|
+
def self.clean_up(forced = false)
|
450
|
+
return unless OnlyofficeFileHelper::LinuxHelper.user_name.include?('nct-at') ||
|
451
|
+
OnlyofficeFileHelper::LinuxHelper.user_name.include?('ubuntu') ||
|
452
|
+
forced == true
|
453
|
+
|
454
|
+
OnlyofficeFileHelper::LinuxHelper.kill_all('chromedriver')
|
455
|
+
OnlyofficeFileHelper::LinuxHelper.kill_all('geckodriver')
|
456
|
+
OnlyofficeFileHelper::LinuxHelper.kill_all('Xvfb')
|
457
|
+
OnlyofficeFileHelper::LinuxHelper.kill_all_browsers
|
458
|
+
end
|
728
459
|
end
|
729
460
|
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnlyofficeWebdriverWrapper
|
4
|
+
# Method to perform different clicks
|
5
|
+
module ClickMethods
|
6
|
+
# Click on specified element
|
7
|
+
# @param element [Selenium::WebDriver::Element] element to click
|
8
|
+
# @return [nil] nothing
|
9
|
+
def click(element)
|
10
|
+
element.click
|
11
|
+
end
|
12
|
+
|
13
|
+
# Click on locator
|
14
|
+
# @param xpath_name [String] xpath to click
|
15
|
+
# @param by_javascript [True, False] should be clicked by javascript
|
16
|
+
# @param count [Integer] count of clicks
|
17
|
+
def click_on_locator(xpath_name, by_javascript = false, count: 1)
|
18
|
+
element = get_element(xpath_name)
|
19
|
+
return webdriver_error("Element with xpath: #{xpath_name} not found") if element.nil?
|
20
|
+
|
21
|
+
if by_javascript
|
22
|
+
execute_javascript("document.evaluate(\"#{xpath_name}\", document, null, XPathResult.ANY_TYPE, null).iterateNext().click();")
|
23
|
+
else
|
24
|
+
begin
|
25
|
+
count.times { element.click }
|
26
|
+
rescue Selenium::WebDriver::Error::ElementNotVisibleError => e
|
27
|
+
webdriver_error(e.class, "Selenium::WebDriver::Error::ElementNotVisibleError: element not visible for xpath: #{xpath_name}")
|
28
|
+
rescue Exception => e
|
29
|
+
webdriver_error(e.class, "UnknownError #{e.message} #{xpath_name}")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Click on one of several which displayed
|
35
|
+
# @param xpath_name [String] xpath to find element
|
36
|
+
# @return [nil]
|
37
|
+
def click_on_displayed(xpath_name)
|
38
|
+
element = get_element_by_display(xpath_name)
|
39
|
+
begin
|
40
|
+
element.is_a?(Array) ? element.first.click : element.click
|
41
|
+
rescue Exception => e
|
42
|
+
webdriver_error(e.class, "Exception #{e} in click_on_displayed(#{xpath_name})")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Click on locator by coordinates
|
47
|
+
# @param xpath_name [String] xpath to click
|
48
|
+
# @param right_by [Integer] shift to right
|
49
|
+
# @param down_by [Integer] shift to bottom
|
50
|
+
# @return [nil]
|
51
|
+
def click_on_locator_coordinates(xpath_name, right_by, down_by)
|
52
|
+
wait_until_element_visible(xpath_name)
|
53
|
+
element = @driver.find_element(:xpath, xpath_name)
|
54
|
+
@driver.action.move_to(element, right_by.to_i, down_by.to_i).perform
|
55
|
+
@driver.action.move_to(element, right_by.to_i, down_by.to_i).click.perform
|
56
|
+
end
|
57
|
+
|
58
|
+
# Click on one of several which displayed
|
59
|
+
# @param xpath_several_elements [String] xpath to find element
|
60
|
+
# @return [True, False] true if click successful, false if not found
|
61
|
+
def click_on_one_of_several_by_display(xpath_several_elements)
|
62
|
+
@driver.find_elements(:xpath, xpath_several_elements).each do |current_element|
|
63
|
+
if current_element.displayed?
|
64
|
+
current_element.click
|
65
|
+
return true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
# Click on one of several xpath filtered by parameter and value
|
72
|
+
# @param xpath_several_elements [String] xpath to select
|
73
|
+
# @param parameter_name [String] parameter name
|
74
|
+
# @param parameter_value [String] parameter value
|
75
|
+
# @return [True, False] true if click successful, false if not found
|
76
|
+
def click_on_one_of_several_by_parameter(xpath_several_elements, parameter_name, parameter_value)
|
77
|
+
@driver.find_elements(:xpath, xpath_several_elements).each do |current_element|
|
78
|
+
if current_element.attribute(parameter_name).include? parameter_value
|
79
|
+
current_element.click
|
80
|
+
return true
|
81
|
+
end
|
82
|
+
end
|
83
|
+
false
|
84
|
+
end
|
85
|
+
|
86
|
+
# Perform right click on xpath
|
87
|
+
# @param xpath_name [String] xpath to click
|
88
|
+
# @return [nil]
|
89
|
+
def right_click(xpath_name)
|
90
|
+
wait_until_element_visible(xpath_name)
|
91
|
+
|
92
|
+
@driver.action.context_click(@driver.find_element(:xpath, xpath_name)).perform
|
93
|
+
end
|
94
|
+
|
95
|
+
# Perform right click on locator with specified coordinates
|
96
|
+
# @param xpath_name [String] xpath to click
|
97
|
+
# @param right_by [Integer] shift to right
|
98
|
+
# @param down_by [Integer] shift to bottom
|
99
|
+
# @return [nil]
|
100
|
+
def right_click_on_locator_coordinates(xpath_name, right_by = nil, down_by = nil)
|
101
|
+
wait_until_element_visible(xpath_name)
|
102
|
+
element = @driver.find_element(:xpath, xpath_name)
|
103
|
+
@driver.action.move_to(element, right_by.to_i, down_by.to_i).perform
|
104
|
+
@driver.action.move_to(element, right_by.to_i, down_by.to_i).context_click.perform
|
105
|
+
end
|
106
|
+
|
107
|
+
# Perform double_click on element
|
108
|
+
# @param xpath_name [String] xpath to click
|
109
|
+
# @return [nil]
|
110
|
+
def double_click(xpath_name)
|
111
|
+
wait_until_element_visible(xpath_name)
|
112
|
+
@driver.action.move_to(@driver.find_element(:xpath, xpath_name)).double_click.perform
|
113
|
+
end
|
114
|
+
|
115
|
+
# Perform double_click on specified coordinates
|
116
|
+
# @param xpath_name [String] xpath to click
|
117
|
+
# @param right_by [Integer] shift to right
|
118
|
+
# @param down_by [Integer] shift to bottom
|
119
|
+
# @return [nil]
|
120
|
+
def double_click_on_locator_coordinates(xpath_name, right_by, down_by)
|
121
|
+
wait_until_element_visible(xpath_name)
|
122
|
+
@driver.action.move_to(@driver.find_element(:xpath, xpath_name), right_by.to_i, down_by.to_i).double_click.perform
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnlyofficeWebdriverWrapper
|
4
|
+
# Method to different wait_until methods
|
5
|
+
module WaitUntilMethods
|
6
|
+
# @return [Integer] default timeout for wait element
|
7
|
+
TIMEOUT_WAIT_ELEMENT = 15
|
8
|
+
|
9
|
+
def wait_until(timeout = ::PageObject.default_page_wait, message = nil, wait_js: true, &block)
|
10
|
+
tries ||= 3
|
11
|
+
wait = Object::Selenium::WebDriver::Wait.new(timeout: timeout, message: message)
|
12
|
+
wait.until(&block)
|
13
|
+
if wait_js
|
14
|
+
wait.until { document_ready? }
|
15
|
+
wait.until { jquery_finished? }
|
16
|
+
end
|
17
|
+
rescue Selenium::WebDriver::Error::TimeOutError
|
18
|
+
webdriver_error("Wait until timeout: #{timeout} seconds in")
|
19
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
20
|
+
OnlyofficeLoggerHelper.log("Wait until: rescuing from Stale Element error, #{tries} attempts remaining")
|
21
|
+
retry unless (tries -= 1).zero?
|
22
|
+
webdriver_error('Wait until: rescuing from Stale Element error failed after 3 tries')
|
23
|
+
end
|
24
|
+
|
25
|
+
def wait_until_element_visible(xpath_name, timeout = 15)
|
26
|
+
wait_until_element_present(xpath_name)
|
27
|
+
time = 0
|
28
|
+
while !element_visible?(xpath_name) && time < timeout
|
29
|
+
sleep(1)
|
30
|
+
time += 1
|
31
|
+
end
|
32
|
+
return unless time >= timeout
|
33
|
+
|
34
|
+
webdriver_error("Element #{xpath_name} not visible for #{timeout} seconds")
|
35
|
+
end
|
36
|
+
|
37
|
+
# Wait until some element present
|
38
|
+
# If timeout exceeded - raise an error
|
39
|
+
# @param xpath_name [String] xpath of element
|
40
|
+
# @param timeout [Integer] timeout to wait
|
41
|
+
# @return [Void]
|
42
|
+
def wait_until_element_present(xpath_name, timeout: TIMEOUT_WAIT_ELEMENT)
|
43
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout) # seconds
|
44
|
+
begin
|
45
|
+
wait.until { get_element(xpath_name) }
|
46
|
+
rescue Selenium::WebDriver::Error::TimeOutError => e
|
47
|
+
timeout_message = "wait_until_element_present(#{xpath_name}) "\
|
48
|
+
'Selenium::WebDriver::Error::TimeOutError: '\
|
49
|
+
"timed out after #{timeout} seconds"
|
50
|
+
webdriver_error(e.class, timeout_message)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Wait until some element disappear
|
55
|
+
# If timeout exceeded - raise an error
|
56
|
+
# @param xpath_name [String] xpath of element
|
57
|
+
# @param timeout [Integer] timeout to wait
|
58
|
+
# @return [Void]
|
59
|
+
def wait_until_element_disappear(xpath_name, timeout: TIMEOUT_WAIT_ELEMENT)
|
60
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout) # seconds
|
61
|
+
begin
|
62
|
+
wait.until { get_element(xpath_name) ? false : true }
|
63
|
+
rescue Selenium::WebDriver::Error::TimeOutError => e
|
64
|
+
timeout_message = "wait_until_element_present(#{xpath_name}) "\
|
65
|
+
'Selenium::WebDriver::Error::TimeOutError: '\
|
66
|
+
"timed out after #{timeout} seconds"
|
67
|
+
webdriver_error(e.class, timeout_message)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -26,13 +26,6 @@ module OnlyofficeWebdriverWrapper
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
def get_attribute_from_displayed_element(xpath_name, attribute)
|
30
|
-
@driver.find_elements(:xpath, xpath_name).each do |current_element|
|
31
|
-
return current_element.attribute(attribute) if current_element.displayed?
|
32
|
-
end
|
33
|
-
false
|
34
|
-
end
|
35
|
-
|
36
29
|
def get_attributes_of_several_elements(xpath_several_elements, attribute)
|
37
30
|
elements = @driver.find_elements(:xpath, xpath_several_elements)
|
38
31
|
|
@@ -16,9 +16,22 @@ module OnlyofficeWebdriverWrapper
|
|
16
16
|
def download(file_url)
|
17
17
|
data = Kernel.open(file_url, &:read)
|
18
18
|
file = Tempfile.new('onlyoffice-downloaded-file')
|
19
|
-
file.write(data)
|
19
|
+
file.write(data.force_encoding('UTF-8'))
|
20
20
|
file.close
|
21
21
|
file.path
|
22
22
|
end
|
23
|
+
|
24
|
+
# Perform safe cleanup of download folder
|
25
|
+
# @return [Nothing]
|
26
|
+
def cleanup_download_folder
|
27
|
+
return unless Dir.exist?(@download_directory)
|
28
|
+
|
29
|
+
if @download_directory.start_with?(Dir.tmpdir)
|
30
|
+
FileUtils.remove_dir(@download_directory)
|
31
|
+
else
|
32
|
+
OnlyofficeLoggerHelper.log("Download directory #{@download_directory} is not at tmp dir. "\
|
33
|
+
'It will be not deleted')
|
34
|
+
end
|
35
|
+
end
|
23
36
|
end
|
24
37
|
end
|
@@ -3,17 +3,24 @@
|
|
3
3
|
module OnlyofficeWebdriverWrapper
|
4
4
|
# Methods for webdriver for calling Javascript
|
5
5
|
module WebdriverJsMethods
|
6
|
-
|
6
|
+
# Execute javascript
|
7
|
+
# @param script [String] code to execute
|
8
|
+
# @param wait_timeout [Integer] wait after JS is executed.
|
9
|
+
# Some code require some time to execute
|
10
|
+
def execute_javascript(script, wait_timeout: 0)
|
7
11
|
result = @driver.execute_script(script)
|
8
12
|
OnlyofficeLoggerHelper.log("Executed js: `#{script}` with result: `#{result}`")
|
13
|
+
sleep(wait_timeout)
|
9
14
|
result
|
10
15
|
rescue Exception => e
|
11
16
|
webdriver_error("Exception #{e} in execute_javascript: #{script}")
|
12
17
|
end
|
13
18
|
|
14
|
-
# @
|
15
|
-
|
16
|
-
|
19
|
+
# @param [String] xpath element to select
|
20
|
+
# @return [String] string to select dom by xpath
|
21
|
+
def dom_element_by_xpath(xpath)
|
22
|
+
escaped_xpath = xpath.tr('"', "'")
|
23
|
+
"document.evaluate(\"#{escaped_xpath}\", document, null, XPathResult.ANY_TYPE, null).iterateNext()"
|
17
24
|
end
|
18
25
|
|
19
26
|
def type_to_locator_by_javascript(xpath_name, text)
|
@@ -29,8 +36,8 @@ module OnlyofficeWebdriverWrapper
|
|
29
36
|
# @param xpath [Sting] xpath of object
|
30
37
|
# @return [Dimensions] size of element
|
31
38
|
def element_size_by_js(xpath)
|
32
|
-
width = execute_javascript("return
|
33
|
-
height = execute_javascript("return
|
39
|
+
width = execute_javascript("return #{dom_element_by_xpath(xpath)}.offsetWidth")
|
40
|
+
height = execute_javascript("return #{dom_element_by_xpath(xpath)}.offsetHeight")
|
34
41
|
Dimensions.new(width, height)
|
35
42
|
end
|
36
43
|
|
@@ -38,8 +45,9 @@ module OnlyofficeWebdriverWrapper
|
|
38
45
|
# @param xpath [Sting] xpath of object
|
39
46
|
# @return [CursorPoint] position of element
|
40
47
|
def object_absolute_position(xpath)
|
41
|
-
|
42
|
-
|
48
|
+
bounding = "#{dom_element_by_xpath(xpath)}.getBoundingClientRect()"
|
49
|
+
left = execute_javascript("return #{bounding}.left")
|
50
|
+
top = execute_javascript("return #{bounding}.top")
|
43
51
|
Dimensions.new(left, top)
|
44
52
|
end
|
45
53
|
|
@@ -73,5 +81,15 @@ module OnlyofficeWebdriverWrapper
|
|
73
81
|
result = execute_javascript("return #{full_command}")
|
74
82
|
result.delete('"')
|
75
83
|
end
|
84
|
+
|
85
|
+
# Remove element by its xpath
|
86
|
+
# @param [String] xpath of element to remove
|
87
|
+
# @return [String] result of javascript execution
|
88
|
+
def remove_element(xpath)
|
89
|
+
script = "element = #{dom_element_by_xpath(xpath)};"\
|
90
|
+
'if (element !== null) '\
|
91
|
+
'{element.parentNode.removeChild(element);};'
|
92
|
+
execute_javascript(script)
|
93
|
+
end
|
76
94
|
end
|
77
95
|
end
|
@@ -7,16 +7,7 @@ module OnlyofficeWebdriverWrapper
|
|
7
7
|
get_attribute(xpath, 'style').split(';').each do |current_param|
|
8
8
|
return /:\s(.*);?$/.match(current_param)[1] if current_param.include?(parameter_name)
|
9
9
|
end
|
10
|
-
|
11
|
-
|
12
|
-
def get_style_attributes_of_several_elements(xpath_several_elements, style)
|
13
|
-
@driver.find_elements(:xpath, xpath_several_elements).map do |element|
|
14
|
-
el_style = element.attribute('style')
|
15
|
-
unless el_style.empty?
|
16
|
-
found_style = el_style.split(';').find { |curr_param| curr_param.include?(style) }
|
17
|
-
found_style&.gsub(/\s?#{style}:/, '')
|
18
|
-
end
|
19
|
-
end.compact
|
10
|
+
nil
|
20
11
|
end
|
21
12
|
|
22
13
|
def set_style_parameter(xpath, attribute, attribute_value)
|
@@ -30,7 +21,7 @@ module OnlyofficeWebdriverWrapper
|
|
30
21
|
end
|
31
22
|
|
32
23
|
def set_style_show_by_xpath(xpath, move_to_center = false)
|
33
|
-
xpath.tr
|
24
|
+
xpath = xpath.tr("'", '"')
|
34
25
|
execute_javascript('document.evaluate( \'' + xpath.to_s +
|
35
26
|
'\' ,document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue.style.display = "block";')
|
36
27
|
return unless move_to_center
|
@@ -9,11 +9,6 @@ module OnlyofficeWebdriverWrapper
|
|
9
9
|
execute_javascript('window.open()')
|
10
10
|
end
|
11
11
|
|
12
|
-
def maximize
|
13
|
-
@driver.manage.window.maximize
|
14
|
-
OnlyofficeLoggerHelper.log('Maximized current window')
|
15
|
-
end
|
16
|
-
|
17
12
|
def resize_tab(width, height)
|
18
13
|
@driver.manage.window.resize_to(width, height)
|
19
14
|
OnlyofficeLoggerHelper.log("Resize current window to #{width}x#{height}")
|
@@ -62,10 +57,6 @@ module OnlyofficeWebdriverWrapper
|
|
62
57
|
switch_to_main_tab
|
63
58
|
end
|
64
59
|
|
65
|
-
def close_window
|
66
|
-
@driver.close
|
67
|
-
end
|
68
|
-
|
69
60
|
def close_popup_and_switch_to_main_tab
|
70
61
|
switch_to_popup
|
71
62
|
close_tab
|
@@ -20,7 +20,10 @@ module OnlyofficeWebdriverWrapper
|
|
20
20
|
begin
|
21
21
|
element.clear
|
22
22
|
rescue Exception => e
|
23
|
-
webdriver_error("Error in element.clear #{e} for
|
23
|
+
webdriver_error(e.class, "Error in element.clear #{e} for "\
|
24
|
+
"type_to_locator(#{xpath_name}, #{text_to_send}, "\
|
25
|
+
"#{clear_content}, #{click_on_it}, "\
|
26
|
+
"#{by_action}, #{by_element_send_key})")
|
24
27
|
end
|
25
28
|
end
|
26
29
|
|
@@ -37,21 +40,25 @@ module OnlyofficeWebdriverWrapper
|
|
37
40
|
@driver.action.send_keys(symbol).perform
|
38
41
|
end
|
39
42
|
else
|
40
|
-
|
43
|
+
webdriver_bug_8179_workaround(text_to_send)
|
41
44
|
end
|
42
45
|
end
|
43
46
|
end
|
44
47
|
|
45
48
|
def type_to_input(xpath_name, text_to_send, clear_content = false, click_on_it = true)
|
46
49
|
element = get_element(xpath_name)
|
47
|
-
|
50
|
+
if element.nil?
|
51
|
+
webdriver_error(Selenium::WebDriver::Error::NoSuchElementError,
|
52
|
+
"type_to_input(#{xpath_name}, #{text_to_send}, "\
|
53
|
+
"#{clear_content}, #{click_on_it}): element not found")
|
54
|
+
end
|
48
55
|
element.clear if clear_content
|
49
56
|
sleep 0.2
|
50
57
|
if click_on_it
|
51
58
|
begin
|
52
59
|
element.click
|
53
60
|
rescue Exception => e
|
54
|
-
webdriver_error("type_to_input(#{xpath_name}, #{text_to_send}, #{clear_content}, #{click_on_it}) error in 'element.click' error: #{e}")
|
61
|
+
webdriver_error(e.class, "type_to_input(#{xpath_name}, #{text_to_send}, #{clear_content}, #{click_on_it}) error in 'element.click' error: #{e}")
|
55
62
|
end
|
56
63
|
sleep 0.2
|
57
64
|
end
|
@@ -80,10 +87,35 @@ module OnlyofficeWebdriverWrapper
|
|
80
87
|
|
81
88
|
def key_down(xpath, key)
|
82
89
|
@driver.action.key_down(get_element(xpath), key).perform
|
90
|
+
sleep(1) # for some reason quick key_down select text in control
|
83
91
|
end
|
84
92
|
|
85
93
|
def key_up(xpath, key)
|
86
94
|
@driver.action.key_up(get_element(xpath), key).perform
|
87
95
|
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
# Workaround for bug with typing with :control
|
100
|
+
# See https://github.com/SeleniumHQ/selenium/issues/8179
|
101
|
+
# for more details
|
102
|
+
def webdriver_bug_8179_workaround(text_to_send)
|
103
|
+
text_to_send = [text_to_send].flatten
|
104
|
+
|
105
|
+
key_modifiers = text_to_send.select { |i| i.is_a?(Symbol) }
|
106
|
+
letters = text_to_send - key_modifiers
|
107
|
+
|
108
|
+
key_modifiers.each do |modifier|
|
109
|
+
@driver.action.key_down(modifier).perform
|
110
|
+
end
|
111
|
+
|
112
|
+
letters.each do |letter|
|
113
|
+
@driver.action.send_keys(letter.to_s).perform
|
114
|
+
end
|
115
|
+
|
116
|
+
key_modifiers.each do |modifier|
|
117
|
+
@driver.action.key_up(modifier).perform
|
118
|
+
end
|
119
|
+
end
|
88
120
|
end
|
89
121
|
end
|
@@ -3,10 +3,18 @@
|
|
3
3
|
module OnlyofficeWebdriverWrapper
|
4
4
|
# Module for wokring with webdriver useragent
|
5
5
|
module WebdriverUserAgentHelper
|
6
|
-
USERAGENT_ANDROID_PHONE = 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MDB08M)
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
USERAGENT_ANDROID_PHONE = 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MDB08M) '\
|
7
|
+
'AppleWebKit/537.36 (KHTML, like Gecko) '\
|
8
|
+
'Chrome/51.0.2704.81 Mobile Safari/537.36'
|
9
|
+
USERAGENT_IPHONE = 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X) '\
|
10
|
+
'AppleWebKit/601.1.46 (KHTML, like Gecko) '\
|
11
|
+
'Version/9.0 Mobile/13F69 Safari/601.1'
|
12
|
+
USERAGENT_IPAD_AIR_2_SAFARI = 'Mozilla/5.0 (iPad; CPU OS 10_0 like Mac OS X) '\
|
13
|
+
'AppleWebKit/602.1.50 (KHTML, like Gecko) '\
|
14
|
+
'Version/10.0 Mobile/14A5346a Safari/602.1'
|
15
|
+
USERAGENT_NEXUS_10_CHROME = 'Mozilla/5.0 (Linux; Android 4.3; Nexus 10 Build/JSS15Q) '\
|
16
|
+
'AppleWebKit/537.36 (KHTML, like Gecko) '\
|
17
|
+
'Chrome/48.0.2564.23 Safari/537.36'
|
10
18
|
|
11
19
|
# @return [String] user agent string for current device
|
12
20
|
def user_agent_for_device
|
metadata
CHANGED
@@ -1,31 +1,32 @@
|
|
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.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
+
- ONLYOFFICE
|
7
8
|
- Pavel Lobashov
|
8
9
|
- Oleg Nazarov
|
9
10
|
- Dmitry Rotaty
|
10
11
|
autorequire:
|
11
12
|
bindir: bin
|
12
13
|
cert_chain: []
|
13
|
-
date: 2020-
|
14
|
+
date: 2020-07-03 00:00:00.000000000 Z
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
17
|
name: headless
|
17
18
|
requirement: !ruby/object:Gem::Requirement
|
18
19
|
requirements:
|
19
|
-
- -
|
20
|
+
- - '='
|
20
21
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
22
|
+
version: 2.3.1
|
22
23
|
type: :runtime
|
23
24
|
prerelease: false
|
24
25
|
version_requirements: !ruby/object:Gem::Requirement
|
25
26
|
requirements:
|
26
|
-
- -
|
27
|
+
- - '='
|
27
28
|
- !ruby/object:Gem::Version
|
28
|
-
version:
|
29
|
+
version: 2.3.1
|
29
30
|
- !ruby/object:Gem::Dependency
|
30
31
|
name: onlyoffice_file_helper
|
31
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,10 +111,23 @@ dependencies:
|
|
110
111
|
- - "~>"
|
111
112
|
- !ruby/object:Gem::Version
|
112
113
|
version: '6'
|
113
|
-
|
114
|
+
- !ruby/object:Gem::Dependency
|
115
|
+
name: rake
|
116
|
+
requirement: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - "~>"
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '13.0'
|
121
|
+
type: :development
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - "~>"
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '13.0'
|
128
|
+
description: ONLYOFFICE Webdriver Wrapper Gem. Used in QA
|
114
129
|
email:
|
115
130
|
- shockwavenn@gmail.com
|
116
|
-
- dafttrick@gmail.com
|
117
131
|
executables: []
|
118
132
|
extensions: []
|
119
133
|
extra_rdoc_files: []
|
@@ -125,12 +139,17 @@ files:
|
|
125
139
|
- lib/onlyoffice_webdriver_wrapper/helpers/bin/geckodriver
|
126
140
|
- lib/onlyoffice_webdriver_wrapper/helpers/chrome_helper.rb
|
127
141
|
- lib/onlyoffice_webdriver_wrapper/helpers/firefox_helper.rb
|
142
|
+
- lib/onlyoffice_webdriver_wrapper/helpers/firefox_helper/save_to_disk_files.list
|
128
143
|
- lib/onlyoffice_webdriver_wrapper/helpers/headless_helper.rb
|
144
|
+
- lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/headless_screenshot_patch.rb
|
129
145
|
- lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/real_display_tools.rb
|
130
146
|
- lib/onlyoffice_webdriver_wrapper/helpers/headless_helper/ruby_helper.rb
|
131
147
|
- lib/onlyoffice_webdriver_wrapper/helpers/os_helper.rb
|
148
|
+
- lib/onlyoffice_webdriver_wrapper/name.rb
|
132
149
|
- lib/onlyoffice_webdriver_wrapper/version.rb
|
133
150
|
- lib/onlyoffice_webdriver_wrapper/webdriver.rb
|
151
|
+
- lib/onlyoffice_webdriver_wrapper/webdriver/click_methods.rb
|
152
|
+
- lib/onlyoffice_webdriver_wrapper/webdriver/wait_until_methods.rb
|
134
153
|
- lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_alert_helper.rb
|
135
154
|
- lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_attributes_helper.rb
|
136
155
|
- lib/onlyoffice_webdriver_wrapper/webdriver/webdriver_browser_info_helper.rb
|
@@ -146,7 +165,12 @@ files:
|
|
146
165
|
homepage: https://github.com/onlyoffice-testing-robot/onlyoffice_webdriver_wrapper
|
147
166
|
licenses:
|
148
167
|
- AGPL-3.0
|
149
|
-
metadata:
|
168
|
+
metadata:
|
169
|
+
bug_tracker_uri: https://github.com/onlyoffice-testing-robot/onlyoffice_webdriver_wrapper/issues
|
170
|
+
changelog_uri: https://github.com/onlyoffice-testing-robot/onlyoffice_webdriver_wrapper/blob/master/CHANGELOG.md
|
171
|
+
documentation_uri: https://www.rubydoc.info/gems/onlyoffice_webdriver_wrapper
|
172
|
+
homepage_uri: https://github.com/onlyoffice-testing-robot/onlyoffice_webdriver_wrapper
|
173
|
+
source_code_uri: https://github.com/onlyoffice-testing-robot/onlyoffice_webdriver_wrapper
|
150
174
|
post_install_message:
|
151
175
|
rdoc_options: []
|
152
176
|
require_paths:
|
@@ -155,14 +179,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
155
179
|
requirements:
|
156
180
|
- - ">="
|
157
181
|
- !ruby/object:Gem::Version
|
158
|
-
version: '
|
182
|
+
version: '0'
|
159
183
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
184
|
requirements:
|
161
185
|
- - ">="
|
162
186
|
- !ruby/object:Gem::Version
|
163
187
|
version: '0'
|
164
188
|
requirements: []
|
165
|
-
rubygems_version: 3.
|
189
|
+
rubygems_version: 3.1.4
|
166
190
|
signing_key:
|
167
191
|
specification_version: 4
|
168
192
|
summary: ONLYOFFICE Webdriver Wrapper Gem
|