Skill: wu-xiyou/nl2ms-ui (version 1.0.0)

--- name: nl2ms-ui description: 根据自然语言通过midscene的api生成midscene脚本，可以生成web端、Android端、iOS端和PC端的midscene脚本。当用户提及生成脚本，android脚本、iOS脚本、web脚本、PC脚本时使用。 --- # Midscene 脚本生成技能 ## 何时使用此技能 当用户需要生成以下类型的自动化测试脚本时使用此技能： - **Android 脚本**：Android 移动端应用的自动化测试脚本 - **iOS 脚本**：iOS 移动端应用的自动化测试脚本 - **Web 脚本**：Web 浏览器的自动化测试脚本 - **PC 脚本**：桌面端应用的自动化测试脚本 ## 平台支持 ### 1. Android 端 - **YAML 示例**：`references/examples-android-yaml.md` - **TypeScript 示例**：`references/examples-android-ts.md` --- ### 2. iOS 端 - **YAML 示例**：`references/examples-ios-yaml.md` - **TypeScript 示例**：`references/examples-ios-ts.md` --- ### 3. Web 端 - **YAML 示例**：`references/examples-web-yaml.md` - **TypeScript 示例**：`references/examples-web-ts.md` --- ### 4. PC 端 - **YAML 示例**：`references/examples-pc-yaml.md` - **TypeScript 示例**：`references/examples-pc-ts.md` --- ## 最佳实践 1. **明确指定平台**：生成脚本时明确目标平台（Android/iOS/Web/PC） 2. **使用描述性步骤名称**：为每个步骤提供清晰的名称和描述 3. **合理使用等待**：优先使用 `aiWaitFor` 而非固定 `sleep` 4. **错误处理**：使用 `continueOnError: true` 或 try-catch 处理可选步骤 5. **验证断言**：在关键步骤后添加断言验证操作成功 6. **环境配置**：使用 `.env` 管理 API 密钥，设置合适的 `aiActionContext` --- ## 参考资源 - **API 参考**：`references/midscene-api` - **详细示例**： - Android: - YAML: `references/examples-android-yaml.md` - TypeScript: `references/examples-android-ts.md` - iOS: - YAML: `references/examples-ios-yaml.md` - TypeScript: `references/examples-ios-ts.md` - Web: - YAML: `references/examples-web-yaml.md` - TypeScript: `references/examples-web-ts.md` - PC: - YAML: `references/examples-pc-yaml.md` - TypeScript: `references/examples-pc-ts.md` - **常见场景**：`references/common-scenarios.md` - **官方文档**：https://midscenejs.com/api.html

path: references/examples-ios-yaml.md
content: # iOS 端 YAML 格式示例脚本

## 示例：发送消息脚本

```yaml
# iOS端单聊消息发送
ios:
  launch: com.testjdme
  wdaPort: 8100

agent:
  cache: true
  aiActionContext: "处理弹窗和权限请求。如果出现位置权限、用户协议等弹窗，点击同意。如果出现登录页面，请关闭它。"

tasks:
  - name: 搜索用户并进入聊天
    flow:

      - aiAction: 点击界面底部的‘消息‘
        description: 点击底部的消息tab

      - aiTap: 搜索
        description: 点击顶部搜索框

      - sleep: 3000

      - aiTap: 联系人
        description: 点击搜索联系人分类
      
      - aiAction: 在搜索框中输入'zhencuicui'
        locate: "搜索框"
        description: 在搜索框中输入zhencuicui
      
      - sleep: 3000
      
      - aiAssert: 搜索结果中显示甄翠翠
        description: 验证搜索结果包含目标用户
      
      - aiTap: 甄翠翠
        description: 点击搜索结果中的甄翠翠用户

  - name: 发送消息
    flow:
      
      - aiTap: 请输入消息
        description: 点击消息输入框获得焦点
      
      - aiInput: AI自动化测试
        locate: 请输入消息
        description: 在输入框中输入测试消息内容

      - aiTap: AI自动化测试
        description: 点击消息输入框获得焦点
      
      - aiTap: 发送
        description: 点击发送按钮发送消息
      
      - aiAssert: 消息"AI自动化测试"已发送成功
        description: 验证消息发送成功，在聊天记录中可见
      
      - aiAction: Back

      - sleep: 1000

      - aiAction: Back
```

## 支持的 iOS 操作（YAML）

| 方法 | YAML 语法 | 说明 |
|------|-----------|------|
| 启动应用 | `ios: { launch: "BundleID" }` | 启动应用 |
| 点击 | `aiTap: "按钮文本"` | 点击元素 |
| 输入 | `aiInput: "内容"`<br>`locate: "输入框"` | 输入文本 |
| 操作 | `aiAction: "操作描述"` | AI 操作 |
| 断言 | `aiAssert: "验证条件"` | 断言验证 |
| 查询 | `aiQuery: "查询内容"` | 查询信息 |
| 布尔判断 | `aiBoolean: "判断条件"` | 布尔判断 |
| 返回 | `aiAction: Back` | 返回上一页 |
| 等待 | `sleep: 毫秒数` | 等待指定时间 |


path: references/examples-android-ts.md
content: # Android 端 TypeScript 格式示例脚本

## 示例：发送消息脚本

```typescript
import { AndroidAgent, AndroidDevice, getConnectedDevices } from '@midscene/android';
import "dotenv/config"; // read environment variables from .env file

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

Promise.resolve(
  (async () => {
    console.log('🚀 启动京东ME消息发送流程自动化测试...');
    
    // 获取连接的设备
    const devices = await getConnectedDevices();
    if (devices.length === 0) {
      throw new Error('未找到连接的Android设备');
    }
    
    const page = new AndroidDevice(devices[0].udid);
    console.log(`📱 使用设备: ${devices[0].udid}`);

    // 初始化 Midscene agent，设置中文上下文
    const agent = new AndroidAgent(page, {
      aiActionContext: '处理弹窗和权限请求。如果出现位置权限、用户协议等弹窗，点击同意。如果出现登录页面，请关闭它。',
    });

    try {
      // 👀 连接设备并启动京东ME应用
      await page.connect();
      console.log('设备连接成功');
      
      await page.launch('com.jd.oa');
      console.log('启动京东ME应用');
      
      await sleep(3000); // 等待应用启动

      console.log('\n=== 第一步：搜索用户并进入聊天 ===');
      
      // 👀 点击底部的消息tab
      await agent.aiTap('消息');
      console.log('✅ 已点击底部消息tab');
      await sleep(2000);

      // 👀 点击顶部搜索框
      await agent.aiTap('搜索框');
      console.log('✅ 已点击顶部搜索框');
      await sleep(1000);

      // 👀 在搜索框中输入用户名
      await agent.aiInput('zhencuicui', '搜索框');
      console.log('✅ 已在搜索框中输入用户名: zhencuicui');
      await sleep(3000);

      // 👀 验证搜索结果包含目标用户
      await agent.aiAssert('搜索结果中显示甄翠翠');
      console.log('✅ 验证成功：搜索结果包含甄翠翠');

      console.log('\n=== 第二步：发送消息 ===');

      // 👀 点击搜索结果中的目标用户
      await agent.aiTap('甄翠翠');
      console.log('✅ 已点击搜索结果中的甄翠翠用户，进入聊天页面');
      await sleep(2000);

      // 👀 点击消息输入框获得焦点
      await agent.aiAction('点击消息输入框');
      console.log('✅ 已点击消息输入框，获得输入焦点');
      await sleep(1000);

      // 👀 在输入框中输入测试消息内容
      await agent.aiInput('AI自动化测试', '消息输入框');
      console.log('✅ 已在消息输入框中输入: AI自动化测试');
      await sleep(1000);

      // 👀 点击发送按钮发送消息
      await agent.aiAction('点击发送按钮');
      console.log('✅ 已点击发送按钮');
      await sleep(2000);

      // 👀 验证消息发送成功
      await agent.aiAssert('消息"AI自动化测试"已发送成功');
      console.log('✅ 验证成功：消息已发送并在聊天记录中可见');

      // 👀 返回上一页
      await agent.aiAction('AndroidBackButton');
      console.log('已返回上一页');
      await sleep(1000);

      // 👀 再次返回到主页面
      await agent.aiAction('AndroidBackButton');
      console.log('已返回主页面');

      console.log('\n🎉 京东ME消息发送流程测试完成！');

    } catch (error) {
      console.error('❌ 测试过程中发生错误:', error);
      throw error;
    }
  })()
);

```

## 支持的 Android 操作（TypeScript）

| 操作 | TypeScript 语法 | 说明 |
|------|----------------|------|
| 点击 | `await agent.aiTap('按钮文本')` | 点击指定文本的元素 |
| 输入 | `await agent.aiInput('内容', '输入框定位')` | 在指定输入框输入内容 |
| 操作 | `await agent.aiAction('操作描述')` | AI 驱动的复杂操作 |
| 断言 | `await agent.aiAssert('验证条件')` | 验证页面状态 |
| 查询 | `await agent.aiQuery('查询内容')` | 提取页面信息 |
| 启动应用 | `await device.launch('包名')` | 启动指定应用 |
| 返回 | `await agent.aiAction('AndroidBackButton')` | 触发系统返回键 |
| 等待 | `await sleep(毫秒数)` | 等待指定时间 |


path: references/examples-web-ts.md
content: # Web 端 TypeScript 格式示例脚本

## 示例：Joyspace基础操作

```typescript
import { chromium, Browser, BrowserContext, Page } from "playwright";
import { PlaywrightAgent } from "@midscene/web/playwright";
import "dotenv/config";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const storageStatePath = path.resolve(__dirname, "../../storage/state.json");

export const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

export interface JoyspaceOptions {
  headless?: boolean;
  url: string;
  waitTime?: number;
}

export class JoyspaceBase {
  private browser: Browser | null = null;
  private context: BrowserContext | null = null;
  private page: Page | null = null;
  private agent: PlaywrightAgent | null = null;

  async init(options: JoyspaceOptions): Promise<void> {
    // 启动浏览器
    this.browser = await chromium.launch({
      headless: options.headless ?? false,
      args: ["--no-sandbox", "--disable-setuid-sandbox"],
    });

    // 创建上下文选项
    const contextOptions: any = {};
    
    // 处理存储状态
    if (fs.existsSync(storageStatePath)) {
      console.log("使用存储的登录状态...");
      contextOptions.storageState = storageStatePath;
    } else {
      console.log("未找到存储状态，请先运行: npm run auth:save");
    }

    this.context = await this.browser.newContext(contextOptions);
    this.page = await this.context.newPage();
    
    // 导航到指定URL
    await this.page.goto(options.url);
    
    // 等待页面加载
    const waitTime = options.waitTime ?? 3000;
    await sleep(waitTime);
    
    // 初始化Midscene agent
    this.agent = new PlaywrightAgent(this.page);
  }

  getAgent(): PlaywrightAgent {
    if (!this.agent) {
      throw new Error("Agent not initialized. Call init() first.");
    }
    return this.agent;
  }

  getPage(): Page {
    if (!this.page) {
      throw new Error("Page not initialized. Call init() first.");
    }
    return this.page;
  }

  async close(): Promise<void> {
    if (this.browser) {
      await this.browser.close();
    }
  }
}
```

## 支持的 Web 操作（TypeScript）

| 操作 | TypeScript 语法 | 说明 |
|------|----------------|------|
| 导航 | `await page.goto('URL')` | 打开指定 URL |
| 点击 | `await aiTap('按钮文本')` | 点击指定文本的元素 |
| 输入 | `await aiInput('输入框', '内容')` | 在指定输入框输入内容 |
| 断言 | `await aiAssert('验证条件')` | 验证页面状态 |
| 查询 | `await aiQuery<string>('查询')` | 提取页面信息 |
| 等待 | `await aiWaitFor('等待条件')` | 等待指定条件 |
| 悬停 | `await aiHover('元素')` | 鼠标悬停 |
| 滚动 | `await aiScroll('down')` | 滚动页面 |
| 键盘 | `await aiKeyboardPress('Enter')` | 按下键盘按键 |
| 截图 | `await page.screenshot({ path: '路径' })` | 保存截图 |
| 等待 | `await page.waitForTimeout(1000)` | 等待指定毫秒 |


path: references/examples-pc-yaml.md
content: # PC 端 YAML 格式示例脚本

## 示例：发送消息脚本

```yaml
# PC端发送消息测试
# 注意：PC端主要使用TypeScript，YAML格式支持有限

pc:
  appName: "ME"
  restoreMinimized: true
  onlyForRect: false

agent:
  screenshotMode: "window"
  aiActionContext: "处理弹窗和权限请求"

tasks:
  - name: 搜索用户并进入聊天
    flow:
      - aiAction: 在应用界面中找到搜索框并点击它
        description: 点击搜索框
      - sleep: 1000
      - aiAction: 在搜索框中输入用户名
        description: 输入搜索内容
      - sleep: 2000
      - aiAction: 点击搜索结果中的目标用户
        description: 进入聊天界面

  - name: 发送消息
    flow:
      - aiAction: 在聊天界面的消息输入框中输入测试消息
        description: 输入消息内容
      - sleep: 1000
      - aiAction: 点击发送按钮发送消息
        description: 发送消息
      - sleep: 2000
      - aiOutput: 判断消息是否已成功发送并在聊天记录中显示
        description: 验证消息发送成功
```

## 支持的 PC 操作（YAML）

| 方法 | YAML 语法 | 说明 |
|------|-----------|------|
| 启动应用 | `pc: { appName: "应用名" }` | 启动应用窗口 |
| AI 操作 | `aiAction: "操作描述"` | AI 操作 |
| AI 输出/查询 | `aiOutput: "查询内容"` | AI 输出/查询 |
| 等待 | `sleep: 毫秒数` | 等待指定时间 |

**注意**：PC端主要使用TypeScript格式，YAML格式支持有限，建议优先使用TypeScript格式。


path: references/examples-pc-ts.md
content: # PC 端 TypeScript 格式示例脚本

## 示例1：发送消息脚本

```typescript
//消息在群聊中发送小表情
import * as dotenv from "dotenv";
import { fileURLToPath } from 'url';
import { dirname, join} from 'path';
import path from "path";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// 加载环境变量，指定.env文件路径
dotenv.config({ 
  path: join(__dirname, "../../.env")
});

import {
  createRemotePCService,
  IPCService,
  localPCService,
  PCDevice,
  PCAgent,
} from "../../src";
import { launchMESimple } from "../launch.me.simple";
import { setScreenshotConfig } from "../../src/config";

(async () => {
  let pcService: IPCService = undefined as any;
  if (process.argv.includes("--remote")) {
    pcService = await createRemotePCService("http://localhost:3333");
  } else {
    pcService = localPCService;
  }
   // 第一步：启动ME应用
   console.log("\n=== 第一步：启动ME应用 ===");
   await launchMESimple(pcService);

   console.log("\n=== 第二步：发送消息 ===");
   await jingmeGroupSendEmoji(pcService);
})();

export async function jingmeGroupSendEmoji(pcService: IPCService) {
  // 设置截图模式为窗口模式，精确捕获ME应用窗口
  setScreenshotConfig({ mode: 'window' });

  // 使用PCDevice确保应用正常运行
  console.log("🚀 初始化PC设备...");
  const pcDevice = new PCDevice({
    pcService,
    launchOptions: {
      windowInfo: {  // 使用窗口截图模式，精确捕获ME应用窗口
        appName: "ME",
        restoreMinimized: true,
        onlyForRect: false, // 关键：使用直接窗口截图，而不是显示器截图+裁剪
      },
    },
  });

  try {
    await pcDevice.launch();
    console.log("✅ PC设备启动成功");

    const pcAgent = new PCAgent(pcDevice);

    // 截取当前屏幕
    console.log("📸 截取当前屏幕...");
    
    // 创建截图保存路径并打印
    const screenshotPath = path.join(process.cwd(), `screenshot-${Date.now()}.png`);
    console.log(`💾 截图保存路径: ${screenshotPath}`);
    
    const screenshot = await pcDevice.screenshotBase64();
    console.log(`✅ 截图成功，大小: ${screenshot.length.toLocaleString()} 字符`);

    // 步骤1: 在顶部搜索"daijie27"
    console.log("🔍 步骤1: 搜索群聊'10220534754'");
    await pcAgent.aiAction("点击京ME应用中间顶部的搜索框，如果没有激活再点击一下；输入'10220534754'并按 Enter 键搜索");
    
    // 步骤2: 等待搜索结果加载
    console.log("⏳ 步骤2: 等待搜索结果加载...");
    await new Promise(resolve => setTimeout(resolve, 2000));
    
    // 步骤3: 打开第一个搜索结果
    console.log("👆 步骤3: 打开第一个搜索结果");
    await pcAgent.aiAction("点击“综合”tab 下搜索结果中含有“10220534754”的会话");
    
    // 步骤4: 等待聊天窗口打开
    console.log("⏳ 步骤4: 等待聊天窗口打开...");
    await new Promise(resolve => setTimeout(resolve, 2000));
    
    // 步骤5: 发送小表情
    console.log("💬 步骤5: 发送小表情");
    await pcAgent.aiTap("点击“请输入消息”上方的表情符号");

    await pcAgent.aiAction("在弹出来的表情弹窗上，点击“默认表情”下方第一个微笑表情");
    await new Promise(resolve => setTimeout(resolve, 1000));
    await pcAgent.aiKeyboardPress("Enter");

    console.log("🎉 京ME发送小表情执行完成！");

  } catch (error) {
    console.error("❌ 京ME发送小表情执行失败:", error);
    throw error;
  }
}
```

## 支持的 PC 操作（TypeScript）

| 方法 | TypeScript 语法 | 说明 |
|------|----------------|------|
| 启动应用 | `await pcDevice.launch()` | 启动应用窗口 |
| AI 操作 | `await pcAgent.aiAction('操作描述')` | AI 操作 |
| AI 输出/查询 | `await pcAgent.aiOutput('查询内容')` | AI 输出/查询 |
| 截图 | `await pcDevice.screenshotBase64()` | 截图 |
| 等待 | `await new Promise(resolve => setTimeout(resolve, ms))` | 等待指定时间 |


path: references/examples-ios-ts.md
content: # iOS 端 TypeScript 格式示例脚本

## 示例：发送消息脚本

```typescript
import { agentFromWebDriverAgent } from '@midscene/ios';
import "dotenv/config"; // read environment variables from .env file

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

// 主函数，包含简化的错误处理
async function messageSendTest() {
  let agent;
  
  try {
    console.log('🚀 开始初始化 Midscene agent...');
    // 👀 init Midscene agent
    agent = await agentFromWebDriverAgent({
      aiActionContext:
        '如果出现任何位置、权限、用户协议等弹窗，请点击"同意"。如果出现登录页面，请将其关闭。',
    });
    console.log('✅ Midscene agent 初始化成功');

    //PackageName="com.newjdme"  #Appstore and TF
    //PackageName = 'com.testjdme'  #Jenkins

    await agent.launch('com.testjdme');
    console.log('启动京东ME应用');
    
    await sleep(3000); // 等待应用启动

    console.log('\n=== 第一步：搜索用户并进入聊天 ===');
    
    // 👀 点击底部的消息tab
    await agent.aiTap('消息');
    console.log('✅ 已点击底部消息tab');
    await sleep(2000);

    // 👀 点击顶部搜索框
    await agent.aiTap('搜索框');
    console.log('✅ 已点击顶部搜索框');
    await sleep(1000);

    console.log('\n=== 第二步：输入搜索内容 ===');
    
    // 👀 在搜索框中输入用户名
    await agent.aiInput('左上角的搜索框', {
      value: "zhencuicui"
    });
    console.log('✅ 已在搜索框中输入用户名: zhencuicui');
    await sleep(5000);

    console.log('\n=== 第四步：进入聊天页面 ===');

    // 👀 点击搜索结果中的目标用户
    await agent.aiTap('甄翠翠');
    console.log('✅ 已点击搜索结果中的甄翠翠用户，进入聊天页面');
    await sleep(2000);

    console.log('\n=== 第五步：发送消息 ===');

    // 👀 在输入框中输入测试消息内容
    await agent.aiTap('消息输入框');
    await agent.aiInput("消息输入框", {
      value: "AI自动化测试"
    });
    console.log('✅ 已在消息输入框中输入: AI自动化测试');
    await sleep(1000);

    // 👀 点击发送按钮发送消息
    await agent.aiTap('发送按钮');
    console.log('✅ 已点击发送按钮');
    await sleep(2000);

    console.log('\n=== 第六步：验证消息发送结果 ===');
    
    // 👀 验证消息发送成功
    await agent.aiAssert('消息"AI自动化测试"已发送成功');
    console.log('✅ 验证成功：消息已发送并在聊天记录中可见');

    // 👀 返回上一页
    await agent.aiTap('返回按钮');
    console.log('✅ 已返回上一页');
    await sleep(1000);

    // 👀 再次返回到主页面
    await agent.aiTap('返回按钮');
    console.log('✅ 已返回主页面');
    await sleep(1000);

    console.log('🎉 京东ME消息发送流程测试完成！');

  } catch (error) {
    console.error('❌ 消息发送测试过程中发生错误:', error);
    
    throw error; // 重新抛出原始错误
  } 
}

// 运行测试
messageSendTest()
  .then(() => {
    console.log('✅ 消息发送测试完成');
    process.exit(0);
  })
  .catch((error) => {
    console.error('💥 消息发送测试失败:', error);
    process.exit(1);
  });
```

## 支持的 iOS 操作（TypeScript）

| 方法 | TypeScript 语法 | 说明 |
|------|----------------|------|
| 启动应用 | `await agent.launch('BundleID')` | 启动应用 |
| 点击 | `await agent.aiTap('按钮文本')` | 点击元素 |
| 输入 | `await agent.aiInput('内容', { locate: '输入框' })` | 输入文本 |
| 操作 | `await agent.aiAction('操作描述')` | AI 操作 |
| 断言 | `await agent.aiAssert('验证条件')` | 断言验证 |
| 查询 | `await agent.aiQuery('查询内容')` | 查询信息 |
| 布尔判断 | `await agent.aiBoolean('判断条件')` | 布尔判断 |
| 返回 | `await agent.aiAction('Back')` | 返回上一页 |
| 等待 | `await sleep(毫秒数)` | 等待指定时间 |


path: references/examples-android-yaml.md
content: # Android 端 YAML 格式示例脚本

## 示例：发送消息脚本

```yaml
# Android端单聊消息发送
android:
  launch: "com.jd.oa"

agent:
  cache: true
  aiActionContext: "处理弹窗和权限请求。如果出现位置权限、用户协议等弹窗，点击同意。如果出现登录页面，请关闭它。"

tasks:
  - name: 搜索用户并进入聊天
    flow:

      - sleep: 8000
      - aiAction: 点击消息
        description: 点击底部的消息tab

      - aiTap: 搜索
        description: 点击顶部搜索框
      
      - aiInput: "zhencuicui"
        locate: "搜索框"
        description: 在搜索框中输入用户名zhencuicui
      
      - sleep: 3000
      
      - aiAssert: 搜索结果中显示甄翠翠
        description: 验证搜索结果包含目标用户
      
      - aiTap: "甄翠翠"
        description: 点击搜索结果中的甄翠翠用户

  - name: 发送消息
    flow:
      
      - aiTap: 消息输入框
        description: 点击消息输入框获得焦点
      
      - aiInput: "AI自动化测试"
        locate: "消息输入框"
        description: 在输入框中输入测试消息内容
      
      - aiTap: 发送
        description: 点击发送按钮发送消息
      
      - aiAssert: 消息"AI自动化测试"已发送成功
        description: 验证消息发送成功，在聊天记录中可见
      
      - aiAction: AndroidBackButton

      - sleep: 1000

      - aiAction: AndroidBackButton
```

## 支持的 Android 操作（YAML）

| 操作 | YAML 语法 | 说明 |
|------|-----------|------|
| 点击 | `aiTap: "按钮文本"` | 点击指定文本的元素 |
| 输入 | `aiInput: "内容"`<br>`locate: "输入框定位"` | 在指定输入框输入内容 |
| 操作 | `aiAction: "操作描述"` | AI 驱动的复杂操作 |
| 断言 | `aiAssert: "验证条件"` | 验证页面状态 |
| 查询 | `aiQuery: "查询内容"` | 提取页面信息 |
| 启动应用 | `android: { launch: "包名" }` | 启动指定应用 |
| 返回 | `aiAction: AndroidBackButton` | 触发系统返回键 |
| 等待 | `sleep: 毫秒数` | 等待指定时间 |


path: references/examples-web-yaml.md
content: # Web 端 YAML 格式示例脚本

## 示例：autobot首页功能验证

```yaml
web:
  url: "https://dataagent.jd.com/#/dataagent/index"
  viewportWidth: 1358
  viewportHeight: 992
tasks:
  - name: "点击新建智能体按钮"
    flow:
      - click: "新建智能体"
      - sleep: 2000
      - aiAssert: "进入智能体创建页面"

  - name: "验证智能体创建页面基础元素"
    flow:
      - aiAssert: "页面显示 '未命名智能体' 标题"
      - aiAssert: "页面显示 '未上线' 状态"
      - aiAssert: "左侧显示导航菜单：体验、智能体、数据源、数据集"
      - aiAssert: "页面包含 '基本信息' 配置区域"
      - aiAssert: "页面包含 'PC端基础设置' 区域"
      - sleep: 1000

  - name: "测试基本信息配置"
    flow:
      - aiAssert: "显示 '应用名称' 输入框，占位符为 '请输入'"
      - type:
          selector: "input[placeholder='请输入']"
          text: "测试销售数据分析师"
      - aiAssert: "显示 '应用简介' 文本域"
      - type:
          selector: "textarea[placeholder='请输入']"
          text: "专业的销售数据分析智能体，提供深度数据洞察和报告生成服务"
      - sleep: 1000

  - name: "验证数据分析能力配置区域"
    flow:
      - aiAssert: "页面显示 '数据分析能力配置' 区域"
      - aiAssert: "包含 '数据问数' 选项"
      - aiAssert: "包含 '智能报告' 选项"
      - click: "数据问数"
      - sleep: 500
      - click: "智能报告"
      - sleep: 1000

  - name: "测试头像配置功能"
    flow:
      - aiAssert: "页面显示 '头像配置' 区域"
      - aiAssert: "显示 '选择头像' 提示"
      - aiAssert: "显示头像上传区域，包含 '+' 图标"
      - aiAssert: "显示 '选择' 按钮"
      - click: "选择"
      - sleep: 2000

  - name: "验证其他配置区域"
    flow:
      - aiAssert: "页面显示 '其他配置' 区域"
      - aiAssert: "包含 '帮助文档地址' 输入项"
      - sleep: 1000

  - name: "测试预览功能"
    flow:
      - aiAssert: "右侧显示 '预览' 区域"
      - aiAssert: "预览区显示智能体头像"
      - aiAssert: "显示 'Hi, ~我是应用名称' 问候语"
      - aiAssert: "显示 '应用简介' 文本"
      - aiAssert: "预览区包含发送按钮和输入框"
      - sleep: 1000

  - name: "验证左侧导航功能"
    flow:
      - aiAssert: "左侧导航显示 '基本信息' 选项"
      - aiAssert: "显示 '数据仓配置' 选项"
      - aiAssert: "显示 '预构内容配置' 选项"
      - click: "数据仓配置"
      - sleep: 1000
      - aiAssert: "切换到数据仓配置页面"

  - name: "测试表单验证功能"
    flow:
      - click: "基本信息"
      - sleep: 1000
      - clear: "input[placeholder='请输入']"
      - aiAssert: "应用名称为必填项，显示验证提示"
      - type:
          selector: "input[placeholder='请输入']"
          text: "销售数据分析师"
      - sleep: 1000

  - name: "测试智能体配置保存"
    flow:
      - aiAssert: "所有必填项已填写完成"
      - aiAssert: "页面配置项显示正常"
      - aiAssert: "预览效果符合预期"
      - sleep: 1000

  - name: "验证页面响应式和交互"
    flow:
      - aiAssert: "页面布局响应式设计正常"
      - aiAssert: "所有输入框和按钮可正常交互"
      - aiAssert: "预览区实时更新配置内容"
      - aiAssert: "页面加载和切换流畅"
      - sleep: 1000

  - name: "测试智能体列表页面功能"
    flow:
      - aiAssert: "智能体列表显示已创建的智能体"
      - aiAssert: "包含 '文件创建数据集', '评测数据分析师', '销售数据分析师【体验】' 等智能体"
      - aiAssert: "每个智能体显示状态：已上线/公共"
      - aiAssert: "显示创建者和更新时间信息"
      - aiAssert: "包含编辑和更多操作按钮"
      - sleep: 1000
```

## 支持的 Web 操作（YAML）

| 操作 | YAML 语法 | 说明 |
|------|-----------|------|
| 导航 | `navigate: { url: "URL" }` | 打开指定 URL |
| AI 点击 | `aiTap: "按钮文本"` | AI 驱动的点击操作（推荐） |
| 点击 | `click: "按钮文本"` | 直接点击指定文本的元素 |
| AI 输入 | `aiInput: { locate: "输入框", value: "内容" }` | AI 驱动的输入操作（推荐） |
| 输入 | `type: { selector: "选择器", text: "内容" }` | 使用选择器直接输入文本 |
| 清空 | `clear: "选择器"` | 清空指定输入框内容 |
| 断言 | `aiAssert: "验证条件"` | 验证页面状态 |
| 查询 | `aiQuery: { query: "查询", type: "string" }` | 提取页面信息 |
| 等待 | `aiWaitFor: "等待条件"` | 等待指定条件 |
| 悬停 | `aiHover: "元素"` | 鼠标悬停 |
| 滚动 | `aiScroll: { direction: "down" }` | 滚动页面 |
| 键盘 | `aiKeyboardPress: { key: "Enter" }` | 按下键盘按键 |
| 截图 | `screenshot: { path: "路径" }` | 保存截图 |
| 等待 | `sleep: 1000` | 等待指定毫秒 |


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)