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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rudra.rb +145 -28
  3. metadata +22 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f065383cc3c1a776dccc5708a77f627383aaa63f4198b087adad977271f713d6
4
- data.tar.gz: 9fc4e3d993f3d3a1b4fb53d57b146df87fe8fa5e561308b726a3c8c46dd5ac1d
3
+ metadata.gz: ff3f69221a8e01fb0c0bf5a517c11547872f475b4cdc7aa551a26f81929c8373
4
+ data.tar.gz: e039db5f85576af890d9b58f8deed4f7f30cf09ea474d8b2226c6574cad9c115
5
5
  SHA512:
6
- metadata.gz: 9f80dd1cc85e183b9ac7ac2be6831a2e1ac56be27ab884133fcbfc4b0f87e03a23d4d9443bd933cfef69292c881d968b2033d3af8cd5a72c909ba8474afcce03
7
- data.tar.gz: ad1f215b1ea9c9f6d16e387f95f1a5f9c087845c2db3239d0f64ea719e94241805578fe1a3589b69dafc0207fcc10b6589677259ecb87939752ab0fd0d5c9a52
6
+ metadata.gz: a632f5ee68fa9417a78e86642246c47d2b4480292ca4816471b8f948458d7c6444150ccb7eb1a65fe8d7167f25dca32e1271f97cd725dbc86643362d763d4361
7
+ data.tar.gz: 9edc12b61b22302ef0d80698a682d859a124acaa7c3d121d87353f83c84fef948f9fa93971ce85074c4b7faf52b27bf9ebef4bdedcb14429a8ef7222b73854f3
@@ -1,10 +1,5 @@
1
1
  require 'selenium-webdriver'
2
- require 'webdrivers/chromedriver'
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 log_prefix timeout verbose
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, :log_prefix, :timeout, :verbose
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] :log_prefix (' - ') log prefix
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 (true) verbose mode
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, true)
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
- abort("Failed to find element: #{locator}") unless element
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
- abort("Failed to find elements: #{locator}")
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 the given path
275
- # @param [String] png_path the path of PNG screenshot
276
- def save_screenshot(png_path)
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
- png_path.end_with?('.png') ? png_path : "#{png_path}.png"
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).property(attribute)
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
- find_element(locator).click
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
- attr_writer :main_label
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
- options.add_argument('--headless') if headless
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
- abort("Cannot parse locator: #{locator}") unless HOWS.include?(how)
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 @verbose && caller_locations(2, 1).first.label == main_label
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 @log_prefix + (
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.0.14
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-01 00:00:00.000000000 Z
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