# Visual Verification Workflow

Run iterative Playwright verification for CSS and visual fixes. Creates test script, verifies issues, applies fixes, re-tests, and only commits when all tests pass.

## When to Use

**REQUIRED for any visual/CSS issue:**
- Text color issues (blue on blue, white on white, unreadable)
- Dark mode problems (both icons showing, wrong colors)
- Font rendering issues
- Layout/spacing/visibility problems
- Button styling issues
- Icon opacity/color problems
- Any CSS-related visual bug

## Workflow

### Step 1: Analyze Issue & Create Test

1. **Gather visual evidence** from user (screenshot, description)
2. **Identify affected elements** (selectors, classes, IDs)
3. **Create Playwright test script** in `tmp/verify-[issue].js`:

```javascript
const { chromium } = require('playwright');
const fs = require('fs');

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

  const results = { timestamp: new Date().toISOString(), tests: [] };

  // Navigate to affected page
  await page.goto('http://localhost:8000/forum/[page]');
  await page.waitForTimeout(2000);

  // TEST: Check computed style
  const element = page.locator('[selector]').first();
  const computedColor = await element.evaluate(el =>
    window.getComputedStyle(el).color
  );

  // Validate (example: check if white)
  const isWhite = computedColor === 'rgb(255, 255, 255)';

  console.log(`Color: ${computedColor} - ${isWhite ? '✅ PASS' : '❌ FAIL'}`);
  results.tests.push({
    name: 'Button text color',
    pass: isWhite,
    expected: 'rgb(255, 255, 255)',
    actual: computedColor
  });

  // Screenshot
  await element.screenshot({ path: 'tmp/test-before.png' });

  await browser.close();

  // Save results
  fs.writeFileSync('tmp/test-results.json', JSON.stringify(results, null, 2));

  // Exit with failure if any test failed
  const allPass = results.tests.every(t => t.pass);
  process.exit(allPass ? 0 : 1);
})();
```

### Step 2: Run Initial Verification (BEFORE Fix)

```bash
node tmp/verify-[issue].js
```

**Expected:** Tests should FAIL, confirming the reported issue exists.

**If tests PASS unexpectedly:**
- Issue may be browser cache
- Test may be checking wrong element
- Issue may be environment-specific
- Refine test or investigate further

### Step 3: Apply Fix

Based on test failures, apply CSS fix to SCSS files:

**Common fixes:**
```scss
// Force white text on primary buttons
.presszone-forum-btn--primary {
  color: #ffffff !important;
}

// Fix dark mode icon visibility
body.dark-mode .presszone-forum-icon-sun {
  display: none !important;
}

// Fix icon opacity
svg {
  opacity: 1;
  color: currentColor;
}
```

### Step 4: Build CSS

```bash
npm run build:css
```

### Step 5: Run Verification AGAIN (AFTER Fix)

```bash
node tmp/verify-[issue].js
```

**Expected:** All tests should now PASS.

### Step 6: If Tests Still Fail

**DO NOT COMMIT.** Instead:

1. **Revert changes:**
```bash
git checkout -- assets/css/
npm run build:css
```

2. **Analyze test output:**
- What CSS property is still wrong?
- Is there a specificity issue?
- Is dark mode selector not matching?

3. **Try different approach:**
- Use `!important` if specificity issue
- Use absolute selector instead of nested
- Check compiled CSS to see what's actually output

4. **Re-test:**
```bash
node tmp/verify-[issue].js
```

5. **Repeat until tests pass**

### Step 7: Only Commit When Tests Pass

```bash
# All tests MUST pass (exit code 0)
git add assets/css/ tmp/verify-[issue].js tmp/test-*.png
git commit -m "fix: [description] - verified with Playwright"
git push
```

## Test Script Template

Save as `tmp/verify-template.js`:

```javascript
const { chromium } = require('playwright');
const fs = require('fs');

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

  const results = { timestamp: new Date().toISOString(), tests: [] };
  let allPass = true;

  console.log('🧪 Running visual verification tests...\n');

  try {
    // ============================================================
    // TEST 1: [Description]
    // ============================================================
    console.log('TEST 1: [Test Name]');
    await page.goto('[URL]');
    await page.waitForTimeout(2000);

    const element = page.locator('[selector]');
    const value = await element.evaluate(el =>
      window.getComputedStyle(el).[property]
    );

    const pass = value === '[expected]';
    console.log(`  Expected: [expected]`);
    console.log(`  Actual: ${value}`);
    console.log(`  ${pass ? '✅ PASS' : '❌ FAIL'}\n`);

    results.tests.push({
      name: '[Test Name]',
      pass,
      expected: '[expected]',
      actual: value
    });

    allPass = allPass && pass;
    await element.screenshot({ path: 'tmp/test-[name].png' });

    // ============================================================
    // Add more tests as needed
    // ============================================================

  } catch (error) {
    console.error('❌ Test error:', error.message);
    results.error = error.message;
    allPass = false;
  } finally {
    await browser.close();
  }

  // Summary
  console.log('\n' + '='.repeat(60));
  console.log(`SUMMARY: ${results.tests.filter(t => t.pass).length}/${results.tests.length} tests passed`);
  console.log('='.repeat(60));

  results.tests.forEach(t => {
    console.log(`${t.pass ? '✅' : '❌'} ${t.name}`);
  });

  fs.writeFileSync('tmp/test-results.json', JSON.stringify(results, null, 2));
  console.log('\nResults saved to tmp/test-results.json');

  process.exit(allPass ? 0 : 1);
})();
```

## Common Test Patterns

### Check Text Color

```javascript
const color = await element.evaluate(el =>
  window.getComputedStyle(el).color
);
const isWhite = color === 'rgb(255, 255, 255)';
```

### Check Display Property

```javascript
const display = await element.evaluate(el =>
  window.getComputedStyle(el).display
);
const isVisible = display !== 'none';
```

### Check Opacity

```javascript
const opacity = await element.evaluate(el =>
  window.getComputedStyle(el).opacity
);
const isOpaque = opacity === '1';
```

### Check Background Color

```javascript
const bg = await element.evaluate(el =>
  window.getComputedStyle(el).backgroundColor
);
// RGB colors: rgb(31, 113, 221) for blue
```

### Parse RGB to Check Color Range

```javascript
const colorMatch = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
const isWhiteish = colorMatch &&
  parseInt(colorMatch[1]) > 240 &&
  parseInt(colorMatch[2]) > 240 &&
  parseInt(colorMatch[3]) > 240;
```

## Benefits

✅ **Eliminates false positives** - No more "looks fixed but isn't"
✅ **Catches specificity issues** - Tests actual computed styles
✅ **Provides proof** - Screenshots and JSON results
✅ **Prevents broken commits** - Only commit when tests pass
✅ **Fast iteration** - Quick feedback loop
✅ **Regression prevention** - Keep test for future verification

## Example Session

```bash
# 1. Create test
node tmp/verify-buttons.js
# ❌ FAIL: Sign up button color is rgb(31, 113, 221), expected rgb(255, 255, 255)

# 2. Apply fix to navbar.scss
# 3. Build
npm run build:css

# 4. Re-test
node tmp/verify-buttons.js
# ❌ FAIL: Still wrong color

# 5. Revert and try different approach
git checkout -- assets/css/
# Use !important flag instead

# 6. Build and test again
npm run build:css
node tmp/verify-buttons.js
# ✅ PASS: All 3 tests passed

# 7. Commit
git add assets/css/ tmp/verify-buttons.js
git commit -m "fix: button text colors - verified with Playwright"
git push
```

## Notes

- **Requires local dev server** running at localhost:8000
- Tests run in **non-headless mode** so you can see what's happening
- Screenshots saved to `tmp/test-*.png` for visual comparison
- Test results saved to `tmp/test-results.json` for analysis
- Exit code 0 = all pass, 1 = any fail (for CI/CD compatibility)

## When NOT to Use

- Non-visual bugs (logic errors, data issues)
- Backend-only changes
- Database schema changes
- Issues that can't be tested in browser

For those, use unit tests or manual testing instead.
