├── .nojekyll
├── gradle.properties
├── settings.gradle
├── script
├── startemulator.bat
├── plugins.txt
├── pixel.json
├── server.bat
└── uploadapp.sh
├── docs
├── gif
│ ├── gif_ios.gif
│ └── gif_android.gif
├── img
│ ├── appium1.png
│ ├── appium2.png
│ ├── appium3.png
│ ├── appium4.png
│ ├── uiautomator.png
│ └── FrameworkArchitecture.png
└── index.md
├── input
├── sqlite
│ └── testdata.db
└── Datasheet.csv
├── .gitignore
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .github
├── workflows
│ ├── docs.yml
│ ├── release-drafter.yml
│ └── gradle.yml
├── dependabot.yml
├── ISSUE_TEMPLATE
│ ├── feature_requested.md
│ └── bug_report.md
├── config.yml
└── PULL_REQUEST_TEMPLATE.md
├── src
├── main
│ ├── resources
│ │ ├── application.conf
│ │ └── log4j.properties
│ └── java
│ │ └── com
│ │ ├── core
│ │ ├── Constants.java
│ │ ├── DriverManager.java
│ │ ├── Access.java
│ │ ├── ServerManager.java
│ │ ├── DataActions.java
│ │ ├── ApiActions.java
│ │ ├── ADB.java
│ │ ├── AppiumController.java
│ │ └── UserActions.java
│ │ ├── exception
│ │ ├── DeviceException.java
│ │ ├── MobileAppException.java
│ │ ├── AppiumException.java
│ │ └── ElementException.java
│ │ ├── model
│ │ └── ApiResponse.java
│ │ ├── logging
│ │ ├── TestStatus.java
│ │ └── ResultSender.java
│ │ ├── constants
│ │ └── Arg.java
│ │ ├── reporting
│ │ ├── Listeners
│ │ │ ├── AnnotationTransformer.java
│ │ │ ├── Retry.java
│ │ │ └── TestListener.java
│ │ ├── ExtentReports
│ │ │ ├── ExtentManager.java
│ │ │ └── ExtentTestManager.java
│ │ └── AWS
│ │ │ └── UploadReport.java
│ │ ├── pages
│ │ ├── LoginPage.java
│ │ └── HomePage.java
│ │ ├── config
│ │ └── AppConfig.java
│ │ └── utils
│ │ └── FileSystem.java
└── test
│ ├── suite
│ └── testng.xml
│ └── java
│ └── com
│ ├── TestDefinitionLayer
│ ├── TC_Test_SauseLabsApp.java
│ └── TC_Test_AndroidBooking.java
│ ├── MockServiceLayer
│ ├── TestDatabase.java
│ ├── WireMock.java
│ └── TC001_MockService.java
│ └── ServiceLayer
│ └── API_Test.java
├── mkdocs.yml
├── docker-compose.yml
├── CONTRIBUTING.md
├── LICENSE
├── Jenkinsfile
├── Dockerfile
├── docker-compose-infra.yml
├── gradlew.bat
├── CODE_OF_CONDUCT.md
├── README.md
└── gradlew
/.nojekyll:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'MobileTestFramework'
2 |
3 |
--------------------------------------------------------------------------------
/script/startemulator.bat:
--------------------------------------------------------------------------------
1 | cd C:\Users\dipjyoti\AppData\Local\Android\Sdk\emulator
2 | emulator -avd Pixel3
--------------------------------------------------------------------------------
/docs/gif/gif_ios.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dipjyotimetia/MobileTestFramework/HEAD/docs/gif/gif_ios.gif
--------------------------------------------------------------------------------
/docs/img/appium1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dipjyotimetia/MobileTestFramework/HEAD/docs/img/appium1.png
--------------------------------------------------------------------------------
/docs/img/appium2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dipjyotimetia/MobileTestFramework/HEAD/docs/img/appium2.png
--------------------------------------------------------------------------------
/docs/img/appium3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dipjyotimetia/MobileTestFramework/HEAD/docs/img/appium3.png
--------------------------------------------------------------------------------
/docs/img/appium4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dipjyotimetia/MobileTestFramework/HEAD/docs/img/appium4.png
--------------------------------------------------------------------------------
/docs/gif/gif_android.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dipjyotimetia/MobileTestFramework/HEAD/docs/gif/gif_android.gif
--------------------------------------------------------------------------------
/docs/img/uiautomator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dipjyotimetia/MobileTestFramework/HEAD/docs/img/uiautomator.png
--------------------------------------------------------------------------------
/input/sqlite/testdata.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dipjyotimetia/MobileTestFramework/HEAD/input/sqlite/testdata.db
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | .idea
3 | .allure
4 | allure-results
5 | build
6 | out
7 | logs
8 | Reports
9 | ScreensDoc
10 | Screenshots
--------------------------------------------------------------------------------
/docs/img/FrameworkArchitecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dipjyotimetia/MobileTestFramework/HEAD/docs/img/FrameworkArchitecture.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dipjyotimetia/MobileTestFramework/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/script/plugins.txt:
--------------------------------------------------------------------------------
1 | git
2 | docker
3 | allure
4 | BrowserStack
5 | build-with-parameters
6 | configuration-as-code
7 | docker-plugin
8 | ssh-credentials
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Apr 14 13:45:26 AEST 2020
2 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
3 | distributionBase=GRADLE_USER_HOME
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/input/Datasheet.csv:
--------------------------------------------------------------------------------
1 | TestcaseInstance,TestcaseName,Field1,Value1,Field2,Value2,Field3,Value3,Field4,Value4,Field5,Value5,Field6,Value6,Field7,Value7,Field8,Value8,Field9,Value9,Field10,Value10,Field11,Value11,Field12,Value12,Field13,Value13,Field14,Value14,Field15,Value15,Field16,Value16,Field17,Value17,Field18,Value18,Field19,Value19,Field20,Value20,Field21,Value21,Field22,Value22,Field23,Value23,Field24,Value24
2 | 1,TC_Test_AndroidBooking,UserName,,Password
3 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: docs
2 | on:
3 | push:
4 | branches:
5 | - master
6 | jobs:
7 | deploy:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v4
11 | - uses: actions/setup-python@v5
12 | with:
13 | python-version: 3.x
14 | - run: pip install mkdocs-material
15 | - run: mkdocs gh-deploy --force
16 | env:
17 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18 |
--------------------------------------------------------------------------------
/src/main/resources/application.conf:
--------------------------------------------------------------------------------
1 | application{
2 | name = "MobileTestFramework"
3 | },
4 | appium {
5 | appiumport = 4723
6 | proxyport = 9001
7 | },
8 | api{
9 | baseuri = ""
10 | username = ""
11 | userpass = ""
12 | tokenuri = ""
13 | clientuser = ""
14 | clisentpass = ""
15 | },
16 | browserStack {
17 | appium_version = "1.22.0"
18 | debug = false
19 | devicelogs = false
20 | networkLogs = false
21 | acceptInsecureCerts = false
22 | appiumLogs = true
23 | video = true
24 | gpsLocation = "0,0"
25 | disableAnimations = false
26 | }
27 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "github-actions"
4 | directory: "/"
5 | schedule:
6 | # Check for updates to GitHub Actions every weekday
7 | interval: "monthly"
8 |
9 | - package-ecosystem: "gradle" # See documentation for possible values
10 | directory: "/" # Location of package manifests
11 | schedule:
12 | interval: "monthly"
13 | time: "19:00"
14 | timezone: Australia/Melbourne
15 | rebase-strategy: "auto"
16 | labels:
17 | - "security"
18 | - "dependencies"
19 | open-pull-requests-limit: 10
20 |
--------------------------------------------------------------------------------
/script/pixel.json:
--------------------------------------------------------------------------------
1 | {
2 | "capabilities": [
3 | {
4 | "platformName": "Android",
5 | "applicationName": "UiAutomator2",
6 | "appPackage": "com.booking",
7 | "appActivity": ".startup.HomeActivity"
8 | }
9 | ],
10 | "configuration": {
11 | "cleanUpCycle": 2000,
12 | "timeout": 30000,
13 | "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
14 | "url": "http://127.0.0.1:4000/wd/hub",
15 | "host": "127.0.0.1",
16 | "port": 4000,
17 | "maxSession": 1,
18 | "register": true,
19 | "registerCycle": 5000,
20 | "hubPort": "4444",
21 | "hubHost": "127.0.0.1"
22 | }
23 | }
--------------------------------------------------------------------------------
/.github/workflows/release-drafter.yml:
--------------------------------------------------------------------------------
1 | name: Release Drafter
2 |
3 | on:
4 | push:
5 | # branches to consider in the event; optional, defaults to all
6 | branches:
7 | - master
8 |
9 | jobs:
10 | update_release_draft:
11 | runs-on: ubuntu-latest
12 | steps:
13 | # Drafts your next Release notes as Pull Requests are merged into "master"
14 | - uses: release-drafter/release-drafter@v6
15 | with:
16 | # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml
17 | config-name: config.yml
18 | env:
19 | GITHUB_TOKEN: ${{ secrets.RELEASE_DRAFTER_TOKEN }}
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_requested.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: MobileTestFramework
2 | theme:
3 | name: material
4 | palette:
5 | primary: deep purple
6 | features:
7 | - search.suggest
8 | - search.highlight
9 | - navigation.tabs
10 | - navigation.tabs.sticky
11 | - navigation.indexes
12 | icon:
13 | repo: fontawesome/brands/git-alt
14 | plugins:
15 | - search
16 | extra:
17 | social:
18 | - icon: fontawesome/brands/github
19 | link: https://github.com/dipjyotimetia
20 | - icon: fontawesome/brands/linkedin
21 | link: https://linkedin.com/in/dipjyotimetia/
22 | - icon: fontawesome/brands/medium
23 | link: https://medium.com/@dipjyotimetia
24 | copyright: Copyright © 2018 - 2021 Dipjyoti Metia
25 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | # more info https://hub.docker.com/r/appium/appium/
4 | services:
5 | # Selenium hub
6 | selenium_hub:
7 | image: selenium/hub
8 | ports:
9 | - "4444:4444"
10 |
11 | # Appium docker android
12 | appium_android_device:
13 | image: appium/appium
14 | depends_on:
15 | - selenium_hub
16 | privileged: true
17 | volumes:
18 | - /dev/bus/usb:/dev/bus/usb
19 | - ~/.android:/root/.android
20 | - "./input/app:/root/tmp"
21 | environment:
22 | - CONNECT_TO_GRID=true
23 | - SELENIUM_HOST=selenium_hub #172.17.0.0
24 | - SELENIUM_PORT=4444
25 | - APPIUM_HOST="127.0.0.1"
26 | - APPIUM_PORT=4723
27 | - RELAXED_SECURITY=true
--------------------------------------------------------------------------------
/script/server.bat:
--------------------------------------------------------------------------------
1 | https://www.browserstack.com/guide/selenium-grid-4-tutorial
2 |
3 | @REM Standalone
4 | java -jar selenium-server-4.0.0-beta-4.jar standalone
5 |
6 | @REM Hub and Node
7 | java -jar selenium-server-4.0.0-beta-4.jar hub
8 |
9 | java -jar selenium-server-4.0.0-alpha-7.jar node --detect-drivers true
10 |
11 | @REM Distributed
12 | java -jar selenium-server-4.0.0-beta-4.jar sessions
13 |
14 | java -jar selenium-server-4.0.0-beta-4.jar distributor --sessions http://localhost:5556
15 |
16 | java -jar selenium-server-4.0.0-beta-4.jar router --sessions http://localhost:5556 --distributor http://localhost:5553
17 |
18 |
19 | @REM # Window 2: the iOS node
20 | appium -p 4723 --nodeconfig /path/to/nodeconfig-ios.json
21 |
22 | @REM # Window 3: the Android node
23 | appium -p 4733 --nodeconfig /path/to/nodeconfig-android.json
--------------------------------------------------------------------------------
/script/uploadapp.sh:
--------------------------------------------------------------------------------
1 | echo "**************** PUBLISH APP TO SAUCELABS WITH THIS DATA ******************"
2 |
3 | #-F "file=@/path/to/app/file/app-debug.ipa"
4 | echo "Enter the app name: "
5 | # shellcheck disable=SC2162
6 | read app
7 | echo "The Current User Name is $app"
8 |
9 | if [ "$app" == "android" ]; then
10 | curl -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" \
11 | -X POST "https://api-cloud.browserstack.com/app-automate/upload" \
12 | -F "url=https://github.com/saucelabs/sample-app-mobile/releases/download/2.7.1/Android.SauceLabs.Mobile.Sample.app.2.7.1.apk"
13 | else
14 | curl -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" \
15 | -X POST "https://api-cloud.browserstack.com/app-automate/upload" \
16 | -F "url=https://github.com/saucelabs/sample-app-mobile/releases/download/2.7.1/iOS.RealDevice.SauceLabs.Mobile.Sample.app.2.7.1.ipa"
17 | fi
18 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug Report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: 'Dipjyoti Metia'
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Smartphone (please complete the following information):**
27 | - Device: [e.g. iPhone8]
28 | - OS: [e.g. iOS12.1]
29 | - Browser [e.g. stock browser, safari]
30 | - Version [e.g. 15]
31 |
32 | **Additional context**
33 | Add any other context about the problem here.
34 |
--------------------------------------------------------------------------------
/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | # Logging level
2 | solr.log=logs/
3 | log4j.rootLogger=INFO, file, CONSOLE
4 | log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
5 | log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
6 | log4j.appender.CONSOLE.layout.ConversionPattern=%-5p - %d{yyyy-MM-dd HH:mm:ss.SSS}; %C: %m\n
7 | #- size rotation with log cleanup.
8 | log4j.appender.file=org.apache.log4j.RollingFileAppender
9 | log4j.appender.file.MaxFileSize=50MB
10 | log4j.appender.file.MaxBackupIndex=9
11 | #- File to log to and log format
12 | log4j.appender.file.File=${solr.log}/logfile.log
13 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
14 | log4j.appender.file.layout.ConversionPattern=%-5p - %d{yyyy-MM-dd HH:mm:ss.SSS}; %C{1}: %m\n
15 | log4j.logger.org.apache.zookeeper=WARN
16 | log4j.logger.org.apache.hadoop=WARN
17 | # set to INFO to enable infostream log messages
18 | log4j.logger.org.apache.solr.update.LoggingInfoStream=OFF
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to MobileTestFramework
2 |
3 | This framework welcomes contributions from everyone. There are a
4 | number of ways you can help:
5 |
6 | ## Bug Reports
7 |
8 | When opening new issues or commenting on existing issues please make
9 | sure discussions are related to concrete technical issues.
10 |
11 | It's imperative that issue reports outline the steps to reproduce
12 | the defect. If the issue can't be reproduced it will be closed.
13 | Please provide and describe what results you are seeing and what results you expect.
14 |
15 | ## Feature Requests
16 |
17 | If you find that some functions are missing, feel free to open an issue
18 | with details describing what feature(s) you'd like added or changed.
19 |
20 | If you'd like a hand at trying to implement the feature yourself, please feel free to create a pull request.
21 |
22 | ## Code Optimization
23 |
24 | You are always welcome to improve the code optimizations wherever required.
25 |
--------------------------------------------------------------------------------
/src/test/suite/testng.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/test/java/com/TestDefinitionLayer/TC_Test_SauseLabsApp.java:
--------------------------------------------------------------------------------
1 | package com.TestDefinitionLayer;
2 |
3 | import com.core.UserActions;
4 | import com.pages.LoginPage;
5 | import com.reporting.ExtentReports.ExtentTestManager;
6 | import io.qameta.allure.Feature;
7 | import io.qameta.allure.Link;
8 | import io.qameta.allure.Severity;
9 | import io.qameta.allure.SeverityLevel;
10 | import org.testng.annotations.Test;
11 |
12 | public class TC_Test_SauseLabsApp extends UserActions {
13 | @Link("Test")
14 | @Feature("test")
15 | @Severity(SeverityLevel.CRITICAL)
16 | @Test(description = "Demo Test")
17 | public void E2E_TestSauseLabs() {
18 |
19 | String TCname = "TC_Test_IOSSause";
20 |
21 | LoginPage loginPage = new LoginPage();
22 |
23 | ExtentTestManager.getTest().setDescription("Sause Login");
24 |
25 | try {
26 | loginPage.login();
27 | } catch (Exception e) {
28 | catchBlock(e);
29 | } finally {
30 | ExtentTestManager.endTest();
31 | }
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/.github/config.yml:
--------------------------------------------------------------------------------
1 | name-template: 'v$RESOLVED_VERSION'
2 | tag-template: 'v$RESOLVED_VERSION'
3 | categories:
4 | - title: '🚀 Features'
5 | labels:
6 | - 'feature'
7 | - 'enhancement'
8 | - title: '🐛 Bug Fixes'
9 | labels:
10 | - 'fix'
11 | - 'bugfix'
12 | - 'bug'
13 | - title: '✅ Tests'
14 | label: 'test'
15 | - title: '⚡ Performance'
16 | label: 'performance'
17 | - title: '📝 Documentation'
18 | label: 'docs'
19 | - title: '🔐 Security'
20 | label: 'security'
21 | - title: '🧰 Maintenance'
22 | label:
23 | - 'cicd'
24 | - 'tech'
25 | - title: '🤖 Dependencies'
26 | label: 'dependencies'
27 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
28 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
29 | version-resolver:
30 | major:
31 | labels:
32 | - 'major'
33 | minor:
34 | labels:
35 | - 'minor'
36 | patch:
37 | labels:
38 | - 'patch'
39 | default: patch
40 | template: |
41 | ## Changes
42 |
43 | $CHANGES
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Dipjyoti Metia
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Summary
4 |
5 |
13 |
14 | ## Test Plan
15 |
16 |
17 |
18 | ### What's required for testing (prerequisites)?
19 |
20 | ### What are the steps to reproduce (after prerequisites)?
21 |
22 | ## Compatibility
23 |
24 | | Platform | Implemented |
25 | | -------- | :---------: |
26 | | Android | ✅❌ |
27 | | iOS | ✅❌ |
28 |
29 | ## Checklist
30 |
31 |
32 |
33 | - [ ] I have tested this on all mobile platforms
34 | - [ ] I added the documentation in `README.md`
35 | - [ ] I updated function description
--------------------------------------------------------------------------------
/src/main/java/com/core/Constants.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.core;
25 |
26 | /**
27 | * @author Dipjyoti Metia
28 | */
29 | public interface Constants {
30 | int KEYBOARD_ANIMATION_DELAY = 1000;
31 | }
32 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | pipeline {
2 | agent { label 'win-local' }
3 | stages {
4 | stage('Build') {
5 | steps {
6 | bat 'gradle clean'
7 | }
8 | }
9 |
10 | stage('SonarQube analysis') {
11 | steps {
12 | withSonarQubeEnv('My SonarQube Server') {
13 | bat 'gradle sonarqube'
14 | }
15 | }
16 | }
17 |
18 | stage('End to End Test'){
19 | steps {
20 | bat 'gradle E2E -Pdownload=NO -Pcloud=YES'
21 | }
22 | }
23 | }
24 |
25 | post {
26 | always {
27 | bat 'gradle allureReport'
28 | script {
29 | allure([
30 | includeProperties: false,
31 | jdk: '',
32 | properties: [],
33 | reportBuildPolicy: 'ALWAYS',
34 | results: [[path: 'build/allure-results']]
35 | ])
36 | }
37 | publishHTML target: [
38 | allowMissing: false,
39 | alwaysLinkToLastBuild: true,
40 | keepAll: false,
41 | reportDir: 'build/reports/tests/E2E',
42 | reportFiles: 'index.html',
43 | reportName: 'Gradle Report'
44 | ]
45 |
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/src/main/java/com/core/DriverManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.core;
25 |
26 | import io.appium.java_client.AppiumDriver;
27 |
28 | /**
29 | * @author Dipjyoti Metia
30 | */
31 | public class DriverManager extends AppiumController {
32 |
33 | public AppiumDriver driver;
34 |
35 | public DriverManager() {
36 | this.driver = super.getDriver();
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/exception/DeviceException.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.exception;
25 |
26 | /**
27 | * @author Dipjyoti Metia
28 | */
29 | public class DeviceException extends Exception {
30 | /**
31 | * Device exception
32 | *
33 | * @param message exception message
34 | */
35 | public DeviceException(String message) {
36 | super(message);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/exception/MobileAppException.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.exception;
25 |
26 | /**
27 | * @author Dipjyoti Metia
28 | */
29 | public class MobileAppException extends Exception {
30 | /**
31 | * App exception
32 | *
33 | * @param message exception message
34 | */
35 | public MobileAppException(String message) {
36 | super(message);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/exception/AppiumException.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.exception;
25 |
26 | /**
27 | * @author Dipjyoti Metia
28 | */
29 | public class AppiumException extends Exception {
30 |
31 | /**
32 | * Appium server exception
33 | *
34 | * @param message exception message
35 | */
36 | public AppiumException(String message) {
37 | super(message);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM java:11-jdk
2 |
3 | ENV GRADLE_VERSION 6.9.0
4 | ENV ALLURE_VERSION 2.14.0
5 |
6 | RUN echo "deb [check-valid-until=no] http://cdn-fastly.deb.debian.org/debian jessie main" > /etc/apt/sources.list.d/jessie.list
7 | RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" > /etc/apt/sources.list.d/jessie-backports.list
8 | RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list
9 | RUN apt-get -o Acquire::Check-Valid-Until=false update
10 | RUN apt-get install -y vim wget curl git python-pip python-dev build-essential
11 |
12 | # Install Gradle
13 | RUN wget https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip && \
14 | unzip gradle-${GRADLE_VERSION}-bin.zip && \
15 | mv gradle-${GRADLE_VERSION} /opt/ && \
16 | rm gradle-${GRADLE_VERSION}-bin.zip
17 | ENV GRADLE_HOME /opt/gradle-${GRADLE_VERSION}
18 | ENV PATH $PATH:$GRADLE_HOME/bin
19 |
20 | RUN echo "export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64" >> ~/.bashrc
21 |
22 | ENV JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/jre"
23 | ENV PATH $JAVA_HOME/bin:$PATH
24 |
25 | # Install allure commandline
26 | RUN curl -o allure-commandline-${ALLURE_VERSION}.tgz -Ls https://dl.bintray.com/qameta/maven/io/qameta/allure/allure-commandline/${ALLURE_VERSION}/allure-commandline-${ALLURE_VERSION}.tgz && \
27 | tar -zxvf allure-commandline-${ALLURE_VERSION}.tgz -C /opt/ && ln -s /opt/allure-${ALLURE_VERSION}/bin/allure /usr/bin/allure && allure --version
28 |
29 | RUN groupadd -g 1000 jenkins && \
30 | useradd -u 1000 -g 1000 -m -s /bin/bash jenkins
31 |
32 | USER jenkins
--------------------------------------------------------------------------------
/src/main/java/com/exception/ElementException.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.exception;
25 |
26 | import org.openqa.selenium.ElementNotInteractableException;
27 |
28 | /**
29 | * @author Dipjyoti Metia
30 | */
31 | public class ElementException extends ElementNotInteractableException {
32 | /**
33 | * Element exception
34 | *
35 | * @param message exception message
36 | */
37 | public ElementException(String message) {
38 | super(message);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/model/ApiResponse.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.model;
25 |
26 | import lombok.Getter;
27 | import lombok.ToString;
28 |
29 | /**
30 | * @author Dipjyoti Metia
31 | */
32 | @Getter
33 | @ToString
34 | public class ApiResponse {
35 | private final int statusCode;
36 | private final String responseBody;
37 |
38 | public ApiResponse(int statusCode, String responseBody) {
39 | this.statusCode = statusCode;
40 | this.responseBody = responseBody;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/logging/TestStatus.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.logging;
25 |
26 | import com.fasterxml.jackson.annotation.JsonProperty;
27 | import lombok.Setter;
28 |
29 | /**
30 | * @author Dipjyoti Metia
31 | */
32 | @Setter
33 | public class TestStatus {
34 |
35 | @JsonProperty("testClass")
36 | private String testClass;
37 |
38 | @JsonProperty("description")
39 | private String description;
40 |
41 | @JsonProperty("status")
42 | private String status;
43 |
44 | @JsonProperty("executionTime")
45 | private String executionTime;
46 | }
--------------------------------------------------------------------------------
/src/main/java/com/constants/Arg.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.constants;
25 |
26 | import io.appium.java_client.service.local.flags.ServerArgument;
27 |
28 | /**
29 | * @author Dipjyoti Metia
30 | */
31 | public enum Arg implements ServerArgument {
32 |
33 | TIMEOUT("--command-timeout"),
34 | LOCAL_TIME_ZONE("--local-timezone"),
35 | LOG_LEVEL("--log-level");
36 |
37 | private final String arg;
38 |
39 | Arg(String arg) {
40 | this.arg = arg;
41 | }
42 |
43 | @Override
44 | public String getArgument() {
45 | return arg;
46 | }
47 | }
--------------------------------------------------------------------------------
/src/main/java/com/reporting/Listeners/AnnotationTransformer.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.reporting.Listeners;
25 |
26 | import org.testng.IAnnotationTransformer;
27 | import org.testng.annotations.ITestAnnotation;
28 |
29 | import java.lang.reflect.Constructor;
30 | import java.lang.reflect.Method;
31 |
32 | /**
33 | * @author Dipjyoti Metia
34 | */
35 | public class AnnotationTransformer implements IAnnotationTransformer {
36 | @Override
37 | public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
38 | annotation.setRetryAnalyzer(Retry.class);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/docker-compose-infra.yml:
--------------------------------------------------------------------------------
1 | # Complete infra creation on the fly jenkins & allure report
2 | version: '3.8'
3 | services:
4 | allure:
5 | image: "frankescobar/allure-docker-service"
6 | environment:
7 | CHECK_RESULTS_EVERY_SECONDS: 1
8 | KEEP_HISTORY: 1
9 | ports:
10 | - "5050:5050"
11 | volumes:
12 | - "./build/allure-results:/app/allure-results"
13 | - "./build/allure-reports:/app/default-reports"
14 |
15 | allure-ui:
16 | image: "frankescobar/allure-docker-service-ui"
17 | environment:
18 | ALLURE_DOCKER_PUBLIC_API_URL: "http://localhost:5050"
19 | ALLURE_DOCKER_PUBLIC_API_URL_PREFIX: ""
20 | ports:
21 | - "5252:5252"
22 |
23 | #docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
24 | jenkins_master:
25 | image: jenkins/jenkins:lts
26 | container_name: jenkins
27 | hostname: jenkins
28 | privileged: true
29 | user: root
30 | restart: always
31 | ports:
32 | - "8080:8080"
33 | - "50000:50000"
34 | volumes:
35 | - ~/jenkins-data:/var/jenkins_home
36 | - /var/run/docker.sock:/var/run/docker.sock
37 | - /usr/local/bin/docker:/usr/local/bin/docker
38 | - "./script/plugins.txt:/usr/share/jenkins/ref/plugins.txt"
39 | # - /var/jenkins_home:/usr/share/jenkins/ref/plugins
40 | # - /var/jenkins_home/plugins.txt:/usr/share/jenkins/ref/plugins.txt
41 |
42 | jenkins_slave:
43 | image: jenkins/jnlp-slave
44 | container_name: jnlp_slave
45 | user: root
46 | command: -url http://192.168.8.113:8080
47 | restart: always
48 | volumes:
49 | - ~/jenkins-data:/var/jenkins_home
50 | - /var/run/docker.sock:/var/run/docker.sock
51 | - /usr/local/bin/docker:/usr/local/bin/docker
--------------------------------------------------------------------------------
/src/main/java/com/reporting/ExtentReports/ExtentManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.reporting.ExtentReports;
25 |
26 | import com.relevantcodes.extentreports.ExtentReports;
27 |
28 | /**
29 | * @author Dipjyoti Metia
30 | */
31 | public class ExtentManager {
32 | private static ExtentReports extent;
33 |
34 | public synchronized static ExtentReports getReporter() {
35 | if (extent == null) {
36 | //Set HTML reporting file location
37 | String workingDir = System.getProperty("user.dir");
38 | extent = new ExtentReports(workingDir + "\\Reports\\ExtentReportResults.html", true);
39 | }
40 | return extent;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/core/Access.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.core;
25 |
26 | import com.config.AppConfig;
27 | import com.typesafe.config.ConfigFactory;
28 |
29 | /**
30 | * @author Dipjyoti Metia
31 | */
32 | public interface Access {
33 |
34 | AppConfig appConfig = new AppConfig(ConfigFactory.load());
35 |
36 | int APPIUM_Port = appConfig.getAppiumPort();
37 | int PROXY_Port = appConfig.getProxyPort();
38 | String PIXEL = "emulator-5556";
39 | String NEXUS = "emulator-5554";
40 | String ANDROID_APP = "";
41 | String AWS_KEY = "";
42 | String AWS_SECRET = "";
43 | String AWS_BUCKET = "";
44 | String AWS_BUCKET_KEY = "";
45 | String APK_PATH = "";
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/.github/workflows/gradle.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v4
14 | - uses: actions/setup-java@v4
15 | with:
16 | distribution: temurin
17 | java-version: 17
18 | - name: Grant execute permission for gradlew
19 | run: chmod +x gradlew
20 | - name: Upload app and set app location
21 | id: app-upload
22 | run: |
23 | IPA_UPLOAD_RESPONSE=$(curl -u "$USERNAME:$ACCESS" -X POST https://api-cloud.browserstack.com/app-automate/upload -F "url=https://github.com/saucelabs/sample-app-mobile/releases/download/2.7.1/iOS.RealDevice.SauceLabs.Mobile.Sample.app.2.7.1.ipa")
24 | APK_UPLOAD_RESPONSE=$(curl -u "$USERNAME:$ACCESS" -X POST https://api-cloud.browserstack.com/app-automate/upload -F "url=https://github.com/saucelabs/sample-app-mobile/releases/download/2.7.1/Android.SauceLabs.Mobile.Sample.app.2.7.1.apk")
25 | echo "::set-output name=IPA_URL::$(echo $IPA_UPLOAD_RESPONSE | jq -r '.app_url')"
26 | echo "::set-output name=APK_URL::$(echo $APK_UPLOAD_RESPONSE | jq -r '.app_url')"
27 | env:
28 | USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
29 | ACCESS: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
30 | - name: Gradle Run Test
31 | run: ./gradlew task e2e
32 | env:
33 | BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
34 | BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
35 | IPA_URL: ${{steps.app-upload.outputs.IPA_URL}}
36 | APK_URL: ${{steps.app-upload.outputs.APK_URL}}
37 | - name: Generate Report
38 | run: ./gradlew task allureReport
39 | - uses: actions/upload-artifact@v4
40 | with:
41 | name: allure-report
42 | path: build/reports/allure-report
43 |
--------------------------------------------------------------------------------
/src/main/java/com/logging/ResultSender.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.logging;
25 |
26 | import com.fasterxml.jackson.databind.ObjectMapper;
27 | import kong.unirest.Unirest;
28 |
29 | /**
30 | * @author Dipjyoti Metia
31 | */
32 | public class ResultSender {
33 | private static final ObjectMapper OM = new ObjectMapper();
34 | private static final String CONTENT_TYPE = "Content-Type";
35 | private static final String CONTENT_TYPE_VALUE = "application/json";
36 | private static final String ELASTICSEARCH_URL = "http://localhost:9200/app/suite";
37 |
38 | public static void send(final TestStatus testStatus) {
39 | try {
40 | Unirest.post(ELASTICSEARCH_URL)
41 | .header(CONTENT_TYPE, CONTENT_TYPE_VALUE)
42 | .body(OM.writeValueAsString(testStatus)).asJson();
43 | System.out.println(OM.writeValueAsString(testStatus));
44 | } catch (Exception e) {
45 | e.printStackTrace();
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/reporting/ExtentReports/ExtentTestManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.reporting.ExtentReports;
25 |
26 | import com.relevantcodes.extentreports.ExtentReports;
27 | import com.relevantcodes.extentreports.ExtentTest;
28 |
29 | import java.util.HashMap;
30 | import java.util.Map;
31 |
32 | /**
33 | * @author Dipjyoti Metia
34 | */
35 | public class ExtentTestManager {
36 | static Map extentTestMap = new HashMap();
37 | static ExtentReports extent = ExtentManager.getReporter();
38 |
39 | public static synchronized ExtentTest getTest() {
40 | return (ExtentTest) extentTestMap.get((int) Thread.currentThread().getId());
41 | }
42 |
43 | public static synchronized void endTest() {
44 | extent.endTest((ExtentTest) extentTestMap.get((int) Thread.currentThread().getId()));
45 | }
46 |
47 | public static synchronized ExtentTest startTest(String testName, String desc) {
48 | ExtentTest test = extent.startTest(testName, desc);
49 | extentTestMap.put((int) Thread.currentThread().getId(), test);
50 | return test;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/test/java/com/TestDefinitionLayer/TC_Test_AndroidBooking.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.TestDefinitionLayer;
25 |
26 | import com.core.UserActions;
27 | import com.pages.HomePage;
28 | import com.reporting.ExtentReports.ExtentTestManager;
29 | import io.qameta.allure.Feature;
30 | import io.qameta.allure.Link;
31 | import io.qameta.allure.Severity;
32 | import io.qameta.allure.SeverityLevel;
33 | import org.testng.annotations.Test;
34 |
35 | public class TC_Test_AndroidBooking extends UserActions {
36 |
37 | @Link("Test")
38 | @Feature("test")
39 | @Severity(SeverityLevel.CRITICAL)
40 | @Test(description = "Demo Test")
41 | public void E2E_TestAndroid_Bookings() {
42 |
43 | String TCname = "TC_Test_AndroidBooking";
44 |
45 | HomePage homePage = new HomePage();
46 |
47 | ExtentTestManager.getTest().setDescription("Search for bookings");
48 |
49 | try {
50 | homePage.searchDestination()
51 | .selectDate()
52 | .search();
53 | // CreateImageDoc(TCname);
54 | } catch (Exception e) {
55 | catchBlock(e);
56 | } finally {
57 | ExtentTestManager.endTest();
58 | }
59 |
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/pages/LoginPage.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.pages;
25 |
26 | import com.core.Constants;
27 | import com.core.UserActions;
28 | import io.appium.java_client.pagefactory.*;
29 | import org.openqa.selenium.WebElement;
30 | import org.openqa.selenium.support.PageFactory;
31 |
32 | /**
33 | * @author Dipjyoti Metia
34 | */
35 | public class LoginPage extends UserActions implements Constants {
36 |
37 | @iOSXCUITFindBys(value = {@iOSXCUITBy(accessibility = "test-Username"), @iOSXCUITBy(xpath = "//XCUIElementTypeTextField[@name=\"test-Username\"]")})
38 | @AndroidFindBy(accessibility = "test-Username")
39 | private WebElement userName;
40 |
41 | @iOSXCUITFindBy(accessibility = "test-Password")
42 | @AndroidFindBy(accessibility = "test-Password")
43 | private WebElement password;
44 |
45 | @iOSXCUITFindBy(accessibility = "test-LOGIN")
46 | @AndroidFindBy(accessibility = "test-LOGIN")
47 | private WebElement loginButton;
48 |
49 | public LoginPage() {
50 | super();
51 | PageFactory.initElements(new AppiumFieldDecorator(driver), this);
52 | }
53 |
54 | public void login() {
55 | enter(userName, "standard_user");
56 | enter(password, "secret_sauce");
57 | click(loginButton);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/test/java/com/MockServiceLayer/TestDatabase.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.MockServiceLayer;
25 |
26 | import org.testng.annotations.Test;
27 |
28 | import java.sql.*;
29 |
30 | public class TestDatabase {
31 |
32 | @Test
33 | public void TestNewDB() {
34 | ResultSet rs = null;
35 | Statement statement = null;
36 | Connection conn = null;
37 | try {
38 | String url = "jdbc:sqlite:input/sqlite/testdata.db";
39 | conn = DriverManager.getConnection(url);
40 | if (conn != null) {
41 | statement = conn.createStatement();
42 | String query = "select * from data";
43 | rs = statement.executeQuery((query));
44 | while (rs.next()) {
45 | System.out.println(rs.getString(2));
46 | }
47 | }
48 | System.out.println("Connection to SQLite has been established.");
49 |
50 | } catch (SQLException e) {
51 | System.out.println(e.getMessage());
52 | } finally {
53 | try {
54 | if (conn != null) {
55 | conn.close();
56 | }
57 | } catch (SQLException ex) {
58 | System.out.println(ex.getMessage());
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/src/main/java/com/config/AppConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.config;
25 |
26 | import com.typesafe.config.Config;
27 | import lombok.Getter;
28 |
29 | /**
30 | * @author Dipjyoti Metia
31 | */
32 | @Getter
33 | public class AppConfig {
34 | private final String applicationName;
35 | private final int appiumPort;
36 | private final int proxyPort;
37 | private final String appiumVersion;
38 | private final boolean debug;
39 | private final boolean deviceLogs;
40 | private final boolean networkLogs;
41 | private final boolean acceptInsecureCerts;
42 | private final boolean appiumLogs;
43 | private final boolean video;
44 | private final String gpsLocation;
45 | private final boolean disableAnimations;
46 |
47 | public AppConfig(Config config) {
48 | this.applicationName = config.getString("application.name");
49 | this.appiumPort = config.getInt("appium.appiumport");
50 | this.proxyPort = config.getInt("appium.proxyport");
51 | this.appiumVersion = config.getString("browserStack.appium_version");
52 | this.debug = config.getBoolean("browserStack.debug");
53 | this.deviceLogs = config.getBoolean("browserStack.devicelogs");
54 | this.networkLogs = config.getBoolean("browserStack.networkLogs");
55 | this.acceptInsecureCerts = config.getBoolean("browserStack.acceptInsecureCerts");
56 | this.appiumLogs = config.getBoolean("browserStack.appiumLogs");
57 | this.video = config.getBoolean("browserStack.video");
58 | this.gpsLocation = config.getString("browserStack.gpsLocation");
59 | this.disableAnimations = config.getBoolean("browserStack.disableAnimations");
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/test/java/com/ServiceLayer/API_Test.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.ServiceLayer;
25 |
26 | import com.core.ApiActions;
27 | import com.reporting.ExtentReports.ExtentTestManager;
28 | import io.qameta.allure.Feature;
29 | import io.restassured.RestAssured;
30 | import io.restassured.response.Response;
31 | import org.json.simple.JSONObject;
32 | import org.testng.Assert;
33 | import org.testng.annotations.Test;
34 |
35 | public class API_Test extends ApiActions {
36 |
37 | @Feature("")
38 | @Test(description = "")
39 | @SuppressWarnings("unchecked")
40 | public void ServiceDemo() {
41 | ExtentTestManager.getTest().setDescription("Demo Service");
42 |
43 | try {
44 | String DateTo = "2018-10-30T13:59:59Z";
45 | String DateFrom = "2018-03-31T13:00:00Z";
46 |
47 | RestAssured.baseURI = "Property.baseURI.getValue()";
48 |
49 | JSONObject params = new JSONObject();
50 | params.put("DateTo", DateTo);
51 | params.put("DateFrom", DateFrom);
52 |
53 | Response response = httpPost(params, "/Demo/Service");
54 | Assert.assertEquals(getStatusCode(response) /*actual value*/, 200 /*expected value*/, "Correct status code returned");
55 | // log.info("Response Body is => " + getBody(response));
56 | T AcId = jsonPathEvaluator(response, "Results.ID");
57 | T Demo = jsonPathEvaluator(response, "Results.Demo");
58 | log("AcId: " + AcId);
59 | log("Demo: " + Demo);
60 | } catch (Exception e) {
61 | e.printStackTrace();
62 | } finally {
63 | ExtentTestManager.endTest();
64 | }
65 |
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ## Mobile Test Framework
2 |
3 | ### Architecture
4 | 
5 | ### Supported Platforms
6 |
7 | Appium supports app automation across a variety of platforms, like iOS,Android, from any platform. Each
8 | platform is supported by one or more "drivers", which know how to automate that particular platform. Choose a driver
9 | below for specific information about how that driver works and how to set it up:
10 |
11 | * Android
12 | * The [UiAutomator2 Driver](https://appium.io/docs/en/drivers/android-uiautomator2/)
13 | * IOS
14 | * The [XCUITest](https://appium.io/docs/en/drivers/ios-xcuitest/)
15 |
16 | ### Why [Appium](https://appium.io/docs/en/about-appium/intro/)?
17 |
18 | * Appium is an Open source automation tool used for cross platform testing like native, hybrid and web applications on
19 | both the platforms IOS and Android. Its capability for testing all kinds of tools under one platform, makes it a
20 | multipurpose and convenient testing tool.Appium is called as a cross platform testing tool because it uses JSON wire
21 | protocol internally to interact with native apps of IOS and Android using Selenium Webdriver.
22 |
23 | ### Setup & Tools
24 |
25 | * Download and install [Nodejs](https://nodejs.org/en/download/)
26 | ``
27 | npm install -g appium
28 | ``
29 | ``
30 | npm install -g appium-doctor
31 | ``
32 | verify all appium dependencies
33 | * [Download Appium Desktop](https://github.com/appium/appium-desktop/releases) download the latest release
34 | * [Install InteliJ Community Edition](https://www.jetbrains.com/idea/download/)
35 | * [Java JDK_11](https://adoptopenjdk.net/) install jdk_11 version
36 | * [Gradle](https://gradle.org/next-steps/?version=6.7.1&format=bin)
37 | * [Allure](https://github.com/allure-framework/allure2/archive/2.14.0.zip)
38 | * Set the below environment variables
39 |
40 | ```shell
41 | * JAVA_HOME: Pointing to the Java SDK folder\bin
42 | * GRADLE_HOME: Pointing to Gradle directory\bin.
43 | * ALLURE_HOME: Pointing to allure directory\bin.
44 | * APPIUM_HOME: Pointing appium main.js from global location.
45 | * NODE_HOME: Pointing nodejs installation.
46 | ```
47 |
48 | * For more details navigate to the above [Wiki Page](https://github.com/dipjyotimetia/MobileTestFramework/wiki)
49 |
50 | ### Connect - Local Devices:
51 |
52 | Connect an Android and an iOS Device using a USB cable to your PC
53 |
54 | - Follow documentation for device connection
55 |
56 | ### Getting Started
57 |
58 | ```shell
59 | $ git clone
60 | $ cd
61 | $ import project from intelij as a gradle project
62 | $ gradle clean
63 | $ gradle build
64 | $ gradle task E2E
65 | $ gradle allureReport
66 | $ gradle allureServe
67 | ```
68 |
69 | ### Write your first user journey
70 |
71 | Create new class and name as the TC00*_E2E_TEST-***
72 |
73 | - Provide jira link in @Link
74 | - Provide all the api components as @Feature
75 | - Provide test severity and description
76 | - Write test
77 | - Use CatchBlock in try/catch section
78 |
79 | #### Android Execution
80 | 
81 |
82 | #### iOS Execution
83 | 
84 |
85 |
--------------------------------------------------------------------------------
/src/main/java/com/reporting/AWS/UploadReport.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.reporting.AWS;
25 |
26 | import com.amazonaws.AmazonServiceException;
27 | import com.amazonaws.SdkClientException;
28 | import com.amazonaws.auth.AWSStaticCredentialsProvider;
29 | import com.amazonaws.auth.BasicAWSCredentials;
30 | import com.amazonaws.regions.Regions;
31 | import com.amazonaws.services.s3.AmazonS3;
32 | import com.amazonaws.services.s3.AmazonS3ClientBuilder;
33 | import com.amazonaws.services.s3.transfer.MultipleFileUpload;
34 | import com.amazonaws.services.s3.transfer.TransferManager;
35 | import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
36 | import io.qameta.allure.Link;
37 | import lombok.extern.slf4j.Slf4j;
38 | import org.testng.annotations.Test;
39 |
40 | import java.io.File;
41 |
42 | /**
43 | * @author Dipjyoti Metia
44 | */
45 | @Slf4j
46 | public class UploadReport {
47 |
48 | @Link("")
49 | @Test
50 | public void UploadToS3() throws Exception {
51 | String bucketName = "";
52 | String keyName = "Reports";
53 | String filePath = "build/reports/allure-report";
54 |
55 | try {
56 | BasicAWSCredentials awsCreds = new BasicAWSCredentials("/", "/");
57 | AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
58 | .withRegion(Regions.AP_SOUTHEAST_2)
59 | .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
60 | .build();
61 | s3Client.deleteObject(bucketName, keyName);
62 |
63 | TransferManager tm = TransferManagerBuilder.standard()
64 | .withS3Client(s3Client)
65 | .build();
66 |
67 | MultipleFileUpload upload = tm.uploadDirectory(bucketName, keyName, new File(filePath), true);
68 | log.info("Object upload started");
69 |
70 | upload.waitForCompletion();
71 | log.info("Object upload complete");
72 | } catch (AmazonServiceException e) {
73 | log.error("Amazon Service Exception", e);
74 | } catch (SdkClientException e) {
75 | log.error("SDK client Exception", e);
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/com/reporting/Listeners/Retry.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.reporting.Listeners;
25 |
26 | import com.core.DriverManager;
27 | import com.relevantcodes.extentreports.LogStatus;
28 | import com.reporting.ExtentReports.ExtentTestManager;
29 | import org.openqa.selenium.OutputType;
30 | import org.openqa.selenium.TakesScreenshot;
31 | import org.testng.IRetryAnalyzer;
32 | import org.testng.ITestResult;
33 |
34 | /**
35 | * @author Dipjyoti Metia
36 | */
37 | public class Retry extends DriverManager implements IRetryAnalyzer {
38 | private static final int maxTry = 0; //Run the failed test 2 times
39 | private int count = 0;
40 |
41 | /**
42 | * Retry Times
43 | *
44 | * @param iTestResult result
45 | * @return count
46 | */
47 | @Override
48 | public boolean retry(ITestResult iTestResult) {
49 | if (!iTestResult.isSuccess()) { //Check if test not succeed
50 | if (count < maxTry) { //Check if maxtry count is reached
51 | count++; //Increase the maxTry count by 1
52 | iTestResult.setStatus(ITestResult.FAILURE); //Mark test as failed
53 | extendReportsFailOperations(iTestResult); //ExtentReports fail operations
54 | return true; //Tells TestNG to re-run the test
55 | }
56 | } else {
57 | iTestResult.setStatus(ITestResult.SUCCESS); //If test passes, TestNG marks it as passed
58 | }
59 | return false;
60 | }
61 |
62 | /**
63 | * Report Fail Operation
64 | *
65 | * @param iTestResult testResult
66 | */
67 | public void extendReportsFailOperations(ITestResult iTestResult) {
68 | Object testClass = iTestResult.getInstance();
69 | this.driver = ((DriverManager) testClass).getDriver();
70 | String base64Screenshot = "data:image/png;base64," + ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);
71 | ExtentTestManager.getTest().log(LogStatus.FAIL, "Test Failed",
72 | ExtentTestManager.getTest().addBase64ScreenShot(base64Screenshot));
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/com/pages/HomePage.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.pages;
25 |
26 | import com.core.Constants;
27 | import com.core.UserActions;
28 | import io.appium.java_client.pagefactory.AndroidFindBy;
29 | import io.appium.java_client.pagefactory.AppiumFieldDecorator;
30 | import io.appium.java_client.pagefactory.iOSXCUITBy;
31 | import org.openqa.selenium.By;
32 | import org.openqa.selenium.WebElement;
33 | import org.openqa.selenium.support.PageFactory;
34 |
35 | /**
36 | * @author Dipjyoti Metia
37 | */
38 | public class HomePage extends UserActions implements Constants {
39 |
40 | @AndroidFindBy(id = "com.booking:id/search_details_text")
41 | @iOSXCUITBy(xpath = "")
42 | private WebElement destination;
43 |
44 | @AndroidFindBy(id = "com.booking:id/disam_search")
45 | private WebElement search;
46 |
47 | @AndroidFindBy(id = "com.booking:id/bt_accept")
48 | private WebElement acceptCookie;
49 |
50 | @AndroidFindBy(xpath = "//android.widget.ImageButton[@content-desc=\"Navigate up\"]")
51 | private WebElement closeButton;
52 |
53 | @AndroidFindBy(id = "com.booking:id/disambiguation_search_edittext")
54 | private WebElement searchEdit;
55 |
56 | @AndroidFindBy(id = "com.booking:id/button_positive")
57 | private WebElement gotIt;
58 |
59 | @AndroidFindBy(xpath = "(//android.widget.TextView[contains(@text,'Paris')])[1]")
60 | private WebElement select;
61 |
62 | @AndroidFindBy(id = "com.booking:id/calendar_confirm")
63 | private WebElement selectDate;
64 |
65 | @AndroidFindBy(id = "com.booking:id/search_search")
66 | private WebElement searchButton;
67 |
68 | public HomePage() {
69 | super();
70 | PageFactory.initElements(new AppiumFieldDecorator(driver), this);
71 | }
72 |
73 | public HomePage searchDestination() {
74 | if (driver.findElements(By.id("com.booking:id/bt_accept")).size() != 0) {
75 | click(acceptCookie);
76 | click(closeButton);
77 | }
78 | waitForElement(destination);
79 | click(destination);
80 | enter(searchEdit, "Paris");
81 | click(select);
82 | return this;
83 | }
84 |
85 | public HomePage selectDate() {
86 | click(selectDate);
87 | return this;
88 | }
89 |
90 | public void search() {
91 | click(searchButton);
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at dipjyotimetia@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/src/main/java/com/core/ServerManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.core;
25 |
26 | import lombok.extern.slf4j.Slf4j;
27 |
28 | import java.io.*;
29 | import java.nio.charset.StandardCharsets;
30 | import java.util.Scanner;
31 |
32 | /**
33 | * @author Dipjyoti Metia
34 | */
35 | @Slf4j
36 | public class ServerManager {
37 |
38 | private static String OS;
39 | private static String ANDROID_HOME;
40 |
41 | public static String getAndroidHome() throws Exception {
42 | if (ANDROID_HOME == null) {
43 | ANDROID_HOME = System.getenv("ANDROID_HOME");
44 | if (ANDROID_HOME == null)
45 | throw new Exception("Failed to find ANDROID_HOME, make sure the environment variable is set");
46 | }
47 | return ANDROID_HOME;
48 | }
49 |
50 | public static String getOS() {
51 | if (OS == null) OS = System.getenv("os.name");
52 | return OS;
53 | }
54 |
55 | public static boolean isWindows() {
56 | return getOS().startsWith("Windows");
57 | }
58 |
59 | public static boolean isMac() {
60 | return getOS().startsWith("Mac");
61 | }
62 |
63 | public static String runCommand(String command) throws Exception {
64 | String output = null;
65 | try {
66 | Scanner scanner = new Scanner(Runtime.getRuntime().exec(command).getInputStream()).useDelimiter("\\A");
67 | if (scanner.hasNext()) output = scanner.next();
68 | } catch (IOException e) {
69 | throw new Exception(e.getMessage());
70 | }
71 | return output;
72 | }
73 |
74 | public static String getWorkingDir() {
75 | return System.getProperty("user.dir");
76 | }
77 |
78 | public static String read(File file) {
79 | StringBuilder output = new StringBuilder();
80 | try {
81 | String line;
82 | FileReader fileReader = new FileReader(file);
83 | BufferedReader bufferedReader = new BufferedReader(fileReader);
84 | while ((line = bufferedReader.readLine()) != null) output.append(line).append("\n");
85 | bufferedReader.close();
86 | } catch (IOException error) {
87 | error.printStackTrace();
88 | }
89 | return output.toString();
90 | }
91 |
92 | public static void write(File file, String content) {
93 | try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {
94 | writer.write(content);
95 | writer.close();
96 | } catch (IOException error) {
97 | error.printStackTrace();
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Mobile Test Framework
2 | [](https://www.codacy.com/gh/dipjyotimetia/MobileTestFramework/dashboard?utm_source=github.com&utm_medium=referral&utm_content=dipjyotimetia/MobileTestFramework&utm_campaign=Badge_Grade)
3 | 
4 | [](https://saucelabs.com)
5 | ### Full-fledged Mobile, API and Database framework using appium and rest-assured
6 |
7 |
8 |
9 | ### Supported Platforms
10 |
11 | Appium supports app automation across a variety of platforms, like iOS,Android, from any platform. Each
12 | platform is supported by one or more "drivers", which know how to automate that particular platform. Choose a driver
13 | below for specific information about how that driver works and how to set it up:
14 |
15 | * Android
16 | * The [UiAutomator2 Driver](https://appium.io/docs/en/drivers/android-uiautomator2/)
17 | * IOS
18 | * The [XCUITest](https://appium.io/docs/en/drivers/ios-xcuitest/)
19 |
20 | ### Why [Appium](https://appium.io/docs/en/about-appium/intro/)?
21 |
22 | * Appium is an Open source automation tool used for cross platform testing like native, hybrid and web applications on
23 | both the platforms IOS and Android. Its capability for testing all kinds of tools under one platform, makes it a
24 | multipurpose and convenient testing tool.Appium is called as a cross platform testing tool because it uses JSON wire
25 | protocol internally to interact with native apps of IOS and Android using Selenium Webdriver.
26 |
27 | ### Setup & Tools
28 |
29 | * Download and install [Nodejs](https://nodejs.org/en/download/)
30 | ``
31 | npm install -g appium
32 | ``
33 | ``
34 | npm install -g appium-doctor
35 | ``
36 | verify all appium dependencies
37 | * [Download Appium Desktop](https://github.com/appium/appium-desktop/releases) download the latest release
38 | * [Install InteliJ Community Edition](https://www.jetbrains.com/idea/download/)
39 | * [Java JDK_11](https://adoptopenjdk.net/) install jdk_11 version
40 | * [Gradle](https://gradle.org/next-steps/?version=6.7.1&format=bin)
41 | * [Allure](https://github.com/allure-framework/allure2/archive/2.17.2.zip)
42 | * Set the below environment variables
43 |
44 | ```shell
45 | * JAVA_HOME: Pointing to the Java SDK folder\bin
46 | * GRADLE_HOME: Pointing to Gradle directory\bin.
47 | * ALLURE_HOME: Pointing to allure directory\bin.
48 | * APPIUM_HOME: Pointing appium main.js from global location.
49 | * NODE_HOME: Pointing nodejs installation.
50 | ```
51 |
52 | * For more details navigate to the above [Wiki Page](https://github.com/dipjyotimetia/MobileTestFramework/wiki)
53 |
54 | ### Connect - Local Devices:
55 |
56 | Connect an Android and an iOS Device using a USB cable to your PC
57 |
58 | - Follow documentation for device connection
59 |
60 | ### Getting Started
61 |
62 | ```shell
63 | $ git clone
64 | $ cd
65 | $ import project from intelij as a gradle project
66 | $ gradle clean
67 | $ gradle build
68 | $ gradle task E2E
69 | $ gradle allureReport
70 | $ gradle allureServe
71 | ```
72 |
73 | ### Write your first user journey
74 |
75 | Create new class and name as the TC00*_E2E_TEST-***
76 |
77 | - Provide jira link in @Link
78 | - Provide all the api components as @Feature
79 | - Provide test severity and description
80 | - Write test
81 | - Use CatchBlock in try/catch section
82 |
83 | #### Android Execution
84 | 
85 |
86 | #### iOS Execution
87 | 
88 |
89 |
--------------------------------------------------------------------------------
/src/main/java/com/utils/FileSystem.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.utils;
25 |
26 | import lombok.extern.slf4j.Slf4j;
27 | import org.apache.commons.io.FileUtils;
28 | import org.testng.Assert;
29 |
30 | import java.io.File;
31 | import java.io.IOException;
32 | import java.nio.charset.Charset;
33 | import java.nio.file.Files;
34 | import java.nio.file.Paths;
35 |
36 | /**
37 | * @author Dipjyoti Metia
38 | */
39 | @Slf4j
40 | public class FileSystem {
41 |
42 | /**
43 | * Delete file path.
44 | *
45 | * @param path Path to file for folder.
46 | * @throws IOException When fail to delete it.
47 | */
48 | public static void deletePath(String path) throws IOException {
49 | try {
50 | File file = new File(path);
51 | if (file.isDirectory()) {
52 | FileUtils.deleteDirectory(file);
53 | } else {
54 | file.delete();
55 | }
56 | log.info("Delete " + path);
57 | } catch (Exception e) {
58 | String errorMessage = "Failed to delete " + path;
59 | log.error(errorMessage);
60 | throw new IOException(errorMessage);
61 | }
62 | }
63 |
64 | /**
65 | * Read content of file.
66 | *
67 | * @param filePath File path as String.
68 | * @return Content of file as String.
69 | * @throws IOException When fail to read file.
70 | */
71 | public static String readFile(String filePath) throws IOException {
72 | byte[] encoded = Files.readAllBytes(Paths.get(filePath));
73 | return new String(encoded, Charset.defaultCharset());
74 | }
75 |
76 | /**
77 | * Check if path exists.
78 | *
79 | * @param path Path as String.
80 | * @return True if path exists. False if path does not exist.
81 | */
82 | public static boolean exist(String path) {
83 | File file = new File(path);
84 | return file.exists();
85 | }
86 |
87 | /**
88 | * Ensure path exists (create if does not exists).
89 | *
90 | * @param directory Path to directory.
91 | */
92 | public static void ensureFolderExists(String directory) {
93 | File file = new File(directory);
94 | if (!file.exists()) {
95 | boolean result = file.mkdirs();
96 | if (!result) {
97 | log.error("Failed to create folder: " + directory);
98 | }
99 | }
100 | }
101 |
102 | /**
103 | * Get size of file.
104 | *
105 | * @param path Path to file.
106 | * @return Size of file in kB.
107 | */
108 | public static long getFileSize(String path) {
109 | File file;
110 | long size = 0;
111 | file = new File(path);
112 | if (file.exists()) {
113 | size = file.length() / 1024; // In KBs
114 | } else {
115 | Assert.fail("File '" + file + "' does not exist!");
116 | }
117 | return size;
118 | }
119 | }
--------------------------------------------------------------------------------
/src/main/java/com/reporting/Listeners/TestListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.reporting.Listeners;
25 |
26 | import com.core.DriverManager;
27 | import com.logging.ResultSender;
28 | import com.logging.TestStatus;
29 | import com.relevantcodes.extentreports.LogStatus;
30 | import com.reporting.ExtentReports.ExtentManager;
31 | import com.reporting.ExtentReports.ExtentTestManager;
32 | import lombok.extern.slf4j.Slf4j;
33 | import org.openqa.selenium.OutputType;
34 | import org.openqa.selenium.TakesScreenshot;
35 | import org.testng.ITestContext;
36 | import org.testng.ITestListener;
37 | import org.testng.ITestResult;
38 |
39 | /**
40 | * @author Dipjyoti Metia
41 | */
42 | @Slf4j
43 | public class TestListener extends DriverManager implements ITestListener {
44 |
45 | private TestStatus testStatus;
46 |
47 | private static String getTestMethodName(ITestResult iTestResult) {
48 | return iTestResult.getMethod().getConstructorOrMethod().getName();
49 | }
50 |
51 | @Override
52 | public void onStart(ITestContext iTestContext) {
53 | log.info("I am in onStart method " + iTestContext.getName());
54 | iTestContext.setAttribute("WebDriver", this.driver);
55 | }
56 |
57 | @Override
58 | public void onFinish(ITestContext iTestContext) {
59 | log.info("I am in onFinish method " + iTestContext.getName());
60 | ExtentTestManager.endTest();
61 | ExtentManager.getReporter().flush();
62 | }
63 |
64 | @Override
65 | public void onTestStart(ITestResult iTestResult) {
66 | this.testStatus = new TestStatus();
67 | log.info("I am in onTestStart method " + getTestMethodName(iTestResult) + " start");
68 | ExtentTestManager.startTest(iTestResult.getMethod().getMethodName(), "");
69 | }
70 |
71 | @Override
72 | public void onTestSuccess(ITestResult iTestResult) {
73 | //this.sendStatus(iTestResult,"PASS");
74 | log.info("I am in onTestSuccess method " + getTestMethodName(iTestResult) + " succeed");
75 | ExtentTestManager.getTest().log(LogStatus.PASS, "Test passed");
76 | }
77 |
78 | @Override
79 | public void onTestFailure(ITestResult iTestResult) {
80 | //this.sendStatus(iTestResult,"FAIL");
81 | log.error("I am in onTestFailure method " + getTestMethodName(iTestResult) + " failed");
82 | Object testClass = iTestResult.getInstance();
83 | this.driver = ((DriverManager) testClass).getDriver();
84 | String base64Screenshot = "data:image/png;base64," + ((TakesScreenshot) driver).
85 | getScreenshotAs(OutputType.BASE64);
86 | ExtentTestManager.getTest().log(LogStatus.FAIL, "Test Failed",
87 | ExtentTestManager.getTest().addBase64ScreenShot(base64Screenshot));
88 | }
89 |
90 | @Override
91 | public void onTestSkipped(ITestResult iTestResult) {
92 | //this.sendStatus(iTestResult,"SKIP");
93 | log.warn("I am in onTestSkipped method " + getTestMethodName(iTestResult) + " skipped");
94 | ExtentTestManager.getTest().log(LogStatus.SKIP, "Test Skipped");
95 | }
96 |
97 | @Override
98 | public void onTestFailedButWithinSuccessPercentage(ITestResult iTestResult) {
99 | log.error("Test failed but it is in defined success ratio " + getTestMethodName(iTestResult));
100 | }
101 |
102 | private void sendStatus(ITestResult iTestResult, String status) {
103 | this.testStatus.setTestClass(iTestResult.getTestClass().getName());
104 | this.testStatus.setDescription(iTestResult.getMethod().getDescription());
105 | this.testStatus.setStatus(status);
106 | // this.testStatus.setExecutionDate(LocalDateTime.now().toString());
107 | ResultSender.send(this.testStatus);
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/test/java/com/MockServiceLayer/WireMock.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.MockServiceLayer;
25 |
26 | import com.github.tomakehurst.wiremock.http.Fault;
27 | import com.github.tomakehurst.wiremock.stubbing.Scenario;
28 |
29 | import static com.github.tomakehurst.wiremock.client.WireMock.*;
30 |
31 |
32 | public class WireMock {
33 |
34 | public WireMock() {
35 | }
36 |
37 | public void setupExampleStub() {
38 |
39 | stubFor(post(urlEqualTo("/pingpong"))
40 | .withRequestBody(matching("PING"))
41 | .willReturn(aResponse()
42 | .withStatus(200)
43 | .withHeader("Content-Type", "application/xml")
44 | .withBody("")));
45 | }
46 |
47 | public void setupStubURLMatching() {
48 |
49 | stubFor(get(urlEqualTo("/urlmatching"))
50 | .willReturn(aResponse()
51 | .withBody("URL matching")
52 | ));
53 | }
54 |
55 | public void setupStubRequestBodyMatching() {
56 |
57 | stubFor(post(urlEqualTo("/requestbodymatching"))
58 | .withRequestBody(containing("RequestBody"))
59 | .willReturn(aResponse()
60 | .withBody("Request body matching")
61 | ));
62 | }
63 |
64 | public void setupStubHeaderMatching() {
65 |
66 | stubFor(get(urlEqualTo("/headermatching"))
67 | .withHeader("Content-Type", containing("application/json"))
68 | .withHeader("DoesntExist", absent())
69 | .willReturn(aResponse()
70 | .withBody("Header matching")
71 | ));
72 | }
73 |
74 | public void setupStubAuthorizationMatching() {
75 |
76 | stubFor(get(urlEqualTo("/authorizationmatching"))
77 | .withBasicAuth("username", "password")
78 | .willReturn(aResponse()
79 | .withBody("Authorization matching")
80 | ));
81 | }
82 |
83 | public void setupStubReturningErrorCode() {
84 |
85 | stubFor(get(urlEqualTo("/errorcode"))
86 | .willReturn(aResponse()
87 | .withStatus(500)
88 | ));
89 | }
90 |
91 | public void setupStubFixedDelay() {
92 |
93 | stubFor(get(urlEqualTo("/fixeddelay"))
94 | .willReturn(aResponse()
95 | .withFixedDelay(2000)
96 | ));
97 | }
98 |
99 | public void setupStubBadResponse() {
100 |
101 | stubFor(get(urlEqualTo("/badresponse"))
102 | .willReturn(aResponse()
103 | .withFault(Fault.MALFORMED_RESPONSE_CHUNK)
104 | ));
105 | }
106 |
107 | public void setupStubStateful() {
108 |
109 | stubFor(get(urlEqualTo("/order")).inScenario("Order processing")
110 | .whenScenarioStateIs(Scenario.STARTED)
111 | .willReturn(aResponse()
112 | .withBody("Your shopping cart is empty")
113 | ));
114 |
115 | stubFor(post(urlEqualTo("/order")).inScenario("Order processing")
116 | .whenScenarioStateIs(Scenario.STARTED)
117 | .withRequestBody(equalTo("Ordering 1 item"))
118 | .willReturn(aResponse()
119 | .withBody("Item placed in shopping cart")
120 | )
121 | .willSetStateTo("ORDER_PLACED"));
122 |
123 | stubFor(get(urlEqualTo("/order")).inScenario("Order processing")
124 | .whenScenarioStateIs("ORDER_PLACED")
125 | .willReturn(aResponse()
126 | .withBody("There is 1 item in your shopping cart")
127 | ));
128 | }
129 |
130 | }
131 |
--------------------------------------------------------------------------------
/src/test/java/com/MockServiceLayer/TC001_MockService.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.MockServiceLayer;
25 |
26 | import com.github.tomakehurst.wiremock.WireMockServer;
27 | import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
28 | import io.restassured.RestAssured;
29 | import org.hamcrest.Matchers;
30 | import org.testng.annotations.Test;
31 |
32 | import java.util.concurrent.TimeUnit;
33 |
34 | public class TC001_MockService {
35 | private final WireMock wme = new WireMock();
36 |
37 | private final WireMockServer server = new WireMockServer(WireMockConfiguration.wireMockConfig().port(9876));
38 |
39 | @Test
40 | public void testPingPongPositive() {
41 |
42 | server.start();
43 |
44 | wme.setupExampleStub();
45 |
46 | RestAssured.given().
47 | body("PING").
48 | when().
49 | post("http://localhost:9876/pingpong").
50 | then().
51 | log().
52 | body().
53 | and().
54 | assertThat().
55 | statusCode(200).
56 | and().
57 | body("output", Matchers.equalTo("PONG"));
58 | }
59 |
60 | @Test
61 | public void testURLMatching() {
62 |
63 | wme.setupStubURLMatching();
64 |
65 | RestAssured.given().
66 | when().
67 | get("http://localhost:9876/urlmatching").
68 | then().
69 | assertThat().
70 | body(Matchers.equalTo("URL matching"));
71 | }
72 |
73 | @Test
74 | public void testRequestBodyMatching() {
75 |
76 | wme.setupStubRequestBodyMatching();
77 |
78 | RestAssured.given().
79 | body("TestRequestBodyMatching").
80 | when().
81 | post("http://localhost:9876/requestbodymatching").
82 | then().
83 | assertThat().
84 | body(Matchers.equalTo("Request body matching"));
85 | }
86 |
87 | @Test
88 | public void testHeaderMatching() {
89 |
90 | wme.setupStubHeaderMatching();
91 |
92 | RestAssured.given().
93 | contentType("application/json").
94 | when().
95 | get("http://localhost:9876/headermatching").
96 | then().
97 | assertThat().
98 | body(Matchers.equalTo("Header matching"));
99 | }
100 |
101 | @Test
102 | public void testAuthorizationMatching() {
103 |
104 | wme.setupStubAuthorizationMatching();
105 |
106 | RestAssured.given().
107 | auth().
108 | preemptive().
109 | basic("username", "password").
110 | when().
111 | get("http://localhost:9876/authorizationmatching").
112 | then().
113 | assertThat().
114 | body(Matchers.equalTo("Authorization matching"));
115 | }
116 |
117 | @Test
118 | public void testErrorCode() {
119 |
120 | wme.setupStubReturningErrorCode();
121 |
122 | RestAssured.given().
123 | when().
124 | get("http://localhost:9876/errorcode").
125 | then().
126 | assertThat().
127 | statusCode(500);
128 | }
129 |
130 | @Test
131 | public void testFixedDelay() {
132 |
133 | wme.setupStubFixedDelay();
134 |
135 | RestAssured.given().
136 | when().
137 | get("http://localhost:9876/fixeddelay").
138 | then().
139 | assertThat().
140 | time(Matchers.greaterThan(2000L), TimeUnit.MILLISECONDS);
141 |
142 | }
143 |
144 | @Test
145 | public void testStatefulStub() {
146 |
147 | wme.setupStubStateful();
148 |
149 | RestAssured.given().
150 | when().
151 | get("http://localhost:9876/order").
152 | then().
153 | assertThat().
154 | body(Matchers.equalTo("Your shopping cart is empty"));
155 |
156 | RestAssured.given().
157 | body("Ordering 1 item").
158 | when().
159 | post("http://localhost:9876/order").
160 | then().
161 | assertThat().
162 | body(Matchers.equalTo("Item placed in shopping cart"));
163 |
164 | RestAssured.given().
165 | when().
166 | get("http://localhost:9876/order").
167 | then().
168 | assertThat().
169 | body(Matchers.equalTo("There is 1 item in your shopping cart"));
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn ( ) {
37 | echo "$*"
38 | }
39 |
40 | die ( ) {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save ( ) {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/src/main/java/com/core/DataActions.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.core;
25 |
26 | import lombok.extern.slf4j.Slf4j;
27 |
28 | import java.sql.DriverManager;
29 | import java.sql.*;
30 |
31 | /**
32 | * @author Dipjyoti Metia
33 | */
34 | @Slf4j
35 | public class DataActions extends ApiActions {
36 |
37 | private static final String JDBC_URL = "jdbc:sqlserver://databaseserver;databaseName=Database;integratedSecurity=true";
38 |
39 | /**
40 | * Get DB connection
41 | */
42 | private void getDbConnection() {
43 | ResultSet rs = null;
44 | Connection connObj = null;
45 | Statement statement = null;
46 | try {
47 | Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
48 | connObj = DriverManager.getConnection(JDBC_URL);
49 | if (connObj != null) {
50 | statement = connObj.createStatement();
51 | String queryString = "select TOP 10 * from ;";
52 | rs = statement.executeQuery(queryString);
53 | while (rs.next()) {
54 | log.info(rs.getString(2));
55 | }
56 | }
57 | } catch (Exception sqlException) {
58 | log.error(sqlException.getMessage());
59 | } finally {
60 | finallyBlock(rs, connObj, statement);
61 | }
62 | }
63 |
64 | /**
65 | * Execute query
66 | *
67 | * @param query query
68 | * @return result
69 | */
70 | private String ExecuteQuery(String query) {
71 | String resultValue = "";
72 | String columnName = "";
73 | try {
74 | Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
75 | } catch (ClassNotFoundException e) {
76 | log.error(e.getMessage());
77 | }
78 | try (Connection connection = java.sql.DriverManager.getConnection(JDBC_URL)) {
79 | try (Statement stmt = connection.createStatement()) {
80 | try (ResultSet rs = stmt.executeQuery(query)) {
81 | while (rs.next()) {
82 | ResultSetMetaData rsmd = rs.getMetaData();
83 | int columnCount = rsmd.getColumnCount();
84 | for (int i = 1; i <= columnCount; i++) {
85 | try {
86 | rs.getString(i);
87 | } catch (NullPointerException e) {
88 | resultValue = "NULL";
89 | log.info("column name:" + columnName + "|" + "Column value:" + resultValue);
90 | continue;
91 | }
92 | columnName = rsmd.getColumnName(i);
93 | resultValue = rs.getString(i);
94 | log.info("column name:" + columnName + "|" + "Column value:" + resultValue);
95 | }
96 | }
97 | }
98 | connection.close();
99 | } catch (SQLException sq) {
100 | log.error(sq.getMessage());
101 | }
102 | } catch (SQLException sq) {
103 | log.error(sq.getMessage());
104 | }
105 | return resultValue;
106 | }
107 |
108 | private void displayRow(String title, ResultSet rs) {
109 | try {
110 | while (rs.next()) {
111 | log.info(rs.getString(title));
112 | }
113 | } catch (Exception e) {
114 | log.error(e.getMessage());
115 | }
116 | }
117 |
118 | private void finallyBlock(ResultSet rs, Connection connObj, Statement stmt) {
119 | if (rs != null) try {
120 | rs.close();
121 | } catch (Exception e) {
122 | log.error(e.getMessage());
123 | }
124 | if (connObj != null) try {
125 | connObj.close();
126 | } catch (Exception e) {
127 | log.error(e.getMessage());
128 | }
129 | if (stmt != null) try {
130 | stmt.close();
131 | } catch (Exception e) {
132 | log.error(e.getMessage());
133 | }
134 | }
135 |
136 | /**
137 | * Query executer
138 | *
139 | * @param query query
140 | * @return resultset
141 | */
142 | private ResultSet query(String query) {
143 | Connection connObj = null;
144 | try {
145 | Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
146 | connObj = DriverManager.getConnection(JDBC_URL);
147 | if (connObj != null) {
148 | Statement statement = connObj.createStatement();
149 | ResultSet rs = statement.executeQuery(query);
150 | return rs;
151 | }
152 | } catch (Exception sqlException) {
153 | log.error(sqlException.getMessage());
154 | }
155 | return null;
156 | }
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/src/main/java/com/core/ApiActions.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.core;
25 |
26 | import com.github.javafaker.Faker;
27 | import io.qameta.allure.Step;
28 | import io.restassured.RestAssured;
29 | import io.restassured.http.ContentType;
30 | import io.restassured.http.Method;
31 | import io.restassured.module.jsv.JsonSchemaValidator;
32 | import io.restassured.response.Response;
33 | import io.restassured.response.ResponseBody;
34 | import io.restassured.response.ValidatableResponse;
35 | import io.restassured.specification.RequestSpecification;
36 | import lombok.extern.slf4j.Slf4j;
37 | import org.apache.http.HttpResponse;
38 | import org.apache.http.auth.AuthScope;
39 | import org.apache.http.auth.NTCredentials;
40 | import org.apache.http.client.CredentialsProvider;
41 | import org.apache.http.client.methods.HttpGet;
42 | import org.apache.http.impl.client.BasicCredentialsProvider;
43 | import org.apache.http.impl.client.CloseableHttpClient;
44 | import org.apache.http.impl.client.HttpClientBuilder;
45 | import org.json.simple.JSONObject;
46 |
47 | import java.io.BufferedReader;
48 | import java.io.InputStreamReader;
49 | import java.text.DateFormat;
50 | import java.text.SimpleDateFormat;
51 | import java.util.Date;
52 |
53 | /**
54 | * @author Dipjyoti Metia
55 | */
56 | @Slf4j
57 | public class ApiActions {
58 |
59 | protected static final Faker faker = new Faker();
60 |
61 | private final static String workstation = System.getenv("COMPUTERNAME");
62 | private final static String domain = System.getenv("USERDOMAIN");
63 | private final static String baseURI = "";
64 | private final static String userName = "";
65 | private final static String userPass = "";
66 | private final static String tokenURI = "";
67 | private final static String clientUser = "";
68 | private final static String clientPass = "";
69 |
70 | @SuppressWarnings("unchecked")
71 | private String authLogin() {
72 | RestAssured.baseURI = baseURI;
73 | RequestSpecification httpRequest = RestAssured
74 | .given()
75 | .contentType(ContentType.JSON);
76 |
77 | JSONObject requestParams = new JSONObject();
78 | requestParams.put("Identifier", userName);
79 | requestParams.put("Password", userPass);
80 |
81 | Response response = httpRequest.body(requestParams.toJSONString()).
82 | request(Method.POST, "/Test");
83 |
84 | return getHeaders(response, "auth");
85 | }
86 |
87 | /**
88 | * Authentication token generate
89 | *
90 | * @return auth token
91 | */
92 | protected String authToken() {
93 | String token = "";
94 | CredentialsProvider credProvider = new BasicCredentialsProvider();
95 | credProvider.setCredentials(AuthScope.ANY,
96 | new NTCredentials(clientUser, clientPass, workstation, domain));
97 | try (CloseableHttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(credProvider).build()) {
98 | HttpGet request = new HttpGet(tokenURI);
99 | HttpResponse response = client.execute(request);
100 | BufferedReader bufReader = new BufferedReader(new InputStreamReader(
101 | response.getEntity().getContent()));
102 | StringBuilder builder = new StringBuilder();
103 | String line;
104 | while ((line = bufReader.readLine()) != null) {
105 | builder.append(line);
106 | builder.append(System.lineSeparator());
107 | }
108 | String[] res = builder.toString().trim().split(",");
109 | token = res[1].substring(9, res[1].length() - 1);
110 | } catch (Exception e) {
111 | log.error(e.getMessage());
112 | }
113 | return token;
114 | }
115 |
116 | /**
117 | * http request with parameter
118 | *
119 | * @param params jsonObject
120 | * @return returns httpRequest
121 | */
122 | private RequestSpecification httpRequest(JSONObject params) {
123 | return RestAssured
124 | .given()
125 | .with()
126 | .header("auth", authLogin())
127 | .contentType(ContentType.JSON)
128 | .with()
129 | .body(params.toJSONString());
130 | }
131 |
132 | /**
133 | * http request with parameter and auth token
134 | *
135 | * @param params jsonObject
136 | * @param token token
137 | * @return httpRequest
138 | */
139 | private RequestSpecification httpRequestLogin(JSONObject params, String token) {
140 | return RestAssured
141 | .given()
142 | .with()
143 | .header("token", token)
144 | .contentType(ContentType.JSON)
145 | .with()
146 | .body(params.toJSONString());
147 | }
148 |
149 | /**
150 | * http request without parameter
151 | *
152 | * @return returns httpRequest
153 | */
154 | private RequestSpecification httpRequest() {
155 | return RestAssured
156 | .given()
157 | .with()
158 | .header("auth", authLogin());
159 | }
160 |
161 | /**
162 | * http request with token
163 | *
164 | * @param token token
165 | * @return http request
166 | */
167 | private RequestSpecification httpLogin(String token) {
168 | return RestAssured
169 | .given()
170 | .with()
171 | .header("token", token);
172 | }
173 |
174 | /**
175 | * Set base uri
176 | *
177 | * @param baseURI baseUri
178 | */
179 | public void setBaseURI(String baseURI) {
180 | RestAssured.baseURI = baseURI;
181 | }
182 |
183 | /**
184 | * Set base path
185 | *
186 | * @param basePathTerm basepath
187 | */
188 | public void setBasePath(String basePathTerm) {
189 | RestAssured.basePath = basePathTerm;
190 | }
191 |
192 | /**
193 | * reset base uri
194 | */
195 | public void resetBaseURI() {
196 | RestAssured.baseURI = null;
197 | }
198 |
199 | /**
200 | * Reset base path
201 | */
202 | public void resetBasePath() {
203 | RestAssured.basePath = null;
204 | }
205 |
206 | /**
207 | * http post
208 | *
209 | * @param params params
210 | * @param path endpoint
211 | * @return response
212 | */
213 | protected Response httpPost(JSONObject params, String path) {
214 | return httpRequest(params).request(Method.POST, path);
215 | }
216 |
217 | /**
218 | * http post cancel
219 | *
220 | * @param params params
221 | * @param path endpoint
222 | * @param token token
223 | * @return response
224 | */
225 | protected Response httpPostCancelPendingBets(JSONObject params, String path, String token) {
226 | return httpRequestLogin(params, token).request(Method.POST, path);
227 | }
228 |
229 | /**
230 | * http get
231 | *
232 | * @param path endpoint
233 | * @return response
234 | */
235 | protected Response httpGet(String path) {
236 | return httpRequest().request(Method.GET, path);
237 | }
238 |
239 | /**
240 | * http get pending
241 | *
242 | * @param path endpoint
243 | * @param token token
244 | * @return response
245 | */
246 | protected Response httpGetMicroServices(String path, String token) {
247 | return httpLogin(token).request(Method.GET, path);
248 | }
249 |
250 | /**
251 | * http delete
252 | *
253 | * @param params params
254 | * @param path endpoint
255 | * @return response
256 | */
257 | protected Response httpDelete(JSONObject params, String path) {
258 | return httpRequest(params).request(Method.DELETE, path);
259 | }
260 |
261 | /**
262 | * http put
263 | *
264 | * @param params params
265 | * @param path endpoint
266 | * @return response
267 | */
268 | protected Response httpPut(JSONObject params, String path) {
269 | return httpRequest(params).request(Method.PUT, path);
270 | }
271 |
272 | /**
273 | * Get Status code
274 | *
275 | * @param response response
276 | * @return status code
277 | */
278 | protected int getStatusCode(Response response) {
279 | return response.getStatusCode();
280 | }
281 |
282 | /**
283 | * Get headers
284 | *
285 | * @param response response
286 | * @param header header
287 | * @return header value
288 | */
289 | private String getHeaders(Response response, String header) {
290 | return response.getHeaders().getValue(header);
291 | }
292 |
293 | /**
294 | * Response Body
295 | *
296 | * @param response response
297 | * @return responseBody
298 | */
299 | private ResponseBody responseBody(Response response) {
300 | return response.getBody();
301 | }
302 |
303 | /**
304 | * Json schema validation
305 | *
306 | * @param response response
307 | * @return responseBody
308 | */
309 | private ValidatableResponse schemaValidation(Response response, String path) {
310 | return response.then().body(JsonSchemaValidator.matchesJsonSchema(path));
311 | }
312 |
313 | /**
314 | * Get Body
315 | *
316 | * @param response response
317 | * @return preety Print
318 | */
319 | protected String getBody(Response response) {
320 | return responseBody(response).prettyPrint();
321 | }
322 |
323 | /**
324 | * JsonPath evaluator
325 | *
326 | * @param response response
327 | * @return jsonPath
328 | */
329 | protected T jsonPathEvaluator(Response response, String exp) {
330 | return response.jsonPath().get(exp);
331 | }
332 |
333 |
334 | protected String sysDateFormat() {
335 | try {
336 | DateFormat date = new SimpleDateFormat("dd-MM-yyyy");
337 | Date date1 = new Date();
338 | String abc1 = date.format(date1);
339 | return abc1;
340 | } catch (Exception e) {
341 | log.error(e.getMessage());
342 | }
343 | return null;
344 | }
345 |
346 | @Step("{0}")
347 | protected void log(String message) {
348 | log.info(message);
349 | }
350 |
351 | }
352 |
--------------------------------------------------------------------------------
/src/main/java/com/core/ADB.java:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2021 Dipjyoti Metia
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.core;
25 |
26 | import lombok.extern.slf4j.Slf4j;
27 |
28 | import java.io.File;
29 | import java.util.ArrayList;
30 | import java.util.Arrays;
31 | import java.util.List;
32 | import java.util.concurrent.TimeUnit;
33 |
34 | /**
35 | * @author Dipjyoti Metia
36 | */
37 | @Slf4j
38 | public class ADB {
39 |
40 | private final String SDK_PATH = System.getenv("ANDROID_HOME");
41 | private final String ADB_PATH = SDK_PATH + "platform-tools" + File.separator + "adb";
42 | private final String EMULATOR_PATH = SDK_PATH + File.separator + "emulator";
43 |
44 | private final String ID;
45 |
46 | public ADB(String deviceID) {
47 | ID = deviceID;
48 | }
49 |
50 | /**
51 | * launch android emulator
52 | *
53 | * @param avdName emulator name
54 | */
55 | public void launchEmulator(String avdName) {
56 | log.info("Starting emulator for" + avdName + "....");
57 | String[] aCommand = new String[]{EMULATOR_PATH, "-avd", avdName};
58 | try {
59 | Process process = new ProcessBuilder(aCommand).start();
60 | process.waitFor(180, TimeUnit.SECONDS);
61 | log.info("Emulator launched successfully");
62 | } catch (Exception e) {
63 | log.error(e.getMessage());
64 | }
65 | }
66 |
67 | /**
68 | * Close android emulator
69 | */
70 | public void closeEmulator() {
71 | log.info("Closing emulator");
72 | String[] aCommand = new String[]{EMULATOR_PATH, "emu", "kill"};
73 | try {
74 | Process process = new ProcessBuilder(aCommand).start();
75 | process.waitFor(1, TimeUnit.SECONDS);
76 | log.info("Emulator closed successfully");
77 | } catch (Exception e) {
78 | log.error(e.getMessage());
79 | }
80 | }
81 |
82 | /**
83 | * avd commands
84 | *
85 | * @param command command
86 | * @return output
87 | */
88 | public String command(String command) throws Exception {
89 | log.debug("Formatting ADB Command: " + command);
90 | if (command.startsWith("adb"))
91 | command = command.replace("adb ", ServerManager.getAndroidHome() + "/platform-tools/adb ");
92 | else throw new Exception("This method is designed to run ADB commands only!");
93 | log.debug("Formatted ADB Command: " + command);
94 | String output = ServerManager.runCommand(command);
95 | log.debug("Output of the ADB Command: " + output);
96 | if (output == null) return "";
97 | else return output.trim();
98 | }
99 |
100 | public void killServer() throws Exception {
101 | command("adb kill-server");
102 | }
103 |
104 | public void startServer() throws Exception {
105 | command("adb start-server");
106 | }
107 |
108 | /**
109 | * Get list of connected device
110 | *
111 | * @return devices
112 | */
113 | public List