perf: optimize app startup and background lifecycles

This commit is contained in:
inman committed 2026-08-19 00:56:15 +08:00
1 parent 31332f6d76
commit 927e13349b
121 files changed
+4359 -1400

No files matched your search

+40 -6
View File
@@ -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();