├── .gitignore ├── README.md ├── jsconfig.json ├── old ├── element.js ├── header.js └── home.element.js ├── package-lock.json ├── package.json ├── pages ├── actions.page.js ├── alertpage.js ├── blazemeter.js ├── crm.page.js ├── internetpage.js └── loginpage.js ├── test ├── actions.test.js ├── alert.test.js ├── blaze.test.js ├── checkbox.test.js ├── dragdrop.test.js ├── dropdown.test.js ├── elements │ ├── elementActions.test.js │ └── url.test.js ├── login.test.js ├── scrollview.test.js └── waits │ ├── waitForEnabled.test.js │ ├── waitForExist.test.js │ └── waitUntil.test.js ├── testdata └── logindata.js ├── urls.js └── wdio.conf.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | allure-results -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WebdriverIO Mocha Framework 2 | The project uses WebdriverIO and JavaScript. It includes examples of the PageObject pattern and some practical examples for different element actions 3 | 4 | ## Requirements 5 | - node >= 12.18.x - [how to install Node](https://nodejs.org/en/download/) 6 | - npm >= 6.14.x - [how to install NPM](https://www.npmjs.com/get-npm) 7 | 8 | ## Getting Started 9 | Clone Repository 10 | ```bash 11 | 1. Fork this repository 12 | 2. git clone https://github.com/{USERNAME}/WebDriverIO-JavaScriptCode.git 13 | 3. Navigate to WebDriverIO-JavaScriptCode 14 | ``` 15 | 16 | Install the dependencies: 17 | ```bash 18 | npm install 19 | ``` 20 | 21 | Run e2e tests: 22 | ```bash 23 | npm run test 24 | ``` 25 | 26 | ### Generate/Open allure reporter 27 | - In the terminal, perform `npm run report` to open allure report port. Report will be opened in default browser 28 | 29 | ### Key Features 30 | - Allure Report 31 | - Mocha framework 32 | - Page Object Design pattern 33 | - Test Data sourced from json file 34 | - Environment set from commandline 35 | 36 | 37 | ### Sample Report 38 | ![image](https://user-images.githubusercontent.com/65847528/118385908-d6997a00-b630-11eb-9a0e-af436d2d6b1f.png) 39 | 40 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "**/*.js", 4 | "**/*.json", 5 | "node_modules/@wdio/sync", 6 | "node_modules/@wdio/mocha-framework", 7 | "node_modules/webdriverio" 8 | ] 9 | } -------------------------------------------------------------------------------- /old/element.js: -------------------------------------------------------------------------------- 1 | describe("interaction with web element", function(){ 2 | 3 | it("enter value in a field", function(){ 4 | browser.url('/'); 5 | const search = $('#twotabsearchtextbox'); 6 | search.setValue('Apple Mac Book'); 7 | browser.pause(5000); 8 | 9 | }); 10 | 11 | it("get text of field", function(){ 12 | browser.url('/'); 13 | const label = $('span.a-size-base.a-color-base'); 14 | let text = label.getText(); 15 | console.log(text); 16 | 17 | 18 | }); 19 | 20 | it("click on a field", function(){ 21 | browser.url('/'); 22 | const icon = $('input.nav-input'); 23 | icon.click(); 24 | 25 | }); 26 | 27 | 28 | }); -------------------------------------------------------------------------------- /old/header.js: -------------------------------------------------------------------------------- 1 | describe("interaction with web element", function(){ 2 | 3 | it("get header value", function(){ 4 | browser.url('https://www.freshworks.com'); 5 | const header = $('h1'); 6 | let text = header.getText(); 7 | console.log(text); 8 | 9 | }); 10 | 11 | }); -------------------------------------------------------------------------------- /old/home.element.js: -------------------------------------------------------------------------------- 1 | const homePage = require("../pages/homepage") 2 | 3 | describe("home page elements handle", function(){ 4 | 5 | it("verify home page elements", function(){ 6 | 7 | browser.url("https://www.freshworks.com/"); 8 | let text = homePage.pageHeader.getText(); 9 | console.log(text); 10 | console.log(homePage.subHeading.getText()); 11 | homePage.supportLink.click(); 12 | browser.pause(5000); 13 | 14 | 15 | 16 | }); 17 | 18 | 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webdriver-io-scripts", 3 | "version": "1.0.0", 4 | "description": "this is webdriver tutorial", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node_modules/.bin/wdio wdio.conf.js", 8 | "elements": "node_modules/.bin/wdio wdio.conf.js --suite elements", 9 | "waits": "node_modules/.bin/wdio wdio.conf.js --suite waits", 10 | "report": "allure generate --clean allure-results && allure open" 11 | }, 12 | "author": "Naveen Khunteta", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "@types/webdriverio": "^5.0.0", 16 | "@wdio/allure-reporter": "^7.5.7", 17 | "@wdio/firefox-profile-service": "^7.5.3", 18 | "@wdio/local-runner": "^7.5.7", 19 | "@wdio/mocha-framework": "^7.5.3", 20 | "@wdio/selenium-standalone-service": "^7.5.7", 21 | "@wdio/spec-reporter": "^7.5.7", 22 | "@wdio/sync": "^7.5.7", 23 | "allure-commandline": "^2.13.8", 24 | "chai": "^4.3.4", 25 | "chai-webdriverio": "^1.0.0", 26 | "chromedriver": "^90.0.0", 27 | "local-runner": "^0.1.1-alpha", 28 | "wdio-chromedriver-service": "^7.0.0", 29 | "webdriverio": "^7.5.7" 30 | }, 31 | "dependencies": { 32 | "@wdio/cli": "^7.5.7", 33 | "i": "^0.3.6" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /pages/actions.page.js: -------------------------------------------------------------------------------- 1 | class Spicejet{ 2 | 3 | get loginSignUpLink() {return $('#ctl00_HyperLinkLogin')} 4 | get spiceClubMem() {return $('=SpiceClub Members')} 5 | get memberLogin() {return $('=Member Login')} 6 | 7 | get search() {return $('#target')} 8 | get resultLabel() {return $('#result')} 9 | 10 | getResultLabelText(){ 11 | this.resultLabel.waitForDisplayed(); 12 | return this.resultLabel.getText(); 13 | } 14 | 15 | enterSearch(text){ 16 | this.search.waitForDisplayed(); 17 | this.search.setValue(text); 18 | } 19 | 20 | moveToElement(element){ 21 | element.waitForDisplayed(); 22 | element.moveTo(); 23 | } 24 | 25 | clickElement(element){ 26 | element.waitForDisplayed(); 27 | element.click(); 28 | } 29 | 30 | 31 | } 32 | 33 | module.exports = new Spicejet(); 34 | 35 | -------------------------------------------------------------------------------- /pages/alertpage.js: -------------------------------------------------------------------------------- 1 | class AlertPage{ 2 | 3 | get result(){ 4 | return $('#result') 5 | } 6 | 7 | getResultText(){ 8 | return this.result.getText() 9 | } 10 | 11 | getAlertButton(index){ 12 | return $(`ul li:nth-child(${index}) button`) 13 | } 14 | 15 | clickOnAlertButton(index){ 16 | this.getAlertButton(index).waitForDisplayed() 17 | this.getAlertButton(index).click() 18 | } 19 | } 20 | 21 | module.exports = new AlertPage() 22 | -------------------------------------------------------------------------------- /pages/blazemeter.js: -------------------------------------------------------------------------------- 1 | class BlazePage { 2 | 3 | get mainHeader() { 4 | return $('h2.home_title') 5 | } 6 | get productLink() { 7 | return $('ul.list-nav-links li:nth-child(11111) a') 8 | } 9 | clickOnProductLink() { 10 | this.productLink.waitForDisplayed(); 11 | if (this.productLink.isDisplayed() === true) { 12 | this.productLink.click(); 13 | } 14 | } 15 | get jmeterLink() { 16 | return $("//a[text()='JMeter']") 17 | } 18 | get parent() { 19 | return $('ul.list-nav-links'); 20 | } 21 | get childElements() { 22 | return this.parent.$$('li'); 23 | } 24 | get getTextForLi() { 25 | return this.childElements.filter(element => { 26 | console.log(element.getText()); 27 | }); 28 | } 29 | 30 | get useCasesElements() { 31 | return $$('div#main_b_footer_second_block>ul>li') 32 | } 33 | 34 | get useCasesElementsText() { 35 | return this.useCasesElements.filter(element => { 36 | console.log(element.getText()); 37 | }); 38 | } 39 | 40 | specifChildElement(index) { 41 | return this.parent.$(`li:nth-child(${index})`) 42 | } 43 | 44 | getSpecificChildElementText(index) { 45 | console.log(this.specifChildElement(index).getText()); 46 | } 47 | 48 | 49 | 50 | 51 | } 52 | 53 | module.exports = new BlazePage(); -------------------------------------------------------------------------------- /pages/crm.page.js: -------------------------------------------------------------------------------- 1 | class CRMPage{ 2 | 3 | get forgotpwdLink() { 4 | return $('=Forgot Password?') 5 | } 6 | 7 | moveToElement(element){ 8 | element.waitForDisplayed(); 9 | element.moveTo(); 10 | } 11 | 12 | 13 | } 14 | 15 | module.exports = new CRMPage(); -------------------------------------------------------------------------------- /pages/internetpage.js: -------------------------------------------------------------------------------- 1 | class InternetPage{ 2 | 3 | get h3Header(){ 4 | return $('h3'); 5 | } 6 | 7 | getLinkElement(index){ 8 | return $(`ul li:nth-child(${index}) a`); 9 | } 10 | 11 | clickOnLink(index){ 12 | this.getLinkElement(index).waitForDisplayed(); 13 | this.getLinkElement(index).click(); 14 | } 15 | 16 | getCheckBoxElement(index){ 17 | return $(`form#checkboxes input:nth-child(${index})`); 18 | } 19 | 20 | clickOnCheckBox(index){ 21 | this.getCheckBoxElement(index).waitForDisplayed(); 22 | this.getCheckBoxElement(index).click(); 23 | } 24 | 25 | } 26 | module.exports = new InternetPage(); 27 | -------------------------------------------------------------------------------- /pages/loginpage.js: -------------------------------------------------------------------------------- 1 | class LoginPage{ 2 | 3 | get username() { return $('#username')} 4 | get password() { return $('#password')} 5 | get loginBtn() { return $('button')} 6 | 7 | enterUserName(text){ 8 | this.username.waitForDisplayed(); 9 | this.username.setValue(text); 10 | } 11 | enterPassword(text){ 12 | this.password.waitForDisplayed(); 13 | this.password.setValue(text); 14 | } 15 | clickOnLogin(){ 16 | this.loginBtn.waitForDisplayed(); 17 | this.loginBtn.click(); 18 | } 19 | } 20 | 21 | module.exports = new LoginPage(); -------------------------------------------------------------------------------- /test/actions.test.js: -------------------------------------------------------------------------------- 1 | const spicejetPage = require("../pages/actions.page") 2 | 3 | 4 | describe("page actions Features", function(){ 5 | 6 | it("move to element", function(){ 7 | browser.url("https://www.spicejet.com/"); 8 | spicejetPage.moveToElement(spicejetPage.loginSignUpLink); 9 | spicejetPage.moveToElement(spicejetPage.spiceClubMem); 10 | spicejetPage.clickElement(spicejetPage.memberLogin); 11 | browser.pause(3000); 12 | }); 13 | 14 | it("KEYS action perform Tab", function(){ 15 | browser.url("http://the-internet.herokuapp.com/key_presses?"); 16 | spicejetPage.enterSearch("Tab"); 17 | const text = spicejetPage.getResultLabelText(); 18 | console.log(text); 19 | assert.equal("You entered: TAB", text); 20 | browser.pause(3000); 21 | }); 22 | 23 | it("KEYS action perform Shift", function(){ 24 | browser.url("http://the-internet.herokuapp.com/key_presses?"); 25 | spicejetPage.enterSearch("Shift"); 26 | const text = spicejetPage.getResultLabelText(); 27 | console.log(text); 28 | assert.equal("You entered: SHIFT", text); 29 | browser.pause(3000); 30 | }); 31 | 32 | it("KEYS action perform F1", function(){ 33 | browser.url("http://the-internet.herokuapp.com/key_presses?"); 34 | spicejetPage.enterSearch("F1"); 35 | const text = spicejetPage.getResultLabelText(); 36 | console.log(text); 37 | assert.equal("You entered: F1", text); 38 | browser.pause(3000); 39 | }); 40 | 41 | it("KEYS action perform F1", function(){ 42 | browser.url("http://the-internet.herokuapp.com/key_presses?"); 43 | spicejetPage.enterSearch("F1"); 44 | const text = spicejetPage.getResultLabelText(); 45 | console.log(text); 46 | assert.equal("You entered: F1", text); 47 | browser.pause(3000); 48 | }); 49 | 50 | 51 | 52 | }); -------------------------------------------------------------------------------- /test/alert.test.js: -------------------------------------------------------------------------------- 1 | const alertPage = require("../pages/alertpage") 2 | //import alertPage from '../pages/alertPage' 3 | 4 | describe("handle alert pop ups", function(){ 5 | 6 | it('accept alert', function(){ 7 | browser.url("http://the-internet.herokuapp.com/javascript_alerts") 8 | alertPage.clickOnAlertButton(1) 9 | const alertText = browser.getAlertText() 10 | console.log(alertText) 11 | assert.equal('I am a JS Alert', alertText) 12 | browser.acceptAlert() 13 | console.log(alertPage.getResultText()) 14 | assert.equal('You successfully clicked an alert',alertPage.getResultText()) 15 | browser.pause(3000) 16 | }) 17 | 18 | it('dismiss alert', function(){ 19 | browser.url("http://the-internet.herokuapp.com/javascript_alerts") 20 | alertPage.clickOnAlertButton(2) 21 | browser.dismissAlert() 22 | console.log(alertPage.getResultText()) 23 | assert.equal('You clicked: Cancel',alertPage.getResultText()) 24 | browser.pause(3000) 25 | }) 26 | 27 | it('enter text on alert and accept', function(){ 28 | browser.url("http://the-internet.herokuapp.com/javascript_alerts") 29 | alertPage.clickOnAlertButton(3) 30 | browser.sendAlertText('this is alert text') 31 | browser.acceptAlert() 32 | console.log(alertPage.getResultText()) 33 | assert.equal('You entered: this is alert text',alertPage.getResultText()) 34 | browser.pause(3000) 35 | }) 36 | 37 | 38 | it('alert accept on rediffmail login page', function(){ 39 | browser.url("https://mail.rediff.com/cgi-bin/login.cgi") 40 | $(`//input[@type='submit']`).waitForDisplayed() 41 | $(`//input[@type='submit']`).click() 42 | browser.pause(3000) 43 | const text = browser.getAlertText() 44 | console.log(text) 45 | assert.equal('Please enter a valid user name', text) 46 | browser.acceptAlert() 47 | browser.pause(3000) 48 | }) 49 | }) -------------------------------------------------------------------------------- /test/blaze.test.js: -------------------------------------------------------------------------------- 1 | const blazePage = require("../pages/blazemeter") 2 | 3 | describe("blaze page elements handle on the page", function(){ 4 | 5 | it("get texts of all main links", function(){ 6 | browser.url('https://www.blazemeter.com/'); 7 | // blazePage.getTextForLi; 8 | // blazePage.useCasesElementsText; 9 | 10 | console.log('third link is : ', 11 | blazePage.specifChildElement(3).getText()); 12 | 13 | blazePage.getSpecificChildElementText(4); 14 | 15 | }) 16 | 17 | it("main heading displayed? ", function(){ 18 | console.log( blazePage.mainHeader.isDisplayed()); 19 | }) 20 | 21 | it("main heading enabled? ", function(){ 22 | console.log( blazePage.mainHeader.isEnabled()); 23 | }) 24 | 25 | it("main heading exists? ", function(){ 26 | console.log( blazePage.mainHeader.isExisting()); 27 | }) 28 | 29 | it("main heading displyed in view port? ", function(){ 30 | console.log( blazePage.mainHeader.isDisplayedInViewport()); 31 | }) 32 | 33 | it("jmeter is displeyd in view port ", function(){ 34 | console.log( blazePage.jmeterLink.isDisplayedInViewport()); 35 | }) 36 | 37 | it("click on product link if displayed ", function(){ 38 | blazePage.clickOnProductLink(); 39 | browser.pause(5000); 40 | }) 41 | 42 | 43 | 44 | 45 | }); 46 | -------------------------------------------------------------------------------- /test/checkbox.test.js: -------------------------------------------------------------------------------- 1 | const internetPage = require("../pages/internetpage"); 2 | 3 | describe("handling checkboxes", function(){ 4 | it("check page url", function(){ 5 | browser.url("/"); 6 | //expect(browser.getUrl()).equals("http://the-internet.herokuapp.com/"); 7 | expect(browser.getUrl()).equals(`${browser.options.baseUrl}/`); 8 | }); 9 | it("should click checkbox", function(){ 10 | browser.url("/"); 11 | internetPage.clickOnLink(6); 12 | internetPage.h3Header.waitForDisplayed(); 13 | internetPage.clickOnCheckBox(1); 14 | expect(internetPage.getCheckBoxElement(1).isSelected()).equals(true); 15 | }); 16 | it("check checkbox page header", function(){ 17 | browser.url("/"); 18 | internetPage.clickOnLink(6); 19 | internetPage.h3Header.waitForDisplayed(); 20 | const text = internetPage.h3Header.getText(); 21 | expect(text).equals("Checkboxes"); 22 | }); 23 | it("check checkbox page url", function(){ 24 | browser.url("/"); 25 | internetPage.clickOnLink(6); 26 | expect(browser.getUrl()).equals(`${browser.options.baseUrl}/checkboxes`); 27 | }); 28 | }); -------------------------------------------------------------------------------- /test/dragdrop.test.js: -------------------------------------------------------------------------------- 1 | describe("drag and drop actions feature", function(){ 2 | 3 | it("do drag and drop", function(){ 4 | browser.url("https://jqueryui.com/resources/demos/droppable/default.html"); 5 | 6 | const sourceElement = $('#draggable'); 7 | const targetElement = $('#droppable'); 8 | 9 | sourceElement.dragAndDrop(targetElement, 10); 10 | 11 | browser.pause(5000); 12 | 13 | 14 | }); 15 | 16 | 17 | 18 | 19 | 20 | }); -------------------------------------------------------------------------------- /test/dropdown.test.js: -------------------------------------------------------------------------------- 1 | describe("drop down handling", function(){ 2 | 3 | it.skip("select drop down value by text", function(){ 4 | browser.url("https://www.facebook.com/") 5 | $('#day').selectByVisibleText('10') 6 | $('#month').selectByVisibleText('Apr') 7 | $('#year').selectByVisibleText('1990') 8 | browser.pause(3000) 9 | }) 10 | 11 | it.skip("select drop down value by index", function(){ 12 | browser.url("https://www.facebook.com/") 13 | $('#day').selectByIndex(3) 14 | $('#month').selectByIndex(9) 15 | $('#year').selectByIndex(13) 16 | browser.pause(3000) 17 | }) 18 | 19 | it.skip("select drop down value by attribute value", function(){ 20 | browser.url("https://www.facebook.com/") 21 | $('#day').selectByAttribute('value',"25") 22 | $('#month').selectByAttribute('value',"7") 23 | $('#year').selectByAttribute('value',"2015") 24 | browser.pause(3000) 25 | }) 26 | 27 | it("get all the values from dropdown", function(){ 28 | browser.url("https://www.facebook.com/") 29 | let list = $$('#month option'); 30 | console.log('length is ', list.length) 31 | 32 | for(let i = 0; i} capabilities list of capabilities details 175 | */ 176 | // onPrepare: function (config, capabilities) { 177 | // }, 178 | /** 179 | * Gets executed just before initialising the webdriver session and test framework. It allows you 180 | * to manipulate configurations depending on the capability or spec. 181 | * @param {Object} config wdio configuration object 182 | * @param {Array.} capabilities list of capabilities details 183 | * @param {Array.} specs List of spec file paths that are to be run 184 | */ 185 | // beforeSession: function (config, capabilities, specs) { 186 | // }, 187 | /** 188 | * Gets executed before test execution begins. At this point you can access to all global 189 | * variables like `browser`. It is the perfect place to define custom commands. 190 | * @param {Array.} capabilities list of capabilities details 191 | * @param {Array.} specs List of spec file paths that are to be run 192 | */ 193 | // before: function (capabilities, specs) { 194 | // }, 195 | /** 196 | * Runs before a WebdriverIO command gets executed. 197 | * @param {String} commandName hook command name 198 | * @param {Array} args arguments that command would receive 199 | */ 200 | // beforeCommand: function (commandName, args) { 201 | // }, 202 | /** 203 | * Hook that gets executed before the suite starts 204 | * @param {Object} suite suite details 205 | */ 206 | // beforeSuite: function (suite) { 207 | // }, 208 | /** 209 | * Function to be executed before a test (in Mocha/Jasmine) starts. 210 | */ 211 | beforeTest: function () { 212 | const chai = require('chai') 213 | const chaiWebdriver = require('chai-webdriverio').default 214 | chai.use(chaiWebdriver(browser)) 215 | 216 | global.assert = chai.assert 217 | global.should = chai.should 218 | global.expect = chai.expect 219 | }, 220 | /** 221 | * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling 222 | * beforeEach in Mocha) 223 | */ 224 | // beforeHook: function (test, context) { 225 | // }, 226 | /** 227 | * Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling 228 | * afterEach in Mocha) 229 | */ 230 | // afterHook: function (test, context, { error, result, duration, passed, retries }) { 231 | // }, 232 | /** 233 | * Function to be executed after a test (in Mocha/Jasmine). 234 | */ 235 | // afterTest: function(test, context, { error, result, duration, passed, retries }) { 236 | // }, 237 | 238 | 239 | /** 240 | * Hook that gets executed after the suite has ended 241 | * @param {Object} suite suite details 242 | */ 243 | // afterSuite: function (suite) { 244 | // }, 245 | /** 246 | * Runs after a WebdriverIO command gets executed 247 | * @param {String} commandName hook command name 248 | * @param {Array} args arguments that command would receive 249 | * @param {Number} result 0 - command success, 1 - command error 250 | * @param {Object} error error object if any 251 | */ 252 | // afterCommand: function (commandName, args, result, error) { 253 | // }, 254 | /** 255 | * Gets executed after all tests are done. You still have access to all global variables from 256 | * the test. 257 | * @param {Number} result 0 - test pass, 1 - test fail 258 | * @param {Array.} capabilities list of capabilities details 259 | * @param {Array.} specs List of spec file paths that ran 260 | */ 261 | // after: function (result, capabilities, specs) { 262 | // }, 263 | /** 264 | * Gets executed right after terminating the webdriver session. 265 | * @param {Object} config wdio configuration object 266 | * @param {Array.} capabilities list of capabilities details 267 | * @param {Array.} specs List of spec file paths that ran 268 | */ 269 | // afterSession: function (config, capabilities, specs) { 270 | // }, 271 | /** 272 | * Gets executed after all workers got shut down and the process is about to exit. An error 273 | * thrown in the onComplete hook will result in the test run failing. 274 | * @param {Object} exitCode 0 - success, 1 - fail 275 | * @param {Object} config wdio configuration object 276 | * @param {Array.} capabilities list of capabilities details 277 | * @param {} results object containing test results 278 | */ 279 | // onComplete: function(exitCode, config, capabilities, results) { 280 | // }, 281 | /** 282 | * Gets executed when a refresh happens. 283 | * @param {String} oldSessionId session ID of the old session 284 | * @param {String} newSessionId session ID of the new session 285 | */ 286 | //onReload: function(oldSessionId, newSessionId) { 287 | //} 288 | } 289 | --------------------------------------------------------------------------------