├── .github
└── workflows
│ └── Semgrep.yml
├── .gitignore
├── .travis.yml
├── CODEOWNERS
├── README.md
├── android
├── examples
│ ├── run-first-test
│ │ ├── first.conf.js
│ │ └── specs
│ │ │ └── first_test.js
│ ├── run-local-test
│ │ ├── local.conf.js
│ │ └── specs
│ │ │ └── local_test.js
│ ├── run-multiple-test
│ │ ├── multiple.conf.js
│ │ └── specs
│ │ │ ├── multiple
│ │ │ ├── test_01.js
│ │ │ ├── test_02.js
│ │ │ └── test_03.js
│ │ │ └── multiple_test.js
│ └── run-parallel-test
│ │ ├── parallel.conf.js
│ │ └── specs
│ │ └── single_test.js
└── package.json
└── ios
├── examples
├── run-first-test
│ ├── first.conf.js
│ └── specs
│ │ └── first_test.js
├── run-local-test
│ ├── local.conf.js
│ └── specs
│ │ └── local_test.js
├── run-multiple-test
│ ├── multiple.conf.js
│ └── specs
│ │ ├── multiple
│ │ ├── test_01.js
│ │ ├── test_02.js
│ │ └── test_03.js
│ │ └── multiple_test.js
└── run-parallel-test
│ ├── parallel.conf.js
│ └── specs
│ └── single_test.js
└── package.json
/.github/workflows/Semgrep.yml:
--------------------------------------------------------------------------------
1 | # Name of this GitHub Actions workflow.
2 | name: Semgrep
3 |
4 | on:
5 | # Scan changed files in PRs (diff-aware scanning):
6 | # The branches below must be a subset of the branches above
7 | pull_request:
8 | branches: ["master", "main"]
9 | push:
10 | branches: ["master", "main"]
11 | schedule:
12 | - cron: '0 6 * * *'
13 |
14 |
15 | permissions:
16 | contents: read
17 |
18 | jobs:
19 | semgrep:
20 | # User definable name of this GitHub Actions job.
21 | permissions:
22 | contents: read # for actions/checkout to fetch code
23 | security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
24 | name: semgrep/ci
25 | # If you are self-hosting, change the following `runs-on` value:
26 | runs-on: ubuntu-latest
27 |
28 | container:
29 | # A Docker image with Semgrep installed. Do not change this.
30 | image: returntocorp/semgrep
31 |
32 | # Skip any PR created by dependabot to avoid permission issues:
33 | if: (github.actor != 'dependabot[bot]')
34 |
35 | steps:
36 | # Fetch project source with GitHub Actions Checkout.
37 | - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
38 | # Run the "semgrep ci" command on the command line of the docker image.
39 | - run: semgrep ci --sarif --output=semgrep.sarif
40 | env:
41 | # Add the rules that Semgrep uses by setting the SEMGREP_RULES environment variable.
42 | SEMGREP_RULES: p/default # more at semgrep.dev/explore
43 |
44 | - name: Upload SARIF file for GitHub Advanced Security Dashboard
45 | uses: github/codeql-action/upload-sarif@6c089f53dd51dc3fc7e599c3cb5356453a52ca9e # v2.20.0
46 | with:
47 | sarif_file: semgrep.sarif
48 | if: always()
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | local.log
3 | errorShots
4 | .DS_Store
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "4.3"
4 | - "4.0"
5 | - "0.12"
6 | - "0.10"
7 |
8 | before_install:
9 | - true && `base64 --decode <<< ZXhwb3J0IEJST1dTRVJTVEFDS19BQ0NFU1NfS0VZPUh5VmZydXJvb3dYb041eGhLZEs2Cg==`
10 |
11 |
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @browserstack/app-automate-public-repos
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # webdriverio-appium-app-browserstack
2 | This repository demonstrates how to run Appium tests using [WebdriverIO](http://webdriver.io/) on BrowserStack App Automate.
3 |
4 |
5 |
6 |

7 |
8 |
9 | Code samples to get started with Appium tests for your Native App using WebdriverIO.
10 |
11 | ## Setup
12 |
13 | ### Requirements
14 |
15 | * Node.js 8.11.2+
16 | - If you don't have Node installed, download it from [here](https://nodejs.org/en/)
17 |
18 | ### Install the dependencies
19 |
20 | For Android tests, run the following command in project's base directory :
21 |
22 | ```sh
23 | cd android
24 | npm i
25 | ```
26 |
27 | Or,
28 |
29 | For dependencies for iOS tests, run following command in project's base directory :
30 |
31 | ```sh
32 | cd ios
33 | npm i
34 | ```
35 |
36 | ## Getting Started
37 |
38 | Getting Started with Appium tests using WebdriverIO on BrowserStack couldn't be easier!
39 |
40 | ### Run first test:
41 | - Test script is available in `run-first-test` directory under [Android examples](./android) or [iOS examples](./ios)
42 | - Follow the steps outlined in the documentation - [Get Started with your first test on App Automate](https://www.browserstack.com/docs/app-automate/appium/getting-started/nodejs/webdriverio)
43 |
44 | ### Speed up test execution with parallel testing :
45 |
46 | - Test script is available in `run-parallel-test` directory under [Android examples](./android) or [iOS examples](./ios)
47 | - Follow the steps outlined in the documentation - [Get Started with parallel testing on App Automate](https://www.browserstack.com/docs/app-automate/appium/getting-started/nodejs/webdriverio/parallelize-tests)
48 |
49 | ### Use Local testing for apps that access resources hosted in development or testing environments :
50 |
51 | - Test script is available in `run-local-test` directory under [Android examples](./android) or [iOS examples](./ios)
52 | - Follow the steps outlined in the documentation - [Get Started with Local testing on App Automate](https://www.browserstack.com/docs/app-automate/appium/getting-started/nodejs/webdriverio/local-testing)
53 |
54 | **Note**: For other test frameworks supported by App-Automate refer our [Developer documentation](https://www.browserstack.com/docs/)
55 |
56 | ## Getting Help
57 |
58 | If you are running into any issues or have any queries, please check [Browserstack Support page](https://www.browserstack.com/support/app-automate) or [get in touch with us](https://www.browserstack.com/contact?ref=help).
59 |
60 |
--------------------------------------------------------------------------------
/android/examples/run-first-test/first.conf.js:
--------------------------------------------------------------------------------
1 | exports.config = {
2 | user: process.env.BROWSERSTACK_USERNAME || 'BROWSERSTACK_USERNAME',
3 | key: process.env.BROWSERSTACK_ACCESS_KEY || 'BROWSERSTACK_ACCESS_KEY',
4 |
5 | updateJob: false,
6 | specs: [
7 | './examples/run-first-test/specs/first_test.js'
8 | ],
9 | exclude: [],
10 |
11 | capabilities: [{
12 | project: "First Webdriverio Android Project",
13 | build: 'Webdriverio Android',
14 | name: 'first_test',
15 | device: 'Google Pixel 3',
16 | os_version: "9.0",
17 | app: process.env.BROWSERSTACK_APP_ID || 'bs://',
18 | 'browserstack.debug': true
19 | }],
20 |
21 | logLevel: 'info',
22 | coloredLogs: true,
23 | screenshotPath: './errorShots/',
24 | baseUrl: '',
25 | waitforTimeout: 10000,
26 | connectionRetryTimeout: 90000,
27 | connectionRetryCount: 3,
28 |
29 | framework: 'mocha',
30 | mochaOpts: {
31 | ui: 'bdd',
32 | timeout: 20000
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/android/examples/run-first-test/specs/first_test.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 |
3 | describe('Search Wikipedia Functionality', () => {
4 | it('can find search results', async () => {
5 | var searchSelector = await $(`~Search Wikipedia`);
6 | await searchSelector.waitForDisplayed({ timeout: 30000 });
7 | await searchSelector.click();
8 |
9 | var insertTextSelector = await $('android=new UiSelector().resourceId("org.wikipedia.alpha:id/search_src_text")');
10 | await insertTextSelector.waitForDisplayed({ timeout: 30000 });
11 |
12 | await insertTextSelector.addValue("Browsertack");
13 | await browser.pause(5000);
14 |
15 | var allProductsName = await $$(`android.widget.TextView`);
16 | assert(allProductsName.length > 0);
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/android/examples/run-local-test/local.conf.js:
--------------------------------------------------------------------------------
1 | var browserstack = require('browserstack-local');
2 |
3 | exports.config = {
4 | user: process.env.BROWSERSTACK_USERNAME || 'BROWSERSTACK_USERNAME',
5 | key: process.env.BROWSERSTACK_ACCESS_KEY || 'BROWSERSTACK_ACCESS_KEY',
6 |
7 | updateJob: false,
8 | specs: [
9 | './examples/run-local-test/specs/local_test.js'
10 | ],
11 | exclude: [],
12 |
13 | capabilities: [{
14 | project: "First Webdriverio Android Project",
15 | build: 'Webdriverio Android Local',
16 | name: 'local_test',
17 | device: 'Google Pixel 3',
18 | os_version: "9.0",
19 | app: process.env.BROWSERSTACK_APP_ID || 'bs://',
20 | 'browserstack.local': true,
21 | 'browserstack.debug': true
22 | }],
23 |
24 | logLevel: 'info',
25 | coloredLogs: true,
26 | screenshotPath: './errorShots/',
27 | baseUrl: '',
28 | waitforTimeout: 10000,
29 | connectionRetryTimeout: 90000,
30 | connectionRetryCount: 3,
31 |
32 | framework: 'mocha',
33 | mochaOpts: {
34 | ui: 'bdd',
35 | timeout: 20000
36 | },
37 |
38 | // Code to start browserstack local before start of test
39 | onPrepare: (config, capabilities) => {
40 | console.log("Connecting local");
41 | return new Promise( (resolve, reject) => {
42 | exports.bs_local = new browserstack.Local();
43 | exports.bs_local.start({'key': exports.config.key }, (error) => {
44 | if (error) return reject(error);
45 | console.log('Connected. Now testing...');
46 |
47 | resolve();
48 | });
49 | });
50 | },
51 |
52 | // Code to stop browserstack local after end of test
53 | onComplete: (capabilties, specs) => {
54 | console.log("Closing local tunnel");
55 | return new Promise( (resolve, reject) => {
56 | exports.bs_local.stop( (error) => {
57 | if (error) return reject(error);
58 | console.log("Stopped BrowserStackLocal");
59 |
60 | resolve();
61 | });
62 | });
63 | }
64 | };
65 |
--------------------------------------------------------------------------------
/android/examples/run-local-test/specs/local_test.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var assert = require('assert');
3 |
4 | describe('BrowserStack Local Testing', () => {
5 | it('can check tunnel working', async () => {
6 | var searchSelector = await $('android=new UiSelector().resourceId("com.example.android.basicnetworking:id/test_action")');
7 | await searchSelector.waitForDisplayed({ timeout: 30000 });
8 | await searchSelector.click();
9 |
10 | var insertTextSelector = await $(`android.widget.TextView`);
11 | await insertTextSelector.waitForDisplayed({ timeout: 30000 });
12 |
13 | var testElement = null;
14 |
15 | try {
16 | var textElement = await $('android=new UiSelector().textContains("active connection is")');
17 | await textElement.waitForDisplayed({ timeout: 30000 });
18 | testElement = textElement;
19 | }
20 | catch {
21 | var screenshotPath = path.resolve(__dirname, 'screenshot.png');
22 | await browser.saveScreenshot(screenshotPath);
23 | console.log('Screenshot stored at ' + screenshotPath);
24 | throw new Error('Cannot find the needed TextView element from app');
25 | }
26 |
27 | var matchedString = await testElement.getText();
28 | console.log(matchedString);
29 | assert(matchedString.indexOf('The active connection is wifi') !== -1);
30 | assert(matchedString.indexOf('Up and running') !== -1);
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/android/examples/run-multiple-test/multiple.conf.js:
--------------------------------------------------------------------------------
1 | exports.config = {
2 | user: process.env.BROWSERSTACK_USERNAME || 'BROWSERSTACK_USERNAME',
3 | key: process.env.BROWSERSTACK_ACCESS_KEY || 'BROWSERSTACK_ACCESS_KEY',
4 |
5 | updateJob: false,
6 | specs: [
7 | './examples/run-multiple-test/specs/multiple_test.js'
8 | ],
9 | exclude: [],
10 |
11 | capabilities: [{
12 | project: "First Webdriverio Android Project",
13 | build: 'Webdriverio Android Multiple',
14 | name: 'multiple_test',
15 | device: 'Google Pixel 3',
16 | os_version: "9.0",
17 | app: process.env.BROWSERSTACK_APP_ID || 'bs://',
18 | 'browserstack.debug': true
19 | }],
20 |
21 | logLevel: 'info',
22 | coloredLogs: true,
23 | screenshotPath: './errorShots/',
24 | baseUrl: '',
25 | waitforTimeout: 10000,
26 | connectionRetryTimeout: 90000,
27 | connectionRetryCount: 3,
28 |
29 | framework: 'mocha',
30 | mochaOpts: {
31 | ui: 'bdd',
32 | timeout: 30000
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/android/examples/run-multiple-test/specs/multiple/test_01.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 |
3 | describe('Search Wikipedia Functionality', () => {
4 | it('can find search results', async () => {
5 | var searchSelector = await $(`~Search Wikipedia`);
6 | await searchSelector.waitForDisplayed({ timeout: 30000 });
7 | await searchSelector.click();
8 |
9 | var insertTextSelector = await $('android=new UiSelector().resourceId("org.wikipedia.alpha:id/search_src_text")');
10 | await insertTextSelector.waitForDisplayed({ timeout: 30000 });
11 |
12 | await insertTextSelector.addValue("Browsertack01");
13 | await browser.pause(5000);
14 |
15 | var allProductsName = await $$(`android.widget.TextView`);
16 | assert(allProductsName.length > 0);
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/android/examples/run-multiple-test/specs/multiple/test_02.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 |
3 | describe('Search Wikipedia Functionality', () => {
4 | it('can find search results', async () => {
5 | var searchSelector = await $(`~Search Wikipedia`);
6 | await searchSelector.waitForDisplayed({ timeout: 30000 });
7 | await searchSelector.click();
8 |
9 | var insertTextSelector = await $('android=new UiSelector().resourceId("org.wikipedia.alpha:id/search_src_text")');
10 | await insertTextSelector.waitForDisplayed({ timeout: 30000 });
11 |
12 | await insertTextSelector.addValue("Browsertack02");
13 | await browser.pause(5000);
14 |
15 | var allProductsName = await $$(`android.widget.TextView`);
16 | assert(allProductsName.length > 0);
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/android/examples/run-multiple-test/specs/multiple/test_03.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 |
3 | describe('Search Wikipedia Functionality', () => {
4 | it('can find search results', async () => {
5 | var searchSelector = await $(`~Search Wikipedia`);
6 | await searchSelector.waitForDisplayed({ timeout: 30000 });
7 | await searchSelector.click();
8 |
9 | var insertTextSelector = await $('android=new UiSelector().resourceId("org.wikipedia.alpha:id/search_src_text")');
10 | await insertTextSelector.waitForDisplayed({ timeout: 30000 });
11 |
12 | await insertTextSelector.addValue("Browsertack03");
13 | await browser.pause(5000);
14 |
15 | var allProductsName = await $$(`android.widget.TextView`);
16 | assert(allProductsName.length > 0);
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/android/examples/run-multiple-test/specs/multiple_test.js:
--------------------------------------------------------------------------------
1 | var specs = [
2 | './multiple/test_01.js',
3 | './multiple/test_02.js',
4 | './multiple/test_03.js'
5 | ];
6 |
7 | for (var i = specs.length - 1; i >= 0; i--) {
8 | require(specs[i]);
9 | }
10 |
--------------------------------------------------------------------------------
/android/examples/run-parallel-test/parallel.conf.js:
--------------------------------------------------------------------------------
1 | exports.config = {
2 | user: process.env.BROWSERSTACK_USERNAME || 'BROWSERSTACK_USERNAME',
3 | key: process.env.BROWSERSTACK_ACCESS_KEY || 'BROWSERSTACK_ACCESS_KEY',
4 |
5 | updateJob: false,
6 | specs: [
7 | './examples/run-parallel-test/specs/single_test.js'
8 | ],
9 | exclude: [],
10 |
11 | maxInstances: 10,
12 | commonCapabilities: {
13 | project: "First Webdriverio Android Project",
14 | build: 'Webdriverio Android Parallel',
15 | name: 'parallel_test',
16 | app: process.env.BROWSERSTACK_APP_ID || 'bs://',
17 | 'browserstack.debug': true
18 | },
19 |
20 | capabilities: [{
21 | device: 'Google Pixel 3',
22 | os_version: "9.0"
23 | }, {
24 | device: 'Samsung Galaxy S10e',
25 | os_version: "9.0"
26 | }],
27 |
28 | logLevel: 'info',
29 | coloredLogs: true,
30 | screenshotPath: './errorShots/',
31 | baseUrl: '',
32 | waitforTimeout: 10000,
33 | connectionRetryTimeout: 90000,
34 | connectionRetryCount: 3,
35 |
36 | framework: 'mocha',
37 | mochaOpts: {
38 | ui: 'bdd',
39 | timeout: 20000
40 | }
41 | };
42 |
43 | // Code to support common capabilities
44 | exports.config.capabilities.forEach(function(caps){
45 | for(var i in exports.config.commonCapabilities) caps[i] = caps[i] || exports.config.commonCapabilities[i];
46 | });
47 |
--------------------------------------------------------------------------------
/android/examples/run-parallel-test/specs/single_test.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 |
3 | describe('Search Wikipedia Functionality', () => {
4 | it('can find search results', async () => {
5 | var searchSelector = await $(`~Search Wikipedia`);
6 | await searchSelector.waitForDisplayed({ timeout: 30000 });
7 | await searchSelector.click();
8 |
9 | var insertTextSelector = await $('android=new UiSelector().resourceId("org.wikipedia.alpha:id/search_src_text")');
10 | await insertTextSelector.waitForDisplayed({ timeout: 30000 });
11 |
12 | await insertTextSelector.addValue("Browsertack");
13 | await browser.pause(5000);
14 |
15 | var allProductsName = await $$(`android.widget.TextView`);
16 | assert(allProductsName.length > 0);
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/android/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webdriverio-appium-app-browserstack",
3 | "version": "0.1.0",
4 | "readme": "WendriverIO Integration with [BrowserStack](https://www.browserstack.com)",
5 | "description": "Selenium examples for WebdriverIO and BrowserStack App Automate",
6 | "scripts": {
7 | "test": "npm run first && npm run local && npm run parallel",
8 | "first": "./node_modules/.bin/wdio examples/run-first-test/first.conf.js",
9 | "parallel": "./node_modules/.bin/wdio examples/run-parallel-test/parallel.conf.js",
10 | "local": "./node_modules/.bin/wdio examples/run-local-test/local.conf.js",
11 | "multiple": "./node_modules/.bin/wdio examples/run-multiple-test/multiple.conf.js"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/browserstack/webdriverio-appium-app-browserstack.git"
16 | },
17 | "keywords": [
18 | "webdriverio",
19 | "browserstack",
20 | "appium",
21 | "tests"
22 | ],
23 | "bugs": {
24 | "url": "https://github.com/browserstack/webdriverio-appium-app-browserstack/issues"
25 | },
26 | "homepage": "https://github.com/browserstack/webdriverio-appium-app-browserstack#readme",
27 | "dependencies": {
28 | "@wdio/cli": "^5.20.1",
29 | "@wdio/local-runner": "^5.20.1",
30 | "@wdio/mocha-framework": "^5.18.7",
31 | "browserstack-local": "^1.4.5"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ios/examples/run-first-test/first.conf.js:
--------------------------------------------------------------------------------
1 | exports.config = {
2 | user: process.env.BROWSERSTACK_USERNAME || 'BROWSERSTACK_USERNAME',
3 | key: process.env.BROWSERSTACK_ACCESS_KEY || 'BROWSERSTACK_ACCESS_KEY',
4 |
5 | updateJob: false,
6 | specs: [
7 | './examples/run-first-test/specs/first_test.js'
8 | ],
9 | exclude: [],
10 |
11 | capabilities: [{
12 | project: "First Webdriverio iOS Project",
13 | build: 'Webdriverio iOS',
14 | name: 'single_test',
15 | device: 'iPhone 11 Pro',
16 | os_version: "13",
17 | app: process.env.BROWSERSTACK_APP_ID || 'bs://',
18 | 'browserstack.debug': true
19 | }],
20 |
21 | logLevel: 'info',
22 | coloredLogs: true,
23 | screenshotPath: './errorShots/',
24 | baseUrl: '',
25 | waitforTimeout: 10000,
26 | connectionRetryTimeout: 90000,
27 | connectionRetryCount: 3,
28 |
29 | framework: 'mocha',
30 | mochaOpts: {
31 | ui: 'bdd',
32 | timeout: 40000
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/ios/examples/run-first-test/specs/first_test.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 |
3 | describe('Text Verification', () => {
4 | it('should match displayed text with input text', async () => {
5 | var textButton = await $(`~Text Button`);
6 | await textButton.waitForDisplayed({ timeout: 30000 });
7 | await textButton.click();
8 |
9 | var textInput = await $(`~Text Input`);
10 | await textInput.waitForDisplayed({ timeout: 30000 });
11 | await textInput.click()
12 | await textInput.addValue("hello@browserstack.com"+"\n");
13 |
14 | var textOutput = await $(`~Text Output`);
15 | await textOutput.waitForDisplayed({ timeout: 30000 });
16 | var value = await textOutput.getText();
17 |
18 | if (value === "hello@browserstack.com")
19 | assert(true)
20 | else
21 | assert(false)
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/ios/examples/run-local-test/local.conf.js:
--------------------------------------------------------------------------------
1 | var browserstack = require('browserstack-local');
2 |
3 | exports.config = {
4 | user: process.env.BROWSERSTACK_USERNAME || 'BROWSERSTACK_USERNAME',
5 | key: process.env.BROWSERSTACK_ACCESS_KEY || 'BROWSERSTACK_ACCESS_KEY',
6 |
7 | updateJob: false,
8 | specs: [
9 | './examples/run-local-test/specs/local_test.js'
10 | ],
11 | exclude: [],
12 |
13 | capabilities: [{
14 | project: "First Webdriverio iOS Project",
15 | build: 'Webdriverio iOS Local',
16 | name: 'local_test',
17 | device: 'iPhone 11 Pro',
18 | os_version: "13",
19 | app: process.env.BROWSERSTACK_APP_ID || 'bs://',
20 | 'browserstack.local': true,
21 | 'browserstack.debug': true
22 | }],
23 |
24 | logLevel: 'info',
25 | coloredLogs: true,
26 | screenshotPath: './errorShots/',
27 | baseUrl: '',
28 | waitforTimeout: 10000,
29 | connectionRetryTimeout: 90000,
30 | connectionRetryCount: 3,
31 |
32 | framework: 'mocha',
33 | mochaOpts: {
34 | ui: 'bdd',
35 | timeout: 30000
36 | },
37 |
38 | // Code to start browserstack local before start of test
39 | onPrepare: (config, capabilities) => {
40 | console.log("Connecting local");
41 | return new Promise( (resolve, reject) => {
42 | exports.bs_local = new browserstack.Local();
43 | exports.bs_local.start({'key': exports.config.key }, (error) => {
44 | if (error) return reject(error);
45 | console.log('Connected. Now testing...');
46 |
47 | resolve();
48 | });
49 | });
50 | },
51 |
52 | // Code to stop browserstack local after end of test
53 | onComplete: (capabilties, specs) => {
54 | console.log("Closing local tunnel");
55 | return new Promise( (resolve, reject) => {
56 | exports.bs_local.stop( (error) => {
57 | if (error) return reject(error);
58 | console.log("Stopped BrowserStackLocal");
59 |
60 | resolve();
61 | });
62 | });
63 | }
64 | };
65 |
--------------------------------------------------------------------------------
/ios/examples/run-local-test/specs/local_test.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var assert = require('assert');
3 |
4 | describe('BrowserStack Local Testing', () => {
5 | it('can check tunnel working', async () => {
6 | var searchSelector = await $(`~Test BrowserStackLocal connection`);
7 | await searchSelector.waitForDisplayed({ timeout: 30000 });
8 | await searchSelector.click();
9 |
10 | var textElements = await $(`~ResultBrowserStackLocal`);
11 | await textElements.waitForDisplayed({ timeout: 30000 });
12 |
13 | var testElement = null;
14 |
15 | var textContent = await textElements.getText();
16 | if (textContent.indexOf('Up and running') !== -1) {
17 | testElement = textElements;
18 | }
19 |
20 | if (testElement === null) {
21 | var screenshotPath = path.resolve(__dirname, 'screenshot.png');
22 | await browser.saveScreenshot(screenshotPath);
23 | console.log('Screenshot stored at ' + screenshotPath);
24 | throw new Error('Cannot find the Up and running response');
25 | }
26 |
27 | var matchedString = await testElement.getText();
28 | assert(matchedString == 'Response is: Up and running');
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/ios/examples/run-multiple-test/multiple.conf.js:
--------------------------------------------------------------------------------
1 | exports.config = {
2 | user: process.env.BROWSERSTACK_USERNAME || 'BROWSERSTACK_USERNAME',
3 | key: process.env.BROWSERSTACK_ACCESS_KEY || 'BROWSERSTACK_ACCESS_KEY',
4 |
5 | updateJob: false,
6 | specs: [
7 | './examples/run-multiple-test/specs/multiple_test.js'
8 | ],
9 | exclude: [],
10 |
11 | capabilities: [{
12 | project: "First Webdriverio iOS Project",
13 | build: 'Webdriverio iOS Multiple',
14 | name: 'multiple_test',
15 | device: 'iPhone 11 Pro',
16 | os_version: "13",
17 | app: process.env.BROWSERSTACK_APP_ID || 'bs://',
18 | 'browserstack.debug': true
19 | }],
20 |
21 | logLevel: 'info',
22 | coloredLogs: true,
23 | screenshotPath: './errorShots/',
24 | baseUrl: '',
25 | waitforTimeout: 10000,
26 | connectionRetryTimeout: 90000,
27 | connectionRetryCount: 3,
28 |
29 | framework: 'mocha',
30 | mochaOpts: {
31 | ui: 'bdd',
32 | timeout: 30000
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/ios/examples/run-multiple-test/specs/multiple/test_01.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 |
3 | describe('Text Verification', () => {
4 | it('should match displayed text with input text', async () => {
5 | var textButton = await $(`~Text Button`);
6 | await textButton.waitForDisplayed({ timeout: 30000 });
7 | await textButton.click();
8 |
9 | var textInput = await $(`~Text Input`);
10 | await textInput.waitForDisplayed({ timeout: 30000 });
11 | await textInput.click()
12 | await textInput.addValue("hello01@browserstack.com"+"\n");
13 |
14 | var textOutput = await $(`~Text Output`);
15 | await textOutput.waitForDisplayed({ timeout: 30000 });
16 | var value = await textOutput.getText();
17 |
18 | if (value === "hello01@browserstack.com")
19 | assert(true)
20 | else
21 | assert(false)
22 |
23 | var back = await $('~UI Elements');
24 | await back.click();
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/ios/examples/run-multiple-test/specs/multiple/test_02.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 |
3 | describe('Text Verification', () => {
4 | it('should match displayed text with input text', async () => {
5 | var textButton = await $(`~Text Button`);
6 | await textButton.waitForDisplayed({ timeout: 30000 });
7 | await textButton.click();
8 |
9 | var textInput = await $(`~Text Input`);
10 | await textInput.waitForDisplayed({ timeout: 30000 });
11 | await textInput.click()
12 | await textInput.addValue("hello02@browserstack.com"+"\n");
13 |
14 | var textOutput = await $(`~Text Output`);
15 | await textOutput.waitForDisplayed({ timeout: 30000 });
16 | var value = await textOutput.getText();
17 |
18 | if (value === "hello02@browserstack.com")
19 | assert(true)
20 | else
21 | assert(false)
22 |
23 | var back = await $('~UI Elements');
24 | await back.click();
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/ios/examples/run-multiple-test/specs/multiple/test_03.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 |
3 | describe('Text Verification', () => {
4 | it('should match displayed text with input text', async () => {
5 | var textButton = await $(`~Text Button`);
6 | await textButton.waitForDisplayed({ timeout: 30000 });
7 | await textButton.click();
8 |
9 | var textInput = await $(`~Text Input`);
10 | await textInput.waitForDisplayed({ timeout: 30000 });
11 | await textInput.click()
12 | await textInput.addValue("hello03@browserstack.com"+"\n");
13 |
14 | var textOutput = await $(`~Text Output`);
15 | await textOutput.waitForDisplayed({ timeout: 30000 });
16 | var value = await textOutput.getText();
17 |
18 | if (value === "hello03@browserstack.com")
19 | assert(true)
20 | else
21 | assert(false)
22 |
23 | var back = await $('~UI Elements');
24 | await back.click();
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/ios/examples/run-multiple-test/specs/multiple_test.js:
--------------------------------------------------------------------------------
1 | var specs = [
2 | './multiple/test_01.js',
3 | './multiple/test_02.js',
4 | './multiple/test_03.js'
5 | ];
6 |
7 | for (var i = specs.length - 1; i >= 0; i--) {
8 | require(specs[i]);
9 | }
10 |
--------------------------------------------------------------------------------
/ios/examples/run-parallel-test/parallel.conf.js:
--------------------------------------------------------------------------------
1 | exports.config = {
2 | user: process.env.BROWSERSTACK_USERNAME || 'BROWSERSTACK_USERNAME',
3 | key: process.env.BROWSERSTACK_ACCESS_KEY || 'BROWSERSTACK_ACCESS_KEY',
4 |
5 | updateJob: false,
6 | specs: [
7 | './examples/run-parallel-test/specs/single_test.js'
8 | ],
9 | exclude: [],
10 |
11 | maxInstances: 10,
12 | commonCapabilities: {
13 | project: "First Webdriverio iOS Project",
14 | build: 'Webdriverio iOS Parallel',
15 | name: 'parallel_test',
16 | app: process.env.BROWSERSTACK_APP_ID || 'bs://',
17 | 'browserstack.debug': true
18 | },
19 |
20 | capabilities: [{
21 | device: "iPhone 11 Pro",
22 | os_version: "13"
23 | }, {
24 | device: "iPhone 11 Pro Max",
25 | os_version: "13"
26 | }],
27 |
28 | logLevel: 'info',
29 | coloredLogs: true,
30 | screenshotPath: './errorShots/',
31 | baseUrl: '',
32 | waitforTimeout: 10000,
33 | connectionRetryTimeout: 90000,
34 | connectionRetryCount: 3,
35 |
36 | framework: 'mocha',
37 | mochaOpts: {
38 | ui: 'bdd',
39 | timeout: 40000
40 | }
41 | };
42 |
43 | // Code to support common capabilities
44 | exports.config.capabilities.forEach(function(caps){
45 | for(var i in exports.config.commonCapabilities) caps[i] = caps[i] || exports.config.commonCapabilities[i];
46 | });
47 |
--------------------------------------------------------------------------------
/ios/examples/run-parallel-test/specs/single_test.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 |
3 | describe('Text Verification', () => {
4 | it('should match displayed text with input text', async () => {
5 | var textButton = await $(`~Text Button`);
6 | await textButton.waitForDisplayed({ timeout: 30000 });
7 | await textButton.click();
8 |
9 | var textInput = await $(`~Text Input`);
10 | await textInput.waitForDisplayed({ timeout: 30000 });
11 | await textInput.click()
12 | await textInput.addValue("hello@browserstack.com"+"\n");
13 |
14 | var textOutput = await $(`~Text Output`);
15 | await textOutput.waitForDisplayed({ timeout: 30000 });
16 | var value = await textOutput.getText();
17 |
18 | if (value === "hello@browserstack.com")
19 | assert(true)
20 | else
21 | assert(false)
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/ios/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webdriverio-appium-app-browserstack",
3 | "version": "0.1.0",
4 | "readme": "WendriverIO Integration with [BrowserStack](https://www.browserstack.com)",
5 | "description": "Selenium examples for WebdriverIO and BrowserStack App Automate",
6 | "scripts": {
7 | "test": "npm run first && npm run local && npm run parallel",
8 | "first": "./node_modules/.bin/wdio examples/run-first-test/first.conf.js",
9 | "parallel": "./node_modules/.bin/wdio examples/run-parallel-test/parallel.conf.js",
10 | "local": "./node_modules/.bin/wdio examples/run-local-test/local.conf.js",
11 | "multiple": "./node_modules/.bin/wdio examples/run-multiple-test/multiple.conf.js"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/browserstack/webdriverio-appium-app-browserstack.git"
16 | },
17 | "keywords": [
18 | "webdriverio",
19 | "browserstack",
20 | "appium",
21 | "tests"
22 | ],
23 | "bugs": {
24 | "url": "https://github.com/browserstack/webdriverio-appium-app-browserstack/issues"
25 | },
26 | "homepage": "https://github.com/browserstack/webdriverio-appium-app-browserstack#readme",
27 | "dependencies": {
28 | "browserstack-local": "^1.4.5",
29 | "@wdio/cli": "^5.20.1",
30 | "@wdio/local-runner": "^5.20.1",
31 | "@wdio/mocha-framework": "^5.18.7"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------