Skip to content

Commit d6ba342

Browse files
committed
feat(CodeEditor): add comprehensive testing utilities for Panel component
- Introduced `renderPanel` function to facilitate rendering of the Panel component with necessary context for testing. - Added `PanelSelectors` for consistent access to panel elements in tests. - Implemented various interaction methods for testing user interactions with the Panel, including format and copy button actions. - Enhanced README documentation to include new testing utilities and examples for better guidance on testing Panel interactions.
1 parent 9e13deb commit d6ba342

File tree

4 files changed

+806
-337
lines changed

4 files changed

+806
-337
lines changed

packages/code-editor/README.md

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,200 @@ test('comprehensive editor testing', async () => {
615615
});
616616
```
617617

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+
618812
## CodeMirror Extension Hooks
619813

620814
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

Comments
 (0)