Skip to content

Commit

Permalink
Merge pull request #1645 from ghiscoding/chore/drag-recycle-bin-e2e
Browse files Browse the repository at this point in the history
chore: improve Drag to Recycle Bin and add Cypress tests [refresh gh-pages]
  • Loading branch information
ghiscoding authored Aug 20, 2024
2 parents f904ee3 + af390b5 commit b231d89
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 52 deletions.
2 changes: 1 addition & 1 deletion examples/vite-demo-vanilla-bundle/src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ <h4 class="is-size-4 has-text-white">Slickgrid-Universal</h4>
Example28 - Infinite Scroll from JSON data
</a>
<a class="navbar-item" onclick.delegate="loadRoute('example29')">
Example29 - Row Reordering & Drag to Delete
Example29 - Row Reordering & Drag to Recycle Bin
</a>
</div>
</div>
Expand Down
15 changes: 4 additions & 11 deletions examples/vite-demo-vanilla-bundle/src/examples/example29.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<h3 class="title is-3">
Example 29 - Row Reordering & Drag to Delete
Example 29 - Row Reordering & Drag to Recycle Bin

<div class="subtitle code-link">
<span class="is-size-6">see</span>
Expand All @@ -18,24 +18,17 @@ <h6 class="title is-6 italic content">
</ul>
</h6>

<div class="columns">
<div class="column is-8">
<div class="columns is-desktop">
<div class="column">
<div class="grid29-1">
<div class="grid-header">
<label>Santa's TODO list:</label>
</div>
</div>
</div>
<div class="column is-4">
<div class="column">
<div id="dropzone" class="recycle-bin">
Recycle Bin
</div>
</div>
</div>

<div class="column is-half">
<hr class="my-4" />
</div>

<div class="grid29-2">
</div>
23 changes: 22 additions & 1 deletion examples/vite-demo-vanilla-bundle/src/examples/example29.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
.drag-message {
position: absolute;
display: inline-block;
padding: 4px 10px;
background: #e0e0e0;
border: 1px solid gray;
z-index: 99999;
border-radius: 8px;
box-shadow: 2px 2px 6px silver;
}

.grid-header {
display: flex;
align-items: center;
Expand All @@ -11,6 +22,8 @@
}

.recycle-bin {
background: transparent;
cursor: default;
width: 120px;
border: 2px solid #e4e4e4;
background: beige;
Expand All @@ -20,4 +33,12 @@
color: black;
text-align: center;
border-radius: 10px;
}

&.drag-dropzone {
border: 2px dashed pink;
}
&.drag-hover {
background: pink;
cursor: crosshair;
}
}
49 changes: 10 additions & 39 deletions examples/vite-demo-vanilla-bundle/src/examples/example29.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,9 @@ import { BindingEventService } from '@slickgrid-universal/binding';
export default class Example29 {
private _bindingEventService: BindingEventService;
gridOptions1!: GridOption;
gridOptions2!: GridOption;
columnDefinitions1!: Column[];
columnDefinitions2!: Column[];
dataset1!: any[];
dataset2!: any[];
sgb1!: SlickVanillaGridBundle;
sgb2!: SlickVanillaGridBundle;
dragHelper;
dragRows: number[];
dragMode = '';
Expand All @@ -26,14 +22,11 @@ export default class Example29 {
attached() {
this.defineGrids();
const gridContainer1Elm = document.querySelector(`.grid29-1`) as HTMLDivElement;
const gridContainer2Elm = document.querySelector(`.grid29-2`) as HTMLDivElement;

// mock some data (different in each dataset)
this.dataset1 = this.mockData(1);
this.dataset2 = this.mockData(2);

this.sgb1 = new Slicker.GridBundle(gridContainer1Elm, this.columnDefinitions1, { ...ExampleGridOptions, ...this.gridOptions1 }, this.dataset1);
this.sgb2 = new Slicker.GridBundle(gridContainer2Elm, this.columnDefinitions2, { ...ExampleGridOptions, ...this.gridOptions2 }, this.dataset2);

// bind any of the grid events
this._bindingEventService.bind(gridContainer1Elm, 'ondraginit', this.handleOnDragInit.bind(this) as EventListener);
Expand All @@ -44,7 +37,6 @@ export default class Example29 {

dispose() {
this.sgb1?.dispose();
this.sgb2?.dispose();
}

isBrowserDarkModeEnabled() {
Expand Down Expand Up @@ -81,11 +73,6 @@ export default class Example29 {
// usabilityOverride: (row, dataContext, grid) => dataContext.id % 2 === 1
},
};

// copy the same Grid Options and Column Definitions to 2nd grid
// but also add Pagination in this grid
this.columnDefinitions2 = this.columnDefinitions1;
this.gridOptions2 = { ...this.gridOptions1 };
}

mockData(gridNo: 1 | 2) {
Expand Down Expand Up @@ -189,24 +176,14 @@ export default class Example29 {
this.dragRows = selectedRows;
const dragCount = selectedRows.length;

const proxy = document.createElement('span');
proxy.style.position = 'absolute';
proxy.style.display = 'inline-block';
proxy.style.padding = '4px 10px';
proxy.style.background = '#e0e0e0';
proxy.style.border = '1px solid gray';
proxy.style.zIndex = '99999';
proxy.style.borderRadius = '8px';
proxy.style.boxShadow = '2px 2px 6px silver';
proxy.textContent = `Drag to Recycle Bin to delete ${dragCount} selected row(s)`;
document.body.appendChild(proxy);

this.dragHelper = proxy;

const dropzoneElm = document.querySelector<HTMLDivElement>('#dropzone')!;
dropzoneElm.style.border = '2px dashed pink';
const dragMsgElm = document.createElement('span');
dragMsgElm.className = 'drag-message';
dragMsgElm.textContent = `Drag to Recycle Bin to delete ${dragCount} selected row(s)`;
this.dragHelper = dragMsgElm;
document.body.appendChild(dragMsgElm);
document.querySelector<HTMLDivElement>('#dropzone')?.classList.add('drag-dropzone');

return proxy;
return dragMsgElm;
}

handleOnDrag(e: CustomEvent) {
Expand All @@ -223,12 +200,9 @@ export default class Example29 {
// add/remove pink background color when hovering recycle bin
const dropzoneElm = document.querySelector<HTMLDivElement>('#dropzone')!;
if (args.target instanceof HTMLElement && (args.target.id === 'dropzone' || args.target === dropzoneElm)) {
dropzoneElm.style.background = 'pink'; // OR: dd.target.style.background = 'pink';
dropzoneElm.style.cursor = 'crosshair';

dropzoneElm.classList.add('drag-hover'); // OR: dd.target.style.background = 'pink';
} else {
dropzoneElm.style.cursor = 'default';
dropzoneElm.style.background = '';
dropzoneElm.classList.remove('drag-hover');
}
}

Expand All @@ -238,8 +212,7 @@ export default class Example29 {
return;
}
this.dragHelper.remove();
const dropzoneElm = document.querySelector<HTMLDivElement>('#dropzone')!;
dropzoneElm.style.border = '2px solid #e4e4e4';
document.querySelector<HTMLDivElement>('#dropzone')?.classList.remove('drag-dropzone', 'drag-hover');

if (this.dragMode != 'recycle' || args.target.id !== 'dropzone') {
return;
Expand All @@ -253,8 +226,6 @@ export default class Example29 {
this.sgb1.dataset = this.dataset1;
this.sgb1.slickGrid?.invalidate();
this.sgb1.slickGrid?.setSelectedRows([]);

dropzoneElm.style.background = '';
}

requiredFieldValidator(value: any) {
Expand Down
95 changes: 95 additions & 0 deletions test/cypress/e2e/example29.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
describe('Example 29 - Row Reordering & Drag to Recycle Bin', () => {
const GRID_ROW_HEIGHT = 33;
const titles = ['', 'Name', 'Complete'];

it('should display Example title', () => {
cy.visit(`${Cypress.config('baseUrl')}/example29`);
cy.get('h3').should('contain', 'Example 29 - Row Reordering & Drag to Recycle Bin');
});

it('should have exact Column Titles in the grid', () => {
cy.get('.grid29-1')
.find('.slick-header-columns')
.children()
.each(($child, index) => expect($child.text()).to.eq(titles[index]));
});

it('should expect first row to include "Task 0" and other specific properties', () => {
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(1)`).should('contain', 'Make a list');
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(2)`).find('.mdi.mdi-check').should('have.length', 1);
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(1)`).should('contain', 'Check it twice');
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(1)`).should('contain', `Find out who's naughty`);
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 3}px;"] > .slick-cell:nth(1)`).should('contain', `Find out who's nice`);
});

it('should drag 2nd row to 3rd position', () => {
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell.cell-reorder`).as('moveIconTask1');
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell.cell-reorder`).as('moveIconTask2');

cy.get('@moveIconTask2').should('have.length', 1);

cy.get('@moveIconTask2')
.trigger('mousedown', { which: 1, force: true })
.trigger('mousemove', 'bottomRight');

cy.get('@moveIconTask1')
.trigger('mousemove', 'bottomRight')
.trigger('mouseup', 'bottomRight', { which: 1, force: true });

cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(1)`).should('contain', 'Make a list');
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(1)`).should('contain', `Find out who's naughty`);
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(1)`).should('contain', 'Check it twice');
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 3}px;"] > .slick-cell:nth(1)`).should('contain', `Find out who's nice`);
});

it('should drag a single row "Check it twice" to recycle bin', () => {
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(1)`)
.contains(`Find out who's naughty`)
.trigger('mousedown', { which: 1, force: true })
.trigger('mousemove', 'bottomRight');

cy.get('.recycle-bin.drag-dropzone').should('have.length', 1);
cy.get('.drag-message')
.contains('Drag to Recycle Bin to delete 1 selected row(s)');

cy.get('#dropzone').trigger('mousemove', 'center');
cy.get('.recycle-bin.drag-hover').should('have.length', 1);
cy.get('#dropzone').trigger('mouseup', 'center', { which: 1, force: true });

cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(1)`).should('contain', 'Make a list');
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(1)`).should('contain', 'Check it twice');
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(1)`).should('contain', `Find out who's nice`);

cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(1)`).should('contain', 'Make a list');
cy.get('.slick-row').should('have.length', 3);
cy.get('.recycle-bin.drag-dropzone').should('have.length', 0);
cy.get('.recycle-bin.drag-hover').should('have.length', 0);
});

it('should be able to drag 2 last rows to recycle bin', () => {
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(1)`)
.contains(`Find out who's nice`)
.type('{ctrl}', { release: false })
.click();

cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(1)`)
.contains('Check it twice')
.click()
.trigger('mousedown', { which: 1, force: true })
.trigger('mousemove', 'bottomRight');

cy.get('.recycle-bin.drag-dropzone').should('have.length', 1);
cy.get('.drag-message')
.contains('Drag to Recycle Bin to delete 2 selected row(s)');

cy.get('#dropzone').trigger('mousemove', 'center');

cy.get('.recycle-bin.drag-hover').should('have.length', 1);
cy.get('#dropzone').trigger('mouseup', 'center', { which: 1, force: true });

cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(1)`).should('contain', 'Make a list');
cy.get('.slick-row').should('have.length', 1);
cy.get('.recycle-bin.drag-dropzone').should('have.length', 0);
cy.get('.recycle-bin.drag-hover').should('have.length', 0);
});
});

0 comments on commit b231d89

Please sign in to comment.