testcentricity_web 4.1.4 → 4.1.5
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/CHANGELOG.md +10 -1
- data/Gemfile.lock +1 -1
- data/README.md +152 -15
- data/lib/testcentricity_web/version.rb +1 -1
- data/lib/testcentricity_web/web_core/webdriver_helper.rb +77 -120
- data/lib/testcentricity_web/web_elements/select_list.rb +10 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 022bc17f6fc489c52de9a91fdccb61b722db97cb17b2c21951a2650930adeeb8
|
4
|
+
data.tar.gz: cfeefd68b74714b35b738f865b8c5796d4ebe3c302bed0deff208cef34d4f225
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
###
|
31
|
+
### Updated
|
23
32
|
* Updated HTML documentation.
|
24
33
|
|
25
34
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -3,9 +3,9 @@
|
|
3
3
|
[](https://badge.fury.io/rb/testcentricity_web) [](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
|
7
|
-
|
8
|
-
|
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
|
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
|
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
|
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
|
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.
|
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.
|
1552
|
-
|
1553
|
-
ipad_air_15_sim:
|
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
|
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
|
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
|
@@ -49,7 +49,7 @@ module TestCentricity
|
|
49
49
|
context = case browser.downcase.to_sym
|
50
50
|
when :appium
|
51
51
|
initialize_appium
|
52
|
-
'
|
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
|
-
|
195
|
-
|
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
|
198
|
-
appium_lib_options = { server_url: @endpoint }
|
196
|
+
Capybara.register_driver(:appium) do |app|
|
199
197
|
all_options = {
|
200
|
-
appium_lib:
|
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
|
-
|
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 =
|
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 =
|
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
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
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
|
-
|
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,
|
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
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
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
|
+
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-
|
11
|
+
date: 2022-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|