pdo = TestDatabase::getPDO(); $db = TestDatabase::getInstance(); $this->ctrl = new ThesisEditController($db); } // ── load() ─────────────────────────────────────────────────────────────── public function testLoadReturnsDataForKnownId(): void { [$authorId, $thesisId] = TestDatabase::seedBasicThesis('Load Test', 'Author Name', 2024); $data = $this->ctrl->load($thesisId); $this->assertIsArray($data); $this->assertArrayHasKey('thesis', $data); $this->assertSame('Load Test', $data['thesis']['title']); $this->assertArrayHasKey('orientations', $data); $this->assertArrayHasKey('formatTypes', $data); } public function testLoadThrowsOnUnknownId(): void { $this->expectException(RuntimeException::class); $this->expectExceptionMessage('TFE non trouvé'); $this->ctrl->load(9999); } public function testLoadThrowsOnInvalidId(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ID invalide'); $this->ctrl->load(0); } public function testLoadThrowsOnNegativeId(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ID invalide'); $this->ctrl->load(-5); } // ── collectJuryMembers (private, test via reflection) ───────────────────── private function collectJuryMembers(array $post): array { $ref = new ReflectionMethod(ThesisEditController::class, 'collectJuryMembers'); $ref->setAccessible(true); return $ref->invoke($this->ctrl, $post); } public function testCollectJuryMembersEmptyInput(): void { $members = $this->collectJuryMembers([]); $this->assertIsArray($members); $this->assertEmpty($members); } public function testCollectJuryMembersSinglePromoteur(): void { $post = ['jury_promoteur' => ['John Smith']]; $members = $this->collectJuryMembers($post); $this->assertCount(1, $members); $this->assertSame('promoteur', $members[0]['role']); $this->assertSame('John Smith', $members[0]['name']); $this->assertSame(0, $members[0]['is_external']); $this->assertSame(0, $members[0]['is_ulb']); } public function testCollectJuryMembersPromoteurUlb(): void { $post = ['jury_promoteur_ulb_name' => ['ULB Prof']]; $members = $this->collectJuryMembers($post); $this->assertCount(1, $members); $this->assertSame('promoteur', $members[0]['role']); $this->assertSame(1, $members[0]['is_external']); $this->assertSame(1, $members[0]['is_ulb']); } public function testCollectJuryMembersLecteurs(): void { $post = [ 'jury_lecteur_interne' => ['Int One', 'Int Two'], 'jury_lecteur_externe' => ['Ext One'], ]; $members = $this->collectJuryMembers($post); $this->assertCount(3, $members); $internes = array_filter($members, fn($m) => $m['is_external'] === 0 && $m['role'] === 'lecteur'); $externes = array_filter($members, fn($m) => $m['is_external'] === 1 && $m['role'] === 'lecteur'); $this->assertCount(2, $internes); $this->assertCount(1, $externes); } public function testCollectJuryMembersDeduplicatesEmptyStrings(): void { $post = [ 'jury_promoteur' => ['John', '', ' ', 'Jane'], ]; $members = $this->collectJuryMembers($post); $names = array_column($members, 'name'); $this->assertCount(2, $names); $this->assertContains('John', $names); $this->assertContains('Jane', $names); } public function testCollectJuryMembersScalarPromoteurAccepted(): void { // Accepts scalar instead of array for promoteur fields $post = ['jury_promoteur' => 'Single Promoter']; $members = $this->collectJuryMembers($post); $this->assertCount(1, $members); $this->assertSame('Single Promoter', $members[0]['name']); } // ── handleWebsiteUrl (private, test via reflection) ─────────────────────── private function invokeHandleWebsiteUrl(int $thesisId, array $post): void { $ref = new ReflectionMethod(ThesisEditController::class, 'handleWebsiteUrl'); $ref->setAccessible(true); $ref->invoke($this->ctrl, $thesisId, $post); } public function testHandleWebsiteUrlStoresValidUrl(): void { [$authorId, $thesisId] = TestDatabase::seedBasicThesis('Website Test', 'Author', 2024); $post = ['website_url' => 'https://example.com', 'website_label' => 'My Site']; $this->invokeHandleWebsiteUrl($thesisId, $post); $pdo = TestDatabase::getPDO(); $files = $pdo->query("SELECT * FROM thesis_files WHERE thesis_id = $thesisId AND file_type = 'website'")->fetchAll(); $this->assertCount(1, $files); $this->assertSame('https://example.com', $files[0]['file_path']); $this->assertSame('My Site', $files[0]['display_label']); } public function testHandleWebsiteUrlSkipsInvalidUrl(): void { [$authorId, $thesisId] = TestDatabase::seedBasicThesis('Bad URL Test', 'Author', 2024); $post = ['website_url' => 'not-a-url']; $this->invokeHandleWebsiteUrl($thesisId, $post); $pdo = TestDatabase::getPDO(); $count = $pdo->query("SELECT COUNT(*) FROM thesis_files WHERE thesis_id = $thesisId AND file_type = 'website'")->fetchColumn(); $this->assertSame(0, (int)$count); } public function testHandleWebsiteUrlSkipsEmptyUrl(): void { [$authorId, $thesisId] = TestDatabase::seedBasicThesis('Empty URL', 'Author', 2024); $post = ['website_url' => '']; $this->invokeHandleWebsiteUrl($thesisId, $post); $pdo = TestDatabase::getPDO(); $count = $pdo->query("SELECT COUNT(*) FROM thesis_files WHERE thesis_id = $thesisId AND file_type = 'website'")->fetchColumn(); $this->assertSame(0, (int)$count); } public function testHandleWebsiteUrlNormalisesHttp(): void { [$authorId, $thesisId] = TestDatabase::seedBasicThesis('HTTP URL Test', 'Author', 2024); $post = ['website_url' => 'https://example.com/path']; $this->invokeHandleWebsiteUrl($thesisId, $post); $pdo = TestDatabase::getPDO(); $file = $pdo->query("SELECT * FROM thesis_files WHERE thesis_id = $thesisId AND file_type = 'website'")->fetch(); $this->assertStringContainsString('example.com/path', $file['file_name']); } }