test: add unit tests for some base components (#32201)

This commit is contained in:
Saumya Talwani 2026-02-12 07:21:18 +05:30 committed by GitHub
parent 32350f7a04
commit f953331f91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 984 additions and 0 deletions

View File

@ -0,0 +1,34 @@
import { render, screen } from '@testing-library/react'
import AnswerIcon from '.'
describe('AnswerIcon', () => {
it('renders default emoji when no icon or image is provided', () => {
const { container } = render(<AnswerIcon />)
const emojiElement = container.querySelector('em-emoji')
expect(emojiElement).toBeInTheDocument()
expect(emojiElement).toHaveAttribute('id', '🤖')
})
it('renders with custom emoji when icon is provided', () => {
const { container } = render(<AnswerIcon icon="smile" />)
const emojiElement = container.querySelector('em-emoji')
expect(emojiElement).toBeInTheDocument()
expect(emojiElement).toHaveAttribute('id', 'smile')
})
it('renders image when iconType is image and imageUrl is provided', () => {
render(<AnswerIcon iconType="image" imageUrl="test-image.jpg" />)
const imgElement = screen.getByAltText('answer icon')
expect(imgElement).toBeInTheDocument()
expect(imgElement).toHaveAttribute('src', 'test-image.jpg')
})
it('applies custom background color', () => {
const { container } = render(<AnswerIcon background="#FF5500" />)
expect(container.firstChild).toHaveStyle('background: #FF5500')
})
it('uses default background color when no background is provided for non-image icons', () => {
const { container } = render(<AnswerIcon />)
expect(container.firstChild).toHaveStyle('background: #D5F5F6')
})
})

View File

@ -0,0 +1,54 @@
import { fireEvent, render } from '@testing-library/react'
import CopyIcon from '.'
const copy = vi.fn()
const reset = vi.fn()
let copied = false
vi.mock('foxact/use-clipboard', () => ({
useClipboard: () => ({
copy,
reset,
copied,
}),
}))
describe('copy icon component', () => {
beforeEach(() => {
vi.resetAllMocks()
copied = false
})
it('renders normally', () => {
const { container } = render(<CopyIcon content="this is some test content for the copy icon component" />)
expect(container.querySelector('svg')).not.toBeNull()
})
it('shows copy icon initially', () => {
const { container } = render(<CopyIcon content="this is some test content for the copy icon component" />)
const icon = container.querySelector('[data-icon="Copy"]')
expect(icon).toBeInTheDocument()
})
it('shows copy check icon when copied', () => {
copied = true
const { container } = render(<CopyIcon content="this is some test content for the copy icon component" />)
const icon = container.querySelector('[data-icon="CopyCheck"]')
expect(icon).toBeInTheDocument()
})
it('handles copy when clicked', () => {
const { container } = render(<CopyIcon content="this is some test content for the copy icon component" />)
const icon = container.querySelector('[data-icon="Copy"]')
fireEvent.click(icon as Element)
expect(copy).toBeCalledTimes(1)
})
it('resets on mouse leave', () => {
const { container } = render(<CopyIcon content="this is some test content for the copy icon component" />)
const icon = container.querySelector('[data-icon="Copy"]')
const div = icon?.parentElement as HTMLElement
fireEvent.mouseLeave(div)
expect(reset).toBeCalledTimes(1)
})
})

View File

@ -0,0 +1,16 @@
import { render, screen } from '@testing-library/react'
import CornerLabel from '.'
describe('CornerLabel', () => {
it('renders the label correctly', () => {
render(<CornerLabel label="Test Label" />)
expect(screen.getByText('Test Label')).toBeInTheDocument()
})
it('applies custom class names', () => {
const { container } = render(<CornerLabel label="Test Label" className="custom-class" labelClassName="custom-label-class" />)
expect(container.querySelector('.custom-class')).toBeInTheDocument()
expect(container.querySelector('.custom-label-class')).toBeInTheDocument()
expect(screen.getByText('Test Label')).toBeInTheDocument()
})
})

View File

@ -0,0 +1,447 @@
import { fireEvent, render, screen } from '@testing-library/react'
import * as React from 'react'
import DrawerPlus from '.'
vi.mock('@/hooks/use-breakpoints', () => ({
default: () => 'desktop',
MediaType: { mobile: 'mobile', desktop: 'desktop', tablet: 'tablet' },
}))
describe('DrawerPlus', () => {
beforeEach(() => {
vi.clearAllMocks()
})
describe('Rendering', () => {
it('should not render when isShow is false', () => {
render(
<DrawerPlus
isShow={false}
onHide={() => {}}
title="Test Drawer"
body={<div>Content</div>}
/>,
)
expect(screen.queryByRole('dialog')).not.toBeInTheDocument()
})
it('should render when isShow is true', () => {
const bodyContent = <div>Body Content</div>
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test Drawer"
body={bodyContent}
/>,
)
expect(screen.getByRole('dialog')).toBeInTheDocument()
expect(screen.getByText('Test Drawer')).toBeInTheDocument()
expect(screen.getByText('Body Content')).toBeInTheDocument()
})
it('should render footer when provided', () => {
const footerContent = <div>Footer Content</div>
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test Drawer"
body={<div>Body</div>}
foot={footerContent}
/>,
)
expect(screen.getByText('Footer Content')).toBeInTheDocument()
})
it('should render JSX element as title', () => {
const titleElement = <h1 data-testid="custom-title">Custom Title</h1>
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title={titleElement}
body={<div>Body</div>}
/>,
)
expect(screen.getByTestId('custom-title')).toBeInTheDocument()
})
it('should render titleDescription when provided', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test Drawer"
titleDescription="Description text"
body={<div>Body</div>}
/>,
)
expect(screen.getByText('Description text')).toBeInTheDocument()
})
it('should not render titleDescription when not provided', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test Drawer"
body={<div>Body</div>}
/>,
)
expect(screen.queryByText(/Description/)).not.toBeInTheDocument()
})
it('should render JSX element as titleDescription', () => {
const descElement = <span data-testid="custom-desc">Custom Description</span>
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
titleDescription={descElement}
body={<div>Body</div>}
/>,
)
expect(screen.getByTestId('custom-desc')).toBeInTheDocument()
})
})
describe('Props - Display Options', () => {
it('should apply default maxWidthClassName', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
/>,
)
const innerPanel = screen.getByText('Test').closest('.bg-components-panel-bg')
const outerPanel = innerPanel?.parentElement
expect(outerPanel?.className).toContain('!max-w-[640px]')
})
it('should apply custom maxWidthClassName', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
maxWidthClassName="!max-w-[800px]"
/>,
)
const innerPanel = screen.getByText('Test').closest('.bg-components-panel-bg')
const outerPanel = innerPanel?.parentElement
expect(outerPanel?.className).toContain('!max-w-[800px]')
})
it('should apply custom panelClassName', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
panelClassName="custom-panel"
/>,
)
const innerPanel = screen.getByText('Test').closest('.bg-components-panel-bg')
const outerPanel = innerPanel?.parentElement
expect(outerPanel?.className).toContain('custom-panel')
})
it('should apply custom dialogClassName', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
dialogClassName="custom-dialog"
/>,
)
const dialog = screen.getByRole('dialog')
expect(dialog.className).toContain('custom-dialog')
})
it('should apply custom contentClassName', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
contentClassName="custom-content"
/>,
)
const title = screen.getByText('Test')
const header = title.closest('.shrink-0.border-b.border-divider-subtle')
const content = header?.parentElement
expect(content?.className).toContain('custom-content')
})
it('should apply custom headerClassName', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
headerClassName="custom-header"
/>,
)
const title = screen.getByText('Test')
const header = title.closest('.shrink-0.border-b.border-divider-subtle')
expect(header?.className).toContain('custom-header')
})
it('should apply custom height', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
height="500px"
/>,
)
const title = screen.getByText('Test')
const header = title.closest('.shrink-0.border-b.border-divider-subtle')
const content = header?.parentElement
expect(content?.getAttribute('style')).toContain('height: 500px')
})
it('should use default height', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
/>,
)
const title = screen.getByText('Test')
const header = title.closest('.shrink-0.border-b.border-divider-subtle')
const content = header?.parentElement
expect(content?.getAttribute('style')).toContain('calc(100vh - 72px)')
})
})
describe('Event Handlers', () => {
it('should call onHide when close button is clicked', () => {
const handleHide = vi.fn()
render(
<DrawerPlus
isShow={true}
onHide={handleHide}
title="Test"
body={<div>Body</div>}
/>,
)
const title = screen.getByText('Test')
const headerRight = title.nextElementSibling // .flex items-center
const closeDiv = headerRight?.querySelector('.cursor-pointer') as HTMLElement
fireEvent.click(closeDiv)
expect(handleHide).toHaveBeenCalledTimes(1)
})
})
describe('Complex Content', () => {
it('should render complex JSX elements in body', () => {
const complexBody = (
<div>
<h2>Header</h2>
<p>Paragraph</p>
<button>Action Button</button>
</div>
)
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={complexBody}
/>,
)
expect(screen.getByText('Header')).toBeInTheDocument()
expect(screen.getByText('Paragraph')).toBeInTheDocument()
expect(screen.getByRole('button', { name: 'Action Button' })).toBeInTheDocument()
})
it('should render complex footer', () => {
const complexFooter = (
<div className="footer-actions">
<button>Cancel</button>
<button>Save</button>
</div>
)
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
foot={complexFooter}
/>,
)
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument()
expect(screen.getByRole('button', { name: 'Save' })).toBeInTheDocument()
})
})
describe('Edge Cases', () => {
it('should handle empty title', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title=""
body={<div>Body</div>}
/>,
)
expect(screen.getByRole('dialog')).toBeInTheDocument()
})
it('should handle undefined titleDescription', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
titleDescription={undefined}
body={<div>Body</div>}
/>,
)
expect(screen.getByRole('dialog')).toBeInTheDocument()
})
it('should handle rapid isShow toggle', () => {
const { rerender } = render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
/>,
)
expect(screen.getByRole('dialog')).toBeInTheDocument()
rerender(
<DrawerPlus
isShow={false}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
/>,
)
expect(screen.queryByRole('dialog')).not.toBeInTheDocument()
rerender(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
/>,
)
expect(screen.getByRole('dialog')).toBeInTheDocument()
})
it('should handle special characters in title', () => {
const specialTitle = 'Test <> & " \' | Drawer'
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title={specialTitle}
body={<div>Body</div>}
/>,
)
expect(screen.getByText(specialTitle)).toBeInTheDocument()
})
it('should handle empty body content', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div></div>}
/>,
)
expect(screen.getByRole('dialog')).toBeInTheDocument()
})
it('should apply both custom maxWidth and panel classNames', () => {
render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
maxWidthClassName="!max-w-[500px]"
panelClassName="custom-style"
/>,
)
const innerPanel = screen.getByText('Test').closest('.bg-components-panel-bg')
const outerPanel = innerPanel?.parentElement
expect(outerPanel?.className).toContain('!max-w-[500px]')
expect(outerPanel?.className).toContain('custom-style')
})
})
describe('Memoization', () => {
it('should be memoized and not re-render on parent changes', () => {
const { rerender } = render(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
/>,
)
const dialog = screen.getByRole('dialog')
rerender(
<DrawerPlus
isShow={true}
onHide={() => {}}
title="Test"
body={<div>Body</div>}
/>,
)
expect(dialog).toBeInTheDocument()
})
})
})

View File

@ -0,0 +1,225 @@
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react'
import Dropdown from './index'
describe('Dropdown Component', () => {
const mockItems = [
{ value: 'option1', text: 'Option 1' },
{ value: 'option2', text: 'Option 2' },
]
const mockSecondItems = [
{ value: 'option3', text: 'Option 3' },
]
const onSelect = vi.fn()
afterEach(() => {
cleanup()
vi.clearAllMocks()
})
it('renders default trigger properly', () => {
const { container } = render(
<Dropdown items={mockItems} onSelect={onSelect} />,
)
const trigger = container.querySelector('button')
expect(trigger).toBeInTheDocument()
})
it('renders custom trigger when provided', () => {
render(
<Dropdown
items={mockItems}
onSelect={onSelect}
renderTrigger={open => <button data-testid="custom-trigger">{open ? 'Open' : 'Closed'}</button>}
/>,
)
const trigger = screen.getByTestId('custom-trigger')
expect(trigger).toBeInTheDocument()
expect(trigger).toHaveTextContent('Closed')
})
it('opens dropdown menu on trigger click and shows items', async () => {
render(
<Dropdown items={mockItems} onSelect={onSelect} />,
)
const trigger = screen.getByRole('button')
await act(async () => {
fireEvent.click(trigger)
})
// Dropdown items are rendered in a portal (document.body)
expect(screen.getByText('Option 1')).toBeInTheDocument()
expect(screen.getByText('Option 2')).toBeInTheDocument()
})
it('calls onSelect and closes dropdown when an item is clicked', async () => {
render(
<Dropdown items={mockItems} onSelect={onSelect} />,
)
const trigger = screen.getByRole('button')
await act(async () => {
fireEvent.click(trigger)
})
const option1 = screen.getByText('Option 1')
await act(async () => {
fireEvent.click(option1)
})
expect(onSelect).toHaveBeenCalledWith(mockItems[0])
expect(screen.queryByText('Option 1')).not.toBeInTheDocument()
})
it('calls onSelect and closes dropdown when a second item is clicked', async () => {
render(
<Dropdown items={mockItems} secondItems={mockSecondItems} onSelect={onSelect} />,
)
await act(async () => {
fireEvent.click(screen.getByRole('button'))
})
const option3 = screen.getByText('Option 3')
await act(async () => {
fireEvent.click(option3)
})
expect(onSelect).toHaveBeenCalledWith(mockSecondItems[0])
expect(screen.queryByText('Option 3')).not.toBeInTheDocument()
})
it('renders second items and divider when provided', async () => {
render(
<Dropdown
items={mockItems}
secondItems={mockSecondItems}
onSelect={onSelect}
/>,
)
const trigger = screen.getByRole('button')
await act(async () => {
fireEvent.click(trigger)
})
expect(screen.getByText('Option 1')).toBeInTheDocument()
expect(screen.getByText('Option 3')).toBeInTheDocument()
// Check for divider (h-px bg-divider-regular)
const divider = document.body.querySelector('.bg-divider-regular.h-px')
expect(divider).toBeInTheDocument()
})
it('applies custom classNames', async () => {
const popupClass = 'custom-popup'
const itemClass = 'custom-item'
const secondItemClass = 'custom-second-item'
render(
<Dropdown
items={mockItems}
secondItems={mockSecondItems}
onSelect={onSelect}
popupClassName={popupClass}
itemClassName={itemClass}
secondItemClassName={secondItemClass}
/>,
)
await act(async () => {
fireEvent.click(screen.getByRole('button'))
})
const popup = document.body.querySelector(`.${popupClass}`)
expect(popup).toBeInTheDocument()
const items = screen.getAllByText('Option 1')
expect(items[0]).toHaveClass(itemClass)
const secondItems = screen.getAllByText('Option 3')
expect(secondItems[0]).toHaveClass(secondItemClass)
})
it('applies open class to trigger when menu is open', async () => {
render(<Dropdown items={mockItems} onSelect={onSelect} />)
const trigger = screen.getByRole('button')
await act(async () => {
fireEvent.click(trigger)
})
expect(trigger).toHaveClass('bg-divider-regular')
})
it('handles JSX elements as item text', async () => {
const itemsWithJSX = [
{ value: 'jsx', text: <span data-testid="jsx-item">JSX Content</span> },
]
render(
<Dropdown items={itemsWithJSX} onSelect={onSelect} />,
)
await act(async () => {
fireEvent.click(screen.getByRole('button'))
})
expect(screen.getByTestId('jsx-item')).toBeInTheDocument()
expect(screen.getByText('JSX Content')).toBeInTheDocument()
})
it('does not render items section if items list is empty', async () => {
render(
<Dropdown items={[]} secondItems={mockSecondItems} onSelect={onSelect} />,
)
await act(async () => {
fireEvent.click(screen.getByRole('button'))
})
const p1Divs = document.body.querySelectorAll('.p-1')
expect(p1Divs.length).toBe(1)
expect(screen.queryByText('Option 1')).not.toBeInTheDocument()
expect(screen.getByText('Option 3')).toBeInTheDocument()
})
it('does not render divider if only one section is provided', async () => {
const { rerender } = render(
<Dropdown items={mockItems} onSelect={onSelect} />,
)
await act(async () => {
fireEvent.click(screen.getByRole('button'))
})
expect(document.body.querySelector('.bg-divider-regular.h-px')).not.toBeInTheDocument()
await act(async () => {
rerender(
<Dropdown items={[]} secondItems={mockSecondItems} onSelect={onSelect} />,
)
})
expect(document.body.querySelector('.bg-divider-regular.h-px')).not.toBeInTheDocument()
})
it('renders nothing if both item lists are empty', async () => {
render(<Dropdown items={[]} secondItems={[]} onSelect={onSelect} />)
await act(async () => {
fireEvent.click(screen.getByRole('button'))
})
const popup = document.body.querySelector('.bg-components-panel-bg')
expect(popup?.children.length).toBe(0)
})
it('passes triggerProps to ActionButton and applies custom className', () => {
render(
<Dropdown
items={mockItems}
onSelect={onSelect}
triggerProps={{
'disabled': true,
'aria-label': 'dropdown-trigger',
'className': 'custom-trigger-class',
}}
/>,
)
const trigger = screen.getByLabelText('dropdown-trigger')
expect(trigger).toBeDisabled()
expect(trigger).toHaveClass('custom-trigger-class')
})
})

View File

@ -0,0 +1,9 @@
import { render } from '@testing-library/react'
import Effect from '.'
describe('Effect', () => {
it('applies custom class names', () => {
const { container } = render(<Effect className="custom-class" />)
expect(container.firstChild).toHaveClass('custom-class')
})
})

View File

@ -0,0 +1,15 @@
import { render, screen } from '@testing-library/react'
import { EncryptedBottom } from '.'
describe('EncryptedBottom', () => {
it('applies custom class names', () => {
const { container } = render(<EncryptedBottom className="custom-class" />)
expect(container.firstChild).toHaveClass('custom-class')
})
it('passes keys', async () => {
render(<EncryptedBottom frontTextKey="provider.encrypted.front" backTextKey="provider.encrypted.back" />)
expect(await screen.findByText(/provider.encrypted.front/i)).toBeInTheDocument()
expect(await screen.findByText(/provider.encrypted.back/i)).toBeInTheDocument()
})
})

View File

@ -0,0 +1,28 @@
import { render } from '@testing-library/react'
import FileIcon from '.'
describe('File icon component', () => {
const testCases = [
{ type: 'csv', icon: 'Csv' },
{ type: 'doc', icon: 'Doc' },
{ type: 'docx', icon: 'Docx' },
{ type: 'htm', icon: 'Html' },
{ type: 'html', icon: 'Html' },
{ type: 'md', icon: 'Md' },
{ type: 'mdx', icon: 'Md' },
{ type: 'markdown', icon: 'Md' },
{ type: 'pdf', icon: 'Pdf' },
{ type: 'xls', icon: 'Xlsx' },
{ type: 'xlsx', icon: 'Xlsx' },
{ type: 'notion', icon: 'Notion' },
{ type: 'something-else', icon: 'Unknown' },
{ type: 'txt', icon: 'Txt' },
{ type: 'json', icon: 'Json' },
]
it.each(testCases)('renders $icon icon for type $type', ({ type, icon }) => {
const { container } = render(<FileIcon type={type} />)
const iconElement = container.querySelector(`[data-icon="${icon}"]`)
expect(iconElement).toBeInTheDocument()
})
})

View File

@ -0,0 +1,61 @@
import { render, screen } from '@testing-library/react'
import NodeStatus, { NodeStatusEnum } from '.'
describe('NodeStatus', () => {
it('renders with default status (warning) and default message', () => {
const { container } = render(<NodeStatus />)
expect(screen.getByText('Warning')).toBeInTheDocument()
// Default warning class
expect(container.firstChild).toHaveClass('bg-state-warning-hover')
expect(container.firstChild).toHaveClass('text-text-warning')
})
it('renders with error status and default message', () => {
const { container } = render(<NodeStatus status={NodeStatusEnum.error} />)
expect(screen.getByText('Error')).toBeInTheDocument()
expect(container.firstChild).toHaveClass('bg-state-destructive-hover')
expect(container.firstChild).toHaveClass('text-text-destructive')
})
it('renders with custom message', () => {
render(<NodeStatus message="Custom Message" />)
expect(screen.getByText('Custom Message')).toBeInTheDocument()
})
it('renders children correctly', () => {
render(
<NodeStatus>
<span data-testid="child">Child Element</span>
</NodeStatus>,
)
expect(screen.getByTestId('child')).toBeInTheDocument()
expect(screen.getByText('Child Element')).toBeInTheDocument()
})
it('applies custom className', () => {
const { container } = render(<NodeStatus className="custom-test-class" />)
expect(container.firstChild).toHaveClass('custom-test-class')
})
it('applies styleCss correctly', () => {
const { container } = render(<NodeStatus styleCss={{ color: 'red' }} />)
expect(container.firstChild).toHaveStyle({ color: 'rgb(255, 0, 0)' })
})
it('applies iconClassName to the icon', () => {
const { container } = render(<NodeStatus iconClassName="custom-icon-class" />)
// The icon is the first child of the div
const icon = container.querySelector('.custom-icon-class')
expect(icon).toBeInTheDocument()
expect(icon).toHaveClass('h-3.5')
expect(icon).toHaveClass('w-3.5')
})
it('passes additional HTML attributes to the container', () => {
render(<NodeStatus data-testid="node-status-container" id="my-id" />)
const container = screen.getByTestId('node-status-container')
expect(container).toHaveAttribute('id', 'my-id')
})
})

View File

@ -0,0 +1,49 @@
import { render, screen } from '@testing-library/react'
import NotionIcon from '.'
describe('Notion Icon', () => {
it('applies custom class names', () => {
const { container } = render(<NotionIcon className="custom-class" />)
expect(container.firstChild).toHaveClass('custom-class')
})
it('renders image on http url', () => {
render(<NotionIcon src="http://example.com/image.png" />)
expect(screen.getByAltText('workspace icon')).toHaveAttribute('src', 'http://example.com/image.png')
})
it('renders image on https url', () => {
render(<NotionIcon src="https://example.com/image.png" />)
expect(screen.getByAltText('workspace icon')).toHaveAttribute('src', 'https://example.com/image.png')
})
it('renders div on non-http url', () => {
render(<NotionIcon src="example.com/image.png" />)
expect(screen.getByText('example.com/image.png')).toBeInTheDocument()
})
it('renders name when no url is provided', () => {
render(<NotionIcon name="test-name" />)
expect(screen.getByText('T')).toBeInTheDocument()
})
it('renders image on type url for page', () => {
render(<NotionIcon type="page" src={{ type: 'url', url: 'https://example.com/image.png', emoji: null }} />)
expect(screen.getByAltText('page icon')).toHaveAttribute('src', 'https://example.com/image.png')
})
it('renders blank image on type url if no url is passed for page', () => {
render(<NotionIcon type="page" src={{ type: 'url', url: null, emoji: null }} />)
expect(screen.getByAltText('page icon')).not.toHaveAttribute('src')
})
it('renders emoji on type emoji for page', () => {
render(<NotionIcon type="page" src={{ type: 'emoji', url: null, emoji: '🚀' }} />)
expect(screen.getByText('🚀')).toBeInTheDocument()
})
it('renders icon on url for page', () => {
const { container } = render(<NotionIcon type="page" src="https://example.com/image.png" />)
expect(container.querySelector('svg')).not.toBeNull()
})
})

View File

@ -0,0 +1,46 @@
import { render, screen } from '@testing-library/react'
import PremiumBadge from './index'
describe('PremiumBadge', () => {
it('renders with default props', () => {
render(<PremiumBadge>Premium</PremiumBadge>)
const badge = screen.getByText('Premium')
expect(badge).toBeInTheDocument()
expect(badge).toHaveClass('premium-badge-m')
expect(badge).toHaveClass('premium-badge-blue')
})
it('renders with custom size and color', () => {
render(
<PremiumBadge size="s" color="indigo">
Premium
</PremiumBadge>,
)
const badge = screen.getByText('Premium')
expect(badge).toBeInTheDocument()
expect(badge).toHaveClass('premium-badge-s')
expect(badge).toHaveClass('premium-badge-indigo')
})
it('applies allowHover class when allowHover is true', () => {
render(
<PremiumBadge allowHover>
Premium
</PremiumBadge>,
)
const badge = screen.getByText('Premium')
expect(badge).toBeInTheDocument()
expect(badge).toHaveClass('allowHover')
})
it('applies custom styles', () => {
render(
<PremiumBadge styleCss={{ backgroundColor: 'red' }}>
Premium
</PremiumBadge>,
)
const badge = screen.getByText('Premium')
expect(badge).toBeInTheDocument()
expect(badge).toHaveStyle('background-color: rgb(255, 0, 0)') // Note: React converts 'red' to 'rgb(255, 0, 0)'
})
})