@wordpress/block-library 9.26.1-next.719a03cbe.0 → 9.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/cover/edit/block-controls.js +4 -2
  3. package/build/cover/edit/block-controls.js.map +1 -1
  4. package/build/cover/edit/index.js +6 -3
  5. package/build/cover/edit/index.js.map +1 -1
  6. package/build/cover/edit/inspector-controls.js +11 -4
  7. package/build/cover/edit/inspector-controls.js.map +1 -1
  8. package/build/cover/edit/poster-image.js +81 -0
  9. package/build/cover/edit/poster-image.js.map +1 -0
  10. package/build/cover/index.js +6 -0
  11. package/build/cover/index.js.map +1 -1
  12. package/build/cover/save.js +3 -1
  13. package/build/cover/save.js.map +1 -1
  14. package/build/media-text/edit.js +2 -2
  15. package/build/media-text/edit.js.map +1 -1
  16. package/build/navigation-link/edit.js +32 -15
  17. package/build/navigation-link/edit.js.map +1 -1
  18. package/build/navigation-link/update-attributes.js +112 -14
  19. package/build/navigation-link/update-attributes.js.map +1 -1
  20. package/build/navigation-submenu/edit.js +19 -2
  21. package/build/navigation-submenu/edit.js.map +1 -1
  22. package/build/post-content/edit.js +78 -16
  23. package/build/post-content/edit.js.map +1 -1
  24. package/build/post-content/index.js +6 -0
  25. package/build/post-content/index.js.map +1 -1
  26. package/build/separator/edit.js +5 -30
  27. package/build/separator/edit.js.map +1 -1
  28. package/build/site-tagline/index.js +1 -1
  29. package/build/video/edit.js +2 -5
  30. package/build/video/edit.js.map +1 -1
  31. package/build/video/poster-image.js +25 -25
  32. package/build/video/poster-image.js.map +1 -1
  33. package/build/video/tracks-editor.js +95 -104
  34. package/build/video/tracks-editor.js.map +1 -1
  35. package/build/video/tracks.js +6 -2
  36. package/build/video/tracks.js.map +1 -1
  37. package/build-module/cover/edit/block-controls.js +4 -2
  38. package/build-module/cover/edit/block-controls.js.map +1 -1
  39. package/build-module/cover/edit/index.js +6 -3
  40. package/build-module/cover/edit/index.js.map +1 -1
  41. package/build-module/cover/edit/inspector-controls.js +10 -4
  42. package/build-module/cover/edit/inspector-controls.js.map +1 -1
  43. package/build-module/cover/edit/poster-image.js +74 -0
  44. package/build-module/cover/edit/poster-image.js.map +1 -0
  45. package/build-module/cover/index.js +6 -0
  46. package/build-module/cover/index.js.map +1 -1
  47. package/build-module/cover/save.js +3 -1
  48. package/build-module/cover/save.js.map +1 -1
  49. package/build-module/media-text/edit.js +2 -2
  50. package/build-module/media-text/edit.js.map +1 -1
  51. package/build-module/navigation-link/edit.js +32 -15
  52. package/build-module/navigation-link/edit.js.map +1 -1
  53. package/build-module/navigation-link/update-attributes.js +113 -15
  54. package/build-module/navigation-link/update-attributes.js.map +1 -1
  55. package/build-module/navigation-submenu/edit.js +20 -3
  56. package/build-module/navigation-submenu/edit.js.map +1 -1
  57. package/build-module/post-content/edit.js +80 -18
  58. package/build-module/post-content/edit.js.map +1 -1
  59. package/build-module/post-content/index.js +6 -0
  60. package/build-module/post-content/index.js.map +1 -1
  61. package/build-module/separator/edit.js +6 -31
  62. package/build-module/separator/edit.js.map +1 -1
  63. package/build-module/site-tagline/index.js +1 -1
  64. package/build-module/video/edit.js +2 -5
  65. package/build-module/video/edit.js.map +1 -1
  66. package/build-module/video/poster-image.js +26 -26
  67. package/build-module/video/poster-image.js.map +1 -1
  68. package/build-module/video/tracks-editor.js +96 -105
  69. package/build-module/video/tracks-editor.js.map +1 -1
  70. package/build-module/video/tracks.js +6 -2
  71. package/build-module/video/tracks.js.map +1 -1
  72. package/build-style/archives/editor-rtl.css +0 -4
  73. package/build-style/archives/editor.css +0 -4
  74. package/build-style/editor-rtl.css +0 -8
  75. package/build-style/editor.css +0 -8
  76. package/build-style/file/style-rtl.css +1 -1
  77. package/build-style/file/style.css +1 -1
  78. package/build-style/navigation/style-rtl.css +1 -0
  79. package/build-style/navigation/style.css +1 -0
  80. package/build-style/style-rtl.css +2 -1
  81. package/build-style/style.css +2 -1
  82. package/build-style/video/editor-rtl.css +0 -4
  83. package/build-style/video/editor.css +0 -4
  84. package/package.json +35 -35
  85. package/src/archives/editor.scss +0 -4
  86. package/src/comments-pagination/index.php +7 -2
  87. package/src/cover/block.json +6 -0
  88. package/src/cover/edit/block-controls.js +22 -17
  89. package/src/cover/edit/index.js +4 -1
  90. package/src/cover/edit/inspector-controls.js +11 -2
  91. package/src/cover/edit/poster-image.js +91 -0
  92. package/src/cover/save.js +2 -0
  93. package/src/file/style.scss +1 -1
  94. package/src/media-text/edit.js +1 -1
  95. package/src/navigation/style.scss +1 -0
  96. package/src/navigation-link/edit.js +28 -16
  97. package/src/navigation-link/test/edit.js +738 -6
  98. package/src/navigation-link/update-attributes.js +125 -12
  99. package/src/navigation-submenu/edit.js +21 -1
  100. package/src/post-content/block.json +6 -0
  101. package/src/post-content/edit.js +71 -19
  102. package/src/post-content/index.php +11 -4
  103. package/src/post-featured-image/index.php +3 -2
  104. package/src/separator/edit.js +8 -43
  105. package/src/site-tagline/block.json +1 -1
  106. package/src/video/edit.js +1 -4
  107. package/src/video/editor.scss +0 -6
  108. package/src/video/poster-image.js +29 -24
  109. package/src/video/tracks-editor.js +93 -103
  110. package/src/video/tracks.js +2 -1
@@ -367,9 +367,9 @@ describe( 'edit', () => {
367
367
  url: 'https://wordpress.local/menu-test/',
368
368
  } );
369
369
  // Click on the existing link control, and toggle opens new tab.
370
+ // Note: When only opensInNewTab is changed (no URL change), ID should be retained
370
371
  updateAttributes(
371
372
  {
372
- url: 'https://wordpress.local/menu-test/',
373
373
  opensInNewTab: true,
374
374
  },
375
375
  setAttributes,
@@ -384,7 +384,7 @@ describe( 'edit', () => {
384
384
  url: 'https://wordpress.local/menu-test/',
385
385
  } );
386
386
  } );
387
- it( 'id is retained after editing url', () => {
387
+ it( 'id is removed after editing url', () => {
388
388
  const mockState = {};
389
389
  const setAttributes = jest.fn( ( attr ) =>
390
390
  Object.assign( mockState, attr )
@@ -407,7 +407,8 @@ describe( 'edit', () => {
407
407
  type: 'post',
408
408
  url: 'https://wordpress.local/menu-test/',
409
409
  } );
410
- // Click on the existing link control, and toggle opens new tab.
410
+ // Click on the existing link control, and change URL.
411
+ // Note: When URL is changed without a new ID, the original ID should be removed
411
412
  updateAttributes(
412
413
  {
413
414
  url: 'https://wordpress.local/foo/',
@@ -417,14 +418,745 @@ describe( 'edit', () => {
417
418
  mockState
418
419
  );
419
420
  expect( mockState ).toEqual( {
420
- id: 1337,
421
+ id: undefined,
421
422
  label: 'Menu Test',
422
423
  opensInNewTab: false,
423
- kind: 'post-type',
424
- type: 'post',
424
+ kind: 'custom',
425
+ type: 'custom',
425
426
  url: 'https://wordpress.local/foo/',
426
427
  } );
427
428
  } );
428
429
  } );
430
+
431
+ describe( 'ID handling when URL is manually changed', () => {
432
+ describe( 'URL modifications that should sever the entity link', () => {
433
+ it( 'should remove ID when URL path is changed', () => {
434
+ const setAttributes = jest.fn();
435
+ const blockAttributes = {
436
+ id: 123,
437
+ type: 'page',
438
+ kind: 'post-type',
439
+ url: 'https://example.com/original-page',
440
+ };
441
+
442
+ const updatedValue = {
443
+ url: 'https://example.com/different-page',
444
+ };
445
+
446
+ updateAttributes(
447
+ updatedValue,
448
+ setAttributes,
449
+ blockAttributes
450
+ );
451
+
452
+ expect( setAttributes ).toHaveBeenCalledWith(
453
+ expect.objectContaining( {
454
+ id: undefined,
455
+ kind: 'custom',
456
+ type: 'custom',
457
+ url: 'https://example.com/different-page',
458
+ } )
459
+ );
460
+ } );
461
+
462
+ it( 'should remove ID when changing to relative URL that does not match the path', () => {
463
+ const setAttributes = jest.fn();
464
+ const blockAttributes = {
465
+ id: 123,
466
+ type: 'page',
467
+ kind: 'post-type',
468
+ url: 'https://example.com/hello-world/',
469
+ };
470
+
471
+ const updatedValue = {
472
+ url: '/different-page',
473
+ };
474
+
475
+ updateAttributes(
476
+ updatedValue,
477
+ setAttributes,
478
+ blockAttributes
479
+ );
480
+
481
+ expect( setAttributes ).toHaveBeenCalledWith(
482
+ expect.objectContaining( {
483
+ id: undefined,
484
+ kind: 'custom',
485
+ type: 'custom',
486
+ url: '/different-page',
487
+ } )
488
+ );
489
+ } );
490
+
491
+ it( 'should remove ID when URL domain is changed', () => {
492
+ const setAttributes = jest.fn();
493
+ const blockAttributes = {
494
+ id: 123,
495
+ type: 'page',
496
+ kind: 'post-type',
497
+ url: 'https://example.com/page',
498
+ };
499
+
500
+ const updatedValue = {
501
+ url: 'https://different-site.com/page',
502
+ };
503
+
504
+ updateAttributes(
505
+ updatedValue,
506
+ setAttributes,
507
+ blockAttributes
508
+ );
509
+
510
+ expect( setAttributes ).toHaveBeenCalledWith(
511
+ expect.objectContaining( {
512
+ id: undefined,
513
+ kind: 'custom',
514
+ type: 'custom',
515
+ url: 'https://different-site.com/page',
516
+ } )
517
+ );
518
+ } );
519
+
520
+ it( 'should remove ID when plain permalink post ID is changed', () => {
521
+ const setAttributes = jest.fn();
522
+ const blockAttributes = {
523
+ id: 123,
524
+ type: 'page',
525
+ kind: 'post-type',
526
+ url: 'https://example.com/?p=123',
527
+ };
528
+
529
+ const updatedValue = {
530
+ url: 'https://example.com/?p=456',
531
+ };
532
+
533
+ updateAttributes(
534
+ updatedValue,
535
+ setAttributes,
536
+ blockAttributes
537
+ );
538
+
539
+ expect( setAttributes ).toHaveBeenCalledWith(
540
+ expect.objectContaining( {
541
+ id: undefined,
542
+ kind: 'custom',
543
+ type: 'custom',
544
+ url: 'https://example.com/?p=456',
545
+ } )
546
+ );
547
+ } );
548
+
549
+ it( 'should remove ID when changing from plain permalink to different plain permalink', () => {
550
+ const setAttributes = jest.fn();
551
+ const blockAttributes = {
552
+ id: 123,
553
+ type: 'page',
554
+ kind: 'post-type',
555
+ url: 'https://example.com/?p=123',
556
+ };
557
+
558
+ const updatedValue = {
559
+ url: 'https://example.com/?page_id=456',
560
+ };
561
+
562
+ updateAttributes(
563
+ updatedValue,
564
+ setAttributes,
565
+ blockAttributes
566
+ );
567
+
568
+ expect( setAttributes ).toHaveBeenCalledWith(
569
+ expect.objectContaining( {
570
+ id: undefined,
571
+ kind: 'custom',
572
+ type: 'custom',
573
+ url: 'https://example.com/?page_id=456',
574
+ } )
575
+ );
576
+ } );
577
+ } );
578
+
579
+ describe( 'URL modifications that should preserve the entity link', () => {
580
+ it( 'should preserve ID when changing to relative URL that matches the path', () => {
581
+ const setAttributes = jest.fn();
582
+ const blockAttributes = {
583
+ id: 123,
584
+ type: 'page',
585
+ kind: 'post-type',
586
+ url: 'https://example.com/hello-world/',
587
+ };
588
+
589
+ const updatedValue = {
590
+ url: '/hello-world/',
591
+ };
592
+
593
+ updateAttributes(
594
+ updatedValue,
595
+ setAttributes,
596
+ blockAttributes
597
+ );
598
+
599
+ expect( setAttributes ).toHaveBeenCalledWith(
600
+ expect.objectContaining( {
601
+ url: '/hello-world/',
602
+ } )
603
+ );
604
+ // Should not sever the entity link when relative URL matches the path
605
+ expect( setAttributes ).not.toHaveBeenCalledWith(
606
+ expect.objectContaining( {
607
+ id: undefined,
608
+ } )
609
+ );
610
+ } );
611
+
612
+ it( 'should preserve ID when only query string is added', () => {
613
+ const setAttributes = jest.fn();
614
+ const blockAttributes = {
615
+ id: 123,
616
+ type: 'page',
617
+ kind: 'post-type',
618
+ url: 'https://example.com/page',
619
+ };
620
+
621
+ const updatedValue = {
622
+ url: 'https://example.com/page?utm_source=test',
623
+ };
624
+
625
+ updateAttributes(
626
+ updatedValue,
627
+ setAttributes,
628
+ blockAttributes
629
+ );
630
+
631
+ expect( setAttributes ).toHaveBeenCalledWith(
632
+ expect.objectContaining( {
633
+ url: 'https://example.com/page?utm_source=test',
634
+ } )
635
+ );
636
+ expect( setAttributes ).not.toHaveBeenCalledWith(
637
+ expect.objectContaining( {
638
+ id: undefined,
639
+ } )
640
+ );
641
+ } );
642
+
643
+ it( 'should preserve ID when only hash fragment is added', () => {
644
+ const setAttributes = jest.fn();
645
+ const blockAttributes = {
646
+ id: 123,
647
+ type: 'page',
648
+ kind: 'post-type',
649
+ url: 'https://example.com/page',
650
+ };
651
+
652
+ const updatedValue = {
653
+ url: 'https://example.com/page#section',
654
+ };
655
+
656
+ updateAttributes(
657
+ updatedValue,
658
+ setAttributes,
659
+ blockAttributes
660
+ );
661
+
662
+ expect( setAttributes ).toHaveBeenCalledWith(
663
+ expect.objectContaining( {
664
+ url: 'https://example.com/page#section',
665
+ } )
666
+ );
667
+ expect( setAttributes ).not.toHaveBeenCalledWith(
668
+ expect.objectContaining( {
669
+ id: undefined,
670
+ } )
671
+ );
672
+ } );
673
+
674
+ it( 'should preserve ID when both query string and hash are added', () => {
675
+ const setAttributes = jest.fn();
676
+ const blockAttributes = {
677
+ id: 123,
678
+ type: 'page',
679
+ kind: 'post-type',
680
+ url: 'https://example.com/page',
681
+ };
682
+
683
+ const updatedValue = {
684
+ url: 'https://example.com/page?param=value#section',
685
+ };
686
+
687
+ updateAttributes(
688
+ updatedValue,
689
+ setAttributes,
690
+ blockAttributes
691
+ );
692
+
693
+ expect( setAttributes ).toHaveBeenCalledWith(
694
+ expect.objectContaining( {
695
+ url: 'https://example.com/page?param=value#section',
696
+ } )
697
+ );
698
+ expect( setAttributes ).not.toHaveBeenCalledWith(
699
+ expect.objectContaining( {
700
+ id: undefined,
701
+ } )
702
+ );
703
+ } );
704
+
705
+ it( 'should preserve ID when query string is modified', () => {
706
+ const setAttributes = jest.fn();
707
+ const blockAttributes = {
708
+ id: 123,
709
+ type: 'page',
710
+ kind: 'post-type',
711
+ url: 'https://example.com/page?old=value',
712
+ };
713
+
714
+ const updatedValue = {
715
+ url: 'https://example.com/page?new=value',
716
+ };
717
+
718
+ updateAttributes(
719
+ updatedValue,
720
+ setAttributes,
721
+ blockAttributes
722
+ );
723
+
724
+ expect( setAttributes ).toHaveBeenCalledWith(
725
+ expect.objectContaining( {
726
+ url: 'https://example.com/page?new=value',
727
+ } )
728
+ );
729
+ expect( setAttributes ).not.toHaveBeenCalledWith(
730
+ expect.objectContaining( {
731
+ id: undefined,
732
+ } )
733
+ );
734
+ } );
735
+
736
+ it( 'should preserve ID when hash fragment is modified', () => {
737
+ const setAttributes = jest.fn();
738
+ const blockAttributes = {
739
+ id: 123,
740
+ type: 'page',
741
+ kind: 'post-type',
742
+ url: 'https://example.com/page#old-section',
743
+ };
744
+
745
+ const updatedValue = {
746
+ url: 'https://example.com/page#new-section',
747
+ };
748
+
749
+ updateAttributes(
750
+ updatedValue,
751
+ setAttributes,
752
+ blockAttributes
753
+ );
754
+
755
+ expect( setAttributes ).toHaveBeenCalledWith(
756
+ expect.objectContaining( {
757
+ url: 'https://example.com/page#new-section',
758
+ } )
759
+ );
760
+ expect( setAttributes ).not.toHaveBeenCalledWith(
761
+ expect.objectContaining( {
762
+ id: undefined,
763
+ } )
764
+ );
765
+ } );
766
+
767
+ it( 'should preserve ID when protocol changes from http to https', () => {
768
+ const setAttributes = jest.fn();
769
+ const blockAttributes = {
770
+ id: 123,
771
+ type: 'page',
772
+ kind: 'post-type',
773
+ url: 'http://example.com/page',
774
+ };
775
+
776
+ const updatedValue = {
777
+ url: 'https://example.com/page',
778
+ };
779
+
780
+ updateAttributes(
781
+ updatedValue,
782
+ setAttributes,
783
+ blockAttributes
784
+ );
785
+
786
+ expect( setAttributes ).toHaveBeenCalledWith(
787
+ expect.objectContaining( {
788
+ url: 'https://example.com/page',
789
+ } )
790
+ );
791
+ expect( setAttributes ).not.toHaveBeenCalledWith(
792
+ expect.objectContaining( {
793
+ id: undefined,
794
+ } )
795
+ );
796
+ } );
797
+
798
+ it( 'should preserve ID when protocol changes from https to http', () => {
799
+ const setAttributes = jest.fn();
800
+ const blockAttributes = {
801
+ id: 123,
802
+ type: 'page',
803
+ kind: 'post-type',
804
+ url: 'https://example.com/page',
805
+ };
806
+
807
+ const updatedValue = {
808
+ url: 'http://example.com/page',
809
+ };
810
+
811
+ updateAttributes(
812
+ updatedValue,
813
+ setAttributes,
814
+ blockAttributes
815
+ );
816
+
817
+ expect( setAttributes ).toHaveBeenCalledWith(
818
+ expect.objectContaining( {
819
+ url: 'http://example.com/page',
820
+ } )
821
+ );
822
+ expect( setAttributes ).not.toHaveBeenCalledWith(
823
+ expect.objectContaining( {
824
+ id: undefined,
825
+ } )
826
+ );
827
+ } );
828
+
829
+ it( 'should preserve ID when query string is removed', () => {
830
+ const setAttributes = jest.fn();
831
+ const blockAttributes = {
832
+ id: 123,
833
+ type: 'page',
834
+ kind: 'post-type',
835
+ url: 'https://example.com/page?utm_source=test',
836
+ };
837
+
838
+ const updatedValue = {
839
+ url: 'https://example.com/page',
840
+ };
841
+
842
+ updateAttributes(
843
+ updatedValue,
844
+ setAttributes,
845
+ blockAttributes
846
+ );
847
+
848
+ expect( setAttributes ).toHaveBeenCalledWith(
849
+ expect.objectContaining( {
850
+ url: 'https://example.com/page',
851
+ } )
852
+ );
853
+ expect( setAttributes ).not.toHaveBeenCalledWith(
854
+ expect.objectContaining( {
855
+ id: undefined,
856
+ } )
857
+ );
858
+ } );
859
+
860
+ it( 'should preserve ID when hash fragment is removed', () => {
861
+ const setAttributes = jest.fn();
862
+ const blockAttributes = {
863
+ id: 123,
864
+ type: 'page',
865
+ kind: 'post-type',
866
+ url: 'https://example.com/page#section',
867
+ };
868
+
869
+ const updatedValue = {
870
+ url: 'https://example.com/page',
871
+ };
872
+
873
+ updateAttributes(
874
+ updatedValue,
875
+ setAttributes,
876
+ blockAttributes
877
+ );
878
+
879
+ expect( setAttributes ).toHaveBeenCalledWith(
880
+ expect.objectContaining( {
881
+ url: 'https://example.com/page',
882
+ } )
883
+ );
884
+ expect( setAttributes ).not.toHaveBeenCalledWith(
885
+ expect.objectContaining( {
886
+ id: undefined,
887
+ } )
888
+ );
889
+ } );
890
+
891
+ it( 'should preserve ID when both query string and hash are removed', () => {
892
+ const setAttributes = jest.fn();
893
+ const blockAttributes = {
894
+ id: 123,
895
+ type: 'page',
896
+ kind: 'post-type',
897
+ url: 'https://example.com/page?param=value#section',
898
+ };
899
+
900
+ const updatedValue = {
901
+ url: 'https://example.com/page',
902
+ };
903
+
904
+ updateAttributes(
905
+ updatedValue,
906
+ setAttributes,
907
+ blockAttributes
908
+ );
909
+
910
+ expect( setAttributes ).toHaveBeenCalledWith(
911
+ expect.objectContaining( {
912
+ url: 'https://example.com/page',
913
+ } )
914
+ );
915
+ expect( setAttributes ).not.toHaveBeenCalledWith(
916
+ expect.objectContaining( {
917
+ id: undefined,
918
+ } )
919
+ );
920
+ } );
921
+
922
+ it( 'should preserve ID when adding query string to URL with hash fragment', () => {
923
+ const setAttributes = jest.fn();
924
+ const blockAttributes = {
925
+ id: 123,
926
+ type: 'page',
927
+ kind: 'post-type',
928
+ url: 'http://localhost:8888/daves-page-2/#somehash',
929
+ };
930
+
931
+ const updatedValue = {
932
+ url: 'http://localhost:8888/daves-page-2?somequery#somehash',
933
+ };
934
+
935
+ updateAttributes(
936
+ updatedValue,
937
+ setAttributes,
938
+ blockAttributes
939
+ );
940
+
941
+ expect( setAttributes ).toHaveBeenCalledWith(
942
+ expect.objectContaining( {
943
+ url: 'http://localhost:8888/daves-page-2?somequery#somehash',
944
+ } )
945
+ );
946
+ expect( setAttributes ).not.toHaveBeenCalledWith(
947
+ expect.objectContaining( {
948
+ id: undefined,
949
+ } )
950
+ );
951
+ } );
952
+
953
+ it( 'should preserve ID when query string is partially removed', () => {
954
+ const setAttributes = jest.fn();
955
+ const blockAttributes = {
956
+ id: 123,
957
+ type: 'page',
958
+ kind: 'post-type',
959
+ url: 'https://example.com/page?param1=value1&param2=value2',
960
+ };
961
+
962
+ const updatedValue = {
963
+ url: 'https://example.com/page?param1=value1',
964
+ };
965
+
966
+ updateAttributes(
967
+ updatedValue,
968
+ setAttributes,
969
+ blockAttributes
970
+ );
971
+
972
+ expect( setAttributes ).toHaveBeenCalledWith(
973
+ expect.objectContaining( {
974
+ url: 'https://example.com/page?param1=value1',
975
+ } )
976
+ );
977
+ expect( setAttributes ).not.toHaveBeenCalledWith(
978
+ expect.objectContaining( {
979
+ id: undefined,
980
+ } )
981
+ );
982
+ } );
983
+ } );
984
+
985
+ it( 'should remove ID when URL is changed without new ID', () => {
986
+ const setAttributes = jest.fn();
987
+ const blockAttributes = {
988
+ id: 123,
989
+ type: 'page',
990
+ kind: 'post-type',
991
+ url: 'https://example.com/original-page',
992
+ };
993
+
994
+ const updatedValue = {
995
+ url: 'https://example.com/custom-url',
996
+ };
997
+
998
+ updateAttributes(
999
+ updatedValue,
1000
+ setAttributes,
1001
+ blockAttributes
1002
+ );
1003
+
1004
+ expect( setAttributes ).toHaveBeenCalledWith(
1005
+ expect.objectContaining( {
1006
+ id: undefined,
1007
+ kind: 'custom',
1008
+ type: 'custom',
1009
+ url: 'https://example.com/custom-url',
1010
+ } )
1011
+ );
1012
+ } );
1013
+
1014
+ it( 'should preserve ID when new ID is provided with URL', () => {
1015
+ const setAttributes = jest.fn();
1016
+ const blockAttributes = {
1017
+ id: 123,
1018
+ type: 'page',
1019
+ kind: 'post-type',
1020
+ url: 'https://example.com/original-page',
1021
+ };
1022
+
1023
+ const updatedValue = {
1024
+ url: 'https://example.com/new-page',
1025
+ id: 456,
1026
+ };
1027
+
1028
+ updateAttributes(
1029
+ updatedValue,
1030
+ setAttributes,
1031
+ blockAttributes
1032
+ );
1033
+
1034
+ expect( setAttributes ).toHaveBeenCalledWith(
1035
+ expect.objectContaining( {
1036
+ id: 456,
1037
+ url: 'https://example.com/new-page',
1038
+ } )
1039
+ );
1040
+ } );
1041
+
1042
+ it( 'should not remove ID when only label is changed', () => {
1043
+ const setAttributes = jest.fn();
1044
+ const blockAttributes = {
1045
+ id: 123,
1046
+ type: 'page',
1047
+ kind: 'post-type',
1048
+ url: 'https://example.com/page',
1049
+ };
1050
+
1051
+ const updatedValue = {
1052
+ label: 'New Label',
1053
+ };
1054
+
1055
+ updateAttributes(
1056
+ updatedValue,
1057
+ setAttributes,
1058
+ blockAttributes
1059
+ );
1060
+
1061
+ // When only label is changed, ID should not be included in the attributes
1062
+ // because it's not being modified
1063
+ expect( setAttributes ).toHaveBeenCalledWith( {
1064
+ label: 'New Label',
1065
+ kind: 'post-type',
1066
+ type: 'page',
1067
+ } );
1068
+ } );
1069
+
1070
+ it( 'should not remove ID when only opensInNewTab is changed', () => {
1071
+ const setAttributes = jest.fn();
1072
+ const blockAttributes = {
1073
+ id: 123,
1074
+ type: 'page',
1075
+ kind: 'post-type',
1076
+ url: 'https://example.com/page',
1077
+ };
1078
+
1079
+ const updatedValue = {
1080
+ opensInNewTab: true,
1081
+ };
1082
+
1083
+ updateAttributes(
1084
+ updatedValue,
1085
+ setAttributes,
1086
+ blockAttributes
1087
+ );
1088
+
1089
+ // When only opensInNewTab is changed, ID should not be included in the attributes
1090
+ // because it's not being modified
1091
+ expect( setAttributes ).toHaveBeenCalledWith( {
1092
+ opensInNewTab: true,
1093
+ kind: 'post-type',
1094
+ type: 'page',
1095
+ } );
1096
+ } );
1097
+
1098
+ it( 'should handle case where block has no existing ID', () => {
1099
+ const setAttributes = jest.fn();
1100
+ const blockAttributes = {
1101
+ type: 'page',
1102
+ kind: 'post-type',
1103
+ url: 'https://example.com/page',
1104
+ };
1105
+
1106
+ const updatedValue = {
1107
+ url: 'https://example.com/new-url',
1108
+ };
1109
+
1110
+ updateAttributes(
1111
+ updatedValue,
1112
+ setAttributes,
1113
+ blockAttributes
1114
+ );
1115
+
1116
+ expect( setAttributes ).toHaveBeenCalledWith(
1117
+ expect.objectContaining( {
1118
+ url: 'https://example.com/new-url',
1119
+ } )
1120
+ );
1121
+ // Should not set id to undefined if it wasn't set before
1122
+ expect( setAttributes ).not.toHaveBeenCalledWith(
1123
+ expect.objectContaining( {
1124
+ id: undefined,
1125
+ } )
1126
+ );
1127
+ } );
1128
+
1129
+ it( 'should handle non-integer ID values', () => {
1130
+ const setAttributes = jest.fn();
1131
+ const blockAttributes = {
1132
+ id: 'not-an-integer',
1133
+ type: 'page',
1134
+ kind: 'post-type',
1135
+ url: 'https://example.com/page',
1136
+ };
1137
+
1138
+ const updatedValue = {
1139
+ url: 'https://example.com/new-url',
1140
+ };
1141
+
1142
+ updateAttributes(
1143
+ updatedValue,
1144
+ setAttributes,
1145
+ blockAttributes
1146
+ );
1147
+
1148
+ // Should not set a new ID since the provided ID is not an integer
1149
+ expect( setAttributes ).toHaveBeenCalledWith(
1150
+ expect.objectContaining( {
1151
+ url: 'https://example.com/new-url',
1152
+ } )
1153
+ );
1154
+ expect( setAttributes ).not.toHaveBeenCalledWith(
1155
+ expect.objectContaining( {
1156
+ id: 'not-an-integer',
1157
+ } )
1158
+ );
1159
+ } );
1160
+ } );
429
1161
  } );
430
1162
  } );