froth-webdriverio-framework 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,95 @@
1
+ exports.config = {
2
+
3
+ user: process.env.BROWSERSTACK_USERNAME || 'subhrasubudhi_uf8nhj',
4
+ key: process.env.BROWSERSTACK_ACCESS_KEY || 'DUGGqze7p9QMZb84y66s',
5
+
6
+ hostname: 'hub.browserstack.com',
7
+
8
+ services: [
9
+ [
10
+ 'browserstack',
11
+ {
12
+ buildIdentifier: '${BUILD_NUMBER}',
13
+ browserstackLocal: true,
14
+ opts: { forcelocal: false, localIdentifier: "webdriverio-appium-app-browserstack-repo" },
15
+ // app: process.env.BROWSERSTACK_APP_PATH || '/Users/subhrasubudhi/WORKSPACES/WEBDRIVERIO/codeceptjs/android/test/Geneco.apk',
16
+ app: 'bs://55f48309e6776984188c25d044bde2b3d90ea057'
17
+ }
18
+ ]
19
+ ],
20
+
21
+ capabilities: [{
22
+ 'bstack:options': {
23
+ deviceName: 'Samsung Galaxy S21',
24
+ osVersion: "11.0"
25
+ }
26
+ }
27
+ //, {
28
+ // 'bstack:options': {
29
+ // deviceName: 'Samsung Galaxy S10e',
30
+ // osVersion: "9.0"
31
+ // }
32
+ // }
33
+ ],
34
+
35
+ commonCapabilities: {
36
+ 'bstack:options': {
37
+ projectName: "YTL APP",
38
+ buildName: 'Android Yes App Build',
39
+ sessionName: 'Yes App Session',
40
+ debug: true,
41
+ networkLogs: true
42
+ // source: 'webdriverio:appium-sample-sdk:v1.0'
43
+ }
44
+ },
45
+ maxInstances: 10,
46
+
47
+ updateJob: false,
48
+ specs: [
49
+ [
50
+ //'./android/specs/yesapp/login.js'
51
+
52
+ ]],
53
+ exclude: [],
54
+ logLevel: 'info',
55
+ coloredLogs: true,
56
+ screenshotPath: './androidReports/',
57
+ baseUrl: '',
58
+ waitforTimeout: 10000,
59
+ connectionRetryTimeout: 90000,
60
+ connectionRetryCount: 3,
61
+
62
+ framework: 'mocha',
63
+ mochaOpts: {
64
+ ui: 'bdd',
65
+ timeout: 60000
66
+ },
67
+ before: function () {
68
+ const chai = require('chai');
69
+ global.expect = chai.expect;
70
+ },
71
+
72
+ reporters: [
73
+ 'spec',
74
+ ['allure', {
75
+ outputDir: './androidReports/allure-results', // Specify the output directory
76
+ disableWebdriverStepsReporting: true,
77
+ disableWebdriverScreenshotsReporting: true,
78
+ }],
79
+ ],
80
+ afterStep: function (test, context, { error, result, duration, passed, retries }) {
81
+ // if (passed) {
82
+ browser.takeScreenshot();
83
+ // }
84
+ },
85
+ afterTest: async function (test, context, { error, result, duration, passed, retries }) {
86
+ if (passed) { await browser.takeScreenshot() }
87
+ }
88
+
89
+ };
90
+
91
+ // Code to support common capabilities
92
+ exports.config.capabilities.forEach(function (caps) {
93
+ for (let key in exports.config.commonCapabilities)
94
+ caps[key] = { ...caps[key], ...exports.config.commonCapabilities[key] };
95
+ });
package/api/index.js ADDED
@@ -0,0 +1,18 @@
1
+ const express = require('express')
2
+ const app = express()
3
+ const port = 5000
4
+
5
+ let count = 0;
6
+
7
+ app.get('/api', (req, res) => {
8
+ res.json({count})
9
+ })
10
+
11
+ app.post('/api', (req, res) => {
12
+ ++count;
13
+ res.json({count});
14
+ });
15
+
16
+ app.listen(port, () => {
17
+ console.log(`Example app listening on port ${port}`)
18
+ })
@@ -0,0 +1,77 @@
1
+ const USER_DIR = process.env['user.dir'];
2
+
3
+ const commonconfig = {
4
+ /**
5
+ * Gets executed before the suite starts (in Mocha/Jasmine only).
6
+ * @param {object} suite suite details
7
+ */
8
+ beforeSuite: function (suite) {
9
+ console.log("Running suite:", suite.title);
10
+ },
11
+
12
+ /**
13
+ * Function to be executed before a test (in Mocha/Jasmine only)
14
+ * @param {object} test test object
15
+ * @param {object} context scope object the test was executed with
16
+ */
17
+ beforeTest: function (test, context) {
18
+ console.log("Test Name:", test.title);
19
+ console.log("Context Details:", context.title);
20
+ console.log("File Name:", test.file);
21
+
22
+ },
23
+
24
+ afterStep: function (test, context, { error, result, duration, passed, retries }) {
25
+ // if (passed) {
26
+ browser.takeScreenshot();
27
+ // }
28
+ },
29
+ // afterTest: async function (test, context, { error, result, duration, passed, retries }) {
30
+ // if (passed) { await browser.takeScreenshot() }
31
+ // },
32
+ /**
33
+ * Function to be executed after a test (in Mocha/Jasmine only)
34
+ * @param {object} test test object
35
+ * @param {object} context scope object the test was executed with
36
+ * @param {Error} result.error error object in case the test fails, otherwise `undefined`
37
+ * @param {*} result.result return object of test function
38
+ * @param {number} result.duration duration of test
39
+ * @param {boolean} result.passed true if test has passed, otherwise false
40
+ * @param {object} result.retries information about spec related retries, e.g. `{ attempts: 0, limit: 0 }`
41
+ */
42
+ afterTest: function (test, context, { error, result, duration, passed, retries }) {
43
+ console.log(`Test '${test.title}' finished.`);
44
+ console.log(`Duration: ${duration}ms`);
45
+ console.log(`Passed: ${passed}`);
46
+ if (error) {
47
+ console.error(`Error: ${error.message}`);
48
+ }
49
+ console.log('---------------------------------------');
50
+ },
51
+ /**
52
+ * Hook that gets executed after the suite has ended (in Mocha/Jasmine only).
53
+ * @param {object} suite suite details
54
+ */
55
+ afterSuite: function (suite) {
56
+ console.log(`Test suite '${suite.title}' has ended.`);
57
+ },
58
+ /**
59
+ * Gets executed after all tests are done. You still have access to all global variables from
60
+ * the test.
61
+ * @param {number} result 0 - test pass, 1 - test fail
62
+ * @param {Array.<Object>} capabilities list of capabilities details
63
+ * @param {Array.<String>} specs List of spec file paths that ran
64
+ */
65
+ after: function (result, capabilities, specs) {
66
+ console.log('All tests are done.');
67
+ console.log(`Result: ${result === 0 ? 'Pass' : 'Fail'}`);
68
+ console.log('Capabilities:');
69
+ console.log(capabilities);
70
+ console.log('Specs:');
71
+ console.log(specs);
72
+ },
73
+
74
+ };
75
+
76
+ module.exports = commonconfig;
77
+
package/ios.conf.js ADDED
@@ -0,0 +1,75 @@
1
+
2
+ exports.config = {
3
+ user: process.env.BROWSERSTACK_USERNAME || 'subhrasubudhi_uf8nhj',
4
+ key: process.env.BROWSERSTACK_ACCESS_KEY || 'DUGGqze7p9QMZb84y66s',
5
+
6
+ services: [
7
+ [
8
+ 'browserstack',
9
+ {
10
+ buildIdentifier: '${BUILD_NUMBER}',
11
+ browserstackLocal: true,
12
+ opts: { forcelocal: false, localIdentifier: "webdriverio-appium-app-browserstack-repo" },
13
+ //app: process.env.BROWSERSTACK_APP_PATH || '/Users/subhrasubudhi/WORKSPACES/WEBDRIVERIO/codeceptjs/ios/test/BStackSampleApp.ipa'
14
+ app: 'bs://512eefa5c0b9f103907f0c69f6ef811defc4a9cb'
15
+ }
16
+ ]
17
+ ],
18
+
19
+ capabilities: [{
20
+ 'bstack:options': {
21
+ deviceName: "iPhone 15 Pro Max",
22
+ osVersion: "17"
23
+ }
24
+ }
25
+
26
+ ],
27
+
28
+ commonCapabilities: {
29
+ 'bstack:options': {
30
+ projectName: "Yes App",
31
+ buildName: 'IOS Yes App build',
32
+ sessionName: 'Yes App Session',
33
+ debug: true,
34
+ networkLogs: true,
35
+ // source: 'webdriverio:appium-sample-sdk:v1.0'
36
+ }
37
+ },
38
+
39
+ maxInstances: 10,
40
+
41
+ updateJob: false,
42
+ specs: [
43
+ // './specs/single_test.js'
44
+ ],
45
+ exclude: [],
46
+
47
+
48
+ logLevel: 'info',
49
+ coloredLogs: true,
50
+ screenshotPath: './errorShots/',
51
+ baseUrl: '',
52
+ waitforTimeout: 10000,
53
+ connectionRetryTimeout: 90000,
54
+ connectionRetryCount: 3,
55
+
56
+ framework: 'mocha',
57
+
58
+ mochaOpts: {
59
+ ui: 'bdd',
60
+ timeout: 60000
61
+ },
62
+
63
+ before: function () {
64
+ const chai = require('chai');
65
+ global.expect = chai.expect;
66
+ },
67
+
68
+
69
+ };
70
+
71
+ // Code to support common capabilities
72
+ exports.config.capabilities.forEach(function (caps) {
73
+ for (let key in exports.config.commonCapabilities)
74
+ caps[key] = { ...caps[key], ...exports.config.commonCapabilities[key] };
75
+ });
package/local.log ADDED
@@ -0,0 +1,8 @@
1
+
2
+
3
+ Thu Feb 15 2024 20:15:19:833 GMT+0800 (+08) -- Starting configuration console on http://localhost:45454
4
+ Thu Feb 15 2024 20:15:21:656 GMT+0800 (+08) -- [SUCCESS] You can now access your local server(s) in our remote browser
5
+
6
+ Thu Feb 15 2024 20:15:22:756 GMT+0800 (+08) -- Press Ctrl-C to exit
7
+
8
+
@@ -0,0 +1,21 @@
1
+ const ScrollToEnd = require('./ScrollToEnd');
2
+ const ClickIfVisible= require('./clickIfVisible');
3
+ const VerifyTextInFieldAttribute= require('./verifyTextInFieldAttribute');
4
+ const ScrollToBeginning = require('./scrollToBeginning');
5
+ const ScrollToLeft = require('./scrollToLeft');
6
+ const ScrollToRight = require('./scrollToRight');
7
+ const ScrollDownToView= require('./ScrollDownToView');
8
+ const ScrollRightToView= require('./ScrollRightToView');
9
+ const verifyText= require('./verifyText');
10
+ // Export the functions
11
+ module.exports = {
12
+ ScrollToEnd,
13
+ ClickIfVisible,
14
+ VerifyTextInFieldAttribute,
15
+ ScrollToBeginning,
16
+ ScrollToLeft,
17
+ ScrollToRight,
18
+ ScrollRightToView,
19
+ ScrollDownToView,
20
+ verifyText
21
+ };
@@ -0,0 +1,23 @@
1
+ async function clickIfVisible(elementSelector) {
2
+ try {
3
+ let isDisplayed;
4
+ // Wait for the element to be visible
5
+ await driver.waitUntil(async () => {
6
+ console.log("Waiting for element to be visible");
7
+ const element = await driver.$(elementSelector);
8
+ isDisplayed = await element.isDisplayed();
9
+ console.log("Element is displayed:", isDisplayed);
10
+ if (isDisplayed) {
11
+ // Get the actual text from the element
12
+ const element = await driver.$(elementSelector);
13
+ await element.click();
14
+ console.log("Element is clicked successfully.");
15
+ return ;
16
+ }
17
+ }, { timeout: 30000 });
18
+ } catch (error) {
19
+ console.error("Element not found or not visible within 30 seconds");
20
+ }
21
+ }
22
+
23
+ module.exports = clickIfVisible;
@@ -0,0 +1,38 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const directory = '/Users/subhrasubudhi/WORKSPACES/WEBDRIVERIO/TEST/mobile/Testdata'; // specify your directory path
4
+ async function getdata(filename_propertyname) {
5
+ try {
6
+ console.log('data:', filename_propertyname);
7
+ const parts = filename_propertyname.split(".");
8
+ const property = parts[1];
9
+ console.log('property:', property);
10
+ fileName = parts[0] + '.json';
11
+ console.log('filename:', fileName);
12
+
13
+ const files = await fs.promises.readdir(directory);
14
+ const file = files.find(file => file === fileName);
15
+
16
+ if (file) {
17
+ const filePath = path.join(directory, file);
18
+ const jsonData = await fs.promises.readFile(filePath, 'utf-8');
19
+ const parsedData = JSON.parse(jsonData);
20
+ console.log(parsedData);
21
+ const value = parsedData[property];
22
+ console.log(value);
23
+ return value;
24
+ } else {
25
+ throw new Error(`File '${_filename}' not found in directory '${directory}'.`);
26
+ }
27
+ } catch (error) {
28
+ console.error('Error occurred:', error);
29
+ throw error; // Rethrow the error for the caller to handle.
30
+ }
31
+ }
32
+ module.exports = getdata;
33
+ // Example usage:
34
+ // specify your file name
35
+
36
+ console.log(getdata('data1.env'));
37
+
38
+
@@ -0,0 +1,12 @@
1
+ async function ScrollDownToView(text) {
2
+
3
+ try {
4
+ console.log('Scrolling down until text is found');
5
+ await $('android=new UiScrollable(new UiSelector().scrollable(true)).scrollTextIntoView("' + text + '")');
6
+ await driver.pause(3000);
7
+ console.log('Scrolled down completed');
8
+ } catch (error) {
9
+ console.error(error.message);
10
+ }
11
+ }
12
+ module.exports = ScrollDownToView;
@@ -0,0 +1,12 @@
1
+ async function ScrollRightToView(text) {
2
+
3
+ try {
4
+ console.log('Scrolling to right until text is found');
5
+ await $('android=new UiScrollable(new UiSelector().scrollable(true)).setAsHorizontalList().scrollTextIntoView("' + text + '")');
6
+ await driver.pause(3000);
7
+ console.log('Scrolled to right completed');
8
+ } catch (error) {
9
+ console.error(error.message);
10
+ }
11
+ }
12
+ module.exports = ScrollRightToView;
@@ -0,0 +1,12 @@
1
+ async function ScrollToBeginning(maxSwipes,steps) {
2
+
3
+ try {
4
+ console.log('Scrolling to beginning');
5
+ await $('android=new UiScrollable(new UiSelector().scrollable(true)).scrollToBeginning('+maxSwipes+','+steps+')');
6
+ await driver.pause(3000);
7
+ console.log('Scrolled to beginning');
8
+ } catch (error) {
9
+ console.error(error.message);
10
+ }
11
+ }
12
+ module.exports = ScrollToBeginning;
@@ -0,0 +1,12 @@
1
+ async function ScrollToEnd(maxSwipes,steps) {
2
+
3
+ try {
4
+ console.log('Scrolling to end');
5
+ await $('android=new UiScrollable(new UiSelector().scrollable(true)).scrollToEnd('+maxSwipes+','+steps+')');
6
+ await driver.pause(3000);
7
+ console.log('Scrolled to end');
8
+ } catch (error) {
9
+ console.error(error.message);
10
+ }
11
+ }
12
+ module.exports = ScrollToEnd;
@@ -0,0 +1,12 @@
1
+ async function ScrollToLeft(steps) {
2
+
3
+ try {
4
+ console.log('Scrolling to left');
5
+ await $('android=new UiScrollable(new UiSelector().scrollable(true)).scrollable.setAsHorizontalList().scrollBackward('+steps+')');
6
+ await driver.pause(3000);
7
+ console.log('Scrolled to left');
8
+ } catch (error) {
9
+ console.error(error.message);
10
+ }
11
+ }
12
+ module.exports = ScrollToLeft;
@@ -0,0 +1,12 @@
1
+ async function ScrollToRight(steps) {
2
+
3
+ try {
4
+ console.log('Scrolling to right');
5
+ await $('android=new UiScrollable(new UiSelector().scrollable(true)).scrollable.setAsHorizontalList().scrollForward('+steps+')');
6
+ await driver.pause(3000);
7
+ console.log('Scrolled to right');
8
+ } catch (error) {
9
+ console.error(error.message);
10
+ }
11
+ }
12
+ module.exports = ScrollToRight;
@@ -0,0 +1,19 @@
1
+ const fs = require("fs");
2
+
3
+ function readAndParseJSON(filename) {
4
+ const [fileName, fileExtension] = filename.split(".");
5
+ const jsonFilePath = fileName + ".json";
6
+ const constantProperty = fileExtension;
7
+
8
+ const filePath = `/Users/subhrasubudhi/WORKSPACES/WEBDRIVERIO/TEST/mobile/Testdata/${jsonFilePath}`;
9
+
10
+ const jsonData = fs.readFileSync(filePath, "utf-8");
11
+ const parsedData = JSON.parse(jsonData);
12
+
13
+ console.log(parsedData);
14
+ const value = parsedData[constantProperty];
15
+ return value;
16
+ }
17
+
18
+ const data1 = readAndParseJSON("data1.env");
19
+ console.log(data1);
@@ -0,0 +1,28 @@
1
+ // Function to verify text in Android app
2
+ async function verifyText(driver, elementSelector, expectedText) {
3
+ try {
4
+ // Wait for the element to be visible
5
+ await driver.waitUntil(async () => {
6
+ const element = await driver.$(elementSelector);
7
+ return await element.isDisplayed();
8
+ }, { timeout: 30000});
9
+
10
+ // Get the actual text from the element
11
+ const element = await driver.$(elementSelector);
12
+ const actualText = await element.getText();
13
+
14
+ // Compare the actual text with the expected text
15
+ if (actualText === expectedText) {
16
+ console.log('Text verification passed. Actual text:', actualText, 'Expected text:', expectedText);
17
+ return true;
18
+ } else {
19
+ console.warn('Text verification failed. Actual text:', actualText, 'Expected text:', expectedText);
20
+ }
21
+ } catch (error) {
22
+ console.error('Error occurred while verifying text:', error);
23
+ }
24
+ }
25
+
26
+ module.exports = verifyText;
27
+
28
+
@@ -0,0 +1,17 @@
1
+
2
+ async function verifyTextInFieldAttribute(element, attribute, expectedText, driver) {
3
+
4
+ try {
5
+ let ele = await driver.$(element);
6
+ // Get the actual text from the specified attribute
7
+ const actualText = await ele.getAttribute(attribute);
8
+
9
+ // Assert that the actual text matches the expected text
10
+ assert.strictEqual(actualText, expectedText, `Expected text: ${expectedText}, Actual text: ${actualText}`);
11
+ console.log('Text verification passed!');
12
+ } catch (error) {
13
+ console.log('Text verification failed:', `Expected text: ${expectedText}, Actual text: ${actualText}`);
14
+ console.error(error.message);
15
+ }
16
+ }
17
+ module.exports = verifyTextInFieldAttribute;
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "froth-webdriverio-framework",
3
+ "version": "0.1.1",
4
+ "readme": "WendriverIO Integration with [BrowserStack]",
5
+ "description": "WebdriverIO and BrowserStack App Automate",
6
+ "license": "MIT",
7
+ "scripts": {
8
+ "wdio:ios": "npx wdio ./ios.conf.js",
9
+ "wdio:android": "npx wdio ./android.conf.js",
10
+ "wdio:web": "npx wdio ./web.conf.js",
11
+ "wdio:webbs": "npx wdio ./web.conf.bs.js",
12
+ "wdio:ios:local": "npx wdio ./ios.local.conf.js",
13
+ "android:generate-allure-report": "allure generate ./mobile/androidReports/allure-results --clean && allure open",
14
+ "ios:generate-allure-report": "allure generate ./mobile/iosReports/allure-results --clean && allure open",
15
+ "web:generate-allure-report": "allure generate ./webReports/allure-results --clean && allure open",
16
+ "lint": "eslint ."
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/RoboticoDigitalProjects/froth-webdriverio.git"
21
+ },
22
+ "keywords": [
23
+ "webdriverio",
24
+ "browserstack",
25
+ "appium",
26
+ "tests"
27
+ ],
28
+ "devDependencies": {
29
+ "@wdio/appium-service": "^8.36.1",
30
+ "@wdio/browserstack-service": "^8.36.1",
31
+ "@wdio/cli": "^8.36.1",
32
+ "@wdio/local-runner": "^8.36.1",
33
+ "@wdio/mocha-framework": "^8.36.1",
34
+ "@wdio/spec-reporter": "^8.36.1",
35
+ "appium": "^2.5.4",
36
+ "appium-uiautomator2-driver": "^3.2.0"
37
+ }
38
+ }