Files
xamxam/app/tests/Unit/DatabaseTest.php
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

85 lines
2.8 KiB
PHP

<?php
/**
* Database Connection Test
* Tests basic database connectivity and query functionality
*/
// Must be set before Database.php is required so getDatabasePath() picks it up.
putenv('DB_ENV=test');
require_once __DIR__ . '/../../src/Database.php';
echo "Database Connection Test\n";
echo "========================\n\n";
try {
// Test 1: Database connection
echo "Test 1: Database Connection\n";
$db = Database::getInstance();
echo "✓ PASS: Database connection successful\n\n";
// Test 2: Count published theses
echo "Test 2: Count Published Theses\n";
$count = $db->countPublishedTheses();
if ($count >= 0) {
echo "✓ PASS: Found {$count} published theses\n\n";
} else {
throw new Exception('Invalid count returned');
}
// Test 3: Get published theses
echo "Test 3: Get Published Theses\n";
$theses = $db->getPublishedTheses(5, 0);
if (is_array($theses)) {
echo '✓ PASS: Retrieved ' . count($theses) . " theses\n\n";
} else {
throw new Exception('Invalid theses array returned');
}
// Test 4: Get single thesis (if any exist)
if (count($theses) > 0) {
echo "Test 4: Get Single Thesis\n";
$first = $theses[0];
$thesis = $db->getThesisById($first['id']);
if ($thesis && isset($thesis['id'])) {
echo "✓ PASS: Successfully retrieved thesis #{$first['id']}\n";
echo ' Title: ' . $thesis['title'] . "\n";
echo ' Author(s): ' . ($thesis['authors'] ?? 'N/A') . "\n";
echo ' Year: ' . $thesis['year'] . "\n\n";
} else {
throw new Exception('Failed to retrieve thesis by ID');
}
}
// Test 5: findOrCreateTag round-trip
echo "Test 5: findOrCreateTag round-trip\n";
$testTag = '__test_tag_' . bin2hex(random_bytes(4));
$id1 = $db->findOrCreateTag($testTag);
$id2 = $db->findOrCreateTag($testTag); // should return same id
if ($id1 && $id1 === $id2) {
echo "✓ PASS: findOrCreateTag returned consistent id=$id1 for '$testTag'\n\n";
// Clean up
$db->deleteTag($id1);
} else {
throw new Exception("findOrCreateTag round-trip failed: id1=$id1, id2=$id2");
}
// Test 6: getUsedTags returns array with 'name' column
echo "Test 6: getUsedTags returns name column\n";
$tags = $db->getUsedTags();
if (is_array($tags) && (empty($tags) || isset($tags[0]['name']))) {
echo '✓ PASS: getUsedTags returned ' . count($tags) . " tags with 'name' column\n\n";
} else {
throw new Exception('getUsedTags did not return expected structure: ' . json_encode($tags[0] ?? []));
}
echo "✅ All database tests passed!\n";
return true;
} catch (Exception $e) {
echo '❌ FAIL: ' . $e->getMessage() . "\n";
return false;
}