web-tests

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
IMPORTANT - Path Resolution: This skill is installed globally but saves outputs to the user's working directory. Always pass
CWD
environment variable when executing commands to ensure outputs go to the correct location.
Common installation paths:
  • Plugin system:
    ~/.claude/plugins/marketplaces/claude-craftkit/plugins/ui-tests/skills/web-tests
  • Manual global:
    ~/.claude/skills/web-tests
  • Project-specific:
    <project>/.claude/skills/web-tests
重要提示 - 路径解析: 此Skill为全局安装,但会将输出内容保存到用户的工作目录。执行命令时务必传入
CWD
环境变量,以确保输出保存到正确位置。
常见安装路径:
  • 插件系统:
    ~/.claude/plugins/marketplaces/claude-craftkit/plugins/ui-tests/skills/web-tests
  • 手动全局安装:
    ~/.claude/skills/web-tests
  • 项目专属:
    <project>/.claude/skills/web-tests

Web Testing & Browser Automation

网页测试与浏览器自动化

General-purpose browser automation skill. I'll write custom Playwright code for any automation task you request and execute it via the universal executor.
CRITICAL WORKFLOW - Follow these steps in order:
  1. Auto-detect dev servers - For localhost testing, ALWAYS run server detection FIRST:
    bash
    cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(servers => console.log(JSON.stringify(servers)))"
    • If 1 server found: Use it automatically, inform user
    • If multiple servers found: Ask user which one to test
    • If no servers found: Ask for URL or offer to help start dev server
  2. Write scripts to user's working directory - Save to
    .web-tests/scripts/test-*.js
    in user's repo
  3. Use visible browser by default - Always use
    headless: false
    unless user specifically requests headless mode
  4. Parameterize URLs - Always make URLs configurable via constant at top of script
通用型浏览器自动化Skill。我会根据你的需求编写自定义Playwright代码,并通过通用执行器运行。
关键工作流程 - 请按以下步骤执行:
  1. 自动检测开发服务器 - 针对本地主机测试,务必先运行服务器检测:
    bash
    cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(servers => console.log(JSON.stringify(servers)))"
    • 找到1个服务器:自动使用该服务器,并告知用户
    • 找到多个服务器:询问用户选择测试哪一个
    • 未找到服务器:询问目标URL,或提供启动开发服务器的帮助
  2. 将脚本写入用户工作目录 - 保存到用户仓库的
    .web-tests/scripts/test-*.js
    路径下
  3. 默认使用可视化浏览器 - 除非用户明确要求无头模式,否则始终使用
    headless: false
  4. 参数化URL - 始终在脚本顶部通过常量配置URL

How It Works

工作原理

  1. You describe what you want to test/automate
  2. I auto-detect running dev servers (or ask for URL if testing external site)
  3. I write custom Playwright code in
    .web-tests/scripts/test-*.js
    (in user's working directory)
  4. I execute it via:
    CWD=$(pwd) cd $SKILL_DIR && node run.js .web-tests/scripts/test-*.js
  5. Results displayed in real-time, browser window visible for debugging
  6. Screenshots automatically saved to
    .web-tests/screenshots/
  1. 你描述需要测试/自动化的任务
  2. 我自动检测运行中的开发服务器(若测试外部网站则询问URL)
  3. 我在用户工作目录下的
    .web-tests/scripts/test-*.js
    中编写自定义Playwright代码
  4. 我通过以下命令执行:
    CWD=$(pwd) cd $SKILL_DIR && node run.js .web-tests/scripts/test-*.js
  5. 实时显示结果,浏览器窗口保持可见以便调试
  6. 截图自动保存到
    .web-tests/screenshots/
    目录

Setup (First Time)

首次设置

bash
cd $SKILL_DIR
npm run setup
This installs Playwright and Chromium browser. Only needed once.
bash
cd $SKILL_DIR
npm run setup
此命令将安装Playwright和Chromium浏览器,仅需执行一次。

Execution Pattern

执行流程

Step 1: Detect dev servers (for localhost testing)
bash
cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(s => console.log(JSON.stringify(s)))"
Step 2: Write test script to user's .web-tests/scripts/ with URL parameter
javascript
// .web-tests/scripts/test-page.js
const { chromium } = require("playwright");

// Parameterized URL (detected or user-provided)
const TARGET_URL = "http://localhost:3001"; // <-- Auto-detected or from user

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(TARGET_URL);
  console.log("Page loaded:", await page.title());

  await page.screenshot({
    path: ".web-tests/screenshots/page.png",
    fullPage: true,
  });
  console.log("📸 Screenshot saved to .web-tests/screenshots/page.png");

  await browser.close();
})();
Step 3: Execute from skill directory with CWD
bash
CWD=$(pwd) cd $SKILL_DIR && node run.js $(pwd)/.web-tests/scripts/test-page.js
步骤1:检测开发服务器(针对本地主机测试)
bash
cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(s => console.log(JSON.stringify(s)))"
步骤2:将带URL参数的测试脚本写入用户的.web-tests/scripts/目录
javascript
// .web-tests/scripts/test-page.js
const { chromium } = require("playwright");

// 参数化URL(自动检测或用户提供)
const TARGET_URL = "http://localhost:3001"; // <-- 自动检测或用户提供

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(TARGET_URL);
  console.log("页面已加载:", await page.title());

  await page.screenshot({
    path: ".web-tests/screenshots/page.png",
    fullPage: true,
  });
  console.log("📸 截图已保存到 .web-tests/screenshots/page.png");

  await browser.close();
})();
步骤3:从Skill目录传入CWD执行
bash
CWD=$(pwd) cd $SKILL_DIR && node run.js $(pwd)/.web-tests/scripts/test-page.js

Common Patterns

常见场景示例

Test a Page (Multiple Viewports)

多视口页面测试

javascript
// .web-tests/scripts/test-responsive.js
const { chromium } = require("playwright");
const helpers = require("$SKILL_DIR/lib/helpers"); // Path will be resolved

const TARGET_URL = "http://localhost:3001"; // Auto-detected

(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 100 });
  const page = await browser.newPage();

  // Desktop test
  await page.setViewportSize({ width: 1920, height: 1080 });
  await page.goto(TARGET_URL);
  console.log("Desktop - Title:", await page.title());
  await helpers.takeScreenshot(page, "desktop"); // Saves to .web-tests/screenshots/

  // Mobile test
  await page.setViewportSize({ width: 375, height: 667 });
  await helpers.takeScreenshot(page, "mobile");

  await browser.close();
})();
javascript
// .web-tests/scripts/test-responsive.js
const { chromium } = require("playwright");
const helpers = require("$SKILL_DIR/lib/helpers"); // 路径会自动解析

const TARGET_URL = "http://localhost:3001"; // 自动检测

(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 100 });
  const page = await browser.newPage();

  // 桌面端测试
  await page.setViewportSize({ width: 1920, height: 1080 });
  await page.goto(TARGET_URL);
  console.log("桌面端 - 页面标题:", await page.title());
  await helpers.takeScreenshot(page, "desktop"); // 保存到 .web-tests/screenshots/

  // 移动端测试
  await page.setViewportSize({ width: 375, height: 667 });
  await helpers.takeScreenshot(page, "mobile");

  await browser.close();
})();

Test Login Flow

登录流程测试

javascript
// .web-tests/scripts/test-login.js
const { chromium } = require("playwright");

const TARGET_URL = "http://localhost:3001"; // Auto-detected

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(`${TARGET_URL}/login`);

  await page.fill('input[name="email"]', "test@example.com");
  await page.fill('input[name="password"]', "password123");
  await page.click('button[type="submit"]');

  // Wait for redirect
  await page.waitForURL("**/dashboard");
  console.log("✅ Login successful, redirected to dashboard");

  await browser.close();
})();
javascript
// .web-tests/scripts/test-login.js
const { chromium } = require("playwright");

const TARGET_URL = "http://localhost:3001"; // 自动检测

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(`${TARGET_URL}/login`);

  await page.fill('input[name="email"]', "test@example.com");
  await page.fill('input[name="password"]', "password123");
  await page.click('button[type="submit"]');

  // 等待重定向
  await page.waitForURL("**/dashboard");
  console.log("✅ 登录成功,已重定向到控制台");

  await browser.close();
})();

Fill and Submit Form

表单填写与提交测试

javascript
// .web-tests/scripts/test-form.js
const { chromium } = require("playwright");
const helpers = require("$SKILL_DIR/lib/helpers");

const TARGET_URL = "http://localhost:3001"; // Auto-detected

(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 50 });
  const page = await browser.newPage();

  await page.goto(`${TARGET_URL}/contact`);

  await page.fill('input[name="name"]', "John Doe");
  await page.fill('input[name="email"]', "john@example.com");
  await page.fill('textarea[name="message"]', "Test message");

  await helpers.takeScreenshot(page, "form-filled");
  await page.click('button[type="submit"]');

  // Verify submission
  await page.waitForSelector(".success-message");
  console.log("✅ Form submitted successfully");
  await helpers.takeScreenshot(page, "form-success");

  await browser.close();
})();
javascript
// .web-tests/scripts/test-form.js
const { chromium } = require("playwright");
const helpers = require("$SKILL_DIR/lib/helpers");

const TARGET_URL = "http://localhost:3001"; // 自动检测

(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 50 });
  const page = await browser.newPage();

  await page.goto(`${TARGET_URL}/contact`);

  await page.fill('input[name="name"]', "John Doe");
  await page.fill('input[name="email"]', "john@example.com");
  await page.fill('textarea[name="message"]', "测试消息");

  await helpers.takeScreenshot(page, "form-filled");
  await page.click('button[type="submit"]');

  // 验证提交结果
  await page.waitForSelector(".success-message");
  console.log("✅ 表单提交成功");
  await helpers.takeScreenshot(page, "form-success");

  await browser.close();
})();

Check for Broken Links

失效链接检查

javascript
// .web-tests/scripts/test-broken-links.js
const { chromium } = require("playwright");

const TARGET_URL = "http://localhost:3001";

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(TARGET_URL);

  const links = await page.locator('a[href^="http"]').all();
  const results = { working: 0, broken: [] };

  for (const link of links) {
    const href = await link.getAttribute("href");
    try {
      const response = await page.request.head(href);
      if (response.ok()) {
        results.working++;
      } else {
        results.broken.push({ url: href, status: response.status() });
      }
    } catch (e) {
      results.broken.push({ url: href, error: e.message });
    }
  }

  console.log(`✅ Working links: ${results.working}`);
  console.log(`❌ Broken links:`, results.broken);

  await browser.close();
})();
javascript
// .web-tests/scripts/test-broken-links.js
const { chromium } = require("playwright");

const TARGET_URL = "http://localhost:3001";

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(TARGET_URL);

  const links = await page.locator('a[href^="http"]').all();
  const results = { working: 0, broken: [] };

  for (const link of links) {
    const href = await link.getAttribute("href");
    try {
      const response = await page.request.head(href);
      if (response.ok()) {
        results.working++;
      } else {
        results.broken.push({ url: href, status: response.status() });
      }
    } catch (e) {
      results.broken.push({ url: href, error: e.message });
    }
  }

  console.log(`✅ 可用链接数: ${results.working}`);
  console.log(`❌ 失效链接:`, results.broken);

  await browser.close();
})();

Take Screenshot with Error Handling

带错误处理的截图

javascript
// .web-tests/scripts/screenshot-with-error-handling.js
const { chromium } = require("playwright");
const helpers = require("$SKILL_DIR/lib/helpers");

const TARGET_URL = "http://localhost:3001";

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  try {
    await page.goto(TARGET_URL, {
      waitUntil: "networkidle",
      timeout: 10000,
    });

    await helpers.takeScreenshot(page, "page-success");
    console.log("📸 Screenshot saved successfully");
  } catch (error) {
    console.error("❌ Error:", error.message);
    await helpers.takeScreenshot(page, "page-error");
  } finally {
    await browser.close();
  }
})();
javascript
// .web-tests/scripts/screenshot-with-error-handling.js
const { chromium } = require("playwright");
const helpers = require("$SKILL_DIR/lib/helpers");

const TARGET_URL = "http://localhost:3001";

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  try {
    await page.goto(TARGET_URL, {
      waitUntil: "networkidle",
      timeout: 10000,
    });

    await helpers.takeScreenshot(page, "page-success");
    console.log("📸 截图保存成功");
  } catch (error) {
    console.error("❌ 错误:", error.message);
    await helpers.takeScreenshot(page, "page-error");
  } finally {
    await browser.close();
  }
})();

Test Responsive Design (Full)

完整响应式设计测试

javascript
// .web-tests/scripts/test-responsive-full.js
const { chromium } = require("playwright");
const helpers = require("$SKILL_DIR/lib/helpers");

const TARGET_URL = "http://localhost:3001"; // Auto-detected

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  const viewports = [
    { name: "Desktop", width: 1920, height: 1080 },
    { name: "Tablet", width: 768, height: 1024 },
    { name: "Mobile", width: 375, height: 667 },
  ];

  for (const viewport of viewports) {
    console.log(
      `Testing ${viewport.name} (${viewport.width}x${viewport.height})`
    );

    await page.setViewportSize({
      width: viewport.width,
      height: viewport.height,
    });

    await page.goto(TARGET_URL);
    await page.waitForTimeout(1000);

    await helpers.takeScreenshot(page, viewport.name.toLowerCase());
  }

  console.log("✅ All viewports tested");
  await browser.close();
})();
javascript
// .web-tests/scripts/test-responsive-full.js
const { chromium } = require("playwright");
const helpers = require("$SKILL_DIR/lib/helpers");

const TARGET_URL = "http://localhost:3001"; // 自动检测

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  const viewports = [
    { name: "Desktop", width: 1920, height: 1080 },
    { name: "Tablet", width: 768, height: 1024 },
    { name: "Mobile", width: 375, height: 667 },
  ];

  for (const viewport of viewports) {
    console.log(
      `正在测试 ${viewport.name} (${viewport.width}x${viewport.height})`
    );

    await page.setViewportSize({
      width: viewport.width,
      height: viewport.height,
    });

    await page.goto(TARGET_URL);
    await page.waitForTimeout(1000);

    await helpers.takeScreenshot(page, viewport.name.toLowerCase());
  }

  console.log("✅ 所有视口测试完成");
  await browser.close();
})();

Inline Execution (Simple Tasks)

内联执行(简单任务)

For quick one-off tasks, you can execute code inline without creating files:
bash
undefined
对于快速一次性任务,你可以直接内联执行代码而无需创建文件:
bash
undefined

Take a quick screenshot

快速截图

cd $SKILL_DIR && CWD=$(pwd) node run.js " const browser = await chromium.launch({ headless: false }); const page = await browser.newPage(); await page.goto('http://localhost:3001'); await helpers.takeScreenshot(page, 'quick-test'); console.log('Screenshot saved'); await browser.close(); "

**When to use inline vs files:**

- **Inline**: Quick one-off tasks (screenshot, check if element exists, get page title)
- **Files**: Complex tests, responsive design checks, anything user might want to re-run
cd $SKILL_DIR && CWD=$(pwd) node run.js " const browser = await chromium.launch({ headless: false }); const page = await browser.newPage(); await page.goto('http://localhost:3001'); await helpers.takeScreenshot(page, 'quick-test'); console.log('截图已保存'); await browser.close(); "

**内联执行与文件执行的适用场景:**

- **内联执行**:快速一次性任务(截图、检查元素是否存在、获取页面标题)
- **文件执行**:复杂测试、响应式设计检查、用户可能需要重复运行的任务

Available Helpers

可用辅助函数

Optional utility functions in
lib/helpers.js
:
javascript
const helpers = require("./lib/helpers");

// Detect running dev servers (CRITICAL - use this first!)
const servers = await helpers.detectDevServers();
console.log("Found servers:", servers);

// Safe click with retry
await helpers.safeClick(page, "button.submit", { retries: 3 });

// Safe type with clear
await helpers.safeType(page, "#username", "testuser");

// Take timestamped screenshot (auto-saves to .web-tests/screenshots/)
await helpers.takeScreenshot(page, "test-result");

// Handle cookie banners
await helpers.handleCookieBanner(page);

// Extract table data
const data = await helpers.extractTableData(page, "table.results");
See
lib/helpers.js
for full list.
lib/helpers.js
中提供了可选的工具函数:
javascript
const helpers = require("./lib/helpers");

// 检测运行中的开发服务器(关键 - 务必优先使用!)
const servers = await helpers.detectDevServers();
console.log("找到的服务器:", servers);

// 带重试的安全点击
await helpers.safeClick(page, "button.submit", { retries: 3 });

// 带清空的安全输入
await helpers.safeType(page, "#username", "testuser");

// 带时间戳的截图(自动保存到 .web-tests/screenshots/)
await helpers.takeScreenshot(page, "test-result");

// 处理Cookie弹窗
await helpers.handleCookieBanner(page);

// 提取表格数据
const data = await helpers.extractTableData(page, "table.results");
完整列表请查看
lib/helpers.js

Directory Structure

目录结构

When testing, the skill creates this structure in the user's working directory:
user-repo/
└── .web-tests/
    ├── scripts/          # Test scripts (reusable)
    │   ├── test-login.js
    │   ├── test-form.js
    │   ├── test-responsive.js
    │   └── test-broken-links.js
    └── screenshots/      # Screenshots with timestamps
        ├── desktop-2025-10-23T12-30-45.png
        ├── mobile-2025-10-23T12-30-51.png
        └── form-success-2025-10-23T12-31-05.png
测试时,此Skill会在用户工作目录中创建以下结构:
user-repo/
└── .web-tests/
    ├── scripts/          # 可复用的测试脚本
    │   ├── test-login.js
    │   ├── test-form.js
    │   ├── test-responsive.js
    │   └── test-broken-links.js
    └── screenshots/      # 带时间戳的截图
        ├── desktop-2025-10-23T12-30-45.png
        ├── mobile-2025-10-23T12-30-51.png
        └── form-success-2025-10-23T12-31-05.png

Tips

技巧提示

  • CRITICAL: Detect servers FIRST - Always run
    detectDevServers()
    before writing test code for localhost testing
  • Save to .web-tests/ - Write scripts to
    .web-tests/scripts/
    , screenshots auto-save to
    .web-tests/screenshots/
  • Parameterize URLs - Put detected/provided URL in a
    TARGET_URL
    constant at the top of every script
  • DEFAULT: Visible browser - Always use
    headless: false
    unless user explicitly asks for headless mode
  • Headless mode - Only use
    headless: true
    when user specifically requests "headless" or "background" execution
  • Slow down: Use
    slowMo: 100
    to make actions visible and easier to follow
  • Wait strategies: Use
    waitForURL
    ,
    waitForSelector
    ,
    waitForLoadState
    instead of fixed timeouts
  • Error handling: Always use try-catch for robust automation
  • Console output: Use
    console.log()
    to track progress and show what's happening
  • Use helpers: The
    helpers.takeScreenshot()
    automatically saves to
    .web-tests/screenshots/
  • 关键:优先检测服务器 - 针对本地主机测试,编写测试代码前务必先运行
    detectDevServers()
  • 保存到.web-tests/目录 - 将脚本写入
    .web-tests/scripts/
    ,截图自动保存到
    .web-tests/screenshots/
  • 参数化URL - 在每个脚本顶部将检测到的/用户提供的URL放入
    TARGET_URL
    常量中
  • 默认使用可视化浏览器 - 除非用户明确要求,否则始终使用
    headless: false
  • 无头模式 - 仅当用户明确要求"无头"或"后台"执行时才使用
    headless: true
  • 放慢速度: 使用
    slowMo: 100
    让操作可见,便于跟踪
  • 等待策略: 使用
    waitForURL
    waitForSelector
    waitForLoadState
    替代固定超时
  • 错误处理: 始终使用try-catch实现健壮的自动化
  • 控制台输出: 使用
    console.log()
    跟踪进度,展示执行过程
  • 使用辅助函数:
    helpers.takeScreenshot()
    会自动将截图保存到
    .web-tests/screenshots/

Troubleshooting

故障排除

Playwright not installed:
bash
cd $SKILL_DIR && npm run setup
Module not found: Ensure running from skill directory via
run.js
wrapper with CWD set
Browser doesn't open: Check
headless: false
and ensure display available
Element not found: Add wait:
await page.waitForSelector('.element', { timeout: 10000 })
Screenshots not in .web-tests/: Make sure
CWD
environment variable is set when executing
Playwright未安装:
bash
cd $SKILL_DIR && npm run setup
模块未找到: 确保通过
run.js
包装器从Skill目录执行,并已设置CWD
浏览器未打开: 检查
headless: false
,并确保显示设备可用
元素未找到: 添加等待:
await page.waitForSelector('.element', { timeout: 10000 })
截图未保存到.web-tests/: 确保执行时已设置
CWD
环境变量

Example Usage

使用示例

User: "Test if the marketing page looks good"

Claude: I'll test the marketing page across multiple viewports. Let me first detect running servers...
[Runs: detectDevServers()]
[Output: Found server on port 3001]
I found your dev server running on http://localhost:3001

[Writes custom automation script to .web-tests/scripts/test-marketing.js with URL parameterized]
[Runs: CWD=$(pwd) cd $SKILL_DIR && node run.js .web-tests/scripts/test-marketing.js]
[Shows results with screenshots from .web-tests/screenshots/]
User: "Check if login redirects correctly"

Claude: I'll test the login flow. First, let me check for running servers...
[Runs: detectDevServers()]
[Output: Found servers on ports 3000 and 3001]
I found 2 dev servers. Which one should I test?
- http://localhost:3000
- http://localhost:3001

User: "Use 3001"

[Writes login automation to .web-tests/scripts/test-login.js]
[Runs: CWD=$(pwd) cd $SKILL_DIR && node run.js .web-tests/scripts/test-login.js]
[Reports: ✅ Login successful, redirected to /dashboard]
用户: "测试营销页面的显示效果"

Claude: 我将在多个视口中测试营销页面。先让我检测运行中的服务器...
[执行: detectDevServers()]
[输出: 找到端口3001上的服务器]
我找到你的开发服务器运行在 http://localhost:3001

[将自定义自动化脚本写入.web-tests/scripts/test-marketing.js,并参数化URL]
[执行: CWD=$(pwd) cd $SKILL_DIR && node run.js .web-tests/scripts/test-marketing.js]
[展示.web-tests/screenshots/中的截图结果]
用户: "检查登录是否正确重定向"

Claude: 我将测试登录流程。首先,让我检查运行中的服务器...
[执行: detectDevServers()]
[输出: 找到端口3000和3001上的服务器]
我找到2个开发服务器。你想测试哪一个?
- http://localhost:3000
- http://localhost:3001

用户: "使用3001"

[将登录自动化脚本写入.web-tests/scripts/test-login.js]
[执行: CWD=$(pwd) cd $SKILL_DIR && node run.js .web-tests/scripts/test-login.js]
[报告: ✅ 登录成功,已重定向到/dashboard]

Notes

注意事项

  • Each automation is custom-written for your specific request
  • Not limited to pre-built scripts - any browser task possible
  • Auto-detects running dev servers to eliminate hardcoded URLs
  • Test scripts saved to
    .web-tests/scripts/
    for reusability
  • Screenshots automatically saved to
    .web-tests/screenshots/
    with timestamps
  • Code executes reliably with proper module resolution via
    run.js
  • Works as global tool - no per-repo installation needed
  • 每个自动化任务均为你的特定需求定制
  • 不限于预构建脚本 - 可实现任何浏览器自动化任务
  • 自动检测运行中的开发服务器,无需硬编码URL
  • 测试脚本保存到
    .web-tests/scripts/
    以便复用
  • 截图自动保存到
    .web-tests/screenshots/
    并带有时间戳
  • 通过
    run.js
    确保代码可靠执行,解决模块解析问题
  • 作为全局工具使用 - 无需每个仓库单独安装",