testcentricity_web 4.1.4 → 4.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee1ff6311bce503168094dbc5546d00419187e6991d67073d590d0cf2dd6beac
4
- data.tar.gz: 5a776195eb96437187dae63eb12f9e6c1cfe0580811dbc369dc09ac75d76e300
3
+ metadata.gz: 022bc17f6fc489c52de9a91fdccb61b722db97cb17b2c21951a2650930adeeb8
4
+ data.tar.gz: cfeefd68b74714b35b738f865b8c5796d4ebe3c302bed0deff208cef34d4f225
5
5
  SHA512:
6
- metadata.gz: 5c05c61753313054175c4d3ae0a36dabe8fd089a2178918e6d796a26806be5af5d6a5020a55658b1951b4d62adfb63725c610afa4c0b4b4612e6e675de015b62
7
- data.tar.gz: 279053b4a2323f9089c183bebf286afb6dbb9be22f9bfee0b22264d2810d1ce77e17b33cec22e26d9b1fd6bdd970c41e2cd1cd1c36a11f010fa0d125fd95e80f
6
+ metadata.gz: 19bb489e029052084ba7c4d3c29bc7a1a5f483039624048860be14ba75d2e8960667410ac7b838a962eac263cd80bb0bf66e881b592f03ce91bcd3ebd45c2e15
7
+ data.tar.gz: 2f45f5c2dda5f485a123527c394f5480e91f1bb123c58efe1a7bf56225388bb0cbed82abbf0c01618d6c370ac7cd6b03f350a338025e06da5597b19989e849b2
data/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
4
 
5
+ ## [4.1.5] - 15-MAR-2022
6
+
7
+ ### Fixed
8
+ * `SelectList.selected?` now correctly returns selected value for custom `selectlist` controls.
9
+
10
+ ### Updated
11
+ * Updated HTML documentation.
12
+
13
+
5
14
  ## [4.1.4] - 09-MAR-2022
6
15
 
7
16
  ### Fixed
@@ -19,7 +28,7 @@ All notable changes to this project will be documented in this file.
19
28
 
20
29
  ## [4.1.2] - 07-MAR-2022
21
30
 
22
- ### Changed
31
+ ### Updated
23
32
  * Updated HTML documentation.
24
33
 
25
34
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- testcentricity_web (4.1.4)
4
+ testcentricity_web (4.1.5)
5
5
  appium_lib
6
6
  browserstack-local
7
7
  capybara (>= 3.1, < 4)
data/README.md CHANGED
@@ -3,9 +3,9 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/testcentricity_web.svg)](https://badge.fury.io/rb/testcentricity_web) [![License (3-Clause BSD)](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg?style=flat-square)](http://opensource.org/licenses/BSD-3-Clause)
4
4
 
5
5
 
6
- The TestCentricity™ Web core generic framework for desktop and mobile web browser-based app testing implements a Page Object and Data
7
- Object Model DSL for use with Cucumber, Capybara (version 3.x), and Selenium-Webdriver (version 4.x). It also facilitates the configuration
8
- of the appropriate Selenium-Webdriver capabilities required to establish a connection with a local or cloud hosted desktop or mobile web browser.
6
+ The TestCentricity™ Web core generic framework for desktop and mobile web browser-based app testing implements a Page Object Model DSL
7
+ for use with Cucumber, Capybara (version 3.x), and Selenium-Webdriver (version 4.x). It also facilitates the configuration of the appropriate
8
+ Selenium-Webdriver capabilities required to establish a connection with a local or cloud hosted desktop or mobile web browser.
9
9
 
10
10
  The TestCentricity™ Web gem supports running automated tests against the following web test targets:
11
11
  * locally hosted desktop browsers (Chrome, Edge, Firefox, Safari, or IE)
@@ -49,7 +49,7 @@ Or install it yourself as:
49
49
  ## Setup
50
50
  ### Using Cucumber
51
51
 
52
- If you are using Cucumber, you need to require the following in your *env.rb* file:
52
+ If you are using Cucumber, you need to require the following in your `env.rb` file:
53
53
 
54
54
  require 'capybara/cucumber'
55
55
  require 'testcentricity_web'
@@ -57,7 +57,7 @@ If you are using Cucumber, you need to require the following in your *env.rb* fi
57
57
 
58
58
  ### Using RSpec
59
59
 
60
- If you are using RSpec instead, you need to require the following in your *env.rb* file:
60
+ If you are using RSpec instead, you need to require the following in your `env.rb` file:
61
61
 
62
62
  require 'capybara'
63
63
  require 'capybara/rspec'
@@ -67,7 +67,7 @@ If you are using RSpec instead, you need to require the following in your *env.r
67
67
  ### Using Appium
68
68
 
69
69
  If you will be running your tests on mobile Safari browsers on simulated iOS devices using Appium and XCode Simulators, you need to require
70
- the following in your *env.rb* file:
70
+ the following in your `env.rb` file:
71
71
 
72
72
  require 'appium_capybara'
73
73
 
@@ -634,6 +634,8 @@ The `verify_ui_states` method supports the following property/state pairs:
634
634
  :class String
635
635
  :value or :caption String
636
636
  :attribute Hash
637
+ :style String
638
+ :tabindex Integer
637
639
 
638
640
  **Text Fields:**
639
641
 
@@ -646,12 +648,17 @@ The `verify_ui_states` method supports the following property/state pairs:
646
648
 
647
649
  **Checkboxes:**
648
650
 
649
- :checked Boolean
651
+ :checked Boolean
652
+ :indeterminate Boolean
650
653
 
651
654
  **Radio Buttons:**
652
655
 
653
656
  :selected Boolean
654
657
 
658
+ **Links:**
659
+
660
+ :href String
661
+
655
662
  **Images**
656
663
 
657
664
  :loaded Boolean
@@ -671,6 +678,8 @@ The `verify_ui_states` method supports the following property/state pairs:
671
678
  :items or :options Array of Strings
672
679
  :itemcount or :optioncount Integer
673
680
  :selected String
681
+ :groupcount Integer
682
+ :group_headings Array of Strings
674
683
 
675
684
  **Tables**
676
685
 
@@ -706,8 +715,6 @@ The `verify_ui_states` method supports the following property/state pairs:
706
715
 
707
716
  The `verify_ui_states` method supports the following ARIA accessibility property/state pairs:
708
717
 
709
- **All Objects:**
710
-
711
718
  :aria_label String
712
719
  :aria_disabled Boolean
713
720
  :aria_labelledby String
@@ -738,8 +745,10 @@ The `verify_ui_states` method supports the following ARIA accessibility property
738
745
  :aria_multiline Boolean
739
746
  :aria_multiselectable Boolean
740
747
  :content_editable Boolean
748
+ :role String
741
749
 
742
750
  #### Comparison States
751
+
743
752
  The `verify_ui_states` method supports comparison states using property/comparison state pairs:
744
753
 
745
754
  object => { property: { comparison_state: value } }
@@ -844,6 +853,126 @@ Baseline translation strings are stored in `.yml` files in the `config/locales/`
844
853
  └── README.md
845
854
 
846
855
 
856
+ ### Working with custom UIElements
857
+
858
+ Many responsive and touch-enabled web based user interfaces are implemented using front-end JavaScript libraries for building user
859
+ interfaces based on UI components. Popular JS libraries include React, Angular, and Ember.js. These stylized and adorned controls can
860
+ present a challenge when attempting to interact with them using Capybara and Selenium based automated tests.
861
+
862
+ #### Radio and Checkbox UIElements
863
+
864
+ Sometimes, radio buttons and checkboxes implemented using JS component libraries cannot be interacted with due to other UI elements
865
+ being overlaid on top of them and the base `input(type='radio')` or `input(type='checkbox')` element not being visible.
866
+
867
+ In the screenshots below of an airline flight search and booking page, the **Roundtrip** and **One-way** radio buttons are adorned with
868
+ `label` elements that also acts as proxies for their associated `input(type='radio')` elements, and they intercept the `click` actions
869
+ that would normally be handled by the `input(type='radio')` elements.
870
+
871
+ <img src="https://i.imgur.com/7bW5u4c.jpg" alt="Roundtrip Radio button Input" title="Roundtrip Radio button Input">
872
+
873
+
874
+ This screenshot shows the `label` element that is overlaid above the **Roundtrip** `input(type='radio')` element.
875
+
876
+ <img src="https://i.imgur.com/2stWiyR.jpg" alt="Roundtrip Radio button Label" title="Roundtrip Radio button Label">
877
+
878
+
879
+ The checkbox controls in this web UI are also adorned with `label` elements that act as proxies for their associated `input(type='checkbox')`
880
+ elements.
881
+
882
+ <img src="https://i.imgur.com/JcOANqZ.jpg" alt="One-way Radio button Label" title="One-way Radio button Label">
883
+
884
+
885
+ The `Radio.define_custom_elements` and `CheckBox.define_custom_elements` methods provide a way to specify the `proxy` and/or `label`
886
+ elements associated with the `input(type='radio')` or `input(type='checkbox')` elements. The `define_custom_elements` method
887
+ should be called from an `initialize` method for the `PageObject` or `PageSection` where the `radio` or `checkbox` element is instantiated.
888
+ The code snippet below demonstrates the use of the `Radio.define_custom_elements` and `CheckBox.define_custom_elements` methods to
889
+ resolve the testability issues posed by the adorned **Roundtrip** and **One-way** radio buttons and the **Flexible dates** checkbox.
890
+
891
+ class FlightBookingPage < TestCentricity::PageObject
892
+ trait(:page_name) { 'Flight Booking Home' }
893
+ trait(:page_locator) { "div[class*='bookerContainer']" }
894
+
895
+ # Flight Booking page UI elements
896
+ radios roundtrip_radio: 'input#roundtrip',
897
+ one_way_radio: 'input#oneway'
898
+ checkbox :flexible_check, 'input#flexibleDates'
899
+
900
+ def initialize
901
+ # define the custom element components for the Round Trip radio button
902
+ radio_spec = { proxy: "label[for='roundtrip']" }
903
+ roundtrip_radio.define_custom_elements(radio_spec)
904
+ # define the custom element components for the One Way radio button
905
+ radio_spec = { proxy: "label[for='oneway']" }
906
+ one_way_radio.define_custom_elements(radio_spec)
907
+ # define the custom element components for the Flexible Date checkbox
908
+ check_spec = { proxy: 'label#flexDatesLabel' }
909
+ flexible_check.define_custom_elements(check_spec)
910
+ end
911
+ end
912
+
913
+
914
+ #### SelectList UIElements
915
+
916
+ The basic HTML `select` element is typically composed of the parent `select` object, and one or more `option` elements representing
917
+ the selectable items in the drop-down list. However, `select` type controls implemented using JS component libraries can be composed
918
+ of multiple elements representing the various components of a drop-down style `selectlist` implementation.
919
+
920
+ In the screenshots below of an airline flight search and booking page, there are no `select` or `option` elements associated with the
921
+ **Month**, **Day**, and **Cabin Type** drop-down style selectors. An inspection of the **Month** selector reveals that it is a `div`
922
+ element that contains a `button` element (outlined in red) for triggering the drop-down list, a `ul` element (outlined in green) that
923
+ contains the drop-down list, and multiple `li` elements (outlined in blue) that represent the list items or options that can be
924
+ selected. The currently selected item or option can be identified by either the `listBoxOptionSelected` snippet in its `class` name or
925
+ the `aria-selected` attribute (outlined in orange).
926
+
927
+ Further examination of the **Day** and **Cabin Type** drop-down style selectors reveal that their composition is identical to the
928
+ **Month** selector.
929
+
930
+ <img src="https://i.imgur.com/LYAC2lh.jpg" alt="Custom SelectList" title="Custom SelectList">
931
+
932
+
933
+ The `SelectList.define_list_elements` method provides a means of specifying the various elements that make up the key components of
934
+ a `selectlist` control. The method accepts a hash of element designators (key) and a CSS or Xpath expression (value) that expression
935
+ that uniquely identifies the element. Valid element designators are `list_item:`, `options_list:`, `list_trigger:`, `selected_item:`,
936
+ `text_field:`, `group_heading:`, and `group_item:`.
937
+
938
+ The code snippet below demonstrates the use of the `SelectList.define_list_elements` method to define the common components that make
939
+ up the **Month**, **Day**, and **Cabin Type** drop-down style selectors. Note the use of the ARIA `role` and `aria-selected` attributes
940
+ as element locators.
941
+
942
+ class FlightBookingPage < TestCentricity::PageObject
943
+ trait(:page_name) { 'Flight Booking Home' }
944
+ trait(:page_locator) { "div[class*='bookerContainer']" }
945
+
946
+ # Flight Booking page UI elements
947
+ selectlists month_select: "div[class*='expandFlexMonth']",
948
+ duration_select: "div[class*='expandFlexDay']",
949
+ cabin_type_select: "div[class*='bookFlightForm__optionField'] > div[class*='app-components-ListBox']"
950
+
951
+ def initialize
952
+ # define the custom list element components for the Month, Duration, and Cabin Type selectlist objects
953
+ list_spec = {
954
+ selected_item: "li[aria-selected=true]",
955
+ options_list: "ul[role='listbox']",
956
+ list_item: "li[role='option']",
957
+ list_trigger: "button[role='combobox']"
958
+ }
959
+ month_select.define_list_elements(list_spec)
960
+ duration_select.define_list_elements(list_spec)
961
+ cabin_type_select.define_list_elements(list_spec)
962
+ end
963
+ end
964
+
965
+
966
+ #### List UIElements
967
+
968
+ The basic HTML list is typically composed of the parent `ul` object, and one or more `li` elements representing the items
969
+ in the list. However, list controls implemented using JS component libraries can be composed of multiple elements representing the
970
+ components of a list implementation.
971
+
972
+ The `List.define_list_elements` method provides a means of specifying the elements that make up the key components of a `list` control.
973
+ The method accepts a hash of element designators (key) and a CSS or Xpath expression (value) that expression that uniquely identifies
974
+ the element. Valid element designators are `list_item:`and `selected_item:`.
975
+
847
976
 
848
977
  ## Instantiating your PageObjects
849
978
 
@@ -1220,7 +1349,7 @@ Once your test environment is properly configured, the following **Environment V
1220
1349
  | `WEB_BROWSER` | Must be set to `appium` |
1221
1350
  | `APP_PLATFORM_NAME` | Must be set to `iOS` |
1222
1351
  | `APP_BROWSER` | Must be set to `Safari` |
1223
- | `APP_VERSION` | Must be set to `15.2`, `14.5`, or which ever iOS version you wish to run within the XCode Simulator |
1352
+ | `APP_VERSION` | Must be set to `15.4`, `14.5`, or which ever iOS version you wish to run within the XCode Simulator |
1224
1353
  | `APP_DEVICE` | Set to iOS device name supported by the iOS Simulator (`iPhone 13 Pro Max`, `iPad Pro (12.9-inch) (5th generation)`, etc.) or name of physically connected iOS device |
1225
1354
  | `DEVICE_TYPE` | Must be set to `phone` or `tablet` |
1226
1355
  | `APP_UDID` | UDID of physically connected iOS device (not used for simulators) |
@@ -1302,6 +1431,13 @@ the code shown below in your `hooks.rb` file.
1302
1431
  end
1303
1432
 
1304
1433
 
1434
+ The `APPIUM_SERVER` environment variable must be set to `run` in order to programmatically start and stop Appium server. This can be
1435
+ set by adding the following to your `cucumber.yml` file and including `-p run_appium` in your command line when starting your Cucumber
1436
+ test suite(s):
1437
+
1438
+ run_appium: APPIUM_SERVER=run
1439
+
1440
+
1305
1441
  Refer to **section 8.6 (Using Browser specific Profiles in cucumber.yml)** below.
1306
1442
 
1307
1443
 
@@ -1548,9 +1684,10 @@ that you intend to connect with.
1548
1684
  #==============
1549
1685
 
1550
1686
  appium_ios: WEB_BROWSER=appium AUTOMATION_ENGINE=XCUITest APP_PLATFORM_NAME="ios" APP_BROWSER="Safari" NEW_COMMAND_TIMEOUT=30 SHOW_SIM_KEYBOARD=false
1551
- app_ios_15: --profile appium_ios APP_VERSION="15.2"
1552
- ipad_pro_12_9_15_sim: --profile app_ios_15 DEVICE_TYPE=tablet APP_DEVICE="iPad Pro (12.9-inch) (5th generation)" <%= desktop %>
1553
- ipad_air_15_sim: --profile app_ios_15 DEVICE_TYPE=tablet APP_DEVICE="iPad Air (4th generation)" <%= desktop %>
1687
+ app_ios_15: --profile appium_ios APP_VERSION="15.4"
1688
+ ipad_pro_12_15_sim: --profile app_ios_15 DEVICE_TYPE=tablet APP_DEVICE="iPad Pro (12.9-inch) (5th generation)"
1689
+ ipad_air_15_sim: --profile app_ios_15 DEVICE_TYPE=tablet APP_DEVICE="iPad Air (5th generation)" <%= desktop %>
1690
+ ipad_15_sim: --profile app_ios_15 DEVICE_TYPE=tablet APP_DEVICE="iPad (9th generation)"
1554
1691
 
1555
1692
 
1556
1693
  #==============
@@ -1686,13 +1823,13 @@ in landscape orientation:
1686
1823
  The following command specifies that Cucumber will run tests against an iPad Pro (12.9-inch) (5th generation) with iOS version 15.2 in an
1687
1824
  XCode Simulator in landscape orientation:
1688
1825
 
1689
- cucumber -p ipad_pro_12_9_15_sim -p landscape
1826
+ cucumber -p ipad_pro_12_15_sim -p landscape
1690
1827
 
1691
1828
  NOTE: Appium must be running prior to executing this command
1692
1829
 
1693
1830
  You can ensure that Appium Server is running by including `-p run_appium` in your command line:
1694
1831
 
1695
- cucumber -p ipad_pro_12_9_15_sim -p landscape -p run_appium
1832
+ cucumber -p ipad_pro_12_15_sim -p landscape -p run_appium
1696
1833
 
1697
1834
 
1698
1835
  The following command specifies that Cucumber will run tests against a remotely hosted Safari web browser running on a macOS Monterey
@@ -1,3 +1,3 @@
1
1
  module TestCentricityWeb
2
- VERSION = '4.1.4'
2
+ VERSION = '4.1.5'
3
3
  end
@@ -49,7 +49,7 @@ module TestCentricity
49
49
  context = case browser.downcase.to_sym
50
50
  when :appium
51
51
  initialize_appium
52
- 'mobile device emulator'
52
+ 'Appium'
53
53
  when :browserstack
54
54
  initialize_browserstack
55
55
  'Browserstack cloud service'
@@ -138,7 +138,6 @@ module TestCentricity
138
138
  Environ.device_orientation = ENV['ORIENTATION'] if ENV['ORIENTATION']
139
139
  Capybara.default_driver = :appium
140
140
  Environ.driver = :appium
141
- @endpoint = 'http://localhost:4723/wd/hub' if @endpoint.nil?
142
141
  desired_capabilities = {
143
142
  platformName: Environ.device_os,
144
143
  platformVersion: Environ.device_os_version,
@@ -190,14 +189,13 @@ module TestCentricity
190
189
  desired_capabilities[:systemPort] = ENV['SYSTEM_PORT'] if ENV['SYSTEM_PORT']
191
190
  end
192
191
 
193
- unless @capabilities.nil?
194
- desired_capabilities = @capabilities
195
- end
192
+ desired_capabilities = @capabilities unless @capabilities.nil?
193
+ # specify endpoint url
194
+ @endpoint = 'http://localhost:4723/wd/hub' if @endpoint.nil?
196
195
 
197
- Capybara.register_driver :appium do |app|
198
- appium_lib_options = { server_url: @endpoint }
196
+ Capybara.register_driver(:appium) do |app|
199
197
  all_options = {
200
- appium_lib: appium_lib_options,
198
+ appium_lib: { server_url: @endpoint },
201
199
  caps: desired_capabilities
202
200
  }
203
201
  Appium::Capybara::Driver.new(app, all_options)
@@ -233,63 +231,18 @@ module TestCentricity
233
231
  when :safari, :ie
234
232
  Capybara::Selenium::Driver.new(app, browser: browser)
235
233
  when :firefox, :firefox_headless
236
- profile = Selenium::WebDriver::Firefox::Profile.new
237
- profile['browser.download.dir'] = @downloads_path
238
- profile['browser.download.folderList'] = 2
239
- profile['browser.download.manager.showWhenStarting'] = false
240
- profile['browser.download.manager.closeWhenDone'] = true
241
- profile['browser.download.manager.showAlertOnComplete'] = false
242
- profile['browser.download.manager.alertOnEXEOpen'] = false
243
- profile['browser.download.manager.useWindow'] = false
244
- profile['browser.helperApps.alwaysAsk.force'] = false
245
- profile['pdfjs.disabled'] = true
246
-
247
- mime_types = ENV['MIME_TYPES'] || 'images/jpeg, application/pdf, application/octet-stream'
248
- profile['browser.helperApps.neverAsk.saveToDisk'] = mime_types
249
-
250
- profile['intl.accept_languages'] = ENV['LOCALE'] if ENV['LOCALE']
251
- options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
252
- options.args << '--headless' if browser == :firefox_headless
234
+ options = firefox_options(browser)
253
235
  Capybara::Selenium::Driver.new(app, browser: :firefox, capabilities: [options])
254
236
  when :chrome, :chrome_headless
255
- options = Selenium::WebDriver::Chrome::Options.new(options: {'excludeSwitches' => ['enable-automation']})
256
- prefs = {
257
- prompt_for_download: false,
258
- directory_upgrade: true,
259
- default_directory: @downloads_path
260
- }
261
- options.add_preference(:download, prefs)
262
- options.add_argument('--disable-dev-shm-usage')
263
- options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
264
- if browser == :chrome_headless
265
- options.add_argument('--headless')
266
- options.add_argument('--disable-gpu')
267
- options.add_argument('--no-sandbox')
268
- end
269
-
237
+ options = chrome_edge_options(browser)
270
238
  Capybara::Selenium::Driver.new(app, browser: :chrome, capabilities: [options])
271
239
  when :edge, :edge_headless
272
- options = Selenium::WebDriver::Edge::Options.new(options: {'excludeSwitches' => ['enable-automation']})
273
- prefs = {
274
- prompt_for_download: false,
275
- directory_upgrade: true,
276
- default_directory: @downloads_path
277
- }
278
- options.add_preference(:download, prefs)
279
- options.add_argument('--disable-dev-shm-usage')
280
- options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
281
- if browser == :edge_headless
282
- options.add_argument('--headless')
283
- options.add_argument('--disable-gpu')
284
- options.add_argument('--no-sandbox')
285
- end
286
-
240
+ options = chrome_edge_options(browser)
287
241
  Capybara::Selenium::Driver.new(app, browser: :edge, capabilities: [options])
288
242
  else
289
243
  if ENV['HOST_BROWSER'] && ENV['HOST_BROWSER'].downcase.to_sym == :chrome
290
244
  user_agent = Browsers.mobile_device_agent(ENV['WEB_BROWSER'])
291
245
  options = Selenium::WebDriver::Chrome::Options.new(options: {'excludeSwitches' => ['enable-automation']})
292
- options.add_argument('--disable-infobars')
293
246
  options.add_argument('--disable-dev-shm-usage')
294
247
  options.add_argument("--user-agent='#{user_agent}'")
295
248
  options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
@@ -452,74 +405,31 @@ module TestCentricity
452
405
  Environ.grid = :selenium_grid
453
406
  browser = ENV['WEB_BROWSER'].downcase.to_sym
454
407
  @endpoint = ENV['REMOTE_ENDPOINT'] || 'http://127.0.0.1:4444/wd/hub' if @endpoint.nil?
455
- Capybara.register_driver :remote_browser do |app|
456
- case browser
457
- when :safari
458
- options = Selenium::WebDriver::Safari::Options.new
459
- when :ie
460
- options = Selenium::WebDriver::IE::Options.new
461
- when :firefox, :firefox_headless
462
- profile = Selenium::WebDriver::Firefox::Profile.new
463
- profile['browser.download.dir'] = @downloads_path
464
- profile['browser.download.folderList'] = 2
465
- profile['browser.download.manager.showWhenStarting'] = false
466
- profile['browser.download.manager.closeWhenDone'] = true
467
- profile['browser.download.manager.showAlertOnComplete'] = false
468
- profile['browser.download.manager.alertOnEXEOpen'] = false
469
- profile['browser.download.manager.useWindow'] = false
470
- profile['browser.helperApps.alwaysAsk.force'] = false
471
- profile['pdfjs.disabled'] = true
472
-
473
- mime_types = ENV['MIME_TYPES'] || 'images/jpeg, application/pdf, application/octet-stream'
474
- profile['browser.helperApps.neverAsk.saveToDisk'] = mime_types
475
-
476
- profile['intl.accept_languages'] = ENV['LOCALE'] if ENV['LOCALE']
477
- options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
478
- options.args << '--headless' if browser == :firefox_headless
479
- when :chrome, :chrome_headless
408
+
409
+ case browser
410
+ when :safari
411
+ options = Selenium::WebDriver::Safari::Options.new
412
+ when :ie
413
+ options = Selenium::WebDriver::IE::Options.new
414
+ when :firefox, :firefox_headless
415
+ options = firefox_options(browser)
416
+ when :chrome, :chrome_headless, :edge, :edge_headless
417
+ options = chrome_edge_options(browser)
418
+ else
419
+ if ENV['HOST_BROWSER'] && ENV['HOST_BROWSER'].downcase.to_sym == :chrome
420
+ Environ.platform = :mobile
421
+ Environ.device_name = Browsers.mobile_device_name(ENV['WEB_BROWSER'])
422
+ user_agent = Browsers.mobile_device_agent(ENV['WEB_BROWSER'])
480
423
  options = Selenium::WebDriver::Chrome::Options.new(options: {'excludeSwitches' => ['enable-automation']})
481
- prefs = {
482
- prompt_for_download: false,
483
- directory_upgrade: true,
484
- default_directory: @downloads_path
485
- }
486
- options.add_preference(:download, prefs)
487
- options.add_argument('--disable-dev-shm-usage')
488
- options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
489
- if browser == :chrome_headless
490
- options.add_argument('--headless')
491
- options.add_argument('--disable-gpu')
492
- options.add_argument('--no-sandbox')
493
- end
494
- when :edge, :edge_headless
495
- options = Selenium::WebDriver::Edge::Options.new(options: {'excludeSwitches' => ['enable-automation']})
496
- prefs = {
497
- prompt_for_download: false,
498
- directory_upgrade: true,
499
- default_directory: @downloads_path
500
- }
501
- options.add_preference(:download, prefs)
502
424
  options.add_argument('--disable-dev-shm-usage')
425
+ options.add_argument("--user-agent='#{user_agent}'")
503
426
  options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
504
- if browser == :edge_headless
505
- options.add_argument('--headless')
506
- options.add_argument('--disable-gpu')
507
- options.add_argument('--no-sandbox')
508
- end
509
427
  else
510
- if ENV['HOST_BROWSER'] && ENV['HOST_BROWSER'].downcase.to_sym == :chrome
511
- Environ.platform = :mobile
512
- Environ.device_name = Browsers.mobile_device_name(ENV['WEB_BROWSER'])
513
- user_agent = Browsers.mobile_device_agent(ENV['WEB_BROWSER'])
514
- options = Selenium::WebDriver::Chrome::Options.new(options: {'excludeSwitches' => ['enable-automation']})
515
- options.add_argument('--disable-infobars')
516
- options.add_argument('--disable-dev-shm-usage')
517
- options.add_argument("--user-agent='#{user_agent}'")
518
- options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
519
- else
520
- raise "Requested browser '#{browser}' is not supported on Selenium Grid"
521
- end
428
+ raise "Requested browser '#{browser}' is not supported on Selenium Grid"
522
429
  end
430
+ end
431
+
432
+ Capybara.register_driver :remote_browser do |app|
523
433
  Capybara::Selenium::Driver.new(app,
524
434
  browser: :remote,
525
435
  url: @endpoint,
@@ -645,6 +555,50 @@ module TestCentricity
645
555
  config_file_uploads unless ENV['TB_PLATFORM']
646
556
  end
647
557
 
558
+ def self.chrome_edge_options(browser)
559
+ options = case browser
560
+ when :chrome, :chrome_headless
561
+ Selenium::WebDriver::Chrome::Options.new(options: {'excludeSwitches' => ['enable-automation']})
562
+ when :edge, :edge_headless
563
+ Selenium::WebDriver::Edge::Options.new(options: {'excludeSwitches' => ['enable-automation']})
564
+ end
565
+ prefs = {
566
+ prompt_for_download: false,
567
+ directory_upgrade: true,
568
+ default_directory: @downloads_path
569
+ }
570
+ options.add_preference(:download, prefs)
571
+ options.add_argument('--disable-dev-shm-usage')
572
+ options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
573
+ if browser == :chrome_headless || browser == :edge_headless
574
+ options.add_argument('--headless')
575
+ options.add_argument('--disable-gpu')
576
+ options.add_argument('--no-sandbox')
577
+ end
578
+ options
579
+ end
580
+
581
+ def self.firefox_options(browser)
582
+ profile = Selenium::WebDriver::Firefox::Profile.new
583
+ profile['browser.download.dir'] = @downloads_path
584
+ profile['browser.download.folderList'] = 2
585
+ profile['browser.download.manager.showWhenStarting'] = false
586
+ profile['browser.download.manager.closeWhenDone'] = true
587
+ profile['browser.download.manager.showAlertOnComplete'] = false
588
+ profile['browser.download.manager.alertOnEXEOpen'] = false
589
+ profile['browser.download.manager.useWindow'] = false
590
+ profile['browser.helperApps.alwaysAsk.force'] = false
591
+ profile['pdfjs.disabled'] = true
592
+
593
+ mime_types = ENV['MIME_TYPES'] || 'images/jpeg, application/pdf, application/octet-stream'
594
+ profile['browser.helperApps.neverAsk.saveToDisk'] = mime_types
595
+
596
+ profile['intl.accept_languages'] = ENV['LOCALE'] if ENV['LOCALE']
597
+ options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
598
+ options.args << '--headless' if browser == :firefox_headless
599
+ options
600
+ end
601
+
648
602
  def self.test_context_message
649
603
  context_message = if ENV['TEST_CONTEXT']
650
604
  "#{Environ.test_environment.to_s.upcase} - #{ENV['TEST_CONTEXT']}"
@@ -662,7 +616,10 @@ module TestCentricity
662
616
  def self.register_remote_driver(driver, browser, options)
663
617
  Capybara.register_driver driver do |app|
664
618
  capabilities = Selenium::WebDriver::Remote::Capabilities.send(browser.gsub(/\s+/, '_').downcase.to_sym, options)
665
- Capybara::Selenium::Driver.new(app, browser: :remote, url: @endpoint, capabilities: capabilities)
619
+ Capybara::Selenium::Driver.new(app,
620
+ browser: :remote,
621
+ url: @endpoint,
622
+ capabilities: capabilities)
666
623
  end
667
624
 
668
625
  Environ.browser = browser
@@ -246,13 +246,16 @@ module TestCentricity
246
246
  def get_selected_option
247
247
  @base_object, = find_element
248
248
  object_not_found_exception(@base_object, nil)
249
- if @base_object.first(:css, @list_item, minimum: 0)
250
- @base_object.first(:css, @selected_item).text
251
- elsif @base_object.first(:css, @selected_item, minimum: 0)
252
- @base_object.first(:css, @selected_item).text
253
- else
254
- @base_object.first('option[selected]', visible: :all).text
255
- end
249
+ trigger_list
250
+ selection = if @base_object.first(:css, @list_item, minimum: 0, wait: 1, visible: :all)
251
+ @base_object.first(:css, @selected_item, wait: 1, visible: :all).text
252
+ elsif @base_object.first(:css, @selected_item, minimum: 0, wait: 1, visible: :all)
253
+ @base_object.first(:css, @selected_item, visible: :all).text
254
+ else
255
+ @base_object.first('option[selected]', visible: :all).text
256
+ end
257
+ trigger_list
258
+ selection
256
259
  end
257
260
 
258
261
  alias selected? get_selected_option
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: testcentricity_web
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.4
4
+ version: 4.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - A.J. Mrozinski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-09 00:00:00.000000000 Z
11
+ date: 2022-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler