Files

Selenium UI Tests for Tilbudgivern

Overview

This directory contains Selenium-based UI tests for the Tilbudgivern application. These tests simulate real user interactions with the browser to verify the complete user journey.

Test Files

1. carpenter_quote_test.py

Complete Carpenter Quote Creation Test

Tests the full user flow:

  • Navigate to application
  • Login
  • Create customer project
  • Enter geometry data (area, dimensions)
  • Select smart package
  • Review materials and labor
  • Generate quote
  • Verify realism (materials, prices, labor)
  • API validation

Test Coverage:

  • 10 comprehensive tests
  • Full user journey simulation
  • Screenshots at each step
  • Realism validation
  • API verification

2. stark_import_test.py

Stark Material Import Tests

Tests Stark CSV import functionality:

  • File upload
  • Data processing
  • Import history
  • API endpoints

Prerequisites

1. Python Requirements

pip install selenium requests

2. Chrome/Chromium Browser

# Ubuntu/Debian
sudo apt-get install chromium-browser

# Or use Google Chrome

3. ChromeDriver

ChromeDriver must match your Chrome version.

Option A: Auto-install (recommended)

pip install webdriver-manager

Option B: Manual download

  1. Check Chrome version: google-chrome --version
  2. Download matching ChromeDriver from: https://chromedriver.chromium.org/downloads
  3. Add to PATH or place in /usr/local/bin/

4. Running Servers

Both servers must be running:

# Terminal 1: Backend
cd backend
node unified-server.js

# Terminal 2: Frontend
cd frontend
npm start

Verify:

Running Tests

Quick Start

cd tests/selenium
./run_carpenter_tests.sh

Manual Run

cd tests/selenium
python3 carpenter_quote_test.py

Headless Mode

Edit test file and uncomment:

options.add_argument('--headless')

Test Results

Screenshots

Screenshots are saved to: tests/test-results/selenium-screenshots/

Example screenshots:

  • 01-homepage.png - Application homepage
  • 02-logged-in.png - After login
  • 03-project-flow.png - Project flow view
  • 04-customer-info.png - Customer information filled
  • 05-geometry.png - Geometry data entered
  • 06-package-selected.png - Smart package selected
  • 07-materials-labor.png - Materials and labor review
  • 08-final-review.png - Final review before quote
  • 08-quote-generated.png - Generated quote

Test Results JSON

Results saved to: tests/test-results/selenium-screenshots/test_results.json

Example structure:

{
  "customer": {
    "customer_name": "Test Tømrerkunde - 20251220-143000",
    "customer_email": "test@toemrer.dk",
    "customer_phone": "42 46 81 10",
    "project_description": "Ny terrasse 25 m² med douglasgran"
  },
  "geometry": {
    "area": "25",
    "length": "5",
    "width": "5"
  },
  "pricing": {
    "total_estimated": 45000.00,
    "prices_found": ["45.000 kr", "11.250 kr", ...]
  },
  "realism_check": {
    "passed": 7,
    "total": 7,
    "details": {
      "Customer name": true,
      "Materials (wood)": true,
      "Area (m²)": true,
      "Price (kr)": true,
      "Labor/hours": true,
      "VAT/Moms": true,
      "Company info": true
    }
  },
  "api_verification": {
    "project_id": 54,
    "status": "materials_pending",
    "area": "25.00",
    "materials": 5
  }
}

Test Configuration

Environment Variables

export BASE_URL=http://localhost:3000
export API_URL=http://localhost:4031

Timeouts

Default: 20 seconds for element waits Modify in test file:

cls.wait = WebDriverWait(cls.driver, 20)

Browser Options

Configured in setUpClass:

options.add_argument('--headless')  # Headless mode
options.add_argument('--window-size=1920,1080')  # Window size
options.add_argument('--no-sandbox')  # Linux compatibility

Troubleshooting

ChromeDriver Version Mismatch

Error: This version of ChromeDriver only supports Chrome version X

Solution: Update ChromeDriver to match Chrome version

Server Not Running

❌ Backend server not running on port 4031

Solution: Start backend server first

Element Not Found

selenium.common.exceptions.NoSuchElementException

Solution:

  • Increase wait timeout
  • Check element selector
  • Verify React has fully loaded

Login Failed

Solution:

  • Check credentials (default: admin/admin123)
  • Verify auth system is working
  • Check for captcha or rate limiting

Comparison: Selenium vs Playwright

Selenium Advantages

  • More mature, wider adoption
  • Better Python integration
  • More browser support options
  • Familiar to most testers

Playwright Advantages

  • Faster execution
  • Better auto-waiting
  • Native TypeScript support
  • Better screenshot/video capture
  • Multiple browser contexts

Recommendation

  • Use Selenium for: Python-heavy workflows, team familiarity
  • Use Playwright for: Modern async workflows, better debugging

Both are production-ready and well-maintained.

CI/CD Integration

GitHub Actions Example

name: Selenium UI Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:
      postgres:
        image: postgres:13
        env:
          POSTGRES_PASSWORD: postgres
    
    steps:
      - uses: actions/checkout@v2
      
      - name: Setup Python
        uses: actions/setup-python@v2
        with:
          python-version: '3.9'
      
      - name: Install Chrome
        run: |
          sudo apt-get update
          sudo apt-get install -y chromium-browser
      
      - name: Install dependencies
        run: |
          pip install selenium requests
      
      - name: Start servers
        run: |
          npm install
          npm run start:backend &
          npm run start:frontend &
          sleep 10
      
      - name: Run Selenium tests
        run: |
          cd tests/selenium
          python3 carpenter_quote_test.py
      
      - name: Upload screenshots
        if: always()
        uses: actions/upload-artifact@v2
        with:
          name: selenium-screenshots
          path: tests/test-results/selenium-screenshots/

Best Practices

  1. Always wait for elements

    element = self.wait.until(
        EC.presence_of_element_located((By.ID, 'element-id'))
    )
    
  2. Take screenshots on failures

    • Automatically done in tearDown
    • Manual: self.screenshot('step-name')
  3. Use descriptive test names

    def test_01_navigate_to_app(self):
    def test_02_login(self):
    
  4. Clean up test data

    • Use unique timestamps
    • Clean database after tests (optional)
  5. Handle dynamic content

    • Wait for React to load
    • Use explicit waits, not sleep()

Support

For issues or questions:

  1. Check screenshots in test-results/
  2. Review test output logs
  3. Verify servers are running
  4. Check browser console for errors

License

Part of Tilbudgivern project - see root LICENSE file.