createMock(IRootFolder::class), $this->createMock(CalendarManager::class), new ToolExecutionPolicyService(), $this->createMock(ShareManager::class), $this->createMock(IUserManager::class), $this->createMock(ToolConfirmationService::class), ); $tools = []; foreach ($provider->getTools() as $tool) { $tools[$tool['name']] = $tool; } $this->assertArrayHasKey('nuqloud_files_list', $tools); $this->assertArrayHasKey('nuqloud_files_read', $tools); $this->assertArrayHasKey('nuqloud_files_write', $tools); $this->assertArrayHasKey('nuqloud_files_copy', $tools); $this->assertArrayHasKey('nuqloud_files_move', $tools); $this->assertArrayHasKey('nuqloud_files_delete', $tools); $this->assertArrayHasKey('nuqloud_files_shares_list', $tools); $this->assertArrayHasKey('nuqloud_files_share_create', $tools); $this->assertArrayHasKey('nuqloud_files_share_update', $tools); $this->assertArrayHasKey('nuqloud_files_share_delete', $tools); $this->assertArrayHasKey('nuqloud_calendar_events_list', $tools); $this->assertArrayHasKey('nuqloud_calendar_availability', $tools); $this->assertArrayHasKey('nuqloud_talk_create_conversation', $tools); $this->assertArrayHasKey('nuqloud_talk_invite_user', $tools); $this->assertArrayHasKey('nuqloud_talk_remove_user', $tools); $this->assertArrayHasKey('nuqloud_talk_set_user_role', $tools); $this->assertArrayHasKey('nuqloud_talk_update_room_settings', $tools); $this->assertSame([], $tools['nuqloud_files_list']['schema']['required']); $this->assertInstanceOf(\stdClass::class, $tools['nuqloud_calendar_list']['schema']['properties']); $this->assertTrue($tools['nuqloud_files_read']['policy']['read_only']); $this->assertFalse($tools['nuqloud_files_write']['policy']['read_only']); $this->assertFalse($tools['nuqloud_files_copy']['policy']['destructive']); $this->assertTrue($tools['nuqloud_files_delete']['policy']['destructive']); $this->assertFalse($tools['nuqloud_talk_create_conversation']['policy']['read_only']); $this->assertTrue($tools['nuqloud_talk_remove_user']['policy']['destructive']); $this->assertArrayNotHasKey('confirmation_id', $tools['nuqloud_talk_create_conversation']['schema']['properties']); $this->assertStringContainsString('NuQloud Files', $tools['nuqloud_files_list']['description']); $this->assertStringContainsString('NuQloud Talk', $tools['nuqloud_talk_create_conversation']['description']); $metadata = $provider->getToolMetadata(); $this->assertSame('NuQloud Files: List Files', $metadata['nuqloud_files_list']['label']); $this->assertSame('NuQloud Talk: Create Conversation', $metadata['nuqloud_talk_create_conversation']['label']); } public function testRefusesExecutionWithoutTrustedInvokingUser(): void { $provider = new NuQloudToolProvider( $this->createMock(IRootFolder::class), $this->createMock(CalendarManager::class), new ToolExecutionPolicyService(), $this->createMock(ShareManager::class), $this->createMock(IUserManager::class), $this->createMock(ToolConfirmationService::class), ); $this->expectException(\RuntimeException::class); $provider->executeTool('nuqloud_files_list', []); } public function testNormalizesTalkUserPrincipalForFiles(): void { $rootFolder = $this->createMock(IRootFolder::class); $userFolder = $this->createMock(Folder::class); $userFolder->method('getDirectoryListing')->willReturn([]); $rootFolder->expects($this->once())->method('getUserFolder')->with('crowetic')->willReturn($userFolder); $provider = new NuQloudToolProvider( $rootFolder, $this->createMock(CalendarManager::class), new ToolExecutionPolicyService(), $this->createMock(ShareManager::class), $this->createMock(IUserManager::class), $this->createMock(ToolConfirmationService::class), ); $provider->setInvocationContext(['user_id' => 'users/crowetic']); $result = $provider->executeTool('nuqloud_files_list', []); $this->assertFalse($result['isError']); } }