Close WeChat QR flow when binding is confirmed
This commit is contained in:
@@ -95,7 +95,7 @@ test('own WeChat conversation approval and generated PPT delivery in the desktop
|
||||
expect(calls.find(call => call.operation === 'channelConversationControl')?.input).toMatchObject({ session_id: 'self-session', run_id: 'channel-run', action: 'resume', decision: { decisions: [{ type: 'approve' }] } });
|
||||
expect(calls.find(call => call.operation === 'downloadChannelArtifact')?.input).toEqual({ session_id: 'self-session', path: '/outputs/创作建议.pptx' });
|
||||
expect(calls.some(call => call.operation === 'resume' || call.operation === 'submit')).toBe(false);
|
||||
await page.getByRole('button', { name: '发布与访问', exact: true }).click();
|
||||
await page.getByRole('button', { name: '使用与接入', exact: true }).click();
|
||||
const linked = page.getByRole('region', { name: '已关联渠道', exact: true });
|
||||
await expect(linked.getByText('创作微信', { exact: true })).toBeVisible();
|
||||
await expect(page.getByRole('region', { name: '个人微信渠道', exact: true })).toHaveCount(0);
|
||||
@@ -115,12 +115,20 @@ test('own WeChat conversation approval and generated PPT delivery in the desktop
|
||||
await page.getByLabel('微信验证码', { exact: true }).fill('123456');
|
||||
await page.getByRole('button', { name: '提交验证码', exact: true }).click();
|
||||
await expect.poll(async () => app.evaluate(() => (globalThis as typeof globalThis & { cloudChannelFixtureCalls: { operation: string; input: unknown }[] }).cloudChannelFixtureCalls.some(call => call.operation === 'channelAccountWechatBindVerification'))).toBe(true);
|
||||
if (await page.getByRole('button', { name: '关闭二维码', exact: true }).count()) await page.getByRole('button', { name: '关闭二维码', exact: true }).click();
|
||||
await expect(page.getByRole('img', { name: '个人微信登录二维码', exact: true })).toHaveCount(0);
|
||||
await expect(page.getByLabel('微信验证码', { exact: true })).toHaveCount(0);
|
||||
await expect(spareDetail.getByRole('status')).toContainText('微信已连接');
|
||||
await expect(spareDetail.getByRole('status')).toContainText('选择目标智能体');
|
||||
await spareDetail.getByRole('status').scrollIntoViewIfNeeded();
|
||||
await page.screenshot({ path: testInfo.outputPath('wechat-binding-completed.png'), fullPage: true });
|
||||
await spareDetail.getByLabel('目标智能体', { exact: true }).selectOption(agentSlug);
|
||||
await spareDetail.getByRole('button', { name: '保存目标', exact: true }).click();
|
||||
await expect.poll(async () => app.evaluate(() => (globalThis as typeof globalThis & { cloudChannelFixtureCalls: { operation: string; input: Record<string, unknown> }[] }).cloudChannelFixtureCalls
|
||||
.filter(call => call.operation === 'routeChannelAccount').some(call => call.input.channel_account_id === 'wechat-b' && call.input.target_agent_slug === 'ml-' + 'a'.repeat(32)))).toBe(true);
|
||||
await expect(page.getByRole('button', { name: /备用微信.*我的创作助手/ })).toBeVisible();
|
||||
await expect(spareDetail.getByRole('status')).toContainText('点击“启用”');
|
||||
await spareDetail.getByRole('button', { name: '启用', exact: true }).click();
|
||||
await expect(spareDetail.getByRole('status')).toContainText('返回微信与智能体对话');
|
||||
await page.getByRole('button', { name: /创作微信.*我的创作助手/ }).click();
|
||||
const legacyDetail = page.getByRole('article', { name: '创作微信账号详情', exact: true });
|
||||
const qrStartsBeforeSwitch = await app.evaluate(() => (globalThis as typeof globalThis & { cloudChannelFixtureCalls: { operation: string }[] }).cloudChannelFixtureCalls.filter(call => call.operation === 'channelAccountWechatBindStart').length);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react';
|
||||
import { act, fireEvent, render, screen, waitFor, within } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { beforeEach, expect, it, vi } from 'vitest';
|
||||
import { afterEach, beforeEach, expect, it, vi } from 'vitest';
|
||||
import { ChannelAccounts } from '@/pages/CloudAgents/ChannelAccounts';
|
||||
|
||||
const api = vi.hoisted(() => ({ call: vi.fn(), list: vi.fn(), recovery: vi.fn(), resolvePending: vi.fn() }));
|
||||
@@ -33,6 +33,73 @@ beforeEach(() => {
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => vi.useRealTimers());
|
||||
|
||||
it('closes the QR after confirmed polling and shows the next step for an unassigned account', async () => {
|
||||
const base = api.call.getMockImplementation()!;
|
||||
let connected = false;
|
||||
api.call.mockImplementation(async (operation, input) => {
|
||||
if (operation === 'channelAccounts') return { items: [connected ? { ...spare, health: 'connected' } : spare] };
|
||||
if (operation === 'channelAccountWechatBindStatus') {
|
||||
connected = true;
|
||||
return { session_key: 'qr-spare', status: 'confirmed', qrcode_url: 'https://login.example.test/qr' };
|
||||
}
|
||||
return base(operation, input);
|
||||
});
|
||||
render(<MemoryRouter><ChannelAccounts /></MemoryRouter>);
|
||||
const detail = await screen.findByRole('article', { name: '备用微信账号详情' });
|
||||
vi.useFakeTimers();
|
||||
await act(async () => fireEvent.click(within(detail).getByRole('button', { name: '扫码连接' })));
|
||||
expect(screen.getByRole('img', { name: '个人微信登录二维码' })).toBeVisible();
|
||||
await act(async () => vi.advanceTimersByTimeAsync(2000));
|
||||
expect(screen.queryByRole('img', { name: '个人微信登录二维码' })).not.toBeInTheDocument();
|
||||
expect(screen.queryByLabelText('微信验证码')).not.toBeInTheDocument();
|
||||
expect(screen.getByRole('status')).toHaveTextContent('微信已连接');
|
||||
expect(screen.getByRole('status')).toHaveTextContent('选择目标智能体');
|
||||
expect(within(detail).getByRole('button', { name: '重新连接' })).toBeEnabled();
|
||||
await act(async () => vi.advanceTimersByTimeAsync(6000));
|
||||
expect(api.call.mock.calls.filter(([operation]) => operation === 'channelAccountWechatBindStatus')).toHaveLength(1);
|
||||
expect(api.call.mock.calls.some(([operation]) => operation === 'routeChannelAccount' || operation === 'enableChannelAccount')).toBe(false);
|
||||
});
|
||||
|
||||
it.each(['channelAccountWechatBindStart', 'channelAccountWechatBindVerification'])('handles confirmed %s for an already routed account', async confirmedOperation => {
|
||||
const base = api.call.getMockImplementation()!;
|
||||
api.call.mockImplementation(async (operation, input) => {
|
||||
if (operation === confirmedOperation) return { session_key: 'qr-spare', status: 'confirmed', qrcode_url: 'https://login.example.test/qr' };
|
||||
return base(operation, input);
|
||||
});
|
||||
render(<MemoryRouter initialEntries={['/cloud-agents/channels?account=wechat-legacy']}><ChannelAccounts /></MemoryRouter>);
|
||||
const detail = await screen.findByRole('article', { name: '原有微信账号详情' });
|
||||
fireEvent.click(within(detail).getByRole('button', { name: '重新连接' }));
|
||||
if (confirmedOperation === 'channelAccountWechatBindVerification') {
|
||||
expect(await screen.findByRole('img', { name: '个人微信登录二维码' })).toBeVisible();
|
||||
fireEvent.change(screen.getByLabelText('微信验证码'), { target: { value: '123456' } });
|
||||
fireEvent.click(screen.getByRole('button', { name: '提交验证码' }));
|
||||
}
|
||||
expect(await screen.findByText('微信已连接', { exact: true })).toBeVisible();
|
||||
expect(screen.queryByRole('img', { name: '个人微信登录二维码' })).not.toBeInTheDocument();
|
||||
expect(screen.queryByLabelText('微信验证码')).not.toBeInTheDocument();
|
||||
expect(within(detail).getByRole('status')).toHaveTextContent('返回微信与智能体对话');
|
||||
fireEvent.click(screen.getByRole('button', { name: /备用微信.*未分配智能体/ }));
|
||||
expect(screen.queryByText('微信已连接', { exact: true })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('keeps the QR while verification is pending instead of claiming the connection is confirmed', async () => {
|
||||
const base = api.call.getMockImplementation()!;
|
||||
api.call.mockImplementation(async (operation, input) => {
|
||||
if (operation === 'channelAccountWechatBindVerification') return { session_key: 'qr-spare', status: 'pending', qrcode_url: 'https://login.example.test/qr' };
|
||||
return base(operation, input);
|
||||
});
|
||||
render(<MemoryRouter initialEntries={['/cloud-agents/channels?account=wechat-spare']}><ChannelAccounts /></MemoryRouter>);
|
||||
const detail = await screen.findByRole('article', { name: '备用微信账号详情' });
|
||||
fireEvent.click(within(detail).getByRole('button', { name: '扫码连接' }));
|
||||
fireEvent.change(await screen.findByLabelText('微信验证码'), { target: { value: '123456' } });
|
||||
fireEvent.click(screen.getByRole('button', { name: '提交验证码' }));
|
||||
expect(await screen.findByText('验证码已提交,请等待微信确认。')).toBeVisible();
|
||||
expect(screen.getByRole('img', { name: '个人微信登录二维码' })).toBeVisible();
|
||||
expect(screen.queryByText('微信已连接', { exact: true })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows legacy and unassigned accounts and can connect before choosing an Agent', async () => {
|
||||
render(<MemoryRouter initialEntries={['/cloud-agents/channels?account=wechat-spare']}><ChannelAccounts /></MemoryRouter>);
|
||||
expect(await screen.findByText('原有微信')).toBeVisible();
|
||||
|
||||
Reference in New Issue
Block a user