rudra 1.0.14 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rudra.rb +145 -28
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff3f69221a8e01fb0c0bf5a517c11547872f475b4cdc7aa551a26f81929c8373
|
4
|
+
data.tar.gz: e039db5f85576af890d9b58f8deed4f7f30cf09ea474d8b2226c6574cad9c115
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a632f5ee68fa9417a78e86642246c47d2b4480292ca4816471b8f948458d7c6444150ccb7eb1a65fe8d7167f25dca32e1271f97cd725dbc86643362d763d4361
|
7
|
+
data.tar.gz: 9edc12b61b22302ef0d80698a682d859a124acaa7c3d121d87353f83c84fef948f9fa93971ce85074c4b7faf52b27bf9ebef4bdedcb14429a8ef7222b73854f3
|
data/lib/rudra.rb
CHANGED
@@ -1,10 +1,5 @@
|
|
1
1
|
require 'selenium-webdriver'
|
2
|
-
require 'webdrivers
|
3
|
-
require 'webdrivers/geckodriver'
|
4
|
-
require 'webdrivers/iedriver'
|
5
|
-
|
6
|
-
# Selenium::WebDriver::Chrome::Service.driver_path = './webdrivers/chromedriver'
|
7
|
-
# Selenium::WebDriver::Firefox::Service.driver_path = './webdrivers/geckodriver'
|
2
|
+
require 'webdrivers'
|
8
3
|
|
9
4
|
# Selenium IDE-like WebDriver based upon Ruby binding
|
10
5
|
# @author Aaron Chen
|
@@ -13,8 +8,13 @@ require 'webdrivers/iedriver'
|
|
13
8
|
# of the chosen browser
|
14
9
|
# @attr_reader [String] install_dir The install directory of WebDrivers
|
15
10
|
# @attr_reader [String] locale The browser locale
|
11
|
+
# @attr_reader [Boolean] headless Headless mode for Google Chrome
|
12
|
+
# @attr_reader [String] window_size Chrome window size when headless
|
13
|
+
# @attr_reader [String] screen_dir The screenshot directory of save_screenshot
|
14
|
+
# @attr_reader [String] log_prefix Prefix for logging descriptions and methods
|
16
15
|
# @attr_reader [Integer] timeout The driver timeout
|
17
|
-
# @attr_reader [Boolean] verbose Verbose mode
|
16
|
+
# @attr_reader [Boolean] verbose Turn on/off Verbose mode
|
17
|
+
# @attr_reader [Boolean] silent Turn off Turn on/off descriptions
|
18
18
|
class Rudra
|
19
19
|
# Supported Browsers
|
20
20
|
BROWSERS = %i[chrome firefox ie safari].freeze
|
@@ -28,11 +28,13 @@ class Rudra
|
|
28
28
|
# Attributes
|
29
29
|
ATTRIBUTES = %i[
|
30
30
|
browser driver install_dir locale
|
31
|
-
headless
|
31
|
+
headless window_size screen_dir
|
32
|
+
log_prefix timeout verbose silent
|
32
33
|
].freeze
|
33
34
|
|
34
35
|
attr_reader :browser, :driver, :install_dir, :locale,
|
35
|
-
:headless, :
|
36
|
+
:headless, :window_size, :screen_dir,
|
37
|
+
:log_prefix, :timeout, :verbose, :silent
|
36
38
|
|
37
39
|
# Initialize an instance of Rudra
|
38
40
|
# @param [Hash] options the options to initialize Rudra
|
@@ -42,16 +44,22 @@ class Rudra
|
|
42
44
|
# directory of WebDrivers
|
43
45
|
# @option options [Symbol] :locale (:en) the browser locale
|
44
46
|
# @option options [Boolean] :headless (false) headless mode
|
45
|
-
# @option options [String] :
|
47
|
+
# @option options [String] :window_size ('1280,720') window size when headless
|
48
|
+
# @option options [String] :screen_dir ('./screens/') the location of screenshots
|
49
|
+
# @option options [String] :log_prefix (' - ') prefix for logging descriptions and methods
|
46
50
|
# @option options [Integer] :timeout (30) implicit_wait timeout
|
47
|
-
# @option options [Boolean] :verbose (
|
51
|
+
# @option options [Boolean] :verbose (false) Turn on/off verbose mode
|
52
|
+
# @option options [Boolean] :silent (false) Turn on/off descriptions
|
48
53
|
def initialize(options = {})
|
49
54
|
self.browser = options.fetch(:browser, :chrome)
|
50
55
|
self.install_dir = options.fetch(:install_dir, './webdrivers/')
|
51
56
|
self.locale = options.fetch(:locale, :en)
|
52
57
|
self.headless = options.fetch(:headless, false)
|
58
|
+
self.window_size = options.fetch(:window_size, '1280,720')
|
59
|
+
self.screen_dir = options.fetch(:screen_dir, './screens/')
|
53
60
|
self.log_prefix = options.fetch(:log_prefix, ' - ')
|
54
|
-
self.verbose = options.fetch(:verbose,
|
61
|
+
self.verbose = options.fetch(:verbose, false)
|
62
|
+
self.silent = options.fetch(:silent, false)
|
55
63
|
self.main_label = caller_locations(2, 1).first.label
|
56
64
|
|
57
65
|
initialize_driver
|
@@ -97,6 +105,7 @@ class Rudra
|
|
97
105
|
end
|
98
106
|
|
99
107
|
# Send keys to an alert
|
108
|
+
# @param [String] keys keystrokes to send
|
100
109
|
def alert_send_keys(keys)
|
101
110
|
switch_to_alert.send_keys(keys)
|
102
111
|
end
|
@@ -168,7 +177,7 @@ class Rudra
|
|
168
177
|
|
169
178
|
element ||= driver.find_element(how, what)
|
170
179
|
|
171
|
-
|
180
|
+
raise Selenium::WebDriver::Error::NoSuchElementError, "Failed to find element: #{locator}" unless element
|
172
181
|
|
173
182
|
wait_for { element.displayed? }
|
174
183
|
|
@@ -180,8 +189,11 @@ class Rudra
|
|
180
189
|
# @return [Array<Selenium::WebDriver::Element>] the elements found
|
181
190
|
def find_elements(locator)
|
182
191
|
how, what = parse_locator(locator)
|
183
|
-
driver.find_elements(how, what)
|
184
|
-
|
192
|
+
elements = driver.find_elements(how, what)
|
193
|
+
|
194
|
+
raise Selenium::WebDriver::Error::NoSuchElementError, "Failed to find elements: #{locator}" if elements.empty?
|
195
|
+
|
196
|
+
elements
|
185
197
|
end
|
186
198
|
|
187
199
|
# Move forward a single entry in the browser's history
|
@@ -201,7 +213,7 @@ class Rudra
|
|
201
213
|
|
202
214
|
# Maximize the current window
|
203
215
|
def maximize
|
204
|
-
driver.manage.window.maximize
|
216
|
+
driver.manage.window.maximize unless headless
|
205
217
|
end
|
206
218
|
|
207
219
|
# Maximize the current window to the size of the screen
|
@@ -259,6 +271,12 @@ class Rudra
|
|
259
271
|
driver.page_source
|
260
272
|
end
|
261
273
|
|
274
|
+
# Print description in the console
|
275
|
+
# @param [String] description description to show
|
276
|
+
def puts(description)
|
277
|
+
$stdout.puts "#{log_prefix}#{description.chomp}" unless silent
|
278
|
+
end
|
279
|
+
|
262
280
|
# Refresh the current pagef
|
263
281
|
def refresh
|
264
282
|
driver.navigate.refresh
|
@@ -271,11 +289,15 @@ class Rudra
|
|
271
289
|
driver.manage.window.resize_to(width, height)
|
272
290
|
end
|
273
291
|
|
274
|
-
# Save a PNG screenshot to
|
275
|
-
# @param [String]
|
276
|
-
def save_screenshot(
|
292
|
+
# Save a PNG screenshot to file
|
293
|
+
# @param [String] filename the filename of PNG screenshot
|
294
|
+
def save_screenshot(filename)
|
295
|
+
mkdir(@screen_dir) unless Dir.exist?(@screen_dir)
|
277
296
|
driver.save_screenshot(
|
278
|
-
|
297
|
+
File.join(
|
298
|
+
@screen_dir,
|
299
|
+
filename.end_with?('.png') ? filename : "#{filename}.png"
|
300
|
+
)
|
279
301
|
)
|
280
302
|
end
|
281
303
|
|
@@ -291,6 +313,7 @@ class Rudra
|
|
291
313
|
end
|
292
314
|
|
293
315
|
# Switch to the frame with the given id
|
316
|
+
# @param [String] id the frame id
|
294
317
|
def switch_to_frame(id)
|
295
318
|
driver.switch_to.frame(id)
|
296
319
|
end
|
@@ -326,6 +349,48 @@ class Rudra
|
|
326
349
|
wait_for { find_element(locator).enabled? }
|
327
350
|
end
|
328
351
|
|
352
|
+
# Wait until the element, identified by locator, is found in frame
|
353
|
+
# @param [String] frame_id the frame id
|
354
|
+
# @param [String] locator the locator to identify the element
|
355
|
+
def wait_for_element_found_in_frame(frame_id, locator)
|
356
|
+
switch_to_frame frame_id
|
357
|
+
|
358
|
+
how, what = parse_locator(locator)
|
359
|
+
|
360
|
+
wait_for do
|
361
|
+
begin
|
362
|
+
driver.find_element(how, what)
|
363
|
+
rescue Selenium::WebDriver::Error::NoSuchWindowError
|
364
|
+
false
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
# Wait (in seconds) until the element is not displayed
|
370
|
+
# @param [String, Selenium::WebDriver::Element] locator the locator to
|
371
|
+
# identify the element or Selenium::WebDriver::Element
|
372
|
+
# @param [Integer] seconds seconds before timed out
|
373
|
+
def wait_for_not_visible(locator, seconds = 2)
|
374
|
+
how, what = parse_locator(locator)
|
375
|
+
|
376
|
+
begin
|
377
|
+
wait_for(seconds) do
|
378
|
+
begin
|
379
|
+
elements = driver.find_elements(how, what)
|
380
|
+
elements.empty? || elements.map(&:displayed?).none?
|
381
|
+
rescue Selenium::WebDriver::Error::NoSuchElementError
|
382
|
+
true
|
383
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
384
|
+
false
|
385
|
+
end
|
386
|
+
end
|
387
|
+
rescue Selenium::WebDriver::Error::TimeoutError
|
388
|
+
true
|
389
|
+
rescue Net::ReadTimeout
|
390
|
+
true
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
329
394
|
# Wait until the title of the page including the given string
|
330
395
|
# @param [String] string the string to compare
|
331
396
|
def wait_for_title(string)
|
@@ -374,7 +439,7 @@ class Rudra
|
|
374
439
|
# @param [String] attribute the name of the attribute
|
375
440
|
# @return [String, nil] attribute value
|
376
441
|
def attribute(locator, attribute)
|
377
|
-
find_element(locator).
|
442
|
+
find_element(locator).attribute(attribute)
|
378
443
|
end
|
379
444
|
|
380
445
|
# If the element, identified by locator, has the given attribute
|
@@ -409,7 +474,13 @@ class Rudra
|
|
409
474
|
# @param [String, Selenium::WebDriver::Element] locator the locator to
|
410
475
|
# identify the element or Selenium::WebDriver::Element
|
411
476
|
def click(locator)
|
412
|
-
|
477
|
+
wait_for do
|
478
|
+
begin
|
479
|
+
find_element(locator).click.nil?
|
480
|
+
rescue Selenium::WebDriver::Error::ElementClickInterceptedError
|
481
|
+
false
|
482
|
+
end
|
483
|
+
end
|
413
484
|
end
|
414
485
|
|
415
486
|
# Click the given element, identified by locator, with an offset
|
@@ -722,6 +793,38 @@ class Rudra
|
|
722
793
|
), find_element(locator), event)
|
723
794
|
end
|
724
795
|
|
796
|
+
# Wait until the element, identified by locator, attribute has value
|
797
|
+
# @param [String, Selenium::WebDriver::Element] locator the locator to identify the element
|
798
|
+
# @param [String] attribute the name of the attribute
|
799
|
+
# @param [String] value the value of the attribute
|
800
|
+
def wait_for_attribute_to_include(locator, attribute, value)
|
801
|
+
how, what = parse_locator(locator)
|
802
|
+
|
803
|
+
wait_for do
|
804
|
+
begin
|
805
|
+
driver.find_element(how, what)&.attribute(attribute)&.downcase&.include?(value.downcase)
|
806
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
807
|
+
false
|
808
|
+
end
|
809
|
+
end
|
810
|
+
end
|
811
|
+
|
812
|
+
# Wait until the element, identified by locator, excluding string in text
|
813
|
+
# @param [String, Selenium::WebDriver::Element] locator the locator to
|
814
|
+
# identify the element or Selenium::WebDriver::Element
|
815
|
+
# @param [String] string the string to exclude
|
816
|
+
def wait_for_text_to_exclude(locator, string)
|
817
|
+
wait_for { text(locator).exclude?(string) }
|
818
|
+
end
|
819
|
+
|
820
|
+
# Wait until the element, identified by locator, including string in text
|
821
|
+
# @param [String, Selenium::WebDriver::Element] locator the locator to
|
822
|
+
# identify the element or Selenium::WebDriver::Element
|
823
|
+
# @param [String] string the string to compare
|
824
|
+
def wait_for_text_to_include(locator, string)
|
825
|
+
wait_for { text(locator).include?(string) }
|
826
|
+
end
|
827
|
+
|
725
828
|
#
|
726
829
|
# Tool Functions
|
727
830
|
#
|
@@ -1059,7 +1162,7 @@ class Rudra
|
|
1059
1162
|
end
|
1060
1163
|
|
1061
1164
|
(instance_methods - superclass.instance_methods).map do |method_name|
|
1062
|
-
next if private_method_defined?(method_name) || ATTRIBUTES.include?(method_name)
|
1165
|
+
next if private_method_defined?(method_name) || ATTRIBUTES.include?(method_name) || method_name == :puts
|
1063
1166
|
|
1064
1167
|
original_method = instance_method(method_name)
|
1065
1168
|
|
@@ -1071,7 +1174,8 @@ class Rudra
|
|
1071
1174
|
|
1072
1175
|
private
|
1073
1176
|
|
1074
|
-
|
1177
|
+
attr_accessor :main_label
|
1178
|
+
attr_writer :silent, :window_size
|
1075
1179
|
|
1076
1180
|
def browser=(brw)
|
1077
1181
|
unless BROWSERS.include?(brw)
|
@@ -1098,6 +1202,10 @@ class Rudra
|
|
1098
1202
|
@headless = true?(mode)
|
1099
1203
|
end
|
1100
1204
|
|
1205
|
+
def screen_dir=(path)
|
1206
|
+
@screen_dir = File.join(path, @locale.to_s)
|
1207
|
+
end
|
1208
|
+
|
1101
1209
|
def log_prefix=(prefix)
|
1102
1210
|
@log_prefix = prefix.chomp
|
1103
1211
|
end
|
@@ -1120,6 +1228,8 @@ class Rudra
|
|
1120
1228
|
def initialize_driver
|
1121
1229
|
@driver = if browser == :chrome
|
1122
1230
|
Selenium::WebDriver.for(:chrome, options: chrome_options)
|
1231
|
+
# elsif browser == :edge
|
1232
|
+
# Selenium::WebDriver.for(:edge, options: edge_options)
|
1123
1233
|
elsif browser == :firefox
|
1124
1234
|
Selenium::WebDriver.for(:firefox, options: firefox_options)
|
1125
1235
|
elsif browser == :ie
|
@@ -1132,7 +1242,10 @@ class Rudra
|
|
1132
1242
|
def chrome_options
|
1133
1243
|
options = Selenium::WebDriver::Chrome::Options.new
|
1134
1244
|
options.add_argument('--disable-notifications')
|
1135
|
-
|
1245
|
+
if headless
|
1246
|
+
options.add_argument('--headless')
|
1247
|
+
options.add_argument("--window-size=#{window_size}")
|
1248
|
+
end
|
1136
1249
|
options.add_option(
|
1137
1250
|
'excludeSwitches',
|
1138
1251
|
%w[enable-automation enable-logging]
|
@@ -1141,6 +1254,10 @@ class Rudra
|
|
1141
1254
|
options
|
1142
1255
|
end
|
1143
1256
|
|
1257
|
+
# def edge_options
|
1258
|
+
# Selenium::WebDriver::Edge::Options.new
|
1259
|
+
# end
|
1260
|
+
|
1144
1261
|
def firefox_options
|
1145
1262
|
options = Selenium::WebDriver::Firefox::Options.new
|
1146
1263
|
options.add_preference('intl.accept_languages', locale)
|
@@ -1173,17 +1290,17 @@ class Rudra
|
|
1173
1290
|
how.to_sym
|
1174
1291
|
end
|
1175
1292
|
|
1176
|
-
|
1293
|
+
raise Selenium::WebDriver::Error::InvalidSelectorError, "Cannot parse locator: #{locator}" unless HOWS.include?(how)
|
1177
1294
|
|
1178
1295
|
[how, what]
|
1179
1296
|
end
|
1180
1297
|
|
1181
1298
|
def log(method_name, *args)
|
1182
|
-
return unless
|
1299
|
+
return unless verbose && caller_locations(2, 1).first.label == main_label
|
1183
1300
|
|
1184
1301
|
arguments = args.map(&:to_s).join(', ')
|
1185
1302
|
|
1186
|
-
puts
|
1303
|
+
puts log_prefix + (
|
1187
1304
|
arguments.empty? ? method_name.to_s : "#{method_name}(#{arguments})"
|
1188
1305
|
)
|
1189
1306
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rudra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Chen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-06-
|
11
|
+
date: 2020-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: yard
|
@@ -24,6 +24,26 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.9.25
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.9.0
|
34
|
+
- - "~>"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '3.9'
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 3.9.0
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3.9'
|
27
47
|
- !ruby/object:Gem::Dependency
|
28
48
|
name: selenium-webdriver
|
29
49
|
requirement: !ruby/object:Gem::Requirement
|