Skip to content
This repository was archived by the owner on Dec 19, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ For more information on PR's step, please see links of Contributing section.
- [Shop by](https://www.godo.co.kr/shopby/main.gd)
- [Payco](https://www.payco.com/)
- [YES24 - Movie Management System (Admin Tools)](http://m.movie.yes24.com/Movie/CurrentMovie.aspx)
- [coreBOS](https://corebos.com)

## 📜 License

Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"packages": ["packages/*"],
"version": "4.16.1"
"version": "4.17.0"
}
9 changes: 9 additions & 0 deletions packages/toast-ui.grid/cypress/helper/util.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { RowKey } from '@t/store/data';

type Address = [number, number];

export function clipboardType(key: string) {
Expand Down Expand Up @@ -34,3 +36,10 @@ export function setSelectionUsingMouse(start: Address, end: Address) {
.trigger('mouseup');
});
}

export function dragAndDrop(rowKey: RowKey, position: number) {
cy.getCell(rowKey, '_draggable')
.trigger('mousedown')
.trigger('mousemove', { pageY: position, force: true })
.trigger('mouseup', { force: true });
}
67 changes: 66 additions & 1 deletion packages/toast-ui.grid/cypress/integration/data.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { OptGrid } from '@t/options';
import { Row, RowKey } from '@t/store/data';
import { cls } from '@/helper/dom';
import { FormatterProps } from '@t/store/column';
import { invokeFilter, applyAliasHeaderCheckbox } from '../helper/util';
import { invokeFilter, applyAliasHeaderCheckbox, dragAndDrop } from '../helper/util';
import { assertGridHasRightRowNumber, assertHeaderCheckboxStatus } from '../helper/assert';

function assertHeaderCheckboxDisabled(disable: boolean) {
Expand Down Expand Up @@ -997,3 +997,68 @@ describe('getFormattedValue()', () => {
cy.gridInstance().invoke('getFormattedValue', 0, 'none').should('eq', null);
});
});

describe('D&D', () => {
function getActiveFocusLayer() {
return cy.getByCls('layer-focus');
}

beforeEach(() => {
const largeData = [
{ name: 'Kim', age: 10 },
{ name: 'Lee', age: 20 },
{ name: 'Ryu', age: 30 },
{ name: 'Han', age: 40 },
];
const columns = [
{ name: 'name', editor: 'text', sortable: true, filter: 'text' },
{ name: 'age', editor: 'text', sortable: true },
];

cy.createGrid({ data: largeData, columns, scrollY: true, bodyHeight: 400, draggable: true });
});

it('should move the row by dragging the row(bottom direction)', () => {
cy.getRsideBody().should('have.cellData', [
['Kim', '10'],
['Lee', '20'],
['Ryu', '30'],
['Han', '40'],
]);

dragAndDrop(1, 140);

cy.getRsideBody().should('have.cellData', [
['Kim', '10'],
['Ryu', '30'],
['Lee', '20'],
['Han', '40'],
]);
});

it('should move the row by dragging the row(top direction)', () => {
cy.getRsideBody().should('have.cellData', [
['Kim', '10'],
['Lee', '20'],
['Ryu', '30'],
['Han', '40'],
]);

dragAndDrop(1, 40);

cy.getRsideBody().should('have.cellData', [
['Lee', '20'],
['Kim', '10'],
['Ryu', '30'],
['Han', '40'],
]);
});

it('should remove the focus when triggering mousedown to drag element', () => {
cy.gridInstance().invoke('focus', 1, 'name');

dragAndDrop(1, 40);

getActiveFocusLayer().should('not.exist');
});
});
79 changes: 57 additions & 22 deletions packages/toast-ui.grid/cypress/integration/dummyRows.spec.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,70 @@
import { cls } from '@/helper/dom';

before(() => {
cy.visit('/dist');
});

beforeEach(() => {
const columns = [{ name: 'id', editor: 'text' }, { name: 'name' }];
const data = [
{ id: 1, name: 'Kim', score: 90, grade: 'A' },
{ id: 2, name: 'Lee', score: 80, grade: 'B' },
];
cy.createGrid({ data, columns, bodyHeight: 400, showDummyRows: true });
});
describe('basic case', () => {
beforeEach(() => {
const columns = [{ name: 'id', editor: 'text' }, { name: 'name' }];
const data = [
{ id: 1, name: 'Kim', score: 90, grade: 'A' },
{ id: 2, name: 'Lee', score: 80, grade: 'B' },
];
cy.createGrid({ data, columns, bodyHeight: 400, showDummyRows: true });
});

it('should render dummy rows', () => {
cy.getByCls('cell-dummy').should('exist');
});
it('should render dummy rows', () => {
cy.getByCls('cell-dummy').should('exist');
});

it('should initialize focus and selection layer', () => {
cy.gridInstance().invoke('focusAt', 0, 0);
cy.gridInstance().invoke('setSelectionRange', { start: [0, 0], end: [0, 0] });

cy.getByCls('cell-dummy').first().click();

cy.getByCls('layer-focus').should('not.exist');
cy.getByCls('layer-selection').should('not.visible');
});

it('should inialize focus and selection layer', () => {
cy.gridInstance().invoke('focusAt', 0, 0);
cy.gridInstance().invoke('setSelectionRange', { start: [0, 0], end: [0, 0] });
it('should save the editing result when clicking the dummy cell', () => {
cy.gridInstance().invoke('startEditing', 0, 'id');
cy.getByCls('content-text').type('test');

cy.getByCls('cell-dummy').first().click();
cy.getByCls('cell-dummy').first().click();

cy.getByCls('layer-focus').should('not.exist');
cy.getByCls('layer-selection').should('not.visible');
cy.getCell(0, 'id').should('have.text', 'test');
});
});

it('should save the editing result when clicking the dummy cell', () => {
cy.gridInstance().invoke('startEditing', 0, 'id');
cy.getByCls('content-text').type('test');
describe('The grid with filters', () => {
beforeEach(() => {
const columns = [
{ name: 'name', minWidth: 200, filter: 'text' },
{ name: 'artist', minWidth: 200 },
{ name: 'type', minWidth: 200 },
{ name: 'price', minWidth: 200 },
{ name: 'release', minWidth: 200 },
{ name: 'genre', minWidth: 200 },
];
const data = [
{ name: 'Beautiful Lies', artist: 'Birdy' },
{ name: 'X', artist: 'Ed Sheeran' },
];
cy.createGrid({ data, columns, bodyHeight: 400, showDummyRows: true });
});

cy.getByCls('cell-dummy').first().click();
it('should show dummy cells when scrollX is located at the farthest right', () => {
cy.gridInstance().invoke('filter', 'name', [{ code: 'eq', value: 'text' }]);
cy.getRsideBody()
.scrollTo('right')
.should(($el) => {
setTimeout(() => {
const leftPos = $el.find(`.${cls('table-container')}`).css('left');

cy.getCell(0, 'id').should('have.text', 'test');
expect(leftPos).eq('200px');
});
});
});
});
12 changes: 11 additions & 1 deletion packages/toast-ui.grid/cypress/integration/editor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ it('should do synchronous rendering of the editing cell', () => {

describe('select, checkbox, radio editor', () => {
function createGridWithType(type: string) {
const data = [{ name: '1' }, { name: '2' }, { name: '3' }];
const data = [{ name: '1' }, { name: '2' }, { name: '3' }, { name: '4' }];
const columns = [
{
name: 'name',
Expand Down Expand Up @@ -391,6 +391,16 @@ describe('select, checkbox, radio editor', () => {
}
});
});

it('should return a empty string when selecting a value that is not in the select box', () => {
createGridWithType('select');

cy.gridInstance().invoke('startEditing', 3, 'name');
// finish editing by clicking the another cell
cy.getCell(0, 'name').click();

cy.getCell(3, 'name').should('have.text', '');
});
});

// @TODO: There is a issue that the checkbox is unchecked when cypress type. Only the hover style is tested.
Expand Down
57 changes: 53 additions & 4 deletions packages/toast-ui.grid/cypress/integration/eventBus.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ beforeEach(() => {
cy.createGrid({
data,
columns,
draggable: true,
bodyHeight: 150,
width: 500,
rowHeaders: ['rowNum', 'checkbox'],
Expand Down Expand Up @@ -171,18 +172,18 @@ it('onGridBeforeDestroy', () => {
});

it('columnResize', () => {
const callback = cy.stub();
const stub = cy.stub();

cy.gridInstance().invoke('on', 'columnResize', callback);
cy.gridInstance().invoke('on', 'columnResize', stub);

cy.getByCls('column-resize-handle')
.first()
.trigger('mousedown')
.trigger('mousemove', { pageX: 400 })
.trigger('mouseup');

cy.wrap(callback).should('be.calledWithMatch', {
resizedColumns: [{ columnName: 'name', width: 311 }],
cy.wrap(stub).should('be.calledWithMatch', {
resizedColumns: [{ columnName: 'name', width: 271 }],
});
});

Expand Down Expand Up @@ -679,3 +680,51 @@ describe('beforeChange, afterChange', () => {
});
// @TODO: add test case when pasting the data
});

describe('D&D', () => {
it('dragStart event', () => {
const stub = cy.stub();

cy.gridInstance().invoke('on', 'dragStart', stub);
cy.getCell(0, '_draggable')
.trigger('mousedown')
.then(() => {
cy.getByCls('floating-row').then((floatingRow) => {
cy.wrap(stub).should('be.calledWithMatch', {
rowKey: 0,
floatingRow: floatingRow[0],
});
});
});
});

it('drag event', () => {
const stub = cy.stub();
cy.gridInstance().invoke('on', 'drag', stub);

cy.getCell(0, '_draggable')
.trigger('mousedown')
.trigger('mousemove', { pageY: 100, force: true });

cy.wrap(stub).should('be.calledWithMatch', {
rowKey: 0,
targetRowKey: 1,
});
});

it('drop event', () => {
const stub = cy.stub();
cy.gridInstance().invoke('on', 'drop', stub);

cy.getCell(0, '_draggable')
.trigger('mousedown')
.trigger('mousemove', { pageY: 100, force: true })
.trigger('mouseup', { force: true });

cy.wrap(stub).should('be.calledWithMatch', {
rowKey: 0,
targetRowKey: 1,
appended: false,
});
});
});
62 changes: 62 additions & 0 deletions packages/toast-ui.grid/cypress/integration/filter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,68 @@ describe('apply filter (type: select)', () => {
});
});

describe('apply filter (type: select) with nil(null, undefined) or empty string value', () => {
const columns = [{ name: 'id', filter: 'select' }, { name: 'name' }];
const data = [
{ id: 'player1', name: 'Choi' },
{ id: 'player2', name: 'Kim' },
{ id: 'player3', name: 'Ryu' },
{ id: null, name: 'Pyo' },
{ id: '', name: 'Oh' },
// eslint-disable-next-line no-undefined
{ id: undefined, name: 'Kwag' },
];

beforeEach(() => {
cy.createGrid({ data, columns });
});

it(`should display 'Empty value' in select filter`, () => {
clickFilterBtn();

const selectFilterList = getFilterListItem();
const expected = ['Select All', 'player1', 'player2', 'player3', 'Empty Value'];

selectFilterList.each(($el, index) => {
cy.wrap($el).should('have.text', expected[index]);
});
});

['API', 'UI'].forEach((method) => {
it(`should filter all empty values(null, undefined, empty string) by ${method}`, () => {
if (method === 'API') {
invokeFilter('id', [
{ code: 'eq', value: 'player1' },
{ code: 'eq', value: 'player2' },
{ code: 'eq', value: 'player3' },
]);
} else {
applyFilterBySelectUI(4);
}
cy.getRsideBody().should('have.cellData', [
['player1', 'Choi'],
['player2', 'Kim'],
['player3', 'Ryu'],
]);
});
});

it(`should toggle all empty values(null, undefined, empty string)`, () => {
applyFilterBySelectUI(4);

toggleSelectFilter(4);

cy.getRsideBody().should('have.cellData', [
['player1', 'Choi'],
['player2', 'Kim'],
['player3', 'Ryu'],
['', 'Pyo'],
['', 'Oh'],
['', 'Kwag'],
]);
});
});

describe('apply filter (type: datepicker)', () => {
const columns = [{ name: 'id' }, { name: 'date', filter: 'date' }];
const data = [
Expand Down
Loading