Initial commit
This commit is contained in:
430
skills/web-tests/SKILL.md
Normal file
430
skills/web-tests/SKILL.md
Normal file
@@ -0,0 +1,430 @@
|
||||
---
|
||||
name: web-tests
|
||||
description: Complete browser automation with Playwright. **ALWAYS use when user needs browser testing, E2E testing, screenshots, form testing, or responsive design validation.** Auto-detects dev servers, saves test scripts to working directory. Examples - "test this page", "take screenshots of responsive design", "test login flow", "check for broken links", "validate form submission".
|
||||
---
|
||||
|
||||
**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`
|
||||
|
||||
# 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
|
||||
|
||||
## 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/`
|
||||
|
||||
## Setup (First Time)
|
||||
|
||||
```bash
|
||||
cd $SKILL_DIR
|
||||
npm run setup
|
||||
```
|
||||
|
||||
This installs Playwright and Chromium browser. Only needed once.
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## 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();
|
||||
})();
|
||||
```
|
||||
|
||||
### 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();
|
||||
})();
|
||||
```
|
||||
|
||||
### 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();
|
||||
})();
|
||||
```
|
||||
|
||||
### 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();
|
||||
})();
|
||||
```
|
||||
|
||||
### 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();
|
||||
}
|
||||
})();
|
||||
```
|
||||
|
||||
### 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();
|
||||
})();
|
||||
```
|
||||
|
||||
## Inline Execution (Simple Tasks)
|
||||
|
||||
For quick one-off tasks, you can execute code inline without creating files:
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
## 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.
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## 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/`
|
||||
|
||||
## 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
|
||||
|
||||
## 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]
|
||||
```
|
||||
|
||||
## 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
|
||||
26
skills/web-tests/package.json
Normal file
26
skills/web-tests/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "ui-tests",
|
||||
"version": "1.0.0",
|
||||
"description": "Web testing and browser automation with Playwright for Claude Code",
|
||||
"author": "Claude Craftkit",
|
||||
"main": "run.js",
|
||||
"scripts": {
|
||||
"setup": "npm install && npx playwright install chromium",
|
||||
"install-all-browsers": "npx playwright install chromium firefox webkit"
|
||||
},
|
||||
"keywords": [
|
||||
"ui-tests",
|
||||
"playwright",
|
||||
"automation",
|
||||
"browser-testing",
|
||||
"web-automation",
|
||||
"claude-skill"
|
||||
],
|
||||
"dependencies": {
|
||||
"playwright": "^1.56.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
217
skills/web-tests/run.js
Executable file
217
skills/web-tests/run.js
Executable file
@@ -0,0 +1,217 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Universal Playwright Executor for Claude Code
|
||||
*
|
||||
* Executes Playwright automation code from:
|
||||
* - File path: node run.js script.js
|
||||
* - Inline code: node run.js 'await page.goto("...")'
|
||||
* - Stdin: cat script.js | node run.js
|
||||
*
|
||||
* Ensures proper module resolution by running from skill directory.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
// Change to skill directory for proper module resolution
|
||||
process.chdir(__dirname);
|
||||
|
||||
/**
|
||||
* Check if Playwright is installed
|
||||
*/
|
||||
function checkPlaywrightInstalled() {
|
||||
try {
|
||||
require.resolve('playwright');
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install Playwright if missing
|
||||
*/
|
||||
function installPlaywright() {
|
||||
console.log('📦 Playwright not found. Installing...');
|
||||
try {
|
||||
execSync('npm install', { stdio: 'inherit', cwd: __dirname });
|
||||
execSync('npx playwright install chromium', { stdio: 'inherit', cwd: __dirname });
|
||||
console.log('✅ Playwright installed successfully');
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error('❌ Failed to install Playwright:', e.message);
|
||||
console.error('Please run manually: cd', __dirname, '&& npm run setup');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get code to execute from various sources
|
||||
*/
|
||||
function getCodeToExecute() {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
// Case 1: File path provided
|
||||
if (args.length > 0 && fs.existsSync(args[0])) {
|
||||
const filePath = path.resolve(args[0]);
|
||||
console.log(`📄 Executing file: ${filePath}`);
|
||||
return fs.readFileSync(filePath, 'utf8');
|
||||
}
|
||||
|
||||
// Case 2: Inline code provided as argument
|
||||
if (args.length > 0) {
|
||||
console.log('⚡ Executing inline code');
|
||||
return args.join(' ');
|
||||
}
|
||||
|
||||
// Case 3: Code from stdin
|
||||
if (!process.stdin.isTTY) {
|
||||
console.log('📥 Reading from stdin');
|
||||
return fs.readFileSync(0, 'utf8');
|
||||
}
|
||||
|
||||
// No input
|
||||
console.error('❌ No code to execute');
|
||||
console.error('Usage:');
|
||||
console.error(' node run.js script.js # Execute file');
|
||||
console.error(' node run.js "code here" # Execute inline');
|
||||
console.error(' cat script.js | node run.js # Execute from stdin');
|
||||
console.error('');
|
||||
console.error('Environment Variables:');
|
||||
console.error(' CWD=/path/to/repo node run.js script.js # Set working directory for outputs');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up old temporary execution files from previous runs
|
||||
*/
|
||||
function cleanupOldTempFiles() {
|
||||
try {
|
||||
const files = fs.readdirSync(__dirname);
|
||||
const tempFiles = files.filter(f => f.startsWith('.temp-execution-') && f.endsWith('.js'));
|
||||
|
||||
if (tempFiles.length > 0) {
|
||||
tempFiles.forEach(file => {
|
||||
const filePath = path.join(__dirname, file);
|
||||
try {
|
||||
fs.unlinkSync(filePath);
|
||||
} catch (e) {
|
||||
// Ignore errors - file might be in use or already deleted
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore directory read errors
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap code in async IIFE if not already wrapped
|
||||
*/
|
||||
function wrapCodeIfNeeded(code) {
|
||||
// Check if code already has require() and async structure
|
||||
const hasRequire = code.includes('require(');
|
||||
const hasAsyncIIFE = code.includes('(async () => {') || code.includes('(async()=>{');
|
||||
|
||||
// If it's already a complete script, return as-is
|
||||
if (hasRequire && hasAsyncIIFE) {
|
||||
return code;
|
||||
}
|
||||
|
||||
// If it's just Playwright commands, wrap in full template
|
||||
if (!hasRequire) {
|
||||
return `
|
||||
const { chromium, firefox, webkit, devices } = require('playwright');
|
||||
const helpers = require('./lib/helpers');
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
${code}
|
||||
} catch (error) {
|
||||
console.error('❌ Automation error:', error.message);
|
||||
if (error.stack) {
|
||||
console.error(error.stack);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
})();
|
||||
`;
|
||||
}
|
||||
|
||||
// If has require but no async wrapper
|
||||
if (!hasAsyncIIFE) {
|
||||
return `
|
||||
(async () => {
|
||||
try {
|
||||
${code}
|
||||
} catch (error) {
|
||||
console.error('❌ Automation error:', error.message);
|
||||
if (error.stack) {
|
||||
console.error(error.stack);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
})();
|
||||
`;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main execution
|
||||
*/
|
||||
async function main() {
|
||||
console.log('🎭 Web Tests - Universal Executor\n');
|
||||
|
||||
// Show working directory info
|
||||
if (process.env.CWD) {
|
||||
console.log(`📁 Working directory: ${process.env.CWD}`);
|
||||
console.log(`📸 Screenshots will be saved to: ${process.env.CWD}/.web-tests/screenshots/\n`);
|
||||
}
|
||||
|
||||
// Clean up old temp files from previous runs
|
||||
cleanupOldTempFiles();
|
||||
|
||||
// Check Playwright installation
|
||||
if (!checkPlaywrightInstalled()) {
|
||||
const installed = installPlaywright();
|
||||
if (!installed) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Get code to execute
|
||||
const rawCode = getCodeToExecute();
|
||||
const code = wrapCodeIfNeeded(rawCode);
|
||||
|
||||
// Create temporary file for execution
|
||||
const tempFile = path.join(__dirname, `.temp-execution-${Date.now()}.js`);
|
||||
|
||||
try {
|
||||
// Write code to temp file
|
||||
fs.writeFileSync(tempFile, code, 'utf8');
|
||||
|
||||
// Execute the code
|
||||
console.log('🚀 Starting automation...\n');
|
||||
require(tempFile);
|
||||
|
||||
// Note: Temp file will be cleaned up on next run
|
||||
// This allows long-running async operations to complete safely
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Execution failed:', error.message);
|
||||
if (error.stack) {
|
||||
console.error('\n📋 Stack trace:');
|
||||
console.error(error.stack);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Run main function
|
||||
main().catch(error => {
|
||||
console.error('❌ Fatal error:', error.message);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user