From f4773bbb61681af51d5c248d762445a3ca9abc18 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Mon, 19 Aug 2024 20:59:26 -0400 Subject: [PATCH 1/2] chore: improve Drag to Recycle Bin and add Cypress tests --- .../src/examples/example29.html | 13 +-- .../src/examples/example29.scss | 23 ++++- .../src/examples/example29.ts | 49 ++-------- test/cypress/e2e/example29.cy.ts | 95 +++++++++++++++++++ 4 files changed, 130 insertions(+), 50 deletions(-) create mode 100644 test/cypress/e2e/example29.cy.ts diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example29.html b/examples/vite-demo-vanilla-bundle/src/examples/example29.html index c618f0e72..ca7c3b6a1 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example29.html +++ b/examples/vite-demo-vanilla-bundle/src/examples/example29.html @@ -18,24 +18,17 @@
-
-
+
+
-
+
Recycle Bin
- -
-
-
- -
-
\ No newline at end of file diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example29.scss b/examples/vite-demo-vanilla-bundle/src/examples/example29.scss index aa2f9dd38..501d543eb 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example29.scss +++ b/examples/vite-demo-vanilla-bundle/src/examples/example29.scss @@ -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; @@ -11,6 +22,8 @@ } .recycle-bin { + background: transparent; + cursor: default; width: 120px; border: 2px solid #e4e4e4; background: beige; @@ -20,4 +33,12 @@ color: black; text-align: center; border-radius: 10px; -} \ No newline at end of file + + &.drag-dropzone { + border: 2px dashed pink; + } + &.drag-hover { + background: pink; + cursor: crosshair; + } +} diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example29.ts b/examples/vite-demo-vanilla-bundle/src/examples/example29.ts index d3edb1cb3..2ffe86eaa 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example29.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example29.ts @@ -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 = ''; @@ -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); @@ -44,7 +37,6 @@ export default class Example29 { dispose() { this.sgb1?.dispose(); - this.sgb2?.dispose(); } isBrowserDarkModeEnabled() { @@ -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) { @@ -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('#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('#dropzone')?.classList.add('drag-dropzone'); - return proxy; + return dragMsgElm; } handleOnDrag(e: CustomEvent) { @@ -223,12 +200,9 @@ export default class Example29 { // add/remove pink background color when hovering recycle bin const dropzoneElm = document.querySelector('#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'); } } @@ -238,8 +212,7 @@ export default class Example29 { return; } this.dragHelper.remove(); - const dropzoneElm = document.querySelector('#dropzone')!; - dropzoneElm.style.border = '2px solid #e4e4e4'; + document.querySelector('#dropzone')?.classList.remove('drag-dropzone', 'drag-hover'); if (this.dragMode != 'recycle' || args.target.id !== 'dropzone') { return; @@ -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) { diff --git a/test/cypress/e2e/example29.cy.ts b/test/cypress/e2e/example29.cy.ts new file mode 100644 index 000000000..0a8e28cff --- /dev/null +++ b/test/cypress/e2e/example29.cy.ts @@ -0,0 +1,95 @@ +describe('Example 29 - Row Reordering & Drag to Delete', () => { + 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 Delete'); + }); + + 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); + }); +}); From af390b59ee8c06bd93d8713f6376dc085e04b4d2 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Mon, 19 Aug 2024 21:10:14 -0400 Subject: [PATCH 2/2] chore: rename example 29 title --- examples/vite-demo-vanilla-bundle/src/app.html | 2 +- examples/vite-demo-vanilla-bundle/src/examples/example29.html | 2 +- test/cypress/e2e/example29.cy.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/vite-demo-vanilla-bundle/src/app.html b/examples/vite-demo-vanilla-bundle/src/app.html index 42c9d6f73..da630fd48 100644 --- a/examples/vite-demo-vanilla-bundle/src/app.html +++ b/examples/vite-demo-vanilla-bundle/src/app.html @@ -121,7 +121,7 @@

Slickgrid-Universal

Example28 - Infinite Scroll from JSON data - Example29 - Row Reordering & Drag to Delete + Example29 - Row Reordering & Drag to Recycle Bin
diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example29.html b/examples/vite-demo-vanilla-bundle/src/examples/example29.html index ca7c3b6a1..d3027fa7a 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example29.html +++ b/examples/vite-demo-vanilla-bundle/src/examples/example29.html @@ -1,5 +1,5 @@

- Example 29 - Row Reordering & Drag to Delete + Example 29 - Row Reordering & Drag to Recycle Bin