@@ -615,6 +615,200 @@ test('comprehensive editor testing', async () => {
615
615
});
616
616
```
617
617
618
+ ### Panel Test Utilities
619
+
620
+ The package also provides comprehensive testing utilities for the Panel component, making it easy to test Panel interactions and behaviors.
621
+
622
+ #### ` renderPanel(config?) `
623
+
624
+ Renders a Panel component with proper LeafyGreen and CodeEditor context for testing.
625
+
626
+ ** Parameters:**
627
+
628
+ - ` config ` _ (optional)_ : Configuration object with the following properties:
629
+ - ` panelProps ` _ (optional)_ : Partial ` PanelProps ` to pass to the Panel component
630
+ - ` contextConfig ` _ (optional)_ : Override the default CodeEditor context values
631
+
632
+ ** Returns:**
633
+
634
+ - ` container ` : The rendered container element from ` @testing-library/react `
635
+ - ` panel ` : Panel test utilities object with methods for interacting with panel elements
636
+
637
+ ** Example:**
638
+
639
+ ``` tsx
640
+ import { renderPanel , PanelSelectors } from ' @leafygreen-ui/code-editor' ;
641
+
642
+ test (' renders panel with format button' , async () => {
643
+ const { container, panel } = renderPanel ({
644
+ panelProps: {
645
+ title: ' JavaScript Editor' ,
646
+ showFormatButton: true ,
647
+ showCopyButton: true ,
648
+ showSecondaryMenuButton: true ,
649
+ },
650
+ });
651
+
652
+ // Use utilities to interact with the panel
653
+ await panel .interactions .clickFormatButton ();
654
+ await panel .interactions .clickUndoMenuItem ();
655
+ });
656
+ ```
657
+
658
+ #### Panel Test Utilities Object
659
+
660
+ The ` panel ` object provides access to Panel elements and interactions:
661
+
662
+ ##### Element Getters
663
+
664
+ - ` panel.getFormatButton() ` - Gets the format button element
665
+ - ` panel.getCopyButton() ` - Gets the copy button element
666
+ - ` panel.getSecondaryMenuButton() ` - Gets the secondary menu button
667
+ - ` panel.getMenuItem(ariaLabel) ` - Gets a menu item by aria-label
668
+ - ` panel.getUndoMenuItem() ` - Gets the undo menu item
669
+ - ` panel.getRedoMenuItem() ` - Gets the redo menu item
670
+ - ` panel.getDownloadMenuItem() ` - Gets the download menu item
671
+ - ` panel.getViewShortcutsMenuItem() ` - Gets the view shortcuts menu item
672
+ - ` panel.getCustomSecondaryButton(labelOrAriaLabel) ` - Gets a custom secondary button
673
+
674
+ ##### Interactions
675
+
676
+ All interaction methods are available under ` panel.interactions ` :
677
+
678
+ - ` clickFormatButton() ` - Clicks the format button
679
+ - ` clickCopyButton() ` - Clicks the copy button
680
+ - ` openSecondaryMenu() ` - Opens the secondary menu
681
+ - ` clickMenuItem(ariaLabel) ` - Clicks a menu item by aria-label
682
+ - ` clickUndoMenuItem() ` - Opens menu and clicks undo
683
+ - ` clickRedoMenuItem() ` - Opens menu and clicks redo
684
+ - ` clickDownloadMenuItem() ` - Opens menu and clicks download
685
+ - ` clickViewShortcutsMenuItem() ` - Opens menu and clicks view shortcuts
686
+ - ` clickCustomSecondaryButton(labelOrAriaLabel) ` - Opens menu and clicks custom button
687
+ - ` hoverFormatButton() ` - Hovers format button and waits for tooltip
688
+ - ` hoverCopyButton() ` - Hovers copy button and waits for tooltip
689
+
690
+ ##### Utilities
691
+
692
+ - ` panel.waitForTooltip(text, timeout?) ` - Waits for a tooltip with specific text
693
+ - ` panel.hasTitleText(expectedTitle) ` - Checks if panel has expected title
694
+ - ` panel.hasInnerContent(testId) ` - Checks if inner content with testId exists
695
+
696
+ #### PanelSelectors
697
+
698
+ Consistent selector constants for testing:
699
+
700
+ ``` tsx
701
+ import { PanelSelectors } from ' @leafygreen-ui/code-editor' ;
702
+
703
+ // Use instead of hardcoded strings
704
+ panel .getMenuItem (PanelSelectors .UndoMenuItem );
705
+ panel .getMenuItem (PanelSelectors .RedoMenuItem );
706
+ panel .getMenuItem (PanelSelectors .DownloadMenuItem );
707
+ panel .getMenuItem (PanelSelectors .ViewShortcutsMenuItem );
708
+ ```
709
+
710
+ Available selectors:
711
+
712
+ - ` PanelSelectors.FormatButton `
713
+ - ` PanelSelectors.CopyButton `
714
+ - ` PanelSelectors.SecondaryMenuButton `
715
+ - ` PanelSelectors.UndoMenuItem `
716
+ - ` PanelSelectors.RedoMenuItem `
717
+ - ` PanelSelectors.DownloadMenuItem `
718
+ - ` PanelSelectors.ViewShortcutsMenuItem `
719
+
720
+ #### Panel Test Examples
721
+
722
+ ##### Testing Format Button
723
+
724
+ ``` tsx
725
+ test (' formats code when format button is clicked' , async () => {
726
+ const onFormatClick = jest .fn ();
727
+
728
+ const { panel } = renderPanel ({
729
+ panelProps: {
730
+ showFormatButton: true ,
731
+ onFormatClick ,
732
+ },
733
+ });
734
+
735
+ await panel .interactions .clickFormatButton ();
736
+
737
+ expect (onFormatClick ).toHaveBeenCalled ();
738
+ expect (mockPanelFunctions .formatCode ).toHaveBeenCalled ();
739
+ });
740
+ ```
741
+
742
+ ##### Testing Secondary Menu
743
+
744
+ ``` tsx
745
+ test (' performs undo when undo menu item is clicked' , async () => {
746
+ const onUndoClick = jest .fn ();
747
+
748
+ const { panel } = renderPanel ({
749
+ panelProps: {
750
+ showSecondaryMenuButton: true ,
751
+ onUndoClick ,
752
+ },
753
+ });
754
+
755
+ await panel .interactions .clickUndoMenuItem ();
756
+
757
+ expect (onUndoClick ).toHaveBeenCalled ();
758
+ expect (mockPanelFunctions .undo ).toHaveBeenCalled ();
759
+ });
760
+ ```
761
+
762
+ ##### Testing Custom Secondary Buttons
763
+
764
+ ``` tsx
765
+ test (' handles custom secondary button clicks' , async () => {
766
+ const customOnClick = jest .fn ();
767
+
768
+ const { panel } = renderPanel ({
769
+ panelProps: {
770
+ showSecondaryMenuButton: true ,
771
+ customSecondaryButtons: [
772
+ {
773
+ label: ' Custom Action' ,
774
+ onClick: customOnClick ,
775
+ ' aria-label' : ' Perform custom action' ,
776
+ },
777
+ ],
778
+ },
779
+ });
780
+
781
+ await panel .interactions .clickCustomSecondaryButton (' Perform custom action' );
782
+
783
+ expect (customOnClick ).toHaveBeenCalled ();
784
+ });
785
+ ```
786
+
787
+ #### mockPanelFunctions
788
+
789
+ The ` mockPanelFunctions ` object provides access to mock functions used in the CodeEditor context:
790
+
791
+ ``` tsx
792
+ import { mockPanelFunctions } from ' @leafygreen-ui/code-editor' ;
793
+
794
+ // Clear all mock calls before each test
795
+ beforeEach (() => {
796
+ mockPanelFunctions .clearAll ();
797
+ });
798
+
799
+ // Access individual mocks
800
+ expect (mockPanelFunctions .undo ).toHaveBeenCalled ();
801
+ expect (mockPanelFunctions .formatCode ).toHaveBeenCalled ();
802
+ ```
803
+
804
+ Available mock functions:
805
+
806
+ - ` mockPanelFunctions.getContents `
807
+ - ` mockPanelFunctions.formatCode `
808
+ - ` mockPanelFunctions.undo `
809
+ - ` mockPanelFunctions.redo `
810
+ - ` mockPanelFunctions.clearAll() ` - Clears all mock calls
811
+
618
812
## CodeMirror Extension Hooks
619
813
620
814
The ` CodeEditor ` component is built on [ CodeMirror v6] ( https://codemirror.net/ ) and provides a complete, ready-to-use editor experience. However, some applications may need highly customized CodeMirror implementations that don't fit the standard ` CodeEditor ` API, while still wanting to maintain consistency with the LeafyGreen design system.
0 commit comments