mirror of
https://github.com/langgenius/dify.git
synced 2026-08-28 19:16:51 +08:00
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: fatelei <fatelei@gmail.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: 盐粒 Yanli <yanli@dify.ai> Co-authored-by: Charles Yao <chongbinyao33@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: yunlu.wen <yunlu.wen@dify.ai> Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com> Co-authored-by: Jingyi <jingyi.qi@dify.ai> Co-authored-by: yyh <yuanyouhuilyz@gmail.com> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: hjlarry <hjlarry@163.com> Co-authored-by: Asuka Minato <i@asukaminato.eu.org> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Xiyuan Chen <52963600+GareArc@users.noreply.github.com> Co-authored-by: gigglewang <gigglewang@dify.ai> Co-authored-by: chariri <w@chariri.moe> Co-authored-by: Evan <2869018789@qq.com> Co-authored-by: zyssyz123 <916125788@qq.com>
305 lines
9.2 KiB
TypeScript
305 lines
9.2 KiB
TypeScript
import { act, render, screen } from '@testing-library/react'
|
|
import userEvent from '@testing-library/user-event'
|
|
import SecretKeyButton from '../secret-key-button'
|
|
|
|
vi.mock('@/app/components/develop/secret-key/secret-key-modal', () => ({
|
|
default: ({ isShow, onClose, appId, canManage }: { isShow: boolean, onClose: () => void, appId?: string, canManage: boolean }) => (
|
|
isShow
|
|
? (
|
|
<div data-testid="secret-key-modal">
|
|
<span data-testid="modal-app-id">{`Modal for ${appId || 'no-app'}`}</span>
|
|
<span data-testid="modal-can-manage">{String(canManage)}</span>
|
|
<button onClick={onClose} data-testid="close-modal">Close</button>
|
|
</div>
|
|
)
|
|
: null
|
|
),
|
|
}))
|
|
|
|
describe('SecretKeyButton', () => {
|
|
describe('rendering', () => {
|
|
it('should render the button', () => {
|
|
render(<SecretKeyButton />)
|
|
expect(screen.getByRole('button'))!.toBeInTheDocument()
|
|
})
|
|
|
|
it('should render the API key text', () => {
|
|
render(<SecretKeyButton />)
|
|
expect(screen.getByText('appApi.apiKey'))!.toBeInTheDocument()
|
|
})
|
|
|
|
it('should render the key icon', () => {
|
|
const { container } = render(<SecretKeyButton />)
|
|
const icon = container.querySelector('.i-ri-key-2-line')
|
|
expect(icon)!.toBeInTheDocument()
|
|
})
|
|
|
|
it('should not show modal initially', () => {
|
|
render(<SecretKeyButton />)
|
|
expect(screen.queryByTestId('secret-key-modal')).not.toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('button interaction', () => {
|
|
it('should open modal when button is clicked', async () => {
|
|
const user = userEvent.setup()
|
|
render(<SecretKeyButton canManage />)
|
|
|
|
const button = screen.getByRole('button')
|
|
await act(async () => {
|
|
await user.click(button)
|
|
})
|
|
|
|
expect(screen.getByTestId('secret-key-modal'))!.toBeInTheDocument()
|
|
})
|
|
|
|
it('should close modal when onClose is called', async () => {
|
|
const user = userEvent.setup()
|
|
render(<SecretKeyButton canManage />)
|
|
|
|
const button = screen.getByRole('button')
|
|
await act(async () => {
|
|
await user.click(button)
|
|
})
|
|
|
|
expect(screen.getByTestId('secret-key-modal'))!.toBeInTheDocument()
|
|
|
|
const closeButton = screen.getByTestId('close-modal')
|
|
await act(async () => {
|
|
await user.click(closeButton)
|
|
})
|
|
|
|
expect(screen.queryByTestId('secret-key-modal')).not.toBeInTheDocument()
|
|
})
|
|
|
|
it('should toggle modal visibility', async () => {
|
|
const user = userEvent.setup()
|
|
render(<SecretKeyButton canManage />)
|
|
|
|
const button = screen.getByRole('button')
|
|
|
|
await act(async () => {
|
|
await user.click(button)
|
|
})
|
|
expect(screen.getByTestId('secret-key-modal'))!.toBeInTheDocument()
|
|
|
|
const closeButton = screen.getByTestId('close-modal')
|
|
await act(async () => {
|
|
await user.click(closeButton)
|
|
})
|
|
expect(screen.queryByTestId('secret-key-modal')).not.toBeInTheDocument()
|
|
|
|
await act(async () => {
|
|
await user.click(button)
|
|
})
|
|
expect(screen.getByTestId('secret-key-modal'))!.toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('props', () => {
|
|
it('should apply custom className', () => {
|
|
render(<SecretKeyButton className="custom-class" />)
|
|
const button = screen.getByRole('button')
|
|
expect(button.className).toContain('custom-class')
|
|
})
|
|
|
|
it('should pass appId to modal', async () => {
|
|
const user = userEvent.setup()
|
|
render(<SecretKeyButton appId="app-123" canManage />)
|
|
|
|
const button = screen.getByRole('button')
|
|
await act(async () => {
|
|
await user.click(button)
|
|
})
|
|
|
|
expect(screen.getByText('Modal for app-123'))!.toBeInTheDocument()
|
|
})
|
|
|
|
it('should handle undefined appId', async () => {
|
|
const user = userEvent.setup()
|
|
render(<SecretKeyButton canManage />)
|
|
|
|
const button = screen.getByRole('button')
|
|
await act(async () => {
|
|
await user.click(button)
|
|
})
|
|
|
|
expect(screen.getByText('Modal for no-app'))!.toBeInTheDocument()
|
|
})
|
|
|
|
it('should pass canManage to modal', async () => {
|
|
const user = userEvent.setup()
|
|
render(<SecretKeyButton appId="app-123" canManage />)
|
|
|
|
const button = screen.getByRole('button')
|
|
await act(async () => {
|
|
await user.click(button)
|
|
})
|
|
|
|
expect(screen.getByTestId('modal-can-manage')).toHaveTextContent('true')
|
|
})
|
|
|
|
it('should disable the button and keep modal closed when canManage is false', async () => {
|
|
const user = userEvent.setup()
|
|
render(<SecretKeyButton appId="app-123" canManage={false} />)
|
|
|
|
const button = screen.getByRole('button')
|
|
expect(button).toBeDisabled()
|
|
|
|
await act(async () => {
|
|
await user.click(button)
|
|
})
|
|
|
|
expect(screen.queryByTestId('secret-key-modal')).not.toBeInTheDocument()
|
|
})
|
|
|
|
it('should disable the button by default when canManage is omitted', () => {
|
|
render(<SecretKeyButton appId="app-123" />)
|
|
|
|
expect(screen.getByRole('button')).toBeDisabled()
|
|
})
|
|
|
|
it('should apply custom textCls', () => {
|
|
render(<SecretKeyButton textCls="custom-text-class" />)
|
|
const text = screen.getByText('appApi.apiKey')
|
|
expect(text.className).toContain('custom-text-class')
|
|
})
|
|
})
|
|
|
|
describe('button styling', () => {
|
|
it('should have px-3 padding', () => {
|
|
render(<SecretKeyButton />)
|
|
const button = screen.getByRole('button')
|
|
expect(button.className).toContain('px-3')
|
|
})
|
|
})
|
|
|
|
describe('icon styling', () => {
|
|
it('should have icon container with flex layout', () => {
|
|
const { container } = render(<SecretKeyButton />)
|
|
const iconContainer = container.querySelector('.flex.items-center.justify-center')
|
|
expect(iconContainer)!.toBeInTheDocument()
|
|
})
|
|
|
|
it('should have correct icon dimensions', () => {
|
|
const { container } = render(<SecretKeyButton />)
|
|
const iconContainer = container.querySelector('.size-3\\.5')
|
|
expect(iconContainer)!.toBeInTheDocument()
|
|
})
|
|
|
|
it('should have tertiary text color on icon', () => {
|
|
const { container } = render(<SecretKeyButton />)
|
|
const icon = container.querySelector('.text-text-tertiary')
|
|
expect(icon)!.toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('text styling', () => {
|
|
it('should have system-xs-medium class', () => {
|
|
render(<SecretKeyButton />)
|
|
const text = screen.getByText('appApi.apiKey')
|
|
expect(text.className).toContain('system-xs-medium')
|
|
})
|
|
|
|
it('should have horizontal padding', () => {
|
|
render(<SecretKeyButton />)
|
|
const text = screen.getByText('appApi.apiKey')
|
|
expect(text.className).toContain('px-[3px]')
|
|
})
|
|
|
|
it('should have tertiary text color', () => {
|
|
render(<SecretKeyButton />)
|
|
const text = screen.getByText('appApi.apiKey')
|
|
expect(text.className).toContain('text-text-tertiary')
|
|
})
|
|
})
|
|
|
|
describe('modal props', () => {
|
|
it('should pass isShow prop to modal', async () => {
|
|
const user = userEvent.setup()
|
|
render(<SecretKeyButton canManage />)
|
|
|
|
expect(screen.queryByTestId('secret-key-modal')).not.toBeInTheDocument()
|
|
|
|
const button = screen.getByRole('button')
|
|
await act(async () => {
|
|
await user.click(button)
|
|
})
|
|
|
|
expect(screen.getByTestId('secret-key-modal'))!.toBeInTheDocument()
|
|
})
|
|
|
|
it('should pass onClose callback to modal', async () => {
|
|
const user = userEvent.setup()
|
|
render(<SecretKeyButton canManage />)
|
|
|
|
const button = screen.getByRole('button')
|
|
await act(async () => {
|
|
await user.click(button)
|
|
})
|
|
|
|
const closeButton = screen.getByTestId('close-modal')
|
|
await act(async () => {
|
|
await user.click(closeButton)
|
|
})
|
|
|
|
expect(screen.queryByTestId('secret-key-modal')).not.toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('accessibility', () => {
|
|
it('should have accessible button', () => {
|
|
render(<SecretKeyButton />)
|
|
const button = screen.getByRole('button')
|
|
expect(button)!.toBeInTheDocument()
|
|
})
|
|
|
|
it('should be keyboard accessible', async () => {
|
|
const user = userEvent.setup()
|
|
render(<SecretKeyButton canManage />)
|
|
|
|
const button = screen.getByRole('button')
|
|
button.focus()
|
|
expect(document.activeElement).toBe(button)
|
|
|
|
await act(async () => {
|
|
await user.keyboard('{Enter}')
|
|
})
|
|
|
|
expect(screen.getByTestId('secret-key-modal'))!.toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('multiple instances', () => {
|
|
it('should work independently when multiple instances exist', async () => {
|
|
const user = userEvent.setup()
|
|
render(
|
|
<>
|
|
<SecretKeyButton appId="app-1" canManage />
|
|
<SecretKeyButton appId="app-2" canManage />
|
|
</>,
|
|
)
|
|
|
|
const buttons = screen.getAllByRole('button')
|
|
expect(buttons).toHaveLength(2)
|
|
|
|
await act(async () => {
|
|
await user.click(buttons[0]!)
|
|
})
|
|
|
|
expect(screen.getByText('Modal for app-1'))!.toBeInTheDocument()
|
|
|
|
const closeButton = screen.getByTestId('close-modal')
|
|
await act(async () => {
|
|
await user.click(closeButton)
|
|
})
|
|
|
|
await act(async () => {
|
|
await user.click(buttons[1]!)
|
|
})
|
|
|
|
expect(screen.getByText('Modal for app-2'))!.toBeInTheDocument()
|
|
})
|
|
})
|
|
})
|