## Major Features ### Streaming Response System - Implement LlmDriver trait with `stream()` method returning async Stream - Add SSE parsing for Anthropic and OpenAI API streaming - Integrate Tauri event system for frontend streaming (`stream:chunk` events) - Add StreamChunk types: Delta, ToolStart, ToolEnd, Complete, Error ### MCP Protocol Implementation - Add MCP JSON-RPC 2.0 types (mcp_types.rs) - Implement stdio-based MCP transport (mcp_transport.rs) - Support tool discovery, execution, and resource operations ### Browser Hand Implementation - Complete browser automation with Playwright-style actions - Support Navigate, Click, Type, Scrape, Screenshot, Wait actions - Add educational Hands: Whiteboard, Slideshow, Speech, Quiz ### Security Enhancements - Implement command whitelist/blacklist for shell_exec tool - Add SSRF protection with private IP blocking - Create security.toml configuration file ## Test Improvements - Fix test import paths (security-utils, setup) - Fix vi.mock hoisting issues with vi.hoisted() - Update test expectations for validateUrl and sanitizeFilename - Add getUnsupportedLocalGatewayStatus mock ## Documentation Updates - Update architecture documentation - Improve configuration reference - Add quick-start guide updates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
145 lines
3.5 KiB
TypeScript
145 lines
3.5 KiB
TypeScript
/**
|
|
* ZCLAW Tauri E2E 测试配置
|
|
*
|
|
* 专门用于测试 Tauri 桌面应用模式
|
|
* 测试完整的 ZCLAW 功能,包括 Kernel Client 和 Rust 后端集成
|
|
*/
|
|
|
|
import { defineConfig, devices } from '@playwright/test';
|
|
import { spawn, ChildProcess } from 'child_process';
|
|
|
|
const TAURI_BINARY_PATH = './target/debug/desktop.exe';
|
|
const TAURI_DEV_PORT = 1420;
|
|
|
|
/**
|
|
* 启动 Tauri 开发应用
|
|
*/
|
|
async function startTauriApp(): Promise<ChildProcess> {
|
|
console.log('[Tauri Setup] Starting ZCLAW Tauri application...');
|
|
|
|
const isWindows = process.platform === 'win32';
|
|
const tauriScript = isWindows ? 'pnpm tauri dev' : 'pnpm tauri dev';
|
|
|
|
const child = spawn(tauriScript, [], {
|
|
shell: true,
|
|
cwd: './desktop',
|
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
env: { ...process.env, TAURI_DEV_PORT: String(TAURI_DEV_PORT) },
|
|
});
|
|
|
|
child.stdout?.on('data', (data) => {
|
|
const output = data.toString();
|
|
if (output.includes('error') || output.includes('Error')) {
|
|
console.error('[Tauri] ', output);
|
|
}
|
|
});
|
|
|
|
child.stderr?.on('data', (data) => {
|
|
console.error('[Tauri Error] ', data.toString());
|
|
});
|
|
|
|
console.log('[Tauri Setup] Waiting for Tauri to initialize...');
|
|
|
|
return child;
|
|
}
|
|
|
|
/**
|
|
* 检查 Tauri 应用是否就绪
|
|
*/
|
|
async function waitForTauriReady(): Promise<void> {
|
|
const maxWait = 120000; // 2 分钟超时
|
|
const startTime = Date.now();
|
|
|
|
while (Date.now() - startTime < maxWait) {
|
|
try {
|
|
const response = await fetch(`http://localhost:${TAURI_DEV_PORT}`, {
|
|
method: 'HEAD',
|
|
timeout: 5000,
|
|
});
|
|
if (response.ok) {
|
|
console.log('[Tauri Setup] Tauri app is ready!');
|
|
return;
|
|
}
|
|
} catch {
|
|
// 还没准备好,继续等待
|
|
}
|
|
|
|
// 检查进程是否还活着
|
|
console.log('[Tauri Setup] Waiting for app to start...');
|
|
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
}
|
|
|
|
throw new Error('Tauri app failed to start within timeout');
|
|
}
|
|
|
|
export default defineConfig({
|
|
testDir: './specs',
|
|
|
|
timeout: 180000, // Tauri 测试需要更长超时
|
|
expect: {
|
|
timeout: 15000,
|
|
},
|
|
|
|
fullyParallel: false, // Tauri 测试需要串行
|
|
forbidOnly: !!process.env.CI,
|
|
retries: 0,
|
|
|
|
reporter: [
|
|
['html', { outputFolder: 'test-results/tauri-report' }],
|
|
['json', { outputFile: 'test-results/tauri-results.json' }],
|
|
['list'],
|
|
],
|
|
|
|
use: {
|
|
baseURL: `http://localhost:${TAURI_DEV_PORT}`,
|
|
trace: 'on-first-retry',
|
|
screenshot: 'only-on-failure',
|
|
video: 'retain-on-failure',
|
|
actionTimeout: 15000,
|
|
navigationTimeout: 60000,
|
|
},
|
|
|
|
projects: [
|
|
// Tauri Chromium WebView 测试
|
|
{
|
|
name: 'tauri-webview',
|
|
use: {
|
|
...devices['Desktop Chrome'],
|
|
viewport: { width: 1280, height: 800 },
|
|
},
|
|
},
|
|
|
|
// Tauri 功能测试
|
|
{
|
|
name: 'tauri-functional',
|
|
testMatch: /tauri-.*\.spec\.ts/,
|
|
use: {
|
|
...devices['Desktop Chrome'],
|
|
viewport: { width: 1280, height: 800 },
|
|
},
|
|
},
|
|
|
|
// Tauri 设置测试
|
|
{
|
|
name: 'tauri-settings',
|
|
testMatch: /tauri-settings\.spec\.ts/,
|
|
use: {
|
|
...devices['Desktop Chrome'],
|
|
viewport: { width: 1280, height: 800 },
|
|
},
|
|
},
|
|
],
|
|
|
|
// 启动 Tauri 应用
|
|
webServer: {
|
|
command: 'pnpm tauri dev',
|
|
url: `http://localhost:${TAURI_DEV_PORT}`,
|
|
reuseExistingServer: process.env.CI ? false : true,
|
|
timeout: 180000,
|
|
stdout: 'pipe',
|
|
stderr: 'pipe',
|
|
},
|
|
|
|
outputDir: 'test-results/tauri-artifacts',
|
|
});
|