UNPKG

@openveo/test

Version:
1,873 lines (1,596 loc) 69.2 kB
'use strict'; /** * @module e2e/pages/TablePage */ var util = require('util'); var browserExt = process.requireTest('lib/e2e/browser.js'); var BackEndPage = process.requireTest('lib/e2e/pages/BackEndPage.js'); /** * Defines a TablePage representing a back end page with a table and form to add an entity. * * Do not use this directly but extend it. * * @example * var TablePage = require('@openveo/test').e2e.pages.TablePage; * * function MyTablePage() { * MyTablePage.super_.call(this); * this.path = 'be/myTablePage'; * } * * module.exports = MyTablePage; * util.inherits(MyTablePage, TablePage); * * var page = new MyTablePage(); * page.logAsAdmin(); * page.load().then(function() { * console.log('Page fully loaded in the first language'); * }); * * @class TablePage * @extends module:e2e/pages/BackEndPage~BackEndPage * @constructor * @param {Object} provider Provider to interact directly with the database */ function TablePage(provider) { TablePage.super_.call(this); var tableSelector = '.datatable div[tasty-table] > table'; var addFormElement = element(by.css('.add-form')); var addLinkElement = element(by.css('.add-element')); var tableElement = element(by.css(tableSelector)); var dialogElement = element(by.css('.modal-dialog')); var paginationElement = element(by.css('.pagination')); var paginationLinkElements = paginationElement.all(by.css('li')); Object.defineProperties(this, /** @lends module:e2e/pages/TablePage~TablePage */ { /** * The entity provider. * * @type {Object} * @instance * @readonly */ provider: {value: provider}, /** * Form element to add a new entity. * * @type {Object} * @instance * @readonly */ addFormElement: {value: addFormElement}, /** * Link to open / close form element to add a new entity. * * @type {Object} * @instance * @readonly */ addLinkElement: {value: addLinkElement}, /** * Wrapper of the add form element. * * This element will be displayed when add form is displayed and hidden when add form is closed. * * @type {Object} * @instance * @readonly */ addFormWrapperElement: { value: addLinkElement.element(by.xpath('..')).all(by.css('div[uib-collapse="isCollapsed"]')).first() }, /** * Submit button of the form to add a new entity. * * @type {Object} * @instance * @readonly */ addButtonElement: {value: addFormElement.element(by.css('button'))}, /** * Table element. * * @type {Object} * @instance * @readonly */ tableElement: {value: tableElement}, /** * Table row elements. * * @type {Object} * @instance * @readonly */ rowElements: {value: element.all(by.css(tableSelector + ' > tbody > tr'))}, /** * Table header elements. * * @type {Object} * @instance * @readonly */ headerElements: {value: element.all(by.css(tableSelector + ' > thead th'))}, /** * Opened line detail containing information about the opened line. * * @type {Object} * @instance * @readonly */ lineDetailElement: {value: element(by.css(tableSelector + ' > tbody > tr.detail'))}, /** * Checkbox to select all line. * * @type {Object} * @instance * @readonly */ selectAllElement: {value: element(by.css('.allactions input[type="checkbox"]'))}, /** * Main action button element to perform actions on all selected lines. * * @type {Object} * @instance * @readonly */ actionsButtonElement: {value: element(by.css('.allactions button'))}, /** * Element holding the list of actions under main action button. * * @type {Object} * @instance * @readonly */ actionsElement: {value: element(by.css('.allactions ul'))}, /** * Dialog box. * * @type {Object} * @instance * @readonly */ dialogElement: {value: dialogElement}, /** * Dialog box confirmation button. * * @type {Object} * @instance * @readonly */ dialogConfirmActionButtonElement: {value: dialogElement.element(by.css('.btn-primary'))}, /** * Dialog box cancel button. * * @type {Object} * @instance * @readonly */ dialogCancelActionButtonElement: {value: dialogElement.element(by.css('.btn-warning'))}, /** * Search engine form to filter lines in the table. * * @type {Object} * @instance * @readonly */ searchFormElement: {value: element(by.css('.search-fields'))}, /** * Link to open / close search engine. * * @type {Object} * @instance * @readonly */ searchLinkElement: {value: element(by.css('.search-title'))}, /** * Element holding the current table page (pagination). * * @type {Object} * @instance * @readonly */ currentPageElement: {value: element(by.exactBinding('pagination.page'))}, /** * Element holding the total number of table pages (pagination). * * @type {Object} * @instance * @readonly */ totalPagesElement: {value: element(by.exactBinding('pagination.pages'))}, /** * Element holding the total number of lines in all table pages (pagination). * * @type {Object} * @instance * @readonly */ totalLinesElement: {value: element(by.exactBinding('pagination.size'))}, /** * Pagination links wrapper. * * @type {Object} * @instance * @readonly */ paginationElement: {value: element(by.css('.pagination'))}, /** * List of pagination links, including the previous and next range buttons. * * @type {Object} * @instance * @readonly */ paginationLinkElements: {value: paginationLinkElements}, /** * List of pagination links, excluding the previous and next range buttons. * * @type {Object} * @instance * @readonly */ paginationPageLinkElements: {value: paginationElement.all(by.repeater('numPage in rangePage')).all(by.css('a'))}, /** * Pagination previous range link. * * @type {Object} * @instance * @readonly */ paginationPreviousRangeElement: {value: paginationLinkElements.first()}, /** * Pagination next range link. * * @type {Object} * @instance * @readonly */ paginationNextRangeElement: {value: paginationLinkElements.last()}, /** * List of per page links to select the number of elements to display per table page. * * @type {Object} * @instance * @readonly */ itemsPerPageLinkElements: {value: element.all(by.repeater('count in listItemsPerPageShow'))} } ); } module.exports = TablePage; util.inherits(TablePage, BackEndPage); /** * Finds a line. * * Iterate through the given list of lines to look for the expected one. * * @private * @method getLineByIndex * @memberof module:e2e/pages/TablePage~TablePage * @this module:e2e/pages/TablePage~TablePage * @param {Array} lines The list of line elements (tr elements) to look into * @param {String} name The name of the line to look for (this value will be compared to the value of each cell) * @param {Number} [index] The index in lines to start from * @return {Promise} Promise resolving with the tr element */ function getLineByIndex(lines, name, index) { index = index || 0; var deferred = protractor.promise.defer(); var self = this; if (index < lines.length && lines.length) { var line = lines[index]; self.lineCellContain(line, name).then(function(contain) { if (contain) { // Line found deferred.fulfill(line); } else { // Line not found // Try next line getLineByIndex.call(self, lines, name, ++index).then(function(elements) { deferred.fulfill(elements); }, function(error) { deferred.reject(error); }); } }); } else deferred.reject(new Error('No lines corresponding to ' + name)); return deferred.promise; } /** * Finds a line by page. * * Iterate through all lines of all pages to look for the expected line. * It starts at current page. * * @private * @method getLineByPage * @memberof module:e2e/pages/TablePage~TablePage * @this module:e2e/pages/TablePage~TablePage * @param {String} name The name of the line to look for (this value will be compared to the value of each cell) * @param {Number} totalPages The total number of pages * @return {Promise} Promise resolving with the searched line (tr element) */ function getLineByPage(name, totalPages) { var self = this; var deferred = protractor.promise.defer(); this.getLineInPage(name).then(function(line) { // Line find in current page deferred.fulfill(line); }, function(error) { // Line not found in current page self.getCurrentPage().then(function(currentPage) { if ((currentPage + 1) <= totalPages) { // Got more pages // Select next page return self.selectPage(currentPage + 1).then(function() { // Get line in page return getLineByPage.call(self, name, totalPages); }); } else { // No more page, line has not been found return protractor.promise.rejected(new Error('No lines corresponding to ' + name)); } }).then(function(line) { deferred.fulfill(line); }, function(error) { deferred.reject(error); }); }); return deferred.promise; } /** * Selects a page. * * Look for page link in pagination links, if page link is not in the pagination actual range, it will search for * the page link in the other pagination ranges. * * @private * @method selectPageByRange * @memberof module:e2e/pages/TablePage~TablePage * @this module:e2e/pages/TablePage~TablePage * @param {String} page The page to select (starting at 1 instead of 0) * @return {Promise} Promise resolving when the page is selected */ function selectPageByRange(page) { var self = this; var deferred = protractor.promise.defer(); // Filter the list of pagination links to get the link corresponding to the page this.paginationPageLinkElements.filter(function(element, index) { return element.all(by.css('span')).first().getText().then(function(text) { return text.replace(/ ?\(current\)/, '') == page; }); }).then(function(links) { if (links.length) { // Page link found // Click on it browserExt.click(links[0]).then(function() { deferred.fulfill(); }); } else { // Page link not found self.isNextRangeLinkEnabled().then(function(isEnabled) { if (isEnabled) { // There is a next range // Select next range self.selectNextPageRange(); // Try to find the page in the next range return selectPageByRange.call(self, page); } else { // Already in last range // Page link not found return protractor.promise.rejected(new Error('No page ' + page + ' found')); } }).then(function() { deferred.fulfill(); }, function(error) { deferred.reject(error); }); } }); return deferred.promise; } /** * Gets the index of a table column in the list of columns. * * @private * @method getHeaderIndex * @memberof module:e2e/pages/TablePage~TablePage * @this module:e2e/pages/TablePage~TablePage * @param {String} name The name of the header to look for * @return {Promise} Promise resolving with the index of the column */ function getHeaderIndex(name) { var self = this; return browser.waitForAngular().then(function() { var deferred = protractor.promise.defer(); var headerIndex = -1; self.headerElements.each(function(thElement, index) { thElement.getText().then(function(text) { if (text === name) headerIndex = index; }); }).then(function() { if (headerIndex >= 0) deferred.fulfill(headerIndex); else deferred.reject(new Error('Table header "' + name + '" not found')); }); return deferred.promise; }); } /** * Gets column value for a list of lines. * * Iterates through the given list of lines and find its value in the given column. * * @private * @method getLineValuesByIndex * @memberof module:e2e/pages/TablePage~TablePage * @this module:e2e/pages/TablePage~TablePage * @param {Array} lines The lines in the page (tr elements) * @param {Number} headerIndex The index of the column to read * @param {Number} [index=0] Current line index being inspected * @return {Promise} Promise resolving with lines values */ function getLineValuesByIndex(lines, headerIndex, index) { index = index || 0; var self = this; var deferred = protractor.promise.defer(); var values = []; var line = lines[index]; self.getLineCellValue(line, headerIndex).then(function(text) { values.push(text); if ((index + 1) < lines.length) { return getLineValuesByIndex.call(self, lines, headerIndex, ++index); } else { deferred.fulfill(values); return protractor.promise.rejected(new Error('No more lines')); } }).then(function(newValues) { values = values.concat(newValues); deferred.fulfill(values); }).then(null, function(error) { // Nothing to do, promise is rejected but it's not an error }); return deferred.promise; } /** * Gets column and field values for a list of lines. * * Iterates through the given list of lines and get all information (column values and field values) for each line. * * @private * @method getAllLineDetailsByIndex * @memberof module:e2e/pages/TablePage~TablePage * @this module:e2e/pages/TablePage~TablePage * @param {Array} lines The lines in the page (tr elements) * @param {Number} [index=0] Current line index being inspected * @return {Promise} Promise resolving with values */ function getAllLineDetailsByIndex(lines, index) { index = index || 0; var self = this; var deferred = protractor.promise.defer(); var datas = []; var line = lines[index]; this.getLineDetails(line).then(function(details) { datas.push(details); if ((index + 1) < lines.length) { // Got more lines // Go to next line return getAllLineDetailsByIndex.call(self, lines, ++index); } else { // No more lines return protractor.promise.fulfilled(); } }).then(function(newDatas) { if (newDatas) datas = datas.concat(newDatas); deferred.fulfill(datas); }); return deferred.promise; } /** * Gets line column values in all pages. * * Iterate through all lines of all pages and get column value for each line. * It starts at current page. * * @private * @method getLineValuesByPage * @memberof module:e2e/pages/TablePage~TablePage * @this module:e2e/pages/TablePage~TablePage * @param {Number} headerIndex The index of the column to read * @param {Number} totalPages The total number of pages * @return {Promise} Promise resolving with column values */ function getLineValuesByPage(headerIndex, totalPages) { var self = this; var values = []; var deferred = protractor.promise.defer(); this.getLinesInPage().then(function(lines) { if (lines.length) { // Found lines in the page return getLineValuesByIndex.call(self, lines, headerIndex); } else { // No lines in the page return deferred.reject(new Error('No lines')); } }).then(function(lineValuesInPage) { // Got line values in the page values = values.concat(lineValuesInPage); return self.getCurrentPage(); }).then(function(currentPage) { if ((currentPage + 1) <= totalPages) { // Got more pages // Select next page return self.selectPage(currentPage + 1); } else { // No more pages deferred.fulfill(values); return protractor.promise.rejected(new Error('No more pages')); } }).then(function() { // Next page selected // Get all values in the page return getLineValuesByPage.call(self, headerIndex, totalPages); }).then(function(lineValuesInPage) { values = values.concat(lineValuesInPage); deferred.fulfill(values); }).then(null, function(error) { // Nothing to do, promise is rejected but it's not an error }); return deferred.promise; } /** * Gets line fields values in all pages. * * Iterate through all lines of all pages and get columns / fields values for each line. * It starts at current page. * * @private * @method getAllLineDetailsByPage * @memberof module:e2e/pages/TablePage~TablePage * @this module:e2e/pages/TablePage~TablePage * @param {Number} totalPages The total number of pages * @return {Promise} Promise resolving with values */ function getAllLineDetailsByPage(totalPages) { var self = this; var datas = []; var deferred = protractor.promise.defer(); // Get all lines in the page this.getLinesInPage().then(function(lines) { if (lines.length) { // Found lines in the page // Get all information about each line return getAllLineDetailsByIndex.call(self, lines); } else { // No lines in the page return deferred.reject(new Error('No lines')); } }).then(function(datasInPage) { // Got field datas in the page datas = datas.concat(datasInPage); return self.getCurrentPage(); }).then(function(currentPage) { if ((currentPage + 1) <= totalPages) { // Got more pages // Select next page return self.selectPage(currentPage + 1); } else { // No more pages return protractor.promise.rejected(new Error('No more pages')); } }).then(function() { // Next page selected // Get all datas in the page return getAllLineDetailsByPage.call(self, totalPages); }).then(function(datasInPage) { datas = datas.concat(datasInPage); deferred.fulfill(datas); }).then(null, function(error) { if (error.message !== 'No more pages' && error.message !== 'No lines') deferred.reject(error); else deferred.fulfill(datas); }); return deferred.promise; } /** * Gets all lines in the table page except the opened one. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getLinesInPage().then(function(lines) { * console.log(lines); * }); * * @return {Promise} Promise resolving with the list of lines elements in the page (tr elements) */ TablePage.prototype.getLinesInPage = function() { var self = this; return browser.waitForAngular().then(function() { var deferred = protractor.promise.defer(); self.rowElements.filter(function(rowElement, index) { return rowElement.getAttribute('class').then(function(classes) { classes = classes.split(' '); return classes.indexOf('detail') < 0; }); }).then(function(lines) { deferred.fulfill(lines); }, function(error) { deferred.reject(error); }); return deferred.promise; }); }; /** * Gets a line within the current page. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getLineInPage('My line').then(function(line) { * console.log(line); * }); * * @param {String} name The name of the line to look for (each column will be compared to this value) * @return {Promise} Promise resolving with the line (tr element) */ TablePage.prototype.getLineInPage = function(name) { var self = this; // Get all lines except opened ones return this.getLinesInPage().then(function(lines) { // Got all lines except opened lines return getLineByIndex.call(self, lines, name); }); }; /** * Gets the number of lines in the current page. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getLinesInPageNumber().then(function(linesNumber) { * console.log('This page contains ' + linesNumber + ' lines'); * }); * * @return {Promise} Promise resolving with the number of lines in the page */ TablePage.prototype.getLinesInPageNumber = function() { return this.getLinesInPage().then(function(lines) { return protractor.promise.fulfilled(lines.length); }); }; /** * Opens add form. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.openAddForm().then(function() { * console.log('Add form opened'); * }); * * @return {Promise} Promise resolving when add form is opened */ TablePage.prototype.openAddForm = function() { var self = this; return this.addFormWrapperElement.isDisplayed().then(function(isDisplayed) { if (!isDisplayed) { // Open add form browserExt.click(self.addLinkElement); return browser.wait(self.EC.visibilityOf(self.addFormWrapperElement), 1000, 'Missing add form'); } else { // Add form is already displayed return protractor.promise.fulfilled(); } }).then(function() { return protractor.promise.fulfilled(); }); }; /** * Closes formular to add an item. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.openAddForm(); * page.closeAddForm().then(function() { * console.log('Add form closed'); * }); * * @return {Promise} Promise resolving when add form is closed */ TablePage.prototype.closeAddForm = function() { var self = this; return this.addFormWrapperElement.isDisplayed().then(function(isDisplayed) { if (isDisplayed) { // Close add form browserExt.click(self.addLinkElement); // Wait for the menu to be invisible return browser.wait(self.EC.invisibilityOf(self.addFormWrapperElement), 1000, 'Add form still visible'); } else { // Add form is already closed return protractor.promise.fulfilled(); } }).then(function() { return protractor.promise.fulfilled(); }); }; /** * Submit formular to add an item. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.submitAddForm().then(function() { * console.log('Add form submitted'); * }); * * @return {Promise} Promise resolving when add form submit button has been clicked */ TablePage.prototype.submitAddForm = function() { return browserExt.click(this.addButtonElement); }; /** * Gets a line. * * Looks for a line in all pages. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getLine('My line').then(function(line) { * console.log(line); * }); * * @param {(String|Object)} lineFinder The name of the line (each column will be compared to this value) or * the line element * @return {Promise} Promise resolving with the line (tr element) */ TablePage.prototype.getLine = function(lineFinder) { var self = this; if (typeof lineFinder !== 'string') return protractor.promise.fulfilled(lineFinder); return browser.waitForAngular().then(function() { var promises = [self.getCurrentPage(), self.getTotalPages()]; return protractor.promise.all(promises).then(function(values) { var currentPage = values[0]; var totalPages = values[1]; if (totalPages) { if (currentPage != 1) self.selectPage(1); return getLineByPage.call(self, lineFinder, totalPages); } else { return protractor.promise.rejected(new Error('No lines')); } }); }); }; /** * Gets values of a column for all lines in all pages. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getLineValues('Name').then(function(values) { * console.log(values); * }); * * @param {String} headerTitle Title of the column to extract values from * @return {Promise} Promise resolving with the list of values */ TablePage.prototype.getLineValues = function(headerTitle) { var self = this; return browser.waitForAngular().then(function() { var currentPage; var totalPages; var promises = [self.getCurrentPage(), self.getTotalPages()]; return protractor.promise.all(promises).then(function(values) { currentPage = values[0]; totalPages = values[1]; if (totalPages) { if (currentPage != 1) self.selectPage(1); return getHeaderIndex.call(self, headerTitle); } else { return protractor.promise.rejected(new Error('No lines')); } }).then(function(headerIndex) { return getLineValuesByPage.call(self, headerIndex, totalPages); }); }); }; /** * Gets values of a column for all lines in current page. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getLineInPageValues('Name').then(function(values) { * console.log(values); * }); * * @param {String} headerTitle Title of the column to extract values from * @return {Promise} Promise resolving with the list of values */ TablePage.prototype.getLineInPageValues = function(headerTitle) { var self = this; return getHeaderIndex.call(this, headerTitle).then(function(headerIndex) { return self.getLinesInPage().then(function(lines) { if (lines.length) { // Found lines in the page return getLineValuesByIndex.call(self, lines, headerIndex); } else { // No lines in the page return protractor.promise.rejected(new Error('No lines')); } }); }); }; /** * Gets all column / fields values for all lines in all pages. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getAllLineDetails().then(function(data) { * console.log(data); * }); * * @return {Promise} Promise resolving with the list of line details */ TablePage.prototype.getAllLineDetails = function() { var self = this; return browser.waitForAngular().then(function() { var promises = [self.getCurrentPage(), self.getTotalPages()]; var currentPage; var totalPages; return protractor.promise.all(promises).then(function(values) { currentPage = values[0]; totalPages = values[1]; if (totalPages) { if (currentPage != 1) self.selectPage(1); return getAllLineDetailsByPage.call(self, totalPages); } else { return protractor.promise.rejected(new Error('No lines')); } }); }); }; /** * Gets all column / field values of a line. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getLineDetails('My line').then(function(data) { * console.log(data); * }); * * @param {(String|Object)} lineFinder The name of the line (each column will be compared to this value) or * the line element * @return {Promise} Promise resolving with the line details */ TablePage.prototype.getLineDetails = function(lineFinder) { var self = this; return browser.waitForAngular().then(function() { var promises = [self.getLineCellValues(lineFinder), self.getLineFieldValues(lineFinder)]; return protractor.promise.all(promises); }).then(function(values) { return protractor.promise.fulfilled({ cells: values[0], fields: values[1] }); }); }; /** * Gets all column values for a line. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getLineCells('My line').then(function(data) { * console.log(data); * }); * * @param {(String|Object)} lineFinder The name of the line (each column will be compared to this value) or * the line element * @return {Promise} Promise resolving with the line column values */ TablePage.prototype.getLineCells = function(lineFinder) { var self = this; return this.getLine(lineFinder).then(function(line) { // Get all cell values return self.getLineCellValues(line); }); }; /** * Gets all fields values for a line. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getLineFieldValues('My line').then(function(data) { * console.log(data); * }); * * @param {(String|Object)} lineFinder The name of the line (each column will be compared to this value) or * the line element * @return {Promise} Promise resolving with the line fields values */ TablePage.prototype.getLineFieldValues = function(lineFinder) { var self = this; var fieldValues = {}; var getFieldText = function(field, fieldName) { return field.getText().then(function(text) { fieldValues[fieldName] = text; }, function(error) { // Field couldn't be found, maybe it is hidden fieldValues[fieldName] = null; }); }; return this.getLine(lineFinder).then(function(line) { var promises = []; // Close any opened line self.closeLine(); // Open line self.openLine(line); // Get all field values var fields = self.getEditFormFields(self.lineDetailElement); for (var fieldId in fields) promises.push(getFieldText(fields[fieldId], fieldId)); return protractor.promise.all(promises); }).then(function() { return protractor.promise.fulfilled(fieldValues); }); }; /** * Opens a line. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.openLine('My line').then(function() { * console.log('My line opened'); * }); * * @param {(String|Object)} lineFinder The name of the line (each column will be compared to this value) or * the line element * @return {Promise} Promise resolving when line is opened */ TablePage.prototype.openLine = function(lineFinder) { var self = this; return this.getLine(lineFinder).then(function(line) { // Click on the line to open it browserExt.click(line.all(by.css('td')).get(1)); // Wait for the detail line return browser.wait(self.EC.presenceOf(self.lineDetailElement), 5000, 'Missing opened line'); }); }; /** * Closes opened line. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.closeLine('My line').then(function() { * console.log('My line closed'); * }); * * @return {Promise} Promise resolving when line is closed */ TablePage.prototype.closeLine = function() { var self = this; return browser.waitForAngular().then(function() { var deferred = protractor.promise.defer(); var openedLineElement; // Iterate on each line to find if one is an opened line self.rowElements.each(function(rowElement, index) { rowElement.getAttribute('class').then(function(classes) { classes = classes.split(' '); if (classes.indexOf('detail') >= 0) { // Found an opened line // Line is on the previous line because the detail is displayed in a new line openedLineElement = self.rowElements.get(--index); } }); }).then(function() { if (openedLineElement) { // Close opened line browserExt.click(openedLineElement.all(by.css('td')).get(1)); // Wait for the detail line to be closed browser.wait(self.EC.stalenessOf(self.lineDetailElement), 5000, 'Line still opened').then(function() { deferred.fulfill(); }, function(error) { deferred.reject(error); }); } else { deferred.fulfill(); } }); return deferred.promise; }); }; /** * Tests if a line is opened. * * As only one line can be opened at a time, no name is required. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.isOpenedLine().then(function(isOpened) { * console.log('Is a line opened ? ' + isOpened); * }); * * @return {Promise} Promise resolving with a boolean indicating if a line is opened or not */ TablePage.prototype.isOpenedLine = function() { var self = this; return browser.waitForAngular().then(function() { var deferred = protractor.promise.defer(); var isOpened = false; // Iterate on each line to find if one is an opened line self.rowElements.each(function(rowElement, index) { rowElement.getAttribute('class').then(function(classes) { classes = classes.split(' '); if (classes.indexOf('detail') >= 0) isOpened = true; }); }).then(function() { deferred.fulfill(isOpened); }); return deferred.promise; }); }; /** * Tests if a line is selected. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.isSelectedLine('my line name').then(function(isSelected) { * console.log('Is line selected ? ' + isSelected); * }); * * @param {(String|Object)} lineFinder The name of the line (each column will be compared to this value) or * the line element * @return {Promise} Promise resolving with a boolean indicating if line is selected or not */ TablePage.prototype.isSelectedLine = function(lineFinder) { return this.getLine(lineFinder).then(function(line) { // Check if line is selected return browserExt.getProperty(line.element(by.css('input[type="checkbox"]')), 'checked'); }); }; /** * Selects a line by checking the line checkbox. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.selectLine('My line').then(function() { * console.log('My line is selected'); * }); * * @param {(String|Object)} lineFinder The name of the line (each column will be compared to this value) or * the line element * @return {Promise} Promise resolving when line is selected */ TablePage.prototype.selectLine = function(lineFinder) { var self = this; return this.isSelectedLine(lineFinder).then(function(isSelected) { if (isSelected) return protractor.promise.fulfilled(); return self.getLine(lineFinder).then(function(line) { // Click on line checkbox return browserExt.click(line.element(by.css('input[type="checkbox"]'))); }); }); }; /** * Deselects a line by clicking on the line checkbox. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.deselectLine('My line').then(function() { * console.log('My line is deselected'); * }); * * @param {(String|Object)} lineFinder The name of the line (each column will be compared to this value) or * the line element * @return {Promise} Promise resolving when line is deselected */ TablePage.prototype.deselectLine = function(lineFinder) { var self = this; return this.isSelectedLine(lineFinder).then(function(isSelected) { if (!isSelected) return protractor.promise.fulfilled(); return self.getLine(lineFinder).then(function(line) { // Click on line checkbox return browserExt.click(line.element(by.css('input[type="checkbox"]'))); }); }); }; /** * Selects all lines. * * At least, one line must be in the table. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.selectAllLines().then(function() { * console.log('All lines selected'); * }); * * @return {Promise} Promise resolving when all lines are selected */ TablePage.prototype.selectAllLines = function() { var self = this; return browserExt.getProperty(this.selectAllElement, 'checked').then(function(isChecked) { if (isChecked) return protractor.promise.fulfilled(); browserExt.click(self.selectAllElement); return browser.wait(self.EC.visibilityOf(self.actionsButtonElement), 1000, 'Missing the global action button'); }); }; /** * Sorts lines. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.sortBy('Name', true).then(function() { * console.log('Lines sorted by Name'); * }); * * @param {String} name The value of the column to act on, each column will be compared to this value * @param {Boolean} asc true to sort in ascendant order, false to sort in descendant order * @return {Promise} Promise resolving when column is clicked */ TablePage.prototype.sortBy = function(name, asc) { var self = this; return browser.waitForAngular().then(function() { var deferred = protractor.promise.defer(); self.headerElements.filter(function(thElement, index) { return thElement.getText().then(function(text) { return text === name; }); }).then(function(thElements) { if (thElements.length) { var thElement = thElements[0]; // Header found thElement.element(by.className('glyphicon-triangle-bottom')).isPresent().then(function(isPresent) { if ((isPresent && asc) || (!isPresent && !asc)) { deferred.fulfill(); } else { browserExt.click(thElement).then(function() { deferred.fulfill(); }, function(error) { deferred.reject(error); }); } }); } else { deferred.reject(new Error('No header corresponding to ' + name)); } }); return deferred.promise; }); }; /** * Performs an action on a single line. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.performAction('My line', 'Remove').then(function() { * console.log('Action "Remove" has been performed on line "My line", confirmation dialog is opened'); * }); * * mple * * page.performAction('My line', 'Remove', true).then(function() { * console.log('"My line" removed'); * }); * * @param {(String|Object)} lineFinder The name of the line (each column will be compared to this value) or * the line element * @param {String} action The translated name of the action to perform * @param {Boolean} [confirm=false] true to confirm the action, false otherwise * @return {Promise} Promise resolving when action is performed */ TablePage.prototype.performAction = function(lineFinder, action, confirm) { var self = this; return this.getLine(lineFinder).then(function(line) { var actionTd = line.all(by.css('td')).last(); var actionButton = actionTd.element(by.css('button')); var actionElement = actionTd.element(by.cssContainingText('a', action)); return actionElement.isDisplayed().then(function(isDisplayed) { // Click on action button if (!isDisplayed) browserExt.click(actionButton); // Click on the desired action browserExt.click(actionElement); if (confirm) { browser.wait(self.EC.visibilityOf(self.dialogElement), 5000, 'Missing confirmation dialog'); return self.confirmAction(); } else return protractor.promise.fulfilled(); }); }); }; /** * Performs a grouped action. * * At least one line must be selected. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.selectAllLines(); * page.performMultipleAction('Remove').then(function() { * console.log('Action "Remove" performed on all selected lines, confirmation dialog is opened'); * }); * * mple * * page.performMultipleAction('Remove', true).then(function() { * console.log('All lines removed'); * }); * * @param {String} action The translated name of the action to perform * @param {Boolean} [confirm=false] true to confirm the action, false otherwise * @return {Promise} Promise resolving when the action is performed */ TablePage.prototype.performMultipleAction = function(action, confirm) { var self = this; return browserExt.click(this.actionsButtonElement).then(function() { browser.wait(self.EC.visibilityOf(self.actionsElement), 1000, 'Missing the list of actions'); browserExt.click(self.actionsElement.element(by.cssContainingText('a', action))); if (confirm) { browser.wait(self.EC.visibilityOf(self.dialogElement), 5000, 'Missing confirmation dialog'); return self.confirmAction(); } else return protractor.promise.fulfilled(); }); }; /** * Accepts the confirmation dialog. * * Confirmation dialog must be displayed. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.selectAllLines(); * page.performMultipleAction('Remove'); * page.confirmAction().then(function() { * console.Log('Dialog confirmed, thus all selected lines are removed'); * }); * * @return {Promise} Promise resolving when confirmation dialog has been accepted */ TablePage.prototype.confirmAction = function() { var self = this; return browserExt.click(this.dialogConfirmActionButtonElement).then(function() { return browser.wait(self.EC.stalenessOf(self.dialogElement), 5000, 'Dialog still visible'); }).then(function() { return protractor.promise.fulfilled(); }); }; /** * Cancels the confirmation dialog. * * Confirmation dialog must be displayed. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.selectAllLines(); * page.performMultipleAction('Remove'); * page.cancelAction().then(function() { * console.Log('Remoe action canceled'); * }); * * @return {Promise} Promise resolving when confirmation dialog has been canceled */ TablePage.prototype.cancelAction = function() { var self = this; return browserExt.click(this.dialogCancelActionButtonElement).then(function() { return browser.wait(self.EC.stalenessOf(self.dialogElement), 1000, 'Dialog still visible'); }).then(function() { return protractor.promise.fulfilled(); }); }; /** * Gets the list of available actions for a line. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getLineActions('My line').then(function(actions) { * console.log(actions); * }); * * @param {(String|Object)} lineFinder The name of the line (each column will be compared to this value) or * the line element * @return {Promise} Promise resolving whith the list of actions */ TablePage.prototype.getLineActions = function(lineFinder) { return this.getLine(lineFinder).then(function(line) { var deferred = protractor.promise.defer(); var actions = []; var actionElements; var actionTd = line.all(by.css('td')).last(); var actionButton = actionTd.element(by.css('button')); actionElements = actionTd.all(by.css('a')); // Click on action button browserExt.click(actionButton); // Get action names actionElements.each(function(actionElement, index) { actionElement.getText().then(function(actionName) { actions.push(actionName); }); }).then(function() { browserExt.click(actionButton); }).then(function() { deferred.fulfill(actions); }); return deferred.promise; }); }; /** * Gets the list of global actions available. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getGlobalActions().then(function(actions) { * console.log(actions); * }); * * @return {Promise} Promise resolving whith the list of global actions */ TablePage.prototype.getGlobalActions = function() { var self = this; return this.selectAllLines().then(function() { var deferred = protractor.promise.defer(); var actions = []; var actionElements = self.actionsElement.all(by.css('a')); browserExt.click(self.actionsButtonElement); browser.wait(self.EC.visibilityOf(self.actionsElement), 1000, 'Missing the list of actions').then(function() { // Get action names actionElements.each(function(actionElement, index) { actionElement.getText().then(function(actionName) { actions.push(actionName); }); }).then(function() { deferred.fulfill(actions); }); }); return deferred.promise; }); }; /** * Searches in the list of lines using search engine. * * Fills search fields. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * * var searchFieldsValues = { * myField: 'Value' * }; * * page.search(searchFieldsValues).then(function() { * console.Log('Search done'); * }); * * @param {Object} fields List of values for fields returned by method getSearchFields * @return {Promise} Promise resolving when search is done */ TablePage.prototype.search = function(values) { var self = this; return this.openSearchEngine().then(function() { var promises = []; var fields = self.getSearchFields(self.searchFormElement); for (var fieldId in values) promises.push(fields[fieldId].setValue(values[fieldId])); return protractor.promise.all(promises); }); }; /** * Clears search fields. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.clearSearch().then(function() { * console.Log('Search engine cleared'); * }); * * @return {Promise} Promise resolving when fields are cleared */ TablePage.prototype.clearSearch = function() { var self = this; return this.openSearchEngine().then(function() { var promises = []; var fields = self.getSearchFields(self.searchFormElement); for (var fieldId in fields) promises.push(fields[fieldId].setValue()); return protractor.promise.all(promises); }); }; /** * Opens search engine. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.openSearchEngine().then(function() { * console.log('Search engine opened'); * }); * * @return {Promise} Promise resolving when search engine is opened */ TablePage.prototype.openSearchEngine = function() { var self = this; return this.searchFormElement.isDisplayed().then(function(isDisplayed) { if (!isDisplayed) { // Open search engine browserExt.click(self.searchLinkElement); return browser.wait(self.EC.visibilityOf(self.searchFormElement), 1000, 'Missing search form'); } else { // Search engine is already displayed return protractor.promise.fulfilled(); } }).then(function() { return protractor.promise.fulfilled(); }); }; /** * Closes search engine. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.closeSearchEngine().then(function() { * console.log('Search engine closed'); * }); * * @return {Promise} Promise resolving when search engine is closed */ TablePage.prototype.closeSearchEngine = function() { var self = this; return this.searchFormElement.isDisplayed().then(function(isDisplayed) { if (isDisplayed) { // Close search engine browserExt.click(self.searchLinkElement); // Wait for the search engine to be invisible return browser.wait(self.EC.invisibilityOf(self.searchFormElement), 1000, 'Search engine still visible'); } else { // Search engine is already closed return protractor.promise.fulfilled(); } }).then(function() { return protractor.promise.fulfilled(); }); }; /** * Gets current page number. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getCurrentPage().then(function(currentPage) { * console.log('Current page is ' + currentPage); * }); * * @return {Promise} Promise resolving with the current page (starting at 1) */ TablePage.prototype.getCurrentPage = function() { return this.currentPageElement.getText().then(function(currentPage) { return protractor.promise.fulfilled(parseInt(currentPage)); }); }; /** * Gets total number of pages. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getTotalPages().then(function(totalPages) { * console.log('There are ' + totalPages + ' pages'); * }); * * @return {Promise} Promise resolving with the total number of pages */ TablePage.prototype.getTotalPages = function() { return this.totalPagesElement.getText().then(function(totalPages) { return protractor.promise.fulfilled(parseInt(totalPages)); }); }; /** * Gets total number of lines. * * @example * // With MyTablePage extending TablePage * var page = new MyTablePage(); * page.logAsAdmin(); * page.load(); * page.getTotalLines()