From c51af02ddb86617f8d4d96cc18621be87121ed1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20I=C3=9Fbr=C3=BCcker?= Date: Tue, 20 Apr 2021 14:30:54 +0200 Subject: [PATCH] fix: clear details-opened attribute when item is removed (#225) (CP: 6) --- src/vaadin-grid.js | 1 + test/row-details.test.js | 93 ++++++++++++++++++++++++++++++++-------- 2 files changed, 77 insertions(+), 17 deletions(-) diff --git a/src/vaadin-grid.js b/src/vaadin-grid.js index 15e1609bf..6ad9cb45e 100644 --- a/src/vaadin-grid.js +++ b/src/vaadin-grid.js @@ -807,6 +807,7 @@ class GridElement extends ElementMixin( this._a11yUpdateRowSelected(row, model.selected); this._a11yUpdateRowLevel(row, model.level); this._toggleAttribute('expanded', model.expanded, row); + this._toggleAttribute('details-opened', this._isDetailsOpened(item), row); if (this._rowDetailsTemplate || this.rowDetailsRenderer) { this._toggleDetailsCell(row, item); } diff --git a/test/row-details.test.js b/test/row-details.test.js index 9c53c0570..02548fc87 100644 --- a/test/row-details.test.js +++ b/test/row-details.test.js @@ -1,15 +1,16 @@ import { expect } from '@esm-bundle/chai'; import sinon from 'sinon'; import { fixtureSync, nextFrame } from '@open-wc/testing-helpers'; -import { PolymerElement, html } from '@polymer/polymer/polymer-element.js'; +import { html, PolymerElement } from '@polymer/polymer/polymer-element.js'; import '@polymer/polymer/lib/elements/dom-repeat.js'; import { + buildDataSet, click, flushGrid, getBodyCellContent, getCellContent, - getRows, getRowCells, + getRows, infiniteDataProvider, scrollToEnd } from './helpers.js'; @@ -49,6 +50,14 @@ describe('row details', () => { let grid; let bodyRows; + function openRowDetails(index) { + grid.openItemDetails(grid._cache.items[index]); + } + + function closeRowDetails(index) { + grid.closeItemDetails(grid._cache.items[index]); + } + it('should not increase row update count', () => { grid = fixtureSync(` @@ -66,10 +75,6 @@ describe('row details', () => { }); describe('simple', () => { - function openRowDetails(index) { - grid.openItemDetails(grid._cache.items[index]); - } - beforeEach(async () => { grid = fixtureSync(` @@ -85,10 +90,6 @@ describe('row details', () => { await nextFrame(); }); - function closeRowDetails(index) { - grid.closeItemDetails(grid._cache.items[index]); - } - it('should not activate on click', () => { openRowDetails(0); const detailsCellContent = getBodyCellContent(grid, 0, 1); @@ -157,13 +158,6 @@ describe('row details', () => { assertDetailsBounds(); }); - it('should have state attribute', () => { - openRowDetails(1); - expect(bodyRows[1].hasAttribute('details-opened')).to.be.true; - closeRowDetails(1); - expect(bodyRows[1].hasAttribute('details-opened')).to.be.false; - }); - it('should have correct bounds when modified after opening', async () => { openRowDetails(1); const cells = getRowCells(bodyRows[1]); @@ -297,4 +291,69 @@ describe('row details', () => { expect(row.offsetHeight).to.be.above(70); }); }); + + describe('details opened attribute', () => { + let dataset = []; + const dataProvider = (params, callback) => callback(dataset); + + const countRowsMarkedAsDetailsOpened = (grid) => { + return grid.$.items.querySelectorAll('tr[details-opened]').length; + }; + + beforeEach(async () => { + dataset = buildDataSet(10); + grid = fixtureSync(` + + + + + + + `); + grid.dataProvider = dataProvider; + flushGrid(grid); + bodyRows = getRows(grid.$.items); + await nextFrame(); + }); + + it('should update when opening/closing imperatively', () => { + openRowDetails(1); + expect(bodyRows[1].hasAttribute('details-opened')).to.be.true; + expect(countRowsMarkedAsDetailsOpened(grid)).to.equal(1); + closeRowDetails(1); + expect(bodyRows[1].hasAttribute('details-opened')).to.be.false; + expect(countRowsMarkedAsDetailsOpened(grid)).to.equal(0); + }); + + it('should be removed when item is removed', () => { + openRowDetails(0); + dataset.shift(); // remove opened item + grid.clearCache(); + + expect(bodyRows[0].hasAttribute('details-opened')).to.be.false; + expect(countRowsMarkedAsDetailsOpened(grid)).to.equal(0); + }); + + it('should be removed when items are replaced', () => { + openRowDetails(0); + dataset = buildDataSet(10); // replace data + grid.clearCache(); + + expect(bodyRows[0].hasAttribute('details-opened')).to.be.false; + expect(countRowsMarkedAsDetailsOpened(grid)).to.equal(0); + }); + + it('should be removed on all rows when items are replaced', () => { + // Open all rows + dataset.forEach((_, i) => { + openRowDetails(i); + }); + expect(countRowsMarkedAsDetailsOpened(grid)).to.equal(dataset.length); + + dataset = buildDataSet(10); // replace data + grid.clearCache(); + + expect(countRowsMarkedAsDetailsOpened(grid)).to.equal(0); + }); + }); });