shareLink = new ShareLink($db); $this->pdo = TestDatabase::getPDO(); } /** * Create a share link and return its row. */ private function createLink(?string $name = null, ?string $expiresAt = null, ?string $objetRestriction = null): array { $link = $this->shareLink->create(1, $expiresAt, $objetRestriction, $name); $this->assertNotNull($link); return $link; } // ── listActive / listArchived ───────────────────────────────────────────── public function testListActiveReturnsOnlyActiveLinks(): void { $this->createLink('Active One'); $active = $this->shareLink->listActive(); $this->assertCount(1, $active); // Archive the link $link = $this->shareLink->findBySlug($active[0]['slug']); $this->shareLink->archive($link['id']); $active = $this->shareLink->listActive(); $this->assertCount(0, $active); } public function testListArchivedReturnsOnlyArchivedLinks(): void { $this->createLink('To Archive'); $archived = $this->shareLink->listArchived(); $this->assertCount(0, $archived); $link = $this->shareLink->findBySlug($this->shareLink->listActive()[0]['slug']); $this->shareLink->archive($link['id']); $archived = $this->shareLink->listArchived(); $this->assertCount(1, $archived); } // ── findBySlug ──────────────────────────────────────────────────────────── public function testFindBySlugHit(): void { $created = $this->createLink('Find Me'); $found = $this->shareLink->findBySlug($created['slug']); $this->assertNotNull($found); $this->assertSame($created['id'], $found['id']); $this->assertSame('Find Me', $found['name']); } public function testFindBySlugMiss(): void { $found = $this->shareLink->findBySlug('nonexistent-slug'); $this->assertNull($found); } // ── setPassword + getDecryptedPassword round-trip ───────────────────────── public function testSetPasswordAndDecryptRoundTrip(): void { $created = $this->createLink('Password Test'); // getDecryptedPassword uses encrypted_password from the DB, not _plain_password $decrypted = $this->shareLink->getDecryptedPassword($created['id']); $this->assertNotEmpty($decrypted); } public function testGetDecryptedPasswordOnNonexistentId(): void { $result = $this->shareLink->getDecryptedPassword(999); $this->assertSame('', $result); } // ── update ──────────────────────────────────────────────────────────────── public function testUpdateChangesNameAndExpiration(): void { $created = $this->createLink('Original Name'); $this->shareLink->update($created['id'], 'Updated Name', '2099-12-31 23:59:59'); $updated = $this->shareLink->findBySlug($created['slug']); $this->assertSame('Updated Name', $updated['name']); $this->assertNotNull($updated['expires_at']); } public function testUpdateOnlyNameLeavesExpirationUnchanged(): void { $created = $this->createLink('Original', '2099-12-31 23:59:59'); $this->shareLink->update($created['id'], 'Only Name Changed', null); $updated = $this->shareLink->findBySlug($created['slug']); $this->assertSame('Only Name Changed', $updated['name']); $this->assertNotNull($updated['expires_at']); } public function testUpdateClearsExpiration(): void { $created = $this->createLink('Expiry Test', '2099-12-31 23:59:59'); // Pass empty string to clear $this->shareLink->update($created['id'], null, ''); $updated = $this->shareLink->findBySlug($created['slug']); $this->assertNull($updated['expires_at']); } // ── locked_year ─────────────────────────────────────────────────────────── public function testCreateWithLockedYear(): void { $created = $this->shareLink->create(1, null, null, 'Locked Year Link', 2025); $found = $this->shareLink->findBySlug($created['slug']); $this->assertSame(2025, $found['locked_year']); } public function testCreateWithInvalidLockedYearRejected(): void { $created = $this->shareLink->create(1, null, null, 'Bad Year Link', 1800); $found = $this->shareLink->findBySlug($created['slug']); $this->assertNull($found['locked_year']); } public function testUpdateLockedYear(): void { $created = $this->createLink('Year Upd'); $this->shareLink->update($created['id'], null, null, '2026'); $updated = $this->shareLink->findBySlug($created['slug']); $this->assertSame(2026, $updated['locked_year']); } public function testUpdateClearLockedYear(): void { $created = $this->shareLink->create(1, null, null, 'Year Clear', 2025); // Empty string clears $this->shareLink->update($created['id'], null, null, ''); $updated = $this->shareLink->findBySlug($created['slug']); $this->assertNull($updated['locked_year']); } // ── incrementUsage ──────────────────────────────────────────────────────── public function testIncrementUsage(): void { $created = $this->createLink('Usage Test'); $found = $this->shareLink->findBySlug($created['slug']); $this->assertSame(0, (int)$found['usage_count']); $this->shareLink->incrementUsage($created['id']); $this->shareLink->incrementUsage($created['id']); $found = $this->shareLink->findBySlug($created['slug']); $this->assertSame(2, (int)$found['usage_count']); } // ── Objet restriction validation ────────────────────────────────────────── public function testCreateDefaultsToTfeWhenInvalidObjet(): void { $created = $this->shareLink->create(1, null, 'invalid_objet', 'Invalid Objet'); $found = $this->shareLink->findBySlug($created['slug']); $this->assertSame('tfe', $found['objet_restriction']); } public function testCreateAcceptsValidObjet(): void { $created = $this->shareLink->create(1, null, 'thèse,frart', 'Multi Objet'); $found = $this->shareLink->findBySlug($created['slug']); $this->assertSame('thèse,frart', $found['objet_restriction']); } }