testcentricity_web 4.1.4 → 4.1.7
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/.gitignore +18 -0
- data/.simplecov +5 -0
- data/CHANGELOG.md +43 -1
- data/Gemfile.lock +60 -2
- data/README.md +166 -21
- data/Rakefile +60 -1
- data/config/cucumber.yml +163 -0
- data/config/test_data/data.json +12 -0
- data/config/test_data/data.xls +0 -0
- data/config/test_data/data.yml +12 -0
- data/docker-compose-v3.yml +48 -0
- data/features/basic_test_page_css.feature +35 -0
- data/features/basic_test_page_xpath.feature +27 -0
- data/features/media_players.feature +87 -0
- data/features/step_definitions/generic_steps.rb.rb +44 -0
- data/features/step_definitions/media_steps.rb +30 -0
- data/features/support/env.rb +50 -0
- data/features/support/hooks.rb +245 -0
- data/features/support/pages/base_test_page.rb +11 -0
- data/features/support/pages/basic_css_test_page.rb +52 -0
- data/features/support/pages/basic_test_page.rb +297 -0
- data/features/support/pages/basic_xpath_test_page.rb +53 -0
- data/features/support/pages/custom_controls_page.rb +16 -0
- data/features/support/pages/indexed_sections_page.rb +16 -0
- data/features/support/pages/media_test_page.rb +195 -0
- data/features/support/sections/header_nav.rb +28 -0
- data/features/support/world_data.rb +12 -0
- data/features/support/world_pages.rb +18 -0
- data/lib/testcentricity_web/data_objects/environment.rb +16 -0
- data/lib/testcentricity_web/version.rb +1 -1
- data/lib/testcentricity_web/web_core/page_object.rb +8 -8
- data/lib/testcentricity_web/web_core/page_objects_helper.rb +41 -8
- data/lib/testcentricity_web/web_core/page_section.rb +1 -16
- data/lib/testcentricity_web/web_core/webdriver_helper.rb +77 -120
- data/lib/testcentricity_web/web_elements/checkbox.rb +3 -4
- data/lib/testcentricity_web/web_elements/media.rb +50 -4
- data/lib/testcentricity_web/web_elements/radio.rb +5 -1
- data/lib/testcentricity_web/web_elements/select_list.rb +18 -7
- data/lib/testcentricity_web/web_elements/ui_elements_helper.rb +13 -0
- data/reports/.keep +1 -0
- data/test_site/basic_test_page.html +290 -0
- data/test_site/custom_controls_page.html +58 -0
- data/test_site/images/Granny.jpg +0 -0
- data/test_site/images/Wilder.jpg +0 -0
- data/test_site/images/You_Betcha.jpg +0 -0
- data/test_site/indexed_sections_page.html +58 -0
- data/test_site/media/MIB2-subtitles-pt-BR.vtt +49 -0
- data/test_site/media/MIB2.mp4 +0 -0
- data/test_site/media/MP4_small.mp4 +0 -0
- data/test_site/media/MPS_sample.mp3 +0 -0
- data/test_site/media_page.html +86 -0
- data/testcentricity_web.gemspec +5 -0
- metadata +125 -4
- data/test_site/test_page.html +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58ddfdbcb8747347fcb06efdd2a888509fa904bd5541a0f3d4d303af6469552c
|
4
|
+
data.tar.gz: 14f9af8661d7e571d10f79e3d093cafa4e744388d5c1d6f9232e207fe5e82d6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 768e113468d0dfc68f01467bc4304f41903bff09f59db9f2c8dd013545c061523c7e0947669d1befadcf43b1187e57df3cb188d803b3d802d905c0c3467ce852
|
7
|
+
data.tar.gz: 3133dc1f23ff3a839c45e2c6424d152f6c85916497c00dd9a815113f2acb8225f45efab91ce9d7cb4ada454d33115649ad61f4073f109a7dec44e40891971043
|
data/.gitignore
CHANGED
@@ -18,3 +18,21 @@ Thumbs.db
|
|
18
18
|
|
19
19
|
# rspec failure tracking
|
20
20
|
.rspec_status
|
21
|
+
|
22
|
+
# Ignore test-reports
|
23
|
+
reports/*.html
|
24
|
+
reports/*.xml
|
25
|
+
reports/*.json
|
26
|
+
reports/screenshots/
|
27
|
+
test-reports
|
28
|
+
capybara-*.html
|
29
|
+
debug.log
|
30
|
+
|
31
|
+
BrowserStackLocal
|
32
|
+
cbttunnel.jar
|
33
|
+
|
34
|
+
/.yardoc/
|
35
|
+
/local.log
|
36
|
+
.run/*.xml
|
37
|
+
|
38
|
+
echo coverage >> .gitignore
|
data/.simplecov
ADDED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,48 @@
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
4
|
|
5
|
+
## [4.1.7] - 28-MAR-2022
|
6
|
+
|
7
|
+
### Fixed
|
8
|
+
* `CheckBox.set_checkbox_state` and `Radio.set_selected_state` work on iOS simulators again.
|
9
|
+
|
10
|
+
### Changes
|
11
|
+
* `Audio.playback_rate` and `Video.playback_rate` now return value as a `Float` instead of a `String`.
|
12
|
+
* `Audio.default_playback_rate` and `Video.default_playback_rate` now return value as a `Float` instead of a `String`.
|
13
|
+
* `Audio.current_time` and `Video.current_time` now return value as a `Float` rounded to two decimal places.
|
14
|
+
* `Audio.duration` and `Video.duration` now return value as a `Float` rounded to two decimal places.
|
15
|
+
|
16
|
+
### Added
|
17
|
+
* `Audio.mute` and `Video.mute` methods added.
|
18
|
+
* `Audio.unmute` and `Video.unmute` methods added.
|
19
|
+
* `Audio.playback_rate` and `Video.playback_rate` now accept a `Float` value as an input for setting the playback rate
|
20
|
+
of media.
|
21
|
+
* `Audio.volume` and `Video.volume` now accept a `Float` value between 0 and 1 as an input for setting the volume of media.
|
22
|
+
|
23
|
+
|
24
|
+
## [4.1.6] - 21-MAR-2022
|
25
|
+
|
26
|
+
### Fixed
|
27
|
+
* `PageObject.verify_page_exists` now works with `page_locator` traits expressed in Xpath format, and no longer fails with a
|
28
|
+
`invalid selector: An invalid or illegal selector was specified - Selenium::WebDriver::Error::InvalidSelectorError` error.
|
29
|
+
|
30
|
+
### Added
|
31
|
+
* `UIElement.required?` method added.
|
32
|
+
* `PageObject.populate_data_fields` and `PageSection.populate_data_fields` methods now work with the following:
|
33
|
+
* `input(type='color')` color picker controls if they are specified as a `textfield` type element.
|
34
|
+
* `input(type='range')` slider controls if they are specified as a `range` type element.
|
35
|
+
* `input(type='file')` file upload controls if they are specified as a `filefield` type element.
|
36
|
+
|
37
|
+
|
38
|
+
## [4.1.5] - 15-MAR-2022
|
39
|
+
|
40
|
+
### Fixed
|
41
|
+
* `SelectList.selected?` now correctly returns selected value for custom `selectlist` controls.
|
42
|
+
|
43
|
+
### Updated
|
44
|
+
* Updated HTML documentation.
|
45
|
+
|
46
|
+
|
5
47
|
## [4.1.4] - 09-MAR-2022
|
6
48
|
|
7
49
|
### Fixed
|
@@ -19,7 +61,7 @@ All notable changes to this project will be documented in this file.
|
|
19
61
|
|
20
62
|
## [4.1.2] - 07-MAR-2022
|
21
63
|
|
22
|
-
###
|
64
|
+
### Updated
|
23
65
|
* Updated HTML documentation.
|
24
66
|
|
25
67
|
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
testcentricity_web (4.1.
|
4
|
+
testcentricity_web (4.1.7)
|
5
5
|
appium_lib
|
6
6
|
browserstack-local
|
7
7
|
capybara (>= 3.1, < 4)
|
@@ -21,6 +21,9 @@ GEM
|
|
21
21
|
specs:
|
22
22
|
addressable (2.8.0)
|
23
23
|
public_suffix (>= 2.0.2, < 5.0)
|
24
|
+
appium_capybara (2.0.0)
|
25
|
+
appium_lib (~> 12.0.0)
|
26
|
+
capybara (~> 3.36)
|
24
27
|
appium_lib (12.0.0)
|
25
28
|
appium_lib_core (~> 5.0.0)
|
26
29
|
nokogiri (~> 1.8, >= 1.8.1)
|
@@ -33,6 +36,7 @@ GEM
|
|
33
36
|
ice_nine (~> 0.11.0)
|
34
37
|
thread_safe (~> 0.3, >= 0.3.1)
|
35
38
|
browserstack-local (1.3.0)
|
39
|
+
builder (3.2.4)
|
36
40
|
capybara (3.36.0)
|
37
41
|
addressable
|
38
42
|
matrix
|
@@ -46,23 +50,63 @@ GEM
|
|
46
50
|
chronic (0.10.2)
|
47
51
|
coercible (1.0.0)
|
48
52
|
descendants_tracker (~> 0.0.1)
|
49
|
-
concurrent-ruby (1.1.
|
53
|
+
concurrent-ruby (1.1.10)
|
54
|
+
cucumber (7.1.0)
|
55
|
+
builder (~> 3.2, >= 3.2.4)
|
56
|
+
cucumber-core (~> 10.1, >= 10.1.0)
|
57
|
+
cucumber-create-meta (~> 6.0, >= 6.0.1)
|
58
|
+
cucumber-cucumber-expressions (~> 14.0, >= 14.0.0)
|
59
|
+
cucumber-gherkin (~> 22.0, >= 22.0.0)
|
60
|
+
cucumber-html-formatter (~> 17.0, >= 17.0.0)
|
61
|
+
cucumber-messages (~> 17.1, >= 17.1.1)
|
62
|
+
cucumber-wire (~> 6.2, >= 6.2.0)
|
63
|
+
diff-lcs (~> 1.4, >= 1.4.4)
|
64
|
+
mime-types (~> 3.3, >= 3.3.1)
|
65
|
+
multi_test (~> 0.1, >= 0.1.2)
|
66
|
+
sys-uname (~> 1.2, >= 1.2.2)
|
67
|
+
cucumber-core (10.1.1)
|
68
|
+
cucumber-gherkin (~> 22.0, >= 22.0.0)
|
69
|
+
cucumber-messages (~> 17.1, >= 17.1.1)
|
70
|
+
cucumber-tag-expressions (~> 4.1, >= 4.1.0)
|
71
|
+
cucumber-create-meta (6.0.4)
|
72
|
+
cucumber-messages (~> 17.1, >= 17.1.1)
|
73
|
+
sys-uname (~> 1.2, >= 1.2.2)
|
74
|
+
cucumber-cucumber-expressions (14.0.0)
|
75
|
+
cucumber-gherkin (22.0.0)
|
76
|
+
cucumber-messages (~> 17.1, >= 17.1.1)
|
77
|
+
cucumber-html-formatter (17.0.0)
|
78
|
+
cucumber-messages (~> 17.1, >= 17.1.0)
|
79
|
+
cucumber-messages (17.1.1)
|
80
|
+
cucumber-tag-expressions (4.1.0)
|
81
|
+
cucumber-wire (6.2.1)
|
82
|
+
cucumber-core (~> 10.1, >= 10.1.0)
|
83
|
+
cucumber-cucumber-expressions (~> 14.0, >= 14.0.0)
|
50
84
|
descendants_tracker (0.0.4)
|
51
85
|
thread_safe (~> 0.3, >= 0.3.1)
|
86
|
+
diff-lcs (1.5.0)
|
87
|
+
docile (1.4.0)
|
52
88
|
eventmachine (1.2.7)
|
53
89
|
faker (2.20.0)
|
54
90
|
i18n (>= 1.8.11, < 2)
|
55
91
|
faye-websocket (0.11.1)
|
56
92
|
eventmachine (>= 0.12.0)
|
57
93
|
websocket-driver (>= 0.5.1)
|
94
|
+
ffi (1.15.5)
|
58
95
|
i18n (1.10.0)
|
59
96
|
concurrent-ruby (~> 1.0)
|
60
97
|
ice_nine (0.11.2)
|
61
98
|
matrix (0.4.2)
|
99
|
+
mime-types (3.4.1)
|
100
|
+
mime-types-data (~> 3.2015)
|
101
|
+
mime-types-data (3.2022.0105)
|
62
102
|
mini_mime (1.1.2)
|
103
|
+
multi_test (0.1.2)
|
63
104
|
nokogiri (1.13.3-x86_64-darwin)
|
64
105
|
racc (~> 1.4)
|
65
106
|
os (1.1.4)
|
107
|
+
parallel (1.21.0)
|
108
|
+
parallel_tests (3.7.3)
|
109
|
+
parallel
|
66
110
|
power_assert (2.0.1)
|
67
111
|
public_suffix (4.0.6)
|
68
112
|
racc (1.6.0)
|
@@ -72,6 +116,7 @@ GEM
|
|
72
116
|
rake (13.0.6)
|
73
117
|
redcarpet (3.5.1)
|
74
118
|
regexp_parser (2.2.1)
|
119
|
+
require_all (1.5.0)
|
75
120
|
rexml (3.2.5)
|
76
121
|
ruby-ole (1.2.12.2)
|
77
122
|
rubyzip (2.3.2)
|
@@ -79,8 +124,16 @@ GEM
|
|
79
124
|
childprocess (>= 0.5, < 5.0)
|
80
125
|
rexml (~> 3.2, >= 3.2.5)
|
81
126
|
rubyzip (>= 1.2.2)
|
127
|
+
simplecov (0.21.2)
|
128
|
+
docile (~> 1.1)
|
129
|
+
simplecov-html (~> 0.11)
|
130
|
+
simplecov_json_formatter (~> 0.1)
|
131
|
+
simplecov-html (0.12.3)
|
132
|
+
simplecov_json_formatter (0.1.4)
|
82
133
|
spreadsheet (1.1.7)
|
83
134
|
ruby-ole (>= 1.0)
|
135
|
+
sys-uname (1.2.2)
|
136
|
+
ffi (~> 1.1)
|
84
137
|
test-unit (3.5.3)
|
85
138
|
power_assert
|
86
139
|
thread_safe (0.3.6)
|
@@ -103,9 +156,14 @@ PLATFORMS
|
|
103
156
|
x86_64-darwin-21
|
104
157
|
|
105
158
|
DEPENDENCIES
|
159
|
+
appium_capybara
|
106
160
|
bundler
|
161
|
+
cucumber
|
162
|
+
parallel_tests
|
107
163
|
rake
|
108
164
|
redcarpet
|
165
|
+
require_all
|
166
|
+
simplecov (~> 0.18)
|
109
167
|
testcentricity_web!
|
110
168
|
|
111
169
|
BUNDLED WITH
|
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
|
|
@@ -239,7 +239,7 @@ the UI to hide implementation details, as shown below:
|
|
239
239
|
remember_checkbox => { exists: true, enabled: true, checked: false },
|
240
240
|
forgot_password_link => { visible: true, caption: 'Forgot your password?' },
|
241
241
|
error_message_label => { visible: false }
|
242
|
-
|
242
|
+
}
|
243
243
|
verify_ui_states(ui)
|
244
244
|
end
|
245
245
|
end
|
@@ -282,7 +282,7 @@ the UI to hide implementation details, as shown below:
|
|
282
282
|
password_field => profile.password,
|
283
283
|
pword_confirm_field => profile.confirm_password,
|
284
284
|
email_opt_in_check => profile.email_opt_in
|
285
|
-
|
285
|
+
}
|
286
286
|
populate_data_fields(fields)
|
287
287
|
sign_up_button.click
|
288
288
|
end
|
@@ -503,6 +503,7 @@ With TestCentricity, all UI elements are based on the `UIElement` class, and inh
|
|
503
503
|
element.displayed?
|
504
504
|
element.obscured?
|
505
505
|
element.focused?
|
506
|
+
element.required?
|
506
507
|
element.content_editable?
|
507
508
|
element.get_value
|
508
509
|
element.count
|
@@ -569,9 +570,10 @@ interacted with.
|
|
569
570
|
|
570
571
|
The `PageObject.populate_data_fields` and `PageSection.populate_data_fields` methods support the entry of test data into a collection of
|
571
572
|
`UIElements`. The `populate_data_fields` method accepts a hash containing key/hash pairs of `UIElements` and their associated data to be
|
572
|
-
entered. Data values must be in the form of a `String` for `textfield` and `
|
573
|
-
must either be a `Boolean` or a `String` that evaluates to a `Boolean` value (Yes, No, 1, 0, true, false). For `
|
574
|
-
must be
|
573
|
+
entered. Data values must be in the form of a `String` for `textfield`, `selectlist`, and `filefield` controls. For `checkbox` and `radio`
|
574
|
+
controls, data must either be a `Boolean` or a `String` that evaluates to a `Boolean` value (Yes, No, 1, 0, true, false). For `range` controls,
|
575
|
+
data must be an `Integer`. For `input(type='color')` color picker controls, which are specified as a `textfield`, data must be in the form
|
576
|
+
of a hex color `String`. For `section` objects, data values must be a `String`, and the `section` object must have a `set` method defined.
|
575
577
|
|
576
578
|
The `populate_data_fields` method verifies that data attributes associated with each `UIElement` is not `nil` or `empty` before attempting to
|
577
579
|
enter data into the `UIElement`.
|
@@ -634,6 +636,14 @@ The `verify_ui_states` method supports the following property/state pairs:
|
|
634
636
|
:class String
|
635
637
|
:value or :caption String
|
636
638
|
:attribute Hash
|
639
|
+
:style String
|
640
|
+
:tabindex Integer
|
641
|
+
:required Boolean
|
642
|
+
|
643
|
+
**Pages:**
|
644
|
+
|
645
|
+
:secure Boolean
|
646
|
+
:title String
|
637
647
|
|
638
648
|
**Text Fields:**
|
639
649
|
|
@@ -646,12 +656,17 @@ The `verify_ui_states` method supports the following property/state pairs:
|
|
646
656
|
|
647
657
|
**Checkboxes:**
|
648
658
|
|
649
|
-
:checked
|
659
|
+
:checked Boolean
|
660
|
+
:indeterminate Boolean
|
650
661
|
|
651
662
|
**Radio Buttons:**
|
652
663
|
|
653
664
|
:selected Boolean
|
654
665
|
|
666
|
+
**Links:**
|
667
|
+
|
668
|
+
:href String
|
669
|
+
|
655
670
|
**Images**
|
656
671
|
|
657
672
|
:loaded Boolean
|
@@ -671,6 +686,8 @@ The `verify_ui_states` method supports the following property/state pairs:
|
|
671
686
|
:items or :options Array of Strings
|
672
687
|
:itemcount or :optioncount Integer
|
673
688
|
:selected String
|
689
|
+
:groupcount Integer
|
690
|
+
:group_headings Array of Strings
|
674
691
|
|
675
692
|
**Tables**
|
676
693
|
|
@@ -706,8 +723,6 @@ The `verify_ui_states` method supports the following property/state pairs:
|
|
706
723
|
|
707
724
|
The `verify_ui_states` method supports the following ARIA accessibility property/state pairs:
|
708
725
|
|
709
|
-
**All Objects:**
|
710
|
-
|
711
726
|
:aria_label String
|
712
727
|
:aria_disabled Boolean
|
713
728
|
:aria_labelledby String
|
@@ -738,8 +753,10 @@ The `verify_ui_states` method supports the following ARIA accessibility property
|
|
738
753
|
:aria_multiline Boolean
|
739
754
|
:aria_multiselectable Boolean
|
740
755
|
:content_editable Boolean
|
756
|
+
:role String
|
741
757
|
|
742
758
|
#### Comparison States
|
759
|
+
|
743
760
|
The `verify_ui_states` method supports comparison states using property/comparison state pairs:
|
744
761
|
|
745
762
|
object => { property: { comparison_state: value } }
|
@@ -844,6 +861,126 @@ Baseline translation strings are stored in `.yml` files in the `config/locales/`
|
|
844
861
|
└── README.md
|
845
862
|
|
846
863
|
|
864
|
+
### Working with custom UIElements
|
865
|
+
|
866
|
+
Many responsive and touch-enabled web based user interfaces are implemented using front-end JavaScript libraries for building user
|
867
|
+
interfaces based on UI components. Popular JS libraries include React, Angular, and Ember.js. These stylized and adorned controls can
|
868
|
+
present a challenge when attempting to interact with them using Capybara and Selenium based automated tests.
|
869
|
+
|
870
|
+
#### Radio and Checkbox UIElements
|
871
|
+
|
872
|
+
Sometimes, radio buttons and checkboxes implemented using JS component libraries cannot be interacted with due to other UI elements
|
873
|
+
being overlaid on top of them and the base `input(type='radio')` or `input(type='checkbox')` element not being visible.
|
874
|
+
|
875
|
+
In the screenshots below of an airline flight search and booking page, the **Roundtrip** and **One-way** radio buttons are adorned with
|
876
|
+
`label` elements that also acts as proxies for their associated `input(type='radio')` elements, and they intercept the `click` actions
|
877
|
+
that would normally be handled by the `input(type='radio')` elements.
|
878
|
+
|
879
|
+
<img src="https://i.imgur.com/7bW5u4c.jpg" alt="Roundtrip Radio button Input" title="Roundtrip Radio button Input">
|
880
|
+
|
881
|
+
|
882
|
+
This screenshot shows the `label` element that is overlaid above the **Roundtrip** `input(type='radio')` element.
|
883
|
+
|
884
|
+
<img src="https://i.imgur.com/2stWiyR.jpg" alt="Roundtrip Radio button Label" title="Roundtrip Radio button Label">
|
885
|
+
|
886
|
+
|
887
|
+
The checkbox controls in this web UI are also adorned with `label` elements that act as proxies for their associated `input(type='checkbox')`
|
888
|
+
elements.
|
889
|
+
|
890
|
+
<img src="https://i.imgur.com/JcOANqZ.jpg" alt="One-way Radio button Label" title="One-way Radio button Label">
|
891
|
+
|
892
|
+
|
893
|
+
The `Radio.define_custom_elements` and `CheckBox.define_custom_elements` methods provide a way to specify the `proxy` and/or `label`
|
894
|
+
elements associated with the `input(type='radio')` or `input(type='checkbox')` elements. The `define_custom_elements` method
|
895
|
+
should be called from an `initialize` method for the `PageObject` or `PageSection` where the `radio` or `checkbox` element is instantiated.
|
896
|
+
The code snippet below demonstrates the use of the `Radio.define_custom_elements` and `CheckBox.define_custom_elements` methods to
|
897
|
+
resolve the testability issues posed by the adorned **Roundtrip** and **One-way** radio buttons and the **Flexible dates** checkbox.
|
898
|
+
|
899
|
+
class FlightBookingPage < TestCentricity::PageObject
|
900
|
+
trait(:page_name) { 'Flight Booking Home' }
|
901
|
+
trait(:page_locator) { "div[class*='bookerContainer']" }
|
902
|
+
|
903
|
+
# Flight Booking page UI elements
|
904
|
+
radios roundtrip_radio: 'input#roundtrip',
|
905
|
+
one_way_radio: 'input#oneway'
|
906
|
+
checkbox :flexible_check, 'input#flexibleDates'
|
907
|
+
|
908
|
+
def initialize
|
909
|
+
# define the custom element components for the Round Trip radio button
|
910
|
+
radio_spec = { proxy: "label[for='roundtrip']" }
|
911
|
+
roundtrip_radio.define_custom_elements(radio_spec)
|
912
|
+
# define the custom element components for the One Way radio button
|
913
|
+
radio_spec = { proxy: "label[for='oneway']" }
|
914
|
+
one_way_radio.define_custom_elements(radio_spec)
|
915
|
+
# define the custom element components for the Flexible Date checkbox
|
916
|
+
check_spec = { proxy: 'label#flexDatesLabel' }
|
917
|
+
flexible_check.define_custom_elements(check_spec)
|
918
|
+
end
|
919
|
+
end
|
920
|
+
|
921
|
+
|
922
|
+
#### SelectList UIElements
|
923
|
+
|
924
|
+
The basic HTML `select` element is typically composed of the parent `select` object, and one or more `option` elements representing
|
925
|
+
the selectable items in the drop-down list. However, `select` type controls implemented using JS component libraries can be composed
|
926
|
+
of multiple elements representing the various components of a drop-down style `selectlist` implementation.
|
927
|
+
|
928
|
+
In the screenshots below of an airline flight search and booking page, there are no `select` or `option` elements associated with the
|
929
|
+
**Month**, **Day**, and **Cabin Type** drop-down style selectors. An inspection of the **Month** selector reveals that it is a `div`
|
930
|
+
element that contains a `button` element (outlined in red) for triggering the drop-down list, a `ul` element (outlined in green) that
|
931
|
+
contains the drop-down list, and multiple `li` elements (outlined in blue) that represent the list items or options that can be
|
932
|
+
selected. The currently selected item or option can be identified by either the `listBoxOptionSelected` snippet in its `class` name or
|
933
|
+
the `aria-selected` attribute (outlined in orange).
|
934
|
+
|
935
|
+
Further examination of the **Day** and **Cabin Type** drop-down style selectors reveal that their composition is identical to the
|
936
|
+
**Month** selector.
|
937
|
+
|
938
|
+
<img src="https://i.imgur.com/LYAC2lh.jpg" alt="Custom SelectList" title="Custom SelectList">
|
939
|
+
|
940
|
+
|
941
|
+
The `SelectList.define_list_elements` method provides a means of specifying the various elements that make up the key components of
|
942
|
+
a `selectlist` control. The method accepts a hash of element designators (key) and a CSS or Xpath expression (value) that expression
|
943
|
+
that uniquely identifies the element. Valid element designators are `list_item:`, `options_list:`, `list_trigger:`, `selected_item:`,
|
944
|
+
`text_field:`, `group_heading:`, and `group_item:`.
|
945
|
+
|
946
|
+
The code snippet below demonstrates the use of the `SelectList.define_list_elements` method to define the common components that make
|
947
|
+
up the **Month**, **Day**, and **Cabin Type** drop-down style selectors. Note the use of the ARIA `role` and `aria-selected` attributes
|
948
|
+
as element locators.
|
949
|
+
|
950
|
+
class FlightBookingPage < TestCentricity::PageObject
|
951
|
+
trait(:page_name) { 'Flight Booking Home' }
|
952
|
+
trait(:page_locator) { "div[class*='bookerContainer']" }
|
953
|
+
|
954
|
+
# Flight Booking page UI elements
|
955
|
+
selectlists month_select: "div[class*='expandFlexMonth']",
|
956
|
+
duration_select: "div[class*='expandFlexDay']",
|
957
|
+
cabin_type_select: "div[class*='bookFlightForm__optionField'] > div[class*='app-components-ListBox']"
|
958
|
+
|
959
|
+
def initialize
|
960
|
+
# define the custom list element components for the Month, Duration, and Cabin Type selectlist objects
|
961
|
+
list_spec = {
|
962
|
+
selected_item: "li[aria-selected=true]",
|
963
|
+
options_list: "ul[role='listbox']",
|
964
|
+
list_item: "li[role='option']",
|
965
|
+
list_trigger: "button[role='combobox']"
|
966
|
+
}
|
967
|
+
month_select.define_list_elements(list_spec)
|
968
|
+
duration_select.define_list_elements(list_spec)
|
969
|
+
cabin_type_select.define_list_elements(list_spec)
|
970
|
+
end
|
971
|
+
end
|
972
|
+
|
973
|
+
|
974
|
+
#### List UIElements
|
975
|
+
|
976
|
+
The basic HTML list is typically composed of the parent `ul` object, and one or more `li` elements representing the items
|
977
|
+
in the list. However, list controls implemented using JS component libraries can be composed of multiple elements representing the
|
978
|
+
components of a list implementation.
|
979
|
+
|
980
|
+
The `List.define_list_elements` method provides a means of specifying the elements that make up the key components of a `list` control.
|
981
|
+
The method accepts a hash of element designators (key) and a CSS or Xpath expression (value) that expression that uniquely identifies
|
982
|
+
the element. Valid element designators are `list_item:`and `selected_item:`.
|
983
|
+
|
847
984
|
|
848
985
|
## Instantiating your PageObjects
|
849
986
|
|
@@ -1220,7 +1357,7 @@ Once your test environment is properly configured, the following **Environment V
|
|
1220
1357
|
| `WEB_BROWSER` | Must be set to `appium` |
|
1221
1358
|
| `APP_PLATFORM_NAME` | Must be set to `iOS` |
|
1222
1359
|
| `APP_BROWSER` | Must be set to `Safari` |
|
1223
|
-
| `APP_VERSION` | Must be set to `15.
|
1360
|
+
| `APP_VERSION` | Must be set to `15.4`, `14.5`, or which ever iOS version you wish to run within the XCode Simulator |
|
1224
1361
|
| `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
1362
|
| `DEVICE_TYPE` | Must be set to `phone` or `tablet` |
|
1226
1363
|
| `APP_UDID` | UDID of physically connected iOS device (not used for simulators) |
|
@@ -1302,6 +1439,13 @@ the code shown below in your `hooks.rb` file.
|
|
1302
1439
|
end
|
1303
1440
|
|
1304
1441
|
|
1442
|
+
The `APPIUM_SERVER` environment variable must be set to `run` in order to programmatically start and stop Appium server. This can be
|
1443
|
+
set by adding the following to your `cucumber.yml` file and including `-p run_appium` in your command line when starting your Cucumber
|
1444
|
+
test suite(s):
|
1445
|
+
|
1446
|
+
run_appium: APPIUM_SERVER=run
|
1447
|
+
|
1448
|
+
|
1305
1449
|
Refer to **section 8.6 (Using Browser specific Profiles in cucumber.yml)** below.
|
1306
1450
|
|
1307
1451
|
|
@@ -1548,9 +1692,10 @@ that you intend to connect with.
|
|
1548
1692
|
#==============
|
1549
1693
|
|
1550
1694
|
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:
|
1695
|
+
app_ios_15: --profile appium_ios APP_VERSION="15.4"
|
1696
|
+
ipad_pro_12_15_sim: --profile app_ios_15 DEVICE_TYPE=tablet APP_DEVICE="iPad Pro (12.9-inch) (5th generation)"
|
1697
|
+
ipad_air_15_sim: --profile app_ios_15 DEVICE_TYPE=tablet APP_DEVICE="iPad Air (5th generation)" <%= desktop %>
|
1698
|
+
ipad_15_sim: --profile app_ios_15 DEVICE_TYPE=tablet APP_DEVICE="iPad (9th generation)"
|
1554
1699
|
|
1555
1700
|
|
1556
1701
|
#==============
|
@@ -1683,16 +1828,16 @@ in landscape orientation:
|
|
1683
1828
|
cucumber -p ipad_pro -p landscape
|
1684
1829
|
|
1685
1830
|
|
1686
|
-
The following command specifies that Cucumber will run tests against an iPad Pro (12.9-inch) (5th generation) with iOS version 15.
|
1831
|
+
The following command specifies that Cucumber will run tests against an iPad Pro (12.9-inch) (5th generation) with iOS version 15.4 in an
|
1687
1832
|
XCode Simulator in landscape orientation:
|
1688
1833
|
|
1689
|
-
cucumber -p
|
1834
|
+
cucumber -p ipad_pro_12_15_sim -p landscape
|
1690
1835
|
|
1691
1836
|
NOTE: Appium must be running prior to executing this command
|
1692
1837
|
|
1693
1838
|
You can ensure that Appium Server is running by including `-p run_appium` in your command line:
|
1694
1839
|
|
1695
|
-
cucumber -p
|
1840
|
+
cucumber -p ipad_pro_12_15_sim -p landscape -p run_appium
|
1696
1841
|
|
1697
1842
|
|
1698
1843
|
The following command specifies that Cucumber will run tests against a remotely hosted Safari web browser running on a macOS Monterey
|
data/Rakefile
CHANGED
@@ -1 +1,60 @@
|
|
1
|
-
require '
|
1
|
+
require 'rubygems'
|
2
|
+
require 'cucumber'
|
3
|
+
require 'cucumber/rake/task'
|
4
|
+
require 'rake'
|
5
|
+
|
6
|
+
|
7
|
+
namespace :features do
|
8
|
+
Cucumber::Rake::Task.new(:edge_local) do |t|
|
9
|
+
t.profile = 'edge_local'
|
10
|
+
end
|
11
|
+
|
12
|
+
Cucumber::Rake::Task.new(:chrome_local) do |t|
|
13
|
+
t.profile = 'chrome_local'
|
14
|
+
end
|
15
|
+
|
16
|
+
Cucumber::Rake::Task.new(:edge_headless) do |t|
|
17
|
+
t.profile = 'edge_headless'
|
18
|
+
end
|
19
|
+
|
20
|
+
Cucumber::Rake::Task.new(:chrome_headless) do |t|
|
21
|
+
t.profile = 'chrome_headless'
|
22
|
+
end
|
23
|
+
|
24
|
+
Cucumber::Rake::Task.new(:safari_local) do |t|
|
25
|
+
t.profile = 'safari_local'
|
26
|
+
end
|
27
|
+
|
28
|
+
Cucumber::Rake::Task.new(:firefox_local) do |t|
|
29
|
+
t.profile = 'firefox_local'
|
30
|
+
end
|
31
|
+
|
32
|
+
Cucumber::Rake::Task.new(:firefox_headless) do |t|
|
33
|
+
t.profile = 'firefox_headless'
|
34
|
+
end
|
35
|
+
|
36
|
+
Cucumber::Rake::Task.new(:edge_grid) do |t|
|
37
|
+
t.profile = 'edge_grid'
|
38
|
+
end
|
39
|
+
|
40
|
+
Cucumber::Rake::Task.new(:chrome_grid) do |t|
|
41
|
+
t.profile = 'chrome_grid'
|
42
|
+
end
|
43
|
+
|
44
|
+
Cucumber::Rake::Task.new(:firefox_grid) do |t|
|
45
|
+
t.profile = 'firefox_grid'
|
46
|
+
end
|
47
|
+
|
48
|
+
Cucumber::Rake::Task.new(:ios_remote) do |t|
|
49
|
+
t.profile = 'ios_remote'
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
task :required => [:edge_local, :edge_headless, :chrome_local, :chrome_headless, :safari_local]
|
54
|
+
|
55
|
+
task :grid => [:edge_grid, :chrome_grid]
|
56
|
+
|
57
|
+
task :mobile => [:ios_remote]
|
58
|
+
|
59
|
+
task :all => [:edge_local, :edge_headless, :chrome_local, :chrome_headless, :safari_local, :edge_grid, :chrome_grid, :ios_remote]
|
60
|
+
end
|