# 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 ```bash pip install selenium requests ``` ### 2. Chrome/Chromium Browser ```bash # 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)** ```bash 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: ```bash # Terminal 1: Backend cd backend node unified-server.js # Terminal 2: Frontend cd frontend npm start ``` Verify: - Backend: http://localhost:4031/health - Frontend: http://localhost:3000 ## Running Tests ### Quick Start ```bash cd tests/selenium ./run_carpenter_tests.sh ``` ### Manual Run ```bash cd tests/selenium python3 carpenter_quote_test.py ``` ### Headless Mode Edit test file and uncomment: ```python 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: ```json { "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 ```bash export BASE_URL=http://localhost:3000 export API_URL=http://localhost:4031 ``` ### Timeouts Default: 20 seconds for element waits Modify in test file: ```python cls.wait = WebDriverWait(cls.driver, 20) ``` ### Browser Options Configured in `setUpClass`: ```python 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 ```yaml 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** ```python 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** ```python 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.