perf: optimize app startup and background lifecycles
This commit is contained in:
1 parent
31332f6d76
commit
927e13349b
121 files changed
+4359
-1400
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react';
|
||||
import { act, fireEvent, render, screen, waitFor, within } from '@testing-library/react';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { AiHardware } from '@/pages/AiHardware';
|
||||
import {
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
type AiHardwareConfigurationCatalog,
|
||||
type AiHardwareOverview,
|
||||
} from '@/lib/ai-hardware';
|
||||
import { announceAiHardwareNavigation } from '@/lib/ai-hardware-navigation';
|
||||
|
||||
const api = vi.hoisted(() => ({
|
||||
getAiHardwareOverview: vi.fn(),
|
||||
@@ -82,6 +83,10 @@ function deferred<T>() {
|
||||
return { promise, resolve };
|
||||
}
|
||||
|
||||
function selectAgent(agentId: string): void {
|
||||
act(() => announceAiHardwareNavigation({ agentId }));
|
||||
}
|
||||
|
||||
async function openConfigurationEditor(): Promise<void> {
|
||||
const editButton = await screen.findByRole('button', { name: '编辑配置' });
|
||||
await waitFor(() => expect(editButton).toBeEnabled());
|
||||
@@ -98,6 +103,7 @@ async function openGuidedHotspotStep(): Promise<void> {
|
||||
|
||||
describe('AI hardware page', () => {
|
||||
beforeEach(() => {
|
||||
window.history.replaceState({}, '', '/ai-hardware');
|
||||
api.getAiHardwareOverview.mockResolvedValue(activeOverview);
|
||||
api.getAiHardwareProvisioningCapabilities.mockResolvedValue({ guidedHotspotBinding: false });
|
||||
api.scanAiHardwareProvisioningHotspots.mockResolvedValue({ platform: 'windows', hotspots: [] });
|
||||
@@ -113,6 +119,17 @@ describe('AI hardware page', () => {
|
||||
api.updateAiHardwareAssignment.mockResolvedValue({ data: { ...device, agent_id: agentTwo.id }, revision: 4 });
|
||||
});
|
||||
|
||||
it('presents basic settings as readable summary cards and a bounded prompt preview', async () => {
|
||||
render(<AiHardware />);
|
||||
|
||||
const settings = await screen.findByTestId('ai-hardware-basic-settings');
|
||||
expect(within(settings).getByTestId('ai-hardware-basic-settings-language')).toHaveTextContent('中文');
|
||||
expect(within(settings).getByTestId('ai-hardware-basic-settings-language')).toHaveTextContent('zh-CN');
|
||||
expect(within(settings).getByTestId('ai-hardware-basic-settings-voice')).toHaveTextContent('voice-a');
|
||||
expect(within(settings).getByTestId('ai-hardware-system-prompt-preview')).toHaveTextContent('保持简洁');
|
||||
expect(within(settings).getByText('配置版本 r4')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows loading, disabled, and credential recovery states without exposing diagnostics', async () => {
|
||||
const pending = deferred<AiHardwareOverview>();
|
||||
api.getAiHardwareOverview.mockReturnValueOnce(pending.promise);
|
||||
@@ -142,7 +159,7 @@ describe('AI hardware page', () => {
|
||||
fireEvent.change(screen.getByLabelText('名称'), { target: { value: '客厅助手' } });
|
||||
fireEvent.click(screen.getByRole('button', { name: '创建' }));
|
||||
await waitFor(() => expect(api.createAiHardwareAgent).toHaveBeenCalledWith('客厅助手'));
|
||||
expect((await screen.findAllByText('客厅助手')).length).toBeGreaterThan(0);
|
||||
expect(await screen.findByText(/客厅助手.*台设备已绑定/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('provisions an unprovisioned account by creating its first agent', async () => {
|
||||
@@ -337,12 +354,11 @@ describe('AI hardware page', () => {
|
||||
|
||||
render(<AiHardware />);
|
||||
|
||||
expect(await screen.findByRole('button', { name: /客厅助手.*1 台设备/ })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /书房助手.*1 台设备/ })).toBeInTheDocument();
|
||||
expect(await screen.findByText(/客厅助手.*1 台设备已绑定/)).toBeInTheDocument();
|
||||
expect(await screen.findByText('设备 device-one')).toBeInTheDocument();
|
||||
expect(screen.queryByText('设备 device-two')).not.toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /书房助手/ }));
|
||||
selectAgent(agentTwo.id);
|
||||
expect(await screen.findByText('设备 device-two')).toBeInTheDocument();
|
||||
expect(screen.queryByText('设备 device-one')).not.toBeInTheDocument();
|
||||
|
||||
@@ -357,6 +373,24 @@ describe('AI hardware page', () => {
|
||||
await waitFor(() => expect(api.bindAiHardwareDevice).toHaveBeenCalledWith('654321', agentTwo.id));
|
||||
});
|
||||
|
||||
it('restores the selected agent from the URL and keeps navigation state shareable', async () => {
|
||||
const agentTwoDevice = { id: 'device-two', agent_id: agentTwo.id, assignment_revision: 1 };
|
||||
window.history.replaceState({}, '', `/ai-hardware?agent=${agentTwo.id}`);
|
||||
api.getAiHardwareOverview.mockResolvedValueOnce({
|
||||
status: 'active',
|
||||
agents: [agentOne, agentTwo],
|
||||
devices: [device, agentTwoDevice],
|
||||
});
|
||||
|
||||
render(<AiHardware />);
|
||||
|
||||
expect(await screen.findByText('设备 device-two')).toBeInTheDocument();
|
||||
expect(window.location.search).toBe(`?agent=${agentTwo.id}`);
|
||||
selectAgent(agentOne.id);
|
||||
expect(await screen.findByText(/设备 device.*al-1/)).toBeInTheDocument();
|
||||
expect(window.location.search).toBe(`?agent=${agentOne.id}`);
|
||||
});
|
||||
|
||||
it('guides the existing hotspot flow, locks navigation while binding, and avoids online claims', async () => {
|
||||
api.getAiHardwareProvisioningCapabilities.mockResolvedValueOnce({ guidedHotspotBinding: true });
|
||||
const binding = deferred<typeof device>();
|
||||
@@ -849,7 +883,7 @@ describe('AI hardware page', () => {
|
||||
render(<AiHardware />);
|
||||
expect(await screen.findByText('保持简洁')).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /书房助手/ }));
|
||||
selectAgent(agentTwo.id);
|
||||
|
||||
expect(screen.queryByText('保持简洁')).not.toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: '编辑配置' })).toBeDisabled();
|
||||
|
||||
Reference in new issue
Block a user