From 3bc9bee4f62fba164e6260f7c75cb49a12c6237e Mon Sep 17 00:00:00 2001 From: faisalsiddique4400 Date: Wed, 24 Jun 2026 16:51:33 +0500 Subject: [PATCH 1/4] feat(admin-ui): add test files for custom components across the system (#2890) Signed-off-by: faisalsiddique4400 --- .../Accordion/__tests__/Accordion.test.tsx | 101 ++++++++ .../__tests__/CustomInput.test.tsx | 82 +++++++ .../__tests__/EmptyLayout.test.tsx | 86 +++++++ .../GluuBadge/__tests__/GluuBadge.test.tsx | 88 +++++++ .../GluuButton/__tests__/GluuButton.test.tsx | 84 +++++++ .../__tests__/GluuDatePicker.test.tsx | 172 ++++++++++++++ .../__tests__/GluuDropdown.test.tsx | 217 ++++++++++++++++++ .../__tests__/GluuDynamicList.test.tsx | 138 +++++++++++ .../__tests__/GluuFilterPopover.test.tsx | 119 ++++++++++ .../__tests__/GluuModalShell.test.tsx | 113 +++++++++ .../__tests__/GluuRefreshButton.test.tsx | 54 +++++ .../__tests__/GluuSearchToolbar.test.tsx | 187 +++++++++++++++ .../LicenseScreens/__tests__/ApiKey.test.tsx | 87 +++++++ .../__tests__/GenerateLicenseCard.test.tsx | 85 +++++++ .../ModalLayer/__tests__/ModalLayer.test.tsx | 64 ++++++ .../Sidebar/__tests__/Sidebar.test.tsx | 150 ++++++++++++ .../__tests__/SidebarMenu.test.tsx | 191 +++++++++++++++ .../Wizard/__tests__/Wizard.test.tsx | 136 +++++++++++ .../Apps/Gluu/Tests/GluuNavBar.test.tsx | 60 +++++ .../Apps/Gluu/__tests__/GluuAlert.test.tsx | 51 ++++ .../Gluu/__tests__/GluuCommitDialog.test.tsx | 147 ++++++++++++ .../Apps/Gluu/__tests__/GluuDialog.test.tsx | 93 ++++++++ .../Gluu/__tests__/GluuErrorModal.test.tsx | 45 ++++ .../Gluu/__tests__/GluuInputEditor.test.tsx | 170 ++++++++++++++ .../__tests__/GluuRemovableInputRow.test.tsx | 117 ++++++++++ .../__tests__/GluuRemovableSelectRow.test.tsx | 126 ++++++++++ .../__tests__/GluuScriptErrorModal.test.tsx | 56 +++++ .../__tests__/GluuServiceDownModal.test.tsx | 50 ++++ .../__tests__/GluuSessionTimeout.test.tsx | 131 +++++++++++ .../GluuSessionTimeoutDialog.test.tsx | 64 ++++++ .../Apps/Gluu/__tests__/GluuTabs.test.tsx | 86 +++++++ .../__tests__/GluuThemeFormFooter.test.tsx | 191 +++++++++++++++ .../Gluu/__tests__/GluuTimeoutModal.test.tsx | 56 +++++ .../Gluu/__tests__/GluuUploadFile.test.tsx | 53 +++++ .../__tests__/GluuViewDetailsModal.test.tsx | 55 +++++ .../GluuWebhookCommitDialog.test.tsx | 121 ++++++++++ .../GluuWebhookExecutionDialog.test.tsx | 133 +++++++++++ 37 files changed, 3959 insertions(+) create mode 100644 admin-ui/app/components/Accordion/__tests__/Accordion.test.tsx create mode 100644 admin-ui/app/components/CustomInput/__tests__/CustomInput.test.tsx create mode 100644 admin-ui/app/components/EmptyLayout/__tests__/EmptyLayout.test.tsx create mode 100644 admin-ui/app/components/GluuBadge/__tests__/GluuBadge.test.tsx create mode 100644 admin-ui/app/components/GluuButton/__tests__/GluuButton.test.tsx create mode 100644 admin-ui/app/components/GluuDatePicker/__tests__/GluuDatePicker.test.tsx create mode 100644 admin-ui/app/components/GluuDropdown/__tests__/GluuDropdown.test.tsx create mode 100644 admin-ui/app/components/GluuDynamicList/__tests__/GluuDynamicList.test.tsx create mode 100644 admin-ui/app/components/GluuFilterPopover/__tests__/GluuFilterPopover.test.tsx create mode 100644 admin-ui/app/components/GluuModalShell/__tests__/GluuModalShell.test.tsx create mode 100644 admin-ui/app/components/GluuSearchToolbar/__tests__/GluuRefreshButton.test.tsx create mode 100644 admin-ui/app/components/GluuSearchToolbar/__tests__/GluuSearchToolbar.test.tsx create mode 100644 admin-ui/app/components/LicenseScreens/__tests__/ApiKey.test.tsx create mode 100644 admin-ui/app/components/LicenseScreens/__tests__/GenerateLicenseCard.test.tsx create mode 100644 admin-ui/app/components/ModalLayer/__tests__/ModalLayer.test.tsx create mode 100644 admin-ui/app/components/Sidebar/__tests__/Sidebar.test.tsx create mode 100644 admin-ui/app/components/SidebarMenu/__tests__/SidebarMenu.test.tsx create mode 100644 admin-ui/app/components/Wizard/__tests__/Wizard.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/Tests/GluuNavBar.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuAlert.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuCommitDialog.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuDialog.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuErrorModal.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuInputEditor.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuRemovableInputRow.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuRemovableSelectRow.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuScriptErrorModal.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuServiceDownModal.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuSessionTimeout.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuSessionTimeoutDialog.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuTabs.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuThemeFormFooter.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuTimeoutModal.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuUploadFile.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuViewDetailsModal.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuWebhookCommitDialog.test.tsx create mode 100644 admin-ui/app/routes/Apps/Gluu/__tests__/GluuWebhookExecutionDialog.test.tsx diff --git a/admin-ui/app/components/Accordion/__tests__/Accordion.test.tsx b/admin-ui/app/components/Accordion/__tests__/Accordion.test.tsx new file mode 100644 index 000000000..5a34d3f89 --- /dev/null +++ b/admin-ui/app/components/Accordion/__tests__/Accordion.test.tsx @@ -0,0 +1,101 @@ +import React from 'react' +import { render, screen, fireEvent } from '@testing-library/react' +import Accordion from '@/components/Accordion' +import AppTestWrapper from 'Routes/Apps/Gluu/Tests/Components/AppTestWrapper' + +const Wrapper = ({ children }: { children: React.ReactNode }) => ( + {children} +) + +type BuildProps = { + initialOpen?: boolean + open?: boolean + onToggle?: (isOpen: boolean) => void +} + +const buildAccordion = ({ initialOpen, open, onToggle }: BuildProps = {}) => ( + + + Section Title + + + Body Content + +) + +describe('Accordion', () => { + it('renders its header and body children', () => { + render(buildAccordion({ initialOpen: true }), { wrapper: Wrapper }) + + expect(screen.getByText('Section Title')).toBeInTheDocument() + expect(screen.getByText('Body Content')).toBeInTheDocument() + }) + + it('shows the closed indicator and hides the body when not initially open', () => { + render(buildAccordion(), { wrapper: Wrapper }) + + expect(screen.getByTestId('AddIcon')).toBeInTheDocument() + expect(screen.queryByTestId('RemoveIcon')).not.toBeInTheDocument() + expect(screen.getByText('Body Content')).not.toBeVisible() + }) + + it('shows the open indicator and reveals the body when initialOpen is true', () => { + render(buildAccordion({ initialOpen: true }), { wrapper: Wrapper }) + + expect(screen.getByTestId('RemoveIcon')).toBeInTheDocument() + expect(screen.queryByTestId('AddIcon')).not.toBeInTheDocument() + expect(screen.getByText('Body Content')).toBeVisible() + }) + + it('toggles open when the header is clicked (uncontrolled)', () => { + render(buildAccordion(), { wrapper: Wrapper }) + + expect(screen.getByTestId('AddIcon')).toBeInTheDocument() + + fireEvent.click(screen.getByText('Section Title')) + + expect(screen.getByTestId('RemoveIcon')).toBeInTheDocument() + expect(screen.getByText('Body Content')).toBeVisible() + }) + + it('toggles closed again on a second header click (uncontrolled)', () => { + render(buildAccordion({ initialOpen: true }), { wrapper: Wrapper }) + + fireEvent.click(screen.getByText('Section Title')) + + // indicator flips back to the closed state + expect(screen.getByTestId('AddIcon')).toBeInTheDocument() + expect(screen.queryByTestId('RemoveIcon')).not.toBeInTheDocument() + }) + + it('throws when open is provided without onToggle', () => { + const consoleError = jest.spyOn(console, 'error').mockImplementation(() => {}) + + expect(() => render(buildAccordion({ open: true }), { wrapper: Wrapper })).toThrow( + /props.open has to be used combined with props.onToggle/, + ) + + consoleError.mockRestore() + }) + + it('calls onToggle with the next open state when controlled, without changing on its own', () => { + const onToggle = jest.fn() + render(buildAccordion({ open: false, onToggle }), { wrapper: Wrapper }) + + expect(screen.getByTestId('AddIcon')).toBeInTheDocument() + + fireEvent.click(screen.getByText('Section Title')) + + expect(onToggle).toHaveBeenCalledTimes(1) + expect(onToggle).toHaveBeenCalledWith(true) + // parent owns state: still closed until the prop changes + expect(screen.getByTestId('AddIcon')).toBeInTheDocument() + }) + + it('renders the state dictated by the parent when controlled', () => { + render(buildAccordion({ open: true, onToggle: jest.fn() }), { wrapper: Wrapper }) + + expect(screen.getByTestId('RemoveIcon')).toBeInTheDocument() + expect(screen.getByText('Body Content')).toBeVisible() + }) +}) diff --git a/admin-ui/app/components/CustomInput/__tests__/CustomInput.test.tsx b/admin-ui/app/components/CustomInput/__tests__/CustomInput.test.tsx new file mode 100644 index 000000000..437883ebc --- /dev/null +++ b/admin-ui/app/components/CustomInput/__tests__/CustomInput.test.tsx @@ -0,0 +1,82 @@ +import React from 'react' +import { render, screen, fireEvent } from '@testing-library/react' +import { CustomInput } from '@/components/CustomInput/CustomInput' +import type { CustomInputProps } from '@/components/CustomInput/types' +import AppTestWrapper from 'Routes/Apps/Gluu/Tests/Components/AppTestWrapper' + +const Wrapper = ({ children }: { children: React.ReactNode }) => ( + {children} +) + +const renderInput = (props: CustomInputProps) => + render(, { wrapper: Wrapper }) + +describe('CustomInput', () => { + it('renders a text input by default', () => { + renderInput({ name: 'firstName', type: 'text' }) + const input = screen.getByTestId('firstName') as HTMLInputElement + expect(input.tagName).toBe('INPUT') + expect(input.type).toBe('text') + }) + + it('displays the provided value', () => { + renderInput({ name: 'firstName', type: 'text', value: 'Alice', onChange: jest.fn() }) + const input = screen.getByTestId('firstName') as HTMLInputElement + expect(input.value).toBe('Alice') + }) + + it('fires onChange when typing in the input', () => { + const onChange = jest.fn() + renderInput({ name: 'firstName', type: 'text', onChange }) + const input = screen.getByTestId('firstName') as HTMLInputElement + fireEvent.change(input, { target: { value: 'Bob' } }) + expect(onChange).toHaveBeenCalledTimes(1) + }) + + it('forwards name, placeholder and disabled props to the input', () => { + renderInput({ + name: 'email', + type: 'text', + disabled: true, + 'data-testid': 'email', + }) + const input = screen.getByTestId('email') as HTMLInputElement + expect(input.name).toBe('email') + expect(input.disabled).toBe(true) + }) + + it('renders a select element when type is select', () => { + renderInput({ + name: 'country', + type: 'select', + children: ( + <> + + + + ), + }) + const select = screen.getByTestId('country') as HTMLSelectElement + expect(select.tagName).toBe('SELECT') + expect(screen.getByText('United States')).toBeInTheDocument() + expect(screen.getByText('United Kingdom')).toBeInTheDocument() + }) + + it('fires onChange when selecting an option', () => { + const onChange = jest.fn() + renderInput({ + name: 'country', + type: 'select', + onChange, + children: ( + <> + + + + ), + }) + const select = screen.getByTestId('country') as HTMLSelectElement + fireEvent.change(select, { target: { value: 'uk' } }) + expect(onChange).toHaveBeenCalledTimes(1) + }) +}) diff --git a/admin-ui/app/components/EmptyLayout/__tests__/EmptyLayout.test.tsx b/admin-ui/app/components/EmptyLayout/__tests__/EmptyLayout.test.tsx new file mode 100644 index 000000000..e10d45904 --- /dev/null +++ b/admin-ui/app/components/EmptyLayout/__tests__/EmptyLayout.test.tsx @@ -0,0 +1,86 @@ +import { render, screen } from '@testing-library/react' +import { EmptyLayout } from '@/components/EmptyLayout/EmptyLayout' +import type { EmptyLayoutProps, SectionProps } from '@/components/EmptyLayout/types' +import AppTestWrapper from 'Routes/Apps/Gluu/Tests/Components/AppTestWrapper' + +const renderLayout = (props: Omit) => + render( + + + , + ) + +const renderSection = (props: SectionProps) => + render( + + + , + ) + +describe('EmptyLayout', () => { + it('renders its children', () => { + renderLayout({ children: hello child }) + expect(screen.getByText('hello child')).toBeInTheDocument() + }) + + it('always applies the fullscreen class on the root element', () => { + renderLayout({ children: content }) + const root = screen.getByTestId('content').parentElement + expect(root).toHaveClass('fullscreen') + }) + + it('merges a custom className alongside fullscreen', () => { + renderLayout({ children: content, className: 'extra' }) + const root = screen.getByTestId('content').parentElement + expect(root).toHaveClass('fullscreen') + expect(root).toHaveClass('extra') + }) + + it('exposes a Section sub-layout', () => { + expect(EmptyLayout.Section).toBeDefined() + }) + + describe('EmptyLayout.Section', () => { + it('renders children and the base section class', () => { + renderSection({ children: section child }) + expect(screen.getByText('section child')).toBeInTheDocument() + const section = screen.getByTestId('sec').parentElement + expect(section).toHaveClass('fullscreen__section') + expect(section).not.toHaveClass('fullscreen__section--center') + }) + + it('does not wrap children in a centering child when center is not set', () => { + renderSection({ children: section child }) + const section = screen.getByTestId('sec').parentElement + expect(section).toHaveClass('fullscreen__section') + }) + + it('applies the center modifier and wraps children with a max-width container when center is true', () => { + renderSection({ center: true, children: centered }) + const wrapper = screen.getByTestId('sec').parentElement + expect(wrapper).toHaveClass('fullscreen__section__child') + expect(wrapper).toHaveStyle({ maxWidth: '420px' }) + const section = wrapper?.parentElement + expect(section).toHaveClass('fullscreen__section--center') + }) + + it('uses a string width verbatim as maxWidth', () => { + renderSection({ center: true, width: '50%', children: x }) + const wrapper = screen.getByTestId('sec').parentElement + expect(wrapper).toHaveStyle({ maxWidth: '50%' }) + }) + + it('appends px to a numeric width', () => { + renderSection({ center: true, width: 600, children: x }) + const wrapper = screen.getByTestId('sec').parentElement + expect(wrapper).toHaveStyle({ maxWidth: '600px' }) + }) + + it('merges a custom className onto the section', () => { + renderSection({ className: 'my-section', children: x }) + const section = screen.getByTestId('sec').parentElement + expect(section).toHaveClass('my-section') + expect(section).toHaveClass('fullscreen__section') + }) + }) +}) diff --git a/admin-ui/app/components/GluuBadge/__tests__/GluuBadge.test.tsx b/admin-ui/app/components/GluuBadge/__tests__/GluuBadge.test.tsx new file mode 100644 index 000000000..d801ab6f8 --- /dev/null +++ b/admin-ui/app/components/GluuBadge/__tests__/GluuBadge.test.tsx @@ -0,0 +1,88 @@ +import React from 'react' +import { render, screen, fireEvent } from '@testing-library/react' +import GluuBadge from '@/components/GluuBadge/GluuBadge' +import type { GluuBadgeProps } from '@/components/GluuBadge/types' +import AppTestWrapper from 'Routes/Apps/Gluu/Tests/Components/AppTestWrapper' + +const Wrapper = ({ children }: { children: React.ReactNode }) => ( + {children} +) + +const renderBadge = (props: Partial = {}) => + render({props.children ?? 'Active'}, { wrapper: Wrapper }) + +describe('GluuBadge', () => { + it('renders its content', () => { + renderBadge({ children: 'Enabled' }) + expect(screen.getByText('Enabled')).toBeInTheDocument() + }) + + it('renders distinct labels for distinct states', () => { + const { rerender } = renderBadge({ children: 'Active' }) + expect(screen.getByText('Active')).toBeInTheDocument() + + // wrapper is preserved by rerender; pass only the updated child element + rerender(Inactive) + expect(screen.getByText('Inactive')).toBeInTheDocument() + expect(screen.queryByText('Active')).not.toBeInTheDocument() + }) + + it('is non-interactive by default (no button role, default cursor)', () => { + renderBadge({ children: 'Static' }) + const badge = screen.getByText('Static') + expect(badge).not.toHaveAttribute('role', 'button') + expect(badge).not.toHaveAttribute('tabindex') + expect(badge).toHaveStyle({ cursor: 'default' }) + }) + + it('becomes interactive when onClick is provided', () => { + const onClick = jest.fn() + renderBadge({ children: 'Clickable', onClick }) + const badge = screen.getByRole('button', { name: 'Clickable' }) + expect(badge).toHaveAttribute('tabindex', '0') + expect(badge).toHaveStyle({ cursor: 'pointer' }) + fireEvent.click(badge) + expect(onClick).toHaveBeenCalledTimes(1) + }) + + it('triggers onClick on Enter key when interactive', () => { + const onClick = jest.fn() + renderBadge({ children: 'Keyed', onClick }) + fireEvent.keyDown(screen.getByRole('button'), { key: 'Enter' }) + expect(onClick).toHaveBeenCalledTimes(1) + }) + + it('triggers onClick on Space key when interactive', () => { + const onClick = jest.fn() + renderBadge({ children: 'Spaced', onClick }) + fireEvent.keyDown(screen.getByRole('button'), { key: ' ' }) + expect(onClick).toHaveBeenCalledTimes(1) + }) + + it('ignores other keys when interactive', () => { + const onClick = jest.fn() + renderBadge({ children: 'Ignored', onClick }) + fireEvent.keyDown(screen.getByRole('button'), { key: 'a' }) + expect(onClick).not.toHaveBeenCalled() + }) + + it('renders outlined variant with transparent background and colored text', () => { + renderBadge({ children: 'Outlined', outlined: true, backgroundColor: 'rgb(255, 0, 0)' }) + const badge = screen.getByText('Outlined') + // outlined => background transparent, text + border take the badge color + expect(badge.style.backgroundColor).toBe('transparent') + expect(badge).toHaveStyle({ color: 'rgb(255, 0, 0)' }) + }) + + it('applies pill border radius when pill is set', () => { + renderBadge({ children: 'Pill', pill: true }) + expect(screen.getByText('Pill')).toHaveStyle({ borderRadius: '50px' }) + }) + + it('applies the title attribute and className', () => { + renderBadge({ children: 'Titled', title: 'A tooltip', className: 'my-badge' }) + const badge = screen.getByText('Titled') + expect(badge).toHaveAttribute('title', 'A tooltip') + expect(badge).toHaveClass('my-badge') + }) +}) diff --git a/admin-ui/app/components/GluuButton/__tests__/GluuButton.test.tsx b/admin-ui/app/components/GluuButton/__tests__/GluuButton.test.tsx new file mode 100644 index 000000000..b6f6dcf12 --- /dev/null +++ b/admin-ui/app/components/GluuButton/__tests__/GluuButton.test.tsx @@ -0,0 +1,84 @@ +import React from 'react' +import { render, screen, fireEvent } from '@testing-library/react' +import GluuButton from '@/components/GluuButton/GluuButton' +import type { GluuButtonProps } from '@/components/GluuButton/types' +import AppTestWrapper from 'Routes/Apps/Gluu/Tests/Components/AppTestWrapper' + +const Wrapper = ({ children }: { children: React.ReactNode }) => ( + {children} +) + +const renderButton = (props: Partial = {}) => + render({props.children ?? 'Click me'}, { wrapper: Wrapper }) + +describe('GluuButton', () => { + it('renders its children', () => { + renderButton({ children: 'Save changes' }) + expect(screen.getByRole('button', { name: 'Save changes' })).toBeInTheDocument() + }) + + it('fires onClick when clicked', () => { + const onClick = jest.fn() + renderButton({ onClick }) + fireEvent.click(screen.getByRole('button')) + expect(onClick).toHaveBeenCalledTimes(1) + }) + + it('does not fire onClick and is disabled when disabled is true', () => { + const onClick = jest.fn() + renderButton({ onClick, disabled: true }) + const button = screen.getByRole('button') as HTMLButtonElement + expect(button).toBeDisabled() + fireEvent.click(button) + expect(onClick).not.toHaveBeenCalled() + }) + + it('renders a spinner and is disabled while loading', () => { + const onClick = jest.fn() + renderButton({ onClick, loading: true, children: 'Submit' }) + const button = screen.getByRole('button') as HTMLButtonElement + expect(button).toBeDisabled() + // spinner span is the first child element before the label text + expect(button.querySelector('span')).toBeInTheDocument() + fireEvent.click(button) + expect(onClick).not.toHaveBeenCalled() + }) + + it('defaults to type="button"', () => { + renderButton() + expect(screen.getByRole('button')).toHaveAttribute('type', 'button') + }) + + it('honors type="submit"', () => { + renderButton({ type: 'submit' }) + expect(screen.getByRole('button')).toHaveAttribute('type', 'submit') + }) + + it('applies the title attribute', () => { + renderButton({ title: 'Tooltip text' }) + expect(screen.getByRole('button')).toHaveAttribute('title', 'Tooltip text') + }) + + it('forwards aria-label and aria-expanded', () => { + renderButton({ 'aria-label': 'menu', 'aria-expanded': true }) + const button = screen.getByRole('button', { name: 'menu' }) + expect(button).toHaveAttribute('aria-expanded', 'true') + }) + + it('renders outlined and custom color props without error', () => { + renderButton({ + outlined: true, + backgroundColor: '#123456', + textColor: '#ffffff', + borderColor: '#000000', + size: 'lg', + block: true, + }) + expect(screen.getByRole('button')).toBeInTheDocument() + }) + + it('applies the provided className', () => { + renderButton({ className: 'my-btn' }) + expect(screen.getByRole('button')).toHaveClass('my-btn') + }) +}) diff --git a/admin-ui/app/components/GluuDatePicker/__tests__/GluuDatePicker.test.tsx b/admin-ui/app/components/GluuDatePicker/__tests__/GluuDatePicker.test.tsx new file mode 100644 index 000000000..858ec7bf9 --- /dev/null +++ b/admin-ui/app/components/GluuDatePicker/__tests__/GluuDatePicker.test.tsx @@ -0,0 +1,172 @@ +import React from 'react' +import { render, screen, fireEvent } from '@testing-library/react' +import { GluuDatePicker } from '@/components/GluuDatePicker/GluuDatePicker' +import { createDate } from '@/utils/dayjsUtils' +import AppTestWrapper from 'Routes/Apps/Gluu/Tests/Components/AppTestWrapper' + +const Wrapper = ({ children }: { children: React.ReactNode }) => ( + {children} +) + +// MUI X date pickers render a hidden per field that carries the +// formatted value, plus a sectioned span group for editing. Reading the +// underlying input value is the reliable way to assert the displayed value. +const getInputs = (container: HTMLElement): HTMLInputElement[] => + Array.from(container.querySelectorAll('input')) + +// The field label text is mirrored in both the