@@ -413,4 +413,256 @@ test.describe('Collaboration', () => {
413
413
` ,
414
414
) ;
415
415
} ) ;
416
+
417
+ test ( 'Undo/redo where text node is split by formatting change' , async ( {
418
+ isRichText,
419
+ page,
420
+ isCollab,
421
+ browserName,
422
+ } ) => {
423
+ test . skip ( ! isCollab ) ;
424
+
425
+ // Left collaborator types two words, sets the second one to bold.
426
+ await focusEditor ( page ) ;
427
+ await page . keyboard . type ( 'normal bold' ) ;
428
+
429
+ await sleep ( 1050 ) ;
430
+ await selectCharacters ( page , 'left' , 'bold' . length ) ;
431
+ await toggleBold ( page ) ;
432
+
433
+ await assertHTML (
434
+ page ,
435
+ html `
436
+ < p
437
+ class ="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr "
438
+ dir ="ltr ">
439
+ < span data-lexical-text ="true "> normal</ span >
440
+ < strong
441
+ class ="PlaygroundEditorTheme__textBold "
442
+ data-lexical-text ="true ">
443
+ bold
444
+ </ strong >
445
+ </ p >
446
+ ` ,
447
+ ) ;
448
+
449
+ // Right collaborator types in the middle of the bold word.
450
+ await page
451
+ . frameLocator ( 'iframe[name="right"]' )
452
+ . locator ( '[data-lexical-editor="true"]' )
453
+ . focus ( ) ;
454
+ await page . keyboard . press ( 'ArrowDown' , { delay : 50 } ) ;
455
+ await page . keyboard . press ( 'ArrowLeft' ) ;
456
+ await page . keyboard . press ( 'ArrowLeft' ) ;
457
+ await page . keyboard . type ( 'BOLD' ) ;
458
+
459
+ await assertHTML (
460
+ page ,
461
+ html `
462
+ < p
463
+ class ="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr "
464
+ dir ="ltr ">
465
+ < span data-lexical-text ="true "> normal</ span >
466
+ < strong
467
+ class ="PlaygroundEditorTheme__textBold "
468
+ data-lexical-text ="true ">
469
+ boBOLDld
470
+ </ strong >
471
+ </ p >
472
+ ` ,
473
+ ) ;
474
+
475
+ // Left collaborator undoes their bold text.
476
+ await page . frameLocator ( 'iframe[name="left"]' ) . getByLabel ( 'Undo' ) . click ( ) ;
477
+
478
+ // The undo causes the text to be appended to the original string, like in the above test.
479
+ await assertHTML (
480
+ page ,
481
+ html `
482
+ < p
483
+ class ="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr "
484
+ dir ="ltr ">
485
+ < span data-lexical-text ="true "> normal boldBOLD</ span >
486
+ </ p >
487
+ ` ,
488
+ ) ;
489
+
490
+ // Left collaborator redoes the bold text.
491
+ await page . frameLocator ( 'iframe[name="left"]' ) . getByLabel ( 'Redo' ) . click ( ) ;
492
+
493
+ // The text should be back as it was prior to the undo.
494
+ await assertHTML (
495
+ page ,
496
+ html `
497
+ < p
498
+ class ="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr "
499
+ dir ="ltr ">
500
+ < span data-lexical-text ="true "> normal</ span >
501
+ < strong
502
+ class ="PlaygroundEditorTheme__textBold "
503
+ data-lexical-text ="true ">
504
+ boBOLDld
505
+ </ strong >
506
+ </ p >
507
+ ` ,
508
+ ) ;
509
+
510
+ // Collaboration should still work.
511
+ await page
512
+ . frameLocator ( 'iframe[name="right"]' )
513
+ . locator ( '[data-lexical-editor="true"]' )
514
+ . focus ( ) ;
515
+ await page . keyboard . press ( 'ArrowDown' , { delay : 50 } ) ;
516
+ await page . keyboard . type ( ' text' ) ;
517
+
518
+ await assertHTML (
519
+ page ,
520
+ html `
521
+ < p
522
+ class ="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr "
523
+ dir ="ltr ">
524
+ < span data-lexical-text ="true "> normal</ span >
525
+ < strong
526
+ class ="PlaygroundEditorTheme__textBold "
527
+ data-lexical-text ="true ">
528
+ boBOLDld text
529
+ </ strong >
530
+ </ p >
531
+ ` ,
532
+ ) ;
533
+ } ) ;
534
+
535
+ test ( 'Undo/redo where text node is split by inline element node' , async ( {
536
+ isRichText,
537
+ page,
538
+ isCollab,
539
+ browserName,
540
+ } ) => {
541
+ test . skip ( ! isCollab ) ;
542
+
543
+ // Left collaborator types some text, then splits the text nodes with an element node.
544
+ await focusEditor ( page ) ;
545
+ await page . keyboard . type ( 'Check out the website!' ) ;
546
+
547
+ await sleep ( 1050 ) ;
548
+ await page . keyboard . press ( 'ArrowLeft' ) ;
549
+ await selectCharacters ( page , 'left' , 'website' . length ) ;
550
+ await page
551
+ . frameLocator ( 'iframe[name="left"]' )
552
+ . getByLabel ( 'Insert link' )
553
+ . first ( )
554
+ . click ( ) ;
555
+
556
+ await assertHTML (
557
+ page ,
558
+ html `
559
+ < p
560
+ class ="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr "
561
+ dir ="ltr ">
562
+ < span data-lexical-text ="true "> Check out the</ span >
563
+ < a
564
+ class ="PlaygroundEditorTheme__link PlaygroundEditorTheme__ltr "
565
+ dir ="ltr "
566
+ href ="https:// "
567
+ rel ="noreferrer ">
568
+ < span data-lexical-text ="true "> website</ span >
569
+ </ a >
570
+ < span data-lexical-text ="true "> !</ span >
571
+ </ p >
572
+ ` ,
573
+ ) ;
574
+
575
+ // Right collaborator adds some text.
576
+ await page
577
+ . frameLocator ( 'iframe[name="right"]' )
578
+ . locator ( '[data-lexical-editor="true"]' )
579
+ . focus ( ) ;
580
+ await page . keyboard . press ( 'ArrowDown' , { delay : 50 } ) ;
581
+ await page . keyboard . press ( 'ArrowLeft' ) ;
582
+ await page . keyboard . type ( ' now' ) ;
583
+
584
+ await assertHTML (
585
+ page ,
586
+ html `
587
+ < p
588
+ class ="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr "
589
+ dir ="ltr ">
590
+ < span data-lexical-text ="true "> Check out the</ span >
591
+ < a
592
+ class ="PlaygroundEditorTheme__link PlaygroundEditorTheme__ltr "
593
+ dir ="ltr "
594
+ href ="https:// "
595
+ rel ="noreferrer ">
596
+ < span data-lexical-text ="true "> website</ span >
597
+ </ a >
598
+ < span data-lexical-text ="true "> now!</ span >
599
+ </ p >
600
+ ` ,
601
+ ) ;
602
+
603
+ // Left collaborator undoes the link.
604
+ await page . frameLocator ( 'iframe[name="left"]' ) . getByLabel ( 'Undo' ) . click ( ) ;
605
+
606
+ // The undo causes the text to be appended to the original string, like in the above test.
607
+ await assertHTML (
608
+ page ,
609
+ html `
610
+ < p
611
+ class ="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr "
612
+ dir ="ltr ">
613
+ < span data-lexical-text ="true "> Check out the website! now</ span >
614
+ </ p >
615
+ ` ,
616
+ ) ;
617
+
618
+ // Left collaborator redoes the link.
619
+ await page . frameLocator ( 'iframe[name="left"]' ) . getByLabel ( 'Redo' ) . click ( ) ;
620
+
621
+ // The text should be back as it was prior to the undo.
622
+ await assertHTML (
623
+ page ,
624
+ html `
625
+ < p
626
+ class ="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr "
627
+ dir ="ltr ">
628
+ < span data-lexical-text ="true "> Check out the</ span >
629
+ < a
630
+ class ="PlaygroundEditorTheme__link PlaygroundEditorTheme__ltr "
631
+ dir ="ltr "
632
+ href ="https:// "
633
+ rel ="noreferrer ">
634
+ < span data-lexical-text ="true "> website</ span >
635
+ </ a >
636
+ < span data-lexical-text ="true "> now!</ span >
637
+ </ p >
638
+ ` ,
639
+ ) ;
640
+
641
+ // Collaboration should still work.
642
+ await page
643
+ . frameLocator ( 'iframe[name="right"]' )
644
+ . locator ( '[data-lexical-editor="true"]' )
645
+ . focus ( ) ;
646
+ await page . keyboard . press ( 'ArrowDown' , { delay : 50 } ) ;
647
+ await page . keyboard . type ( ' Check it out.' ) ;
648
+
649
+ await assertHTML (
650
+ page ,
651
+ html `
652
+ < p
653
+ class ="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr "
654
+ dir ="ltr ">
655
+ < span data-lexical-text ="true "> Check out the</ span >
656
+ < a
657
+ class ="PlaygroundEditorTheme__link PlaygroundEditorTheme__ltr "
658
+ dir ="ltr "
659
+ href ="https:// "
660
+ rel ="noreferrer ">
661
+ < span data-lexical-text ="true "> website</ span >
662
+ </ a >
663
+ < span data-lexical-text ="true "> now! Check it out.</ span >
664
+ </ p >
665
+ ` ,
666
+ ) ;
667
+ } ) ;
416
668
} ) ;
0 commit comments