8cc0dcb167
- Moved 4 skills: browser-testing, claude-multimedia, exa-search, gravl-research - Moved 14 agents: architect, backend-dev, browser-tester, coach, data, flight, frontend-dev, gravl-pm, gravl-researcher, nutritionist, research, reviewer, staging, update - Created symlinks from ~/clawd/skills and ~/clawd/agents back to hub - Single source of truth in claude-agents-skills repo
288 lines
6.8 KiB
Markdown
288 lines
6.8 KiB
Markdown
# Browser Testing Skill
|
|
|
|
Automatisk webbtestning med headless Chrome för Gravl och andra projekt.
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
# Installera Playwright (enklast)
|
|
npm install -g playwright
|
|
npx playwright install chromium
|
|
|
|
# Eller Puppeteer
|
|
npm install -g puppeteer
|
|
|
|
# Eller direkt Chrome
|
|
which chromium-browser || which google-chrome || which chromium
|
|
```
|
|
|
|
## Snabbstart
|
|
|
|
### 1. Skärmdump för visuell regression
|
|
|
|
```javascript
|
|
const { chromium } = require('playwright');
|
|
|
|
(async () => {
|
|
const browser = await chromium.launch({ headless: true });
|
|
const page = await browser.newPage();
|
|
|
|
await page.goto('https://03-design-polish.gravl.homelab.local');
|
|
await page.screenshot({ path: 'gravl-landing.png', fullPage: true });
|
|
|
|
await browser.close();
|
|
})();
|
|
```
|
|
|
|
### 2. Interaktivt test (login-flöde)
|
|
|
|
```javascript
|
|
const { chromium } = require('playwright');
|
|
|
|
(async () => {
|
|
const browser = await chromium.launch({ headless: true });
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
|
|
// Gå till login
|
|
await page.goto('https://03-design-polish.gravl.homelab.local/login');
|
|
|
|
// Fyll i formulär
|
|
await page.fill('[data-testid="email"]', 'test@example.com');
|
|
await page.fill('[data-testid="password"]', 'test123');
|
|
|
|
// Klicka login
|
|
await page.click('[data-testid="login-button"]');
|
|
|
|
// Vänta på redirect
|
|
await page.waitForURL('**/dashboard');
|
|
|
|
// Verifiera
|
|
const welcomeText = await page.textContent('[data-testid="welcome-message"]');
|
|
console.log('Login test:', welcomeText.includes('Välkommen') ? '✅ PASS' : '❌ FAIL');
|
|
|
|
await browser.close();
|
|
})();
|
|
```
|
|
|
|
## Gravl-specifika tester
|
|
|
|
### Test Suite: Login/Onboarding (Phase 3)
|
|
|
|
```javascript
|
|
// tests/gravl-phase3.spec.js
|
|
const { test, expect } = require('@playwright/test');
|
|
|
|
test.describe('Gravl Phase 3 - Login/Onboarding', () => {
|
|
const BASE_URL = process.env.STAGING_URL || 'https://03-design-polish.gravl.homelab.local';
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto(BASE_URL);
|
|
});
|
|
|
|
test('visar logotyp', async ({ page }) => {
|
|
const logo = await page.locator('[data-testid="logo"]').isVisible();
|
|
expect(logo).toBeTruthy();
|
|
});
|
|
|
|
test('login-form finns', async ({ page }) => {
|
|
await expect(page.locator('form')).toBeVisible();
|
|
await expect(page.locator('input[type="email"]')).toBeVisible();
|
|
await expect(page.locator('input[type="password"]')).toBeVisible();
|
|
});
|
|
|
|
test('gradient animationer', async ({ page }) => {
|
|
const body = await page.locator('body');
|
|
const bg = await body.evaluate(el =>
|
|
getComputedStyle(el).background
|
|
);
|
|
expect(bg).toContain('gradient');
|
|
});
|
|
});
|
|
```
|
|
|
|
### Test Suite: Dashboard (Phase 3)
|
|
|
|
```javascript
|
|
test.describe('Gravl Phase 3 - Dashboard', () => {
|
|
test('stat cards visas', async ({ page }) => {
|
|
await page.goto(process.env.STAGING_URL + '/dashboard');
|
|
const cards = await page.locator('[data-testid="stat-card"]').count();
|
|
expect(cards).toBeGreaterThan(0);
|
|
});
|
|
|
|
test('kalender komponent', async ({ page }) => {
|
|
const calendar = await page.locator('[data-testid="calendar"]').isVisible();
|
|
expect(calendar).toBeTruthy();
|
|
});
|
|
});
|
|
```
|
|
|
|
### Test Suite: Workout Page (Phase 3)
|
|
|
|
```javascript
|
|
test.describe('Gravl Phase 3 - Workout', () => {
|
|
test('exercise cards med animationer', async ({ page }) => {
|
|
await page.goto(process.env.STAGING_URL + '/workout');
|
|
const cards = await page.locator('.exercise-card');
|
|
await expect(cards.first()).toHaveClass(/animate/);
|
|
});
|
|
|
|
test('rest timer finns', async ({ page }) => {
|
|
const timer = await page.locator('[data-testid="rest-timer"]').isVisible();
|
|
expect(timer).toBeTruthy();
|
|
});
|
|
|
|
test('KLART button styling', async ({ page }) => {
|
|
const button = page.locator('[data-testid="complete-workout"]');
|
|
await expect(button).toHaveCSS('background-color', 'rgb(255, 107, 53)');
|
|
});
|
|
});
|
|
```
|
|
|
|
## Automatisk staging-test
|
|
|
|
### Skript för PM
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# /workspace/gravl/scripts/test-staging.sh
|
|
|
|
BRANCH_NAME=$1
|
|
echo "🧪 Testar staging för $BRANCH_NAME"
|
|
|
|
export STAGING_URL="https://$BRANCH_NAME.gravl.homelab.local"
|
|
|
|
# Kör Playwright-tester
|
|
cd /workspace/gravl/frontend
|
|
npx playwright test tests/gravl-phase3.spec.js --reporter=json
|
|
|
|
# Om tester failar → rapportera till PM
|
|
if [ $? -ne 0 ]; then
|
|
echo "❌ Tester failade"
|
|
exit 1
|
|
fi
|
|
|
|
echo "✅ Alla tester passerade"
|
|
```
|
|
|
|
## PM Workflow med browser-test
|
|
|
|
### Steg 1: Efter staging skapats
|
|
|
|
```bash
|
|
# PM spawnar test-agent
|
|
sessions_spawn:
|
|
agentId: browser-tester
|
|
task: "Testa https://03-design-polish.gravl.homelab.local.
|
|
Använd Playwright.
|
|
Kolla: login-form, logotyp, animationer, rest-timer.
|
|
Rapportera pass/fail för varje test."
|
|
```
|
|
|
|
### Steg 2: Test-agenten kör
|
|
|
|
```bash
|
|
exec pty:true workdir:/workspace/gravl \
|
|
command:"npx playwright test --reporter=html"
|
|
```
|
|
|
|
### Steg 3: Rapportera resultat
|
|
|
|
```
|
|
🧪 Browser Test Results
|
|
|
|
✅ Login page (3/3)
|
|
- Logotyp visible
|
|
- Form validation
|
|
- Gradient animations
|
|
|
|
✅ Dashboard (2/2)
|
|
- Stat cards
|
|
- Calendar component
|
|
|
|
✅ Workout (3/3)
|
|
- Exercise cards
|
|
- Rest timer
|
|
- KLART button
|
|
|
|
📊 Screenshot: test-results/screenshots/
|
|
📄 Report: test-results/report.html
|
|
|
|
Alla Phase 3-tester passerade! ✅
|
|
```
|
|
|
|
## Headless Chrome direkt
|
|
|
|
### Utan Playwright (bara Chrome)
|
|
|
|
```bash
|
|
# Skärmdump
|
|
chromium --headless --disable-gpu --screenshot=gravl.png \
|
|
--window-size=1920,1080 \
|
|
https://03-design-polish.gravl.homelab.local
|
|
|
|
# PDF-export
|
|
chromium --headless --disable-gpu --print-to-pdf=gravl.pdf \
|
|
https://03-design-polish.gravl.homelab.local
|
|
|
|
# HTML-innehåll
|
|
chromium --headless --disable-gpu --dump-dom \
|
|
https://03-design-polish.gravl.homelab.local > gravl.html
|
|
```
|
|
|
|
## Skill-definition (för OpenClaw)
|
|
|
|
```yaml
|
|
name: browser-testing
|
|
version: 1.0.0
|
|
commands:
|
|
capture:
|
|
exec: "chromium --headless --screenshot={output} {url}"
|
|
test:
|
|
exec: "npx playwright test {spec} --reporter={format}"
|
|
interactive:
|
|
exec: "npx playwright open {url}"
|
|
env:
|
|
CHROME_BIN: /usr/bin/chromium
|
|
PLAYWRIGHT_BROWSERS_PATH: 0
|
|
```
|
|
|
|
## Installation i Gravl
|
|
|
|
```bash
|
|
cd /workspace/gravl
|
|
npm init -y
|
|
npm install --save-dev @playwright/test
|
|
npx playwright install chromium
|
|
|
|
# Skapa test-mapp
|
|
mkdir -p tests
|
|
mkdir -p test-results/screenshots
|
|
```
|
|
|
|
## Integrering med PM
|
|
|
|
```javascript
|
|
// I gravl-pm/SOUL.md
|
|
|
|
## Browser Testing
|
|
|
|
Efter varje staging-creation:
|
|
|
|
1. Skärmdump för visuell validering
|
|
2. Kärnflödestest (login -> dashboard)
|
|
3. Rapportera till Josef med screenshots
|
|
|
|
Använd alltid:
|
|
- exec pty:true för Playwright
|
|
- Spara screenshots i .staging/{branch}/screenshots/
|
|
- Vid fail → rapportera med screenshot
|
|
```
|
|
|
|
## Resurser
|
|
|
|
- [Playwright Docs](https://playwright.dev/)
|
|
- [Headless Chrome](https://developer.chrome.com/docs/chromium/headless)
|
|
- [Testing Best Practices](https://playwright.dev/docs/best-practices)
|