├── README.md ├── src ├── support │ ├── env.js │ ├── helper │ │ ├── string.js │ │ └── data-generator.js │ ├── hooks.js │ ├── config.js │ ├── context.js │ └── world.js └── step-definitions │ ├── data.js │ ├── modal.js │ ├── table.js │ ├── form.js │ └── page.js └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # angular-protractor-cucumber 2 | 3 | See doc in [Wiki](https://github.com/donkeycode/angular-protractor-cucumber/wiki) 4 | -------------------------------------------------------------------------------- /src/support/env.js: -------------------------------------------------------------------------------- 1 | var configure = function () { 2 | this.setDefaultTimeout(60 * 1000); 3 | }; 4 | 5 | module.exports = configure; 6 | -------------------------------------------------------------------------------- /src/support/helper/string.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function StringHelper() { 4 | return { 5 | /** 6 | * Returns running env 7 | * @returns {string} 8 | */ 9 | slugify: function (string) { 10 | return string.toLowerCase().replace(/[^a-z0-9]+/gi, '-'); 11 | } 12 | }; 13 | }(); 14 | -------------------------------------------------------------------------------- /src/support/helper/data-generator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var faker = require('faker'); 4 | 5 | module.exports = function DataGeneratorHelper() { 6 | var memorized_strings = {}; 7 | 8 | return { 9 | generate: function (category, type, mem) { 10 | if (memorized_strings[mem]) { 11 | return memorized_strings[mem]; 12 | } 13 | 14 | return memorized_strings[mem] = faker[category][type](); 15 | } 16 | }; 17 | }(); 18 | -------------------------------------------------------------------------------- /src/step-definitions/data.js: -------------------------------------------------------------------------------- 1 | var context = require('../support/context'); 2 | 3 | module.exports = function DataSteps() { 4 | 5 | /** 6 | * Load backend mockups 7 | */ 8 | this.Given(/^I use "([^"]*)" mocked database$/, function (mock, callback) { 9 | var databases = require(process.cwd() + '/test/e2e/support/databases/' + mock); 10 | databases.initialize(); 11 | context.database = databases; 12 | 13 | this.delayCallback(callback); 14 | }); 15 | 16 | }; 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-protractor-cucumber", 3 | "version": "0.1.28", 4 | "description": "A collection of sentences for cucumber js", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Cedric LOMBARDOT ", 10 | "license": "MIT", 11 | "dependencies": { 12 | "cucumber": "^1.3.0", 13 | "faker": "^3.1.0", 14 | "glob": "^6.0.1", 15 | "minimist": "^1.2.0", 16 | "protractor": "^4.0.9", 17 | "protractor-cucumber": "^0.1.6", 18 | "protractor-cucumber-junit": "^1.1.3", 19 | "protractor-cucumber-framework": "^0.6.0", 20 | "q": "^1.4.1", 21 | "selenium-server-standalone-jar": "^2.53.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/support/hooks.js: -------------------------------------------------------------------------------- 1 | var context = require('./context'); 2 | 3 | module.exports = function Hooks() { 4 | 5 | this.registerHandler('BeforeFeature', function (feature, callback) { 6 | context.setCurrentFeature(feature); 7 | 8 | callback(); 9 | }); 10 | 11 | /** 12 | * Clear database if mocked with HttpBackend 13 | */ 14 | this.registerHandler('AfterFeature', function (feature, callback) { 15 | if (context.database) { 16 | context.database.clear(); 17 | context.database = null; 18 | } 19 | 20 | callback(); 21 | }); 22 | 23 | this.registerHandler('BeforeScenario', function (scenario, callback) { 24 | context.setCurrentScenario(scenario); 25 | 26 | callback(); 27 | }); 28 | 29 | this.registerHandler('BeforeStep', function (step, callback) { 30 | context.setCurrentStep(step); 31 | 32 | callback(); 33 | }); 34 | }; 35 | -------------------------------------------------------------------------------- /src/step-definitions/modal.js: -------------------------------------------------------------------------------- 1 | var context = require('../support/context'); 2 | 3 | module.exports = function ModalSteps() { 4 | 5 | /* 6 | * Show a modal 7 | */ 8 | this.Then(/^I see the modal "([^"]*)"$/, function(modalName, callback) { 9 | var _this = this; 10 | var modalBody = element(by.css('body.modal-open')); 11 | 12 | modalBody.isPresent().then(function isOpen(result) { 13 | if (result !== true) { 14 | _this.handleError("Unable to retrieve element (Modal is not open). Binding: " + JSON.stringify(elementBinding) + ", currentPageInstance.url: " + context.getCurrentPageInstance().url, callback); 15 | } else { 16 | var titleBinding = element(by.binding(context.getCurrentPageInstance().getModalElement(modalName))); 17 | titleBinding.isPresent().then(function isPresentSuccess(result) { 18 | if (result !== true) { 19 | _this.handleError("Unable to retrieve element (Modal is not correct). Binding: " + JSON.stringify(by.css(context.getCurrentPageInstance().getModalElement(modalName))) + ", currentPageInstance.url: " + context.getCurrentPageInstance().url, callback); 20 | } else { 21 | _this.delayCallback(callback); 22 | } 23 | }); 24 | } 25 | }); 26 | }); 27 | 28 | /* 29 | * Accept the confirm modal 30 | */ 31 | this.Then(/^I accept confirm modal$/, function (callback) { 32 | _this = this; 33 | 34 | var button = element(by.css('.modal-content button[ng-click="confirm()"]')); 35 | 36 | if (button.isPresent()) { 37 | button.click(); 38 | _this.delayCallback(callback); 39 | } else { 40 | _this.handleError("Confirm button is not present", callback); 41 | } 42 | 43 | }); 44 | 45 | }; 46 | -------------------------------------------------------------------------------- /src/support/config.js: -------------------------------------------------------------------------------- 1 | var minimist = require('minimist'); 2 | 3 | 'use strict'; 4 | 5 | module.exports = function Config() { 6 | 7 | return { 8 | /** 9 | * DEV envrionment contant 10 | * @type {string} 11 | */ 12 | ENV_DEV: 'dev', 13 | 14 | /** 15 | * STAGE envrionment contant 16 | * @type {string} 17 | */ 18 | ENV_STAGE: 'jenkins', 19 | 20 | /** 21 | * Delay for callbacks 22 | * @type {number} 23 | */ 24 | delay: 5000, 25 | 26 | /** 27 | * Delay for callbacks 28 | * @type {number} 29 | */ 30 | jenkins_delay: 100, 31 | 32 | /** 33 | * Returns running env 34 | * @returns {string} 35 | */ 36 | getEnvironment: function () { 37 | return this.getArgv('env'); 38 | }, 39 | 40 | /** 41 | * Returns running routing mode (default /#/) can set to html5mode 42 | * @returns {string} 43 | */ 44 | getAngularMode: function () { 45 | return this.getArgv('angularMode') || 'default'; 46 | }, 47 | 48 | /** 49 | * Remove trailing slashes 50 | * @returns {string} 51 | */ 52 | keepTrailingSlash: function () { 53 | return this.getArgv('keepTrailingSlash') || false; 54 | }, 55 | 56 | /** 57 | * Get argument value in arv 58 | * @param {string} name of argument 59 | * @return undefinded if not found or agument value 60 | */ 61 | getArgv: function(name) { 62 | var args = minimist(process.argv); 63 | 64 | return args[name]; 65 | }, 66 | 67 | /** 68 | * Returns delay for callbacks 69 | * @returns {number} 70 | */ 71 | getDelay: function () { 72 | if (!!this.getArgv('delay')) { 73 | return this.getArgv('delay'); 74 | } 75 | 76 | if (!this.isDev()) { 77 | return this.jenkins_delay; 78 | } 79 | 80 | return this.delay; 81 | }, 82 | 83 | /** 84 | * Tells if we are in dev env 85 | * @returns {boolean} 86 | */ 87 | isDev: function () { 88 | return this.getEnvironment() === this.ENV_DEV; 89 | }, 90 | 91 | /** 92 | * Tells if we are in stage env 93 | * @returns {boolean} 94 | */ 95 | isStage: function () { 96 | return !this.isDev(); 97 | } 98 | }; 99 | }(); 100 | -------------------------------------------------------------------------------- /src/step-definitions/table.js: -------------------------------------------------------------------------------- 1 | var context = require('../support/context'); 2 | 3 | module.exports = function TableSteps() { 4 | this.Then(/^I can see "([^"]*)" for the first "([^"]*)" data$/, function(valueName, repeaterName, callback) { 5 | var _this = this; 6 | valueName = _this.generateValue(valueName); 7 | 8 | var objectData = context.getCurrentPageInstance().getTableByRepeater(repeaterName); 9 | var searchBy = by.repeater(objectData.ngRepeat).row(0).column(objectData.columnKey); 10 | var firstData = element(searchBy); 11 | _this.isPresentAndDisplayed(firstData).then(function isPresentAndDisplayedSuccess() { 12 | firstData.getText().then(function getTextSuccess(textFirstData) { 13 | if (textFirstData == valueName) { 14 | _this.delayCallback(callback); 15 | } else { 16 | _this.handleError("Doesn't match between " + valueName + " and first data text (" + firstData + ")", callback); 17 | } 18 | 19 | }, function getTextError(error) { 20 | _this.handleError("Doesn't find first data text " + firstData + " - " + error, callback); 21 | }); 22 | 23 | }, function isPresentAndDisplayedError(errorMessage) { 24 | _this.handleError("Doesn't find first data " + firstData + " - " + errorMessage, callback); 25 | }); 26 | }); 27 | 28 | /* 29 | * Check a value in a table 30 | */ 31 | this.Then(/^I see "([^"]*)" in the column "([^"]*)" of the row "([^"]*)" of the table "([^"]*)"$/, function (valueToMatch, columnToSearch, line, table, callback) { 32 | _this = this; 33 | valueToMatch = _this.generateValue(valueToMatch); 34 | 35 | var mappedTable = context.getCurrentPageInstance().getTableByRepeater(table); 36 | var mappedColumn = context.getCurrentPageInstance().getColumnByName(columnToSearch); 37 | 38 | var row = element(by.repeater(mappedTable).row(line - 1)); 39 | 40 | if (row.isPresent()) { 41 | var column = row.all(by.css('td')).get(mappedColumn - 1); 42 | 43 | if (column.isPresent()) { 44 | column.getText().then(function getValue(value) { 45 | if (value === valueToMatch) { 46 | _this.delayCallback(callback); 47 | } else { 48 | _this.handleError("Value mismatch : " + value + " / " + valueToMatch, callback); 49 | } 50 | }); 51 | } else { 52 | _this.handleError("Column is not present", callback); 53 | } 54 | } else { 55 | _this.handleError("Row is not present", callback); 56 | } 57 | 58 | }); 59 | 60 | /* 61 | * Click on an action button in a table 62 | */ 63 | this.When(/^I click on the action "([^"]*)" of the row "([^"]*)" of the table "([^"]*)"$/, function (action, line, table, callback) { 64 | _this = this; 65 | 66 | var mappedTable = context.getCurrentPageInstance().getTableByRepeater(table); 67 | var mappedColumn = context.getCurrentPageInstance().getColumnByName("actions"); 68 | var mappedAction = context.getCurrentPageInstance().getActionByClassName(action); 69 | 70 | var row = element(by.repeater(mappedTable).row(line - 1)); 71 | if (row.isPresent()) { 72 | var column = row.all(by.css('td')).get(mappedColumn - 1); 73 | 74 | if (column.isPresent()) { 75 | column.element(by.className(mappedAction)).click(); 76 | _this.delayCallback(callback); 77 | } else { 78 | _this.handleError("Column is not present", callback); 79 | } 80 | } else { 81 | _this.handleError("Row is not present", callback); 82 | } 83 | }); 84 | 85 | }; 86 | -------------------------------------------------------------------------------- /src/support/context.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var glob = require("glob"); 4 | var $q = require("q"); 5 | 6 | module.exports = function Context() { 7 | return { 8 | /** 9 | * Current page instance 10 | * @type {object} 11 | */ 12 | currentPageInstance: null, 13 | 14 | /** 15 | * Current running feature 16 | * @type {object} 17 | */ 18 | currentFeature: null, 19 | 20 | /** 21 | * Current running scenario 22 | * @type {object} 23 | */ 24 | currentScenario: null, 25 | 26 | /** 27 | * Current running step 28 | * @type {object} 29 | */ 30 | currentStep: null, 31 | 32 | /** 33 | * Httpbackend 34 | * @type {object} 35 | */ 36 | database: null, 37 | 38 | /** 39 | * Returns an instance of the given page 40 | * @param pageName 41 | * @returns {Promise} success(pageInstance), error(pageNotFoundMessage) 42 | */ 43 | loadPageInstance: function (pageName) { 44 | var deffered = $q.defer(); 45 | glob(process.cwd() + '/test/e2e/support/pages/**/' + pageName+".js", {}, function (er, files) { 46 | if (files.length === 0) { 47 | deffered.reject("Page "+pageName+" not found !"); 48 | 49 | throw "Page "+pageName+" not found !"; 50 | } 51 | 52 | var p = require(files[0]); 53 | 54 | deffered.resolve(p); 55 | }); 56 | 57 | return deffered.promise; 58 | }, 59 | 60 | /** 61 | * Returns current page instance 62 | * @returns {Object|context.currentPageInstance|*} 63 | */ 64 | getCurrentPageInstance: function () { 65 | return this.currentPageInstance; 66 | }, 67 | 68 | /** 69 | * Set current page instance 70 | * @param pageInstance 71 | * @returns {exports} 72 | */ 73 | setCurrentPageInstance: function (pageInstance) { 74 | this.currentPageInstance = pageInstance; 75 | 76 | return this; 77 | }, 78 | 79 | /** 80 | * Returns current running feature 81 | * @returns {Object|context.currentFeature|*} 82 | */ 83 | getCurrentFeature: function () { 84 | return this.currentFeature; 85 | }, 86 | 87 | /** 88 | * Set current running feature 89 | * @param feature 90 | * @returns {exports} 91 | */ 92 | setCurrentFeature: function (feature) { 93 | this.currentFeature = feature; 94 | 95 | return this; 96 | }, 97 | 98 | /** 99 | * Returns current running scenario 100 | * @returns {Object|context.currentScenario|*} 101 | */ 102 | getCurrentScenario: function () { 103 | return this.currentScenario; 104 | }, 105 | 106 | /** 107 | * Set current running scenario 108 | * @param scenario 109 | * @returns {exports} 110 | */ 111 | setCurrentScenario: function (scenario) { 112 | this.currentScenario = scenario; 113 | 114 | return this; 115 | }, 116 | 117 | /** 118 | * Returns current running step 119 | * @returns {Object|context.currentStep|*} 120 | */ 121 | getCurrentStep: function () { 122 | return this.currentStep; 123 | }, 124 | 125 | /** 126 | * Set current running step 127 | * @param step 128 | * @returns {exports} 129 | */ 130 | setCurrentStep: function (step) { 131 | this.currentStep = step; 132 | 133 | return this; 134 | } 135 | }; 136 | }(); 137 | -------------------------------------------------------------------------------- /src/support/world.js: -------------------------------------------------------------------------------- 1 | var $q = require('q'); 2 | var fs = require('fs'); 3 | var context = require('./context'); 4 | var config = require('./config'); 5 | var helperString = require('./helper/string'); 6 | var dataGenerator = require('./helper/data-generator'); 7 | 8 | 9 | module.exports = function () { 10 | 11 | this.World = function World() { 12 | 13 | /** 14 | * Check if an element is present and visible 15 | * @param {object} elementFinder 16 | * @returns {Promise} 17 | */ 18 | this.isPresentAndDisplayed = function (elementFinder) { 19 | var deferred = $q.defer(); 20 | 21 | elementFinder.isPresent().then(function isPresentSuccess(isPresent) { 22 | if (isPresent === true) { 23 | elementFinder.isDisplayed().then(function isDisplayedSuccess(isVisible) { 24 | if (isVisible === true) { 25 | deferred.resolve(); 26 | } else { 27 | deferred.reject("Element is present but not visible. Binding: " + JSON.stringify(elementFinder.locator()) + ", currentPageInstance.url: " + context.getCurrentPageInstance().url); 28 | } 29 | }, function isDisplayedFailure() { 30 | deferred.reject("Element is present but not visible. Binding: " + JSON.stringify(elementFinder.locator()) + ", currentPageInstance.url: " + context.getCurrentPageInstance().url); 31 | }); 32 | } else { 33 | deferred.reject("Unable to retrieve element. Binding: " + JSON.stringify(elementFinder.locator()) + ", currentPageInstance.url: " + context.getCurrentPageInstance().url); 34 | } 35 | }); 36 | 37 | return deferred.promise; 38 | }; 39 | 40 | /** 41 | * Visit the given page 42 | * @param {Promise} pageInstancePromise 43 | * @param {object} params 44 | * @param {function} callback 45 | * @returns {exports} 46 | */ 47 | this.visit = function (pageInstancePromise, params, callback) { 48 | var _this = this; 49 | 50 | this.tryVisit(pageInstancePromise, params, function (pageInstance) { 51 | _this.isOnPage(pageInstance, callback); 52 | }, false); 53 | 54 | return _this; 55 | }; 56 | 57 | /** 58 | * Change the default base Url 59 | * @param {string} newUrl 60 | * @returns {null} 61 | */ 62 | this.changeBaseUrl = function (newUrl) { 63 | browser.baseUrl = newUrl; 64 | }; 65 | 66 | /** 67 | * Refresh the current url 68 | * @returns {null} 69 | */ 70 | this.refresh = function () { 71 | return browser.driver.navigate().refresh(); 72 | }; 73 | 74 | /** 75 | * try Visit the given page without check is on page 76 | * @param {Promise} pageInstancePromise 77 | * @param {object} params 78 | * @param {function} callback 79 | * @returns {exports} 80 | */ 81 | this.tryVisit = function (pageInstancePromise, params, callback, simpleCallback) { 82 | var _this = this; 83 | if (simpleCallback === undefined) { 84 | simpleCallback = true; 85 | } 86 | 87 | pageInstancePromise.then(function onPageLoaded(pageInstance) { 88 | 89 | var finalUrl = pageInstance.url; 90 | for (var paramName in params) { 91 | finalUrl = finalUrl.replace(new RegExp("/:" + paramName + "/", "g"), "/" + params[paramName] + "/"); 92 | finalUrl = finalUrl.replace(new RegExp("/:" + paramName + "$", "g"), "/" + params[paramName]); 93 | } 94 | 95 | if (config.getAngularMode() === 'default') { 96 | finalUrl = '#/' + finalUrl; 97 | } 98 | 99 | browser.get(finalUrl).then(function () { 100 | context.setCurrentPageInstance(pageInstance); 101 | 102 | // we had test-mode class on body for specifics CSS rules (i.e. hide relative footer) 103 | browser.executeScript('document.querySelector("body").classList.add("test-mode");').then(function () { 104 | _this.delayCallback(function () { 105 | if (!simpleCallback) { 106 | return callback(pageInstance); 107 | } 108 | 109 | callback(); 110 | }); 111 | }); 112 | }); 113 | }); 114 | 115 | return _this; 116 | }; 117 | 118 | /** 119 | * Validate if we are on the expected page 120 | * @param pageInstance 121 | * @param callback 122 | * @returns {exports} 123 | */ 124 | this.isOnPage = function (pageInstance, callback) { 125 | var _this = this; 126 | 127 | browser.getCurrentUrl().then(function (url) { 128 | var splittedUrl = url.split("/#/"); 129 | 130 | if (config.getAngularMode() === 'html5mode') { 131 | splittedUrl = url.replace(/:\/\//, '[dash]').split(/\/(.+)/); 132 | if (!config.keepTrailingSlash() && url.slice(-1) === "/") { 133 | url = url.replace(/\/$/, ''); 134 | splittedUrl = url.replace(/:\/\//, '[dash]').split(/\/(.+)/); 135 | splittedUrl.push(""); 136 | } 137 | } 138 | 139 | var urlReg = new RegExp('^' + pageInstance.url.replace(/:[^\/]+/g, '(.+)').replace(/\//g, '\\/').replace("?", "\\?") + '$'); 140 | 141 | if (urlReg.test(splittedUrl[1]) === true) { 142 | _this.delayCallback(callback); 143 | } else { 144 | _this.handleError("isOnPage fails, pageInstance.url: " + pageInstance.url + ", url: " + url + ", splittedUrl: " + splittedUrl[1] + ", RegExp: " + urlReg.toString(), callback); 145 | } 146 | }); 147 | 148 | return _this; 149 | }; 150 | 151 | /** 152 | * Runs callback with a delay on dev environment 153 | * @param callback 154 | * @returns {exports} 155 | */ 156 | this.delayCallback = function (callback) { 157 | var _this = this; 158 | 159 | setTimeout(callback, config.getDelay()); 160 | 161 | return _this; 162 | }; 163 | 164 | /** 165 | * Error handler (take screenshot and call callback.fail()) 166 | * @param error 167 | * @param callback 168 | * @returns {exports} 169 | */ 170 | this.handleError = function (error, callback) { 171 | var _this = this; 172 | 173 | browser.takeScreenshot().then(function (imageData) { 174 | var formatFeature = helperString.slugify(context.getCurrentFeature().getName()); 175 | var formatScenario = helperString.slugify(context.getCurrentScenario().getName()); 176 | 177 | var token = formatFeature + '_' + formatScenario; 178 | var path = process.cwd() + '/logs/test/e2e/'; 179 | 180 | var pngStream = fs.createWriteStream(path + token + '_screenshot.png'); 181 | 182 | pngStream.write(new Buffer(imageData, 'base64')); 183 | pngStream.end(); 184 | 185 | _this.delayCallback(function handleErrorCallback() { 186 | callback(new Error(error)); 187 | }); 188 | }); 189 | 190 | return _this; 191 | }; 192 | 193 | /** 194 | * Generate values for fields 195 | */ 196 | this.generateValue = function (fieldValue) { 197 | if (fieldValue[0] != '@') { 198 | return fieldValue; 199 | } 200 | 201 | var functionToCall = fieldValue.replace('@', 'dataGenerator.generate'); 202 | 203 | return eval(functionToCall); 204 | }; 205 | }; 206 | }; 207 | -------------------------------------------------------------------------------- /src/step-definitions/form.js: -------------------------------------------------------------------------------- 1 | var context = require('../support/context'); 2 | 3 | module.exports = function FormSteps() { 4 | 5 | /** 6 | * Check select box by ngModel 7 | */ 8 | this.Then(/^I see "([^"]*)" select box filled with value "([^"]*)"$/, function (selectBox, value, callback) { 9 | var _this = this; 10 | var mappedNgModel = context.getCurrentPageInstance().getElementByNgModel(selectBox); 11 | 12 | var elementFinder = element(by.css(mappedNgModel)); 13 | 14 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 15 | elementFinder.element(by.css('option[selected=selected]')).getText().then(function getValue(fieldValue) { 16 | if (fieldValue === value) { 17 | _this.delayCallback(callback); 18 | } else { 19 | _this.handleError(fieldValue + " !== " + value, callback); 20 | } 21 | }); 22 | }, function isPresentAndDisplayedError(errorMessage) { 23 | _this.handleError(errorMessage, callback); 24 | }); 25 | }); 26 | 27 | /** 28 | * Click on a value on the mapped select box 29 | */ 30 | this.Then(/^I click on the select box "([^"]*)" to select "([^"]*)"$/, function (selectBox, value, callback) { 31 | var _this = this; 32 | var mappedNgModel = context.getCurrentPageInstance().getSelectBoxByNgModel(selectBox); 33 | var elementFinder = element(by.css(mappedNgModel)); 34 | 35 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 36 | elementFinder.click().then(function elementClickSuccess() { 37 | elementFinder.all(by.css('option')).then(function getOptions(options) { 38 | var nbOptions = options.length; 39 | var textOptions = ''; 40 | elementFinder.all(by.css('option')).each(function forEarchOption(option, index) { 41 | option.getText().then(function getTextSuccess(textOption){ 42 | textOptions += "'" + textOption + "', "; 43 | if (textOption === value){ 44 | option.click().then(function elementClickSuccess() { 45 | _this.delayCallback(callback); 46 | }); 47 | } 48 | if (index + 1 == nbOptions) { 49 | _this.handleError("Not found '" + value + "' value in select box options : " + textOptions, callback); 50 | } 51 | }); 52 | }, function allOptionsError(errorMessage){ 53 | _this.handleError("Not found '" + selectBox + "' select box options", callback); 54 | }); 55 | }); 56 | }); 57 | }, function isPresentAndDisplayedError(errorMessage) { 58 | _this.handleError(errorMessage, callback); 59 | }); 60 | }); 61 | 62 | /** 63 | * Put value for the field 64 | */ 65 | this.When(/^I fill "([^"]*)" field with "([^"]*)"$/, function (fieldName, fieldValue, callback) { 66 | var _this = this; 67 | 68 | var fieldIdSelector = context.getCurrentPageInstance().getFieldByName(fieldName); 69 | var elementFinder = element(by.css(fieldIdSelector)); 70 | 71 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 72 | elementFinder.clear().sendKeys(_this.generateValue(fieldValue)).then(function(){ 73 | _this.delayCallback(callback); 74 | }); 75 | 76 | }, function isPresentAndDisplayedError(errorMessage) { 77 | _this.handleError(errorMessage, callback); 78 | }); 79 | }); 80 | 81 | /** 82 | * Put value for the field in iframe 83 | */ 84 | this.When(/^I fill "([^"]*)" field with "([^"]*)" in iframe "([^"]*)"$/, function (fieldName, fieldValue, iframeElement, callback) { 85 | var _this = this; 86 | browser.ignoreSynchronization = true; 87 | 88 | var fieldIdSelector = context.getCurrentPageInstance().getFieldByName(fieldName); 89 | var elementFinder = element(by.css(fieldIdSelector)); 90 | 91 | var iframe = by.css(context.getCurrentPageInstance().getIframeByName(iframeElement)); 92 | element(iframe).getWebElement().then(function(frame) { 93 | browser.switchTo().frame(frame); 94 | 95 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 96 | elementFinder.clear().sendKeys(_this.generateValue(fieldValue)).then(function(){ 97 | browser.switchTo().defaultContent(); 98 | _this.delayCallback(callback); 99 | }); 100 | 101 | }, function isPresentAndDisplayedError(errorMessage) { 102 | _this.handleError(errorMessage, callback); 103 | }); 104 | }); 105 | }); 106 | 107 | /** 108 | * Put value for a ckeditor 109 | */ 110 | this.When(/^I fill "([^"]*)" ckeditor field with "([^"]*)"$/, function (fieldName, fieldValue, callback) { 111 | var fieldSelector = context.getCurrentPageInstance().getFieldByName(fieldName); 112 | var _this = this; 113 | var script = "CKEDITOR.instances." + fieldSelector + ".setData('" + fieldValue + "')"; 114 | browser.executeScript(script); 115 | _this.delayCallback(callback); 116 | }); 117 | 118 | /** 119 | * Check value in a ckeditor 120 | */ 121 | this.Then(/^I can see "([^"]*)" in ckeditor "([^"]*)"$/, function (valueObject, fieldName, callback) { 122 | var fieldSelector = context.getCurrentPageInstance().getFieldByName(fieldName); 123 | var _this = this; 124 | 125 | function getCkeditorData(fieldSelector) { 126 | return CKEDITOR.instances[fieldSelector].getData(); 127 | } 128 | 129 | browser.executeScript(getCkeditorData, fieldSelector).then(function isPresentAndDisplayedSuccess(contentField) { 130 | // remove new lines 131 | contentField = contentField.replace(/(\r\n|\n|\r)/gm,""); 132 | if (contentField === valueObject) { 133 | _this.delayCallback(callback); 134 | } else { 135 | _this.handleError("contentField and valueObject doesn't match. contentField: " + contentField + ", valueObject: " + valueObject + ", currentPageInstance.url: " + context.getCurrentPageInstance().url, callback); 136 | } 137 | }, function isPresentAndDisplayedError(errorMessage) { 138 | _this.handleError(errorMessage, callback); 139 | }); 140 | }); 141 | 142 | /** 143 | * Put value for the time field 144 | */ 145 | this.When(/^I fill "([^"]*)" time field with "([^"]*)"$/, function (fieldName, fieldValue, callback) { 146 | var _this = this; 147 | 148 | var fieldIdSelector = context.getCurrentPageInstance().getFieldByName(fieldName); 149 | var elementFinder = element(by.css(fieldIdSelector)); 150 | 151 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 152 | elementFinder.sendKeys(_this.generateValue(fieldValue)).then(function(){ 153 | _this.delayCallback(callback); 154 | }); 155 | 156 | }, function isPresentAndDisplayedError(errorMessage) { 157 | _this.handleError(errorMessage, callback); 158 | }); 159 | }); 160 | 161 | /** 162 | * Put value for the timepicker 163 | */ 164 | this.When(/^I fill "([^"]*)" datepicker with "([^"]*)"$/, function (fieldName, fieldValue, callback) { 165 | var _this = this; 166 | 167 | var fieldIdSelector = context.getCurrentPageInstance().getFieldByName(fieldName); 168 | var elementFinder = element(by.css(fieldIdSelector)); 169 | 170 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 171 | elementFinder.sendKeys(_this.generateValue(fieldValue)).then(function(){ 172 | _this.delayCallback(callback); 173 | }); 174 | 175 | }, function isPresentAndDisplayedError(errorMessage) { 176 | _this.handleError(errorMessage, callback); 177 | }); 178 | }); 179 | 180 | /** 181 | * Check field error message with key translate 182 | */ 183 | this.Then(/^I see "([^"]*)" error for "([^"]*)" field$/, function (messageName, fieldName, callback) { 184 | var _this = this; 185 | 186 | var errorMessageTranslateKey = context.getCurrentPageInstance().getErrorMessageByField(fieldName, messageName); 187 | 188 | var fieldSelector = context.getCurrentPageInstance().getFieldByName(fieldName); 189 | var fieldElementFinder = element(by.css(fieldSelector)); 190 | 191 | _this.isPresentAndDisplayed(fieldElementFinder).then(function isPresentAndDisplayedSuccess() { 192 | fieldElementFinder.getWebElement().findElement(by.xpath('ancestor::div[contains(@class, "form-group")]')).then(function findFormGroupSuccess(formGroupWebElement) { 193 | formGroupWebElement.findElement(by.css('div[al-error-message][translate-key="' + errorMessageTranslateKey + '"]:not(.ng-hide)')).then(function onErrorMessageFound() { 194 | _this.delayCallback(callback); 195 | }, function onErrorMessageNotFound() { 196 | return _this.handleError("Error '" + errorMessageTranslateKey + "' not found for '" + fieldName + "' field. currentPageInstance.url: " + context.getCurrentPageInstance().url, callback); 197 | }); 198 | }, function findFormGroupError() { 199 | return _this.handleError("Unable to retrieve formGroup element for '" + fieldName + "' field. currentPageInstance.url: " + context.getCurrentPageInstance().url, callback); 200 | }); 201 | }, function isPresentAndDisplayedError(errorMessage) { 202 | _this.handleError(errorMessage, callback); 203 | }); 204 | }); 205 | 206 | /** 207 | * Check format value 208 | */ 209 | this.Then(/^I see "([^"]*)" select box values match format "([^"]*)"$/, function (selectBox, format, callback) { 210 | var _this = this; 211 | var mappedNgModel = context.getCurrentPageInstance().getElementByNgModel(selectBox); 212 | var mappedFormat = context.getCurrentPageInstance().getFormatByName(format); 213 | var elementFinder = element(by.css(mappedNgModel)); 214 | 215 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 216 | var formatIsCorrect = true; 217 | 218 | element.all(by.css(mappedNgModel + ' option')).each(function forEachElement(element) { 219 | element.getText().then(function getValue(value) { 220 | if (!new RegExp(mappedFormat).test(value)) { 221 | formatIsCorrect = false; 222 | } 223 | }); 224 | }); 225 | 226 | if (formatIsCorrect) { 227 | _this.delayCallback(callback); 228 | } else { 229 | _this.handleError("One of the value is incorrectly formated", callback); 230 | } 231 | }, function isPresentAndDisplayedError(errorMessage) { 232 | _this.handleError(errorMessage, callback); 233 | }); 234 | }); 235 | 236 | }; 237 | -------------------------------------------------------------------------------- /src/step-definitions/page.js: -------------------------------------------------------------------------------- 1 | var context = require('../support/context'); 2 | 3 | module.exports = function PageSteps() { 4 | this.Then(/^I wait ([^"]*) seconds$/, function (time, callback) { 5 | var _this = this; 6 | setTimeout(function() { 7 | _this.delayCallback(callback) 8 | }, time * 1000); 9 | }); 10 | 11 | /** 12 | * Try go to the given page 13 | */ 14 | this.Given(/^I try visit the page "([^"]*)"$/, function (pageName, callback) { 15 | this.tryVisit(context.loadPageInstance(pageName), {}, callback); 16 | }); 17 | 18 | /** 19 | * Refresh the current Url 20 | */ 21 | this.Given(/^I refresh the page$/, function (callback) { 22 | var _this = this; 23 | this.refresh().then(function(){ 24 | _this.delayCallback(callback); 25 | }); 26 | }); 27 | 28 | /** 29 | * Redirect to the given page 30 | */ 31 | this.Given(/^I am on the "([^"]*)"$/, function (pageName, callback) { 32 | this.visit(context.loadPageInstance(pageName), {}, callback); 33 | }); 34 | 35 | /** 36 | * Redirect to the given page changing base url 37 | */ 38 | this.Given(/^I am on the "([^"]*)" of the domain "([^"]*)"$/, function (pageName, pageBaseDomain, callback) { 39 | var helper = require(process.cwd() + '/test/e2e/support/helper/model/domain'); 40 | this.changeBaseUrl(helper.get(pageBaseDomain)); 41 | this.visit(context.loadPageInstance(pageName), {}, callback); 42 | }); 43 | 44 | /** 45 | * Redirect to the given page 46 | */ 47 | this.Given(/^I am on the "([^"]*)" of ([a-z0-9]+) "([^"]*)"$/, function (pageName, objectName, param, callback) { 48 | var helper = require(process.cwd() + '/test/e2e/support/helper/model/' + objectName); 49 | 50 | this.visit(context.loadPageInstance(pageName), helper.get(param), callback); 51 | }); 52 | 53 | /** 54 | * Click on a button 55 | */ 56 | this.When(/^I click on the button "([^"]*)"$/, function (buttonName, callback) { 57 | var _this = this; 58 | 59 | var elementBinding = by.css(context.getCurrentPageInstance().getButtonByName(buttonName)); 60 | var elementFinder = element(elementBinding); 61 | 62 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 63 | elementFinder.click().then(function elementClickSuccess() { 64 | _this.delayCallback(callback); 65 | }); 66 | }, function isPresentAndDisplayedError(errorMessage) { 67 | _this.handleError(errorMessage, callback); 68 | }); 69 | }); 70 | 71 | /** 72 | * Click on a button and accept/dismiss the popup 73 | */ 74 | this.When(/^I click on the button "([^"]*)" and ([^"]*) the popup$/, function (buttonName, action, callback) { 75 | var _this = this; 76 | 77 | var elementBinding = by.css(context.getCurrentPageInstance().getButtonByName(buttonName)); 78 | var elementFinder = element(elementBinding); 79 | 80 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 81 | elementFinder.click().then(function elementClickSuccess() { 82 | // thread sleep before switch 83 | setTimeout(function() { 84 | if (action !== "accept" && action !== "dismiss") { 85 | browser.switchTo().alert().dismiss(); 86 | _this.handleError("Action " + action + " unknown", callback); 87 | return; 88 | } 89 | if (action === "accept") { 90 | browser.switchTo().alert().accept(); 91 | } 92 | if (action === "dismiss") { 93 | browser.switchTo().alert().dismiss(); 94 | } 95 | _this.delayCallback(callback); 96 | }, 200); 97 | }); 98 | }, function isPresentAndDisplayedError(errorMessage) { 99 | _this.handleError(errorMessage, callback); 100 | }); 101 | }); 102 | 103 | /** 104 | * See a button 105 | */ 106 | this.Then(/^I should see the button "([^"]*)"$/, function (buttonName, callback) { 107 | var _this = this; 108 | 109 | var elementBinding = by.css(context.getCurrentPageInstance().getButtonByName(buttonName)); 110 | var elementFinder = element(elementBinding); 111 | 112 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 113 | _this.delayCallback(callback); 114 | }, function isPresentAndDisplayedError(errorMessage) { 115 | _this.handleError(errorMessage, callback); 116 | }); 117 | }); 118 | 119 | /** 120 | * See a diabled button 121 | */ 122 | this.Then(/^I should see the button "([^"]*)" disabled$/, function (buttonName, callback) { 123 | var _this = this; 124 | 125 | var elementBinding = by.css(context.getCurrentPageInstance().getButtonByName(buttonName)); 126 | var elementFinder = element(elementBinding); 127 | 128 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 129 | elementFinder.isEnabled().then(function isDisplayedSuccess(isEnabled) { 130 | if(!isEnabled) { 131 | return _this.delayCallback(callback); 132 | } 133 | 134 | _this.handleError("Button "+ buttonName +" present but enabled", callback); 135 | }); 136 | }, function isPresentAndDisplayedError(errorMessage) { 137 | _this.handleError(errorMessage, callback); 138 | }); 139 | }); 140 | 141 | /** 142 | * See an enabled button 143 | */ 144 | this.Then(/^I should see the button "([^"]*)" enabled$/, function (buttonName, callback) { 145 | var _this = this; 146 | 147 | var elementBinding = by.css(context.getCurrentPageInstance().getButtonByName(buttonName)); 148 | var elementFinder = element(elementBinding); 149 | 150 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 151 | elementFinder.isEnabled().then(function isDisplayedSuccess(isEnabled) { 152 | if(isEnabled) { 153 | return _this.delayCallback(callback); 154 | } 155 | 156 | _this.handleError("Button "+ buttonName +" present but enabled", callback); 157 | }); 158 | }, function isPresentAndDisplayedError(errorMessage) { 159 | _this.handleError(errorMessage, callback); 160 | }); 161 | }); 162 | 163 | /** 164 | * Not see a button 165 | */ 166 | this.Then(/^I should not see the button "([^"]*)"$/, function (buttonName, callback) { 167 | var _this = this; 168 | 169 | var elementBinding = by.css(context.getCurrentPageInstance().getButtonByName(buttonName)); 170 | var elementFinder = element(elementBinding); 171 | 172 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 173 | _this.handleError("Button found", callback); 174 | }, function isPresentAndDisplayedError() { 175 | _this.delayCallback(callback); 176 | }); 177 | }); 178 | 179 | /** 180 | * Click on a tab 181 | */ 182 | this.When(/^I click on the tab "([^"]*)"$/, function (tagName, callback) { 183 | var _this = this; 184 | 185 | var elementBinding = by.css(context.getCurrentPageInstance().getTabByName(tagName)); 186 | var elementFinder = element(elementBinding); 187 | 188 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 189 | elementFinder.click().then(function elementClickSuccess() { 190 | _this.delayCallback(callback); 191 | }); 192 | }, function isPresentAndDisplayedError(errorMessage) { 193 | _this.handleError(errorMessage, callback); 194 | }); 195 | }); 196 | 197 | /** 198 | * Check the current page 199 | */ 200 | this.Then(/^I should be redirected on "([^"]*)"$/, function (pageName, callback) { 201 | var _this = this; 202 | 203 | context.loadPageInstance(pageName).then(function onPageLoaded(pageInstance) { 204 | context.setCurrentPageInstance(pageInstance); 205 | 206 | _this.isOnPage(pageInstance, callback); 207 | }); 208 | }); 209 | 210 | /** 211 | * Check content page in data line (form) 212 | */ 213 | this.Then(/^I can see "([^"]*)" at line "([^"]*)"$/, function (valueObject, keyObject, callback) { 214 | var _this = this; 215 | valueObject = _this.generateValue(valueObject); 216 | 217 | var keyBinding = by.css(context.getCurrentPageInstance().getFieldByName(keyObject)); 218 | var elementFinder = element(keyBinding); 219 | 220 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 221 | elementFinder.element(by.css('.like-input span')).getText().then(function (contentField) { 222 | if (contentField === valueObject) { 223 | _this.delayCallback(callback); 224 | } else { 225 | _this.handleError("contentField and valueObject doesn't match. contentField: " + contentField + ", valueObject: " + valueObject + ", Binding: " + JSON.stringify(keyBinding) + ", currentPageInstance.url: " + context.getCurrentPageInstance().url, callback); 226 | } 227 | }); 228 | }, function isPresentAndDisplayedError(errorMessage) { 229 | _this.handleError(errorMessage, callback); 230 | }); 231 | }); 232 | 233 | /** 234 | * Check content page (in line) 235 | */ 236 | this.Then(/^I can see "([^"]*)" in element "([^"]*)"$/, function (valueObject, nameElement, callback) { 237 | var _this = this; 238 | valueObject = _this.generateValue(valueObject); 239 | 240 | var keyBinding = by.css(context.getCurrentPageInstance().getElementByName(nameElement)); 241 | var elementFinder = element(keyBinding); 242 | 243 | // escape double quotes 244 | valueObject = valueObject.replace(/''/g, '"'); 245 | 246 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 247 | elementFinder.getText().then(function (contentField) { 248 | if (contentField === valueObject) { 249 | _this.delayCallback(callback); 250 | } else { 251 | _this.handleError("contentField and valueObject doesn't match. contentField: " + contentField + ", valueObject: " + valueObject + ", Binding: " + JSON.stringify(keyBinding) + ", currentPageInstance.url: " + context.getCurrentPageInstance().url, callback); 252 | } 253 | }); 254 | }, function isPresentAndDisplayedError(errorMessage) { 255 | _this.handleError(errorMessage, callback); 256 | }); 257 | }); 258 | 259 | /** 260 | * Check content input 261 | */ 262 | this.Then(/^I can see "([^"]*)" in input "([^"]*)"$/, function (valueObject, nameElement, callback) { 263 | var _this = this; 264 | valueObject = _this.generateValue(valueObject); 265 | 266 | var keyBinding = by.css(context.getCurrentPageInstance().getElementByName(nameElement)); 267 | var elementFinder = element(keyBinding); 268 | 269 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 270 | elementFinder.getAttribute('value').then(function (value) { 271 | if (value === valueObject) { 272 | _this.delayCallback(callback); 273 | } else { 274 | _this.handleError("contentField and valueObject doesn't match. value: " + value + ", valueObject: " + valueObject + ", Binding: " + JSON.stringify(keyBinding) + ", currentPageInstance.url: " + context.getCurrentPageInstance().url, callback); 275 | } 276 | }); 277 | }, function isPresentAndDisplayedError(errorMessage) { 278 | _this.handleError(errorMessage, callback); 279 | }); 280 | }); 281 | 282 | /** 283 | * Check content iframe 284 | */ 285 | this.Then(/^I can see "([^"]*)" in element "([^"]*)" in iframe "([^"]*)"$/, function (valueObject, nameElement, iframeElement, callback) { 286 | var _this = this; 287 | valueObject = _this.generateValue(valueObject); 288 | browser.ignoreSynchronization = true; 289 | 290 | var iframe = by.css(context.getCurrentPageInstance().getIframeByName(iframeElement)); 291 | element(iframe).getWebElement().then(function(frame) { 292 | browser.switchTo().frame(frame); 293 | 294 | var keyBinding = by.css(context.getCurrentPageInstance().getElementByName(nameElement)); 295 | var elementFinder = element(keyBinding); 296 | 297 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 298 | elementFinder.getText().then(function (contentField) { 299 | if (contentField === valueObject) { 300 | _this.delayCallback(callback); 301 | } else { 302 | _this.handleError("contentField and valueObject doesn't match. contentField: " + contentField + ", valueObject: " + valueObject + ", Binding: " + JSON.stringify(keyBinding) + ", currentPageInstance.url: " + context.getCurrentPageInstance().url, callback); 303 | } 304 | }); 305 | }, function isPresentAndDisplayedError(errorMessage) { 306 | _this.handleError(errorMessage, callback); 307 | }); 308 | }); 309 | }); 310 | 311 | /** 312 | * Check content page with binding 313 | */ 314 | this.Then(/^I can see "([^"]*)" for data "([^"]*)"$/,function (textWanted, keyName, callback) { 315 | var _this = this; 316 | 317 | textWanted = _this.generateValue(textWanted); 318 | var keyBinding = by.binding(context.getCurrentPageInstance().getBindingByName(keyName)); 319 | var elementFinder = element(keyBinding); 320 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 321 | elementFinder.getText().then(function getTextSuccess(textElementBinding) { 322 | if (textElementBinding === textWanted) { 323 | _this.delayCallback(callback); 324 | } else { 325 | _this.handleError("Not match betwen text element binding " + textElementBinding + " and wanted text " + textWanted, callback); 326 | } 327 | 328 | }, function getTextError() { 329 | _this.handleError("Not find text element binding " + keyBinding + " " + error, callback); 330 | }); 331 | 332 | }, function isPresentAndDisplayed(error) { 333 | _this.handleError("Not find element binding " + keyBinding + " " + error, callback); 334 | }); 335 | }); 336 | 337 | /** 338 | * Check content page in frame (text with key translate) 339 | */ 340 | this.Then(/^I can see text "([^"]*)" at frame "([^"]*)"$/, function (valueObject, nameFrame, callback) { 341 | var _this = this; 342 | valueObject = _this.generateValue(valueObject); 343 | 344 | var keyBinding = by.css(context.getCurrentPageInstance().getContainerByName(nameFrame)); 345 | var elementFinder = element(keyBinding); 346 | 347 | _this.isPresentAndDisplayed(elementFinder).then(function isPresentAndDisplayedSuccess() { 348 | elementFinder.element(by.css(context.getCurrentPageInstance().getTextByName(valueObject))).then(function (contentField) { 349 | _this.delayCallback(callback); 350 | }); 351 | }, function isPresentAndDisplayedError(errorMessage) { 352 | _this.handleError(errorMessage, callback); 353 | }); 354 | 355 | }); 356 | 357 | /** 358 | * scroll down 359 | */ 360 | this.When(/^I scroll (down|up)$/, function (direction, callback) { 361 | var _this = this; 362 | if (direction === 'down') { 363 | browser.executeScript('window.scrollTo(0,100000);'); 364 | } else { 365 | browser.executeScript('window.scrollTo(0,0);'); 366 | } 367 | _this.delayCallback(callback); 368 | }); 369 | 370 | /** 371 | * scroll down 372 | */ 373 | this.When(/^I scroll to "([^"]*)"$/, function (elementClass, callback) { 374 | var _this = this; 375 | var location = context.getCurrentPageInstance().getLocationByName(elementClass); 376 | var elementFinder = element(by.css(location)); 377 | 378 | elementFinder.getLocation().then(function locate(elementLocation) { 379 | browser.executeScript('window.scrollTo(0, 0);'); 380 | browser.executeScript('window.scrollTo(' + elementLocation.x + ',' + elementLocation.y + ');'); 381 | _this.delayCallback(callback); 382 | }); 383 | }); 384 | 385 | /** 386 | * Check if element is present 387 | */ 388 | this.Then(/^I should see element "([^"]*)"$/, function (elementClass, callback) { 389 | var _this = this; 390 | var mappedElement = context.getCurrentPageInstance().getElementByClass(elementClass); 391 | 392 | var elementFinder = element(by.css(mappedElement)); 393 | 394 | _this.isPresentAndDisplayed(elementFinder).then(function isPresent() { 395 | _this.delayCallback(callback); 396 | }, function isNotPresent() { 397 | _this.handleError("Element '" + mappedElement + "' is present", callback); 398 | }); 399 | }); 400 | 401 | /** 402 | * Check if element is present 403 | */ 404 | this.Then(/^I should not see element "([^"]*)"$/, function (elementClass, callback) { 405 | var _this = this; 406 | var mappedElement = context.getCurrentPageInstance().getElementByClass(elementClass); 407 | 408 | var elementFinder = element(by.css(mappedElement)); 409 | 410 | _this.isPresentAndDisplayed(elementFinder).then(function isPresent() { 411 | _this.handleError("Element '" + mappedElement + "' is present", callback); 412 | }, function isNotPresent() { 413 | _this.delayCallback(callback); 414 | }); 415 | }); 416 | }; 417 | --------------------------------------------------------------------------------