mirror of
https://github.com/langgenius/dify.git
synced 2026-04-20 22:28:09 +08:00
109 lines
3.3 KiB
TypeScript
109 lines
3.3 KiB
TypeScript
import { render, screen } from '@testing-library/react'
|
|
import userEvent from '@testing-library/user-event'
|
|
import { useContextSelector } from 'use-context-selector'
|
|
// Group.test.tsx
|
|
import { describe, expect, it, vi } from 'vitest'
|
|
import RadioGroupContext from '../../context'
|
|
import Group from './index'
|
|
|
|
// small consumer that uses the same context as your component
|
|
function ContextConsumer({ showButton = true }: { showButton?: boolean }) {
|
|
// eslint-disable-next-line ts/no-explicit-any
|
|
const ctx = useContextSelector(RadioGroupContext, (v: any) => v)
|
|
const value = ctx?.value
|
|
const onChange = ctx?.onChange
|
|
return (
|
|
<div>
|
|
<span data-testid="radio-value">{String(value)}</span>
|
|
{showButton && (
|
|
<button
|
|
data-testid="radio-change-btn"
|
|
onClick={() => onChange?.('clicked-from-test')}
|
|
>
|
|
change
|
|
</button>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
describe('Group component', () => {
|
|
it('renders children and exposes provided value through context', () => {
|
|
render(
|
|
<Group value="initial-value">
|
|
<ContextConsumer />
|
|
</Group>,
|
|
)
|
|
|
|
const valueNode = screen.getByTestId('radio-value')
|
|
expect(valueNode).toBeInTheDocument()
|
|
expect(valueNode).toHaveTextContent('initial-value')
|
|
})
|
|
|
|
it('merges custom className with existing classes on root element', () => {
|
|
const { container } = render(
|
|
<Group value="v" className="my-extra-class">
|
|
<ContextConsumer />
|
|
</Group>,
|
|
)
|
|
|
|
const root = container.firstChild as HTMLElement
|
|
|
|
expect(root).toBeInTheDocument()
|
|
expect(root.className).toContain('my-extra-class')
|
|
|
|
// ensure it still has other classes (from cn + css module)
|
|
expect(root.className.length).toBeGreaterThan('my-extra-class'.length)
|
|
})
|
|
|
|
it('calls onChange from context when consumer triggers it', async () => {
|
|
const user = userEvent.setup()
|
|
const handleChange = vi.fn()
|
|
|
|
render(
|
|
<Group value="whatever" onChange={handleChange}>
|
|
<ContextConsumer />
|
|
</Group>,
|
|
)
|
|
|
|
const btn = screen.getByTestId('radio-change-btn')
|
|
await user.click(btn)
|
|
expect(handleChange).toHaveBeenCalledTimes(1)
|
|
expect(handleChange).toHaveBeenCalledWith('clicked-from-test')
|
|
})
|
|
|
|
it('does not throw if onChange is not provided and consumer calls it', async () => {
|
|
const user = userEvent.setup()
|
|
render(
|
|
<Group value={0}>
|
|
{/* the consumer will call onChange which is undefined */}
|
|
<ContextConsumer />
|
|
</Group>,
|
|
)
|
|
|
|
const btn = screen.getByTestId('radio-change-btn')
|
|
// clicking should not throw (if it threw the test would fail)
|
|
await user.click(btn)
|
|
// value still rendered correctly (verifies consumer reads numeric/false-y values too)
|
|
expect(screen.getByTestId('radio-value')).toHaveTextContent('0')
|
|
})
|
|
|
|
it('correctly passes boolean and numeric values through context', () => {
|
|
render(
|
|
<>
|
|
<Group value={false}>
|
|
<ContextConsumer />
|
|
</Group>
|
|
<Group value={123}>
|
|
<ContextConsumer showButton={false} />
|
|
</Group>
|
|
</>,
|
|
)
|
|
|
|
const nodes = screen.getAllByTestId('radio-value')
|
|
// first should be "false", second "123"
|
|
expect(nodes[0]).toHaveTextContent('false')
|
|
expect(nodes[1]).toHaveTextContent('123')
|
|
})
|
|
})
|