refactor(channels): integrate channel runtime status management and enhance account status handling (#547)
This commit is contained in:
129
tests/unit/channels-page.test.tsx
Normal file
129
tests/unit/channels-page.test.tsx
Normal file
@@ -0,0 +1,129 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { act, render, waitFor } from '@testing-library/react';
|
||||
import { Channels } from '@/pages/Channels/index';
|
||||
|
||||
const hostApiFetchMock = vi.fn();
|
||||
const subscribeHostEventMock = vi.fn();
|
||||
|
||||
const { gatewayState } = vi.hoisted(() => ({
|
||||
gatewayState: {
|
||||
status: { state: 'running', port: 18789 },
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('@/stores/gateway', () => ({
|
||||
useGatewayStore: (selector: (state: typeof gatewayState) => unknown) => selector(gatewayState),
|
||||
}));
|
||||
|
||||
vi.mock('@/lib/host-api', () => ({
|
||||
hostApiFetch: (...args: unknown[]) => hostApiFetchMock(...args),
|
||||
}));
|
||||
|
||||
vi.mock('@/lib/host-events', () => ({
|
||||
subscribeHostEvent: (...args: unknown[]) => subscribeHostEventMock(...args),
|
||||
}));
|
||||
|
||||
vi.mock('react-i18next', () => ({
|
||||
useTranslation: () => ({
|
||||
t: (key: string) => key,
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock('sonner', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('Channels page status refresh', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
gatewayState.status = { state: 'running', port: 18789 };
|
||||
hostApiFetchMock.mockImplementation(async (path: string) => {
|
||||
if (path === '/api/channels/accounts') {
|
||||
return {
|
||||
success: true,
|
||||
channels: [
|
||||
{
|
||||
channelType: 'feishu',
|
||||
defaultAccountId: 'default',
|
||||
status: 'connected',
|
||||
accounts: [
|
||||
{
|
||||
accountId: 'default',
|
||||
name: 'Primary Account',
|
||||
configured: true,
|
||||
status: 'connected',
|
||||
isDefault: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
if (path === '/api/agents') {
|
||||
return {
|
||||
success: true,
|
||||
agents: [],
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error(`Unexpected host API path: ${path}`);
|
||||
});
|
||||
});
|
||||
|
||||
it('refetches channel accounts when gateway channel-status events arrive', async () => {
|
||||
let channelStatusHandler: (() => void) | undefined;
|
||||
subscribeHostEventMock.mockImplementation((eventName: string, handler: () => void) => {
|
||||
if (eventName === 'gateway:channel-status') {
|
||||
channelStatusHandler = handler;
|
||||
}
|
||||
return vi.fn();
|
||||
});
|
||||
|
||||
render(<Channels />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(hostApiFetchMock).toHaveBeenCalledWith('/api/channels/accounts');
|
||||
expect(hostApiFetchMock).toHaveBeenCalledWith('/api/agents');
|
||||
});
|
||||
expect(subscribeHostEventMock).toHaveBeenCalledWith('gateway:channel-status', expect.any(Function));
|
||||
|
||||
await act(async () => {
|
||||
channelStatusHandler?.();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
const channelFetchCalls = hostApiFetchMock.mock.calls.filter(([path]) => path === '/api/channels/accounts');
|
||||
const agentFetchCalls = hostApiFetchMock.mock.calls.filter(([path]) => path === '/api/agents');
|
||||
expect(channelFetchCalls).toHaveLength(2);
|
||||
expect(agentFetchCalls).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
it('refetches when the gateway transitions to running after mount', async () => {
|
||||
gatewayState.status = { state: 'starting', port: 18789 };
|
||||
|
||||
const { rerender } = render(<Channels />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(hostApiFetchMock).toHaveBeenCalledWith('/api/channels/accounts');
|
||||
expect(hostApiFetchMock).toHaveBeenCalledWith('/api/agents');
|
||||
});
|
||||
|
||||
gatewayState.status = { state: 'running', port: 18789 };
|
||||
await act(async () => {
|
||||
rerender(<Channels />);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
const channelFetchCalls = hostApiFetchMock.mock.calls.filter(([path]) => path === '/api/channels/accounts');
|
||||
const agentFetchCalls = hostApiFetchMock.mock.calls.filter(([path]) => path === '/api/agents');
|
||||
expect(channelFetchCalls).toHaveLength(2);
|
||||
expect(agentFetchCalls).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user