testcentricity 2.4.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +29 -0
  3. data/.rspec +2 -1
  4. data/.rubocop.yml +38 -0
  5. data/.ruby-version +1 -1
  6. data/.simplecov +9 -0
  7. data/.yardopts +3 -0
  8. data/CHANGELOG.md +275 -0
  9. data/CODE_OF_CONDUCT.md +13 -0
  10. data/{LICENSE.txt → LICENSE.md} +3 -4
  11. data/README.md +938 -1378
  12. data/Rakefile +63 -1
  13. data/config/cucumber.yml +145 -0
  14. data/config/locales/en-US.yml +56 -0
  15. data/config/test_data/LOCAL_data.yml +11 -0
  16. data/config/test_data/data.yml +10 -0
  17. data/features/deep_links.feature +26 -0
  18. data/features/login.feature +30 -0
  19. data/features/navigation.feature +31 -0
  20. data/features/step_definitions/generic_steps.rb +72 -0
  21. data/features/support/android/screens/about_screen.rb +11 -0
  22. data/features/support/android/screens/base_app_screen.rb +29 -0
  23. data/features/support/android/screens/checkout_address_screen.rb +17 -0
  24. data/features/support/android/screens/checkout_payment_screen.rb +22 -0
  25. data/features/support/android/screens/login_screen.rb +18 -0
  26. data/features/support/android/screens/products_screen.rb +13 -0
  27. data/features/support/android/screens/saucebot_screen.rb +16 -0
  28. data/features/support/android/screens/webview_screen.rb +13 -0
  29. data/features/support/android/sections/nav_widgets/nav_menu.rb +39 -0
  30. data/features/support/env.rb +61 -0
  31. data/features/support/hooks.rb +135 -0
  32. data/features/support/ios/screens/about_screen.rb +11 -0
  33. data/features/support/ios/screens/base_app_screen.rb +19 -0
  34. data/features/support/ios/screens/checkout_address_screen.rb +17 -0
  35. data/features/support/ios/screens/checkout_payment_screen.rb +22 -0
  36. data/features/support/ios/screens/login_screen.rb +18 -0
  37. data/features/support/ios/screens/products_screen.rb +13 -0
  38. data/features/support/ios/screens/saucebot_screen.rb +16 -0
  39. data/features/support/ios/screens/webview_screen.rb +13 -0
  40. data/features/support/ios/sections/list_items/product_cell_item.rb +13 -0
  41. data/features/support/ios/sections/modals/base_modal.rb +23 -0
  42. data/features/support/ios/sections/modals/logout_modal.rb +6 -0
  43. data/features/support/ios/sections/modals/reset_app_state_modal.rb +6 -0
  44. data/features/support/ios/sections/nav_widgets/nav_bar.rb +31 -0
  45. data/features/support/ios/sections/nav_widgets/nav_menu.rb +41 -0
  46. data/features/support/shared_components/screens/base_app_screen.rb +31 -0
  47. data/features/support/shared_components/screens/checkout_address_screen.rb +17 -0
  48. data/features/support/shared_components/screens/checkout_payment_screen.rb +22 -0
  49. data/features/support/shared_components/screens/login_screen.rb +39 -0
  50. data/features/support/shared_components/screens/saucebot_screen.rb +17 -0
  51. data/features/support/shared_components/screens/webview_screen.rb +12 -0
  52. data/features/support/shared_components/sections/nav_menu.rb +58 -0
  53. data/features/support/world_data.rb +12 -0
  54. data/features/support/world_pages.rb +26 -0
  55. data/lib/testcentricity/app_core/appium_connect_helper.rb +355 -111
  56. data/lib/testcentricity/app_core/screen_object.rb +252 -0
  57. data/lib/testcentricity/app_core/screen_objects_helper.rb +29 -280
  58. data/lib/testcentricity/app_core/screen_section.rb +350 -0
  59. data/lib/testcentricity/app_elements/app_element_helper.rb +17 -8
  60. data/lib/testcentricity/app_elements/checkbox.rb +3 -3
  61. data/lib/testcentricity/data_objects/environment.rb +133 -39
  62. data/lib/testcentricity/version.rb +1 -1
  63. data/lib/testcentricity.rb +4 -129
  64. data/reports/.keep +1 -0
  65. data/spec/fixtures/page_object.rb +22 -0
  66. data/spec/fixtures/page_section_object.rb +21 -0
  67. data/spec/fixtures/screen_object.rb +16 -0
  68. data/spec/fixtures/screen_section_object.rb +16 -0
  69. data/spec/spec_helper.rb +28 -9
  70. data/spec/testcentricity/elements/button_spec.rb +18 -0
  71. data/spec/testcentricity/elements/checkbox_spec.rb +28 -0
  72. data/spec/testcentricity/elements/image_spec.rb +13 -0
  73. data/spec/testcentricity/elements/label_spec.rb +18 -0
  74. data/spec/testcentricity/elements/list_spec.rb +13 -0
  75. data/spec/testcentricity/elements/ui_element_spec.rb +72 -0
  76. data/spec/testcentricity/mobile/appium_connect_spec.rb +117 -0
  77. data/spec/testcentricity/mobile/screen_object_spec.rb +63 -0
  78. data/spec/testcentricity/mobile/screen_section_object_spec.rb +56 -0
  79. data/spec/testcentricity/version_spec.rb +7 -0
  80. data/spec/testcentricity/web/browser_spec.rb +41 -0
  81. data/spec/testcentricity/web/local_webdriver_spec.rb +86 -0
  82. data/spec/testcentricity/web/mobile_webdriver_spec.rb +123 -0
  83. data/spec/testcentricity/web/page_object_spec.rb +85 -0
  84. data/spec/testcentricity/web/page_section_object_spec.rb +72 -0
  85. data/testcentricity.gemspec +28 -27
  86. metadata +196 -127
  87. data/.ruby-gemset +0 -1
  88. data/Gemfile.lock +0 -93
  89. data/bin/console +0 -14
  90. data/bin/setup +0 -8
  91. data/lib/devices/devices.yml +0 -352
  92. data/lib/testcentricity/app_core/appium_server.rb +0 -69
  93. data/lib/testcentricity/app_core/screen_sections_helper.rb +0 -491
  94. data/lib/testcentricity/browser_helper.rb +0 -174
  95. data/lib/testcentricity/data_objects/data_objects_helper.rb +0 -78
  96. data/lib/testcentricity/data_objects/excel_helper.rb +0 -242
  97. data/lib/testcentricity/exception_queue_helper.rb +0 -111
  98. data/lib/testcentricity/utility_helpers.rb +0 -28
  99. data/lib/testcentricity/web_core/drag_drop_helper.rb +0 -15
  100. data/lib/testcentricity/web_core/page_objects_helper.rb +0 -711
  101. data/lib/testcentricity/web_core/page_sections_helper.rb +0 -932
  102. data/lib/testcentricity/web_core/webdriver_helper.rb +0 -588
  103. data/lib/testcentricity/web_elements/button.rb +0 -8
  104. data/lib/testcentricity/web_elements/cell_button.rb +0 -8
  105. data/lib/testcentricity/web_elements/cell_checkbox.rb +0 -38
  106. data/lib/testcentricity/web_elements/cell_element.rb +0 -69
  107. data/lib/testcentricity/web_elements/cell_image.rb +0 -8
  108. data/lib/testcentricity/web_elements/cell_radio.rb +0 -31
  109. data/lib/testcentricity/web_elements/checkbox.rb +0 -100
  110. data/lib/testcentricity/web_elements/file_field.rb +0 -45
  111. data/lib/testcentricity/web_elements/image.rb +0 -34
  112. data/lib/testcentricity/web_elements/label.rb +0 -8
  113. data/lib/testcentricity/web_elements/link.rb +0 -8
  114. data/lib/testcentricity/web_elements/list.rb +0 -100
  115. data/lib/testcentricity/web_elements/list_button.rb +0 -8
  116. data/lib/testcentricity/web_elements/list_checkbox.rb +0 -38
  117. data/lib/testcentricity/web_elements/list_element.rb +0 -61
  118. data/lib/testcentricity/web_elements/list_radio.rb +0 -31
  119. data/lib/testcentricity/web_elements/radio.rb +0 -74
  120. data/lib/testcentricity/web_elements/select_list.rb +0 -208
  121. data/lib/testcentricity/web_elements/siebel_open_ui_helper.rb +0 -15
  122. data/lib/testcentricity/web_elements/table.rb +0 -612
  123. data/lib/testcentricity/web_elements/textfield.rb +0 -114
  124. data/lib/testcentricity/web_elements/ui_elements_helper.rb +0 -532
  125. data/lib/testcentricity/world_extensions.rb +0 -26
  126. data/my_templates/default/method_details/setup.rb +0 -3
  127. data/spec/testcentricity_spec.rb +0 -9
data/Rakefile CHANGED
@@ -1 +1,63 @@
1
- require 'bundler/gem_tasks'
1
+ require 'rubygems'
2
+ require 'cucumber'
3
+ require 'cucumber/rake/task'
4
+ require 'rake'
5
+ require 'rspec/core/rake_task'
6
+ require 'simplecov'
7
+ require 'yard'
8
+
9
+
10
+ desc 'Run required specs'
11
+ RSpec::Core::RakeTask.new(:required_specs) do |t|
12
+ t.rspec_opts = '--tag required'
13
+ end
14
+
15
+
16
+ desc 'Run web specs'
17
+ RSpec::Core::RakeTask.new(:web_specs) do |t|
18
+ t.rspec_opts = '--tag web'
19
+ end
20
+
21
+
22
+ desc 'Run Cucumber features on iOS simulator'
23
+ Cucumber::Rake::Task.new(:ios_sim) do |t|
24
+ t.profile = 'ios_sim'
25
+ end
26
+
27
+
28
+ desc 'Run Cucumber features on Android simulator'
29
+ Cucumber::Rake::Task.new(:android_sim) do |t|
30
+ t.profile = 'android_sim'
31
+ end
32
+
33
+
34
+ desc 'Run required specs and Cucumber features'
35
+ task required: [:required_specs, :android_sim, :ios_sim]
36
+
37
+
38
+ desc 'Run all specs and Cucumber features'
39
+ task all_specs: [:required_specs, :web_specs]
40
+
41
+
42
+ desc 'Run all specs and Cucumber features'
43
+ task all: [:required_specs, :web_specs, :android_sim, :ios_sim]
44
+
45
+
46
+ desc 'Update HTML docs'
47
+ YARD::Rake::YardocTask.new(:docs) do |t|
48
+ t.files = ['lib/**/*.rb']
49
+ end
50
+
51
+
52
+ desc 'Build and release new version'
53
+ task :release do
54
+ version = TestCentricity::VERSION
55
+ puts "Releasing #{version}, y/n?"
56
+ exit(1) unless $stdin.gets.chomp == 'y'
57
+ sh 'gem build testcentricity.gemspec && ' \
58
+ "gem push testcentricity-#{version}.gem"
59
+ end
60
+
61
+
62
+ desc 'Update docs, build gem, and push to RubyGems'
63
+ task ship_it: [:docs, :release]
@@ -0,0 +1,145 @@
1
+ <% desktop = "--require features BROWSER_TILE=true BROWSER_SIZE=1300,1000 --publish-quiet" %>
2
+ <% mobile = "--require features --publish-quiet" %>
3
+ <% reports = "--require features --format pretty --format html --out reports/test_results.html --format junit --out reports --format json --out reports/test_results.json" %>
4
+ <% regression = "--tags '@regression and (not @wip and not @failing)' --require features" %>
5
+ <% acceptance = "--tags '@bat and (not @wip and not @failing)' --require features" %>
6
+
7
+
8
+ #==============
9
+ # generic test context profiles
10
+ #==============
11
+
12
+ failing: --tags '@failing and not @wip'
13
+ wip: --tags '@wip and not @failing'
14
+ dev: --tags '@dev and (not @wip and not @failing)'
15
+ regress: <%= regression %>
16
+ bvt: <%= acceptance %>
17
+
18
+
19
+ #==============
20
+ # test reporting profiles
21
+ #==============
22
+
23
+ report: <%= reports %> REPORTING=true
24
+
25
+
26
+ #==============
27
+ # conditionally load Page and Screen Object implementations based on which target platform we're running on
28
+ #==============
29
+
30
+ ios: PLATFORM=ios --tags @ios -r features/support/ios -e features/support/android
31
+ android: PLATFORM=android --tags @android -r features/support/android -e features/support/ios
32
+ web: PLATFORM=web --tags @web -r features/support/web -e features/support/ios -e features/support/android
33
+
34
+
35
+ #==============
36
+ # target_test_environment profiles
37
+ #==============
38
+
39
+ local: TEST_ENVIRONMENT=LOCAL
40
+ debug: DEBUG=true
41
+
42
+
43
+ #==============
44
+ # profiles for mobile device screen orientation
45
+ #==============
46
+
47
+ landscape: ORIENTATION=landscape
48
+ portrait: ORIENTATION=portrait
49
+
50
+
51
+ #==============
52
+ # profile to start Appium Server prior to running mobile browser tests on iOS or Android simulators or physical devices
53
+ #==============
54
+ run_appium: APPIUM_SERVER=run
55
+ upload_app: UPLOAD_APP=true
56
+
57
+
58
+ #==============
59
+ # profiles for native iOS apps hosted within XCode iOS simulators
60
+ # NOTE: Requires installation of XCode, iOS version specific target simulators, and Appium
61
+ #==============
62
+
63
+ appium_ios: WEB_BROWSER=appium --profile ios AUTOMATION_ENGINE=XCUITest APP_PLATFORM_NAME="iOS" NEW_COMMAND_TIMEOUT="30" <%= mobile %>
64
+ app_ios_14: --profile appium_ios APP_VERSION="14.5"
65
+ app_ios_15: --profile appium_ios APP_VERSION="15.4"
66
+
67
+ iphone_12PM_14_sim: --profile app_ios_14 DEVICE_TYPE=phone APP_DEVICE="iPhone 12 Pro Max"
68
+ iphone_13PM_15_sim: --profile app_ios_15 DEVICE_TYPE=phone APP_DEVICE="iPhone 13 Pro Max"
69
+ iphone_11_14_sim: --profile app_ios_14 DEVICE_TYPE=phone APP_DEVICE="iPhone 11"
70
+ ipad_pro_12_15_sim: --profile app_ios_15 DEVICE_TYPE=tablet APP_DEVICE="iPad Pro (12.9-inch) (5th generation)"
71
+ ios_sim: --profile iphone_13PM_15_sim --profile local --profile run_appium
72
+
73
+
74
+ #==============
75
+ # profiles for native Android apps hosted within Android Studio Android Virtual Device emulators
76
+ # NOTE: Requires installation of Android Studio, Android version specific virtual device simulators, and Appium
77
+ #==============
78
+
79
+ appium_android: WEB_BROWSER=appium --profile android AUTOMATION_ENGINE=UiAutomator2 APP_PLATFORM_NAME="Android" <%= mobile %>
80
+ app_android_12: --profile appium_android APP_VERSION="12.0"
81
+ pixel_5_api31_sim: --profile app_android_12 DEVICE_TYPE=phone APP_DEVICE="Pixel_5_API_31"
82
+ android_sim: --profile pixel_5_api31_sim --profile local --profile run_appium
83
+
84
+
85
+ #==============
86
+ # profiles for remotely hosted devices on the BrowserStack service
87
+ #==============
88
+
89
+ browserstack: WEB_BROWSER=browserstack BS_USERNAME="<INSERT USER NAME HERE>" BS_AUTHKEY="<INSERT PASSWORD HERE>" TEST_CONTEXT="TestCentricity"
90
+
91
+ # BrowserStack iOS real device native app profiles
92
+ bs_ios: --profile browserstack --profile ios BS_OS=ios <%= mobile %>
93
+ bs_iphone: --profile bs_ios DEVICE_TYPE=phone
94
+ bs_iphone13PM_15: --profile bs_iphone BS_OS_VERSION="15" BS_DEVICE="iPhone 13 Pro Max"
95
+ bs_iphone11_14: --profile bs_iphone BS_OS_VERSION="14" BS_DEVICE="iPhone 11"
96
+
97
+ # BrowserStack Android real device native app profiles
98
+ bs_android: --profile browserstack --profile android BS_OS=android <%= mobile %>
99
+ bs_pixel5: --profile bs_android BS_DEVICE="Google Pixel 5" BS_OS_VERSION="12.0" DEVICE_TYPE=phone
100
+
101
+
102
+ #==============
103
+ # profiles for remotely hosted devices on the SauceLabs service
104
+ #==============
105
+
106
+ saucelabs: WEB_BROWSER=saucelabs SL_USERNAME="<INSERT USER NAME HERE>" SL_AUTHKEY="<INSERT PASSWORD HERE>" DATA_CENTER="us-west-1" AUTOMATE_PROJECT="TestCentricity - SauceLabs"
107
+
108
+ # SauceLabs iOS real device native app profiles
109
+ sl_ios: --profile saucelabs --profile ios SL_OS=ios <%= mobile %>
110
+ sl_iphone: --profile sl_ios DEVICE_TYPE=phone
111
+ sl_iphone13PM_15: --profile sl_iphone SL_DEVICE="iPhone 13 Pro Max Simulator" SL_OS_VERSION="15.4"
112
+
113
+ # SauceLabs Android real device native app profiles
114
+ sl_android: --profile saucelabs --profile android SL_OS=android <%= mobile %>
115
+ sl_pixel5: --profile sl_android SL_DEVICE="Google Pixel 5 GoogleAPI Emulator" SL_OS_VERSION="12.0" DEVICE_TYPE=phone
116
+
117
+
118
+ #==============
119
+ # profiles for remotely hosted devices on the TestingBot service
120
+ #==============
121
+
122
+ testingbot: WEB_BROWSER=testingbot TB_USERNAME="<INSERT USER NAME HERE>" TB_AUTHKEY="<INSERT PASSWORD HERE>" AUTOMATE_PROJECT="TestCentricity - TestingBot"
123
+
124
+ # TestingBot iOS real device native app profiles
125
+ tb_ios: --profile testingbot --profile ios TB_OS=iOS <%= mobile %>
126
+ tb_iphone: --profile tb_ios DEVICE_TYPE=phone
127
+ tb_iphone11_14_dev: --profile tb_iphone TB_OS_VERSION="14.0" TB_DEVICE="iPhone 11" REAL_DEVICE=true
128
+ tb_iphone11_14_sim: --profile tb_iphone TB_OS_VERSION="14.2" TB_DEVICE="iPhone 11"
129
+ tb_iphone13PM_15_sim: --profile tb_iphone TB_OS_VERSION="15.4" TB_DEVICE="iPhone 13 Pro Max"
130
+
131
+ # TestingBot Android real device native app profiles
132
+ tb_android: --profile testingbot --profile android TB_OS=Android <%= mobile %>
133
+ tb_pixel_dev: --profile tb_android TB_DEVICE="Pixel" TB_OS_VERSION="9.0" DEVICE_TYPE=phone REAL_DEVICE=true
134
+ tb_pixel6_sim: --profile tb_android TB_DEVICE="Pixel 6" TB_OS_VERSION="12.0" DEVICE_TYPE=phone
135
+
136
+
137
+ #==============
138
+ # profiles for remotely hosted devices on the LambdaTest service
139
+ #==============
140
+
141
+ lambdatest: WEB_BROWSER=lambdatest LT_USERNAME="<INSERT USER NAME HERE>" LT_AUTHKEY="<INSERT PASSWORD HERE>" AUTOMATE_PROJECT="TestCentricity - LambdaTest"
142
+
143
+ # LambdaTest iOS real device native app profiles
144
+ lt_ios: --profile lambdatest --profile ios LT_OS=iOS <%= mobile %>
145
+ lt_iphone: --profile lt_ios DEVICE_TYPE=phone
@@ -0,0 +1,56 @@
1
+ # Localization file for English/U.S. locale.
2
+
3
+ en-US:
4
+ time:
5
+ formats:
6
+ default: "%m/%d/%Y"
7
+ long: "%B %d, %Y"
8
+ short: "%b %d"
9
+ abbrev: "%b %d, %Y"
10
+ abbrev_month: "%b"
11
+ month_year: "%B %Y"
12
+ date:
13
+ abbr_day_names:
14
+ - Sun
15
+ - Mon
16
+ - Tue
17
+ - Wed
18
+ - Thu
19
+ - Fri
20
+ - Sat
21
+ abbr_month_names:
22
+ -
23
+ - Jan
24
+ - Feb
25
+ - Mar
26
+ - Apr
27
+ - May
28
+ - Jun
29
+ - Jul
30
+ - Aug
31
+ - Sep
32
+ - Oct
33
+ - Nov
34
+ - Dec
35
+ day_names:
36
+ - Sunday
37
+ - Monday
38
+ - Tuesday
39
+ - Wednesday
40
+ - Thursday
41
+ - Friday
42
+ - Saturday
43
+ month_names:
44
+ -
45
+ - January
46
+ - February
47
+ - March
48
+ - April
49
+ - May
50
+ - June
51
+ - July
52
+ - August
53
+ - September
54
+ - October
55
+ - November
56
+ - December
@@ -0,0 +1,11 @@
1
+ Form_data:
2
+ primary:
3
+ username: "Ignatius von Snicklefritz"
4
+ password: "T0p_Sekrit"
5
+ image_filename: "Wilder.jpg"
6
+ multi_select: "Selection Item 2"
7
+ drop_down_item: "Drop Down Item 5"
8
+ check1: true
9
+ check2: true
10
+ check3: false
11
+ radio_select: 2
@@ -0,0 +1,10 @@
1
+ # This section is populated with Environment data required to execute automated test suites on all supported environments
2
+ Environments:
3
+ LOCAL:
4
+ DEEP_LINK_PREFIX: 'mydemoapprn'
5
+ IOS_BUNDLE_ID: 'com.saucelabs.mydemoapp.rn'
6
+ ANDROID_APP_ID: 'com.saucelabs.mydemoapp.rn'
7
+ IOS_APP_PATH: '/Users/Shared/Test_Apps/iOS/MyRNDemoApp.app'
8
+ IOS_IPA_PATH: '/Users/Shared/Test_Apps/iOS/iOS-Real-Device-MyRNDemoApp.1.3.0-162.ipa'
9
+ ANDROID_APK_PATH: '/Users/Shared/Test_Apps/Android/Android-MyDemoAppRN.1.2.0.build-231.apk'
10
+
@@ -0,0 +1,26 @@
1
+ @mobile @ios @android @regression
2
+
3
+
4
+ Feature: App screen deep links
5
+ In order to ensure comprehensive support for native app deep links
6
+ As a developer of the TestCentricity gem
7
+ I expect to validate that app screens can be directly accessed with minimal UI interactions
8
+
9
+
10
+ Background:
11
+ Given I have launched the SauceLabs My Demo app
12
+
13
+
14
+ Scenario Outline: Verify screens can be directly accessed via deep links
15
+ Given I am on the <start> screen
16
+ When I load the <destination> screen
17
+ Then I expect the <destination> screen to be correctly displayed
18
+
19
+ Examples:
20
+ |start |destination |
21
+ |Products |About |
22
+ |Products |Login |
23
+ |Products |Webview |
24
+ |Products |Checkout - Address |
25
+ |Products |Checkout - Payment |
26
+ |About |Products |
@@ -0,0 +1,30 @@
1
+ @mobile @ios @android @regression
2
+
3
+
4
+ Feature: Login page
5
+ In order to ensure comprehensive support for native app login features
6
+ As a developer of the TestCentricity gem
7
+ I expect users to access the app only with valid login credentials
8
+
9
+
10
+ Background:
11
+ Given I have launched the SauceLabs My Demo app
12
+
13
+
14
+ Scenario: Verify login with valid credentials
15
+ Given I am on the Login screen
16
+ When I enter user credentials with valid data
17
+ Then I expect the Checkout - Address screen to be correctly displayed
18
+
19
+
20
+ Scenario Outline: Verify correct error states when using invalid credentials
21
+ Given I am on the Login screen
22
+ When I enter user credentials with <reason>
23
+ Then I expect an error to be displayed due to <reason>
24
+
25
+ Examples:
26
+ |reason |
27
+ |no username |
28
+ |no password |
29
+ |locked account |
30
+ |invalid user |
@@ -0,0 +1,31 @@
1
+ @mobile @ios @android @regression
2
+
3
+
4
+ Feature: Screen Navigation
5
+ In order to ensure comprehensive support for native app navigation features
6
+ As a developer of the TestCentricity gem
7
+ I expect to validate that app screens can be accessed via navigation controls
8
+
9
+
10
+ Background:
11
+ Given I have launched the SauceLabs My Demo app
12
+ And I am on the Products screen
13
+
14
+
15
+ Scenario: Verify navigation menu can be invoked and is properly displayed
16
+ When I open the navigation menu
17
+ Then I expect the navigation menu to be correctly displayed
18
+ When I close the navigation menu
19
+ Then I expect the navigation menu to be hidden
20
+
21
+
22
+ Scenario Outline: Verify screen navigation features
23
+ When I tap the <screen_name> navigation menu item
24
+ Then I expect the <screen_name> screen to be correctly displayed
25
+
26
+ Examples:
27
+ |screen_name |
28
+ |About |
29
+ |Login |
30
+ |Webview |
31
+ |SauceBot Video |
@@ -0,0 +1,72 @@
1
+ include TestCentricity
2
+
3
+
4
+ Given(/^I have launched the SauceLabs My Demo app$/) do
5
+ # activate the app
6
+ AppiumConnect.launch_app
7
+ end
8
+
9
+
10
+ When(/^I (?:load|am on) the (.*) (?:page|screen)$/) do |screen_name|
11
+ # find and load the specified target page/screen
12
+ target_page = PageManager.find_page(screen_name)
13
+ target_page.load_page
14
+ end
15
+
16
+
17
+ When(/^I (?:click|tap) the ([^\"]*) navigation menu item$/) do |screen_name|
18
+ # find and navigate to the specified target page/screen
19
+ target_page = PageManager.find_page(screen_name)
20
+ target_page.navigate_to
21
+ end
22
+
23
+
24
+ Then(/^I expect the (.*) (?:page|screen) to be correctly displayed$/) do |screen_name|
25
+ # find and verify that the specified target page/screen is loaded
26
+ target_page = PageManager.find_page(screen_name)
27
+ target_page.verify_page_exists
28
+ # verify that target page/screen is correctly displayed
29
+ target_page.verify_page_ui
30
+ end
31
+
32
+
33
+ When(/^I enter user credentials with (.*)$/) do |reason|
34
+ case reason.gsub(/\s+/, '_').downcase.to_sym
35
+ when :valid_data
36
+ username = 'bob@example.com'
37
+ password = '10203040'
38
+ when :invalid_user
39
+ username = 'iggy.snicklefritz@example.com'
40
+ password = '10203040'
41
+ when :locked_account
42
+ username = 'alice@example.com'
43
+ password = '10203040'
44
+ when :no_username
45
+ password = '10203040'
46
+ when :no_password
47
+ username = 'bob@example.com'
48
+ else
49
+ raise "#{reason} is not a valid selector"
50
+ end
51
+ login_screen.login(username, password)
52
+ end
53
+
54
+
55
+ Then(/^I expect an error to be displayed due to (.*)$/) do |reason|
56
+ PageManager.current_page.verify_entry_error(reason)
57
+ end
58
+
59
+
60
+ When(/^I (.*) the navigation menu$/) do |action|
61
+ PageManager.current_page.nav_menu_action(action)
62
+ end
63
+
64
+
65
+ Then(/^I expect the navigation menu to be correctly displayed$/) do
66
+ PageManager.current_page.verify_nav_menu(state = :displayed)
67
+ end
68
+
69
+
70
+ Then(/^I expect the navigation menu to be hidden$/) do
71
+ PageManager.current_page.verify_nav_menu(state = :closed)
72
+ end
@@ -0,0 +1,11 @@
1
+ class AboutScreen < BaseAppScreen
2
+ trait(:page_name) { 'About' }
3
+ trait(:page_locator) { { accessibility_id: 'about screen' } }
4
+ trait(:page_url) { 'about' }
5
+ trait(:navigator) { nav_menu.open_about }
6
+
7
+ def verify_page_ui
8
+ super
9
+ verify_ui_states(header_label => { visible: true, caption: 'About' })
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ class BaseAppScreen < TestCentricity::ScreenObject
2
+ include SharedBaseAppScreen
3
+
4
+ trait(:page_name) { 'Base App Screen' }
5
+
6
+ # Base App screen UI elements
7
+ buttons menu_button: { accessibility_id: 'open menu' },
8
+ cart_button: { accessibility_id: 'cart badge' }
9
+ labels header_label: { xpath: '//android.view.ViewGroup[@content-desc="container header"]/android.widget.TextView' },
10
+ cart_quantity: { xpath: '//android.view.ViewGroup[@content-desc="cart badge"]/android.widget.TextView' }
11
+ section :nav_menu, NavMenu
12
+
13
+ def verify_page_ui
14
+ ui = {
15
+ menu_button => { visible: true, enabled: true },
16
+ cart_button => { visible: true, enabled: true }
17
+ }
18
+ verify_ui_states(ui)
19
+ end
20
+
21
+ def invoke_nav_menu
22
+ menu_button.click
23
+ nav_menu.wait_until_visible(3)
24
+ end
25
+
26
+ def open_cart
27
+ cart_button.click
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ class CheckoutAddressScreen < BaseAppScreen
2
+ include SharedCheckoutAddressScreen
3
+
4
+ trait(:page_name) { 'Checkout - Address' }
5
+ trait(:page_locator) { { accessibility_id: 'checkout address screen' } }
6
+ trait(:page_url) { 'checkout-address' }
7
+
8
+ # Checkout Address screen UI elements
9
+ textfields fullname_field: { accessibility_id: 'Full Name* input field' },
10
+ address1_field: { accessibility_id: 'Address Line 1* input field' },
11
+ address2_field: { accessibility_id: 'Address Line 2 input field' },
12
+ city_field: { accessibility_id: 'City* input field' },
13
+ state_region_field: { accessibility_id: 'State/Region input field' },
14
+ zip_code_field: { accessibility_id: 'Zip Code* input field' },
15
+ country_field: { accessibility_id: 'Country* input field' }
16
+ button :to_payment_button, { accessibility_id: 'To Payment button' }
17
+ end
@@ -0,0 +1,22 @@
1
+ class CheckoutPaymentScreen < BaseAppScreen
2
+ include SharedCheckoutPaymentScreen
3
+
4
+ trait(:page_name) { 'Checkout - Payment' }
5
+ trait(:page_locator) { { accessibility_id: 'checkout payment screen' } }
6
+ trait(:page_url) { 'checkout-payment' }
7
+
8
+ # Checkout Payment screen UI elements
9
+ textfields payee_name_field: { xpath: '(//android.widget.EditText[@content-desc="Full Name* input field"])[1]' },
10
+ card_number_field: { accessibility_id: 'Card Number* input field' },
11
+ expiration_field: { accessibility_id: 'Expiration Date* input field' },
12
+ security_code_field: { accessibility_id: 'Security Code* input field' },
13
+ recipient_name_field: { xpath: '(//android.widget.EditText[@content-desc="Full Name* input field"])[2]' },
14
+ address1_field: { accessibility_id: 'Address Line 1* input field' },
15
+ address2_field: { accessibility_id: 'Address Line 2 input field' },
16
+ city_field: { accessibility_id: 'City* input field' },
17
+ state_region_field: { accessibility_id: 'State/Region input field' },
18
+ zip_code_field: { accessibility_id: 'Zip Code* input field' },
19
+ country_field: { accessibility_id: 'Country* input field' }
20
+ checkbox :bill_address_check, { xpath: '//android.view.ViewGroup[contains(@content-desc, "checkbox")]/android.view.ViewGroup'}
21
+ button :review_order_button, { accessibility_id: 'Review Order button' }
22
+ end
@@ -0,0 +1,18 @@
1
+ class LoginScreen < BaseAppScreen
2
+ include SharedLoginScreen
3
+
4
+ trait(:page_name) { 'Login' }
5
+ trait(:page_locator) { { accessibility_id: 'login screen' } }
6
+ trait(:page_url) { 'login' }
7
+ trait(:navigator) { nav_menu.open_log_in }
8
+
9
+ # Login screen UI elements
10
+ labels username_label: { xpath: '//android.view.ViewGroup[@content-desc="login screen"]/android.widget.ScrollView/android.view.ViewGroup/android.widget.TextView[2]'},
11
+ password_label: { xpath: '//android.view.ViewGroup[@content-desc="login screen"]/android.widget.ScrollView/android.view.ViewGroup/android.widget.TextView[3]'},
12
+ username_error: { accessibility_id: 'Username-error-message' },
13
+ password_error: { accessibility_id: 'Password-error-message' },
14
+ generic_error: { accessibility_id: 'generic-error-message' }
15
+ textfields username_field: { accessibility_id: 'Username input field' },
16
+ password_field: { accessibility_id: 'Password input field' }
17
+ button :login_button, { accessibility_id: 'Login button' }
18
+ end
@@ -0,0 +1,13 @@
1
+ class ProductsScreen < BaseAppScreen
2
+ trait(:page_name) { 'Products' }
3
+ trait(:page_locator) { { accessibility_id: 'products screen' } }
4
+ trait(:page_url) { 'store-overview' }
5
+
6
+ def verify_page_ui
7
+ super
8
+ ui = {
9
+ header_label => { visible: true, caption: 'Products' }
10
+ }
11
+ verify_ui_states(ui)
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ class SauceBotScreen < BaseAppScreen
2
+ include SharedSauceBotScreen
3
+
4
+ trait(:page_name) { 'SauceBot Video' }
5
+ trait(:page_locator) { { accessibility_id: 'SauceBot screen' } }
6
+ trait(:navigator) { nav_menu.open_saucebot_video }
7
+
8
+ # SauceBot Video screen UI elements
9
+ element :video_player, { xpath: '//android.view.View[@resource-id="movie_player"]' }
10
+ buttons video_back: { accessibility_id: 'video icon backward' },
11
+ video_play: { accessibility_id: 'video icon play' },
12
+ video_pause: { accessibility_id: 'video icon stop' },
13
+ video_forward: { accessibility_id: 'video icon forward' },
14
+ video_volume: { accessibility_id: 'video icon volume-up' },
15
+ video_mute: { accessibility_id: 'video icon volume-mute' }
16
+ end
@@ -0,0 +1,13 @@
1
+ class WebViewScreen < BaseAppScreen
2
+ include SharedWebViewScreen
3
+
4
+ trait(:page_name) { 'Webview' }
5
+ trait(:page_locator) { { accessibility_id: 'webview selection screen' } }
6
+ trait(:page_url) { 'webview' }
7
+ trait(:navigator) { nav_menu.open_webview }
8
+
9
+ # Webview screen UI elements
10
+ label :url_label, { xpath: '//android.view.ViewGroup[@content-desc="webview selection screen"]/android.widget.ScrollView/android.view.ViewGroup/android.widget.TextView[1]' }
11
+ textfield :url_field, { accessibility_id: 'URL input field' }
12
+ button :go_to_site_button, { accessibility_id: 'Go To Site button' }
13
+ end
@@ -0,0 +1,39 @@
1
+ class NavMenu < TestCentricity::ScreenSection
2
+ include SharedNavMenu
3
+
4
+ trait(:section_name) { 'Nav Menu' }
5
+ trait(:section_locator) { { xpath: '//android.widget.ScrollView/android.view.ViewGroup' } }
6
+
7
+ # Nav Menu UI elements
8
+ buttons close_button: { accessibility_id: 'menu item catalog' },
9
+ webview_button: { accessibility_id: 'menu item webview' },
10
+ qr_code_button: { accessibility_id: 'menu item qr code scanner' },
11
+ geo_location_button: { accessibility_id: 'menu item geo location' },
12
+ drawing_button: { accessibility_id: 'menu item drawing' },
13
+ about_button: { accessibility_id: 'menu item about' },
14
+ reset_app_button: { accessibility_id: 'menu item reset app' },
15
+ biometrics_button: { accessibility_id: 'menu item biometrics' },
16
+ log_in_button: { accessibility_id: 'menu item log in' },
17
+ log_out_button: { accessibility_id: 'menu item log out' },
18
+ api_calls_button: { accessibility_id: 'menu item api calls' },
19
+ sauce_video_button: { accessibility_id: 'menu item sauce bot video' }
20
+
21
+ def verify_ui
22
+ ui = {
23
+ self => { visible: true },
24
+ close_button => { visible: true, enabled: true },
25
+ webview_button => { visible: true, enabled: true, caption: 'Webview' },
26
+ qr_code_button => { visible: true, enabled: true, caption: 'QR Code Scanner' },
27
+ geo_location_button => { visible: true, enabled: true, caption: 'Geo Location' },
28
+ drawing_button => { visible: true, enabled: true, caption: 'Drawing' },
29
+ about_button => { visible: true, enabled: true, caption: 'About' },
30
+ reset_app_button => { visible: true, enabled: true, caption: 'Reset App State' },
31
+ biometrics_button => { visible: true, enabled: true, caption: 'FingerPrint' },
32
+ log_in_button => { visible: true, enabled: true, caption: 'Log In' },
33
+ log_out_button => { visible: true, enabled: true, caption: 'Log Out' },
34
+ api_calls_button => { visible: true, enabled: true, caption: 'Api Calls' },
35
+ sauce_video_button => { visible: true, enabled: true, caption: 'Sauce Bot Video' }
36
+ }
37
+ verify_ui_states(ui)
38
+ end
39
+ end