fix(bots): move adapter debugger to configuration

This commit is contained in:
RockChinQ
2026-08-26 23:07:02 +08:00
parent 3d692fa8db
commit a7badf6258
8 changed files with 49 additions and 13 deletions
@@ -233,7 +233,12 @@ try {
.click(); .click();
await page.getByRole("dialog").waitFor({ state: "hidden" }); await page.getByRole("dialog").waitFor({ state: "hidden" });
await page const adapterConfigCard = page.locator('[data-slot="card"]').filter({
has: page.getByText(/Adapter Configuration|适配器配置|アダプター設定/, {
exact: true,
}),
});
await adapterConfigCard
.getByRole("button", { .getByRole("button", {
name: /Listen for platform events|监听平台事件|プラットフォームイベントを監視/, name: /Listen for platform events|监听平台事件|プラットフォームイベントを監視/,
}) })
@@ -33,14 +33,14 @@ steps:
- "Confirm the adapter capability summary, friendly event name, target, and route status are visible." - "Confirm the adapter capability summary, friendly event name, target, and route status are visible."
- "Confirm overlapping routes and unmatched-event fallback behavior are explained before save." - "Confirm overlapping routes and unmatched-event fallback behavior are explained before save."
- "Open Test event route and run a dry-run against the current form." - "Open Test event route and run a dry-run against the current form."
- "Open Platform event debugging and send a real inbound event through the HTTP Bot adapter." - "Open Platform event debugging from Adapter Configuration and send a real inbound event through the HTTP Bot adapter."
- "Confirm the normalized event, raw event code, payload, and latest discarded route status are visible." - "Confirm the normalized event, raw event code, payload, and latest discarded route status are visible."
checks: checks:
- "UI: A user can choose a channel and add a scenario-labeled behavior during initial Bot creation." - "UI: A user can choose a channel and add a scenario-labeled behavior during initial Bot creation."
- "UI: Event routing uses user-facing labels and does not require the raw event name in the primary route card." - "UI: Event routing uses user-facing labels and does not require the raw event name in the primary route card."
- "UI: Definite route shadowing and unmatched-event fallback behavior are visible without opening raw logs." - "UI: Definite route shadowing and unmatched-event fallback behavior are visible without opening raw logs."
- "UI: Dry-run visibly reports that the route matched the discard processor." - "UI: Dry-run visibly reports that the route matched the discard processor."
- "UI: Adapter event debugging is clearly separate from route preview and starts listening only after the dialog opens." - "UI: Adapter event debugging lives under Adapter Configuration, remains separate from route preview, and starts listening only after the dialog opens."
- "UI: A real adapter event shows its friendly name, raw code, and normalized event data." - "UI: A real adapter event shows its friendly name, raw code, and normalized event data."
- "UI: The route card updates to discarded after the real inbound event is handled." - "UI: The route card updates to discarded after the real inbound event is handled."
- "Console: No unexpected frontend errors appear during the flow." - "Console: No unexpected frontend errors appear during the flow."
@@ -22,6 +22,7 @@ import { Agent, Bot } from '@/app/infra/entities/api';
import { getAdapterDocUrl } from '@/app/infra/entities/adapter-docs'; import { getAdapterDocUrl } from '@/app/infra/entities/adapter-docs';
import { ExternalLink, ChevronDown, ChevronRight } from 'lucide-react'; import { ExternalLink, ChevronDown, ChevronRight } from 'lucide-react';
import EventBindingsEditor from './EventBindingsEditor'; import EventBindingsEditor from './EventBindingsEditor';
import AdapterEventDebugDialog from './AdapterEventDebugDialog';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
@@ -687,6 +688,27 @@ const BotForm = forwardRef<BotFormHandle, BotFormProps>(function BotForm(
}} }}
/> />
)} )}
{currentAdapter && initBotId && (
<div className="flex flex-col gap-3 border-t pt-4 sm:flex-row sm:items-center sm:justify-between">
<div className="min-w-0">
<p className="text-sm font-medium">
{t('bots.adapterConfigurationTest')}
</p>
<p className="mt-1 text-sm text-muted-foreground">
{t('bots.adapterConfigurationTestDescription')}
</p>
</div>
<AdapterEventDebugDialog
botId={initBotId}
adapterLabel={
adapterNameList.find(
(adapter) => adapter.value === currentAdapter,
)?.label ?? currentAdapter
}
/>
</div>
)}
</CardContent> </CardContent>
</Card> </Card>
@@ -703,11 +725,6 @@ const BotForm = forwardRef<BotFormHandle, BotFormProps>(function BotForm(
<EventBindingsEditor <EventBindingsEditor
form={form} form={form}
botId={initBotId} botId={initBotId}
adapterLabel={
adapterNameList.find(
(adapter) => adapter.value === currentAdapter,
)?.label ?? currentAdapter
}
supportedEvents={adapterSupportedEvents[currentAdapter] || []} supportedEvents={adapterSupportedEvents[currentAdapter] || []}
agentOptions={agentNameList} agentOptions={agentNameList}
/> />
@@ -120,7 +120,6 @@ import {
groupEventPatterns, groupEventPatterns,
} from '@/app/home/components/event-patterns/event-pattern-groups'; } from '@/app/home/components/event-patterns/event-pattern-groups';
import EventSelectOptionContent from '@/app/home/components/event-patterns/EventSelectOptionContent'; import EventSelectOptionContent from '@/app/home/components/event-patterns/EventSelectOptionContent';
import AdapterEventDebugDialog from './AdapterEventDebugDialog';
export const PIPELINE_DISCARD = '__discard__'; export const PIPELINE_DISCARD = '__discard__';
@@ -129,7 +128,6 @@ export const PIPELINE_DISCARD = '__discard__';
interface EventBindingsEditorProps { interface EventBindingsEditorProps {
form: UseFormReturn<any>; form: UseFormReturn<any>;
botId?: string; botId?: string;
adapterLabel: string;
supportedEvents: string[]; supportedEvents: string[];
agentOptions: Agent[]; agentOptions: Agent[];
} }
@@ -1428,7 +1426,6 @@ function SortableBindingCard({
export default function EventBindingsEditor({ export default function EventBindingsEditor({
form, form,
botId, botId,
adapterLabel,
supportedEvents, supportedEvents,
agentOptions, agentOptions,
}: EventBindingsEditorProps) { }: EventBindingsEditorProps) {
@@ -1800,7 +1797,6 @@ export default function EventBindingsEditor({
eventOptions={dryRunEventOptions} eventOptions={dryRunEventOptions}
agentOptions={agentOptions} agentOptions={agentOptions}
/> />
<AdapterEventDebugDialog botId={botId} adapterLabel={adapterLabel} />
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<Button <Button
+3
View File
@@ -471,6 +471,9 @@ const enUS = {
adapterEventNeedsSavedBot: adapterEventNeedsSavedBot:
'Save the bot before listening for platform events.', 'Save the bot before listening for platform events.',
adapterEventCurrentPlatform: 'the current platform', adapterEventCurrentPlatform: 'the current platform',
adapterConfigurationTest: 'Test adapter configuration',
adapterConfigurationTestDescription:
'Trigger an event on the platform to confirm these settings work.',
refreshRouteStatus: 'Refresh status', refreshRouteStatus: 'Refresh status',
routeStatusIdle: 'No run yet', routeStatusIdle: 'No run yet',
routeStatusRefreshFailed: 'Failed to refresh route status.', routeStatusRefreshFailed: 'Failed to refresh route status.',
+3
View File
@@ -478,6 +478,9 @@ const jaJP = {
adapterEventNeedsSavedBot: adapterEventNeedsSavedBot:
'プラットフォームイベントを監視する前にボットを保存してください。', 'プラットフォームイベントを監視する前にボットを保存してください。',
adapterEventCurrentPlatform: '現在のプラットフォーム', adapterEventCurrentPlatform: '現在のプラットフォーム',
adapterConfigurationTest: 'アダプター設定をテスト',
adapterConfigurationTestDescription:
'プラットフォームでイベントを発生させ、この設定が動作することを確認します。',
refreshRouteStatus: '状態を更新', refreshRouteStatus: '状態を更新',
routeStatusIdle: '実行記録なし', routeStatusIdle: '実行記録なし',
routeStatusRefreshFailed: 'ルート状態の更新に失敗しました。', routeStatusRefreshFailed: 'ルート状態の更新に失敗しました。',
+3
View File
@@ -448,6 +448,9 @@ const zhHans = {
adapterEventData: '查看事件数据', adapterEventData: '查看事件数据',
adapterEventNeedsSavedBot: '请先保存机器人后再监听平台事件。', adapterEventNeedsSavedBot: '请先保存机器人后再监听平台事件。',
adapterEventCurrentPlatform: '当前平台', adapterEventCurrentPlatform: '当前平台',
adapterConfigurationTest: '适配器测试',
adapterConfigurationTestDescription:
'在当前平台触发事件,确认这组配置是否已经生效。',
refreshRouteStatus: '刷新状态', refreshRouteStatus: '刷新状态',
routeStatusIdle: '暂无运行记录', routeStatusIdle: '暂无运行记录',
routeStatusRefreshFailed: '刷新路由状态失败。', routeStatusRefreshFailed: '刷新路由状态失败。',
+10 -1
View File
@@ -445,6 +445,9 @@ test.describe('bot advanced flows', () => {
const routingCard = page const routingCard = page
.locator('[data-slot="card"]') .locator('[data-slot="card"]')
.filter({ has: page.getByText('Event Routing', { exact: true }) }); .filter({ has: page.getByText('Event Routing', { exact: true }) });
const adapterCard = page.locator('[data-slot="card"]').filter({
has: page.getByText('Adapter Configuration', { exact: true }),
});
const dangerCard = page const dangerCard = page
.locator('[data-slot="card"]') .locator('[data-slot="card"]')
.filter({ has: page.getByText('Danger Zone', { exact: true }) }); .filter({ has: page.getByText('Danger Zone', { exact: true }) });
@@ -532,7 +535,13 @@ test.describe('bot advanced flows', () => {
expect(dialogBox!.height).toBeLessThan(500); expect(dialogBox!.height).toBeLessThan(500);
await routeDialog.getByRole('button', { name: 'Close' }).first().click(); await routeDialog.getByRole('button', { name: 'Close' }).first().click();
await routingCard await expect(
routingCard.getByRole('button', { name: 'Listen for platform events' }),
).toHaveCount(0);
await expect(
adapterCard.getByText('Test adapter configuration'),
).toBeVisible();
await adapterCard
.getByRole('button', { name: 'Listen for platform events' }) .getByRole('button', { name: 'Listen for platform events' })
.click(); .click();
const adapterDialog = page.getByRole('dialog'); const adapterDialog = page.getByRole('dialog');