11import { expect } from '@vaadin/chai-plugins' ;
22import { sendKeys } from '@vaadin/test-runner-commands' ;
3- import { enter , esc , fixtureSync , focusin , focusout , nextFrame } from '@vaadin/testing-helpers' ;
3+ import {
4+ aTimeout ,
5+ enter ,
6+ esc ,
7+ fixtureSync ,
8+ focusin ,
9+ focusout ,
10+ isFirefox ,
11+ nextFrame ,
12+ oneEvent ,
13+ } from '@vaadin/testing-helpers' ;
414import sinon from 'sinon' ;
515import './not-animated-styles.js' ;
616import '../src/vaadin-grid-pro.js' ;
@@ -10,6 +20,7 @@ import {
1020 dblclick ,
1121 flatMap ,
1222 flushGrid ,
23+ getCellContent ,
1324 getCellEditor ,
1425 getContainerCell ,
1526 getRowCells ,
@@ -570,6 +581,111 @@ describe('edit column', () => {
570581 } ) ;
571582 } ) ;
572583 } ) ;
584+
585+ describe ( 'lazy column rendering' , ( ) => {
586+ const UPDATE_CONTENT_VISIBILITY_DEBOUNCER_TIMEOUT = 100 ;
587+
588+ async function scrollHorizontally ( delta ) {
589+ grid . $ . table . scrollLeft += delta ;
590+ await oneEvent ( grid . $ . table , 'scroll' ) ;
591+ await aTimeout ( UPDATE_CONTENT_VISIBILITY_DEBOUNCER_TIMEOUT ) ;
592+ }
593+
594+ function getCellByColumnPath ( columnPath ) {
595+ const row = getRows ( grid . $ . items ) [ 0 ] ;
596+ const cells = getRowCells ( row ) ;
597+ const cell = cells . find ( ( c ) => c . _column . path === columnPath ) ;
598+ expect ( cell , `Could not find cell for column with path ${ columnPath } ` ) . to . be . ok ;
599+
600+ return cell ;
601+ }
602+
603+ beforeEach ( ( ) => {
604+ grid = fixtureSync ( `<vaadin-grid-pro style="width: 400px;"></vaadin-grid-pro>` ) ;
605+
606+ const columns = [ ] ;
607+ for ( let i = 0 ; i < 8 ; i ++ ) {
608+ const column = document . createElement ( 'vaadin-grid-pro-edit-column' ) ;
609+ column . path = `col${ i } ` ;
610+ column . header = `Col ${ i } ` ;
611+ column . width = '100px' ;
612+ column . flexGrow = 0 ;
613+ columns . push ( column ) ;
614+ grid . appendChild ( column ) ;
615+ }
616+
617+ grid . items = [
618+ { col0 : 'a0' , col1 : 'a1' , col2 : 'a2' , col3 : 'a3' , col4 : 'a4' , col5 : 'a5' , col6 : 'a6' , col7 : 'a7' } ,
619+ { col0 : 'b0' , col1 : 'b1' , col2 : 'b2' , col3 : 'b3' , col4 : 'b4' , col5 : 'b5' , col6 : 'b6' , col7 : 'b7' } ,
620+ ] ;
621+
622+ // Make odd-indexed columns conditionally editable
623+ columns . forEach ( ( column , i ) => {
624+ column . isCellEditable = ( ) => i % 2 === 1 ;
625+ } ) ;
626+
627+ grid . columnRendering = 'lazy' ;
628+ flushGrid ( grid ) ;
629+ } ) ;
630+
631+ it ( 'should mark initially visible cells as non-editable based on isCellEditable' , ( ) => {
632+ expect ( hasEditablePart ( 0 , 0 ) ) . to . be . false ;
633+ expect ( hasEditablePart ( 0 , 1 ) ) . to . be . true ;
634+ } ) ;
635+
636+ it ( 'should mark lazily rendered cells as non-editable based on isCellEditable after scrolling' , async ( ) => {
637+ // Scroll far enough to reveal the last columns
638+ await scrollHorizontally ( 400 ) ;
639+
640+ const cells = getRowCells ( getRows ( grid . $ . items ) [ 0 ] ) ;
641+
642+ // Verify we are testing correct cells
643+ expect ( getCellContent ( cells [ cells . length - 2 ] ) . textContent ) . to . equal ( 'a6' ) ;
644+ expect ( getCellContent ( cells [ cells . length - 1 ] ) . textContent ) . to . equal ( 'a7' ) ;
645+
646+ expect ( hasEditablePart ( 0 , cells . length - 2 ) ) . to . be . false ;
647+ expect ( hasEditablePart ( 0 , cells . length - 1 ) ) . to . be . true ;
648+ } ) ;
649+
650+ // Focus button mode that is active on MacOS causes issues with Tab key navigation in Firefox when run with Playwright
651+ ( isFirefox && isMac ? it . skip : it ) ( 'should navigate through editable cells with Tab' , async ( ) => {
652+ let cell = getCellByColumnPath ( 'col1' ) ;
653+ cell . focus ( ) ;
654+ await sendKeys ( { press : 'Enter' } ) ;
655+ expect ( getCellEditor ( cell ) ) . to . be . ok ;
656+
657+ await sendKeys ( { press : 'Tab' } ) ;
658+ cell = getCellByColumnPath ( 'col3' ) ;
659+ expect ( getCellEditor ( cell ) ) . to . be . ok ;
660+
661+ await sendKeys ( { press : 'Tab' } ) ;
662+ cell = getCellByColumnPath ( 'col5' ) ;
663+ expect ( getCellEditor ( cell ) ) . to . be . ok ;
664+
665+ await sendKeys ( { press : 'Tab' } ) ;
666+ cell = getCellByColumnPath ( 'col7' ) ;
667+ expect ( getCellEditor ( cell ) ) . to . be . ok ;
668+ } ) ;
669+
670+ it ( 'should edit cell again after it was temporarily removed due to scrolling' , async ( ) => {
671+ const cell = getCellByColumnPath ( 'col1' ) ;
672+ cell . focus ( ) ;
673+ await sendKeys ( { press : 'Enter' } ) ;
674+ expect ( getCellEditor ( cell ) ) . to . be . ok ;
675+
676+ await scrollHorizontally ( 500 ) ;
677+
678+ expect ( cell . isConnected ) . to . be . false ;
679+
680+ await scrollHorizontally ( - 500 ) ;
681+
682+ expect ( getCellEditor ( cell ) ) . to . not . be . ok ;
683+
684+ cell . focus ( ) ;
685+ await sendKeys ( { press : 'Enter' } ) ;
686+ expect ( getCellEditor ( cell ) ) . to . be . ok ;
687+ } ) ;
688+ } ) ;
573689 } ) ;
574690
575691 describe ( 'vertical scrolling' , ( ) => {
0 commit comments