diff --git a/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-card.spec.tsx b/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-card.spec.tsx
index d28ed387e138ce..6e4c5b3c1e401b 100644
--- a/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-card.spec.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-card.spec.tsx
@@ -1,5 +1,6 @@
import type { EndpointListItem, PluginDetail } from '../../types'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import EndpointCard from '../endpoint-card'
@@ -10,6 +11,10 @@ const mockDeleteEndpoint = vi.fn()
const mockUpdateEndpoint = vi.fn()
const mockToastNotify = vi.fn()
+const getEditButton = () => screen.getByRole('button', { name: 'common.operation.edit' })
+const getDeleteButton = () => screen.getByRole('button', { name: 'common.operation.delete' })
+const getCopyButton = () => screen.getByRole('button', { name: 'common.operation.copy' })
+
vi.mock('@langgenius/dify-ui/toast', () => ({
toast: Object.assign(
(message: string, options?: { type?: string }) =>
@@ -212,6 +217,26 @@ describe('EndpointCard', () => {
})
describe('User Interactions', () => {
+ it('should reach endpoint actions through the tab order', async () => {
+ const user = userEvent.setup()
+ render(
+ ,
+ )
+
+ await user.tab()
+ expect(getEditButton()).toHaveFocus()
+
+ await user.tab()
+ expect(getDeleteButton()).toHaveFocus()
+
+ await user.keyboard('{Enter}')
+ expect(screen.getByText('plugin.detailPanel.endpointDeleteTip')).toBeInTheDocument()
+ })
+
it('should show disable confirm when switching off', () => {
render(
{
/>,
)
- const allButtons = screen.getAllByRole('button')
- fireEvent.click(allButtons[1]!)
+ fireEvent.click(getDeleteButton())
expect(screen.getByText('plugin.detailPanel.endpointDeleteTip'))!.toBeInTheDocument()
})
@@ -266,8 +290,7 @@ describe('EndpointCard', () => {
/>,
)
- const allButtons = screen.getAllByRole('button')
- fireEvent.click(allButtons[1]!)
+ fireEvent.click(getDeleteButton())
fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' }))
expect(mockDeleteEndpoint).toHaveBeenCalledWith('ep-1')
@@ -282,8 +305,7 @@ describe('EndpointCard', () => {
/>,
)
- const allButtons = screen.getAllByRole('button')
- fireEvent.click(allButtons[0]!)
+ fireEvent.click(getEditButton())
expect(screen.getByTestId('endpoint-modal'))!.toBeInTheDocument()
})
@@ -297,8 +319,7 @@ describe('EndpointCard', () => {
/>,
)
- const allButtons = screen.getAllByRole('button')
- fireEvent.click(allButtons[0]!)
+ fireEvent.click(getEditButton())
fireEvent.click(screen.getByTestId('modal-save'))
expect(mockUpdateEndpoint).toHaveBeenCalled()
@@ -316,8 +337,7 @@ describe('EndpointCard', () => {
/>,
)
- const allButtons = screen.getAllByRole('button')
- fireEvent.click(allButtons[2]!)
+ fireEvent.click(getCopyButton())
act(() => {
vi.advanceTimersByTime(2000)
@@ -386,8 +406,7 @@ describe('EndpointCard', () => {
/>,
)
- const allButtons = screen.getAllByRole('button')
- fireEvent.click(allButtons[1]!)
+ fireEvent.click(getDeleteButton())
expect(screen.getByText('plugin.detailPanel.endpointDeleteTip'))!.toBeInTheDocument()
fireEvent.click(screen.getByRole('button', { name: 'common.operation.cancel' }))
@@ -403,8 +422,7 @@ describe('EndpointCard', () => {
/>,
)
- const allButtons = screen.getAllByRole('button')
- fireEvent.click(allButtons[0]!)
+ fireEvent.click(getEditButton())
expect(screen.getByTestId('endpoint-modal'))!.toBeInTheDocument()
fireEvent.click(screen.getByTestId('modal-cancel'))
@@ -456,8 +474,7 @@ describe('EndpointCard', () => {
/>,
)
- const allButtons = screen.getAllByRole('button')
- fireEvent.click(allButtons[1]!)
+ fireEvent.click(getDeleteButton())
fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' }))
expect(mockDeleteEndpoint).toHaveBeenCalled()
@@ -472,8 +489,7 @@ describe('EndpointCard', () => {
/>,
)
- const allButtons = screen.getAllByRole('button')
- fireEvent.click(allButtons[0]!)
+ fireEvent.click(getEditButton())
expect(screen.getByTestId('endpoint-modal'))!.toBeInTheDocument()
diff --git a/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx b/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx
index 7376cbe59c5bc0..a7b08b8deec414 100644
--- a/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx
@@ -154,11 +154,15 @@ const EndpointCard = ({ pluginDetail, data, handleChange }: Props) => {
{data.name}
-
-
+
+
$['operation.edit'], { ns: 'common' })}
+ onClick={showEndpointModalConfirm}
+ >
$['operation.delete'], { ns: 'common' })}
onClick={showDeleteConfirm}
className="text-text-tertiary hover:bg-state-destructive-hover hover:text-text-destructive"
>