@@ -298,6 +298,11 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
298298 autoRepair : boolean ;
299299 projectPath : string ;
300300 } ) : Promise < void > {
301+ const token = await this . _context . secrets . get ( "testpilot.token" ) ;
302+ if ( ! token ) {
303+ this . _postMessage ( { command : "testError" , data : { error : "请先登录账号后再运行测试" } } ) ;
304+ return ;
305+ }
301306 try {
302307 this . _client . ensureWsConnected ( ) ;
303308 this . _postMessage ( { command : "testStarted" } ) ;
@@ -327,6 +332,11 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
327332 platform ?: string ;
328333 mobile_session_id ?: string ;
329334 } ) : Promise < void > {
335+ const token = await this . _context . secrets . get ( "testpilot.token" ) ;
336+ if ( ! token ) {
337+ this . _postMessage ( { command : "testError" , data : { error : "请先登录账号后再运行测试" } } ) ;
338+ return ;
339+ }
330340 try {
331341 // 测试前确保 WebSocket 已连接,保证步骤进度能实时推送到 WebView
332342 this . _client . ensureWsConnected ( ) ;
@@ -392,6 +402,11 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
392402 platform ?: string ;
393403 mobile_session_id ?: string ;
394404 } ) : Promise < void > {
405+ const token = await this . _context . secrets . get ( "testpilot.token" ) ;
406+ if ( ! token ) {
407+ this . _postMessage ( { command : "testError" , data : { error : "请先登录账号后再运行测试" } } ) ;
408+ return ;
409+ }
395410 try {
396411 this . _client . ensureWsConnected ( ) ;
397412 this . _postMessage ( { command : "testStarted" } ) ;
@@ -778,37 +793,15 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
778793 const lines : string [ ] = [ ] ;
779794 if ( projectDir ) {
780795 lines . push ( `当前项目路径:${ projectDir . replace ( / \\ / g, "/" ) } ` ) ;
781- lines . push ( `请直接读取该目录下的源代码生成蓝本,无需再次询问项目路径。` ) ;
782796 lines . push ( `` ) ;
783797 }
784798 lines . push ( `请为当前【${ pName } 】项目生成或更新测试蓝本。` ) ;
785799 lines . push ( `` ) ;
786- lines . push ( `⚠️ 生成前请先按顺序完成以下步骤(缺一不可):` ) ;
787- lines . push ( `1. 阅读 AGENTS.md(蓝本通用规则)` ) ;
788- lines . push ( `2. 阅读 .testpilot/platforms/${ platform } .md(${ pName } 平台专属规则、选择器规范和完整模板)` ) ;
789- lines . push ( `3. 通读项目源代码,确认已实现的功能列表` ) ;
790- lines . push ( `4. 检查 testpilot/ 目录是否已有蓝本文件:` ) ;
791- lines . push ( ` - 若【没有蓝本】:按规则从零生成完整蓝本,保存到 testpilot/ 目录` ) ;
792- lines . push ( ` ⚠️ 生成时 start_cwd 必须填当前项目的绝对路径,禁止填 "." 或相对路径` ) ;
793- lines . push ( ` - 若【已有蓝本】:必须按以下步骤做增量更新(禁止跳过任意一步):` ) ;
794- lines . push ( ` a. 校验配置字段(必须逐项检查):` ) ;
795- lines . push ( ` - start_cwd:必须是绝对路径(如 D:\\projects\\my-app 或 /home/user/my-app),禁止是 "." 或相对路径` ) ;
796- lines . push ( ` - base_url:必须非空且格式正确(如 http://localhost:5173)` ) ;
797- lines . push ( ` - platform:必须与项目类型匹配` ) ;
798- lines . push ( ` - start_command:必须能在 start_cwd 目录下独立运行` ) ;
799- lines . push ( ` b. 读取现有蓝本,列出其中所有 target 选择器` ) ;
800- lines . push ( ` c. 对每个 target,打开对应的源文件(HTML/JSX/TSX/Vue),验证该选择器真实存在:` ) ;
801- lines . push ( ` - 找到对应 DOM 元素:保留` ) ;
802- lines . push ( ` - 搜不到或已失效:更正为源码中实际存在的选择器` ) ;
803- lines . push ( ` ⚠️【选择器陷阱】React/Vue/Angular 中 <Select>、<Modal>、<Dropdown> 等自定义组件名` ) ;
804- lines . push ( ` 不会出现在渲染后的 DOM class 中!必须打开该组件的源文件查看其根元素实际渲染的 class/id。` ) ;
805- lines . push ( ` 例如:JSX 里 <CategorySelect /> 渲染后根节点可能是 <div class="relative"> 而不是 <div class="CategorySelect">` ) ;
806- lines . push ( ` d. 检查每个页面下的场景数量:若某个 page 有 ≥2 个场景且都需要先登录后操作同一页面,` ) ;
807- lines . push ( ` 必须给该 page 设置 "flow": true,避免每个场景都重复冷启动+登录(极大浪费时间)` ) ;
808- lines . push ( ` e. 检查源码中是否有新增功能未被现有蓝本覆盖,若有则补充对应场景` ) ;
809- lines . push ( ` f. 检查已删除的功能,删除对应场景` ) ;
810- lines . push ( ` g. 将更新后的完整蓝本覆盖写回原文件(禁止新建额外文件)` ) ;
811- lines . push ( ` ⚠️ 禁止仅凭印象或整体扫描就宣布"无需更新"——必须逐个搜索验证每个 target` ) ;
800+ lines . push ( `请按顺序完成以下步骤:` ) ;
801+ lines . push ( `1. 阅读本项目的 AGENTS.md` ) ;
802+ lines . push ( `2. 阅读 .testpilot/platforms/${ platform } .md` ) ;
803+ lines . push ( `3. 扫描项目源码,确认已实现的功能` ) ;
804+ lines . push ( `4. 按两个文件中的规则,生成或更新 testpilot/ 目录下的蓝本` ) ;
812805
813806 const prompt = lines . join ( "\n" ) ;
814807 await vscode . env . clipboard . writeText ( prompt ) ;
@@ -1412,22 +1405,22 @@ ${commonRules}`;
14121405 content="default-src 'none'; style-src 'unsafe-inline'; script-src 'nonce-${ nonce } '; img-src data:;">
14131406 <title>TestPilot AI</title>
14141407 <style>
1415- body { position: relative; }
1408+ body { position: relative; background: var(--bg); }
14161409 :root {
1417- --bg: var(--vscode-sideBar-background, #1e1e1e) ;
1418- --fg: var(--vscode-sideBar-foreground, #cccccc) ;
1419- --input-bg: var(--vscode-input-background, #3c3c3c) ;
1420- --input-border: var(--vscode-input-border, rgba(255,255,255,0.35) );
1421- --input-fg: var(--vscode-input-foreground, #cccccc) ;
1422- --btn-bg: var(--vscode-button-background, #0e639c) ;
1423- --btn-fg: var(--vscode-button-foreground, #ffffff) ;
1424- --btn-hover: var(--vscode-button-hoverBackground, #1177bb) ;
1425- --muted: var(--vscode-descriptionForeground, rgba(204,204,204,0.55) );
1410+ --bg: #1e1e1e;
1411+ --fg: #cccccc;
1412+ --input-bg: #3c3c3c;
1413+ --input-border: rgba(255,255,255,0.35);
1414+ --input-fg: #cccccc;
1415+ --btn-bg: #0e639c;
1416+ --btn-fg: #ffffff;
1417+ --btn-hover: #1177bb;
1418+ --muted: rgba(204,204,204,0.55);
14261419 --success: #4ec9b0;
14271420 --error: #f44747;
14281421 --warn: #cca700;
1429- --info: var(--vscode-descriptionForeground, #9d9d9d) ;
1430- --editor-bg: var(--vscode-editor-background, #252526) ;
1422+ --info: #9d9d9d;
1423+ --editor-bg: #252526;
14311424 }
14321425 body.light-mode {
14331426 --bg: #e8e8e8;
@@ -1525,7 +1518,7 @@ ${commonRules}`;
15251518 padding:0 12px 6px; text-align:right;
15261519 }
15271520 * { margin: 0; padding: 0; box-sizing: border-box; }
1528- body { font-family: var(--vscode-font-family) ; font-size: 13px; color: var(--fg); padding: 12px; }
1521+ body { font-family: "Segoe UI", system-ui, -apple-system, sans-serif ; font-size: 13px; color: var(--fg); padding: 12px; }
15291522 h2 { font-size: 14px; margin-bottom: 8px; display: flex; align-items: center; gap: 6px; }
15301523 .section { margin-bottom: 16px; }
15311524 .status-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
@@ -1571,7 +1564,7 @@ ${commonRules}`;
15711564 padding: 8px;
15721565 max-height: 200px;
15731566 overflow-y: auto;
1574- font-family: var(--vscode-editor-font-family) ;
1567+ font-family: "Cascadia Code", "Consolas", "Courier New", monospace ;
15751568 font-size: 12px;
15761569 line-height: 1.5;
15771570 }
0 commit comments