UNPKG

siesta-lite

Version:

Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers

360 lines (297 loc) 14.9 kB
/* Siesta 5.6.1 Copyright(c) 2009-2022 Bryntum AB https://bryntum.com/contact https://bryntum.com/products/siesta/license */ /** @class Siesta.Test.ExtJS.Grid This is a mixin, with helper methods for testing functionality relating to ExtJS grids. This mixin is being consumed by {@link Siesta.Test.ExtJS} */ Role('Siesta.Test.ExtJS.Grid', { requires : [ 'waitFor', 'pass', 'fail', 'typeOf' ], methods : { /** * Waits for the rows of a gridpanel or tree panel (or view) to render and then calls the supplied callback. Please note, that if the store of the grid has no records, * the condition for this waiter will never be fullfilled. * * @param {Ext.view.Table/Ext.panel.Table/String} view The view or a ComponentQuery matching a view * @param {Function} callback A function to call when the condition has been met. * @param {Object} scope The scope for the callback * @param {Int} timeout The maximum amount of time to wait for the condition to be fulfilled. Defaults to the {@link Siesta.Test.ExtJS#waitForTimeout} value. */ waitForRowsVisible : function(view, callback, scope, timeout) { if (typeof view === 'function') { timeout = scope; scope = callback; callback = view; view = this.Ext() && this.cq1('tableview') || 'tableview'; } var cmp = this.Ext() && this.normalizeComponent(view, true); var me = this; if (!cmp && typeof view === 'string') { // Make sure CQ returns a result first return this.waitForCQ(view, function(result) { this.waitForRowsVisible(result[0], callback, scope, timeout); }, this); } else { var checkerFn; // Handle case of locking grid (Ext JS 4+ only) if (cmp.normalGrid) { var selector = cmp.normalGrid.getView().itemSelector; checkerFn = function() { if (!cmp.rendered || !cmp.normalGrid.rendered || !cmp.lockedGrid.rendered) return; var lockedResult = this.query(selector, cmp.lockedGrid.getView().getEl().dom); var normalResult = this.query(selector, cmp.normalGrid.getView().getEl().dom); if (lockedResult.length > 0 && normalResult.length > 0) { return { lockedRows : lockedResult, normalRows : normalResult }; } } } else { var view = (cmp.getView && cmp.getView()) || cmp; var selector = view.itemSelector || view.rowSelector; // Handling Ext 4 + Ext 3 cases checkerFn = function() { if (!cmp.rendered) return; var result = this.query(selector, view.el.dom); if (result.length > 0) { return result; } } } return this.waitFor({ method : checkerFn, callback : function() { // Grid might be refreshing itself multiple times during initialization which can // break tests easily var as = me.beginAsync(); me.global.setTimeout(function(){ me.endAsync(as); callback.call(scope || me); }, 100); }, timeout : timeout, assertionName : 'waitForRowsVisible', description : ' ' + Siesta.Resource('Siesta.Test.ExtJS.Grid').get('waitForRowsVisible') + ' "' + cmp.id + '"' }); } }, /** * Utility method which returns the first grid row element. * * Please also refer to the {@link #getRow} method for additional information about the buffered renderer case. * * @param {Ext.panel.Table/String} panel The panel or a ComponentQuery matching a panel * @return {Ext.Element} The element of the first row in the grid. */ getFirstRow : function(grid) { grid = this.normalizeComponent(grid); return this.getRow(grid, 0); }, /** * Utility method which returns the first grid cell element (the one at (0, 0) coordinates). * * Please also refer to the {@link #getRow} method for additional information about the buffered renderer case. * * @param {Ext.panel.Table/String} panel The panel or a ComponentQuery matching a panel * * @return {Ext.Element} The element of the first cell in the grid. */ getFirstCell : function(panel) { panel = this.normalizeComponent(panel); return this.getCell(panel, 0, 0); }, /** * Utility method which returns a grid row element. If the grid is locking, then the row element from the locked grid is returned * (from the left part). * * Please note, that if the grid uses buffered rendering, you need to make sure the row with the required index * is currently rendered (as buffered renderer only renders a part of the dataset). This can be done * with the `grid.ensureVisible()` call, please refer to ExtJS grid docs: * grid.ensureVisible(80, { callback : function() { var row = t.getRow(80); var cell = t.getCell(grid, 80, 0); } }); * * @param {Ext.panel.Table/String} panel The table panel instance or a ComponentQuery matching a panel * @param {Int} index The row index in the whole dataset * * @return {Ext.Element} The element corresponding to the grid row. */ getRow : function (grid, index) { var Ext = this.Ext(); grid = this.normalizeComponent(grid); var domNode; // Sencha Modern if (Ext.grid.Grid && (grid instanceof Ext.grid.Grid)) { var rowCmp = grid.getViewItems()[ index ]; domNode = rowCmp && rowCmp.element; } else { // Sencha Classic // if this is a locking grid, grab from locked grid grid = grid.lockedGrid || grid; if (grid.getView().bufferedRenderer) { var record = grid.getStore().getRange(index, index + 1)[ 0 ] if (record) { domNode = grid.getView().getNode(record) } } else domNode = grid && this.query(grid.getView().itemSelector, grid.getView().getEl().dom)[ index ]; } return domNode && Ext.get(domNode); }, /** * Utility method which returns the cell at the supplied row and col position. * * Please also refer to the {@link #getRow} method for additional information about the buffered renderer case. * * @param {Ext.panel.Table/String} panel The panel or a ComponentQuery matching a panel * @param {Int} row The row index * @param {Int} column The column index * * @return {Ext.Element} The element of the grid cell at specified position. */ getCell : function(grid, row, col) { grid = this.normalizeComponent(grid); var rowEl = grid && this.getRow(grid, row); var cellNode = rowEl && this.query(grid.view.cellSelector, rowEl.dom)[ col ]; return cellNode && this.Ext().get(cellNode); }, /** * Utility method which returns the last cell for the supplied row. * * @param {Ext.panel.Table/String} panel The panel or a ComponentQuery matching a panel * @param {Int} row The row index * * @return {Ext.Element} The element of the grid cell at specified position. */ getLastCellInRow : function(grid, row) { grid = this.normalizeComponent(grid); return this.getCell(grid, row, grid.headerCt.getColumnCount() - 1); }, /** * This assertion passes if the passed string is found in the passed grid's cell element. * * @param {Ext.panel.Table/String} panel The panel or a ComponentQuery matching a panel * @param {Int} row The row index * @param {Int} column The column index * @param {String/RegExp} string The string to find or RegExp to match * @param {String} [description] The description for the assertion */ matchGridCellContent : function(grid, rowIndex, colIndex, string, description) { grid = this.normalizeComponent(grid); var view = grid.getView(), Ext = this.Ext(), cell = this.getCell(grid, rowIndex, colIndex).child('.' + Ext.baseCSSPrefix + 'grid-cell-inner'); var isRegExp = this.typeOf(string) == 'RegExp'; var content = cell.dom.innerHTML; if (isRegExp ? string.test(content) : content.indexOf(string) != -1) { this.pass(description, { descTpl : isRegExp ? 'Cell content {content} matches regexp {string}' : 'Cell content {content} has a string {string}', content : content, string : string }); } else { this.fail(description, { assertionName : 'matchGridCellContent', got : cell.dom.innerHTML, gotDesc : 'Cell content', need : string, needDesc : 'String matching', annotation : 'Row index: ' + rowIndex + ', column index: ' + colIndex }); } }, /** * This method performs either a click or double click on the specified grid cell * (depending from the [clicksToEdit](http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.grid.plugin.Editing-cfg-clicksToEdit) * config of its editing plugin), then waits until the `input` selector appears under the cursor and calls the provided callback. * The callback will receive the DOM `<input> element as the 1st argument. * * In some browsers the editor is shown with delay, so its highly recommended to use this method when editing cells. * Typical usage will be: * t.chain( function (next) { t.clickToEditCell(grid, 0, 1, next) }, function (next, inputEl) { t.type(inputEl, "my text", next) } ) * * * @param {Ext.grid.Panel/String} grid The grid panel or a ComponentQuery matching a panel * @param {Int} rowIndex The row index * @param {Int} colIndex The column index * @param {Function} callback The callback to call once the `input` selector appears under the cursor * @param {String} selector Custom selector to wait for, instead of `input`. */ clickToEditCell : function (grid, rowIndex, colIndex, callback, selector) { var Ext = this.getExt() grid = this.normalizeComponent(grid); var editingPlugin = grid && grid.editingPlugin if (!editingPlugin || !(editingPlugin instanceof Ext.grid.plugin.CellEditing)) { this.fail("No grid, or grid has no editing plugin, or its not a Ext.grid.plugin.CellEditing plugin") callback && callback(null) return } var me = this this[ editingPlugin.clicksToEdit == 2 ? 'doubleClick' : 'click' ](this.getCell(grid, rowIndex, colIndex), function () { // manually force editing if it didn't get started by the click if (!editingPlugin.getActiveEditor()) editingPlugin.startEditByPosition({ row : rowIndex, column : colIndex }) me.waitForSelectorAtCursor(selector || '.x-editor,input', callback) }) }, getTrimmedCellContent : function(grid, row, column) { var cell = this.getCell(grid, row, column); return cell.dom.innerText.trim(); }, /** * Assertion method which passes if the grid cell is empty. * * @param {Ext.panel.Table/String} panel The panel or a ComponentQuery matching a panel * @param {Int} rowIndex The row index * @param {Int} colIndex The column index * @param {String} message The assertion message * * @return {Ext.Element} The element of the grid cell at specified position. */ assertCellIsEmpty : function(grid, row, column, message) { this.is(this.getTrimmedCellContent(grid, row, column), '', message); }, /** * Wait-for method which waits until the chosen grid cell is empty. * * @param {Ext.panel.Table/String} panel The panel or a ComponentQuery matching a panel * @param {Int} rowIndex The row index * @param {Int} colIndex The column index * @param {Object} scope The 'this' object for the callback * @param {Int} timeout The timeout in ms * @param {Function} callback The callback called when the condition is fulfilled * * @return {Ext.Element} The element of the grid cell at specified position. */ waitForCellEmpty : function(grid, row, column, scope, timeout, callback) { if (typeof scope === 'function') { callback = scope; } else if (typeof timeout === 'function') { callback = timeout; } this.waitFor({ method : function() { return this.getTrimmedCellContent(grid, row, column).length === 0; }, callback : function() { callback.call(scope || this); }, timeout : timeout, assertionName : 'waitForCellEmpty', description : ' ' + Siesta.Resource('Siesta.Test.ExtJS.Grid').get('waitForCellEmpty') }); } } });