mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Improvements to the Query Results grid:
- Improve the UI - Allow copy/paste from sets of rows, columns or arbitrary blocks of cells Patch by Matt, Shruti, Joao and Sarah @ Pivotal Fixes #2476
This commit is contained in:
342
web/regression/javascript/selection/active_cell_capture_spec.js
Normal file
342
web/regression/javascript/selection/active_cell_capture_spec.js
Normal file
@@ -0,0 +1,342 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
define([
|
||||
'sources/selection/active_cell_capture',
|
||||
'sources/selection/range_selection_helper',
|
||||
], function (ActiveCellCapture, RangeSelectionHelper) {
|
||||
describe('ActiveCellCapture', function () {
|
||||
var grid, activeCellPlugin, getSelectedRangesSpy, setSelectedRangesSpy;
|
||||
var onHeaderClickFunction;
|
||||
var onClickFunction;
|
||||
var onColumnsResizedFunction;
|
||||
var onHeaderMouseEnterFunction;
|
||||
var onHeaderMouseLeaveFunction;
|
||||
|
||||
beforeEach(function () {
|
||||
getSelectedRangesSpy = jasmine.createSpy('getSelectedRangesSpy');
|
||||
setSelectedRangesSpy = jasmine.createSpy('setSelectedRangesSpy');
|
||||
grid = {
|
||||
getSelectionModel: function () {
|
||||
return {
|
||||
getSelectedRanges: getSelectedRangesSpy,
|
||||
setSelectedRanges: setSelectedRangesSpy,
|
||||
}
|
||||
},
|
||||
|
||||
getColumns: function () {
|
||||
return [
|
||||
{id: 'row-header-column'},
|
||||
{id: 'column-1'},
|
||||
{id: 'column-2'}
|
||||
]
|
||||
},
|
||||
|
||||
onDragEnd: jasmine.createSpyObj('onDragEnd', ['subscribe']),
|
||||
onActiveCellChanged: jasmine.createSpyObj('onActiveCellChanged', ['subscribe']),
|
||||
onHeaderClick: jasmine.createSpy('onHeaderClick'),
|
||||
onClick: jasmine.createSpy('onClick'),
|
||||
onKeyDown: jasmine.createSpyObj('onKeyDown', ['subscribe']),
|
||||
onColumnsResized: jasmine.createSpyObj('onColumnsResized', ['subscribe']),
|
||||
onHeaderMouseEnter: jasmine.createSpyObj('onHeaderMouseEnter', ['subscribe']),
|
||||
onHeaderMouseLeave: jasmine.createSpyObj('onHeaderMouseLeave', ['subscribe']),
|
||||
|
||||
getDataLength: function () { return 10 },
|
||||
|
||||
setActiveCell: jasmine.createSpy('setActiveCell'),
|
||||
getActiveCell: jasmine.createSpy('getActiveCell'),
|
||||
resetActiveCell: jasmine.createSpy('resetActiveCell'),
|
||||
};
|
||||
activeCellPlugin = new ActiveCellCapture();
|
||||
|
||||
grid.onHeaderClick.subscribe =
|
||||
jasmine.createSpy('subscribe').and.callFake(function (callback) {
|
||||
onHeaderClickFunction = callback.bind(activeCellPlugin);
|
||||
});
|
||||
|
||||
grid.onClick.subscribe =
|
||||
jasmine.createSpy('subscribe').and.callFake(function (callback) {
|
||||
onClickFunction = callback.bind(activeCellPlugin);
|
||||
});
|
||||
|
||||
grid.onColumnsResized.subscribe =
|
||||
jasmine.createSpy('subscribe').and.callFake(function (callback) {
|
||||
onColumnsResizedFunction = callback.bind(activeCellPlugin);
|
||||
});
|
||||
|
||||
grid.onHeaderMouseEnter.subscribe =
|
||||
jasmine.createSpy('subscribe').and.callFake(function (callback) {
|
||||
onHeaderMouseEnterFunction = callback.bind(activeCellPlugin);
|
||||
});
|
||||
|
||||
grid.onHeaderMouseLeave.subscribe =
|
||||
jasmine.createSpy('subscribe').and.callFake(function (callback) {
|
||||
onHeaderMouseLeaveFunction = callback.bind(activeCellPlugin);
|
||||
});
|
||||
|
||||
activeCellPlugin.init(grid);
|
||||
});
|
||||
|
||||
describe('onHeaderClickHandler', function () {
|
||||
describe('when no ranges are selected', function () {
|
||||
beforeEach(function () {
|
||||
getSelectedRangesSpy.and.returnValue([]);
|
||||
onHeaderClickFunction({}, {column: {pos: 1}});
|
||||
grid.getActiveCell.and.returnValue(null);
|
||||
});
|
||||
|
||||
it('should set the active cell', function () {
|
||||
expect(grid.setActiveCell).toHaveBeenCalledWith(0, 2);
|
||||
});
|
||||
|
||||
it('should not change the selected ranges', function () {
|
||||
expect(setSelectedRangesSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when only one column is already selected', function () {
|
||||
beforeEach(function () {
|
||||
getSelectedRangesSpy.and.returnValue([RangeSelectionHelper.rangeForColumn(grid, 2)]);
|
||||
grid.getActiveCell.and.returnValue({cell: 2, row: 0});
|
||||
});
|
||||
|
||||
describe('when a different column is clicked', function () {
|
||||
beforeEach(function () {
|
||||
onHeaderClickFunction({}, {column: {pos: 4}})
|
||||
});
|
||||
|
||||
it('should set the active cell to the newly clicked columns top cell', function () {
|
||||
expect(grid.setActiveCell).toHaveBeenCalledWith(0, 5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the same column is clicked', function () {
|
||||
beforeEach(function () {
|
||||
onHeaderClickFunction({}, {column: {pos: 1}});
|
||||
});
|
||||
|
||||
it('should reset the active cell', function () {
|
||||
expect(grid.resetActiveCell).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when mouse is inside the header row', function () {
|
||||
beforeEach(function () {
|
||||
onHeaderMouseEnterFunction({}, {});
|
||||
});
|
||||
|
||||
describe('when user finishes resizing the selected column', function () {
|
||||
var eventSpy;
|
||||
|
||||
beforeEach(function () {
|
||||
eventSpy = jasmine.createSpyObj('event', ['stopPropagation']);
|
||||
onColumnsResizedFunction({}, {grid: grid});
|
||||
onHeaderClickFunction(eventSpy, {column: {pos: 1}});
|
||||
});
|
||||
|
||||
it('should not deselect the current selected column', function () {
|
||||
expect(grid.setActiveCell).not.toHaveBeenCalled();
|
||||
expect(grid.resetActiveCell).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should prevent further event propagation', function () {
|
||||
expect(eventSpy.stopPropagation).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('when the user clicks the resized column header', function () {
|
||||
beforeEach(function () {
|
||||
eventSpy.stopPropagation.calls.reset();
|
||||
onHeaderClickFunction(eventSpy, {column: {pos: 2}});
|
||||
});
|
||||
|
||||
it('should change the active cell', function () {
|
||||
expect(grid.setActiveCell).toHaveBeenCalledWith(0, 3);
|
||||
expect(grid.resetActiveCell).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should allow further event propagation', function () {
|
||||
expect(eventSpy.stopPropagation).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when mouse is outside the header row', function () {
|
||||
beforeEach(function () {
|
||||
onHeaderMouseEnterFunction({}, {});
|
||||
onHeaderMouseLeaveFunction({}, {});
|
||||
});
|
||||
|
||||
describe('when user finishes resizing the selected column', function () {
|
||||
beforeEach(function () {
|
||||
onColumnsResizedFunction({}, {grid: grid});
|
||||
});
|
||||
|
||||
it('should not deselect the current selected column', function () {
|
||||
expect(grid.setActiveCell).not.toHaveBeenCalled();
|
||||
expect(grid.resetActiveCell).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('when the user clicks another column header', function () {
|
||||
var eventSpy;
|
||||
|
||||
beforeEach(function () {
|
||||
eventSpy = jasmine.createSpyObj('event', ['stopPropagation']);
|
||||
onHeaderMouseEnterFunction({}, {});
|
||||
onHeaderClickFunction(eventSpy, {column: {pos: 3}});
|
||||
});
|
||||
|
||||
it('should change the active cell', function () {
|
||||
expect(grid.setActiveCell).toHaveBeenCalledWith(0, 4);
|
||||
expect(grid.resetActiveCell).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should allow further event propagation', function () {
|
||||
expect(eventSpy.stopPropagation).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when three non-consecutive columns are selected', function () {
|
||||
beforeEach(function () {
|
||||
getSelectedRangesSpy.and.returnValue([
|
||||
RangeSelectionHelper.rangeForColumn(grid, 10),
|
||||
RangeSelectionHelper.rangeForColumn(grid, 6),
|
||||
RangeSelectionHelper.rangeForColumn(grid, 22),
|
||||
]);
|
||||
grid.getActiveCell.and.returnValue({cell: 22, row: 0});
|
||||
});
|
||||
|
||||
describe('when the third column is clicked (thereby deselecting it)', function () {
|
||||
beforeEach(function () {
|
||||
onHeaderClickFunction({}, {column: {pos: 21}})
|
||||
});
|
||||
|
||||
it('should set the active cell to the second column', function () {
|
||||
expect(grid.setActiveCell).toHaveBeenCalledWith(0, 6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the second column is clicked (thereby deselecting it)', function () {
|
||||
beforeEach(function () {
|
||||
onHeaderClickFunction({}, {column: {pos: 5}})
|
||||
});
|
||||
|
||||
it('should not set the active cell', function () {
|
||||
expect(grid.setActiveCell).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('onClick', function () {
|
||||
describe('when the target is a random cell in the grid', function () {
|
||||
it('should not change the active cell', function () {
|
||||
onClickFunction({}, {row: 1, cell: 2});
|
||||
grid.getActiveCell.and.returnValue(null);
|
||||
|
||||
expect(grid.setActiveCell).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the target is the row header', function () {
|
||||
describe('when no rows are selected', function () {
|
||||
beforeEach(function () {
|
||||
getSelectedRangesSpy.and.returnValue([]);
|
||||
onClickFunction({}, {row: 1, cell: 0});
|
||||
grid.getActiveCell.and.returnValue(null);
|
||||
});
|
||||
|
||||
it('changes the active cell', function () {
|
||||
expect(grid.setActiveCell).toHaveBeenCalledWith(1, 1);
|
||||
});
|
||||
|
||||
it('should not change the selected ranges', function () {
|
||||
expect(setSelectedRangesSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there is one cell selected', function () {
|
||||
beforeEach(function () {
|
||||
grid.getActiveCell.and.returnValue({row: 4, cell: 5});
|
||||
getSelectedRangesSpy.and.returnValue([
|
||||
new Slick.Range(4, 5)
|
||||
]);
|
||||
});
|
||||
|
||||
it('sets the active cell', function () {
|
||||
onClickFunction({}, {row: 4, cell: 0});
|
||||
|
||||
expect(grid.setActiveCell).toHaveBeenCalledWith(4, 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there is one row selected', function () {
|
||||
beforeEach(function () {
|
||||
grid.getActiveCell.and.returnValue({row: 3, cell: 1});
|
||||
getSelectedRangesSpy.and.returnValue([
|
||||
RangeSelectionHelper.rangeForRow(grid, 3)
|
||||
]);
|
||||
});
|
||||
|
||||
it('resets the selected row', function () {
|
||||
onClickFunction({}, {row: 3, cell: 0});
|
||||
|
||||
expect(grid.resetActiveCell).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('when we select a different row', function () {
|
||||
it('should change the active cell', function () {
|
||||
onClickFunction({}, {row: 9, cell: 0});
|
||||
|
||||
expect(grid.setActiveCell).toHaveBeenCalledWith(9, 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there are 2 rows selected', function () {
|
||||
beforeEach(function () {
|
||||
grid.getActiveCell.and.returnValue({row: 3, cell: 1});
|
||||
getSelectedRangesSpy.and.returnValue([
|
||||
RangeSelectionHelper.rangeForRow(grid, 5),
|
||||
RangeSelectionHelper.rangeForRow(grid, 3)
|
||||
]);
|
||||
});
|
||||
|
||||
describe('when the last selected row is clicked again', function () {
|
||||
it('should change the active cell to the first selected row', function () {
|
||||
onClickFunction({}, {row: 3, cell: 0});
|
||||
|
||||
expect(grid.setActiveCell).toHaveBeenCalledWith(5, 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the first selected row is clicked again', function () {
|
||||
it('should not change the active cell', function () {
|
||||
onClickFunction({}, {row: 5, cell: 0});
|
||||
|
||||
expect(grid.setActiveCell).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('and the editable new row', function () {
|
||||
beforeEach(function () {
|
||||
onClickFunction({}, {row: 10, cell: 0})
|
||||
});
|
||||
it('does not select the row', function () {
|
||||
expect(grid.setActiveCell).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,85 +1,120 @@
|
||||
define(
|
||||
["jquery",
|
||||
"underscore",
|
||||
"slickgrid/slick.grid",
|
||||
"sources/selection/column_selector",
|
||||
"slickgrid/slick.rowselectionmodel",
|
||||
"slickgrid"
|
||||
"sources/selection/active_cell_capture",
|
||||
"sources/selection/grid_selector",
|
||||
'sources/selection/xcell_selection_model',
|
||||
|
||||
"slickgrid",
|
||||
'sources/slickgrid/pgslick.cellrangedecorator',
|
||||
'sources/slickgrid/pgslick.cellrangeselector',
|
||||
"slickgrid/slick.grid",
|
||||
],
|
||||
function ($, _, SlickGrid, ColumnSelector, RowSelectionModel, Slick) {
|
||||
function ($, _, ColumnSelector, ActiveCellCapture, GridSelector, XCellSelectionModel) {
|
||||
var KEY_RIGHT = 39;
|
||||
var KEY_LEFT = 37;
|
||||
var KEY_UP = 38;
|
||||
var KEY_DOWN = 40;
|
||||
|
||||
var Slick = window.Slick;
|
||||
var SlickGrid = Slick.Grid;
|
||||
|
||||
describe("ColumnSelector", function () {
|
||||
var container, data, columns, options;
|
||||
beforeEach(function () {
|
||||
container = $("<div></div>");
|
||||
container.height(9999);
|
||||
container.width(9999);
|
||||
|
||||
data = [{'some-column-name': 'first value', 'second column': 'second value'}];
|
||||
data = [{
|
||||
'some-column-name': 'first value',
|
||||
'second column': 'second value',
|
||||
'third column': 'nonselectable value'
|
||||
}, {
|
||||
'some-column-name': 'row 1 - first value',
|
||||
'second column': 'row 1 - second value',
|
||||
'third column': 'row 1 - nonselectable value'
|
||||
}];
|
||||
|
||||
columns = [
|
||||
{
|
||||
id: 'row-header-column',
|
||||
name: 'row header column name',
|
||||
selectable: false,
|
||||
display_name: 'row header column name',
|
||||
column_type: 'text'
|
||||
},
|
||||
{
|
||||
id: '1',
|
||||
name: 'some-column-name',
|
||||
pos: 0,
|
||||
display_name: 'some-column-name',
|
||||
column_type: 'text'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'second column',
|
||||
pos: 1,
|
||||
display_name: 'second column',
|
||||
column_type: 'json'
|
||||
},
|
||||
{
|
||||
id: 'third-column-id',
|
||||
name: 'third column',
|
||||
pos: 2,
|
||||
display_name: 'third column',
|
||||
column_type: 'text'
|
||||
},
|
||||
{
|
||||
name: 'some-non-selectable-column',
|
||||
selectable: false
|
||||
selectable: false,
|
||||
pos: 3,
|
||||
display_name: 'some-non-selectable-column',
|
||||
column_type: 'numeric'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
describe("when a column is not selectable", function () {
|
||||
it("does not create a checkbox for selecting the column", function () {
|
||||
var checkboxColumn = {
|
||||
name: 'some-column-name-4',
|
||||
selectable: false
|
||||
};
|
||||
columns.push(checkboxColumn);
|
||||
|
||||
setupGrid(columns);
|
||||
|
||||
expect(container.find('.slick-header-columns input').length).toBe(2)
|
||||
});
|
||||
});
|
||||
|
||||
it("renders a checkbox in the column header", function () {
|
||||
setupGrid(columns);
|
||||
|
||||
expect(container.find('.slick-header-columns input').length).toBe(2)
|
||||
];
|
||||
});
|
||||
|
||||
it("displays the name of the column", function () {
|
||||
setupGrid(columns);
|
||||
|
||||
expect($(container.find('.slick-header-columns .slick-column-name')[0]).text())
|
||||
expect($(container.find('.slick-header-columns .slick-column-name')[1]).text())
|
||||
.toContain('some-column-name');
|
||||
expect($(container.find('.slick-header-columns .slick-column-name')[1]).text())
|
||||
.toContain('text');
|
||||
expect($(container.find('.slick-header-columns .slick-column-name')[2]).text())
|
||||
.toContain('second column');
|
||||
expect($(container.find('.slick-header-columns .slick-column-name')[2]).text())
|
||||
.toContain('json');
|
||||
});
|
||||
|
||||
it("preserves the other attributes of column definitions", function () {
|
||||
var columnSelector = new ColumnSelector();
|
||||
var selectableColumns = columnSelector.getColumnDefinitionsWithCheckboxes(columns);
|
||||
var selectableColumns = columnSelector.getColumnDefinitions(columns);
|
||||
|
||||
expect(selectableColumns[0].id).toBe('1');
|
||||
expect(selectableColumns[1].id).toBe('1');
|
||||
});
|
||||
|
||||
describe("selecting columns", function () {
|
||||
var grid, rowSelectionModel;
|
||||
describe("with ActiveCellCapture, CellSelectionModel, and GridSelector: selecting columns", function () {
|
||||
var grid, cellSelectionModel;
|
||||
beforeEach(function () {
|
||||
var columnSelector = new ColumnSelector();
|
||||
columns = columnSelector.getColumnDefinitionsWithCheckboxes(columns);
|
||||
columns = columnSelector.getColumnDefinitions(columns);
|
||||
data = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
data.push({'some-column-name': 'some-value-' + i, 'second column': 'second value ' + i});
|
||||
data.push({
|
||||
'some-column-name': 'some-value-' + i,
|
||||
'second column': 'second value ' + i,
|
||||
'third column': 'third value ' + i,
|
||||
'fourth column': 'fourth value ' + i,
|
||||
});
|
||||
}
|
||||
grid = new SlickGrid(container, data, columns, options);
|
||||
grid = new SlickGrid(container, data, columns);
|
||||
|
||||
rowSelectionModel = new RowSelectionModel();
|
||||
grid.setSelectionModel(rowSelectionModel);
|
||||
grid.registerPlugin(new ActiveCellCapture());
|
||||
cellSelectionModel = new XCellSelectionModel();
|
||||
grid.setSelectionModel(cellSelectionModel);
|
||||
|
||||
grid.registerPlugin(columnSelector);
|
||||
grid.invalidate();
|
||||
@@ -92,57 +127,118 @@ define(
|
||||
|
||||
describe("when the user clicks a column header", function () {
|
||||
it("selects the column", function () {
|
||||
container.find('.slick-header-column')[0].click();
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
container.find('.slick-header-column:contains(some-column-name)').click();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
expectOnlyTheFirstColumnToBeSelected(selectedRanges);
|
||||
});
|
||||
|
||||
it("toggles a selected class to the header cell", function () {
|
||||
container.find('.slick-header-column:contains(second column)').click();
|
||||
expect($(container.find('.slick-header-column:contains(second column)')).hasClass('selected'))
|
||||
.toBe(true);
|
||||
|
||||
container.find('.slick-header-column:contains(second column)').click();
|
||||
expect($(container.find('.slick-header-column:contains(second column)')).hasClass('selected'))
|
||||
.toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the user clicks additional column headers", function () {
|
||||
describe("when the user clicks an additional column header", function () {
|
||||
beforeEach(function () {
|
||||
container.find('.slick-header-column')[1].click();
|
||||
container.find('.slick-header-column:contains(some-column-name)').click();
|
||||
container.find('.slick-header-column:contains(second column)').click();
|
||||
});
|
||||
|
||||
it("selects additional columns", function () {
|
||||
container.find('.slick-header-column')[0].click();
|
||||
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toBe(2);
|
||||
var column1 = selectedRanges[0];
|
||||
|
||||
expect(selectedRanges.length).toEqual(2);
|
||||
expect(column1.fromCell).toBe(1);
|
||||
expect(column1.toCell).toBe(1);
|
||||
|
||||
var column2 = selectedRanges[1];
|
||||
expect(column2.fromCell).toBe(2);
|
||||
expect(column2.toCell).toBe(2);
|
||||
});
|
||||
|
||||
expect(column2.fromCell).toBe(0);
|
||||
expect(column2.toCell).toBe(0);
|
||||
describe("and presses shift + right-arrow", function () {
|
||||
beforeEach(function () {
|
||||
pressShiftArrow(KEY_RIGHT);
|
||||
});
|
||||
|
||||
it("keeps the last column selected", function () {
|
||||
expect(cellSelectionModel.getSelectedRanges().length).toBe(1);
|
||||
});
|
||||
|
||||
it("grows the selection to the right", function () {
|
||||
var selectedRange = cellSelectionModel.getSelectedRanges()[0];
|
||||
expect(selectedRange.fromCell).toBe(2);
|
||||
expect(selectedRange.toCell).toBe(3);
|
||||
expect(selectedRange.fromRow).toBe(0);
|
||||
expect(selectedRange.toRow).toBe(9);
|
||||
});
|
||||
|
||||
it("keeps selected class on columns 2 and 3", function () {
|
||||
expect($(container.find('.slick-header-column:contains(second column)')).hasClass('selected'))
|
||||
.toBe(true);
|
||||
expect($(container.find('.slick-header-column:contains(third column)')).hasClass('selected'))
|
||||
.toBe(true);
|
||||
expect($(container.find('.slick-header-column:contains(some-column-name)')).hasClass('selected'))
|
||||
.toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the user deselects the last selected column header", function () {
|
||||
beforeEach(function () {
|
||||
container.find('.slick-header-column:contains(second column)').click();
|
||||
});
|
||||
|
||||
describe("and presses shift + right-arrow", function () {
|
||||
it("first and second columns are selected", function () {
|
||||
pressShiftArrow(KEY_RIGHT);
|
||||
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
expect(selectedRanges[0].fromCell).toBe(1);
|
||||
expect(selectedRanges[0].toCell).toBe(2);
|
||||
expect(selectedRanges[0].fromRow).toBe(0);
|
||||
expect(selectedRanges[0].toRow).toBe(9);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the user clicks a column header checkbox", function () {
|
||||
describe("when the user clicks a column header description", function () {
|
||||
it("selects the column", function () {
|
||||
container.find('.slick-header-columns input')[0].click();
|
||||
container.find('.slick-header-columns span.column-description:contains(some-column-name)').click();
|
||||
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
expectOnlyTheFirstColumnToBeSelected(selectedRanges);
|
||||
});
|
||||
|
||||
it("checks the checkbox", function () {
|
||||
container.find('.slick-header-column')[1].click();
|
||||
expect($(container.find('.slick-header-columns input')[1]).is(':checked')).toBeTruthy();
|
||||
it("toggles a selected class to the header cell", function () {
|
||||
container.find('.slick-header-column span.column-description:contains(second column)').click();
|
||||
expect($(container.find('.slick-header-column:contains(second column)')).hasClass('selected'))
|
||||
.toBe(true);
|
||||
|
||||
container.find('.slick-header-column span.column-description:contains(second column)').click();
|
||||
expect($(container.find('.slick-header-column:contains(second column)')).hasClass('selected'))
|
||||
.toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when a row is selected", function () {
|
||||
beforeEach(function () {
|
||||
var selectedRanges = [new Slick.Range(0, 0, 0, 1)];
|
||||
rowSelectionModel.setSelectedRanges(selectedRanges);
|
||||
cellSelectionModel.setSelectedRanges(selectedRanges);
|
||||
});
|
||||
|
||||
it("deselects the row", function () {
|
||||
container.find('.slick-header-column')[1].click();
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
|
||||
@@ -152,7 +248,7 @@ define(
|
||||
expect(column.toCell).toBe(1);
|
||||
expect(column.fromRow).toBe(0);
|
||||
expect(column.toRow).toBe(9);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe("clicking a second time", function () {
|
||||
@@ -160,14 +256,9 @@ define(
|
||||
container.find('.slick-header-column')[1].click();
|
||||
});
|
||||
|
||||
it("unchecks checkbox", function () {
|
||||
container.find('.slick-header-column')[1].click();
|
||||
expect($(container.find('.slick-header-columns input')[1]).is(':checked')).toBeFalsy();
|
||||
});
|
||||
|
||||
it("deselects the column", function () {
|
||||
container.find('.slick-header-column')[1].click();
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toEqual(0);
|
||||
})
|
||||
@@ -176,7 +267,7 @@ define(
|
||||
describe("when the column is not selectable", function () {
|
||||
it("does not select the column", function () {
|
||||
$(container.find('.slick-header-column:contains(some-non-selectable-column)')).click();
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toEqual(0);
|
||||
});
|
||||
@@ -187,49 +278,142 @@ define(
|
||||
container.find('.slick-header-column')[1].click();
|
||||
});
|
||||
|
||||
it("unchecks the checkbox", function () {
|
||||
rowSelectionModel.setSelectedRanges([]);
|
||||
it("removes selected class from header", function () {
|
||||
cellSelectionModel.setSelectedRanges([]);
|
||||
|
||||
expect($(container.find('.slick-header-columns input')[1])
|
||||
.is(':checked')).toBeFalsy();
|
||||
expect($(container.find('.slick-header-column')[1]).hasClass('selected'))
|
||||
.toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when a non-column range was already selected", function () {
|
||||
beforeEach(function () {
|
||||
var selectedRanges = [new Slick.Range(0, 0, 1, 0)];
|
||||
rowSelectionModel.setSelectedRanges(selectedRanges);
|
||||
var selectedRanges = [new Slick.Range(0, 0, 2, 0)];
|
||||
cellSelectionModel.setSelectedRanges(selectedRanges);
|
||||
});
|
||||
|
||||
it("deselects the non-column range", function () {
|
||||
container.find('.slick-header-column')[0].click();
|
||||
container.find('.slick-header-column:contains(some-column-name)').click();
|
||||
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
expectOnlyTheFirstColumnToBeSelected(selectedRanges);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('when a column is selected', function () {
|
||||
beforeEach(function () {
|
||||
container.find('.slick-header-column:contains(some-column-name)').click();
|
||||
});
|
||||
|
||||
describe('when the user click a cell on the current range', function () {
|
||||
beforeEach(function () {
|
||||
container.find('.slick-cell.l1.r1')[1].click();
|
||||
});
|
||||
|
||||
it('column is deselected', function () {
|
||||
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
|
||||
var column = selectedRanges[0];
|
||||
|
||||
expect(column.fromCell).toBe(1);
|
||||
expect(column.toCell).toBe(1);
|
||||
expect(column.fromRow).toBe(1);
|
||||
expect(column.toRow).toBe(1);
|
||||
});
|
||||
|
||||
it('keep select class on column header', function () {
|
||||
expect($(container.find('.slick-header-column:contains(some-column-name)')).hasClass('selected'))
|
||||
.toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the user click a cell outside the current range', function () {
|
||||
beforeEach(function () {
|
||||
container.find('.slick-cell.l2.r2')[2].click();
|
||||
});
|
||||
|
||||
it('column is deselected', function () {
|
||||
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
|
||||
var column = selectedRanges[0];
|
||||
|
||||
expect(column.fromCell).toBe(2);
|
||||
expect(column.toCell).toBe(2);
|
||||
expect(column.fromRow).toBe(2);
|
||||
expect(column.toRow).toBe(2);
|
||||
});
|
||||
|
||||
it('remove select class on "some-column-name" column header', function () {
|
||||
expect($(container.find('.slick-header-column:contains(some-column-name)')).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-header-column:contains(second column)')).hasClass('selected'))
|
||||
.toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the user click in a row header', function () {
|
||||
beforeEach(function () {
|
||||
var selectedRanges = [new Slick.Range(1, 1, 1, 3)];
|
||||
cellSelectionModel.setSelectedRanges(selectedRanges);
|
||||
});
|
||||
|
||||
it('column is deselected', function () {
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
|
||||
var column = selectedRanges[0];
|
||||
|
||||
expect(column.fromCell).toBe(1);
|
||||
expect(column.toCell).toBe(3);
|
||||
expect(column.fromRow).toBe(1);
|
||||
expect(column.toRow).toBe(1);
|
||||
});
|
||||
|
||||
it('no column should have the class "selected"', function () {
|
||||
expect($(container.find('.slick-header-column:contains(some-column-name)')).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var setupGrid = function (columns) {
|
||||
function setupGrid(columns) {
|
||||
var columnSelector = new ColumnSelector();
|
||||
columns = columnSelector.getColumnDefinitionsWithCheckboxes(columns);
|
||||
columns = columnSelector.getColumnDefinitions(columns);
|
||||
var grid = new SlickGrid(container, data, columns, options);
|
||||
|
||||
var rowSelectionModel = new RowSelectionModel();
|
||||
grid.setSelectionModel(rowSelectionModel);
|
||||
var cellSelectionModel = new XCellSelectionModel();
|
||||
grid.setSelectionModel(cellSelectionModel);
|
||||
|
||||
grid.registerPlugin(columnSelector);
|
||||
grid.invalidate();
|
||||
};
|
||||
}
|
||||
|
||||
function expectOnlyTheFirstColumnToBeSelected(selectedRanges) {
|
||||
var row = selectedRanges[0];
|
||||
|
||||
expect(selectedRanges.length).toEqual(1);
|
||||
expect(row.fromCell).toBe(0);
|
||||
expect(row.toCell).toBe(0);
|
||||
expect(row.fromCell).toBe(1);
|
||||
expect(row.toCell).toBe(1);
|
||||
expect(row.fromRow).toBe(0);
|
||||
expect(row.toRow).toBe(9);
|
||||
}
|
||||
|
||||
function pressShiftArrow(keyCode) {
|
||||
var pressEvent = new $.Event("keydown");
|
||||
pressEvent.shiftKey = true;
|
||||
pressEvent.ctrlKey = false;
|
||||
pressEvent.altKey = false;
|
||||
pressEvent.which = keyCode;
|
||||
|
||||
$(container.find('.grid-canvas')).trigger(pressEvent);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,21 +1,38 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
define(
|
||||
["jquery",
|
||||
"slickgrid/slick.grid",
|
||||
"slickgrid/slick.rowselectionmodel",
|
||||
"sources/selection/xcell_selection_model",
|
||||
"sources/selection/copy_data",
|
||||
"sources/selection/clipboard",
|
||||
"sources/selection/range_selection_helper"
|
||||
],
|
||||
function ($, SlickGrid, RowSelectionModel, copyData, clipboard, RangeSelectionHelper) {
|
||||
function ($, SlickGrid, XCellSelectionModel, copyData, clipboard, RangeSelectionHelper) {
|
||||
describe('copyData', function () {
|
||||
var grid, sqlEditor;
|
||||
var grid, sqlEditor, gridContainer, buttonPasteRow;
|
||||
|
||||
beforeEach(function () {
|
||||
var data = [[1, "leopord", "12"],
|
||||
[2, "lion", "13"],
|
||||
[3, "puma", "9"]];
|
||||
|
||||
var columns = [{
|
||||
var columns = [
|
||||
{
|
||||
id: 'row-header-column',
|
||||
name: 'row header column name',
|
||||
selectable: false,
|
||||
display_name: 'row header column name',
|
||||
column_type: 'text'
|
||||
},
|
||||
{
|
||||
name: "id",
|
||||
pos: 0,
|
||||
label: "id<br> numeric",
|
||||
@@ -39,17 +56,18 @@ define(
|
||||
}
|
||||
]
|
||||
;
|
||||
var gridContainer = $("<div id='grid'></div>");
|
||||
gridContainer = $("<div id='grid'></div>");
|
||||
$("body").append(gridContainer);
|
||||
$("body").append("<button id='btn-paste-row' disabled></button>");
|
||||
buttonPasteRow = $("<button id='btn-paste-row' disabled></button>");
|
||||
$("body").append(buttonPasteRow);
|
||||
grid = new Slick.Grid("#grid", data, columns, {});
|
||||
grid.setSelectionModel(new Slick.RowSelectionModel({selectActiveRow: false}));
|
||||
grid.setSelectionModel(new XCellSelectionModel());
|
||||
sqlEditor = {slickgrid: grid};
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
$("body").remove('#grid');
|
||||
$("body").remove('#btn-paste-row');
|
||||
gridContainer.remove();
|
||||
buttonPasteRow.remove();
|
||||
});
|
||||
|
||||
describe("when rows are selected", function () {
|
||||
@@ -83,8 +101,8 @@ define(
|
||||
|
||||
describe("when a column is selected", function () {
|
||||
beforeEach(function () {
|
||||
var firstColumn = new Slick.Range(0, 0, 2, 0);
|
||||
grid.getSelectionModel().setSelectedRanges([firstColumn])
|
||||
var firstDataColumn = RangeSelectionHelper.rangeForColumn(grid, 1);
|
||||
grid.getSelectionModel().setSelectedRanges([firstDataColumn])
|
||||
});
|
||||
|
||||
it("copies text to the clipboard", function () {
|
||||
@@ -108,9 +126,11 @@ define(
|
||||
});
|
||||
|
||||
describe("when the user can edit the grid", function () {
|
||||
it("disables the paste row button", function () {
|
||||
beforeEach(function () {
|
||||
copyData.apply(_.extend({can_edit: true}, sqlEditor));
|
||||
});
|
||||
|
||||
it("disables the paste row button", function () {
|
||||
expect($("#btn-paste-row").prop('disabled')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
define(["jquery",
|
||||
"underscore",
|
||||
"slickgrid/slick.grid",
|
||||
"slickgrid/slick.rowselectionmodel",
|
||||
"sources/selection/xcell_selection_model",
|
||||
"sources/selection/grid_selector"
|
||||
],
|
||||
function ($, _, SlickGrid, RowSelectionModel, GridSelector) {
|
||||
function ($, _, SlickGrid, XCellSelectionModel, GridSelector) {
|
||||
describe("GridSelector", function () {
|
||||
var container, data, columns, gridSelector, rowSelectionModel;
|
||||
var container, data, columns, gridSelector, xCellSelectionModel;
|
||||
|
||||
beforeEach(function () {
|
||||
container = $("<div></div>");
|
||||
@@ -14,13 +14,15 @@ define(["jquery",
|
||||
columns = [{
|
||||
id: '1',
|
||||
name: 'some-column-name',
|
||||
pos: 0
|
||||
}, {
|
||||
id: '2',
|
||||
name: 'second column',
|
||||
pos: 1
|
||||
}];
|
||||
|
||||
gridSelector = new GridSelector();
|
||||
columns = gridSelector.getColumnDefinitionsWithCheckboxes(columns);
|
||||
columns = gridSelector.getColumnDefinitions(columns);
|
||||
|
||||
data = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
@@ -28,8 +30,8 @@ define(["jquery",
|
||||
}
|
||||
var grid = new SlickGrid(container, data, columns);
|
||||
|
||||
rowSelectionModel = new RowSelectionModel();
|
||||
grid.setSelectionModel(rowSelectionModel);
|
||||
xCellSelectionModel = new XCellSelectionModel();
|
||||
grid.setSelectionModel(xCellSelectionModel);
|
||||
|
||||
grid.registerPlugin(gridSelector);
|
||||
grid.invalidate();
|
||||
@@ -48,11 +50,7 @@ define(["jquery",
|
||||
expect(leftmostColumn.id).toBe('row-header-column');
|
||||
});
|
||||
|
||||
it("renders checkboxes for selecting columns", function () {
|
||||
expect(container.find('[data-test="output-column-header"] input').length).toBe(2)
|
||||
});
|
||||
|
||||
it("renders a checkbox for selecting all the cells", function () {
|
||||
it("renders a button for selecting all the cells", function () {
|
||||
expect(container.find("[title='Select/Deselect All']").length).toBe(1);
|
||||
});
|
||||
|
||||
@@ -60,7 +58,7 @@ define(["jquery",
|
||||
it("selects the whole grid", function () {
|
||||
container.find("[title='Select/Deselect All']").parent().click();
|
||||
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = xCellSelectionModel.getSelectedRanges();
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
var selectedRange = selectedRanges[0];
|
||||
expect(selectedRange.fromCell).toBe(1);
|
||||
@@ -69,25 +67,19 @@ define(["jquery",
|
||||
expect(selectedRange.toRow).toBe(9);
|
||||
});
|
||||
|
||||
it("checks the checkbox", function () {
|
||||
it("adds selected class", function () {
|
||||
container.find("[title='Select/Deselect All']").parent().click();
|
||||
|
||||
expect($(container.find("[data-id='checkbox-select-all']")).is(':checked')).toBeTruthy();
|
||||
})
|
||||
expect($(container.find("[data-id='select-all']")).hasClass('selected')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the main checkbox in the corner gets selected", function () {
|
||||
it("unchecks all the columns", function () {
|
||||
container.find("[title='Select/Deselect All']").click();
|
||||
|
||||
expect($(container.find('.slick-header-columns input')[1]).is(':checked')).toBeFalsy();
|
||||
expect($(container.find('.slick-header-columns input')[2]).is(':checked')).toBeFalsy();
|
||||
});
|
||||
describe("when the select all button in the corner gets selected", function () {
|
||||
|
||||
it("selects all the cells", function () {
|
||||
container.find("[title='Select/Deselect All']").click();
|
||||
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = xCellSelectionModel.getSelectedRanges();
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
var selectedRange = selectedRanges[0];
|
||||
expect(selectedRange.fromCell).toBe(1);
|
||||
@@ -96,7 +88,7 @@ define(["jquery",
|
||||
expect(selectedRange.toRow).toBe(9);
|
||||
});
|
||||
|
||||
describe("when the main checkbox in the corner gets deselected", function () {
|
||||
describe("when the select all button in the corner gets deselected", function () {
|
||||
beforeEach(function () {
|
||||
container.find("[title='Select/Deselect All']").click();
|
||||
});
|
||||
@@ -104,7 +96,7 @@ define(["jquery",
|
||||
it("deselects all the cells", function () {
|
||||
container.find("[title='Select/Deselect All']").click();
|
||||
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = xCellSelectionModel.getSelectedRanges();
|
||||
expect(selectedRanges.length).toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -114,11 +106,10 @@ define(["jquery",
|
||||
container.find("[title='Select/Deselect All']").click();
|
||||
});
|
||||
|
||||
it("unchecks the main checkbox", function () {
|
||||
var ranges = [new Slick.Range(0, 0, 0, 1)];
|
||||
rowSelectionModel.setSelectedRanges(ranges);
|
||||
it("removes the selected class", function () {
|
||||
container.find("[title='Select/Deselect All']").parent().click();
|
||||
|
||||
expect($(container.find("[title='Select/Deselect All']")).is(':checked')).toBeFalsy();
|
||||
expect($(container.find("[data-id='select-all']")).hasClass('selected')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -61,7 +61,6 @@ define(['sources/selection/range_boundary_navigator'], function (rangeBoundaryNa
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("#mapDimensionBoundaryUnion", function () {
|
||||
it("returns a list of the results of the callback", function () {
|
||||
var rangeBounds = [[0, 1], [3, 3]];
|
||||
@@ -132,20 +131,27 @@ define(['sources/selection/range_boundary_navigator'], function (rangeBoundaryNa
|
||||
});
|
||||
|
||||
it("returns csv for the provided ranges", function () {
|
||||
|
||||
var csvResult = rangeBoundaryNavigator.rangesToCsv(data, columnDefinitions, ranges);
|
||||
|
||||
expect(csvResult).toEqual("1,'leopard','12'\n4,'tiger','10'");
|
||||
});
|
||||
|
||||
describe("when no cells are selected", function () {
|
||||
it("should return an empty string", function () {
|
||||
var csvResult = rangeBoundaryNavigator.rangesToCsv(data, columnDefinitions, []);
|
||||
|
||||
expect(csvResult).toEqual('');
|
||||
});
|
||||
});
|
||||
|
||||
describe("when there is an extra column with checkboxes", function () {
|
||||
|
||||
beforeEach(function () {
|
||||
columnDefinitions = [{name: 'not-a-data-column'}, {name: 'id', pos: 0}, {name: 'animal', pos: 1}, {
|
||||
name: 'size',
|
||||
pos: 2
|
||||
}];
|
||||
ranges = [new Slick.Range(0, 0, 0, 3), new Slick.Range(3, 0, 3, 3)];
|
||||
|
||||
});
|
||||
|
||||
it("returns csv for the columns with data", function () {
|
||||
@@ -153,6 +159,13 @@ define(['sources/selection/range_boundary_navigator'], function (rangeBoundaryNa
|
||||
|
||||
expect(csvResult).toEqual("1,'leopard','12'\n4,'tiger','10'");
|
||||
});
|
||||
describe("when no cells are selected", function () {
|
||||
it("should return an empty string", function () {
|
||||
var csvResult = rangeBoundaryNavigator.rangesToCsv(data, columnDefinitions, []);
|
||||
|
||||
expect(csvResult).toEqual('');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
define([
|
||||
'jquery',
|
||||
'slickgrid/slick.grid',
|
||||
'sources/selection/range_selection_helper'
|
||||
], function ($, SlickGrid, RangeSelectionHelper) {
|
||||
describe("RangeSelectionHelper utility functions", function () {
|
||||
var grid;
|
||||
beforeEach(function () {
|
||||
var container, data, columns, options;
|
||||
container = $("<div></div>");
|
||||
container.height(9999);
|
||||
|
||||
columns = [{
|
||||
id: '1',
|
||||
name: 'some-column-name',
|
||||
pos: 0
|
||||
}, {
|
||||
id: 'second-column-id',
|
||||
name: 'second column',
|
||||
pos: 1
|
||||
}];
|
||||
|
||||
data = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
data.push({'some-column-name': 'some-value-' + i, 'second column': 'second value ' + i});
|
||||
}
|
||||
|
||||
grid = new SlickGrid(container, data, columns, options);
|
||||
grid.invalidate();
|
||||
});
|
||||
|
||||
describe("#getIndexesOfCompleteRows", function () {
|
||||
describe("when selected ranges are not rows", function () {
|
||||
it("returns an empty array", function () {
|
||||
var rowlessRanges = [RangeSelectionHelper.rangeForColumn(grid, 1)];
|
||||
|
||||
expect(RangeSelectionHelper.getIndexesOfCompleteRows(grid, rowlessRanges))
|
||||
.toEqual([]);
|
||||
});
|
||||
});
|
||||
describe("when selected range", function () {
|
||||
describe("is a single row", function () {
|
||||
it("returns an array with one index", function () {
|
||||
var singleRowRange = [RangeSelectionHelper.rangeForRow(grid, 1)];
|
||||
|
||||
expect(RangeSelectionHelper.getIndexesOfCompleteRows(grid, singleRowRange))
|
||||
.toEqual([1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("is multiple rows", function () {
|
||||
it("returns an array of each row's index", function () {
|
||||
var multipleRowRange = [
|
||||
RangeSelectionHelper.rangeForRow(grid, 0),
|
||||
RangeSelectionHelper.rangeForRow(grid, 3),
|
||||
RangeSelectionHelper.rangeForRow(grid, 2),
|
||||
];
|
||||
|
||||
var indexesOfCompleteRows = RangeSelectionHelper.getIndexesOfCompleteRows(grid, multipleRowRange);
|
||||
indexesOfCompleteRows.sort();
|
||||
expect(indexesOfCompleteRows).toEqual([0, 2, 3]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("contains a multi row selection", function () {
|
||||
it("returns an array of each individual row's index", function () {
|
||||
var multipleRowRange = [
|
||||
new Slick.Range(3, 0, 5, 1)
|
||||
];
|
||||
|
||||
var indexesOfCompleteRows = RangeSelectionHelper.getIndexesOfCompleteRows(grid, multipleRowRange);
|
||||
indexesOfCompleteRows.sort();
|
||||
expect(indexesOfCompleteRows).toEqual([3, 4, 5]);
|
||||
});
|
||||
|
||||
describe("and also contains a selection that is not a row", function () {
|
||||
it("returns an array of only the complete rows' indexes", function () {
|
||||
var multipleRowRange = [
|
||||
new Slick.Range(8, 1, 9, 1),
|
||||
new Slick.Range(3, 0, 5, 1)
|
||||
];
|
||||
|
||||
var indexesOfCompleteRows = RangeSelectionHelper.getIndexesOfCompleteRows(grid, multipleRowRange);
|
||||
indexesOfCompleteRows.sort();
|
||||
expect(indexesOfCompleteRows).toEqual([3, 4, 5]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -2,26 +2,37 @@ define(
|
||||
["jquery",
|
||||
"underscore",
|
||||
"slickgrid/slick.grid",
|
||||
"sources/selection/active_cell_capture",
|
||||
"sources/selection/row_selector",
|
||||
"slickgrid/slick.rowselectionmodel",
|
||||
'sources/selection/xcell_selection_model',
|
||||
|
||||
"slickgrid",
|
||||
'sources/slickgrid/pgslick.cellrangedecorator',
|
||||
'sources/slickgrid/pgslick.cellrangeselector',
|
||||
],
|
||||
function ($, _, SlickGrid, RowSelector, RowSelectionModel, Slick) {
|
||||
function ($, _, SlickGrid, ActiveCellCapture, RowSelector, XCellSelectionModel, Slick) {
|
||||
var KEY_RIGHT = 39;
|
||||
var KEY_LEFT = 37;
|
||||
var KEY_UP = 38;
|
||||
var KEY_DOWN = 40;
|
||||
describe("RowSelector", function () {
|
||||
var container, data, columnDefinitions, grid, rowSelectionModel;
|
||||
var container, data, columnDefinitions, grid, cellSelectionModel;
|
||||
|
||||
beforeEach(function () {
|
||||
container = $("<div></div>");
|
||||
container.height(9999);
|
||||
container.width(9999);
|
||||
|
||||
columnDefinitions = [{
|
||||
id: '1',
|
||||
name: 'some-column-name',
|
||||
selectable: true
|
||||
selectable: true,
|
||||
pos: 0
|
||||
}, {
|
||||
id: '2',
|
||||
name: 'second column',
|
||||
selectable: true
|
||||
selectable: true,
|
||||
pos: 1
|
||||
}];
|
||||
|
||||
var rowSelector = new RowSelector();
|
||||
@@ -29,11 +40,13 @@ define(
|
||||
for (var i = 0; i < 10; i++) {
|
||||
data.push(['some-value-' + i, 'second value ' + i]);
|
||||
}
|
||||
columnDefinitions = rowSelector.getColumnDefinitionsWithCheckboxes(columnDefinitions);
|
||||
columnDefinitions = rowSelector.getColumnDefinitions(columnDefinitions);
|
||||
grid = new SlickGrid(container, data, columnDefinitions);
|
||||
|
||||
rowSelectionModel = new RowSelectionModel();
|
||||
grid.setSelectionModel(rowSelectionModel);
|
||||
grid.registerPlugin(new ActiveCellCapture());
|
||||
cellSelectionModel = new XCellSelectionModel();
|
||||
grid.setSelectionModel(cellSelectionModel);
|
||||
|
||||
grid.registerPlugin(rowSelector);
|
||||
grid.invalidate();
|
||||
|
||||
@@ -53,9 +66,9 @@ define(
|
||||
expect(leftmostColumn.selectable).toBe(false);
|
||||
});
|
||||
|
||||
it("renders a checkbox the leftmost column", function () {
|
||||
expect(container.find('.sr').length).toBe(11);
|
||||
expect(container.find('.sr .sc:first-child input[type="checkbox"]').length).toBe(10);
|
||||
it("renders a span on the leftmost column", function () {
|
||||
expect(container.find('.slick-row').length).toBe(10);
|
||||
expect(container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]').length).toBe(10);
|
||||
});
|
||||
|
||||
it("preserves the other attributes of column definitions", function () {
|
||||
@@ -64,44 +77,168 @@ define(
|
||||
});
|
||||
|
||||
describe("selecting rows", function () {
|
||||
describe("when the user clicks a row header checkbox", function () {
|
||||
describe("when the user clicks a row header span", function () {
|
||||
it("selects the row", function () {
|
||||
container.find('.sr .sc:first-child input[type="checkbox"]')[0].click();
|
||||
container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[0].click();
|
||||
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
expectOnlyTheFirstRowToBeSelected(selectedRanges);
|
||||
});
|
||||
|
||||
it("checks the checkbox", function () {
|
||||
container.find('.sr .sc:first-child input[type="checkbox"]')[5].click();
|
||||
it("add selected class to parent of the span", function () {
|
||||
container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[5].click();
|
||||
|
||||
expect($(container.find('.sr .sc:first-child input[type="checkbox"]')[5])
|
||||
.is(':checked')).toBeTruthy();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[5])
|
||||
.hasClass('selected')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the user clicks a row header", function () {
|
||||
it("selects the row", function () {
|
||||
container.find('.sr .sc:first-child')[0].click();
|
||||
beforeEach(function () {
|
||||
container.find('.slick-row .slick-cell:first-child')[1].click();
|
||||
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
expectOnlyTheFirstRowToBeSelected(selectedRanges);
|
||||
});
|
||||
it("selects the row", function () {
|
||||
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
var row = selectedRanges[0];
|
||||
|
||||
expect(selectedRanges.length).toEqual(1);
|
||||
expect(row.fromCell).toBe(1);
|
||||
expect(row.toCell).toBe(2);
|
||||
expect(row.fromRow).toBe(1);
|
||||
expect(row.toRow).toBe(1);
|
||||
});
|
||||
|
||||
it("checks the checkbox", function () {
|
||||
container.find('.sr .sc:first-child')[7].click();
|
||||
it("add selected class to parent of the span", function () {
|
||||
|
||||
expect($(container.find('.sr .sc:first-child input[type="checkbox"]')[7])
|
||||
.is(':checked')).toBeTruthy();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[1])
|
||||
.hasClass('selected')).toBeTruthy();
|
||||
});
|
||||
|
||||
describe("when the user clicks again the same row header", function () {
|
||||
it("add selected class to parent of the span", function () {
|
||||
container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[1].click();
|
||||
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[1])
|
||||
.hasClass('selected')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("and presses shift + down-arrow", function () {
|
||||
beforeEach(function () {
|
||||
pressShiftArrow(KEY_DOWN);
|
||||
});
|
||||
|
||||
it("keeps the last row selected", function () {
|
||||
expect(cellSelectionModel.getSelectedRanges().length).toBe(1);
|
||||
});
|
||||
|
||||
it("grows the selection down", function () {
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
var row = selectedRanges[0];
|
||||
|
||||
expect(selectedRanges.length).toEqual(1);
|
||||
expect(row.fromCell).toBe(1);
|
||||
expect(row.toCell).toBe(2);
|
||||
expect(row.fromRow).toBe(1);
|
||||
expect(row.toRow).toBe(2);
|
||||
});
|
||||
|
||||
it("keeps selected class on rows 1 and 2", function () {
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[0])
|
||||
.hasClass('selected')).toBeFalsy();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[1])
|
||||
.hasClass('selected')).toBeTruthy();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[2])
|
||||
.hasClass('selected')).toBeTruthy();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[3])
|
||||
.hasClass('selected')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the user clicks a cell on the current range', function () {
|
||||
beforeEach(function () {
|
||||
container.find('.slick-cell.l1.r1')[5].click();
|
||||
});
|
||||
|
||||
it('row gets deselected', function () {
|
||||
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
|
||||
var newSelection = selectedRanges[0];
|
||||
|
||||
expect(newSelection.fromCell).toBe(1);
|
||||
expect(newSelection.fromRow).toBe(5);
|
||||
expect(newSelection.toCell).toBe(1);
|
||||
expect(newSelection.toRow).toBe(5);
|
||||
});
|
||||
|
||||
it('keep select class on row header', function () {
|
||||
expect($(container.find('.slick-cell.l0.r0')[5]).hasClass('selected'))
|
||||
.toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the user clicks a cell outside the current range', function () {
|
||||
beforeEach(function () {
|
||||
container.find('.slick-cell.l2.r2')[2].click();
|
||||
});
|
||||
|
||||
it('row gets deselected', function () {
|
||||
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
|
||||
var newSelection = selectedRanges[0];
|
||||
|
||||
expect(newSelection.fromCell).toBe(2);
|
||||
expect(newSelection.fromRow).toBe(2);
|
||||
expect(newSelection.toCell).toBe(2);
|
||||
expect(newSelection.toRow).toBe(2);
|
||||
});
|
||||
|
||||
it('remove select class on "some-column-name" column header', function () {
|
||||
expect($(container.find('.slick-cell.l0.r0')[5]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-cell.l0.r0')[2]).hasClass('selected'))
|
||||
.toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the user has a column selected', function () {
|
||||
beforeEach(function () {
|
||||
var selectedRanges = [new Slick.Range(0, 1, 9, 1)];
|
||||
cellSelectionModel.setSelectedRanges(selectedRanges);
|
||||
});
|
||||
|
||||
it('no row should have the class "selected"', function () {
|
||||
expect($(container.find('.slick-cell.l0.r0')[0]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-cell.l0.r0')[1]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-cell.l0.r0')[2]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-cell.l0.r0')[3]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-cell.l0.r0')[4]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-cell.l0.r0')[5]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the user clicks multiple row headers", function () {
|
||||
it("selects another row", function () {
|
||||
container.find('.sr .sc:first-child')[4].click();
|
||||
container.find('.sr .sc:first-child')[0].click();
|
||||
container.find('.slick-row .slick-cell:first-child')[4].click();
|
||||
container.find('.slick-row .slick-cell:first-child')[0].click();
|
||||
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
expect(selectedRanges.length).toEqual(2);
|
||||
|
||||
var row1 = selectedRanges[0];
|
||||
@@ -117,49 +254,59 @@ define(
|
||||
describe("when a column was already selected", function () {
|
||||
beforeEach(function () {
|
||||
var selectedRanges = [new Slick.Range(0, 0, 0, 1)];
|
||||
rowSelectionModel.setSelectedRanges(selectedRanges);
|
||||
cellSelectionModel.setSelectedRanges(selectedRanges);
|
||||
});
|
||||
|
||||
it("deselects the column", function () {
|
||||
container.find('.sr .sc:first-child')[0].click();
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
container.find('.slick-row .slick-cell:first-child')[0].click();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expectOnlyTheFirstRowToBeSelected(selectedRanges);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the row is deselected through setSelectedRanges", function () {
|
||||
beforeEach(function () {
|
||||
container.find('.sr .sc:first-child')[4].click();
|
||||
container.find('.slick-row .slick-cell:first-child')[4].click();
|
||||
});
|
||||
|
||||
it("should uncheck the checkbox", function () {
|
||||
rowSelectionModel.setSelectedRanges([]);
|
||||
it("should remove the selected class", function () {
|
||||
cellSelectionModel.setSelectedRanges([]);
|
||||
|
||||
expect($(container.find('.sr .sc:first-child input[type="checkbox"]')[4])
|
||||
.is(':checked')).toBeFalsy();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[4])
|
||||
.hasClass('selected')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("click a second time", function () {
|
||||
beforeEach(function () {
|
||||
container.find('.sr .sc:first-child')[1].click();
|
||||
container.find('.slick-row .slick-cell:first-child')[1].click();
|
||||
});
|
||||
|
||||
it("unchecks checkbox", function () {
|
||||
container.find('.sr .sc:first-child')[1].click();
|
||||
expect($(container.find('.sr .sc:first-child input[type="checkbox"]')[1])
|
||||
.is(':checked')).toBeFalsy();
|
||||
it("removes the selected class", function () {
|
||||
container.find('.slick-row .slick-cell:first-child')[1].click();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[1])
|
||||
.hasClass('selected')).toBeFalsy();
|
||||
});
|
||||
|
||||
it("unselects the row", function () {
|
||||
container.find('.sr .sc:first-child')[1].click();
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
container.find('.slick-row .slick-cell:first-child')[1].click();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toEqual(0);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
function pressShiftArrow(keyCode) {
|
||||
var pressEvent = new $.Event("keydown");
|
||||
pressEvent.shiftKey = true;
|
||||
pressEvent.ctrlKey = false;
|
||||
pressEvent.altKey = false;
|
||||
pressEvent.which = keyCode;
|
||||
|
||||
$(container.find('.grid-canvas')).trigger(pressEvent);
|
||||
}
|
||||
});
|
||||
|
||||
function expectOnlyTheFirstRowToBeSelected(selectedRanges) {
|
||||
|
||||
@@ -12,131 +12,137 @@ define([
|
||||
"underscore",
|
||||
"sources/selection/set_staged_rows",
|
||||
], function ($, _, SetStagedRows) {
|
||||
describe('when no full rows are selected', function () {
|
||||
var sqlEditorObj, deleteButton, copyButton;
|
||||
describe('set_staged_rows', function () {
|
||||
var sqlEditorObj, gridSpy, deleteButton, copyButton, selectionSpy;
|
||||
beforeEach(function () {
|
||||
var gridSpy = jasmine.createSpyObj('gridSpy', ['getData', 'getCellNode']);
|
||||
gridSpy = jasmine.createSpyObj('gridSpy', ['getData', 'getCellNode', 'getColumns']);
|
||||
gridSpy.getData.and.returnValue([
|
||||
{0: 'one', 1: 'two', __temp_PK: '123'},
|
||||
{0: 'three', 1: 'four', __temp_PK: '456'},
|
||||
{0: 'five', 1: 'six', __temp_PK: '789'},
|
||||
{0: 'seven', 1: 'eight', __temp_PK: '432'}
|
||||
]);
|
||||
gridSpy.getColumns.and.returnValue([
|
||||
{
|
||||
pos: 0,
|
||||
selectable: true,
|
||||
}, {
|
||||
pos: 1,
|
||||
selectable: true,
|
||||
}
|
||||
]);
|
||||
|
||||
selectionSpy = jasmine.createSpyObj('selectionSpy', ['setSelectedRows', 'getSelectedRanges']);
|
||||
|
||||
deleteButton = $('<button id="btn-delete-row"></button>');
|
||||
copyButton = $('<button id="btn-copy-row"></button>');
|
||||
|
||||
sqlEditorObj = {
|
||||
grid: gridSpy,
|
||||
editor: {
|
||||
handler: {
|
||||
data_store: {
|
||||
staged_rows: {1: [1, 2]}
|
||||
}
|
||||
staged_rows: {'456': {}}
|
||||
},
|
||||
can_edit: false
|
||||
}
|
||||
}
|
||||
},
|
||||
keys: null,
|
||||
selection: selectionSpy,
|
||||
columns: [
|
||||
{
|
||||
name: 'a pk column',
|
||||
pos: 0
|
||||
},
|
||||
{
|
||||
name: 'some column',
|
||||
pos: 1
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
$('body').append(deleteButton);
|
||||
$('body').append(copyButton);
|
||||
deleteButton.prop('disabled', false);
|
||||
copyButton.prop('disabled', false);
|
||||
|
||||
deleteButton.prop('disabled', true);
|
||||
copyButton.prop('disabled', true);
|
||||
|
||||
selectionSpy = jasmine.createSpyObj('selectionSpy', [
|
||||
'setSelectedRows',
|
||||
'getSelectedRanges',
|
||||
]);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
copyButton.remove();
|
||||
deleteButton.remove();
|
||||
});
|
||||
describe('when no full rows are selected', function () {
|
||||
describe('when nothing is selected', function () {
|
||||
beforeEach(function () {
|
||||
selectionSpy.getSelectedRanges.and.returnValue([]);
|
||||
sqlEditorObj.selection = selectionSpy;
|
||||
SetStagedRows.call(sqlEditorObj, {}, {});
|
||||
});
|
||||
|
||||
describe('when getSelectedRows is not present in the selection model', function () {
|
||||
beforeEach(function () {
|
||||
SetStagedRows.call(sqlEditorObj, {}, {});
|
||||
});
|
||||
it('should disable the delete row button', function () {
|
||||
expect($('#btn-delete-row').prop('disabled')).toBeTruthy();
|
||||
it('should disable the delete row button', function () {
|
||||
expect($('#btn-delete-row').prop('disabled')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should disable the copy row button', function () {
|
||||
expect($('#btn-copy-row').prop('disabled')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should clear staged rows', function () {
|
||||
expect(sqlEditorObj.editor.handler.data_store.staged_rows).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
it('should disable the copy row button', function () {
|
||||
expect($('#btn-copy-row').prop('disabled')).toBeTruthy();
|
||||
});
|
||||
describe('when there is a selection', function () {
|
||||
beforeEach(function () {
|
||||
var range = {
|
||||
fromCell: 0,
|
||||
toCell: 0,
|
||||
fromRow: 1,
|
||||
toRow: 1,
|
||||
};
|
||||
|
||||
it('should clear staged rows', function () {
|
||||
expect(sqlEditorObj.editor.handler.data_store.staged_rows).toEqual({});
|
||||
selectionSpy.getSelectedRanges.and.returnValue([range]);
|
||||
sqlEditorObj.selection = selectionSpy;
|
||||
SetStagedRows.call(sqlEditorObj, {}, {});
|
||||
});
|
||||
|
||||
it('should disable the delete row button', function () {
|
||||
expect($('#btn-delete-row').prop('disabled')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should disable the copy row button', function () {
|
||||
expect($('#btn-copy-row').prop('disabled')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should clear staged rows', function () {
|
||||
expect(sqlEditorObj.editor.handler.data_store.staged_rows).toEqual({});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when getSelectedRows is present in the selection model', function () {
|
||||
describe('when 2 full rows are selected', function () {
|
||||
beforeEach(function () {
|
||||
var selectionSpy = jasmine.createSpyObj('selectionSpy', ['getSelectedRows', 'setSelectedRows']);
|
||||
selectionSpy.getSelectedRows.and.returnValue([]);
|
||||
sqlEditorObj.selection = selectionSpy;
|
||||
SetStagedRows.call(sqlEditorObj, {}, {});
|
||||
});
|
||||
|
||||
it('should disable the delete row button', function () {
|
||||
expect($('#btn-delete-row').prop('disabled')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should disable the copy row button', function () {
|
||||
expect($('#btn-copy-row').prop('disabled')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should clear staged rows', function () {
|
||||
expect(sqlEditorObj.editor.handler.data_store.staged_rows).toEqual({});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when 2 full rows are selected', function () {
|
||||
describe('when getSelectedRows is present in the selection model', function () {
|
||||
var sqlEditorObj, gridSpy, deleteButton, copyButton;
|
||||
beforeEach(function () {
|
||||
gridSpy = jasmine.createSpyObj('gridSpy', ['getData', 'getCellNode']);
|
||||
gridSpy.getData.and.returnValue([
|
||||
{0: 'one', 1: 'two', __temp_PK: '123'},
|
||||
{0: 'three', 1: 'four', __temp_PK: '456'},
|
||||
{0: 'five', 1: 'six', __temp_PK: '789'},
|
||||
{0: 'seven', 1: 'eight', __temp_PK: '432'}
|
||||
]);
|
||||
|
||||
var selectionSpy = jasmine.createSpyObj('selectionSpy', ['getSelectedRows', 'setSelectedRows']);
|
||||
selectionSpy.getSelectedRows.and.returnValue([1, 2]);
|
||||
|
||||
deleteButton = $('<button id="btn-delete-row"></button>');
|
||||
copyButton = $('<button id="btn-copy-row"></button>');
|
||||
|
||||
sqlEditorObj = {
|
||||
grid: gridSpy,
|
||||
editor: {
|
||||
handler: {
|
||||
data_store: {
|
||||
staged_rows: {'456': {}}
|
||||
},
|
||||
can_edit: false
|
||||
}
|
||||
},
|
||||
keys: null,
|
||||
selection: selectionSpy,
|
||||
columns: [
|
||||
{
|
||||
name: 'a pk column',
|
||||
pos: 0
|
||||
},
|
||||
{
|
||||
name: 'some column',
|
||||
pos: 1
|
||||
}
|
||||
]
|
||||
var range1 = {
|
||||
fromCell: 0,
|
||||
toCell: 1,
|
||||
fromRow: 1,
|
||||
toRow: 1,
|
||||
};
|
||||
var range2 = {
|
||||
fromCell: 0,
|
||||
toCell: 1,
|
||||
fromRow: 2,
|
||||
toRow: 2,
|
||||
};
|
||||
|
||||
$('body').append(deleteButton);
|
||||
$('body').append(copyButton);
|
||||
|
||||
deleteButton.prop('disabled', true);
|
||||
copyButton.prop('disabled', true);
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
copyButton.remove();
|
||||
deleteButton.remove();
|
||||
selectionSpy.getSelectedRanges.and.returnValue([range1, range2]);
|
||||
sqlEditorObj.selection = selectionSpy;
|
||||
});
|
||||
|
||||
describe('when table does not have primary keys', function () {
|
||||
@@ -181,7 +187,6 @@ define([
|
||||
SetStagedRows.call(sqlEditorObj, {}, {});
|
||||
expect(sqlEditorObj.selection.setSelectedRows).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('selected rows missing primary key', function () {
|
||||
@@ -203,7 +208,6 @@ define([
|
||||
SetStagedRows.call(sqlEditorObj, {}, {});
|
||||
expect(sqlEditorObj.selection.setSelectedRows).toHaveBeenCalledWith([]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('when the selected row is a new row', function () {
|
||||
@@ -235,4 +239,4 @@ define([
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,513 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
define([
|
||||
'sources/selection/xcell_selection_model',
|
||||
"slickgrid/slick.grid",
|
||||
'slickgrid',
|
||||
], function (XCellSelectionModel, SlickGrid, Slick) {
|
||||
describe('XCellSelectionModel', function () {
|
||||
var KEY_RIGHT = 39;
|
||||
var KEY_LEFT = 37;
|
||||
var KEY_UP = 38;
|
||||
var KEY_DOWN = 40;
|
||||
|
||||
var container, grid;
|
||||
var oldWindowParent = window.parent;
|
||||
|
||||
beforeEach(function () {
|
||||
window.parent = window;
|
||||
|
||||
var columns = [{
|
||||
id: 'row-header-column',
|
||||
name: 'row header column name',
|
||||
selectable: false,
|
||||
}, {
|
||||
id: '1',
|
||||
name: 'some-column-name',
|
||||
pos: 0
|
||||
}, {
|
||||
id: 'second-column-id',
|
||||
name: 'second column',
|
||||
pos: 1
|
||||
}, {
|
||||
id: 'third-column-id',
|
||||
name: 'third column',
|
||||
pos: 2
|
||||
},
|
||||
];
|
||||
|
||||
var data = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
data.push({
|
||||
'some-column-name': 'some-value-' + i,
|
||||
'second column': 'second value ' + i,
|
||||
'third column': 'third value ' + i,
|
||||
'fourth column': 'fourth value ' + i,
|
||||
});
|
||||
}
|
||||
container = $("<div></div>");
|
||||
container.height(9999);
|
||||
container.width(9999);
|
||||
|
||||
grid = new SlickGrid(container, data, columns);
|
||||
grid.setSelectionModel(new XCellSelectionModel());
|
||||
$("body").append(container);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
grid.destroy();
|
||||
container.remove();
|
||||
window.parent = oldWindowParent;
|
||||
});
|
||||
|
||||
describe('handleKeyDown', function () {
|
||||
describe('when we press a random key', function () {
|
||||
it('should not change the range', function () {
|
||||
var range = new Slick.Range(1, 2);
|
||||
grid.setActiveCell(1, 2);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
pressKey(72);
|
||||
|
||||
expect(grid.getSelectionModel().getSelectedRanges()[0]).toEqual(range);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when we press an arrow key ', function () {
|
||||
it('should select the cell to the right', function () {
|
||||
var range = new Slick.Range(1, 2);
|
||||
grid.setActiveCell(1, 2);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
pressKey(KEY_RIGHT);
|
||||
|
||||
expectOneSelectedRange(1, 3, 1, 3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when we press shift', function () {
|
||||
describe('and we press an arrow key', function () {
|
||||
var scrollColumnIntoViewSpy, scrollRowIntoViewSpy;
|
||||
|
||||
beforeEach(function () {
|
||||
scrollColumnIntoViewSpy = spyOn(grid, 'scrollColumnIntoView');
|
||||
scrollRowIntoViewSpy = spyOn(grid, 'scrollRowIntoView');
|
||||
});
|
||||
|
||||
describe('the right arrow', function () {
|
||||
describe('when a cell is selected', function () {
|
||||
beforeEach(function () {
|
||||
var range = new Slick.Range(1, 1);
|
||||
grid.setActiveCell(1, 1);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
pressShiftPlusKey(KEY_RIGHT);
|
||||
});
|
||||
|
||||
it('increases the range by one to the right', function () {
|
||||
expectOneSelectedRange(1, 1, 1, 2);
|
||||
});
|
||||
|
||||
it('should scroll the next column into view', function () {
|
||||
expect(scrollColumnIntoViewSpy).toHaveBeenCalledWith(2);
|
||||
expect(scrollRowIntoViewSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('pressing right again grows the range right', function () {
|
||||
pressShiftPlusKey(KEY_RIGHT);
|
||||
|
||||
expectOneSelectedRange(1, 1, 1, 3);
|
||||
});
|
||||
|
||||
it('then pressing left keeps the original selection', function () {
|
||||
pressShiftPlusKey(KEY_LEFT);
|
||||
|
||||
expectOneSelectedRange(1, 1, 1, 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when a column is selected', function () {
|
||||
beforeEach(function () {
|
||||
var range = new Slick.Range(0, 1, 9, 1);
|
||||
grid.setActiveCell(0, 1);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
pressShiftPlusKey(KEY_RIGHT);
|
||||
});
|
||||
|
||||
it('increases the range by one column to the right', function () {
|
||||
expectOneSelectedRange(0, 1, 9, 2);
|
||||
});
|
||||
|
||||
it('should scroll the next column into view', function () {
|
||||
expect(scrollColumnIntoViewSpy).toHaveBeenCalledWith(2);
|
||||
expect(scrollRowIntoViewSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('the left arrow', function () {
|
||||
describe('when a cell is selected', function () {
|
||||
beforeEach(function () {
|
||||
var range = new Slick.Range(1, 3);
|
||||
grid.setActiveCell(1, 3);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
pressShiftPlusKey(KEY_LEFT);
|
||||
});
|
||||
|
||||
it('increases the range by one to the left', function () {
|
||||
expectOneSelectedRange(1, 2, 1, 3);
|
||||
});
|
||||
|
||||
it('should scroll previous column into view', function () {
|
||||
expect(scrollColumnIntoViewSpy).toHaveBeenCalledWith(2);
|
||||
expect(scrollRowIntoViewSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('pressing left again grows the range the left', function () {
|
||||
pressShiftPlusKey(KEY_LEFT);
|
||||
|
||||
expectOneSelectedRange(1, 1, 1, 3);
|
||||
});
|
||||
|
||||
it('then pressing right keeps the original selection', function () {
|
||||
pressShiftPlusKey(KEY_RIGHT);
|
||||
|
||||
expectOneSelectedRange(1, 3, 1, 3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when a column is selected', function () {
|
||||
beforeEach(function () {
|
||||
var range = new Slick.Range(0, 2, 9, 2);
|
||||
grid.setActiveCell(0, 2);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
pressShiftPlusKey(KEY_LEFT);
|
||||
});
|
||||
|
||||
it('increases the range by one column to the left', function () {
|
||||
expectOneSelectedRange(0, 1, 9, 2);
|
||||
});
|
||||
|
||||
it('should scroll previous column into view', function () {
|
||||
expect(scrollColumnIntoViewSpy).toHaveBeenCalledWith(1);
|
||||
expect(scrollRowIntoViewSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('the up arrow', function () {
|
||||
describe('when a cell is selected', function () {
|
||||
beforeEach(function () {
|
||||
var range = new Slick.Range(2, 2);
|
||||
grid.setActiveCell(2, 2);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
pressShiftPlusKey(KEY_UP);
|
||||
});
|
||||
|
||||
it('increases the range by one up', function () {
|
||||
expectOneSelectedRange(1, 2, 2, 2);
|
||||
});
|
||||
|
||||
it('should scroll the row above into view', function () {
|
||||
expect(scrollRowIntoViewSpy).toHaveBeenCalledWith(1);
|
||||
expect(scrollColumnIntoViewSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('pressing up again grows the range up', function () {
|
||||
pressShiftPlusKey(KEY_UP);
|
||||
|
||||
expectOneSelectedRange(0, 2, 2, 2);
|
||||
});
|
||||
|
||||
it('then pressing down keeps the original selection', function () {
|
||||
pressShiftPlusKey(KEY_DOWN);
|
||||
|
||||
expectOneSelectedRange(2, 2, 2, 2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when a row is selected', function () {
|
||||
beforeEach(function () {
|
||||
var range = new Slick.Range(2, 1, 2, 3);
|
||||
grid.setActiveCell(2, 1);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
pressShiftPlusKey(KEY_UP);
|
||||
});
|
||||
|
||||
it('increases the range by one row up', function () {
|
||||
expectOneSelectedRange(1, 1, 2, 3);
|
||||
});
|
||||
|
||||
it('should scroll the row above into view', function () {
|
||||
expect(scrollRowIntoViewSpy).toHaveBeenCalledWith(1);
|
||||
expect(scrollColumnIntoViewSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('the down arrow', function () {
|
||||
describe('when a cell is selected', function () {
|
||||
beforeEach(function () {
|
||||
var range = new Slick.Range(2, 2);
|
||||
grid.setActiveCell(2, 2);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
pressShiftPlusKey(KEY_DOWN);
|
||||
});
|
||||
|
||||
it('increases the range by one down', function () {
|
||||
expectOneSelectedRange(2, 2, 3, 2);
|
||||
});
|
||||
|
||||
it('should scroll the row below into view', function () {
|
||||
expect(scrollRowIntoViewSpy).toHaveBeenCalledWith(3);
|
||||
expect(scrollColumnIntoViewSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('pressing down again grows the range down', function () {
|
||||
pressShiftPlusKey(KEY_DOWN);
|
||||
|
||||
expectOneSelectedRange(2, 2, 4, 2);
|
||||
});
|
||||
|
||||
it('then pressing up keeps the original selection', function () {
|
||||
pressShiftPlusKey(KEY_UP);
|
||||
|
||||
expectOneSelectedRange(2, 2, 2, 2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when a row is selected', function () {
|
||||
beforeEach(function () {
|
||||
var range = new Slick.Range(2, 1, 2, 3);
|
||||
grid.setActiveCell(2, 1);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
pressShiftPlusKey(KEY_DOWN);
|
||||
});
|
||||
|
||||
it('increases the range by one row down', function () {
|
||||
expectOneSelectedRange(2, 1, 3, 3);
|
||||
});
|
||||
|
||||
it('should scroll the row below into view', function () {
|
||||
expect(scrollRowIntoViewSpy).toHaveBeenCalledWith(3);
|
||||
expect(scrollColumnIntoViewSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('rectangular selection works', function () {
|
||||
|
||||
it('in the down-and-rightward direction', function () {
|
||||
var range = new Slick.Range(1, 1);
|
||||
grid.setActiveCell(1, 1);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
|
||||
pressShiftPlusKey(KEY_DOWN);
|
||||
pressShiftPlusKey(KEY_DOWN);
|
||||
pressShiftPlusKey(KEY_DOWN);
|
||||
pressShiftPlusKey(KEY_RIGHT);
|
||||
pressShiftPlusKey(KEY_RIGHT);
|
||||
|
||||
expectOneSelectedRange(1, 1, 4, 3);
|
||||
});
|
||||
|
||||
it('in the up-and-leftward direction', function () {
|
||||
var range = new Slick.Range(4, 3);
|
||||
grid.setActiveCell(4, 3);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
|
||||
pressShiftPlusKey(KEY_UP);
|
||||
pressShiftPlusKey(KEY_UP);
|
||||
pressShiftPlusKey(KEY_UP);
|
||||
pressShiftPlusKey(KEY_LEFT);
|
||||
pressShiftPlusKey(KEY_LEFT);
|
||||
|
||||
expectOneSelectedRange(1, 1, 4, 3);
|
||||
});
|
||||
|
||||
it('in the up-and-rightward direction', function () {
|
||||
var range = new Slick.Range(4, 1);
|
||||
grid.setActiveCell(4, 1);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
|
||||
pressShiftPlusKey(KEY_UP);
|
||||
pressShiftPlusKey(KEY_UP);
|
||||
pressShiftPlusKey(KEY_UP);
|
||||
pressShiftPlusKey(KEY_RIGHT);
|
||||
pressShiftPlusKey(KEY_RIGHT);
|
||||
|
||||
expectOneSelectedRange(1, 1, 4, 3);
|
||||
});
|
||||
|
||||
it('in the down-and-leftward direction', function () {
|
||||
var range = new Slick.Range(1, 3);
|
||||
grid.setActiveCell(1, 3);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
|
||||
pressShiftPlusKey(KEY_DOWN);
|
||||
pressShiftPlusKey(KEY_DOWN);
|
||||
pressShiftPlusKey(KEY_DOWN);
|
||||
pressShiftPlusKey(KEY_LEFT);
|
||||
pressShiftPlusKey(KEY_LEFT);
|
||||
|
||||
expectOneSelectedRange(1, 1, 4, 3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('and we are on an edge', function () {
|
||||
var range;
|
||||
|
||||
beforeEach(function () {
|
||||
range = new Slick.Range(2, 1);
|
||||
grid.setActiveCell(2, 1);
|
||||
grid.getSelectionModel().setSelectedRanges([range]);
|
||||
});
|
||||
|
||||
it('we still have the selected range before we arrowed', function () {
|
||||
pressShiftPlusKey(KEY_LEFT);
|
||||
expectOneSelectedRange(2, 1, 2, 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when we drag and drop', function () {
|
||||
var dd;
|
||||
// We could not find an elegant way to calculate this value
|
||||
// after changing window size we saw this was a constant value
|
||||
var offsetLeftColumns = 100;
|
||||
|
||||
function cellTopPosition($cell, rowNumber) {
|
||||
return $(grid.getCanvasNode()).offset().top + $cell[0].scrollHeight * rowNumber;
|
||||
}
|
||||
|
||||
function cellLeftPosition(columnNumber) {
|
||||
return $(grid.getCanvasNode()).offset().left + offsetLeftColumns * columnNumber;
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
var initialPosition = {cell: 3, row: 4};
|
||||
var $cell = $($('.slick-cell.l3')[initialPosition.row]);
|
||||
var event = {
|
||||
target: $cell,
|
||||
isPropagationStopped: jasmine.createSpy('isPropagationStopped').and.returnValue(false),
|
||||
isImmediatePropagationStopped: jasmine.createSpy('isImmediatePropagationStopped').and.returnValue(false),
|
||||
stopImmediatePropagation: jasmine.createSpy('stopImmediatePropagation')
|
||||
};
|
||||
|
||||
dd = {
|
||||
grid: grid,
|
||||
startX: cellLeftPosition(initialPosition.cell),
|
||||
startY: cellTopPosition($cell, initialPosition.row)
|
||||
};
|
||||
|
||||
grid.onDragStart.notify(dd, event, grid);
|
||||
});
|
||||
|
||||
describe('when the drop happens outside of the grid', function () {
|
||||
beforeEach(function () {
|
||||
var $cell = $($('.slick-cell.l1')[1]);
|
||||
var finalPosition = {cell: 1, row: 1};
|
||||
|
||||
var event = {
|
||||
target: $cell,
|
||||
isPropagationStopped: jasmine.createSpy('isPropagationStopped').and.returnValue(false),
|
||||
isImmediatePropagationStopped: jasmine.createSpy('isImmediatePropagationStopped').and.returnValue(false),
|
||||
stopImmediatePropagation: jasmine.createSpy('stopImmediatePropagation'),
|
||||
|
||||
pageX: cellLeftPosition(finalPosition.cell),
|
||||
pageY: cellTopPosition($cell, finalPosition.row)
|
||||
};
|
||||
|
||||
grid.onDrag.notify(dd, event, grid);
|
||||
$(window).mouseup();
|
||||
});
|
||||
it('should call handleDragEnd from CellRangeSelector', function () {
|
||||
var newRange = grid.getSelectionModel().getSelectedRanges();
|
||||
|
||||
expect(newRange.length).toBe(1);
|
||||
|
||||
expect(newRange[0].fromCell).toBe(1);
|
||||
expect(newRange[0].toCell).toBe(3);
|
||||
expect(newRange[0].fromRow).toBe(1);
|
||||
expect(newRange[0].toRow).toBe(4);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when we mouse up and no drag and drop occured', function () {
|
||||
beforeEach(function () {
|
||||
grid.onDragEnd.notify = jasmine.createSpy('notify');
|
||||
grid.onDragEnd.notify.calls.reset();
|
||||
$(window).mouseup();
|
||||
});
|
||||
|
||||
it('do not notify onDragEnd', function () {
|
||||
expect(grid.onDragEnd.notify).not.toHaveBeenCalled()
|
||||
});
|
||||
});
|
||||
|
||||
describe('setSelectedRows', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
grid.getSelectionModel().setSelectedRanges(
|
||||
[new Slick.Range(1, 1, 1, 1)]
|
||||
);
|
||||
});
|
||||
|
||||
describe('when passed an empty array', function () {
|
||||
beforeEach(function () {
|
||||
grid.getSelectionModel().setSelectedRows([]);
|
||||
});
|
||||
it('clears ranges', function () {
|
||||
var newRanges = grid.getSelectionModel().getSelectedRanges();
|
||||
expect(newRanges.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('sets ranges corresponding to rows', function () {
|
||||
grid.getSelectionModel().setSelectedRows([0, 2]);
|
||||
|
||||
var selectedRanges = grid.getSelectionModel().getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toBe(2);
|
||||
expectRangeToMatch(selectedRanges[0], 0, 1, 0, 3);
|
||||
expectRangeToMatch(selectedRanges[1], 2, 1, 2, 3);
|
||||
});
|
||||
});
|
||||
|
||||
function pressKey(keyCode) {
|
||||
var pressEvent = new $.Event("keydown");
|
||||
pressEvent.which = keyCode;
|
||||
|
||||
$(container.find('.grid-canvas')).trigger(pressEvent);
|
||||
}
|
||||
|
||||
function pressShiftPlusKey(keyCode) {
|
||||
var pressEvent = new $.Event("keydown");
|
||||
pressEvent.shiftKey = true;
|
||||
pressEvent.which = keyCode;
|
||||
|
||||
$(container.find('.grid-canvas')).trigger(pressEvent);
|
||||
}
|
||||
|
||||
function expectOneSelectedRange(fromRow, fromCell, toRow, toCell) {
|
||||
var selectedRanges = grid.getSelectionModel().getSelectedRanges();
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
expectRangeToMatch(selectedRanges[0], fromRow, fromCell, toRow, toCell);
|
||||
}
|
||||
|
||||
function expectRangeToMatch(range, fromRow, fromCell, toRow, toCell) {
|
||||
expect(range.fromRow).toBe(fromRow);
|
||||
expect(range.toRow).toBe(toRow);
|
||||
expect(range.fromCell).toBe(fromCell);
|
||||
expect(range.toCell).toBe(toCell);
|
||||
}
|
||||
});
|
||||
})
|
||||
;
|
||||
77
web/regression/javascript/slickgrid/cell_selector_spec.js
Normal file
77
web/regression/javascript/slickgrid/cell_selector_spec.js
Normal file
@@ -0,0 +1,77 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
define(["jquery",
|
||||
"slickgrid/slick.grid",
|
||||
"sources/selection/xcell_selection_model",
|
||||
"sources/slickgrid/cell_selector",
|
||||
"sources/selection/range_selection_helper"
|
||||
],
|
||||
function ($, SlickGrid, XCellSelectionModel, CellSelector, RangeSelectionHelper) {
|
||||
describe("CellSelector", function () {
|
||||
var container, columns, cellSelector, data, cellSelectionModel, grid;
|
||||
beforeEach(function () {
|
||||
container = $("<div></div>");
|
||||
container.height(9999);
|
||||
container.width(9999);
|
||||
columns = [{
|
||||
name: 'some-column-name',
|
||||
}, {
|
||||
name: 'second column',
|
||||
}];
|
||||
|
||||
cellSelector = new CellSelector();
|
||||
|
||||
data = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
data.push({'some-column-name': 'some-value-' + i, 'second column': 'second value ' + i});
|
||||
}
|
||||
grid = new SlickGrid(container, data, columns);
|
||||
|
||||
cellSelectionModel = new XCellSelectionModel();
|
||||
grid.setSelectionModel(cellSelectionModel);
|
||||
|
||||
grid.registerPlugin(cellSelector);
|
||||
grid.invalidate();
|
||||
|
||||
$("body").append(container);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
$("body").find(container).remove();
|
||||
});
|
||||
|
||||
describe("when the user clicks or tabs to a cell", function () {
|
||||
it("sets the selected range to that cell", function () {
|
||||
var row = 1, column = 0;
|
||||
$(container.find(".slick-row .slick-cell.l" + column)[row]).click();
|
||||
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
expect(selectedRanges[0].fromCell).toBe(0);
|
||||
expect(selectedRanges[0].toCell).toBe(0);
|
||||
expect(selectedRanges[0].fromRow).toBe(1);
|
||||
expect(selectedRanges[0].toRow).toBe(1);
|
||||
});
|
||||
|
||||
it("deselects previously selected ranges", function () {
|
||||
var row2Range = RangeSelectionHelper.rangeForRow(grid, 2);
|
||||
var ranges = RangeSelectionHelper.addRange(cellSelectionModel.getSelectedRanges(),
|
||||
row2Range);
|
||||
cellSelectionModel.setSelectedRanges(ranges);
|
||||
|
||||
var row = 4, column = 1;
|
||||
$(container.find(".slick-row .slick-cell.l" + column)[row]).click();
|
||||
|
||||
expect(RangeSelectionHelper.isRangeSelected(cellSelectionModel.getSelectedRanges(), row2Range))
|
||||
.toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,143 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
define([
|
||||
'sources/slickgrid/event_handlers/handle_query_output_keyboard_event',
|
||||
'sources/selection/clipboard',
|
||||
'sources/selection/range_selection_helper',
|
||||
'sources/selection/xcell_selection_model',
|
||||
'slickgrid'
|
||||
],
|
||||
function (handleQueryOutputKeyboardEvent, clipboard, RangeSelectionHelper, XCellSelectionModel) {
|
||||
var Slick = window.Slick;
|
||||
|
||||
describe('#handleQueryOutputKeyboardEvent', function () {
|
||||
var event, view, grid, slickEvent;
|
||||
beforeEach(function () {
|
||||
event = {
|
||||
shiftKey: false,
|
||||
ctrlKey: false,
|
||||
metaKey: false,
|
||||
which: -1,
|
||||
keyCode: -1,
|
||||
preventDefault: jasmine.createSpy('preventDefault')
|
||||
};
|
||||
|
||||
var data = [['', '0,0-cell-content', '0,1-cell-content'],
|
||||
['', '1,0-cell-content', '1,1-cell-content'],
|
||||
['', '2,0-cell-content', '2,1-cell-content']];
|
||||
var columnDefinitions = [{name: 'checkboxColumn'}, {pos: 1, name: 'firstColumn'}, {
|
||||
pos: 2,
|
||||
name: 'secondColumn'
|
||||
}];
|
||||
grid = new Slick.Grid($('<div></div>'), data, columnDefinitions);
|
||||
grid.setSelectionModel(new XCellSelectionModel());
|
||||
|
||||
slickEvent = {
|
||||
grid: grid
|
||||
};
|
||||
|
||||
view = {};
|
||||
spyOn(clipboard, 'copyTextToClipboard');
|
||||
});
|
||||
|
||||
describe("when a range is selected", function () {
|
||||
beforeEach(function () {
|
||||
grid.getSelectionModel().setSelectedRanges([
|
||||
RangeSelectionHelper.rangeForRow(grid, 0),
|
||||
RangeSelectionHelper.rangeForRow(grid, 2),
|
||||
]);
|
||||
});
|
||||
|
||||
describe("pressing Command + C", function () {
|
||||
beforeEach(function () {
|
||||
event.metaKey = true;
|
||||
event.keyCode = 67;
|
||||
});
|
||||
|
||||
it("copies the cell content to the clipboard", function () {
|
||||
handleQueryOutputKeyboardEvent(event, slickEvent);
|
||||
|
||||
expect(clipboard.copyTextToClipboard).toHaveBeenCalledWith("'0,0-cell-content','0,1-cell-content'\n'2,0-cell-content','2,1-cell-content'");
|
||||
});
|
||||
});
|
||||
|
||||
describe("pressing Ctrl + C", function () {
|
||||
beforeEach(function () {
|
||||
event.ctrlKey = true;
|
||||
event.keyCode = 67;
|
||||
});
|
||||
|
||||
it("copies the cell content to the clipboard", function () {
|
||||
handleQueryOutputKeyboardEvent(event, slickEvent);
|
||||
|
||||
expect(clipboard.copyTextToClipboard).toHaveBeenCalledWith("'0,0-cell-content','0,1-cell-content'\n'2,0-cell-content','2,1-cell-content'");
|
||||
});
|
||||
});
|
||||
|
||||
describe("pressing Command + A", function () {
|
||||
beforeEach(function () {
|
||||
event.metaKey = true;
|
||||
event.keyCode = 65;
|
||||
});
|
||||
|
||||
it("selects the entire grid to ranges", function () {
|
||||
handleQueryOutputKeyboardEvent(event, slickEvent);
|
||||
|
||||
expect(RangeSelectionHelper.isEntireGridSelected(grid)).toBeTruthy();
|
||||
expect(grid.getSelectionModel().getSelectedRanges().length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("pressing Ctrl + A", function () {
|
||||
beforeEach(function () {
|
||||
event.ctrlKey = true;
|
||||
event.keyCode = 65;
|
||||
});
|
||||
|
||||
it("selects the entire grid to ranges", function () {
|
||||
handleQueryOutputKeyboardEvent(event, slickEvent);
|
||||
|
||||
expect(RangeSelectionHelper.isEntireGridSelected(grid)).toBeTruthy();
|
||||
expect(grid.getSelectionModel().getSelectedRanges().length).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when no ranges are selected", function () {
|
||||
describe("pressing Command + A", function () {
|
||||
beforeEach(function () {
|
||||
event.metaKey = true;
|
||||
event.keyCode = 65;
|
||||
});
|
||||
|
||||
it("selects the entire grid to ranges", function () {
|
||||
handleQueryOutputKeyboardEvent(event, slickEvent);
|
||||
|
||||
expect(RangeSelectionHelper.isEntireGridSelected(grid)).toBeTruthy();
|
||||
expect(grid.getSelectionModel().getSelectedRanges().length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("pressing Ctrl + A", function () {
|
||||
beforeEach(function () {
|
||||
event.ctrlKey = true;
|
||||
event.keyCode = 65;
|
||||
});
|
||||
|
||||
it("selects the entire grid to ranges", function () {
|
||||
handleQueryOutputKeyboardEvent(event, slickEvent);
|
||||
|
||||
expect(RangeSelectionHelper.isEntireGridSelected(grid)).toBeTruthy();
|
||||
expect(grid.getSelectionModel().getSelectedRanges().length).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -36,7 +36,6 @@ require.config({
|
||||
'underscore.string': sourcesDir + 'vendor/underscore/underscore.string',
|
||||
'slickgrid': sourcesDir + 'vendor/slickgrid/slick.core',
|
||||
'slickgrid/slick.grid': sourcesDir + 'vendor/slickgrid/slick.grid',
|
||||
'slickgrid/slick.rowselectionmodel': sourcesDir + 'vendor/slickgrid/plugins/slick.rowselectionmodel',
|
||||
'translations': '/base/regression/javascript/fake_translations',
|
||||
'sources': sourcesDir + 'js',
|
||||
'browser': '/base/pgadmin/browser/static/js'
|
||||
@@ -58,11 +57,23 @@ require.config({
|
||||
],
|
||||
"exports": 'window.Slick.Grid'
|
||||
},
|
||||
"slickgrid/slick.rowselectionmodel": {
|
||||
"sources/slickgrid/pgslick.cellrangedecorator": {
|
||||
"deps": [
|
||||
"jquery"
|
||||
],
|
||||
"exports": 'window.Slick.RowSelectionModel'
|
||||
"exports": 'PGRowRangeDecorator'
|
||||
},
|
||||
"sources/slickgrid/pgslick.cellrangeselector": {
|
||||
"deps": [
|
||||
"jquery", "sources/slickgrid/pgslick.cellrangedecorator"
|
||||
],
|
||||
"exports": 'PGCellRangeSelector'
|
||||
},
|
||||
"sources/selection/xcell_selection_model": {
|
||||
"deps": [
|
||||
"jquery", "sources/slickgrid/pgslick.cellrangeselector"
|
||||
],
|
||||
"exports": 'XCellSelectionModel'
|
||||
},
|
||||
"backbone": {
|
||||
"deps": ['underscore', 'jquery'],
|
||||
|
||||
Reference in New Issue
Block a user