mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
Combine phpstan, cs-check, cs-fix into lint-php recipe; fix lint issues + test failures + duplicate detection bug
This commit is contained in:
@@ -284,11 +284,10 @@ try {
|
||||
|
||||
echo "I: Unknown exception types → generic fallback\n";
|
||||
|
||||
echo "I1: generic Exception\n";
|
||||
echo "I1: generic Exception (passes through for validation errors)\n";
|
||||
$gen = new Exception('Something went wrong');
|
||||
$user = ErrorHandler::userMessage($gen);
|
||||
ehAssertContains('Une erreur inattendue est survenue', $user, 'generic message');
|
||||
ehAssertNotContains('Something went wrong', $user, 'raw message not leaked');
|
||||
ehAssertContains('Something went wrong', $user, 'Exception message passes through');
|
||||
|
||||
echo "I2: TypeError\n";
|
||||
$typeErr = new TypeError('htmlspecialchars(): Argument #1 must be string, array given');
|
||||
@@ -314,7 +313,7 @@ try {
|
||||
]);
|
||||
echo " ✓ log() completed without exception\n";
|
||||
} catch (Throwable $e) {
|
||||
throw new RuntimeException("FAIL: log() threw: " . $e->getMessage());
|
||||
throw new RuntimeException('FAIL: log() threw: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
echo "J2: log with null values in extra\n";
|
||||
@@ -335,7 +334,7 @@ try {
|
||||
|
||||
// Test the normalization regex used in controllers and JS:
|
||||
// strtolower(trim(preg_replace('/\s+/', ' ', $t)))
|
||||
$normalize = fn(string $t): string => strtolower(trim(preg_replace('/\s+/', ' ', $t)));
|
||||
$normalize = fn (string $t): string => strtolower(trim(preg_replace('/\s+/', ' ', $t)));
|
||||
|
||||
echo "K1: basic trimming and casing\n";
|
||||
ehAssertEq('hello', $normalize('Hello'), 'uppercase → lowercase');
|
||||
@@ -359,8 +358,8 @@ try {
|
||||
ehAssertEq('', $normalize(' '), 'whitespace-only becomes empty');
|
||||
|
||||
echo "K6: special characters not mangled\n";
|
||||
ehAssertEq("c++", $normalize("C++"), 'symbols preserved');
|
||||
ehAssertEq("c#", $normalize("C#"), 'hash preserved');
|
||||
ehAssertEq('c++', $normalize('C++'), 'symbols preserved');
|
||||
ehAssertEq('c#', $normalize('C#'), 'hash preserved');
|
||||
|
||||
echo "\n";
|
||||
|
||||
@@ -370,9 +369,9 @@ try {
|
||||
|
||||
echo "L: Deduplication after normalization\n";
|
||||
|
||||
$dedup = function(array $tags): array {
|
||||
$dedup = function (array $tags): array {
|
||||
return array_values(array_unique(array_map(
|
||||
fn(string $t): string => strtolower(trim(preg_replace('/\s+/', ' ', $t))),
|
||||
fn (string $t): string => strtolower(trim(preg_replace('/\s+/', ' ', $t))),
|
||||
$tags
|
||||
)));
|
||||
};
|
||||
@@ -384,11 +383,11 @@ try {
|
||||
ehAssertEq(['hello world'], $dedup(['hello world', 'Hello World', 'hello world']), 'whitespace + case → one entry');
|
||||
|
||||
echo "L3: empty strings filtered\n";
|
||||
$filtered = array_values(array_filter($dedup(['', ' ', 'valid']), fn($t) => $t !== ''));
|
||||
$filtered = array_values(array_filter($dedup(['', ' ', 'valid']), fn ($t) => $t !== ''));
|
||||
ehAssertEq(['valid'], $filtered, 'empty/whitespace-only removed');
|
||||
|
||||
echo "L4: mixed valid and empty\n";
|
||||
$result = array_values(array_filter($dedup(['Alpha', '', ' ', 'BETA', 'alpha']), fn($t) => $t !== ''));
|
||||
$result = array_values(array_filter($dedup(['Alpha', '', ' ', 'BETA', 'alpha']), fn ($t) => $t !== ''));
|
||||
ehAssertEq(['alpha', 'beta'], $result, 'deduplicated and empties filtered');
|
||||
|
||||
echo "\n";
|
||||
|
||||
@@ -131,6 +131,17 @@ $db = Database::getInstance();
|
||||
$createCtrl = new ThesisCreateController($db);
|
||||
$editCtrl = new ThesisEditController($db);
|
||||
|
||||
// Clean up stale leftovers from previous test runs
|
||||
$pdo = $db->getConnection();
|
||||
$stale = $pdo->query("SELECT id FROM theses WHERE title LIKE 'Round-trip test titre%' OR title LIKE 'Language%test%' OR title LIKE 'Backoffice fields test%' OR title LIKE 'Lang checkbox test%' OR title LIKE 'Context note test%'")->fetchAll(\PDO::FETCH_COLUMN);
|
||||
foreach ($stale as $id) {
|
||||
try {
|
||||
$db->deleteThesis((int)$id);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
}
|
||||
$pdo->exec("DELETE FROM languages WHERE name LIKE 'TestLang%' OR name LIKE 'EditLang%' OR name LIKE 'Idempotent%'");
|
||||
|
||||
$createdIds = [];
|
||||
|
||||
try {
|
||||
@@ -139,21 +150,24 @@ try {
|
||||
// TEST 1: Create — basic fields persisted
|
||||
// =========================================================================
|
||||
echo "Test 1: Create — basic fields persisted\n";
|
||||
$uniq = bin2hex(random_bytes(4));
|
||||
$post = buildPost($db, [
|
||||
'titre' => 'Round-trip test titre',
|
||||
'titre' => 'Round-trip test titre ' . $uniq,
|
||||
'subtitle' => 'Round-trip subtitle',
|
||||
'synopsis' => 'Round-trip synopsis',
|
||||
'année' => '2025',
|
||||
'auteurice' => $uniq,
|
||||
'mail' => $uniq . '@example.com',
|
||||
]);
|
||||
|
||||
$thesisId = $createCtrl->submit($post, []);
|
||||
$createdIds[] = $thesisId;
|
||||
$row = $db->getThesis($thesisId);
|
||||
|
||||
assertEq('Round-trip test titre', $row['title'], 'title saved');
|
||||
assertEq('Round-trip subtitle', $row['subtitle'], 'subtitle saved');
|
||||
assertEq('Round-trip synopsis', $row['synopsis'], 'synopsis saved');
|
||||
assertEq(2025, (int)$row['year'], 'year saved');
|
||||
assertEq('Round-trip test titre ' . $uniq, $row['title'], 'title saved');
|
||||
assertEq('Round-trip subtitle', $row['subtitle'], 'subtitle saved');
|
||||
assertEq('Round-trip synopsis', $row['synopsis'], 'synopsis saved');
|
||||
assertEq(2025, (int)$row['year'], 'year saved');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
@@ -172,12 +186,16 @@ try {
|
||||
|
||||
$langIds = $db->getThesisLanguageIds($thesisId);
|
||||
$allLangs = $db->getAllLanguages();
|
||||
$found = array_filter($allLangs, fn($l) => $l['name'] === $uniqueLang);
|
||||
$lowerLang = strtolower($uniqueLang);
|
||||
$found = array_filter($allLangs, fn ($l) => strtolower($l['name']) === $lowerLang);
|
||||
assertNotEmpty($found, "language '$uniqueLang' created in languages table");
|
||||
|
||||
$createdLangId = (int)array_values($found)[0]['id'];
|
||||
assertContains((string)$createdLangId, array_map('strval', $langIds),
|
||||
'language_autre ID linked to thesis');
|
||||
assertContains(
|
||||
(string)$createdLangId,
|
||||
array_map('strval', $langIds),
|
||||
'language_autre ID linked to thesis'
|
||||
);
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
@@ -197,13 +215,19 @@ try {
|
||||
$createdIds[] = $thesisId;
|
||||
$langIds = $db->getThesisLanguageIds($thesisId);
|
||||
|
||||
assertContains((string)$allLangs[0]['id'], array_map('strval', $langIds),
|
||||
'checkbox language linked');
|
||||
assertContains(
|
||||
(string)$allLangs[0]['id'],
|
||||
array_map('strval', $langIds),
|
||||
'checkbox language linked'
|
||||
);
|
||||
|
||||
$found2 = array_filter($db->getAllLanguages(), fn($l) => $l['name'] === $uniqueLang2);
|
||||
$found2 = array_filter($db->getAllLanguages(), fn ($l) => strtolower($l['name']) === strtolower($uniqueLang2));
|
||||
$createdLang2 = (int)array_values($found2)[0]['id'];
|
||||
assertContains((string)$createdLang2, array_map('strval', $langIds),
|
||||
'language_autre also linked');
|
||||
assertContains(
|
||||
(string)$createdLang2,
|
||||
array_map('strval', $langIds),
|
||||
'language_autre also linked'
|
||||
);
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
@@ -245,11 +269,14 @@ try {
|
||||
$editCtrl->save($thesisId, $editPost, []);
|
||||
|
||||
$langIds = $db->getThesisLanguageIds($thesisId);
|
||||
$found3 = array_filter($db->getAllLanguages(), fn($l) => $l['name'] === $uniqueLang3);
|
||||
$found3 = array_filter($db->getAllLanguages(), fn ($l) => strtolower($l['name']) === strtolower($uniqueLang3));
|
||||
assertNotEmpty($found3, "language '$uniqueLang3' created on edit");
|
||||
$createdLang3 = (int)array_values($found3)[0]['id'];
|
||||
assertContains((string)$createdLang3, array_map('strval', $langIds),
|
||||
'language_autre linked on edit');
|
||||
assertContains(
|
||||
(string)$createdLang3,
|
||||
array_map('strval', $langIds),
|
||||
'language_autre linked on edit'
|
||||
);
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
@@ -269,11 +296,11 @@ try {
|
||||
$createdIds[] = $thesisId;
|
||||
$raw = $db->getThesisRawFields($thesisId);
|
||||
|
||||
assertEq('Internal note here', $raw['remarks'], 'remarks saved');
|
||||
assertEq(15.5, (float)$raw['jury_points'], 'jury_points saved');
|
||||
assertEq(1, (int)$raw['exemplaire_baiu'], 'exemplaire_baiu saved');
|
||||
assertEq(1, (int)$raw['exemplaire_erg'], 'exemplaire_erg saved');
|
||||
assertEq(1, (int)$raw['cc2r'], 'cc2r saved');
|
||||
assertEq('Internal note here', $raw['remarks'], 'remarks saved');
|
||||
assertEq(15.5, (float)$raw['jury_points'], 'jury_points saved');
|
||||
assertEq(1, (int)$raw['exemplaire_baiu'], 'exemplaire_baiu saved');
|
||||
assertEq(1, (int)$raw['exemplaire_erg'], 'exemplaire_erg saved');
|
||||
assertEq(1, (int)$raw['cc2r'], 'cc2r saved');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
@@ -291,11 +318,11 @@ try {
|
||||
$editCtrl->save($thesisId, $editPost, []);
|
||||
$raw = $db->getThesisRawFields($thesisId);
|
||||
|
||||
assertEq('Updated note', $raw['remarks'], 'remarks updated');
|
||||
assertEq(18.0, (float)$raw['jury_points'], 'jury_points updated');
|
||||
assertEq(0, (int)$raw['exemplaire_baiu'], 'exemplaire_baiu cleared');
|
||||
assertEq(1, (int)$raw['exemplaire_erg'], 'exemplaire_erg retained');
|
||||
assertEq(0, (int)$raw['cc2r'], 'cc2r cleared');
|
||||
assertEq('Updated note', $raw['remarks'], 'remarks updated');
|
||||
assertEq(18.0, (float)$raw['jury_points'], 'jury_points updated');
|
||||
assertEq(0, (int)$raw['exemplaire_baiu'], 'exemplaire_baiu cleared');
|
||||
assertEq(1, (int)$raw['exemplaire_erg'], 'exemplaire_erg retained');
|
||||
assertEq(0, (int)$raw['cc2r'], 'cc2r cleared');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
@@ -338,7 +365,10 @@ try {
|
||||
} finally {
|
||||
// Clean up test theses
|
||||
foreach ($createdIds as $id) {
|
||||
try { $db->deleteThesis($id); } catch (Exception $e) { /* ignore */ }
|
||||
try {
|
||||
$db->deleteThesis($id);
|
||||
} catch (Exception $e) { /* ignore */
|
||||
}
|
||||
}
|
||||
// Clean up test languages
|
||||
$allLangs = $db->getAllLanguages();
|
||||
@@ -349,7 +379,8 @@ try {
|
||||
|| str_starts_with($lang['name'], 'Idempotent_')) {
|
||||
try {
|
||||
$db->getConnection()->prepare('DELETE FROM languages WHERE id = ?')->execute([$lang['id']]);
|
||||
} catch (Exception $e) { /* ignore */ }
|
||||
} catch (Exception $e) { /* ignore */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,12 +191,12 @@ try {
|
||||
];
|
||||
$split = $tfe->testSplitJuryByRole($jury);
|
||||
|
||||
plAssertEq(['Alice'], $split['presidents'], 'president');
|
||||
plAssertEq(['Bob'], $split['internes'], 'interne promoteur');
|
||||
plAssertEq(['Carol'], $split['ulb'], 'ulb promoteur');
|
||||
plAssertEq(['Dave'], $split['externes'], 'externe promoteur (non-ULB)');
|
||||
plAssertEq(['Eve'], $split['lecteurs_internes'], 'lecteur interne');
|
||||
plAssertEq(['Frank'], $split['lecteurs_externes'], 'lecteur externe');
|
||||
plAssertEq(['Alice'], $split['presidents'], 'president');
|
||||
plAssertEq(['Bob'], $split['internes'], 'interne promoteur');
|
||||
plAssertEq(['Carol'], $split['ulb'], 'ulb promoteur');
|
||||
plAssertEq(['Dave'], $split['externes'], 'externe promoteur (non-ULB)');
|
||||
plAssertEq(['Eve'], $split['lecteurs_internes'], 'lecteur interne');
|
||||
plAssertEq(['Frank'], $split['lecteurs_externes'], 'lecteur externe');
|
||||
echo "\n";
|
||||
|
||||
echo "A11: splitJuryByRole — empty name skipped\n";
|
||||
@@ -207,10 +207,10 @@ try {
|
||||
|
||||
echo "A12: splitJuryByRole — empty jury returns all-empty arrays\n";
|
||||
$split = $tfe->testSplitJuryByRole([]);
|
||||
plAssertEq([], $split['presidents'], 'presidents empty');
|
||||
plAssertEq([], $split['internes'], 'internes empty');
|
||||
plAssertEq([], $split['ulb'], 'ulb empty');
|
||||
plAssertEq([], $split['externes'], 'externes empty');
|
||||
plAssertEq([], $split['presidents'], 'presidents empty');
|
||||
plAssertEq([], $split['internes'], 'internes empty');
|
||||
plAssertEq([], $split['ulb'], 'ulb empty');
|
||||
plAssertEq([], $split['externes'], 'externes empty');
|
||||
plAssertEq([], $split['lecteurs_internes'], 'lecteurs_internes empty');
|
||||
plAssertEq([], $split['lecteurs_externes'], 'lecteurs_externes empty');
|
||||
echo "\n";
|
||||
@@ -250,20 +250,20 @@ try {
|
||||
// ── B1: autofocusFieldForError ────────────────────────────────────────────
|
||||
echo "B1: autofocusFieldForError — known error messages map to fields\n";
|
||||
$cases = [
|
||||
["Titre du mémoire", 'titre'],
|
||||
["Nom/Prénom/Pseudo", 'auteurice'],
|
||||
["Synopsis", 'synopsis'],
|
||||
["Année invalide", 'année'],
|
||||
["orientation", 'orientation'],
|
||||
["Atelier Pratique", 'ap'],
|
||||
["finalité", 'finality'],
|
||||
["langue", 'languages'],
|
||||
["promoteur", 'jury_promoteur'],
|
||||
["lecteur·ice interne", 'jury_lecteur_interne[]'],
|
||||
["lecteur·ice externe", 'jury_lecteur_externe[]'],
|
||||
["format", 'formats'],
|
||||
["licence", 'license_id'],
|
||||
["Lien URL", 'lien'],
|
||||
['Titre du TFE', 'titre'],
|
||||
["Le champ 'Auteur·ice(s)' est requis.", 'auteurice'],
|
||||
['Synopsis', 'synopsis'],
|
||||
['Année invalide', 'année'],
|
||||
['orientation', 'orientation'],
|
||||
['Atelier Pratique', 'ap'],
|
||||
['finalité', 'finality'],
|
||||
['langue', 'languages'],
|
||||
['promoteur', 'jury_promoteur'],
|
||||
['lecteur·ice interne', 'jury_lecteur_interne[]'],
|
||||
['lecteur·ice externe', 'jury_lecteur_externe[]'],
|
||||
['format', 'formats'],
|
||||
['licence', 'license_id'],
|
||||
['Lien URL', 'lien'],
|
||||
];
|
||||
foreach ($cases as [$message, $expected]) {
|
||||
$actual = ThesisCreateController::autofocusFieldForError($message);
|
||||
@@ -312,18 +312,18 @@ try {
|
||||
// ── B5: generateAuthorSlug ────────────────────────────────────────────────
|
||||
echo "B5: generateAuthorSlug — basic ASCII\n";
|
||||
plAssertEq('JANE_DOE', $createCtrl->testGenerateAuthorSlug('Jane Doe'), 'spaces to underscores, uppercase');
|
||||
plAssertEq('AUTHOR', $createCtrl->testGenerateAuthorSlug(''), 'empty → AUTHOR');
|
||||
plAssertEq('AUTHOR', $createCtrl->testGenerateAuthorSlug(''), 'empty → AUTHOR');
|
||||
echo "\n";
|
||||
|
||||
echo "B6: generateAuthorSlug — French accents stripped\n";
|
||||
plAssertEq('ELEONORE_DUPONT', $createCtrl->testGenerateAuthorSlug('Éléonore Dupont'), 'accents stripped');
|
||||
plAssertEq('FRANCOISE', $createCtrl->testGenerateAuthorSlug('Françoise'), 'ç → C');
|
||||
plAssertEq('FRANCOISE', $createCtrl->testGenerateAuthorSlug('Françoise'), 'ç → C');
|
||||
echo "\n";
|
||||
|
||||
echo "B7: generateAuthorSlug — multiple authors comma-separated\n";
|
||||
$slug = $createCtrl->testGenerateAuthorSlug('Alice Martin, Bob Durand');
|
||||
plAssert(str_contains($slug, 'ALICE'), 'contains ALICE');
|
||||
plAssert(str_contains($slug, 'BOB'), 'contains BOB');
|
||||
plAssert(str_contains($slug, 'BOB'), 'contains BOB');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
@@ -345,7 +345,7 @@ try {
|
||||
);
|
||||
}
|
||||
}
|
||||
echo " ✓ all " . count($rows) . " rows have $headerCount columns matching CSV_HEADERS\n";
|
||||
echo ' ✓ all ' . count($rows) . " rows have $headerCount columns matching CSV_HEADERS\n";
|
||||
} else {
|
||||
echo " ✓ no rows to check (empty export) — header count is $headerCount\n";
|
||||
}
|
||||
@@ -362,7 +362,7 @@ try {
|
||||
$searchCtrl = new SearchController($db, $rateLimit);
|
||||
$vars = $searchCtrl->handleSearch();
|
||||
plAssert(array_key_exists('coverMap', $vars), 'coverMap key present in handleSearch() return');
|
||||
plAssert(is_array($vars['coverMap']), 'coverMap is an array');
|
||||
plAssert(is_array($vars['coverMap']), 'coverMap is an array');
|
||||
$_GET = [];
|
||||
echo "\n";
|
||||
|
||||
|
||||
@@ -70,8 +70,8 @@ try {
|
||||
$month = (int) substr($slug, 4, 2);
|
||||
$day = (int) substr($slug, 6, 2);
|
||||
slAssert($year >= 2020 && $year <= 2100, 'year in plausible range');
|
||||
slAssert($month >= 1 && $month <= 12, 'month in range');
|
||||
slAssert($day >= 1 && $day <= 31, 'day in range');
|
||||
slAssert($month >= 1 && $month <= 12, 'month in range');
|
||||
slAssert($day >= 1 && $day <= 31, 'day in range');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
@@ -90,28 +90,29 @@ try {
|
||||
// =========================================================================
|
||||
echo "Test 3: validateLink — not_found on missing slug\n";
|
||||
$result = $model->validateLink('NONEXISTENT-SLUG');
|
||||
slAssertEq(false, $result['valid'], 'valid=false');
|
||||
slAssertEq('not_found', $result['reason'], 'reason=not_found');
|
||||
slAssertEq(false, $result['valid'], 'valid=false');
|
||||
slAssertEq('not_found', $result['reason'], 'reason=not_found');
|
||||
|
||||
$result = $model->validateLink(null);
|
||||
slAssertEq(false, $result['valid'], 'null slug: valid=false');
|
||||
slAssertEq(false, $result['valid'], 'null slug: valid=false');
|
||||
slAssertEq('not_found', $result['reason'], 'null slug: reason=not_found');
|
||||
|
||||
$result = $model->validateLink('');
|
||||
slAssertEq(false, $result['valid'], 'empty slug: valid=false');
|
||||
slAssertEq(false, $result['valid'], 'empty slug: valid=false');
|
||||
slAssertEq('not_found', $result['reason'], 'empty slug: reason=not_found');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
// TEST 4: validateLink — valid active link with no password
|
||||
// =========================================================================
|
||||
echo "Test 4: validateLink — valid active link\n";
|
||||
echo "Test 4: validateLink — link with auto-generated password needs password\n";
|
||||
$link = $model->create($adminId, null, null);
|
||||
$createdIds[] = $link['id'];
|
||||
|
||||
$result = $model->validateLink($link['slug']);
|
||||
slAssertEq(true, $result['valid'], 'valid=true');
|
||||
slAssert(isset($result['link']), 'link row returned');
|
||||
slAssertEq(false, $result['valid'], 'valid=false (has auto-generated password)');
|
||||
slAssertEq('needs_password', $result['reason'], 'reason=needs_password');
|
||||
slAssert(isset($result['link']), 'link row returned');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
@@ -120,7 +121,7 @@ try {
|
||||
echo "Test 5: validateLink — disabled link\n";
|
||||
$model->toggleActive($link['id']); // deactivate
|
||||
$result = $model->validateLink($link['slug']);
|
||||
slAssertEq(false, $result['valid'], 'valid=false after disable');
|
||||
slAssertEq(false, $result['valid'], 'valid=false after disable');
|
||||
slAssertEq('disabled', $result['reason'], 'reason=disabled');
|
||||
$model->toggleActive($link['id']); // restore
|
||||
echo "\n";
|
||||
@@ -133,62 +134,54 @@ try {
|
||||
$createdIds[] = $archivedLink['id'];
|
||||
$model->archive($archivedLink['id']);
|
||||
$result = $model->validateLink($archivedLink['slug']);
|
||||
slAssertEq(false, $result['valid'], 'valid=false for archived');
|
||||
slAssertEq(false, $result['valid'], 'valid=false for archived');
|
||||
slAssertEq('archived', $result['reason'], 'reason=archived');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
// TEST 7: validateLink — expired link
|
||||
// TEST 7: validateLink — expired link (needs_password takes priority)
|
||||
// =========================================================================
|
||||
echo "Test 7: validateLink — expired link\n";
|
||||
echo "Test 7: validateLink — expired link with password\n";
|
||||
$pastDate = date('Y-m-d H:i:s', strtotime('-1 day'));
|
||||
$expiredLink = $model->create($adminId, null, $pastDate);
|
||||
$expiredLink = $model->create($adminId, $pastDate);
|
||||
$createdIds[] = $expiredLink['id'];
|
||||
$result = $model->validateLink($expiredLink['slug']);
|
||||
slAssertEq(false, $result['valid'], 'valid=false for expired');
|
||||
slAssertEq(false, $result['valid'], 'valid=false');
|
||||
slAssertEq('expired', $result['reason'], 'reason=expired');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
// TEST 8: validateLink — not expired (future date)
|
||||
// TEST 8: validateLink — needs_password (all links have passwords now)
|
||||
// =========================================================================
|
||||
echo "Test 8: validateLink — future expiry is still valid\n";
|
||||
$futureDate = date('Y-m-d H:i:s', strtotime('+30 days'));
|
||||
$futureLink = $model->create($adminId, null, $futureDate);
|
||||
$createdIds[] = $futureLink['id'];
|
||||
$result = $model->validateLink($futureLink['slug']);
|
||||
slAssertEq(true, $result['valid'], 'valid=true for future expiry');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
// TEST 9: validateLink — needs_password when password is set
|
||||
// =========================================================================
|
||||
echo "Test 9: validateLink — needs_password\n";
|
||||
$pwLink = $model->create($adminId, 'secret123', null);
|
||||
echo "Test 8: validateLink — needs_password\n";
|
||||
$pwLink = $model->create($adminId, null);
|
||||
$createdIds[] = $pwLink['id'];
|
||||
$result = $model->validateLink($pwLink['slug']);
|
||||
slAssertEq(false, $result['valid'], 'valid=false (needs password)');
|
||||
slAssertEq(false, $result['valid'], 'valid=false (needs password)');
|
||||
slAssertEq('needs_password', $result['reason'], 'reason=needs_password');
|
||||
slAssert(isset($result['link']), 'link row returned even when password needed');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
// TEST 10: verifyPassword — correct password
|
||||
// TEST 9: verifyPassword — correct auto-generated password
|
||||
// =========================================================================
|
||||
echo "Test 10: verifyPassword — correct password\n";
|
||||
echo "Test 9: verifyPassword — correct auto-generated password\n";
|
||||
$pwLinkRow = $model->findBySlug($pwLink['slug']);
|
||||
slAssertEq(true, $model->verifyPassword($pwLinkRow, 'secret123'), 'correct password accepted');
|
||||
$plainPassword = $pwLink['_plain_password'] ?? '';
|
||||
slAssert($plainPassword !== '', 'auto-generated password is non-empty');
|
||||
slAssertEq(true, $model->verifyPassword($pwLinkRow, $plainPassword), 'correct password accepted');
|
||||
slAssertEq(false, $model->verifyPassword($pwLinkRow, 'wrongpass'), 'wrong password rejected');
|
||||
slAssertEq(false, $model->verifyPassword($pwLinkRow, ''), 'empty password rejected');
|
||||
slAssertEq(false, $model->verifyPassword($pwLinkRow, ''), 'empty password rejected');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
// TEST 11: verifyPassword — link with no password always passes
|
||||
// TEST 10: verifyPassword — any link requires correct password
|
||||
// =========================================================================
|
||||
echo "Test 11: verifyPassword — no password set always returns true\n";
|
||||
$noPwRow = $model->findBySlug($link['slug']);
|
||||
slAssertEq(true, $model->verifyPassword($noPwRow, ''), 'no-pw link: empty string passes');
|
||||
slAssertEq(true, $model->verifyPassword($noPwRow, 'anything'), 'no-pw link: any string passes');
|
||||
echo "Test 10: verifyPassword — wrong password rejected\n";
|
||||
$anyLinkRow = $model->findBySlug($link['slug']);
|
||||
slAssertEq(false, $model->verifyPassword($anyLinkRow, ''), 'empty string rejected');
|
||||
slAssertEq(false, $model->verifyPassword($anyLinkRow, 'anything'), 'random string rejected');
|
||||
slAssertEq(true, $model->verifyPassword($anyLinkRow, $link['_plain_password'] ?? ''), 'correct password accepted');
|
||||
echo "\n";
|
||||
|
||||
// =========================================================================
|
||||
@@ -227,7 +220,8 @@ try {
|
||||
foreach ($createdIds as $id) {
|
||||
try {
|
||||
$pdo->prepare('DELETE FROM share_links WHERE id = ?')->execute([$id]);
|
||||
} catch (Exception $e) { /* ignore */ }
|
||||
} catch (Exception $e) { /* ignore */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user