|  | 
| 9 | 9 | use WordPress\AiClient\AiClient; | 
| 10 | 10 | use WordPress\AiClient\Messages\DTO\MessagePart; | 
| 11 | 11 | use WordPress\AiClient\Messages\DTO\UserMessage; | 
|  | 12 | +use WordPress\AiClient\ProviderImplementations\OpenAi\OpenAiProvider; | 
| 12 | 13 | use WordPress\AiClient\Providers\Contracts\ProviderAvailabilityInterface; | 
| 13 | 14 | use WordPress\AiClient\Providers\Models\DTO\ModelConfig; | 
| 14 | 15 | use WordPress\AiClient\Providers\ProviderRegistry; | 
| @@ -246,6 +247,115 @@ public function testIsConfiguredReturnsFalseWhenProviderIsNotConfigured(): void | 
| 246 | 247 |         $this->assertFalse($result); | 
| 247 | 248 |     } | 
| 248 | 249 | 
 | 
|  | 250 | +    /** | 
|  | 251 | +     * Tests isConfigured method with provider ID string leverages default registry. | 
|  | 252 | +     */ | 
|  | 253 | +    public function testIsConfiguredWithProviderIdString(): void | 
|  | 254 | +    { | 
|  | 255 | +        // This test will use the actual default registry since we can't easily mock static methods | 
|  | 256 | +        // The default registry should have providers registered, so we test the delegation path | 
|  | 257 | +        $result = AiClient::isConfigured('openai'); | 
|  | 258 | + | 
|  | 259 | +        // The result will be false because no actual API keys are configured in tests, | 
|  | 260 | +        // but the important thing is that no exception is thrown and the registry delegation works | 
|  | 261 | +        $this->assertIsBool($result); | 
|  | 262 | +    } | 
|  | 263 | + | 
|  | 264 | +    /** | 
|  | 265 | +     * Tests isConfigured method with provider class name leverages default registry. | 
|  | 266 | +     */ | 
|  | 267 | +    public function testIsConfiguredWithProviderClassName(): void | 
|  | 268 | +    { | 
|  | 269 | +        // This test will use the actual default registry since we can't easily mock static methods | 
|  | 270 | +        // The default registry should have providers registered, so we test the delegation path | 
|  | 271 | +        $result = AiClient::isConfigured(OpenAiProvider::class); | 
|  | 272 | + | 
|  | 273 | +        // The result will be false because no actual API keys are configured in tests, | 
|  | 274 | +        // but the important thing is that no exception is thrown and the registry delegation works | 
|  | 275 | +        $this->assertIsBool($result); | 
|  | 276 | +    } | 
|  | 277 | + | 
|  | 278 | +    /** | 
|  | 279 | +     * Tests isConfigured method throws exception for invalid parameter types. | 
|  | 280 | +     */ | 
|  | 281 | +    public function testIsConfiguredThrowsExceptionForInvalidParameterTypes(): void | 
|  | 282 | +    { | 
|  | 283 | +        $this->expectException(\InvalidArgumentException::class); | 
|  | 284 | +        $this->expectExceptionMessage( | 
|  | 285 | +            'Parameter must be a ProviderAvailabilityInterface instance, provider ID string, or provider class name. ' . | 
|  | 286 | +            'Received: integer' | 
|  | 287 | +        ); | 
|  | 288 | + | 
|  | 289 | +        AiClient::isConfigured(123); | 
|  | 290 | +    } | 
|  | 291 | + | 
|  | 292 | +    /** | 
|  | 293 | +     * Data provider for invalid isConfigured parameter types. | 
|  | 294 | +     * | 
|  | 295 | +     * @return array<string, array{mixed, string}> | 
|  | 296 | +     */ | 
|  | 297 | +    public function invalidIsConfiguredParameterTypesProvider(): array | 
|  | 298 | +    { | 
|  | 299 | +        return [ | 
|  | 300 | +            'integer parameter' => [123, 'integer'], | 
|  | 301 | +            'array parameter' => [['invalid_array'], 'array'], | 
|  | 302 | +            'object parameter' => [new \stdClass(), 'stdClass'], | 
|  | 303 | +            'boolean parameter' => [true, 'boolean'], | 
|  | 304 | +            'null parameter' => [null, 'NULL'], | 
|  | 305 | +        ]; | 
|  | 306 | +    } | 
|  | 307 | + | 
|  | 308 | +    /** | 
|  | 309 | +     * Tests that isConfigured rejects all invalid parameter types consistently. | 
|  | 310 | +     * | 
|  | 311 | +     * @dataProvider invalidIsConfiguredParameterTypesProvider | 
|  | 312 | +     * @param mixed $invalidParam | 
|  | 313 | +     */ | 
|  | 314 | +    public function testIsConfiguredRejectsInvalidParameterTypes($invalidParam, string $expectedType): void | 
|  | 315 | +    { | 
|  | 316 | +        try { | 
|  | 317 | +            AiClient::isConfigured($invalidParam); | 
|  | 318 | +            $this->fail("Expected InvalidArgumentException for isConfigured with $expectedType"); | 
|  | 319 | +        } catch (\InvalidArgumentException $e) { | 
|  | 320 | +            $this->assertStringContainsString( | 
|  | 321 | +                'Parameter must be a ProviderAvailabilityInterface instance, provider ID string, ' . | 
|  | 322 | +                'or provider class name.', | 
|  | 323 | +                $e->getMessage(), | 
|  | 324 | +                "isConfigured should reject invalid parameter type: $expectedType" | 
|  | 325 | +            ); | 
|  | 326 | +            $this->assertStringContainsString( | 
|  | 327 | +                "Received: $expectedType", | 
|  | 328 | +                $e->getMessage(), | 
|  | 329 | +                "isConfigured should include received type in error message" | 
|  | 330 | +            ); | 
|  | 331 | +        } | 
|  | 332 | +    } | 
|  | 333 | + | 
|  | 334 | +    /** | 
|  | 335 | +     * Tests backward compatibility - isConfigured still works with ProviderAvailabilityInterface. | 
|  | 336 | +     */ | 
|  | 337 | +    public function testIsConfiguredBackwardCompatibility(): void | 
|  | 338 | +    { | 
|  | 339 | +        // Test that the original interface-based approach still works exactly as before | 
|  | 340 | +        $mockAvailability = $this->createMock(ProviderAvailabilityInterface::class); | 
|  | 341 | +        $mockAvailability->expects($this->once()) | 
|  | 342 | +            ->method('isConfigured') | 
|  | 343 | +            ->willReturn(true); | 
|  | 344 | + | 
|  | 345 | +        // Should work without registry parameter | 
|  | 346 | +        $result = AiClient::isConfigured($mockAvailability); | 
|  | 347 | +        $this->assertTrue($result); | 
|  | 348 | + | 
|  | 349 | +        // Should work in all cases with interface input | 
|  | 350 | +        $mockAvailability2 = $this->createMock(ProviderAvailabilityInterface::class); | 
|  | 351 | +        $mockAvailability2->expects($this->once()) | 
|  | 352 | +            ->method('isConfigured') | 
|  | 353 | +            ->willReturn(false); | 
|  | 354 | + | 
|  | 355 | +        $result2 = AiClient::isConfigured($mockAvailability2); | 
|  | 356 | +        $this->assertFalse($result2); | 
|  | 357 | +    } | 
|  | 358 | + | 
| 249 | 359 |     /** | 
| 250 | 360 |      * Tests generateResult delegates to generateTextResult when model supports text generation. | 
| 251 | 361 |      */ | 
|  | 
0 commit comments