mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-28 21:27:14 +00:00
fix(bots): move adapter debugger to configuration
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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.',
|
||||||
|
|||||||
@@ -478,6 +478,9 @@ const jaJP = {
|
|||||||
adapterEventNeedsSavedBot:
|
adapterEventNeedsSavedBot:
|
||||||
'プラットフォームイベントを監視する前にボットを保存してください。',
|
'プラットフォームイベントを監視する前にボットを保存してください。',
|
||||||
adapterEventCurrentPlatform: '現在のプラットフォーム',
|
adapterEventCurrentPlatform: '現在のプラットフォーム',
|
||||||
|
adapterConfigurationTest: 'アダプター設定をテスト',
|
||||||
|
adapterConfigurationTestDescription:
|
||||||
|
'プラットフォームでイベントを発生させ、この設定が動作することを確認します。',
|
||||||
refreshRouteStatus: '状態を更新',
|
refreshRouteStatus: '状態を更新',
|
||||||
routeStatusIdle: '実行記録なし',
|
routeStatusIdle: '実行記録なし',
|
||||||
routeStatusRefreshFailed: 'ルート状態の更新に失敗しました。',
|
routeStatusRefreshFailed: 'ルート状態の更新に失敗しました。',
|
||||||
|
|||||||
@@ -448,6 +448,9 @@ const zhHans = {
|
|||||||
adapterEventData: '查看事件数据',
|
adapterEventData: '查看事件数据',
|
||||||
adapterEventNeedsSavedBot: '请先保存机器人后再监听平台事件。',
|
adapterEventNeedsSavedBot: '请先保存机器人后再监听平台事件。',
|
||||||
adapterEventCurrentPlatform: '当前平台',
|
adapterEventCurrentPlatform: '当前平台',
|
||||||
|
adapterConfigurationTest: '适配器测试',
|
||||||
|
adapterConfigurationTestDescription:
|
||||||
|
'在当前平台触发事件,确认这组配置是否已经生效。',
|
||||||
refreshRouteStatus: '刷新状态',
|
refreshRouteStatus: '刷新状态',
|
||||||
routeStatusIdle: '暂无运行记录',
|
routeStatusIdle: '暂无运行记录',
|
||||||
routeStatusRefreshFailed: '刷新路由状态失败。',
|
routeStatusRefreshFailed: '刷新路由状态失败。',
|
||||||
|
|||||||
@@ -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');
|
||||||
|
|||||||
Reference in New Issue
Block a user