Major changes: - Add HandList.tsx component for left sidebar - Add HandTaskPanel.tsx for middle content area - Restructure Sidebar tabs: 分身/HANDS/Workflow - Remove Hands tab from RightPanel - Localize all UI text to Chinese - Archive legacy OpenClaw documentation - Add Hands integration lessons document - Update feature checklist with new components UI improvements: - Left sidebar now shows Hands list with status icons - Middle area shows selected Hand's tasks and results - Consistent styling with Tailwind CSS - Chinese status labels and buttons Documentation: - Create docs/archive/openclaw-legacy/ for old docs - Add docs/knowledge-base/hands-integration-lessons.md - Update docs/knowledge-base/feature-checklist.md - Update docs/knowledge-base/README.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
99 lines
3.2 KiB
TypeScript
99 lines
3.2 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const useGatewayStoreMock = vi.fn();
|
|
const useChatStoreMock = vi.fn();
|
|
const getStoredGatewayUrlMock = vi.fn(() => 'ws://127.0.0.1:18789');
|
|
const getStoredGatewayTokenMock = vi.fn(() => 'stored-token');
|
|
|
|
vi.mock('../../desktop/src/store/gatewayStore', () => ({
|
|
useGatewayStore: () => useGatewayStoreMock(),
|
|
}));
|
|
|
|
vi.mock('../../desktop/src/store/chatStore', () => ({
|
|
useChatStore: () => useChatStoreMock(),
|
|
}));
|
|
|
|
vi.mock('../../desktop/src/lib/gateway-client', () => ({
|
|
getStoredGatewayUrl: () => getStoredGatewayUrlMock(),
|
|
getStoredGatewayToken: () => getStoredGatewayTokenMock(),
|
|
}));
|
|
|
|
describe('General settings local gateway diagnostics', () => {
|
|
let refreshLocalGatewayMock: ReturnType<typeof vi.fn>;
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
refreshLocalGatewayMock = vi.fn(async () => ({ supported: true }));
|
|
|
|
useGatewayStoreMock.mockReturnValue({
|
|
connectionState: 'connected',
|
|
gatewayVersion: '2026.3.11',
|
|
error: null,
|
|
localGatewayBusy: false,
|
|
localGateway: {
|
|
supported: true,
|
|
cliAvailable: true,
|
|
serviceLoaded: true,
|
|
serviceLabel: 'OpenClaw Gateway',
|
|
serviceStatus: 'running',
|
|
port: 18789,
|
|
portStatus: 'busy',
|
|
probeUrl: 'ws://127.0.0.1:18789',
|
|
listenerPids: [1234],
|
|
runtimeSource: 'bundled',
|
|
runtimePath: 'C:/ZCLAW/resources/openclaw-runtime',
|
|
error: null,
|
|
},
|
|
quickConfig: {
|
|
gatewayUrl: 'ws://127.0.0.1:18789',
|
|
gatewayToken: '',
|
|
theme: 'light',
|
|
autoStart: false,
|
|
showToolCalls: false,
|
|
},
|
|
connect: vi.fn(async () => {}),
|
|
disconnect: vi.fn(),
|
|
saveQuickConfig: vi.fn(async () => {}),
|
|
refreshLocalGateway: refreshLocalGatewayMock,
|
|
startLocalGateway: vi.fn(async () => undefined),
|
|
stopLocalGateway: vi.fn(async () => undefined),
|
|
restartLocalGateway: vi.fn(async () => undefined),
|
|
});
|
|
|
|
useChatStoreMock.mockReturnValue({
|
|
currentModel: 'glm-5',
|
|
});
|
|
});
|
|
|
|
it('renders bundled runtime diagnostics and refreshes local gateway status on mount', async () => {
|
|
const reactModule = 'react';
|
|
const reactDomClientModule = 'react-dom/client';
|
|
const [{ act, createElement }, { createRoot }, { General }] = await Promise.all([
|
|
import(reactModule),
|
|
import(reactDomClientModule),
|
|
import('../../desktop/src/components/Settings/General'),
|
|
]);
|
|
|
|
const container = document.createElement('div');
|
|
document.body.appendChild(container);
|
|
const root = createRoot(container);
|
|
(globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
|
|
|
await act(async () => {
|
|
root.render(createElement(General));
|
|
});
|
|
|
|
expect(container.textContent).toContain('本地 Gateway');
|
|
expect(container.textContent).toContain('运行时来源');
|
|
expect(container.textContent).toContain('内置运行时');
|
|
expect(container.textContent).toContain('运行时路径');
|
|
expect(container.textContent).toContain('C:/ZCLAW/resources/openclaw-runtime');
|
|
expect(refreshLocalGatewayMock).toHaveBeenCalledTimes(1);
|
|
|
|
await act(async () => {
|
|
root.unmount();
|
|
});
|
|
container.remove();
|
|
});
|
|
});
|