Skip to content

fix(security): prevent open redirect in auth flow, update SECURITY.md #241

fix(security): prevent open redirect in auth flow, update SECURITY.md

fix(security): prevent open redirect in auth flow, update SECURITY.md #241

Workflow file for this run

name: E2E Tests
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
workflow_dispatch:
jobs:
e2e:
name: E2E Tests
runs-on: ubuntu-latest
timeout-minutes: 60
continue-on-error: true # Allow CI to pass even if E2E tests fail
strategy:
fail-fast: false
matrix:
# Start with just Chromium to save resources
# Uncomment others once tests are passing
browser: [chromium]
# browser: [chromium, firefox, webkit]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set repository name
id: repo
run: echo "name=${GITHUB_REPOSITORY##*/}" >> $GITHUB_OUTPUT
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10.16.1
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Install Playwright browsers
run: pnpm exec playwright install --with-deps ${{ matrix.browser }}
- name: Build application
run: pnpm build
env:
# Don't use GitHub base path for E2E tests - build for local testing
GITHUB_ACTIONS: false
NEXT_PUBLIC_EMAILJS_PUBLIC_KEY: ${{ secrets.EMAILJS_PUBLIC_KEY }}
NEXT_PUBLIC_EMAILJS_SERVICE_ID: ${{ vars.NEXT_PUBLIC_EMAILJS_SERVICE_ID }}
NEXT_PUBLIC_EMAILJS_TEMPLATE_ID: ${{ vars.NEXT_PUBLIC_EMAILJS_TEMPLATE_ID }}
# Supabase credentials for app build
NEXT_PUBLIC_SUPABASE_URL: ${{ vars.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ vars.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
- name: Debug - Check build output
run: |
echo "=== Build output structure ==="
ls -la out/
echo "=== Checking index.html ==="
head -20 out/index.html
- name: Start server
run: |
# Serve static files from out directory at root (no SPA mode for Next.js static export)
npx serve out -l 3000 &
sleep 5
npx wait-on http://localhost:3000 --timeout 60000
env:
CI: true
- name: Debug - Check served content
run: |
echo "=== Checking homepage ==="
curl -s http://localhost:3000 | grep -o '<title>[^<]*</title>' || echo "No title found"
echo "=== Checking for progress badge ==="
curl -s http://localhost:3000 | grep -o 'badge.*badge-success' || echo "No progress badge found"
echo "=== Checking for ScriptHammer text ==="
curl -s http://localhost:3000 | grep -o 'ScriptHammer' | head -5 || echo "No ScriptHammer text found"
# Run rate-limiting tests FIRST (clean IP quota)
# These use project dependencies for ordering
- name: Run rate-limiting tests (ordered)
run: pnpm test:e2e --project=rate-limiting --project=brute-force --project=signup --reporter=list --trace=on-first-retry
env:
CI: true
PLAYWRIGHT_BROWSER: chromium
SKIP_WEBSERVER: true
BASE_URL: http://localhost:3000
# Supabase credentials
NEXT_PUBLIC_SUPABASE_URL: ${{ vars.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ vars.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }}
# Test users
TEST_USER_PRIMARY_EMAIL: ${{ vars.TEST_USER_PRIMARY_EMAIL }}
TEST_USER_PRIMARY_PASSWORD: ${{ secrets.TEST_USER_PRIMARY_PASSWORD }}
TEST_USER_SECONDARY_EMAIL: ${{ vars.TEST_USER_SECONDARY_EMAIL }}
TEST_USER_SECONDARY_PASSWORD: ${{ secrets.TEST_USER_SECONDARY_PASSWORD }}
TEST_USER_TERTIARY_EMAIL: ${{ vars.TEST_USER_TERTIARY_EMAIL }}
TEST_USER_TERTIARY_PASSWORD: ${{ secrets.TEST_USER_TERTIARY_PASSWORD }}
# Then run remaining tests in parallel (rate-limiting tests excluded via testIgnore)
- name: Run E2E tests - ${{ matrix.browser }}
run: pnpm test:e2e --project=${{ matrix.browser }} --reporter=list --trace=on-first-retry
env:
CI: true
PLAYWRIGHT_BROWSER: ${{ matrix.browser }}
SKIP_WEBSERVER: true
BASE_URL: http://localhost:3000
DEBUG: pw:api
# Supabase credentials
NEXT_PUBLIC_SUPABASE_URL: ${{ vars.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ vars.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }}
# Primary test user
TEST_USER_PRIMARY_EMAIL: ${{ vars.TEST_USER_PRIMARY_EMAIL }}
TEST_USER_PRIMARY_PASSWORD: ${{ secrets.TEST_USER_PRIMARY_PASSWORD }}
# Secondary test user (multi-user tests)
TEST_USER_SECONDARY_EMAIL: ${{ vars.TEST_USER_SECONDARY_EMAIL }}
TEST_USER_SECONDARY_PASSWORD: ${{ secrets.TEST_USER_SECONDARY_PASSWORD }}
# Tertiary test user (group chat/friend tests)
TEST_USER_TERTIARY_EMAIL: ${{ vars.TEST_USER_TERTIARY_EMAIL }}
TEST_USER_TERTIARY_PASSWORD: ${{ secrets.TEST_USER_TERTIARY_PASSWORD }}
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-results-${{ matrix.browser }}
path: test-results/
retention-days: 7
- name: Upload playwright report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report-${{ matrix.browser }}
path: playwright-report/
retention-days: 7
e2e-report:
name: E2E Test Report
runs-on: ubuntu-latest
needs: e2e
if: always()
steps:
- name: Download all test results
uses: actions/download-artifact@v4
with:
pattern: playwright-results-*
merge-multiple: true
- name: Download all reports
uses: actions/download-artifact@v4
with:
pattern: playwright-report-*
merge-multiple: true
- name: Generate summary
run: |
echo "## E2E Test Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Browser Coverage" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Chromium" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Firefox" >> $GITHUB_STEP_SUMMARY
echo "- ✅ WebKit (Safari)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "View detailed reports in the workflow artifacts." >> $GITHUB_STEP_SUMMARY