From 770fd6c76bf211fb4400a1d8a8e2e863f62485cc Mon Sep 17 00:00:00 2001 From: Anand Bagmar Date: Wed, 21 Jun 2023 16:20:21 +0530 Subject: [PATCH] Add support for Selenium4, Appium2.0 and Applitools v5 SDK (#178) * updated to latest ATD (from main branch) * fix io.netty compile error (#149) * merge from main, and updated based on new ATD * fixed attaching device logs to reportportal * use the latest ATD (from fixesForTeswiz branch) * updated the CI workflow branches * updated dependencies * updated multiuser-multi-app scenario * downgraded com.epam.reportportal:agent-java-cucumber6 to 5.1.2 * removed unnecessary dependencies and use them from atd. (atd uses the latest reportportal's agent-java-cucumber6 - 5.1.3 * updated ATD which uses agent-java-cucumber6 v5.1.0 * Updated ATD: reverted to agent-java-cucumber6 v5.1.3. Added debug trace to see what launchId is returned by rq.getLaunchUuid(); * updated teswiz version * updated ATD and teswiz to create the correct reportportal URL is launchID is not available as a system property * use ATD which has all dependencies updated. No need to retrieve launchID from ScenarioReporter - was behaving same as getting it from system property - rp.launch.id * Created files for VodQA application testing and implemented scroll() method (#179) * Created config and capabilities file for VodQA App testing * Created feature, steps, BL, abstract screen and android screen files for VodQA scroll testing * VodQA config file path set in CONFIG variable * Implementation of scroll(fromPoint, toPoint) method according to appium 2.0 changes * removed config path * added command to execute feature, changed scenario name * changed function and arguement names * merged "When" "And" in feature and its related code in other files * replaced 700 millisec with 1 second wait * Removed string passed from feature, no longer needed * modified steps according to feature * changed method names and removed arguments * changed method names, removed arguments, added visual validations and moved locators to top * changed "Given" * changed steps according to feature --------- Co-authored-by: Mukund1 Gupta * Tap in the middle of the screen (#180) * Tap in the middle of the screen * Changed return type in business layer and android screen * removing unused locators * Resolved comments * Tap in the middle of the screen * removing unused locators * removing existing files * Revert "removing existing files" This reverts commit 44259e6633aa62cec6144918a92cbe907f80d0aa. * Updated according to the comments * Changing function names and variable names * Update vodqa.feature * Appium2.0 (#183) * updated driver method scrollDownByScreenSize for appium 2.0 implementation * added test steps for scrollDownByScreenSize method * added test step implementation for scenario to test scrollDownByScreenSize * added visually for scrolled screen * added a wait for an element to remove flakiness due to screen load * removed unused imports * Updated scroll down by screen size scenario name * removed duplicate step * resolved issue due to conflict * AppiumDriver.closeApp() replaced by AndroidDriver.terminateApp() (#187) * Created config and capabilities file for VodQA App testing * Created feature, steps, BL, abstract screen and android screen files for VodQA scroll testing * VodQA config file path set in CONFIG variable * Implementation of scroll(fromPoint, toPoint) method according to appium 2.0 changes * removed config path * added command to execute feature, changed scenario name * changed function and arguement names * merged "When" "And" in feature and its related code in other files * replaced 700 millisec with 1 second wait * Removed string passed from feature, no longer needed * modified steps according to feature * changed method names and removed arguments * changed method names, removed arguments, added visual validations and moved locators to top * changed "Given" * changed steps according to feature * replaced closeApp() with terminateApp(appPackageName) and called it using AndroidDriver instead of AppiumDriver * optimized imports --------- Co-authored-by: Mukund1 Gupta * replace closeApp() with terminateApp(), updated todo to test this change (#188) * Created config and capabilities file for VodQA App testing * Created feature, steps, BL, abstract screen and android screen files for VodQA scroll testing * VodQA config file path set in CONFIG variable * Implementation of scroll(fromPoint, toPoint) method according to appium 2.0 changes * removed config path * added command to execute feature, changed scenario name * changed function and arguement names * merged "When" "And" in feature and its related code in other files * replaced 700 millisec with 1 second wait * Removed string passed from feature, no longer needed * modified steps according to feature * changed method names and removed arguments * changed method names, removed arguments, added visual validations and moved locators to top * changed "Given" * changed steps according to feature * replaced closeApp() with terminateApp(appPackageName) and called it using AndroidDriver instead of AppiumDriver * optimized imports * replaced closeApp() with terminateApp() using AndroidDriver for closeWindowsAppOnMachine method, updated TODO to test on windows app in windows OS --------- Co-authored-by: Mukund1 Gupta * select Notification From Notification Drawer (#182) * Added implementation for selectNotificationFromNotificationDrawer() and scenario to test test the feature in JioMeet * Removed commented Code * Code formating * Renamed sequenced object * Updated the scenario name * updated the apk name for jio meet --------- Co-authored-by: Darshan * Appium2.0: Swipe Gesture implementation and addition of 3 test scenarios (#186) * implemented swipe for android and added a new method swipeByPassingPercentageAttributes in Driver.java * updated swipe left and swipe right methods in Driver.java * Added 3 Test scenarios for validating swipe gestures * using duration as seconds instead of milli seconds in the swipe gesture method * updated steps and screen names * added visual validation for swipe gesture test * resolved review comments * taken pull from origin branch * throwing exception in checkPercentagesAreValid() method in Driver.java * minor changes * minor changes * Hybrid App Compatibility of Context Switching utility for Appium 2.0 (#184) * added feature for context switching * Latest pull * Implementation of test scenario * took latest pull * Added visual checks to the screens * Updated step file * Modified feature file and removed commented code * Updated step file * updated feature file and added visual checks * Backmerging from appium:2.0 (#191) * cleaned up build.gradle * updated fasterxmlJackson and applitools dependency version * set next teswiz version to v0.0.80 * revert to Applitools library 5.54.0 * Appium2.0 : Added test scenario for ScrollVertically by percentage (#193) * removed unused imports * Added scroll vertically by percentage scenario * Added step implementation for scroll vertically by percentage scenario * Appium2.0: Scroll in dynamic layer implementation and addition of a test scenario (#194) * implemented swipe for android and added a new method swipeByPassingPercentageAttributes in Driver.java * updated swipe left and swipe right methods in Driver.java * Added 3 Test scenarios for validating swipe gestures * using duration as seconds instead of milli seconds in the swipe gesture method * updated steps and screen names * added visual validation for swipe gesture test * resolved review comments * taken pull from origin branch * throwing exception in checkPercentagesAreValid() method in Driver.java * minor changes * minor changes * implemented scroll in dynamic layer in Driver.java * updated scroll function points in Driver.java * added test scenario to validate scrollInDynamicLayer() functionality * replaced from and to screen height in scrollDownByScreenSize() * replaced from and to elements in test scenario * added a direction enum * passing direction enum to scrollInDynamicLayer() * passing direction from feature file * added tags for few scenarios in vodqa.feature * changed Direction into enum * removed direction validation in scrollInDynamicLayer() * passing direction onj instead of string * minor changes * Changed appiumDriver.queryAppState() to androidDriver.queryAppState() (#195) * queryAppState * Throw exception for other platform * Update AppiumDriverManager.java * Added gradle command to execute the scenario * Throw exception for other platform * Update AppiumDriverManager.java * reverting feature file changes * removing extra else condition * Removed redundant methods from vodQa scenarios (#197) * updated Applitools version to v5.55.0 * updated to ATD 13.1.0 * removed appium2.0 branch from CI workflow * updated app path for calculator and jiomeet caps (#198) * fix apk path in capabilities file * added missing serverConfig to capabilities file * use remote path for VodQA.apk --------- Co-authored-by: Sai Krishna Co-authored-by: Mukund Gupta Co-authored-by: Mukund1 Gupta Co-authored-by: MedhaGupta-Ril <122343539+MedhaGupta-Ril@users.noreply.github.com> Co-authored-by: aamisharora1 <107185850+aamisharora1@users.noreply.github.com> Co-authored-by: Darshan S <57480993+DarshanS4444@users.noreply.github.com> Co-authored-by: Darshan Co-authored-by: Tammewar snehit <31981138+snehith07@users.noreply.github.com> Co-authored-by: ngourkar <117643274+ngourkar@users.noreply.github.com> Co-authored-by: Raghav Garg <117148030+raghavgarg1996@users.noreply.github.com> --- .github/workflows/CI.yml | 6 +- .gitignore | 3 +- build.gradle | 51 ++-- build.gradle.sample | 2 +- caps/ajio_local_capabilities.json | 16 +- caps/calculator2_local_capabilities.json | 17 +- caps/calculator_local_capabilities.json | 16 +- caps/calculator_pcloudy_capabilities.json | 14 +- caps/confengine_local_capabilities.json | 16 +- caps/dineout_local_capabilities.json | 16 +- caps/indigo_local_capabilities.json | 16 +- caps/jiomeet_browserStack_capabilities.json | 16 +- caps/jiomeet_local_capabilities.json | 17 +- caps/jiomeetlatest_capabilities.json | 16 +- caps/jiomeetoldversion_capabilities.json | 16 +- caps/theapp_browserStack_capabilities.json | 19 +- caps/theapp_headspin_capabilities.json | 14 +- caps/theapp_local_capabilities.json | 16 +- caps/theapp_pcloudy_capabilities.json | 14 +- caps/vodqa_local_capabilities.json | 36 +++ caps/windows_capabilities.json | 12 + configs/vodqa_local_config.properties | 28 ++ .../com/znsio/teswiz/entities/Direction.java | 11 + .../listener/CucumberWebScenarioListener.java | 8 +- .../CucumberWebScenarioReporterListener.java | 5 +- .../teswiz/runner/AppiumDriverManager.java | 185 ++++++------ .../teswiz/runner/BrowserDriverManager.java | 8 +- .../com/znsio/teswiz/runner/DeviceSetup.java | 12 +- .../java/com/znsio/teswiz/runner/Driver.java | 269 +++++++++++------- .../teswiz/runner/LocalDevicesSetup.java | 75 +---- .../businessLayer/jiomeet/InAMeetingBL.java | 14 + .../teswiz/businessLayer/vodqa/VodqaBL.java | 134 +++++++++ .../BrowserStackImageInjectionTest.java | 3 +- .../ConfEngineLandingScreenAndroid.java | 7 +- .../IndigoGiftVouchersScreenAndroid.java | 2 +- .../jiomeet/InAMeetingScreenAndroid.java | 16 +- .../theapp/ClipboardDemoScreenAndroid.java | 6 +- .../vodqa/NativeViewScreenAndroid.java | 29 ++ .../android/vodqa/VodqaScreenAndroid.java | 190 +++++++++++++ .../android/vodqa/WebViewScreenAndroid.java | 52 ++++ .../screen/jiomeet/InAMeetingScreen.java | 3 + .../teswiz/screen/vodqa/NativeViewScreen.java | 31 ++ .../teswiz/screen/vodqa/VodqaScreen.java | 66 +++++ .../teswiz/screen/vodqa/WebViewScreen.java | 35 +++ .../web/jiomeet/InAMeetingScreenWeb.java | 12 +- .../znsio/teswiz/steps/AppLaunchSteps.java | 2 +- .../com/znsio/teswiz/steps/JioMeetSteps.java | 10 + .../com/znsio/teswiz/steps/VodQASteps.java | 102 +++++++ .../com/znsio/teswiz/features/jiomeet.feature | 9 +- .../features/multiuser-multidevice.feature | 14 +- .../com/znsio/teswiz/features/vodqa.feature | 72 +++++ 51 files changed, 1367 insertions(+), 392 deletions(-) create mode 100644 caps/vodqa_local_capabilities.json create mode 100644 configs/vodqa_local_config.properties create mode 100644 src/main/java/com/znsio/teswiz/entities/Direction.java create mode 100644 src/test/java/com/znsio/teswiz/businessLayer/vodqa/VodqaBL.java create mode 100644 src/test/java/com/znsio/teswiz/screen/android/vodqa/NativeViewScreenAndroid.java create mode 100644 src/test/java/com/znsio/teswiz/screen/android/vodqa/VodqaScreenAndroid.java create mode 100644 src/test/java/com/znsio/teswiz/screen/android/vodqa/WebViewScreenAndroid.java create mode 100644 src/test/java/com/znsio/teswiz/screen/vodqa/NativeViewScreen.java create mode 100644 src/test/java/com/znsio/teswiz/screen/vodqa/VodqaScreen.java create mode 100644 src/test/java/com/znsio/teswiz/screen/vodqa/WebViewScreen.java create mode 100644 src/test/java/com/znsio/teswiz/steps/VodQASteps.java create mode 100644 src/test/resources/com/znsio/teswiz/features/vodqa.feature diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7b7bea1c9..e72863416 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -9,9 +9,9 @@ name: Java CI with Gradle on: push: - branches: [ main, newSamples ] + branches: [ main ] pull_request: - branches: [ main, newSamples ] + branches: [ main ] jobs: build: @@ -26,6 +26,6 @@ jobs: java-version: '11' distribution: 'temurin' - name: Build with Gradle - uses: gradle/gradle-build-action@6095a76664413da4c8c134ee32e8a8ae900f0f1f + uses: gradle/gradle-build-action@749f47bda3e44aa060e82d7b3ef7e40d953bd629 with: arguments: build --refresh-dependencies diff --git a/.gitignore b/.gitignore index 2707b2540..53857e04e 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,5 @@ upload libs *.plantuml reportportal.lock -reportportal.sync \ No newline at end of file +reportportal.sync +.vscode/* \ No newline at end of file diff --git a/build.gradle b/build.gradle index 69c1a4214..e7211d538 100644 --- a/build.gradle +++ b/build.gradle @@ -4,24 +4,21 @@ buildscript { ext { gradleVersion = '7.3.3' assertJVersion = '3.24.2' - atdVersion = 'dbef9be' - applitoolsSeleniumVersion = '3.213.0' - applitoolsAppiumVersion = '3.213.0' + atdVersion = '13.1.0' + applitoolsSeleniumVersion = '5.55.0' + applitoolsAppiumVersion = '5.55.0' + applitoolsUniversalCoreVersion = '5.55.0' commonsLang3Version = '3.12.0' unirestVersion = '3.14.2' jadbVersion = '1.2.1' - webDriverManagerVersion = '5.3.2' - googleCodeJsonSimpleVersion = '1.1.1' - junitVersion = '5.9.2' + webDriverManagerVersion = '5.3.3' + junitVersion = '5.9.3' slf4jVersion = '2.0.7' - reportportalAgentCucumberVersion = '5.0.6' - reportportalAgentTestNGVersion = '5.0.11' - fasterxmlJacksonVersion = '2.14.2' - jsonPathVersion = '2.8.0' - everitSchemaValidatorVersion = '1.5.1' - jodaTimeVersion = '2.12.4' + fasterxmlJacksonVersion = '2.15.2' + jodaTimeVersion = '2.12.5' masterThoughtVersion = '5.7.5' browserStackLocalVersion = '1.0.7' + jetbrainsAnnotationsVersion = '24.0.0' } } @@ -34,7 +31,7 @@ plugins { } group = 'com.github.znsio' -version '0.0.74' +version '0.0.80' repositories { mavenLocal() @@ -57,6 +54,7 @@ compileJava { options.encoding = "UTF-8" } + idea { module { downloadJavadoc = true @@ -68,35 +66,21 @@ dependencies { implementation fileTree(dir: "$project.projectDir/libs", include: ['*.jar']) implementation files("$buildDir/classes/main") implementation files("$buildDir/classes/test") - implementation "com.googlecode.json-simple:json-simple:$project.googleCodeJsonSimpleVersion" implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$project.fasterxmlJacksonVersion" implementation "com.konghq:unirest-java:$project.unirestVersion" implementation "org.assertj:assertj-core:$project.assertJVersion" implementation "com.github.AppiumTestDistribution:AppiumTestDistribution:$project.atdVersion" implementation "org.apache.commons:commons-lang3:$project.commonsLang3Version" implementation "io.github.bonigarcia:webdrivermanager:$project.webDriverManagerVersion" - implementation "com.jayway.jsonpath:json-path:$project.jsonPathVersion" implementation "com.github.vidstige:jadb:$project.jadbVersion" + implementation "org.jetbrains:annotations:$project.jetbrainsAnnotationsVersion" implementation "org.junit.jupiter:junit-jupiter:$project.junitVersion" - implementation "com.epam.reportportal:agent-java-cucumber6:$project.reportportalAgentCucumberVersion" implementation "org.slf4j:slf4j-api:$project.slf4jVersion" implementation "joda-time:joda-time:$project.jodaTimeVersion" implementation "com.browserstack:browserstack-local-java:$project.browserStackLocalVersion" - implementation("com.epam.reportportal:agent-java-testng:$project.reportportalAgentTestNGVersion") { - exclude group: 'com.fasterxml.jackson.core' - } - implementation("com.applitools:eyes-appium-java3:$project.applitoolsAppiumVersion") { - exclude group: 'java-client' - exclude group: 'selenium-java' - exclude group: 'eyes-connectivity-java5-jersey2x' - } - implementation("com.applitools:eyes-selenium-java3:$project.applitoolsSeleniumVersion") { - exclude group: 'java-client' - exclude group: 'selenium-java' - exclude group: 'eyes-connectivity-java5-jersey2x' - } - implementation "com.applitools:eyes-connectivity-java3-jersey1x:$project.applitoolsSeleniumVersion" - implementation "org.everit.json:org.everit.json.schema:$project.everitSchemaValidatorVersion" + implementation "com.applitools:eyes-appium-java5:$project.applitoolsAppiumVersion" + implementation "com.applitools:eyes-selenium-java5:$project.applitoolsSeleniumVersion" + implementation "com.applitools:eyes-universal-core-mac:$project.applitoolsUniversalCoreVersion" implementation "net.masterthought:cucumber-reporting:$masterThoughtVersion" } @@ -177,9 +161,12 @@ task run(type: JavaExec) { ] args = runnerArgs + println("Debug mode: " + System.getProperty('debug', 'false')) // attach debugger if (System.getProperty('debug', 'false') == 'true') { - jvmArgs '-Xdebug', '-agentlib:jdwp=transport=dt_socket,server=n,address=192.168.29.248:9009,suspend=y' + println("In debug mode") + jvmArgs '-Xdebug', '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,' + + 'address=*:5005' } } mainClass = "com.znsio.teswiz.runner.Runner" diff --git a/build.gradle.sample b/build.gradle.sample index ae04c57cb..fc6334ce1 100644 --- a/build.gradle.sample +++ b/build.gradle.sample @@ -3,7 +3,7 @@ import java.text.SimpleDateFormat buildscript { ext { gradleVersion = '7.3.3' - teswizVersion = '0.0.74' + teswizVersion = '0.0.80' } repositories { mavenLocal() diff --git a/caps/ajio_local_capabilities.json b/caps/ajio_local_capabilities.json index 02e7b3709..dcea01c46 100644 --- a/caps/ajio_local_capabilities.json +++ b/caps/ajio_local_capabilities.json @@ -1,9 +1,7 @@ { "android": { "adbExecTimeout": 45000, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/ajio-8-3-4.apk" - }, + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/ajio-8-3-4.apk", "appActivity": "com.ril.ajio.launch.activity.SplashScreenActivity", "appPackage": "com.ril.ajio", "appWaitDuration": 45000, @@ -21,6 +19,18 @@ "skipUnlock": true, "noReset": false }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "hostMachines": [ { "machineIP": "127.0.0.1", diff --git a/caps/calculator2_local_capabilities.json b/caps/calculator2_local_capabilities.json index 946997b66..2d538d91d 100644 --- a/caps/calculator2_local_capabilities.json +++ b/caps/calculator2_local_capabilities.json @@ -1,9 +1,7 @@ { "android": { "adbExecTimeout": 45000, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/AndroidCalculator.apk" - }, + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/AndroidCalculator.apk", "appPackage": "com.android2.calculator3", "appActivity": "com.android2.calculator3.Calculator", "appWaitDuration": 45000, @@ -16,10 +14,21 @@ "newCommandTimeout": 12000, "noSign": true, "platformName": "android", - "platformVersion": "11.0", "printPageSourceOnFindFailure": true, "skipUnlock": true }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "hostMachines": [ { "machineIP": "127.0.0.1" diff --git a/caps/calculator_local_capabilities.json b/caps/calculator_local_capabilities.json index 946997b66..03a38044d 100644 --- a/caps/calculator_local_capabilities.json +++ b/caps/calculator_local_capabilities.json @@ -1,9 +1,7 @@ { "android": { "adbExecTimeout": 45000, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/AndroidCalculator.apk" - }, + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/AndroidCalculator.apk", "appPackage": "com.android2.calculator3", "appActivity": "com.android2.calculator3.Calculator", "appWaitDuration": 45000, @@ -16,10 +14,20 @@ "newCommandTimeout": 12000, "noSign": true, "platformName": "android", - "platformVersion": "11.0", "printPageSourceOnFindFailure": true, "skipUnlock": true }, + "serverConfig" : { + "server": { + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "hostMachines": [ { "machineIP": "127.0.0.1" diff --git a/caps/calculator_pcloudy_capabilities.json b/caps/calculator_pcloudy_capabilities.json index 6837d6c6c..5eab369f2 100644 --- a/caps/calculator_pcloudy_capabilities.json +++ b/caps/calculator_pcloudy_capabilities.json @@ -17,8 +17,18 @@ "unicodeKeyboard": true, "resetKeyboard": true, "noReset": false, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/AndroidCalculator.apk" + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/AndroidCalculator.apk" + }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } } }, "cloud": { diff --git a/caps/confengine_local_capabilities.json b/caps/confengine_local_capabilities.json index d61bdfda9..3de029aa9 100644 --- a/caps/confengine_local_capabilities.json +++ b/caps/confengine_local_capabilities.json @@ -1,9 +1,7 @@ { "android": { "adbExecTimeout": 45000, - "app": { - "local": "./src/test/resources/sampleApps/confEngine-devApi-debug.apk" - }, + "app": "./src/test/resources/sampleApps/confEngine-devApi-debug.apk", "appActivity": "com.confengine.confengine.activity.Html5Activity", "appPackage": "com.confengine.confengine", "appWaitDuration": 45000, @@ -21,6 +19,18 @@ "skipUnlock": true, "noReset": false }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "hostMachines": [ { "machineIP": "127.0.0.1", diff --git a/caps/dineout_local_capabilities.json b/caps/dineout_local_capabilities.json index e0325f430..bb3283207 100644 --- a/caps/dineout_local_capabilities.json +++ b/caps/dineout_local_capabilities.json @@ -1,9 +1,7 @@ { "android": { "adbExecTimeout": 45000, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/dineout.book_2022-10-18.apk" - }, + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/dineout.book_2022-10-18.apk", "appActivity": "com.dineout.book.splash.presentation.view.NewSplashActivity", "appPackage": "com.dineout.book", "appWaitDuration": 45000, @@ -21,6 +19,18 @@ "skipUnlock": true, "noReset": false }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "hostMachines": [ { "machineIP": "127.0.0.1", diff --git a/caps/indigo_local_capabilities.json b/caps/indigo_local_capabilities.json index 8a4f5ee3c..e3cea768c 100644 --- a/caps/indigo_local_capabilities.json +++ b/caps/indigo_local_capabilities.json @@ -1,9 +1,7 @@ { "android": { "adbExecTimeout": 45000, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/IndiGoFlight-App_5.0.85.apk" - }, + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/IndiGoFlight-App_5.0.85.apk", "appActivity": "in.goindigo.android.ui.modules.splash.SplashActivity", "appPackage": "in.goindigo.android", "appWaitDuration": 45000, @@ -21,6 +19,18 @@ "skipUnlock": true, "noReset": false }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "hostMachines": [ { "machineIP": "127.0.0.1", diff --git a/caps/jiomeet_browserStack_capabilities.json b/caps/jiomeet_browserStack_capabilities.json index 5dc06faac..d301a888c 100644 --- a/caps/jiomeet_browserStack_capabilities.json +++ b/caps/jiomeet_browserStack_capabilities.json @@ -1,9 +1,7 @@ { "android": { "adbExecTimeout": 45000, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/com.jio.rilconferences_v4.21.6.7-421607_Android-5.0.apk" - }, + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/com.jio.rilconferences_v4.21.6.7-421607_Android-5.0.apk", "appActivity": "org.jio.meet.introduction.views.SplashActivity", "appPackage": "com.jio.rilconferences", "automationName": "UiAutomator2", @@ -26,6 +24,18 @@ "browserstack.locale": "IN", "project": "teswiz" }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "cloud": { "android": [ ] diff --git a/caps/jiomeet_local_capabilities.json b/caps/jiomeet_local_capabilities.json index aabbed2eb..656b64f98 100644 --- a/caps/jiomeet_local_capabilities.json +++ b/caps/jiomeet_local_capabilities.json @@ -1,9 +1,7 @@ { "android": { "adbExecTimeout": 45000, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/com.jio.rilconferences_v4.21.6.7-421607_Android-5.0.apk" - }, + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/com.jio.rilconferences_v4.21.6.7-421607_Android-5.0.apk", "appActivity": "org.jio.meet.introduction.views.SplashActivity", "appPackage": "com.jio.rilconferences", "appWaitDuration": 45000, @@ -16,11 +14,22 @@ "newCommandTimeout": 12000, "noSign": true, "platformName": "android", - "platformVersion": "11.0", "printPageSourceOnFindFailure": true, "skipUnlock": true, "noReset": false }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "hostMachines": [ { "machineIP": "127.0.0.1", diff --git a/caps/jiomeetlatest_capabilities.json b/caps/jiomeetlatest_capabilities.json index aabbed2eb..472156c11 100644 --- a/caps/jiomeetlatest_capabilities.json +++ b/caps/jiomeetlatest_capabilities.json @@ -1,9 +1,7 @@ { "android": { "adbExecTimeout": 45000, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/com.jio.rilconferences_v4.21.6.7-421607_Android-5.0.apk" - }, + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/com.jio.rilconferences_v4.21.6.7-421607_Android-5.0.apk", "appActivity": "org.jio.meet.introduction.views.SplashActivity", "appPackage": "com.jio.rilconferences", "appWaitDuration": 45000, @@ -21,6 +19,18 @@ "skipUnlock": true, "noReset": false }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "hostMachines": [ { "machineIP": "127.0.0.1", diff --git a/caps/jiomeetoldversion_capabilities.json b/caps/jiomeetoldversion_capabilities.json index 7d2a095da..caab334e9 100644 --- a/caps/jiomeetoldversion_capabilities.json +++ b/caps/jiomeetoldversion_capabilities.json @@ -1,9 +1,7 @@ { "android": { "adbExecTimeout": 45000, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/com.jio.rilconferences_v4.21.4.5-421405_Android-5.0.apk" - }, + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/com.jio.rilconferences_v4.21.4.5-421405_Android-5.0.apk", "appActivity": "org.jio.meet.introduction.views.SplashActivity", "appPackage": "com.jio.rilconferences", "appWaitDuration": 45000, @@ -21,6 +19,18 @@ "skipUnlock": true, "noReset": false }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "hostMachines": [ { "machineIP": "127.0.0.1", diff --git a/caps/theapp_browserStack_capabilities.json b/caps/theapp_browserStack_capabilities.json index b33ffcbc1..93b252c1a 100644 --- a/caps/theapp_browserStack_capabilities.json +++ b/caps/theapp_browserStack_capabilities.json @@ -21,9 +21,7 @@ "browserstack.gpsLocation": "22,75", "browserstack.locale": "IN", "project": "teswiz", - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/TheApp-release.apk" - } + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/TheApp-release.apk" }, "web": { "browserName": "chrome", @@ -36,6 +34,21 @@ "networkLogs": "true" } }, + "serverConfig": { + "server": { + "port": 31337, + "use-plugins": [ + "device-farm", + "appium-dashboard" + ], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "cloud": { "android": [ ] diff --git a/caps/theapp_headspin_capabilities.json b/caps/theapp_headspin_capabilities.json index 00c971616..7950a1ba0 100644 --- a/caps/theapp_headspin_capabilities.json +++ b/caps/theapp_headspin_capabilities.json @@ -12,8 +12,18 @@ "resetKeyboard": true, "noReset": true, "autoAcceptAlerts": true, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/TheApp-release.apk" + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/TheApp-release.apk" + }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } } }, "cloud": { diff --git a/caps/theapp_local_capabilities.json b/caps/theapp_local_capabilities.json index 2038b2dd4..504fa8b4c 100644 --- a/caps/theapp_local_capabilities.json +++ b/caps/theapp_local_capabilities.json @@ -1,7 +1,6 @@ { "android": { "platformName": "android", - "platformVersion": "11.0", "automationName": "UiAutomator2", "autoGrantPermissions": true, "appPackage": "com.appiumpro.the_app", @@ -10,12 +9,21 @@ "eventTimings": true, "enablePerformanceLogging": true, "printPageSourceOnFindFailure": true, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/TheApp-release.apk" - }, + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/TheApp-release.apk", "deviceName": "android", "noSign": true }, + "serverConfig" : { + "server": { + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "hostMachines": [ { "machineIP": "127.0.0.1" diff --git a/caps/theapp_pcloudy_capabilities.json b/caps/theapp_pcloudy_capabilities.json index d7c71c168..e5381d735 100644 --- a/caps/theapp_pcloudy_capabilities.json +++ b/caps/theapp_pcloudy_capabilities.json @@ -17,8 +17,18 @@ "unicodeKeyboard": true, "resetKeyboard": true, "noReset": false, - "app": { - "local": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/TheApp-release.apk" + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/TheApp-release.apk" + }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } } }, "cloud": { diff --git a/caps/vodqa_local_capabilities.json b/caps/vodqa_local_capabilities.json new file mode 100644 index 000000000..3278b7535 --- /dev/null +++ b/caps/vodqa_local_capabilities.json @@ -0,0 +1,36 @@ +{ + "android": { + "adbExecTimeout": 45000, + "app": "https://github.com/anandbagmar/sampleAppsForNativeMobileAutomation/raw/main/VodQA.apk", + "appPackage": "com.vodqareactnative", + "appActivity": "com.vodqareactnative.MainActivity", + "appWaitDuration": 45000, + "automationName": "UiAutomator2", + "autoGrantPermissions": true, + "deviceName": "android", + "dontStopAppOnReset": true, + "enablePerformanceLogging": true, + "eventTimings": true, + "newCommandTimeout": 12000, + "noSign": true, + "platformName": "android", + "printPageSourceOnFindFailure": true, + "skipUnlock": true + }, + "serverConfig" : { + "server": { + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, + "hostMachines": [ + { + "machineIP": "127.0.0.1" + } + ] +} \ No newline at end of file diff --git a/caps/windows_capabilities.json b/caps/windows_capabilities.json index e495557f4..fcff5f0ca 100644 --- a/caps/windows_capabilities.json +++ b/caps/windows_capabilities.json @@ -5,6 +5,18 @@ "local": "C:\\Windows\\System32\\notepad.exe" } }, + "serverConfig" : { + "server": { + "port": 31337, + "use-plugins": ["device-farm", "appium-dashboard"], + "plugin": { + "device-farm": { + "platform": "android", + "skipChromeDownload": true + } + } + } + }, "hostMachines": [ { "machineIP": "127.0.0.1" diff --git a/configs/vodqa_local_config.properties b/configs/vodqa_local_config.properties new file mode 100644 index 000000000..fc2ebd128 --- /dev/null +++ b/configs/vodqa_local_config.properties @@ -0,0 +1,28 @@ +RUNNER=distribute +FRAMEWORK=cucumber +RUNNER_LEVEL=methods +CAPS=./caps/vodqa_local_capabilities.json +APP_NAME=teswiz +APP_PACKAGE_NAME=com.vodqareactnative +APPLITOOLS_CONFIGURATION=./configs/applitools_config.json +BASE_URL_FOR_WEB=BASE_URL +BROWSER=chrome +ENVIRONMENT_CONFIG_FILE=./src/test/resources/environments.json +CLEANUP_DEVICE_BEFORE_STARTING_EXECUTION=false +IS_VISUAL=false +LOG_DIR=target +LOG_PROPERTIES_FILE=./src/test/resources/log4j.properties +PARALLEL=1 +PLATFORM=android +PROXY_KEY=HTTP_PROXY +BUILD_ID=BUILDID +WEBDRIVER_MANAGER_PROXY_KEY=HTTP_PROXY +REPORT_PORTAL_FILE=./src/test/resources/reportportal.properties +REMOTE_WEBDRIVER_GRID_PORT=TESWIZ_GRID_PORT +RUN_IN_CI=false +TARGET_ENVIRONMENT=prod +TEST_DATA_FILE=./src/test/resources/testData.json +MAX_NUMBER_OF_APPIUM_DRIVERS=5 +MAX_NUMBER_OF_WEB_DRIVERS=5 +BROWSER_CONFIG_FILE=./configs/browser_config.json +BRANCH_NAME=BUILD_SOURCEBRANCH \ No newline at end of file diff --git a/src/main/java/com/znsio/teswiz/entities/Direction.java b/src/main/java/com/znsio/teswiz/entities/Direction.java new file mode 100644 index 000000000..95685c211 --- /dev/null +++ b/src/main/java/com/znsio/teswiz/entities/Direction.java @@ -0,0 +1,11 @@ +package com.znsio.teswiz.entities; + +public enum Direction { + UP("up"), + DOWN("down"); + private final String direction; + + Direction(String direction) { + this.direction = direction; + } +} \ No newline at end of file diff --git a/src/main/java/com/znsio/teswiz/listener/CucumberWebScenarioListener.java b/src/main/java/com/znsio/teswiz/listener/CucumberWebScenarioListener.java index 6018fafba..bc46165ff 100644 --- a/src/main/java/com/znsio/teswiz/listener/CucumberWebScenarioListener.java +++ b/src/main/java/com/znsio/teswiz/listener/CucumberWebScenarioListener.java @@ -4,9 +4,12 @@ import com.context.SessionContext; import com.context.TestExecutionContext; import com.znsio.teswiz.entities.TEST_CONTEXT; -import com.znsio.teswiz.runner.Runner; import io.cucumber.plugin.ConcurrentEventListener; -import io.cucumber.plugin.event.*; +import io.cucumber.plugin.event.EventPublisher; +import io.cucumber.plugin.event.TestCaseFinished; +import io.cucumber.plugin.event.TestCaseStarted; +import io.cucumber.plugin.event.TestRunFinished; +import io.cucumber.plugin.event.TestRunStarted; import org.apache.log4j.Logger; import java.io.File; @@ -78,6 +81,7 @@ private void webCaseFinishedHandler(TestCaseFinished event) { private void webRunFinishedHandler(TestRunFinished event) { LOGGER.info("webRunFinishedHandler: " + event.getResult().toString()); + LOGGER.debug("webRunFinishedHandler: rp.launch.id: " + System.getProperty("rp.launch.id")); SessionContext.setReportPortalLaunchURL(); LOGGER.info(String.format("ThreadId: %d: afterSuite: %n", Thread.currentThread().getId())); } diff --git a/src/main/java/com/znsio/teswiz/listener/CucumberWebScenarioReporterListener.java b/src/main/java/com/znsio/teswiz/listener/CucumberWebScenarioReporterListener.java index 5d4fc358b..11af2b490 100644 --- a/src/main/java/com/znsio/teswiz/listener/CucumberWebScenarioReporterListener.java +++ b/src/main/java/com/znsio/teswiz/listener/CucumberWebScenarioReporterListener.java @@ -13,6 +13,7 @@ public class CucumberWebScenarioReporterListener CucumberWebScenarioReporterListener.class.getName()); private static final String DUMMY_ROOT_SUITE_NAME = "End-2-End Tests"; private static final String RP_STORY_TYPE = "SUITE"; + public static String launchUUID; public CucumberWebScenarioReporterListener() { LOGGER.info("CucumberWebScenarioReporterListener"); @@ -25,7 +26,9 @@ protected void startRootItem() { rq.setName(DUMMY_ROOT_SUITE_NAME); rq.setStartTime(Calendar.getInstance().getTime()); rq.setType(RP_STORY_TYPE); - return launch.get().startTestItem(rq); + launchUUID = this.getItemTree().getLaunchId().blockingGet(); + LOGGER.info("CucumberWebScenarioReporterListener: launchUUID: " + launchUUID); + return this.getLaunch().startTestItem(rq); }); } } diff --git a/src/main/java/com/znsio/teswiz/runner/AppiumDriverManager.java b/src/main/java/com/znsio/teswiz/runner/AppiumDriverManager.java index 08a4040d0..08aa197b9 100644 --- a/src/main/java/com/znsio/teswiz/runner/AppiumDriverManager.java +++ b/src/main/java/com/znsio/teswiz/runner/AppiumDriverManager.java @@ -1,40 +1,41 @@ package com.znsio.teswiz.runner; -import com.appium.manager.AppiumDevice; -import com.appium.manager.DeviceAllocationManager; +import com.appium.capabilities.DriverSession; +import com.appium.filelocations.FileLocations; +import com.appium.manager.AppiumDeviceManager; +import com.appium.plugin.PluginClI; import com.context.SessionContext; import com.context.TestExecutionContext; -import com.github.device.Device; import com.znsio.teswiz.entities.Platform; import com.znsio.teswiz.entities.TEST_CONTEXT; -import com.znsio.teswiz.exceptions.DriverCreationException; import com.znsio.teswiz.exceptions.EnvironmentSetupException; import com.znsio.teswiz.exceptions.InvalidTestDataException; import com.znsio.teswiz.tools.ReportPortalLogger; import com.znsio.teswiz.tools.cmd.CommandLineExecutor; import com.znsio.teswiz.tools.cmd.CommandLineResponse; import io.appium.java_client.AppiumDriver; +import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.appmanagement.ApplicationState; -import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.log4j.Logger; import org.jetbrains.annotations.NotNull; import org.openqa.selenium.Capabilities; import org.openqa.selenium.NoSuchSessionException; -import org.openqa.selenium.WebElement; +import org.openqa.selenium.logging.LogEntries; import java.io.File; -import java.io.IOException; +import java.io.FileNotFoundException; +import java.io.PrintStream; import java.util.ArrayList; -import java.util.Date; import java.util.List; +import java.util.stream.StreamSupport; -import static com.znsio.teswiz.runner.Runner.DEBUG; +import static com.cucumber.listener.CucumberScenarioListener.createFile; import static com.znsio.teswiz.runner.Runner.DEFAULT; import static com.znsio.teswiz.runner.Setup.CAPS; class AppiumDriverManager { private static final int MAX_NUMBER_OF_APPIUM_DRIVERS = Runner.getMaxNumberOfAppiumDrivers(); - private static final List additionalDevices = new ArrayList<>(); + private static final List additionalDevices = new ArrayList<>(); private static final Logger LOGGER = Logger.getLogger(AppiumDriverManager.class.getName()); private static final String CAPABILITIES = "CAPABILITIES: "; private static int numberOfAppiumDriversUsed = 0; @@ -109,8 +110,15 @@ private static Driver createNewAppiumDriver(String userPersona, Platform forPlat File capabilityFileToUseForDriverCreation) { Driver currentDriver; try { - AppiumDriver appiumDriver = allocateNewDeviceAndStartAppiumDriver(userPersona, context, - capabilityFileToUseForDriverCreation.getAbsolutePath()); + AppiumDriver appiumDriver = new com.appium.manager.AppiumDriverManager().startAppiumDriverInstance(userPersona, + capabilityFileToUseForDriverCreation.getAbsolutePath()); + + + String scenarioDirectory = context.getTestStateAsString("scenarioDirectory"); + Integer scenarioRunCount = (Integer) context.getTestState("scenarioRunCount"); + String deviceLogFileName = startDataCapture(scenarioRunCount, scenarioDirectory); + addDeviceLogFileNameFor(userPersona, forPlatform.name(), deviceLogFileName); + currentDriver = new Driver(context.getTestName() + "-" + userPersona, forPlatform, userPersona, appName, appiumDriver); Capabilities appiumDriverCapabilities = appiumDriver.getCapabilities(); @@ -127,17 +135,46 @@ private static Driver createNewAppiumDriver(String userPersona, Platform forPlat return currentDriver; } + private static String startDataCapture(Integer scenarioRunCount, + String deviceLogFileDirectory) { + String fileName = String.format("/run-%s", scenarioRunCount); + if (AppiumDeviceManager.getAppiumDevice().getPlatformName().equalsIgnoreCase("android")) { + try { + fileName = String.format("/%s-run-%s", + AppiumDeviceManager.getAppiumDevice().getUdid(), scenarioRunCount); + File logFile = createFile(deviceLogFileDirectory + + FileLocations.DEVICE_LOGS_DIRECTORY, + fileName); + fileName = logFile.getAbsolutePath(); + LOGGER.debug("Capturing device logs here: " + fileName); + PrintStream logFileStream = null; + logFileStream = new PrintStream(logFile); + LogEntries logcatOutput = com.appium.manager.AppiumDriverManager.getDriver() + .manage().logs().get("logcat"); + StreamSupport.stream(logcatOutput.spliterator(), false) + .forEach(logFileStream::println); + } catch (FileNotFoundException e) { + LOGGER.warn("ERROR in getting logcat. Skipping logcat capture"); + } + } + return fileName; + } + @NotNull private static Driver setupFirstAppiumDriver(String userPersona, Platform forPlatform, TestExecutionContext context, String appName) { Driver currentDriver; - AppiumDriver appiumDriver = (AppiumDriver) context.getTestState( + AppiumDriver appiumDriver = (AppiumDriver) context.getTestState( TEST_CONTEXT.APPIUM_DRIVER); - AppiumDevice deviceInfo = (AppiumDevice) context.getTestState(TEST_CONTEXT.DEVICE_INFO); + DriverSession deviceInfo = (DriverSession) context.getTestState(TEST_CONTEXT.DEVICE_INFO); // Do not add the device info to additionalDevices for the driver created by ATD // additionalDevices.add(deviceInfo); Capabilities appiumDriverCapabilities = appiumDriver.getCapabilities(); - context.addTestState(TEST_CONTEXT.DEVICE_ON, deviceInfo.getDeviceOn()); + if (PluginClI.getInstance().isCloudExecution()) { + context.addTestState(TEST_CONTEXT.DEVICE_ON, PluginClI.getInstance().isCloudExecution()); + } else { + context.addTestState(TEST_CONTEXT.DEVICE_ON, "localDevice"); + } LOGGER.info(CAPABILITIES + appiumDriverCapabilities); Drivers.addUserPersonaDriverCapabilities(userPersona, appiumDriverCapabilities); Drivers.addUserPersonaDeviceLogFileName(userPersona, @@ -148,51 +185,6 @@ private static Driver setupFirstAppiumDriver(String userPersona, Platform forPla return currentDriver; } - private static AppiumDriver allocateNewDeviceAndStartAppiumDriver(String userPersona, - TestExecutionContext context, - String capabilityFile) { - String testName = context.getTestName(); - try { - String normalisedScenarioName = context.getTestStateAsString( - TEST_CONTEXT.NORMALISED_SCENARIO_NAME); - Integer scenarioRunCount = (Integer) context.getTestState( - TEST_CONTEXT.SCENARIO_RUN_COUNT); - DeviceAllocationManager deviceAllocationManager = DeviceAllocationManager.getInstance(); - AppiumDevice availableDevice = deviceAllocationManager.getNextAvailableDevice(); - deviceAllocationManager.allocateDevice(availableDevice); - AppiumDriver driver = - new com.appium.manager.AppiumDriverManager().startAppiumDriverInstance( - testName, capabilityFile); - additionalDevices.add(availableDevice); - updateAvailableDeviceInformation(availableDevice); - startDataCaptureFromDevice(userPersona, normalisedScenarioName, scenarioRunCount, - availableDevice); - ReportPortalLogger.logDebugMessage( - String.format("allocateNewDeviceAndStartAppiumDriver: Device Info%n%s", - availableDevice)); - return driver; - } catch(Exception e) { - LOGGER.info(ExceptionUtils.getStackTrace(e)); - throw new DriverCreationException( - String.format("Unable to create/allocate driver for test: '%s'", testName), e); - } - } - - private static void startDataCaptureFromDevice(String userPersona, - String normalisedScenarioName, - Integer scenarioRunCount, - AppiumDevice availableDevice) { - try { - String deviceLogFileName = availableDevice.startDataCapture(normalisedScenarioName, - scenarioRunCount); - addDeviceLogFileNameFor(userPersona, Platform.android.name(), deviceLogFileName); - LOGGER.info(String.format("Started device log capture in file: %s", deviceLogFileName)); - } catch(IOException | InterruptedException e) { - LOGGER.info(String.format("Error in starting data capture: %s", e.getMessage())); - e.printStackTrace(); - } - } - private static void disableNotificationsAndToastsOnDevice(Driver currentDriver, String deviceOn, String udid) { if(Runner.isRunningInCI()) { @@ -223,46 +215,29 @@ private static void disableNotificationsForLocalDevice(String udid) { private static void disableNotificationsForDeviceInDeviceFarm(Driver currentDriver, String deviceOn) { if(deviceOn.equalsIgnoreCase("pCloudy")) { - Object disableToasts = ((AppiumDriver) currentDriver.getInnerDriver()).executeScript( + Object disableToasts = ((AppiumDriver) currentDriver.getInnerDriver()).executeScript( "pCloudy_executeAdbCommand", "adb shell appops set " + Runner.getAppPackageName() + " TOAST_WINDOW " + "deny"); LOGGER.info(String.format("@disableToastsCommandResponse: %s", disableToasts)); Object disableNotifications = - ((AppiumDriver) currentDriver.getInnerDriver()).executeScript( + ((AppiumDriver) currentDriver.getInnerDriver()).executeScript( "pCloudy_executeAdbCommand", "adb shell settings put global heads_up_notifications_enabled 0"); LOGGER.info("@disableNotificationsCommandResponse: " + disableNotifications); } } - private static AppiumDevice updateAvailableDeviceInformation(AppiumDevice availableDevice) { - Capabilities capabilities = com.appium.manager.AppiumDriverManager.getDriver() - .getCapabilities(); - LOGGER.info(String.format("allocateDeviceAndStartDriver: %s", capabilities)); - - String udid = capabilities.is("udid") ? Drivers.getCapabilityFor(capabilities, "udid") - : Drivers.getCapabilityFor(capabilities, - "deviceUDID"); - Device device = availableDevice.getDevice(); - device.setUdid(udid); - device.setDeviceManufacturer(Drivers.getCapabilityFor(capabilities, "deviceManufacturer")); - device.setDeviceModel(Drivers.getCapabilityFor(capabilities, "deviceModel")); - device.setName(Drivers.getCapabilityFor(capabilities, - "deviceName") + " " + Drivers.getCapabilityFor( - capabilities, "deviceModel")); - device.setApiLevel(Drivers.getCapabilityFor(capabilities, "deviceApiLevel")); - device.setDeviceType(Drivers.getCapabilityFor(capabilities, "platformName")); - device.setScreenSize(Drivers.getCapabilityFor(capabilities, "deviceScreenSize")); - return availableDevice; - } - static void closeAppiumDriver(String userPersona, Driver driver) { if(Runner.getPlatform().equals(Platform.windows)) { closeWindowsAppOnMachine(userPersona, driver); - } else { + } else if(Runner.getPlatform().equals(Platform.android)){ closeAndroidAppOnDevice(userPersona, driver); } + // todo - fix for appium 2.0, implement new method to terminate app on iOS devices + else { + throw new InvalidTestDataException(String.format("No implementation for platform: %s", Runner.getPlatform())); + } } static void closeWindowsAppOnMachine(String userPersona, @@ -282,11 +257,13 @@ static void closeWindowsAppOnMachine(String userPersona, logMessage = String.format("Closing WindowsDriver for App '%s' for user '%s'", appPackageName, userPersona); LOGGER.info(logMessage); - appiumDriver.closeApp(); + // todo - fix for appium 2.0, test terminateApp() on windows app in windows OS + AndroidDriver androidDriver = (AndroidDriver) appiumDriver; + androidDriver.terminateApp(appPackageName); TestExecutionContext context = SessionContext.getTestExecutionContext( Thread.currentThread().getId()); - AppiumDriver atdAppiumDriver = - (AppiumDriver) context.getTestState( + AppiumDriver atdAppiumDriver = + (AppiumDriver) context.getTestState( TEST_CONTEXT.APPIUM_DRIVER); if(appiumDriver.equals(atdAppiumDriver)) { LOGGER.info( @@ -317,15 +294,15 @@ static void closeAndroidAppOnDevice(String userPersona, } else { TestExecutionContext context = SessionContext.getTestExecutionContext( Thread.currentThread().getId()); - AppiumDriver atdAppiumDriver = - (AppiumDriver) context.getTestState( + AppiumDriver atdAppiumDriver = + (AppiumDriver) context.getTestState( TEST_CONTEXT.APPIUM_DRIVER); if(appiumDriver.equals(atdAppiumDriver)) { LOGGER.info( String.format("ATD will quit the driver for persona: '%s'", userPersona)); LOGGER.info("Close the app"); - appiumDriver.closeApp(); - + AndroidDriver androidDriver = (AndroidDriver) appiumDriver; + androidDriver.terminateApp(appPackageName); } else { LOGGER.info(String.format("Quit driver for persona: '%s'", userPersona)); attachDeviceLogsToReportPortal(userPersona); @@ -340,15 +317,16 @@ private static void terminateAndroidAppOnDevice(String appPackageName, ApplicationState applicationState = null; try { LOGGER.info(String.format("Terminate app: %s", appPackageName)); - applicationState = appiumDriver.queryAppState(appPackageName); + AndroidDriver androidDriver = (AndroidDriver) appiumDriver; + applicationState = androidDriver.queryAppState(appPackageName); logMessage = String.format("App: '%s' Application state before closing app: '%s'%n", appPackageName, applicationState); LOGGER.info(logMessage); ReportPortalLogger.logDebugMessage(logMessage); - appiumDriver.closeApp(); - appiumDriver.terminateApp(appPackageName); - applicationState = appiumDriver.queryAppState(appPackageName); + + androidDriver.terminateApp(appPackageName); + applicationState = androidDriver.queryAppState(appPackageName); logMessage = String.format("App: '%s' Application state after closing app: '%s'%n", appPackageName, applicationState); LOGGER.info(logMessage); @@ -361,11 +339,13 @@ private static void terminateAndroidAppOnDevice(String appPackageName, private static void attachDeviceLogsToReportPortal(String userPersona) { String deviceLogFileName = getDeviceLogFileNameFor(userPersona, Platform.android.name()); + File destinationFile = new File(deviceLogFileName); String adbLogMessage = String.format("ADB Logs for %s, file name: %s", Drivers.getNameOfDeviceUsedByUser(userPersona), - deviceLogFileName); - ReportPortalLogger.attachFileInReportPortal(adbLogMessage, new File(deviceLogFileName)); + destinationFile.getName()); + LOGGER.info(adbLogMessage); + ReportPortalLogger.attachFileInReportPortal(adbLogMessage, destinationFile); } private static String getDeviceLogFileNameFor(String userPersona, String forPlatform) { @@ -382,12 +362,11 @@ private static void addDeviceLogFileNameFor(String userPersona, String forPlatfo } static void freeDevices() { - for(AppiumDevice additionalDevice : additionalDevices) { + for(DriverSession additionalDevice : additionalDevices) { LOGGER.info( - String.format("Freeing device: %s", additionalDevice.getDevice().getName())); - additionalDevice.freeDevice(); - additionalDevice.setChromeDriverPort(0); + String.format("Freeing device: %s", additionalDevice.getDeviceName())); } + additionalDevices.clear(); } @NotNull @@ -412,8 +391,8 @@ private static Driver createWindowsDriver(String userPersona, Platform forPlatfo TestExecutionContext context) { Driver currentDriver; if(numberOfAppiumDriversUsed < MAX_NUMBER_OF_APPIUM_DRIVERS) { - AppiumDriver windowsDriver = - (AppiumDriver) context.getTestState( + AppiumDriver windowsDriver = + (AppiumDriver) context.getTestState( TEST_CONTEXT.APPIUM_DRIVER); String appName = Drivers.getAppNamefor(userPersona); diff --git a/src/main/java/com/znsio/teswiz/runner/BrowserDriverManager.java b/src/main/java/com/znsio/teswiz/runner/BrowserDriverManager.java index decfb6e52..15f56f62b 100644 --- a/src/main/java/com/znsio/teswiz/runner/BrowserDriverManager.java +++ b/src/main/java/com/znsio/teswiz/runner/BrowserDriverManager.java @@ -247,7 +247,7 @@ private static WebDriver createChromeDriver(String forUserPersona, } else { logPrefs.enable(LogType.BROWSER, Level.ALL); } - chromeOptions.setCapability(CapabilityType.LOGGING_PREFS, logPrefs); + chromeOptions.setCapability(ChromeOptions.LOGGING_PREFS, logPrefs); if(null != proxyUrl) { LOGGER.info(SETTING_PROXY_FOR_BROWSER + proxyUrl); @@ -341,7 +341,8 @@ private static WebDriver createFirefoxDriver(String forUserPersona, firefoxOptions.setLogLevel(FirefoxDriverLogLevel.INFO); logPrefs.enable(LogType.BROWSER, Level.ALL); } - firefoxOptions.setCapability(CapabilityType.LOGGING_PREFS, logPrefs); + // todo - fix +// firefoxOptions.setCapability(FirefoxOptions.LOGGING_PREFS, logPrefs); if(null != proxyUrl) { LOGGER.info(SETTING_PROXY_FOR_BROWSER + proxyUrl); @@ -372,13 +373,12 @@ private static WebDriver createSafariDriver(String forUserPersona, TestExecutionContext testExecutionContext, JSONObject safariConfigurations) { SafariOptions safariOptions = new SafariOptions(); - DesiredCapabilities caps = DesiredCapabilities.safari(); boolean setUseTechnologyPreview = safariConfigurations.getBoolean( "setUseTechnologyPreview"); boolean acceptInsecureCerts = safariConfigurations.getBoolean(ACCEPT_INSECURE_CERTS); String proxyUrl = Runner.getProxyURL(); shouldBrowserBeMaximized = safariConfigurations.getBoolean(MAXIMIZE); - caps.setCapability(ACCEPT_INSECURE_CERTS, acceptInsecureCerts); + safariOptions.setCapability(ACCEPT_INSECURE_CERTS, acceptInsecureCerts); if(null != proxyUrl) { LOGGER.info(String.format("%s%s", SETTING_PROXY_FOR_BROWSER, proxyUrl)); safariOptions.setProxy(new Proxy().setHttpProxy(proxyUrl)); diff --git a/src/main/java/com/znsio/teswiz/runner/DeviceSetup.java b/src/main/java/com/znsio/teswiz/runner/DeviceSetup.java index 0fee957ca..a547cf8c3 100644 --- a/src/main/java/com/znsio/teswiz/runner/DeviceSetup.java +++ b/src/main/java/com/znsio/teswiz/runner/DeviceSetup.java @@ -19,7 +19,14 @@ import java.util.regex.Pattern; import static com.znsio.teswiz.runner.Runner.NOT_SET; -import static com.znsio.teswiz.runner.Setup.*; +import static com.znsio.teswiz.runner.Setup.APP_PATH; +import static com.znsio.teswiz.runner.Setup.APP_VERSION; +import static com.znsio.teswiz.runner.Setup.CAPS; +import static com.znsio.teswiz.runner.Setup.EXECUTED_ON; +import static com.znsio.teswiz.runner.Setup.LOG_DIR; +import static com.znsio.teswiz.runner.Setup.PARALLEL; +import static com.znsio.teswiz.runner.Setup.PLUGIN; +import static com.znsio.teswiz.runner.Setup.RUN_IN_CI; class DeviceSetup { private static final Logger LOGGER = Logger.getLogger(DeviceSetup.class.getName()); @@ -138,8 +145,7 @@ static void setupCloudExecution() { private static String getAppPathFromCapabilities() { String capabilityFile = Setup.getFromConfigs(CAPS); return JsonFile.getNodeValueAsStringFromJsonFile(capabilityFile, - new String[]{Setup.getPlatform().name(), - "app", "local"}); + new String[]{Setup.getPlatform().name(), "app"}); } private static void checkIfAppExistsAtTheMentionedPath(String appPath, diff --git a/src/main/java/com/znsio/teswiz/runner/Driver.java b/src/main/java/com/znsio/teswiz/runner/Driver.java index 9507b6e91..e50ee8030 100644 --- a/src/main/java/com/znsio/teswiz/runner/Driver.java +++ b/src/main/java/com/znsio/teswiz/runner/Driver.java @@ -1,21 +1,36 @@ package com.znsio.teswiz.runner; import com.google.common.collect.ImmutableMap; +import com.znsio.teswiz.entities.Direction; import com.znsio.teswiz.entities.Platform; import com.znsio.teswiz.exceptions.FileNotUploadedException; -import com.znsio.teswiz.tools.Wait; -import io.appium.java_client.*; +import io.appium.java_client.AppiumBy; +import io.appium.java_client.AppiumDriver; +import io.appium.java_client.HidesKeyboard; +import io.appium.java_client.MobileBy; +import io.appium.java_client.PerformsTouchActions; +import io.appium.java_client.TouchAction; import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.HasNotifications; import io.appium.java_client.android.StartsActivity; import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.remote.SupportsContextSwitching; import io.appium.java_client.touch.LongPressOptions; import io.appium.java_client.touch.WaitOptions; import io.appium.java_client.touch.offset.ElementOption; -import io.appium.java_client.touch.offset.PointOption; import org.apache.commons.lang3.NotImplementedException; import org.apache.log4j.Logger; -import org.openqa.selenium.*; +import org.openqa.selenium.By; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.Point; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.interactions.Pause; +import org.openqa.selenium.interactions.PointerInput; +import org.openqa.selenium.interactions.Sequence; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; @@ -27,6 +42,11 @@ import java.util.List; import java.util.Set; +import static com.znsio.teswiz.tools.Wait.waitFor; +import static java.time.Duration.ofMillis; +import static java.time.Duration.ofSeconds; +import static java.util.Collections.singletonList; + public class Driver { public static final String WEB_DRIVER = "WebDriver"; public static final String APPIUM_DRIVER = "AppiumDriver"; @@ -38,12 +58,12 @@ public class Driver { private final Platform driverForPlatform; private static final String DIMENSION = "dimension: "; private static final String FROM_HEIGHT_TO_HEIGHT = "width: %s, from height: %s, to height: %s"; - private static final String TO = "' to '"; private final boolean isRunningInHeadlessMode; + private static final String TO = "' to '"; private Visual visually; Driver(String testName, Platform forPlatform, String userPersona, String appName, - AppiumDriver appiumDriver) { + AppiumDriver appiumDriver) { this.driver = appiumDriver; this.type = APPIUM_DRIVER; this.userPersona = userPersona; @@ -53,17 +73,21 @@ public class Driver { instantiateEyes(testName, appiumDriver); } - Driver(String testName, Platform forPlaform, String userPersona, String appName, + Driver(String testName, Platform forPlatform, String userPersona, String appName, WebDriver webDriver, boolean isRunInHeadlessMode) { this.driver = webDriver; this.type = WEB_DRIVER; this.userPersona = userPersona; this.appName = appName; - this.driverForPlatform = forPlaform; + this.driverForPlatform = forPlatform; this.isRunningInHeadlessMode = isRunInHeadlessMode; instantiateEyes(testName, webDriver); } + private void instantiateEyes(String testName, AppiumDriver innerDriver) { + this.visually = new Visual(this.type, this.driverForPlatform, innerDriver, testName, userPersona, appName); + } + private void instantiateEyes(String testName, WebDriver innerDriver) { this.visually = new Visual(this.type, this.driverForPlatform, innerDriver, testName, userPersona, appName); @@ -74,12 +98,11 @@ public WebElement waitForClickabilityOf(String elementId) { } public WebElement waitForClickabilityOf(String elementId, int numberOfSecondsToWait) { - return (new WebDriverWait(driver, numberOfSecondsToWait)).until( - ExpectedConditions.elementToBeClickable(findElementByAccessibilityId(elementId))); + return (new WebDriverWait(driver, Duration.ofSeconds(numberOfSecondsToWait))).until(ExpectedConditions.elementToBeClickable(findElementByAccessibilityId(elementId))); } public WebElement findElementByAccessibilityId(String locator) { - return ((AppiumDriver) driver).findElementByAccessibilityId(locator); + return driver.findElement(AppiumBy.accessibilityId(locator)); } public void waitForAlert() { @@ -87,9 +110,9 @@ public void waitForAlert() { } public void waitForAlert(int numberOfSecondsToWait) { - (new WebDriverWait(driver, numberOfSecondsToWait)).until( - ExpectedConditions.alertIsPresent()); - driver.switchTo().alert(); + new WebDriverWait(driver, Duration.ofSeconds(numberOfSecondsToWait)).until(ExpectedConditions.alertIsPresent()); + driver.switchTo() + .alert(); } public WebElement findElement(By elementId) { @@ -97,7 +120,7 @@ public WebElement findElement(By elementId) { } public void hideKeyboard() { - ((AppiumDriver) driver).hideKeyboard(); + ((HidesKeyboard) driver).hideKeyboard(); } public List findElements(By element) { @@ -113,10 +136,16 @@ public WebElement findElementByXpath(String locator) { } public void scroll(Point fromPoint, Point toPoint) { - TouchAction touchAction = new TouchAction(((AppiumDriver) driver)); - touchAction.press(PointOption.point(fromPoint)) - .waitAction(WaitOptions.waitOptions(Duration.ofMillis(1000))) - .moveTo(PointOption.point(toPoint)).release().perform(); + AppiumDriver appiumDriver = (AppiumDriver) this.driver; + PointerInput touch = new PointerInput(PointerInput.Kind.TOUCH, "touch"); + Sequence scroller = new Sequence(touch, 1); + scroller.addAction(touch.createPointerMove(Duration.ofSeconds(0), PointerInput.Origin.viewport(), fromPoint.getX(), fromPoint.getY())); + scroller.addAction(touch.createPointerDown(PointerInput.MouseButton.LEFT.asArg())); + scroller.addAction(touch.createPointerMove(Duration.ofSeconds(1), PointerInput.Origin.viewport(), toPoint.getX(), toPoint.getY())); + scroller.addAction(touch.createPointerUp(PointerInput.MouseButton.LEFT.asArg())); + LOGGER.info(String.format("fromPoint width: %s, fromPoint height: %s", fromPoint.getX(), fromPoint.getY())); + LOGGER.info(String.format("toPoint width: %s, toPoint height: %s", toPoint.getX(), toPoint.getY())); + appiumDriver.perform(singletonList(scroller)); } public WebElement scrollToAnElementByText(String text) { @@ -129,7 +158,8 @@ public boolean isElementPresent(By locator) { } public boolean isElementPresentByAccessibilityId(String locator) { - return !((AppiumDriver) driver).findElementsByAccessibilityId(locator).isEmpty(); + return driver.findElements(AppiumBy.accessibilityId(locator)) + .size() > 0; } public boolean isElementPresentWithin(WebElement parentElement, By locator) { @@ -141,14 +171,12 @@ public void scrollDownByScreenSize() { Dimension windowSize = appiumDriver.manage().window().getSize(); LOGGER.info(DIMENSION + windowSize.toString()); int width = windowSize.width / 2; - int fromHeight = (int) (windowSize.height * 0.9); - int toHeight = (int) (windowSize.height * 0.5); - LOGGER.info(String.format(FROM_HEIGHT_TO_HEIGHT, width, fromHeight, toHeight)); - - TouchAction touchAction = new TouchAction(appiumDriver); - touchAction.press(PointOption.point(new Point(width, fromHeight))) - .waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1))) - .moveTo(PointOption.point(new Point(width, toHeight))).release().perform(); + int fromHeight = (int) (windowSize.height * 0.8); + int toHeight = (int) (windowSize.height * 0.2); + LOGGER.info(String.format("width: %s, from height: %s, to height: %s", width, fromHeight, toHeight)); + Point from=new Point(width,fromHeight); + Point to=new Point(width,toHeight); + scroll(from,to); } public void scrollVertically(int fromPercentScreenHeight, int toPercentScreenHeight, @@ -159,13 +187,11 @@ public void scrollVertically(int fromPercentScreenHeight, int toPercentScreenHei int width = (windowSize.width * percentScreenWidth) / 100; int fromHeight = (windowSize.height * fromPercentScreenHeight) / 100; int toHeight = (windowSize.height * toPercentScreenHeight) / 100; - LOGGER.info(String.format(FROM_HEIGHT_TO_HEIGHT, width, fromHeight, toHeight)); - LOGGER.info(String.format(FROM_HEIGHT_TO_HEIGHT, width, fromHeight, toHeight)); - - TouchAction touchAction = new TouchAction(appiumDriver); - touchAction.press(PointOption.point(new Point(width, fromHeight))) - .waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1))) - .moveTo(PointOption.point(new Point(width, toHeight))).release().perform(); + LOGGER.info(String.format("width: %s, from height: %s, to height: %s", width, fromHeight, toHeight)); + LOGGER.info(String.format("width: %s, from height: %s, to height: %s", width, fromHeight, toHeight)); + Point from=new Point(width,fromHeight); + Point to=new Point(width,toHeight); + scroll(from,to); } public void tapOnMiddleOfScreen() { @@ -181,12 +207,14 @@ private void tapOnMiddleOfScreenOnDevice() { Dimension screenSize = appiumDriver.manage().window().getSize(); int midHeight = screenSize.height / 2; int midWidth = screenSize.width / 2; - LOGGER.info(String.format( - "tapOnMiddleOfScreen: Screen dimensions: '%s'. Tapping on coordinates: %d:%d%n", - screenSize, midWidth, midHeight)); - TouchAction touchAction = new TouchAction(appiumDriver); - touchAction.tap(PointOption.point(midWidth, midHeight)).perform(); - Wait.waitFor(1); + LOGGER.info(String.format("tapOnMiddleOfScreen: Screen dimensions: '%s'. Tapping on coordinates: %d:%d%n", screenSize, midWidth, midHeight)); + PointerInput touch = new PointerInput(PointerInput.Kind.TOUCH, "touch"); + Sequence clickPosition = new Sequence(touch, 1); + clickPosition.addAction(touch.createPointerMove(Duration.ofMillis(0), PointerInput.Origin.viewport(), midWidth,midHeight)) + .addAction(touch.createPointerDown(PointerInput.MouseButton.LEFT.asArg())) + .addAction(touch.createPointerUp(PointerInput.MouseButton.LEFT.asArg())); + appiumDriver.perform(Arrays.asList(clickPosition)); + waitFor(1); } private void simulateMouseMovementOnBrowser() { @@ -207,15 +235,7 @@ private void simulateMouseMovementOnBrowser() { LOGGER.info(String.format("Using offset: '%d':'%d'", offsetX, offsetY)); actions.moveByOffset(offsetX, offsetY).perform(); - Wait.waitFor(1); - } - - public void swipeRight() { - int height = getWindowHeight() / 2; - int fromWidth = (int) (getWindowWidth() * 0.5); - int toWidth = (int) (getWindowWidth() * 0.9); - LOGGER.info("height: " + height + ", from width: " + fromWidth + ", to width: " + toWidth); - swipe(height, fromWidth, toWidth); + waitFor(1); } private int getWindowHeight() { @@ -230,44 +250,85 @@ private int getWindowWidth() { return appiumDriver.manage().window().getSize().width; } - private void swipe(int height, int fromWidth, int toWidth) { - AppiumDriver appiumDriver = (AppiumDriver) this.driver; - TouchAction touchAction = new TouchAction(appiumDriver); - touchAction.press(PointOption.point(new Point(fromWidth, height))) - .waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1))) - .moveTo(PointOption.point(new Point(toWidth, height))).release().perform(); + private void checkPercentagesAreValid(int... percentages) { + boolean arePercentagesValid = Arrays.stream(percentages).allMatch(percentage -> percentage >= 0 && percentage <= 100); + if (!arePercentagesValid) { + throw new RuntimeException(String.format("Invalid percentage value - percentage value should be between 0 - 100. but are %s", + Arrays.toString(percentages))); + } + } + + public void swipeRight() { + int height = getWindowHeight() / 2; + int fromWidth = (int) (getWindowWidth() * 0.2); + int toWidth = (int) (getWindowWidth() * 0.7); + LOGGER.info(String.format("height: %s, from width: %s, to width: %s", height, fromWidth, toWidth)); + swipe(height, fromWidth, toWidth); } public void swipeLeft() { int height = getWindowHeight() / 2; - int fromWidth = (int) (getWindowWidth() * 0.9); - int toWidth = (int) (getWindowWidth() * 0.5); - LOGGER.info(String.format("height: %s, from width: %s, to width: %s", height, fromWidth, - toWidth)); + int fromWidth = (int) (getWindowWidth() * 0.8); + int toWidth = (int) (getWindowWidth() * 0.3); + LOGGER.info(String.format("height: %s, from width: %s, to width: %s", height, fromWidth, toWidth)); + swipe(height, fromWidth, toWidth); + } + + public void swipeByPassingPercentageAttributes(int percentScreenHeight, int fromPercentScreenWidth, int toPercentScreenWidth) { + LOGGER.info(String.format("percent attributes passed to method are: percentScreenHeight: %s, fromPercentScreenWidth: %s, toPercentScreenWidth: %s", + percentScreenHeight, fromPercentScreenWidth, toPercentScreenWidth)); + checkPercentagesAreValid(percentScreenHeight, fromPercentScreenWidth, toPercentScreenWidth); + int height = getWindowHeight() * percentScreenHeight / 100; + int fromWidth = getWindowWidth() * fromPercentScreenWidth / 100; + int toWidth = getWindowWidth() * toPercentScreenWidth / 100; + LOGGER.info(String.format("swipe gesture at height: %s, from width: %s, to width: %s", height, fromWidth, toWidth)); swipe(height, fromWidth, toWidth); } + private void swipe(int height, int fromWidth, int toWidth) { + AppiumDriver appiumDriver = (AppiumDriver) this.driver; + PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger"); + Sequence sequence = new Sequence(finger, 1); + sequence.addAction(finger.createPointerMove(ofMillis(0), PointerInput.Origin.viewport(), fromWidth, height)); + sequence.addAction(finger.createPointerDown(PointerInput.MouseButton.MIDDLE.asArg())); + sequence.addAction(new Pause(finger, ofSeconds(1))); + sequence.addAction(finger.createPointerMove(ofSeconds(1), PointerInput.Origin.viewport(), toWidth, height)); + sequence.addAction(finger.createPointerUp(PointerInput.MouseButton.MIDDLE.asArg())); + appiumDriver.perform(singletonList(sequence)); + } + public void openNotifications() { LOGGER.info("Fetching the NOTIFICATIONS on the device: "); - Wait.waitFor(3); - ((AndroidDriver) driver).openNotifications(); - Wait.waitFor(2); + waitFor(3); + ((HasNotifications) driver).openNotifications(); + waitFor(2); } - public void selectNotification(By selectNotificationLocator) { + public void selectNotificationFromNotificationDrawer(By selectNotificationLocator) { AppiumDriver appiumDriver = (AppiumDriver) this.driver; + Dimension screenSize = appiumDriver.manage().window().getSize(); + PointerInput touch = new PointerInput(PointerInput.Kind.TOUCH, "touch"); + Sequence dragNotificationBar = new Sequence(touch, 1); + dragNotificationBar.addAction(touch.createPointerMove(Duration.ofSeconds(0), PointerInput.Origin.viewport(), screenSize.width / 2, 0)); + dragNotificationBar.addAction(touch.createPointerDown(PointerInput.MouseButton.LEFT.asArg())); + dragNotificationBar.addAction(touch.createPointerMove(Duration.ofSeconds(1), PointerInput.Origin.viewport(), screenSize.width / 2, screenSize.height)); + dragNotificationBar.addAction(touch.createPointerUp(PointerInput.MouseButton.LEFT.asArg())); + appiumDriver.perform(singletonList(dragNotificationBar)); + appiumDriver.perform(singletonList(dragNotificationBar)); + waitFor(1); + WebElement selectNotificationElement = driver.findElement(selectNotificationLocator); LOGGER.info("Notification found: " + selectNotificationElement.isDisplayed()); - Point notificationCoordinates = selectNotificationElement.getLocation(); - - TouchAction touchAction = new TouchAction(appiumDriver); - touchAction.tap(PointOption.point(notificationCoordinates)).perform(); - LOGGER.info("Tapped on notification. Go back to meeting"); - Wait.waitFor(3); + selectNotificationElement.click(); } - public void putAppInBackground(int duration) { - ((AppiumDriver) driver).runAppInBackground(Duration.ofSeconds(duration)); + public void putAppInBackgroundFor(int numberOfSeconds) { + if (Runner.getPlatform() == Platform.android) { + ((AndroidDriver) driver).runAppInBackground(Duration.ofSeconds(numberOfSeconds)); + } else { + throw new NotImplementedException( + "Method is not implemented for " + Runner.getPlatform()); + } } public void bringAppInForeground() { @@ -293,8 +354,8 @@ public Visual getVisual() { } public void longPress(By elementId) { - MobileElement elementToBeLongTapped = (MobileElement) new WebDriverWait(driver, 10).until( - ExpectedConditions.elementToBeClickable(elementId)); + WebElement elementToBeLongTapped = + new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.elementToBeClickable(elementId)); TouchAction action = new TouchAction((PerformsTouchActions) driver); action.longPress(LongPressOptions.longPressOptions() @@ -331,40 +392,35 @@ public WebElement waitForClickabilityOf(By elementId) { } public WebElement waitForClickabilityOf(By elementId, int numberOfSecondsToWait) { - return (new WebDriverWait(driver, numberOfSecondsToWait)).until( - ExpectedConditions.elementToBeClickable(elementId)); + return (new WebDriverWait(driver, Duration.ofSeconds(numberOfSecondsToWait)).until(ExpectedConditions.elementToBeClickable(elementId))); } public List findElementsByAccessibilityId(String elementId) { - return ((AppiumDriver) driver).findElementsByAccessibilityId(elementId); + return ((AppiumDriver) driver).findElements(AppiumBy.accessibilityId(elementId)); } public WebElement waitTillElementIsPresent(By elementId) { return waitTillElementIsPresent(elementId, 10); } - public WebElement waitTillElementIsPresent(By elementId, int numberOfSecondsToWait) { - return (new WebDriverWait(driver, numberOfSecondsToWait)).until( - ExpectedConditions.presenceOfElementLocated(elementId)); - } - public WebElement waitTillElementIsVisible(By elementId) { return waitTillElementIsVisible(elementId, 10); } + public WebElement waitTillElementIsPresent(By elementId, int numberOfSecondsToWait) { + return (new WebDriverWait(driver, Duration.ofSeconds(numberOfSecondsToWait)).until(ExpectedConditions.presenceOfElementLocated(elementId))); + } + public WebElement waitTillElementIsVisible(By elementId, int numberOfSecondsToWait) { - return (new WebDriverWait(driver, numberOfSecondsToWait)).until( - ExpectedConditions.visibilityOfElementLocated(elementId)); + return (new WebDriverWait(driver, Duration.ofSeconds(numberOfSecondsToWait)).until(ExpectedConditions.visibilityOfElementLocated(elementId))); } public List waitTillVisibilityOfAllElements(By elementId) { return waitTillVisibilityOfAllElements(elementId, 10); } - public List waitTillVisibilityOfAllElements(By elementId, - int numberOfSecondsToWait) { - return (new WebDriverWait(driver, numberOfSecondsToWait)).until( - ExpectedConditions.visibilityOfAllElementsLocatedBy(elementId)); + public List waitTillVisibilityOfAllElements(By elementId, int numberOfSecondsToWait){ + return (new WebDriverWait(driver, Duration.ofSeconds(numberOfSecondsToWait)).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(elementId))); } public WebElement waitTillElementIsVisible(String elementId) { @@ -372,8 +428,7 @@ public WebElement waitTillElementIsVisible(String elementId) { } public WebElement waitTillElementIsVisible(String elementId, int numberOfSecondsToWait) { - return (new WebDriverWait(driver, numberOfSecondsToWait)).until( - ExpectedConditions.visibilityOf(findElementByAccessibilityId(elementId))); + return (new WebDriverWait(driver, Duration.ofSeconds(numberOfSecondsToWait)).until(ExpectedConditions.visibilityOf(findElementByAccessibilityId(elementId)))); } public List waitTillPresenceOfAllElements(By elementId) { @@ -381,8 +436,7 @@ public List waitTillPresenceOfAllElements(By elementId) { } public List waitTillPresenceOfAllElements(By elementId, int numberOfSecondsToWait) { - return (new WebDriverWait(driver, numberOfSecondsToWait)).until( - ExpectedConditions.presenceOfAllElementsLocatedBy(elementId)); + return (new WebDriverWait(driver, Duration.ofSeconds(numberOfSecondsToWait)).until(ExpectedConditions.presenceOfAllElementsLocatedBy(elementId))); } public void setWindowSize(int width, int height) { @@ -394,7 +448,7 @@ public void setWindowSize(int width, int height) { public void moveToElement(By moveToElementLocator) { Actions actions = new Actions(driver); actions.moveToElement(driver.findElement(moveToElementLocator)).build().perform(); - Wait.waitFor(1); + waitFor(1); } public boolean isDriverRunningInHeadlessMode() { @@ -402,9 +456,12 @@ public boolean isDriverRunningInHeadlessMode() { } public WebDriver setWebViewContext() { - AppiumDriver appiumDriver = (AppiumDriver) driver; - Set contextNames = appiumDriver.getContextHandles(); - return appiumDriver.context((String) contextNames.toArray()[contextNames.size() - 1]); + LOGGER.info("Setting web view context"); + SupportsContextSwitching contextSwitchingDriver = (SupportsContextSwitching) driver; + Set contextHandles = contextSwitchingDriver.getContextHandles(); + LOGGER.info("List of context handles present"); + contextHandles.stream().forEach(LOGGER::info); + return contextSwitchingDriver.context((String) contextHandles.toArray()[contextHandles.size() - 1]); } public WebDriver setNativeAppContext() { @@ -412,8 +469,9 @@ public WebDriver setNativeAppContext() { } public WebDriver setNativeAppContext(String contextName) { - AppiumDriver appiumDriver = (AppiumDriver) driver; - return appiumDriver.context(contextName); + LOGGER.info("Setting native app context"); + SupportsContextSwitching contextSwitchingDriver = (SupportsContextSwitching) driver; + return contextSwitchingDriver.context(contextName); } public WebDriver switchFrameToDefault() { @@ -484,18 +542,17 @@ public void injectMediaToBrowserstackDevice(String uploadFileURL) { } } - public void scrollInDynamicLayer(String direction) { + public void scrollInDynamicLayer(Direction direction) { Dimension dimension = driver.manage().window().getSize(); int width = (int) (dimension.width * 0.5); - int fromHeight = (int) (dimension.height * 0.7), toHeight = (int) (dimension.height * 0.6); + int fromHeight = (int) (dimension.height * 0.7); + int toHeight = (int) (dimension.height * 0.6); int[] height = {fromHeight, toHeight}; - if (direction.equalsIgnoreCase("up")) { + if (direction.equals(Direction.UP)) { Arrays.sort(height); } - - TouchAction touchAction = new TouchAction<>((PerformsTouchActions) driver); - touchAction.press(PointOption.point(width, height[0])) - .waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1))) - .moveTo(PointOption.point(width, height[1])).release().perform(); + Point fromPoint = new Point(width, height[0]); + Point toPoint = new Point(width, height[1]); + scroll(fromPoint, toPoint); } } \ No newline at end of file diff --git a/src/main/java/com/znsio/teswiz/runner/LocalDevicesSetup.java b/src/main/java/com/znsio/teswiz/runner/LocalDevicesSetup.java index a8cee51ad..7b9efc286 100644 --- a/src/main/java/com/znsio/teswiz/runner/LocalDevicesSetup.java +++ b/src/main/java/com/znsio/teswiz/runner/LocalDevicesSetup.java @@ -1,6 +1,5 @@ package com.znsio.teswiz.runner; -import com.github.device.Device; import com.znsio.teswiz.exceptions.EnvironmentSetupException; import com.znsio.teswiz.tools.cmd.CommandLineExecutor; import org.apache.log4j.Logger; @@ -13,7 +12,6 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.List; import static com.znsio.teswiz.runner.Setup.*; @@ -24,15 +22,12 @@ class LocalDevicesSetup { private static final String UNINSTALL = "uninstall"; private static final String GETPROP = "getprop"; - private static List devices; - private LocalDevicesSetup() { LOGGER.debug("LocalDevicesSetup - private constructor"); } static void setupLocalExecution() { - List devices = setupLocalDevices(); - int numberOfDevicesForParallelExecution = devices.size(); + int numberOfDevicesForParallelExecution = setupLocalDevices().size(); if(numberOfDevicesForParallelExecution == 0) { throw new EnvironmentSetupException("No devices available to run the tests"); } @@ -46,23 +41,17 @@ static void setupLocalExecution() { Setup.addToConfigs(EXECUTED_ON, "Local Devices"); } - private static List setupLocalDevices() { + private static List setupLocalDevices() { startADBServerForLocalDevice(); - if(null == devices) { - JadbConnection jadb = new JadbConnection(); - List deviceList; - devices = new ArrayList<>(); - try { - deviceList = jadb.getDevices(); - } catch(IOException | JadbException e) { - throw new EnvironmentSetupException("Unable to get devices information", e); - } - - extractInfoFromEachLocalDevice(deviceList); - - LOGGER.info("Number of Devices connected: " + devices.size()); + JadbConnection jadb = new JadbConnection(); + List deviceList; + try { + deviceList = jadb.getDevices(); + } catch (IOException | JadbException e) { + throw new EnvironmentSetupException("Unable to get devices information", e); } - return devices; + LOGGER.info("Number of Devices connected: " + deviceList.size()); + return deviceList; } private static void startADBServerForLocalDevice() { @@ -71,29 +60,6 @@ private static void startADBServerForLocalDevice() { CommandLineExecutor.execCommand(listOfDevices); } - private static void extractInfoFromEachLocalDevice(List deviceList) { - deviceList.forEach(jadbDevice -> { - try { - Device device = new Device(); - device.setName(jadbDevice.getSerial()); - device.setUdid(jadbDevice.getSerial()); - device.setApiLevel(getAdbCommandOutputFromLocalDevice(jadbDevice, GETPROP, - "ro.build.version.sdk")); - device.setDeviceManufacturer(getAdbCommandOutputFromLocalDevice(jadbDevice, GETPROP, - "ro.product" + - ".brand")); - device.setDeviceModel(getAdbCommandOutputFromLocalDevice(jadbDevice, GETPROP, - "ro.product.model")); - device.setOsVersion(getAdbCommandOutputFromLocalDevice(jadbDevice, GETPROP, - "ro.build.version.release")); - devices.add(device); - uninstallAppFromLocalDevice(device, Setup.getFromConfigs(APP_PACKAGE_NAME)); - } catch(IOException | JadbException e) { - throw new EnvironmentSetupException("Unable to get devices information", e); - } - }); - } - @NotNull private static String getAdbCommandOutputFromLocalDevice(JadbDevice device, String command, String args) throws IOException, @@ -105,25 +71,4 @@ private static String getAdbCommandOutputFromLocalDevice(JadbDevice device, Stri LOGGER.info("\tOutput: " + adbCommandOutput); return adbCommandOutput; } - - private static void uninstallAppFromLocalDevice(Device device, String appPackageName) { - String[] uninstallAppiumAutomator2Server = new String[]{"adb", "-s", device.getUdid(), - UNINSTALL, - APPIUM_UI_AUTOMATOR2_SERVER}; - CommandLineExecutor.execCommand(uninstallAppiumAutomator2Server); - String[] uninstallAppiumSettings = new String[]{"adb", "-s", device.getUdid(), UNINSTALL, - APPIUM_SETTINGS}; - CommandLineExecutor.execCommand(uninstallAppiumSettings); - - if(Setup.getBooleanValueFromConfigs(CLEANUP_DEVICE_BEFORE_STARTING_EXECUTION)) { - String[] uninstallApp = new String[]{"adb", "-s", device.getUdid(), UNINSTALL, - appPackageName}; - CommandLineExecutor.execCommand(uninstallApp); - } else { - LOGGER.info( - "skipping uninstalling of apk as the flag " + - "CLEANUP_DEVICE_BEFORE_STARTING_EXECUTION = false"); - } - } - } diff --git a/src/test/java/com/znsio/teswiz/businessLayer/jiomeet/InAMeetingBL.java b/src/test/java/com/znsio/teswiz/businessLayer/jiomeet/InAMeetingBL.java index 71bab3105..5c51eff04 100644 --- a/src/test/java/com/znsio/teswiz/businessLayer/jiomeet/InAMeetingBL.java +++ b/src/test/java/com/znsio/teswiz/businessLayer/jiomeet/InAMeetingBL.java @@ -7,6 +7,8 @@ import com.znsio.teswiz.screen.jiomeet.InAMeetingScreen; import org.apache.log4j.Logger; import org.assertj.core.api.SoftAssertions; +import static org.assertj.core.api.Assertions.assertThat; + public class InAMeetingBL { private static final Logger LOGGER = Logger.getLogger(InAMeetingBL.class.getName()); @@ -42,4 +44,16 @@ public InAMeetingBL muteMyself() { InAMeetingScreen.get().mute(); return this; } + + public InAMeetingBL openNotificationFromNotificationBar() { + InAMeetingScreen.get().openJioMeetNotification(); + return this; + } + + public InAMeetingBL verifyMeetingOpenedInJioMeetApplication() { + assertThat(InAMeetingScreen.get().isMeetingStarted()) + .as("Meeting is not opened in Jio Meet Application") + .isTrue(); + return this; + } } diff --git a/src/test/java/com/znsio/teswiz/businessLayer/vodqa/VodqaBL.java b/src/test/java/com/znsio/teswiz/businessLayer/vodqa/VodqaBL.java new file mode 100644 index 000000000..bbe2d614f --- /dev/null +++ b/src/test/java/com/znsio/teswiz/businessLayer/vodqa/VodqaBL.java @@ -0,0 +1,134 @@ +package com.znsio.teswiz.businessLayer.vodqa; + +import com.context.TestExecutionContext; +import com.znsio.teswiz.entities.Direction; +import com.znsio.teswiz.entities.Platform; +import com.znsio.teswiz.entities.SAMPLE_TEST_CONTEXT; +import com.znsio.teswiz.runner.Runner; +import com.znsio.teswiz.screen.vodqa.VodqaScreen; +import com.znsio.teswiz.screen.vodqa.WebViewScreen; +import org.apache.log4j.Logger; +import org.assertj.core.api.SoftAssertions; +import static org.assertj.core.api.Assertions.assertThat; + +public class VodqaBL { + private static final Logger LOGGER = Logger.getLogger(VodqaBL.class.getName()); + private final TestExecutionContext context; + private final SoftAssertions softly; + private final String currentUserPersona; + private final Platform currentPlatform; + + public VodqaBL(String userPersona, Platform forPlatform) { + long threadId = Thread.currentThread().getId(); + this.context = Runner.getTestExecutionContext(threadId); + softly = Runner.getSoftAssertion(threadId); + this.currentUserPersona = userPersona; + this.currentPlatform = forPlatform; + Runner.setCurrentDriverForUser(userPersona, forPlatform, context); + } + + public VodqaBL() { + long threadId = Thread.currentThread().getId(); + this.context = Runner.getTestExecutionContext(threadId); + softly = Runner.getSoftAssertion(threadId); + this.currentUserPersona = SAMPLE_TEST_CONTEXT.ME; + this.currentPlatform = Runner.getPlatform(); + } + + public VodqaBL login() { + VodqaScreen.get().login(); + return this; + } + + public VodqaBL scrollFromOneElementPointToAnother() { + VodqaScreen.get().scrollFromOneElementPointToAnother(); + return this; + } + + public VodqaBL selectScreenAndSwipeLeft(String screenName) { + VodqaScreen.get().selectScreen(screenName).swipeLeft(); + return this; + } + + public VodqaBL verifySwipe(String elementText) { + assertThat(VodqaScreen.get().isSwipeSuccessful(elementText)) + .as("swipe was not successful") + .isTrue(); + return this; + } + + public VodqaBL selectScreenAndSwipeRight(String screenName) { + VodqaScreen.get().selectScreen(screenName).swipeRight(); + return this; + } + + public VodqaBL selectScreenAndSwipeByPassingPercentageAttributes(int atPercentScreenHeight, int fromPercentScreenWidth, int toPercentScreenWidth, String screenName) { + VodqaScreen.get().selectScreen(screenName) + .swipeByPassingPercentageAttributes(atPercentScreenHeight, fromPercentScreenWidth, toPercentScreenWidth); + return this; + } + + public VodqaBL scrollDownByScreenSizeOnVerticalSwipingScreen() { + VodqaScreen.get().openVerticalSwipingScreen().scrollDownByScreenSize(); + return this; + } + + public VodqaBL tapInTheMiddleOfTheScreen() { + LOGGER.info("performTapActionInTheMiddle(): perform tap operation in the middle of the screen"); + VodqaScreen.get().tapInTheMiddle(); + return this; + } + + public VodqaBL verifyUserMoveToNextPage(String pageHeading) { + LOGGER.info("performTapActionInTheMiddle(): verify the operation has been executed successfully or not"); + assertThat(VodqaScreen.get().isPreviousPageHeadingVisible(pageHeading)).as(String.format("User is still on %s page", pageHeading)).isFalse(); + return this; + } + + public VodqaBL enterAndVerifyLoginOptionUnderWebViewSection() { + LOGGER.info("Entering into hacker news under webView section"); + assertThat(VodqaScreen.get().enterIntoNewsWebViewSection() + .isUserOnNewsWebViewScreen()) + .as("User unable to navigate to news webview screen") + .isTrue(); + + LOGGER.info("Verify login option is visible for hacker news under web view"); + assertThat(WebViewScreen.get().isLoginOptionVisible()) + .as("Login Option for hacker news under web view is not visible") + .isTrue(); + return this; + } + + public VodqaBL enterIntoNativeViewSection() { + LOGGER.info("Navigating into Native view section"); + assertThat(WebViewScreen.get().navigateToSamplesList() + .enterIntoNativeViewSection() + .isUserOnNativeViewScreen()) + .as("User Unable to navigate to native view section") + .isTrue(); + return this; + } + + public VodqaBL verifyAppWorksInBackground(int time) { + LOGGER.info("Validating app working in background"); + boolean isAppWorkInBackground = VodqaScreen.get().putAppInTheBackground(time).isAppWorkingInBackground(); + assertThat(isAppWorkInBackground).as(String.format("App do not works in background")).isTrue(); + return this; + } + + public VodqaBL scrollInDynamicLayerOnVerticalSwipingScreen(Direction direction) { + VodqaScreen.get().openVerticalSwipingScreen().scrollDownInDynamicLayer(direction); + return this; + } + + public VodqaBL isElementWithTextVisible(String elementText) { + boolean isScrollSuccessful= VodqaScreen.get().isElementWithTextVisible(elementText); + assertThat(isScrollSuccessful).as("Scroll was not successful, text is not visible").isTrue(); + return this; + } + + public VodqaBL scrollVerticallyByPercentageOnVerticalSwipingScreen(int fromPercentHeight, int toPercentHeight, int percentWidth) { + VodqaScreen.get().openVerticalSwipingScreen().scrollVerticallyByPercentage(fromPercentHeight, toPercentHeight, percentWidth); + return this; + } +} \ No newline at end of file diff --git a/src/test/java/com/znsio/teswiz/runner/BrowserStackImageInjectionTest.java b/src/test/java/com/znsio/teswiz/runner/BrowserStackImageInjectionTest.java index 209a88e64..d12936424 100644 --- a/src/test/java/com/znsio/teswiz/runner/BrowserStackImageInjectionTest.java +++ b/src/test/java/com/znsio/teswiz/runner/BrowserStackImageInjectionTest.java @@ -1,7 +1,6 @@ package com.znsio.teswiz.runner; import io.appium.java_client.android.AndroidDriver; -import io.appium.java_client.android.AndroidElement; import org.apache.log4j.Logger; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -19,7 +18,7 @@ class BrowserStackImageInjectionTest { private static final Logger LOGGER = Logger.getLogger( BrowserStackImageInjectionTest.class.getName()); - static AndroidDriver driver; + static AndroidDriver driver; static String authenticationUser = null; static String authenticationKey = null; static String cloudName = null; diff --git a/src/test/java/com/znsio/teswiz/screen/android/confengine/ConfEngineLandingScreenAndroid.java b/src/test/java/com/znsio/teswiz/screen/android/confengine/ConfEngineLandingScreenAndroid.java index 7294aa7d0..eb2e7d8bd 100644 --- a/src/test/java/com/znsio/teswiz/screen/android/confengine/ConfEngineLandingScreenAndroid.java +++ b/src/test/java/com/znsio/teswiz/screen/android/confengine/ConfEngineLandingScreenAndroid.java @@ -26,13 +26,12 @@ public ConfEngineLandingScreenAndroid(Driver driver, Visual visually) { @Override public ConfEngineLandingScreen getListOfConferences() { visually.checkWindow(SCREEN_NAME, "Landing screen"); - Set contextNames = ((AppiumDriver) driver.getInnerDriver()).getContextHandles(); + Set contextNames = ((AppiumDriver) driver.getInnerDriver()).getWindowHandles(); for(String contextName : contextNames) { System.out.println(contextName); //prints out something like NATIVE_APP \n WEBVIEW_1 } - ((AppiumDriver) driver.getInnerDriver()).context(String.valueOf(contextNames.toArray()[1])); - driver.waitTillElementIsPresent(By.xpath("//li[@conference-id='selenium-conf-2022']")) - .click(); + ((AppiumDriver) driver.getInnerDriver()).switchTo().window(String.valueOf(contextNames.toArray()[1])); + driver.waitTillElementIsPresent(By.xpath("//li[@conference-id='selenium-conf-2022']")).click(); visually.checkWindow(SCREEN_NAME, "Selected Selenium Conf 2022"); return this; } diff --git a/src/test/java/com/znsio/teswiz/screen/android/indigo/IndigoGiftVouchersScreenAndroid.java b/src/test/java/com/znsio/teswiz/screen/android/indigo/IndigoGiftVouchersScreenAndroid.java index e6133237f..c76ccd9d3 100644 --- a/src/test/java/com/znsio/teswiz/screen/android/indigo/IndigoGiftVouchersScreenAndroid.java +++ b/src/test/java/com/znsio/teswiz/screen/android/indigo/IndigoGiftVouchersScreenAndroid.java @@ -62,7 +62,7 @@ public IndigoGiftVouchersScreen select(String numberOfGiftVouchersToPurchase, numberOfGiftVouchersToPurchase); driver.waitTillElementIsVisible(By.xpath(quantitytoSelectXpath)).click(); visually.checkWindow(SCREEN_NAME, "Selected voucher quantity"); - Set contextNames = ((AppiumDriver) driver.getInnerDriver()).getContextHandles(); + Set contextNames = ((AppiumDriver) driver.getInnerDriver()).getWindowHandles(); driver.scrollDownByScreenSize(); String lblTotal = driver.findElement(byTotalAmountId).getText(); diff --git a/src/test/java/com/znsio/teswiz/screen/android/jiomeet/InAMeetingScreenAndroid.java b/src/test/java/com/znsio/teswiz/screen/android/jiomeet/InAMeetingScreenAndroid.java index 2c21a503c..1a1b998be 100644 --- a/src/test/java/com/znsio/teswiz/screen/android/jiomeet/InAMeetingScreenAndroid.java +++ b/src/test/java/com/znsio/teswiz/screen/android/jiomeet/InAMeetingScreenAndroid.java @@ -19,6 +19,8 @@ public class InAMeetingScreenAndroid private static final By byMeetingId = By.id("com.jio.rilconferences:id/caller_number"); private static final By byMeetingPasswordId = By.id( "com.jio.rilconferences:id/caller_password"); + + private static final By byMeetingNotificationXpath = By.xpath("//android.widget.TextView[@text='JioMeet Video call']"); private static final By byTopHeaderControlsPanelId = By.id("videoTopLayout1"); private static final String NOT_YET_IMPLEMENTED = " not yet implemented"; private final Driver driver; @@ -53,9 +55,15 @@ public String getMeetingId() { public String getMeetingPassword() { enableInMeetingControls("getMeetingPassword"); return driver.waitTillElementIsPresent(byMeetingPasswordId).getText() - .replace("Password: ", ""); + .replace("Password: ", ""); } + @Override + public InAMeetingScreen openJioMeetNotification() { + LOGGER.info("Opening Jio Meeting notification from notification bar "); + driver.selectNotificationFromNotificationDrawer(byMeetingNotificationXpath); + return this; + } @Override public InAMeetingScreen unmute() { enableInMeetingControls("unmute"); @@ -106,7 +114,7 @@ private void enableInMeetingControls(String calledFrom) { int seconds = 1; LOGGER.info(String.format( "enableInMeetingControls: Called from: '%s', ': headers not displayed. " + - "Wait for '%d' sec and try again", + "Wait for '%d' sec and try again", calledFrom, seconds)); waitFor(seconds); retryAttempt++; @@ -114,7 +122,7 @@ private void enableInMeetingControls(String calledFrom) { isTopHeaderDisplayed = areInMeetingControlsDisplayed(); LOGGER.info(String.format( "enableInMeetingControls: Called from: '%s': retryAttempt: '%d' : are " + - "headers displayed now: '%s'", + "headers displayed now: '%s'", calledFrom, retryAttempt, isTopHeaderDisplayed)); } while(!isTopHeaderDisplayed && retryAttempt < 8); if(!isTopHeaderDisplayed) { @@ -127,4 +135,4 @@ private void enableInMeetingControls(String calledFrom) { private boolean areInMeetingControlsDisplayed() { return driver.isElementPresent(byTopHeaderControlsPanelId); } -} +} \ No newline at end of file diff --git a/src/test/java/com/znsio/teswiz/screen/android/theapp/ClipboardDemoScreenAndroid.java b/src/test/java/com/znsio/teswiz/screen/android/theapp/ClipboardDemoScreenAndroid.java index 2cacbeaf4..4bce33f85 100644 --- a/src/test/java/com/znsio/teswiz/screen/android/theapp/ClipboardDemoScreenAndroid.java +++ b/src/test/java/com/znsio/teswiz/screen/android/theapp/ClipboardDemoScreenAndroid.java @@ -5,8 +5,8 @@ import com.znsio.teswiz.runner.Driver; import com.znsio.teswiz.runner.Visual; import com.znsio.teswiz.screen.theapp.ClipboardDemoScreen; -import io.appium.java_client.MobileElement; import org.apache.log4j.Logger; +import org.openqa.selenium.WebElement; import static com.znsio.teswiz.tools.Wait.waitFor; @@ -53,8 +53,8 @@ private ClipboardDemoScreenAndroid saveEnteredTextToClipBoard() { private ClipboardDemoScreenAndroid enterTextToAddInClipboard(String content) { waitFor(2); - MobileElement contentElement = (MobileElement) driver.findElementByAccessibilityId( - byMessageInputAccessibilityId); + WebElement contentElement = + driver.findElementByAccessibilityId(byMessageInputAccessibilityId); contentElement.click(); contentElement.clear(); contentElement.sendKeys(content); diff --git a/src/test/java/com/znsio/teswiz/screen/android/vodqa/NativeViewScreenAndroid.java b/src/test/java/com/znsio/teswiz/screen/android/vodqa/NativeViewScreenAndroid.java new file mode 100644 index 000000000..86a8dd2a3 --- /dev/null +++ b/src/test/java/com/znsio/teswiz/screen/android/vodqa/NativeViewScreenAndroid.java @@ -0,0 +1,29 @@ +package com.znsio.teswiz.screen.android.vodqa; + +import com.znsio.teswiz.runner.Driver; +import com.znsio.teswiz.runner.Visual; +import com.znsio.teswiz.screen.vodqa.NativeViewScreen; +import io.appium.java_client.AppiumBy; +import org.apache.log4j.Logger; +import org.openqa.selenium.By; + +public class NativeViewScreenAndroid extends NativeViewScreen { + private final Driver driver; + private final Visual visually; + private static final String SCREEN_NAME = NativeViewScreenAndroid.class.getSimpleName(); + private static final Logger LOGGER = Logger.getLogger(SCREEN_NAME); + + private static final By byNativeViewScreenHeaderXpath = AppiumBy.xpath("//android.widget.TextView[@text = 'Native View Demo']"); + + public NativeViewScreenAndroid(Driver driver, Visual visually) { + this.driver = driver; + this.visually = visually; + } + + @Override + public boolean isUserOnNativeViewScreen() { + LOGGER.info("Verify user is on native view screen"); + visually.checkWindow(SCREEN_NAME, "Native View Screen"); + return driver.findElement(byNativeViewScreenHeaderXpath).isDisplayed(); + } +} diff --git a/src/test/java/com/znsio/teswiz/screen/android/vodqa/VodqaScreenAndroid.java b/src/test/java/com/znsio/teswiz/screen/android/vodqa/VodqaScreenAndroid.java new file mode 100644 index 000000000..6f2b2b16d --- /dev/null +++ b/src/test/java/com/znsio/teswiz/screen/android/vodqa/VodqaScreenAndroid.java @@ -0,0 +1,190 @@ +package com.znsio.teswiz.screen.android.vodqa; + +import com.applitools.eyes.appium.Target; +import com.znsio.teswiz.entities.Direction; +import com.znsio.teswiz.runner.Driver; +import com.znsio.teswiz.runner.Runner; +import com.znsio.teswiz.runner.Visual; +import com.znsio.teswiz.screen.vodqa.NativeViewScreen; +import com.znsio.teswiz.screen.vodqa.VodqaScreen; +import com.znsio.teswiz.screen.vodqa.WebViewScreen; +import com.znsio.teswiz.tools.cmd.CommandLineExecutor; +import io.appium.java_client.AppiumBy; +import org.apache.log4j.Logger; +import org.openqa.selenium.By; +import org.openqa.selenium.Point; + +public class VodqaScreenAndroid extends VodqaScreen { + private final Driver driver; + private final Visual visually; + private final String SCREEN_NAME = VodqaScreenAndroid.class.getSimpleName(); + private static final Logger LOGGER = Logger.getLogger(VodqaScreenAndroid.class.getName()); + + private final By byLoginButton = AppiumBy.xpath("//android.view.ViewGroup[@content-desc='login']/android.widget.Button"); + private final By byVerticalSwipeViewGroup = AppiumBy.xpath("//android.view.ViewGroup[@content-desc='verticalSwipe']"); + private final By byCLanguageTextView = AppiumBy.xpath("//android.widget.TextView[@text=' C']"); + private final By byRubyLanguageTextView = AppiumBy.xpath("//android.widget.TextView[@text=' Ruby']"); + private final String screenSelectionXpath = "//android.view.ViewGroup[@content-desc='%s']"; + private final String swipeViewXpath = "//android.widget.TextView[@text='%s']"; + private final String swipeViewTileXpath = "//android.view.ViewGroup[@content-desc='view%s']/android.view.ViewGroup"; + private final By byNativeViewXpath = AppiumBy.xpath("//android.widget.TextView[@content-desc=\"chainedView\"]"); + private final String byPageHeaderXpath = "//android.widget.TextView[@text='%s']"; + private final By byWebViewSectionOptionXpath = AppiumBy.xpath("//android.view.ViewGroup[@content-desc='webView']"); + private final By byNativeViewSectionXpath = AppiumBy.xpath("//android.view.ViewGroup[@content-desc='chainedView']"); + private final String languageTextView = "//android.widget.TextView[@text=' %s']"; + + public VodqaScreenAndroid(Driver driver, Visual visually) { + this.driver = driver; + this.visually = visually; + } + + @Override + public VodqaScreen login() { + driver.waitTillElementIsPresent(byLoginButton); + visually.checkWindow(SCREEN_NAME, "Login Screen"); + driver.findElement(byLoginButton).click(); + return this; + } + + @Override + public VodqaScreen scrollFromOneElementPointToAnother() { + driver.waitTillElementIsPresent(byVerticalSwipeViewGroup); + visually.checkWindow(SCREEN_NAME, "Home Screen"); + driver.findElement(byVerticalSwipeViewGroup).click(); + driver.waitTillElementIsPresent(byCLanguageTextView); + visually.checkWindow(SCREEN_NAME, "Vertical Swiping Screen Before Scroll"); + Point fromPoint = driver.findElement(byRubyLanguageTextView).getLocation(); + Point toPoint = driver.findElement(byCLanguageTextView).getLocation(); + driver.scroll(fromPoint, toPoint); + visually.checkWindow(SCREEN_NAME, "Vertical Swiping Screen After Scroll"); + return this; + } + + @Override + public VodqaScreen tapInTheMiddle() { + driver.waitTillElementIsVisible(byNativeViewXpath); + visually.checkWindow(SCREEN_NAME, "Sample List page"); + driver.tapOnMiddleOfScreen(); + return this; + } + + @Override + public boolean isPreviousPageHeadingVisible(String pageHeading) { + visually.checkWindow(SCREEN_NAME, "Page landed after tapping in the middle"); + return driver.isElementPresent(AppiumBy.xpath(String.format(byPageHeaderXpath, pageHeading))); + } + + @Override + public VodqaScreen openVerticalSwipingScreen() { + driver.waitTillElementIsPresent(byVerticalSwipeViewGroup); + visually.checkWindow(SCREEN_NAME, "Home Screen"); + driver.findElement(byVerticalSwipeViewGroup).click(); + LOGGER.info("vertical swiping screen is open"); + return this; + } + + @Override + public VodqaScreen scrollDownByScreenSize() { + driver.waitTillElementIsPresent(byCLanguageTextView); + driver.scrollDownByScreenSize(); + visually.checkWindow(SCREEN_NAME, "Screen scrolled down"); + return this; + } + + @Override + public VodqaScreen selectScreen(String screenName) { + By byScreenNameXpath = AppiumBy.xpath(String.format(screenSelectionXpath, screenName)); + driver.waitTillElementIsPresent(byScreenNameXpath); + driver.findElement(byScreenNameXpath).click(); + return this; + } + + @Override + public VodqaScreen swipeLeft() { + driver.waitTillElementIsPresent(AppiumBy.xpath(String.format(swipeViewXpath, "1"))); + visually.check(SCREEN_NAME, "Carousel Tile before swipe left", + Target.region(AppiumBy.xpath(String.format(swipeViewTileXpath, "1")))); + driver.swipeLeft(); + return this; + } + + @Override + public boolean isSwipeSuccessful(String elementText) { + boolean isSwipeSuccessful = driver.findElement(AppiumBy.xpath(String.format(swipeViewXpath, elementText))).isDisplayed(); + visually.check(SCREEN_NAME, "Carousel Tile after swipe", Target.region(AppiumBy.xpath(String.format(swipeViewTileXpath, elementText)))); + return isSwipeSuccessful; + } + + @Override + public VodqaScreen swipeRight() { + driver.waitTillElementIsPresent(AppiumBy.xpath(String.format(swipeViewXpath, "1"))); + visually.check(SCREEN_NAME, "Carousel Tile before swipe right", + Target.region(AppiumBy.xpath(String.format(swipeViewTileXpath, "1")))); + driver.swipeRight(); + return this; + } + + @Override + public VodqaScreen swipeByPassingPercentageAttributes(int atPercentScreenHeight, int fromPercentageWidth, int toPercentScreenWidth) { + driver.waitTillElementIsPresent(AppiumBy.xpath(String.format(swipeViewXpath, "1"))); + visually.check(SCREEN_NAME, "Carousel Tile before swipe by percentage Attributes", + Target.region(AppiumBy.xpath(String.format(swipeViewTileXpath, "1")))); + driver.swipeByPassingPercentageAttributes(atPercentScreenHeight, fromPercentageWidth, toPercentScreenWidth); + return this; + } + + @Override + public WebViewScreen enterIntoNewsWebViewSection() { + LOGGER.info("Enter into news web view section"); + visually.checkWindow(SCREEN_NAME, "Sample List Screen"); + driver.waitTillElementIsVisible(byWebViewSectionOptionXpath).click(); + return WebViewScreen.get(); + } + + @Override + public NativeViewScreen enterIntoNativeViewSection() { + LOGGER.info("Enter into native view section"); + visually.checkWindow(SCREEN_NAME, "Sample List Screen"); + driver.waitTillElementIsVisible(byNativeViewSectionXpath).click(); + return NativeViewScreen.get(); + } + + @Override + public VodqaScreen putAppInTheBackground(int time) { + driver.putAppInBackgroundFor(time); + visually.checkWindow(SCREEN_NAME, "App screen should visible after putting app in background"); + return this; + } + + @Override + public boolean isAppWorkingInBackground() { + LOGGER.info("Validating current app package to know app work in background"); + String adbCommand = "adb shell dumpsys window | grep -E 'mCurrentFocus'"; + LOGGER.info(adbCommand); + String currentOpenApp = CommandLineExecutor.execCommand(new String[]{adbCommand}).toString(); + String currentAppPackageName = Runner.getAppPackageName(); + return currentOpenApp.contains(currentAppPackageName); + } + + @Override + public VodqaScreen scrollDownInDynamicLayer(Direction direction) { + driver.waitTillElementIsPresent(byCLanguageTextView); + driver.scrollInDynamicLayer(direction); + return this; + } + + @Override + public boolean isElementWithTextVisible(String elementText) { + By byLanguageTextView = AppiumBy.xpath(String.format(this.languageTextView, elementText)); + visually.check(SCREEN_NAME, String.format("%s language element text view", elementText), Target.region(byLanguageTextView)); + return driver.isElementPresent(byLanguageTextView); + } + + @Override + public VodqaScreen scrollVerticallyByPercentage(int fromPercentHeight, int toPercentHeight, int percentWidth) { + driver.waitTillElementIsPresent(byCLanguageTextView); + driver.scrollVertically(fromPercentHeight, toPercentHeight, percentWidth); + visually.checkWindow(SCREEN_NAME, "Screen scrolled down"); + return this; + } +} diff --git a/src/test/java/com/znsio/teswiz/screen/android/vodqa/WebViewScreenAndroid.java b/src/test/java/com/znsio/teswiz/screen/android/vodqa/WebViewScreenAndroid.java new file mode 100644 index 000000000..92f7eab42 --- /dev/null +++ b/src/test/java/com/znsio/teswiz/screen/android/vodqa/WebViewScreenAndroid.java @@ -0,0 +1,52 @@ +package com.znsio.teswiz.screen.android.vodqa; + +import com.znsio.teswiz.runner.Driver; +import com.znsio.teswiz.runner.Visual; +import com.znsio.teswiz.screen.vodqa.VodqaScreen; +import com.znsio.teswiz.screen.vodqa.WebViewScreen; +import io.appium.java_client.AppiumBy; + +import org.apache.log4j.Logger; +import org.openqa.selenium.By; + +public class WebViewScreenAndroid extends WebViewScreen { + private final Driver driver; + private final Visual visually; + private static final String SCREEN_NAME = WebViewScreenAndroid.class.getSimpleName(); + private static final Logger LOGGER = Logger.getLogger(SCREEN_NAME); + + private static final By byWebViewScreenHeaderXpath = AppiumBy.xpath("//android.widget.TextView[@text = 'Webview']"); + private static final By byLoginOptionWebviewXpath = By.xpath("//a[text()='login']"); + private static final By byBackButtonXpath = AppiumBy.xpath("//android.widget.TextView[@text = 'Back']"); + + public WebViewScreenAndroid(Driver driver, Visual visually) { + this.driver = driver; + this.visually = visually; + } + + @Override + public boolean isUserOnNewsWebViewScreen() { + LOGGER.info("Verify user is on news web view screen"); + visually.checkWindow(SCREEN_NAME, "Web View Screen"); + return driver.findElement(byWebViewScreenHeaderXpath).isDisplayed(); + } + + @Override + public boolean isLoginOptionVisible() { + LOGGER.info("Switching context to web view context and verifying login option under webView is visible"); + visually.checkWindow(SCREEN_NAME, "Web view screen"); + return driver.setWebViewContext() + .findElement(byLoginOptionWebviewXpath) + .isDisplayed(); + } + + @Override + public VodqaScreen navigateToSamplesList() { + LOGGER.info("Switching context to native app and navigate to samples list"); + driver.setNativeAppContext() + .findElement(byBackButtonXpath) + .click(); + visually.checkWindow(SCREEN_NAME, "Sample list screen"); + return VodqaScreen.get(); + } +} diff --git a/src/test/java/com/znsio/teswiz/screen/jiomeet/InAMeetingScreen.java b/src/test/java/com/znsio/teswiz/screen/jiomeet/InAMeetingScreen.java index 5092db67c..079c5cdad 100644 --- a/src/test/java/com/znsio/teswiz/screen/jiomeet/InAMeetingScreen.java +++ b/src/test/java/com/znsio/teswiz/screen/jiomeet/InAMeetingScreen.java @@ -41,4 +41,7 @@ public static InAMeetingScreen get() { public abstract InAMeetingScreen mute(); public abstract String getMicLabelText(); + + public abstract InAMeetingScreen openJioMeetNotification(); + } diff --git a/src/test/java/com/znsio/teswiz/screen/vodqa/NativeViewScreen.java b/src/test/java/com/znsio/teswiz/screen/vodqa/NativeViewScreen.java new file mode 100644 index 000000000..3f65a569c --- /dev/null +++ b/src/test/java/com/znsio/teswiz/screen/vodqa/NativeViewScreen.java @@ -0,0 +1,31 @@ +package com.znsio.teswiz.screen.vodqa; + +import com.znsio.teswiz.entities.Platform; +import com.znsio.teswiz.runner.Driver; +import com.znsio.teswiz.runner.Drivers; +import com.znsio.teswiz.runner.Runner; +import com.znsio.teswiz.runner.Visual; +import com.znsio.teswiz.screen.android.vodqa.NativeViewScreenAndroid; +import org.apache.commons.lang3.NotImplementedException; +import org.apache.log4j.Logger; + +public abstract class NativeViewScreen { + private static final String SCREEN_NAME = NativeViewScreen.class.getSimpleName(); + private static final Logger LOGGER = Logger.getLogger(SCREEN_NAME); + + public static NativeViewScreen get() { + Driver driver = Drivers.getDriverForCurrentUser(Thread.currentThread().getId()); + Platform platform = Runner.fetchPlatform(Thread.currentThread().getId()); + LOGGER.info(SCREEN_NAME + ": Driver type: " + driver.getType() + ": Platform: " + platform); + Visual visually = Drivers.getVisualDriverForCurrentUser(Thread.currentThread().getId()); + + switch(platform) { + case android: + return new NativeViewScreenAndroid(driver, visually); + } + throw new NotImplementedException( + SCREEN_NAME + " is not implemented in " + Runner.getPlatform()); + } + + public abstract boolean isUserOnNativeViewScreen(); +} diff --git a/src/test/java/com/znsio/teswiz/screen/vodqa/VodqaScreen.java b/src/test/java/com/znsio/teswiz/screen/vodqa/VodqaScreen.java new file mode 100644 index 000000000..4afc06d9b --- /dev/null +++ b/src/test/java/com/znsio/teswiz/screen/vodqa/VodqaScreen.java @@ -0,0 +1,66 @@ +package com.znsio.teswiz.screen.vodqa; + +import com.znsio.teswiz.entities.Direction; +import com.znsio.teswiz.entities.Platform; +import com.znsio.teswiz.runner.Driver; +import com.znsio.teswiz.runner.Drivers; +import com.znsio.teswiz.runner.Runner; +import com.znsio.teswiz.runner.Visual; +import com.znsio.teswiz.screen.android.vodqa.VodqaScreenAndroid; +import org.apache.commons.lang3.NotImplementedException; +import org.apache.log4j.Logger; + +public abstract class VodqaScreen { + private static final String SCREEN_NAME = VodqaScreen.class.getSimpleName(); + private static final Logger LOGGER = Logger.getLogger(SCREEN_NAME); + + public static VodqaScreen get() { + Driver driver = Drivers.getDriverForCurrentUser(Thread.currentThread().getId()); + Platform platform = Runner.fetchPlatform(Thread.currentThread().getId()); + LOGGER.info(SCREEN_NAME + ": Driver type: " + driver.getType() + ": Platform: " + platform); + Visual visually = Drivers.getVisualDriverForCurrentUser(Thread.currentThread().getId()); + + switch (platform) { + case android: + return new VodqaScreenAndroid(driver, visually); + } + throw new NotImplementedException( + SCREEN_NAME + " is not implemented in " + Runner.getPlatform()); + } + + public abstract VodqaScreen login(); + + public abstract VodqaScreen scrollFromOneElementPointToAnother(); + + public abstract VodqaScreen tapInTheMiddle(); + + public abstract boolean isPreviousPageHeadingVisible(String pageHeading); + + public abstract VodqaScreen openVerticalSwipingScreen(); + + public abstract VodqaScreen scrollDownByScreenSize(); + + public abstract VodqaScreen selectScreen(String screenName); + + public abstract VodqaScreen swipeLeft(); + + public abstract boolean isSwipeSuccessful(String tileNumber); + + public abstract VodqaScreen swipeRight(); + + public abstract VodqaScreen swipeByPassingPercentageAttributes(int atPercentScreenHeight, int fromPercentScreenWidth, int toPercentScreenWidth); + + public abstract WebViewScreen enterIntoNewsWebViewSection(); + + public abstract NativeViewScreen enterIntoNativeViewSection(); + + public abstract VodqaScreen putAppInTheBackground(int time); + + public abstract boolean isAppWorkingInBackground(); + + public abstract VodqaScreen scrollDownInDynamicLayer(Direction direction); + + public abstract boolean isElementWithTextVisible(String elementText); + + public abstract VodqaScreen scrollVerticallyByPercentage(int fromPercentHeight, int toPercentHeight, int percentWidth); +} diff --git a/src/test/java/com/znsio/teswiz/screen/vodqa/WebViewScreen.java b/src/test/java/com/znsio/teswiz/screen/vodqa/WebViewScreen.java new file mode 100644 index 000000000..aafa6542f --- /dev/null +++ b/src/test/java/com/znsio/teswiz/screen/vodqa/WebViewScreen.java @@ -0,0 +1,35 @@ +package com.znsio.teswiz.screen.vodqa; + +import com.znsio.teswiz.entities.Platform; +import com.znsio.teswiz.runner.Driver; +import com.znsio.teswiz.runner.Drivers; +import com.znsio.teswiz.runner.Runner; +import com.znsio.teswiz.runner.Visual; +import com.znsio.teswiz.screen.android.vodqa.WebViewScreenAndroid; +import org.apache.commons.lang3.NotImplementedException; +import org.apache.log4j.Logger; + +public abstract class WebViewScreen { + private static final String SCREEN_NAME = WebViewScreen.class.getSimpleName(); + private static final Logger LOGGER = Logger.getLogger(SCREEN_NAME); + + public static WebViewScreen get() { + Driver driver = Drivers.getDriverForCurrentUser(Thread.currentThread().getId()); + Platform platform = Runner.fetchPlatform(Thread.currentThread().getId()); + LOGGER.info(SCREEN_NAME + ": Driver type: " + driver.getType() + ": Platform: " + platform); + Visual visually = Drivers.getVisualDriverForCurrentUser(Thread.currentThread().getId()); + + switch(platform) { + case android: + return new WebViewScreenAndroid(driver, visually); + } + throw new NotImplementedException( + SCREEN_NAME + " is not implemented in " + Runner.getPlatform()); + } + + public abstract boolean isUserOnNewsWebViewScreen(); + + public abstract boolean isLoginOptionVisible(); + + public abstract VodqaScreen navigateToSamplesList(); +} \ No newline at end of file diff --git a/src/test/java/com/znsio/teswiz/screen/web/jiomeet/InAMeetingScreenWeb.java b/src/test/java/com/znsio/teswiz/screen/web/jiomeet/InAMeetingScreenWeb.java index 5716fa94b..655f1e663 100644 --- a/src/test/java/com/znsio/teswiz/screen/web/jiomeet/InAMeetingScreenWeb.java +++ b/src/test/java/com/znsio/teswiz/screen/web/jiomeet/InAMeetingScreenWeb.java @@ -7,6 +7,7 @@ import com.znsio.teswiz.runner.Visual; import com.znsio.teswiz.screen.jiomeet.InAMeetingScreen; import com.znsio.teswiz.tools.ReportPortalLogger; +import org.apache.commons.lang.NotImplementedException; import org.apache.log4j.Logger; import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor; @@ -56,7 +57,7 @@ public String getMeetingId() { meetingId = meetingId.replaceAll("\\s", ""); String pin = driver.waitForClickabilityOf(byCurrentMeetingPinXpath).getText(); String invitationLink = driver.waitForClickabilityOf(byCurrentMeetingInvitationLinkXpath) - .getText(); + .getText(); js.executeScript("arguments[0].click()", infoIcon);//to close the meeting info frame visually.takeScreenshot(SCREEN_NAME, "After closing meeting info icon"); LOGGER.info("On Web the meeting id: " + meetingId + " Password: " + pin); @@ -99,12 +100,17 @@ public String getMicLabelText() { return micLabelText; } + @Override + public InAMeetingScreen openJioMeetNotification() { + throw new NotImplementedException("Jio Meet Device Notification of Meeting is not available for Web"); + } + private void enableInMeetingControls(String calledFrom) { try { LOGGER.info(String.format("enableInMeetingControls: Called from: '%s'%n", calledFrom)); Actions actions = new Actions(innerDriver); actions.moveToElement(driver.waitForClickabilityOf(byMeetingInfoIconXpath)) - .moveByOffset(25, 25).perform(); + .moveByOffset(25, 25).perform(); } catch(Exception e) { String logMessage = String.format( "Exception occurred : enableInMeetingControls%nException: %s", @@ -113,4 +119,4 @@ private void enableInMeetingControls(String calledFrom) { ReportPortalLogger.logDebugMessage(logMessage); } } -} +} \ No newline at end of file diff --git a/src/test/java/com/znsio/teswiz/steps/AppLaunchSteps.java b/src/test/java/com/znsio/teswiz/steps/AppLaunchSteps.java index 3efe71603..c52c38ea8 100644 --- a/src/test/java/com/znsio/teswiz/steps/AppLaunchSteps.java +++ b/src/test/java/com/znsio/teswiz/steps/AppLaunchSteps.java @@ -25,7 +25,7 @@ public AppLaunchSteps() { public void startOn(String userPersona, String appName) { String[] appNameParts = appName.split("-"); appName = appNameParts[0].toLowerCase(Locale.ROOT) + "_" + Runner.getCloudName() - .toLowerCase(); + .toLowerCase(); String onPlatform = appNameParts[appNameParts.length - 1].toLowerCase(Locale.ROOT); LOGGER.info(System.out.printf("startOn - Persona:'%s', AppName: '%s', Platform: '%s'", userPersona, appName, onPlatform)); diff --git a/src/test/java/com/znsio/teswiz/steps/JioMeetSteps.java b/src/test/java/com/znsio/teswiz/steps/JioMeetSteps.java index 36cb49cb0..0c2d77ef5 100644 --- a/src/test/java/com/znsio/teswiz/steps/JioMeetSteps.java +++ b/src/test/java/com/znsio/teswiz/steps/JioMeetSteps.java @@ -112,4 +112,14 @@ public void joinsTheMeetingFromOn(String userPersona, String appName, String pla String meetingPassword = context.getTestStateAsString(SAMPLE_TEST_CONTEXT.MEETING_PASSWORD); new JoinAMeetingBL(userPersona, onPlatform).joinMeeting(meetingId, meetingPassword); } + + @When("I open the JioMeet meeting notification from notification bar") + public void iOpenTheNotificationFromNotificationBar() { + new InAMeetingBL().openNotificationFromNotificationBar(); + } + + @Then("I should be able to go back to Meeting") + public void iShouldBeAbleToGoBackToMeeting() { + new InAMeetingBL().verifyMeetingOpenedInJioMeetApplication(); + } } diff --git a/src/test/java/com/znsio/teswiz/steps/VodQASteps.java b/src/test/java/com/znsio/teswiz/steps/VodQASteps.java new file mode 100644 index 000000000..d1607a517 --- /dev/null +++ b/src/test/java/com/znsio/teswiz/steps/VodQASteps.java @@ -0,0 +1,102 @@ +package com.znsio.teswiz.steps; + +import com.context.SessionContext; +import com.context.TestExecutionContext; +import com.znsio.teswiz.businessLayer.vodqa.VodqaBL; +import com.znsio.teswiz.entities.Direction; +import com.znsio.teswiz.entities.SAMPLE_TEST_CONTEXT; +import com.znsio.teswiz.runner.Drivers; +import com.znsio.teswiz.runner.Runner; +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import org.apache.log4j.Logger; + +public class VodQASteps { + private static final Logger LOGGER = Logger.getLogger(VodQASteps.class.getName()); + private final TestExecutionContext context; + + public VodQASteps() { + context = SessionContext.getTestExecutionContext(Thread.currentThread().getId()); + LOGGER.info("context: " + context.getTestName()); + } + + @Given("I login to vodqa application using valid credentials") + public void loginToApplication() { + Drivers.createDriverFor(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform(), context); + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()).login(); + } + + @When("I scroll from one to another element point on vertical swiping screen") + public void scrollToElement() { + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()).scrollFromOneElementPointToAnother(); + } + + @When("I tap in the middle of the screen") + public void iTapInTheMiddleOfTheScreen() { + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()).tapInTheMiddleOfTheScreen(); + } + + @Then("I am able to move from {string} page to next page") + public void iAmAbleToMoveFromPageToNextPage(String pageHeading) { + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()).verifyUserMoveToNextPage(pageHeading); + } + + @When("I scroll down by screen size on vertical swiping screen") + public void iScrollDownByScreenSizeOnVerticalSwipingScreen() { + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()).scrollDownByScreenSizeOnVerticalSwipingScreen(); + } + + @When("I swipe left on {string} screen") + public void selectScreenAndSwipeLeft(String screenName) { + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()).selectScreenAndSwipeLeft(screenName); + } + + @When("I swipe right on {string} screen") + public void selectScreenAndSwipeRight(String screenName) { + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()).selectScreenAndSwipeRight(screenName); + } + + @Then("I am able to see element with text {string} on the screen") + public void iAmAbleToSeeElementWithTextOnTheScreen(String elementText) { + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()).verifySwipe(elementText); + } + + @When("I swipe at {int} percent height from {int} percent width to {int} percent width on {string} screen") + public void iSwipeAtPercentHeightFromPercentWidthToPercentWidthOnScreen(int atPercentileHeight, int fromPercentageWidth, int toPercentageWidth, String screenName) { + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()) + .selectScreenAndSwipeByPassingPercentageAttributes(atPercentileHeight, fromPercentageWidth, toPercentageWidth, screenName); + } + + @Then("I am able to view hacker news login button inside web view section") + public void iAmAbleToViewHackerNewsLoginButtonInsideWebViewSection() { + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()).enterAndVerifyLoginOptionUnderWebViewSection(); + } + + @And("I am able to view section header by navigating inside native view section") + public void iAmAbleToViewSectionHeaderByNavigatingInsideNativeViewSection() { + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()).enterIntoNativeViewSection(); + } + + @Then("App should work in background for {int} sec") + public void appShouldWorkInBackgroundForDefinedTime(int time) { + new VodqaBL().verifyAppWorksInBackground(time); + } + + @Then("Element text {string} should be visible") + public void elementTextShouldBeVisible(String elementText) { + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()).isElementWithTextVisible(elementText); + } + + @When("I scroll {string} in dynamic layer on vertical swiping screen") + public void iScrollInDynamicLayerOnVerticalSwipingScreen(String direction) { + new VodqaBL(SAMPLE_TEST_CONTEXT.ME, Runner.getPlatform()) + .scrollInDynamicLayerOnVerticalSwipingScreen(Direction.valueOf(direction.toUpperCase())); + } + + @When("I scroll vertically from {int} percent height to {int} percent height and {int} percent width") + public void iScrollVerticallyFromPercentHeightToPercentHeightAndPercentWidth(int fromPercentHeight, int toPercentHeight, int percentWidth) { + new VodqaBL().scrollVerticallyByPercentageOnVerticalSwipingScreen(fromPercentHeight, toPercentHeight, percentWidth); + } +} diff --git a/src/test/resources/com/znsio/teswiz/features/jiomeet.feature b/src/test/resources/com/znsio/teswiz/features/jiomeet.feature index e26fd89c4..f9d88aa61 100644 --- a/src/test/resources/com/znsio/teswiz/features/jiomeet.feature +++ b/src/test/resources/com/znsio/teswiz/features/jiomeet.feature @@ -45,4 +45,11 @@ Feature: In a meeting scenarios And "Guest-2" joins the meeting from "jiomeet-chrome" on "web" Then "Host" should be able to get to chat window When "Host" sends "Hey" chat message - Then "Guest-2" should see the chat message on its chat window \ No newline at end of file + Then "Guest-2" should see the chat message on its chat window + +# CONFIG=./configs/jiomeet_local_config.properties TAG="@jiomeet and @selectNotificationTest" PLATFORM=android ./gradlew run + @selectNotificationTest @android + Scenario: User should be able to view and open the JioMeet Meeting Notification + Given "Host" logs-in and starts an instant meeting in "jiomeetLatest" on "android" + When I open the JioMeet meeting notification from notification bar + Then I should be able to go back to Meeting diff --git a/src/test/resources/com/znsio/teswiz/features/multiuser-multidevice.feature b/src/test/resources/com/znsio/teswiz/features/multiuser-multidevice.feature index c4b457027..4583f61d3 100644 --- a/src/test/resources/com/znsio/teswiz/features/multiuser-multidevice.feature +++ b/src/test/resources/com/znsio/teswiz/features/multiuser-multidevice.feature @@ -33,12 +33,14 @@ Feature: Test valid and invalid login @multiuser-android-web Scenario: Verify 2 different apps and 2 web sites orchestration Given "you" start "Calculator-Android" - And "I" start "theapp-Android" + And "I" start "Calculator-Android" +# And "I" start "theapp-Android" And "someone" starts "images-web" on "chrome" - And "someone-else" starts "bing-web" on "firefox" - Then "I" login with invalid credentials - "znsio5", "invalid password" + And "someone_else" starts "bing-web" on "chrome" +# Then "I" login with invalid credentials - "znsio5", "invalid password" + And "I" select "8" + And "you" select "7" When "someone" searches for "bear" - And "someone-else" searches for "tiger" + And "someone_else" searches for "tiger" And "you" select "2" - And "you" press "plus" - And "you" select "5" \ No newline at end of file + And "I" select "3" \ No newline at end of file diff --git a/src/test/resources/com/znsio/teswiz/features/vodqa.feature b/src/test/resources/com/znsio/teswiz/features/vodqa.feature new file mode 100644 index 000000000..e8e4e5ebc --- /dev/null +++ b/src/test/resources/com/znsio/teswiz/features/vodqa.feature @@ -0,0 +1,72 @@ +@vodqa +# CONFIG=./configs/vodqa_local_config.properties PLATFORM=android TAG=vodqa ./gradlew run +Feature: Vodqa test + + # CONFIG=./configs/vodqa_local_config.properties PLATFORM=android TAG=scrollUsing2Points ./gradlew run + @android @scrollUsing2Points + Scenario: Validating scroll functionality using 2 points + Given I login to vodqa application using valid credentials + When I scroll from one to another element point on vertical swiping screen + Then Element text "Jasmine" should be visible + + # CONFIG=./configs/vodqa_local_config.properties PLATFORM=android TAG=tapInMiddleOfScreen ./gradlew run + @android @tapInMiddleOfScreen + Scenario: User tap in the middle of the screen + Given I login to vodqa application using valid credentials + When I tap in the middle of the screen + Then I am able to move from "Samples List" page to next page + + # CONFIG=./configs/vodqa_local_config.properties PLATFORM=android TAG=scrollDownByScreenSize ./gradlew run + @android @scrollDownByScreenSize + Scenario: Validate that user is able to scroll down by screen size + Given I login to vodqa application using valid credentials + When I scroll down by screen size on vertical swiping screen + Then Element text "Jasmine" should be visible + + # CONFIG=./configs/vodqa_local_config.properties TAG=@swipeLeft PLATFORM=android ./gradlew run + @android @swipeLeft + Scenario: validating swipe left functionality + Given I login to vodqa application using valid credentials + When I swipe left on "carousel" screen + Then I am able to see element with text "2" on the screen + + # CONFIG=./configs/vodqa_local_config.properties TAG=@swipeRight PLATFORM=android ./gradlew run + @android @swipeRight + Scenario: validating swipe right functionality + Given I login to vodqa application using valid credentials + When I swipe right on "carousel" screen + Then I am able to see element with text "3" on the screen + + # CONFIG=./configs/vodqa_local_config.properties TAG=@swipeByPercentageAttributes PLATFORM=android ./gradlew run + @android @swipeByPercentageAttributes + Scenario: validating Swipe by percentage Attributes functionality + Given I login to vodqa application using valid credentials + When I swipe at 60 percent height from 10 percent width to 70 percent width on "carousel" screen + Then I am able to see element with text "3" on the screen + + # CONFIG=./configs/vodqa_local_config.properties PLATFORM=android TAG=vodqaContextSwitch ./gradlew run + @vodqaContextSwitch @android + Scenario: Validate context switching between native and web view context + Given I login to vodqa application using valid credentials + Then I am able to view hacker news login button inside web view section + And I am able to view section header by navigating inside native view section + + # CONFIG=./configs/vodqa_local_config.properties TAG=@appInBackground PLATFORM=android ./gradlew run + @android @appInBackground + Scenario: Put app in background + Given I login to vodqa application using valid credentials + Then App should work in background for 5 sec + + # CONFIG=./configs/vodqa_local_config.properties TAG=@scrollInDynamicLayer PLATFORM=android ./gradlew run + @android @scrollInDynamicLayer + Scenario: Validating scroll in dynamic layer functionality + Given I login to vodqa application using valid credentials + When I scroll "down" in dynamic layer on vertical swiping screen + Then Element text ".net" should be visible + + # CONFIG=./configs/vodqa_local_config.properties TAG=@scrollVertically PLATFORM=android ./gradlew run + @android @scrollVertically + Scenario: Validate that user is able to scroll vertically by screen percentage + Given I login to vodqa application using valid credentials + When I scroll vertically from 60 percent height to 20 percent height and 50 percent width + Then Element text "Jasmine" should be visible \ No newline at end of file