使用 Playwright 提供完整的瀏覽器自動化功能。自動偵測開發伺服器,並將乾淨的測試腳本寫入 /tmp。支援測試頁面、填寫表單、擷取螢幕截圖、檢查響應式設計、驗證 UX(使用者體驗)、測試登入流程、檢查連結,以及自動化執行任何瀏覽器任務。當使用者想要測試網站、自動化瀏覽器互動、驗證網頁功能或進行任何基於瀏覽器的測試時使用。
重要說明 - 路徑解析:
此 Skill 可能安裝於不同位置(外掛系統、手動安裝、全域或專案特定)。在執行任何命令之前,請根據載入此 SKILL.md 檔案的位置來確定 Skill 目錄,並在下方的所有命令中使用該路徑。請將 $SKILL_DIR 替換為實際找到的路徑。
常見的安裝路徑:
- 外掛系統:
~/.claude/plugins/marketplaces/playwright-skill/skills/playwright-skill - 手動全域安裝:
~/.claude/skills/playwright-skill - 專案特定安裝:
<project>/.claude/skills/playwright-skill
Playwright 瀏覽器自動化
通用型瀏覽器自動化 Skill。我會針對你要求的任何自動化任務撰寫自訂 Playwright 程式碼,並透過通用執行器來執行。
關鍵工作流程 - 請依序執行以下步驟:
-
自動偵測開發伺服器 - 進行 localhost 測試時,務必先執行伺服器偵測:
cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(servers => console.log(JSON.stringify(servers)))"- 若找到 1 個伺服器:自動使用該伺服器並通知使用者
- 若找到多個伺服器:詢問使用者要測試哪一個
- 若未找到伺服器:詢問 URL 或提供協助以啟動開發伺服器
-
將腳本寫入 /tmp - 切勿將測試檔案寫入 Skill 目錄;請一律使用
/tmp/playwright-test-*.js -
預設使用可見的瀏覽器 - 除非使用者特別要求無頭(headless)模式,否則請一律使用
headless: false -
參數化 URL - 務必在腳本頂端透過環境變數或常數讓 URL 可供設定
運作方式
- 你說明想要測試/自動化的內容
- 我自動偵測正在執行的開發伺服器(若是測試外部網站則詢問 URL)
- 我在
/tmp/playwright-test-*.js中撰寫自訂 Playwright 程式碼(不會弄亂你的專案) - 我透過以下命令執行:
cd $SKILL_DIR && node run.js /tmp/playwright-test-*.js - 實時顯示結果,並顯示瀏覽器視窗以便除錯
- 測試檔案會由作業系統自動清理,不留垃圾
安裝與設定(初次使用)
cd $SKILL_DIR
npm run setup
這會安裝 Playwright 和 Chromium 瀏覽器。只需執行一次。
執行模式
步驟 1:偵測開發伺服器(用於 localhost 測試)
cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(s => console.log(JSON.stringify(s)))"
步驟 2:將帶有 URL 參數的測試腳本寫入 /tmp
// /tmp/playwright-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: '/tmp/screenshot.png', fullPage: true });
console.log('📸 螢幕截圖已儲存至 /tmp/screenshot.png');
await browser.close();
})();
步驟 3:從 Skill 目錄執行
cd $SKILL_DIR && node run.js /tmp/playwright-test-page.js
常見用法範例
測試頁面(多種視埠尺寸)
// /tmp/playwright-test-responsive.js
const { chromium } = require('playwright');
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 page.screenshot({ path: '/tmp/desktop.png', fullPage: true });
// 行動裝置測試
await page.setViewportSize({ width: 375, height: 667 });
await page.screenshot({ path: '/tmp/mobile.png', fullPage: true });
await browser.close();
})();
測試登入流程
// /tmp/playwright-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();
})();
填寫並提交表單
// /tmp/playwright-test-form.js
const { chromium } = require('playwright');
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"]', 'Test message');
await page.click('button[type="submit"]');
// 驗證提交結果
await page.waitForSelector('.success-message');
console.log('✅ 表單已成功提交');
await browser.close();
})();
檢查失效連結(死連結)
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('http://localhost:3000');
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();
})();
擷取截圖(含錯誤處理)
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
await page.goto('http://localhost:3000', {
waitUntil: 'networkidle',
timeout: 10000,
});
await page.screenshot({
path: '/tmp/screenshot.png',
fullPage: true,
});
console.log('📸 螢幕截圖已儲存至 /tmp/screenshot.png');
} catch (error) {
console.error('❌ 錯誤:', error.message);
} finally {
await browser.close();
}
})();
測試響應式設計
// /tmp/playwright-test-responsive-full.js
const { chromium } = require('playwright');
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 page.screenshot({
path: `/tmp/${viewport.name.toLowerCase()}.png`,
fullPage: true,
});
}
console.log('✅ 所有視埠尺寸均已測試完成');
await browser.close();
})();
單行即時執行(簡單任務)
對於快速的單次任務,你可以直接在命令列執行程式碼,無需建立檔案:
# 快速擷取螢幕截圖
cd $SKILL_DIR && node run.js "
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('http://localhost:3001');
await page.screenshot({ path: '/tmp/quick-screenshot.png', fullPage: true });
console.log('Screenshot saved');
await browser.close();
"
何時使用單行即時執行 vs 建立檔案:
- 單行即時執行:快速單次任務(擷取截圖、檢查元素是否存在、取得頁面標題)
- 建立檔案:複雜測試、響應式設計檢查,以及任何使用者可能想要重複執行的內容
可用的 Helper 函式
lib/helpers.js 中提供的選用公用函式:
const helpers = require('./lib/helpers');
// 偵測正在執行的開發伺服器(關鍵 - 請優先使用此函式!)
const servers = await helpers.detectDevServers();
console.log('Found servers:', servers);
// 安全點擊(含重試機制)
await helpers.safeClick(page, 'button.submit', { retries: 3 });
// 安全輸入(含清除舊文字)
await helpers.safeType(page, '#username', 'testuser');
// 擷取帶有時間戳記的螢幕截圖
await helpers.takeScreenshot(page, 'test-result');
// 處理 Cookie 提示橫幅
await helpers.handleCookieBanner(page);
// 擷取表格資料
const data = await helpers.extractTableData(page, 'table.results');
請參閱 lib/helpers.js 查看完整列表。
自訂 HTTP 標頭
透過環境變數為所有 HTTP 請求設定自訂標頭。適用於:
- 識別傳送至你後端的自動化流量
- 取得適合 LLM 閱讀的回應(例如純文字錯誤頁面,而非帶樣式的 HTML)
- 全域新增身份驗證 Token
設定方式
單一標頭(常見用法):
PW_HEADER_NAME=X-Automated-By PW_HEADER_VALUE=playwright-skill \
cd $SKILL_DIR && node run.js /tmp/my-script.js
多個標頭(JSON 格式):
PW_EXTRA_HEADERS='{"X-Automated-By":"playwright-skill","X-Debug":"true"}' \
cd $SKILL_DIR && node run.js /tmp/my-script.js
運作原理
使用 helpers.createContext() 時會自動套用標頭:
const context = await helpers.createContext(browser);
const page = await context.newPage();
// 來自此頁面的所有請求都會包含你的自訂標頭
若腳本直接使用原生的 Playwright API,請使用注入的 getContextOptionsWithHeaders():
const context = await browser.newContext(
getContextOptionsWithHeaders({ viewport: { width: 1920, height: 1080 } }),
);
進階用法
如需完整的 Playwright API 文件,請參閱 API_REFERENCE.md:
- 選擇器與定位器(Selectors & Locators)的最佳實踐
- 網路攔截與 API 模擬(Mocking)
- 身份驗證與工作階段(Session)管理
- 視覺回歸測試(Visual regression testing)
- 行動裝置模擬
- 效能測試
- 除錯技巧
- CI/CD 整合
技巧與實用建議
- 關鍵:優先偵測伺服器 - 針對 localhost 測試撰寫測試程式碼前,務必先執行
detectDevServers() - 自訂標頭 - 使用
PW_HEADER_NAME/PW_HEADER_VALUE環境變數來標示傳送至後端的自動化流量 - 使用 /tmp 存放測試檔案 - 請寫入至
/tmp/playwright-test-*.js,切勿寫入 Skill 目錄或使用者的專案目錄 - 將 URL 參數化 - 在每個腳本頂端將偵測到或由使用者提供的 URL 設為
TARGET_URL常數 - 預設:顯示瀏覽器視窗 - 除非使用者明確要求無頭模式,否則一律使用
headless: false - 無頭模式 - 僅在使用者特別要求「無頭(headless)」或「背景執行」時才使用
headless: true - 放慢速度: 使用
slowMo: 100讓操作過程可視化,更容易追蹤 - 等待策略: 使用
waitForURL、waitForSelector、waitForLoadState代替固定的逾時等待時間 - 錯誤處理
<!-- truncated for translation batch; full body continues in source -->




