Files
Pontoporeia a2cba6d3c0 feat: prevent duplicate TFE submissions with logging and user feedback
- Add DuplicateThesisException (typed, carries existing thesis metadata)
- Add Database::findDuplicateThesis(): matches on year + author + normalised
  title (exact, prefix, Levenshtein ≤10% of longer string)
- ThesisCreateController::submit() runs duplicate check before any DB write
  and throws DuplicateThesisException on match
- AppLogger::logDuplicate() writes status=duplicate entries to the JSON-lines
  log for audit purposes
- App::flash/consumeFlash extended to support 'warning' flash type
- admin/actions/formulaire.php: catches DuplicateThesisException, logs it,
  flashes an HTML warning toast with a clickable link to the existing thesis,
  and repopulates the form fields
- partage/index.php: same catch block; surfaces a plain-text flash-warning
  banner on the student form with identifier, title, and year of the match;
  form is repopulated via session
- toast.php: renders toast--warning variant
- admin.css: .toast--warning + link colour rules
- form.css: .flash-warning style for the partage form
2026-05-05 11:04:52 +02:00
..

XAMXAM Test Suite

Centralized test suite for the XAMXAM thesis management system.

📁 Structure

tests/
├── run-tests.php           # Test runner (runs all tests)
├── Unit/                   # Unit tests
│   ├── DatabaseTest.php    # Database connection & queries
│   └── RateLimitTest.php   # Rate limiting functionality
├── Integration/            # Integration tests
│   └── SearchTest.php      # Search functionality
├── Security/               # Security tests
│   └── SecurityTest.php    # SQL injection & XSS protection
└── README.md              # This file

🚀 Running Tests

Run All Tests

# Using justfile (recommended)
just test

# Or directly
php tests/run-tests.php

Run Individual Tests

# Database test
php tests/Unit/DatabaseTest.php

# Search test
php tests/Integration/SearchTest.php

# Security test
php tests/Security/SecurityTest.php

# Rate limit test
php tests/Unit/RateLimitTest.php

Test Coverage

Unit Tests

DatabaseTest.php - Tests basic database operations:

  • Database connection
  • Count published theses
  • Get published theses
  • Get single thesis by ID

RateLimitTest.php - Tests rate limiting:

  • RateLimit initialization
  • check() method
  • sendHeaders() method
  • getResetTime() method
  • cleanup() method

Integration Tests

SearchTest.php - Tests search functionality:

  • Empty search query handling
  • Search for specific terms
  • Special characters in search

Security Tests

SecurityTest.php - Tests security measures:

  • SQL injection protection
  • Invalid ID rejection
  • XSS protection (output escaping)

📝 Writing New Tests

Test File Template

<?php
/**
 * Test Name
 * Description of what this tests
 */

require_once __DIR__ . '/../../lib/YourClass.php';

echo "Test Name\n";
echo "=========\n\n";

try {
    // Test 1
    echo "Test 1: Description\n";
    // ... test code ...
    echo "✓ PASS: Test passed\n\n";

    // Test 2
    echo "Test 2: Description\n";
    // ... test code ...
    echo "✓ PASS: Test passed\n\n";

    echo "✅ All tests passed!\n";
    return true;

} catch (Exception $e) {
    echo "❌ FAIL: " . $e->getMessage() . "\n";
    return false;
}

Guidelines

  1. Return Value: Return true for pass, false for fail
  2. Output Format: Use ✓ PASS: for successes, ❌ FAIL: for failures
  3. Exceptions: Catch and report exceptions clearly
  4. Dependencies: Require only what's needed via relative paths
  5. Location:
    • Unit/ - Tests for individual classes/functions
    • Integration/ - Tests for feature workflows
    • Security/ - Tests for security vulnerabilities

🔧 Test Database

Tests use the main database at storage/xamxam.db.

Setup Test Database

# Create from schema
just init-db

Reset Test Database

just reset-db

📊 Expected Output

Successful test run:

╔════════════════════════════════════════════╗
║         XAMXAM Test Suite                ║
╚════════════════════════════════════════════╝

┌─────────────────────────────────────────┐
│ Database (Unit)                         │
└─────────────────────────────────────────┘

✓ PASS: Database connection successful
✓ PASS: Found 16 published theses
...
✅ TEST PASSED

...

╔════════════════════════════════════════════╗
║              Test Summary                  ║
╠════════════════════════════════════════════╣
║ Total:   4                                 ║
║ Passed:  4 ✅                              ║
║ Failed:  0                                 ║
╚════════════════════════════════════════════╝

✅ All tests passed!

🐛 Debugging Failed Tests

Check Logs

# Application errors
tail -f error.log

# Test output
php tests/run-tests.php > test-output.txt 2>&1

Run Tests Individually

When a test fails, run it directly to see full output:

php tests/Unit/DatabaseTest.php

Check Database

# Open database
just query

# Check stats
just stats

🔄 Continuous Testing

Watch Mode (Future)

Could add file watching for auto-run:

# Future: auto-run tests on file change
just watch-tests

Pre-commit Hook (Future)

Add to .git/hooks/pre-commit:

#!/bin/bash
php tests/run-tests.php

To run tests: just test