From 53cd540d2c5f92eaa32cc369a53ee187e8bc682b Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Thu, 17 Jul 2025 17:00:13 -0600 Subject: [PATCH 01/15] test: adds enum unit tests --- phpunit.xml.dist | 30 +++ tests/unit/Common/AbstractEnumTest.php | 233 ++++++++++++++++++ tests/unit/Common/InvalidNameTestEnum.php | 17 ++ tests/unit/Common/InvalidTypeTestEnum.php | 16 ++ tests/unit/Common/ValidTestEnum.php | 24 ++ tests/unit/EnumTestTrait.php | 115 +++++++++ .../Enums/MessagePartTypeEnumTest.php | 48 ++++ .../Messages/Enums/MessageRoleEnumTest.php | 49 ++++ .../unit/Messages/Enums/ModalityEnumTest.php | 48 ++++ .../Enums/OperationStateEnumTest.php | 48 ++++ .../Providers/Enums/ProviderTypeEnumTest.php | 49 ++++ .../unit/Providers/Enums/ToolTypeEnumTest.php | 41 +++ .../Models/Enums/CapabilityEnumTest.php | 51 ++++ .../Providers/Models/Enums/OptionEnumTest.php | 53 ++++ .../Results/Enums/FinishReasonEnumTest.php | 48 ++++ 15 files changed, 870 insertions(+) create mode 100644 phpunit.xml.dist create mode 100644 tests/unit/Common/AbstractEnumTest.php create mode 100644 tests/unit/Common/InvalidNameTestEnum.php create mode 100644 tests/unit/Common/InvalidTypeTestEnum.php create mode 100644 tests/unit/Common/ValidTestEnum.php create mode 100644 tests/unit/EnumTestTrait.php create mode 100644 tests/unit/Messages/Enums/MessagePartTypeEnumTest.php create mode 100644 tests/unit/Messages/Enums/MessageRoleEnumTest.php create mode 100644 tests/unit/Messages/Enums/ModalityEnumTest.php create mode 100644 tests/unit/Operations/Enums/OperationStateEnumTest.php create mode 100644 tests/unit/Providers/Enums/ProviderTypeEnumTest.php create mode 100644 tests/unit/Providers/Enums/ToolTypeEnumTest.php create mode 100644 tests/unit/Providers/Models/Enums/CapabilityEnumTest.php create mode 100644 tests/unit/Providers/Models/Enums/OptionEnumTest.php create mode 100644 tests/unit/Results/Enums/FinishReasonEnumTest.php diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..37e522f --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,30 @@ + + + + + tests/unit + + + + + + src + + + src/DummyForAnalysis.php + + + \ No newline at end of file diff --git a/tests/unit/Common/AbstractEnumTest.php b/tests/unit/Common/AbstractEnumTest.php new file mode 100644 index 0000000..325f383 --- /dev/null +++ b/tests/unit/Common/AbstractEnumTest.php @@ -0,0 +1,233 @@ +assertInstanceOf(ValidTestEnum::class, $enum); + $this->assertSame('first', $enum->value); + $this->assertSame('FIRST_NAME', $enum->name); + } + + public function testFromWithValidIntValue(): void + { + $enum = ValidTestEnum::from(42); + $this->assertInstanceOf(ValidTestEnum::class, $enum); + $this->assertSame(42, $enum->value); + $this->assertSame('AGE', $enum->name); + } + + public function testFromWithInvalidValueThrowsException(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('invalid is not a valid backing value for enum WordPress\AiClient\Tests\unit\Common\ValidTestEnum'); + ValidTestEnum::from('invalid'); + } + + public function testTryFromWithValidValue(): void + { + $enum = ValidTestEnum::tryFrom('first'); + $this->assertInstanceOf(ValidTestEnum::class, $enum); + $this->assertSame('first', $enum->value); + } + + public function testTryFromWithInvalidValueReturnsNull(): void + { + $enum = ValidTestEnum::tryFrom('invalid'); + $this->assertNull($enum); + } + + public function testCasesReturnsAllEnumInstances(): void + { + $cases = ValidTestEnum::cases(); + $this->assertCount(3, $cases); + + $values = array_map(fn($case) => $case->value, $cases); + $this->assertContains('first', $values); + $this->assertContains('last', $values); + $this->assertContains(42, $values); + + $names = array_map(fn($case) => $case->name, $cases); + $this->assertContains('FIRST_NAME', $names); + $this->assertContains('LAST_NAME', $names); + $this->assertContains('AGE', $names); + } + + public function testSingletonBehavior(): void + { + $enum1 = ValidTestEnum::from('first'); + $enum2 = ValidTestEnum::from('first'); + $enum3 = ValidTestEnum::firstName(); + + $this->assertSame($enum1, $enum2); + $this->assertSame($enum1, $enum3); + } + + public function testStaticFactoryMethods(): void + { + $firstName = ValidTestEnum::firstName(); + $this->assertSame('first', $firstName->value); + $this->assertSame('FIRST_NAME', $firstName->name); + + $lastName = ValidTestEnum::lastName(); + $this->assertSame('last', $lastName->value); + $this->assertSame('LAST_NAME', $lastName->name); + + $age = ValidTestEnum::age(); + $this->assertSame(42, $age->value); + $this->assertSame('AGE', $age->name); + } + + public function testInvalidStaticMethodThrowsException(): void + { + $this->expectException(BadMethodCallException::class); + $this->expectExceptionMessage( + 'Method WordPress\AiClient\Tests\unit\Common\ValidTestEnum::invalidMethod does not exist' + ); + ValidTestEnum::invalidMethod(); + } + + public function testIsCheckMethods(): void + { + $enum = ValidTestEnum::firstName(); + + $this->assertTrue($enum->isFirstName()); + $this->assertFalse($enum->isLastName()); + $this->assertFalse($enum->isAge()); + } + + public function testInvalidIsMethodThrowsException(): void + { + $enum = ValidTestEnum::firstName(); + + $this->expectException(BadMethodCallException::class); + $this->expectExceptionMessage( + 'Method WordPress\AiClient\Tests\unit\Common\ValidTestEnum::isInvalidMethod does not exist' + ); + $enum->isInvalidMethod(); + } + + public function testEqualsWithSameValue(): void + { + $enum = ValidTestEnum::firstName(); + + $this->assertTrue($enum->equals('first')); + $this->assertTrue($enum->equals(ValidTestEnum::firstName())); + $this->assertFalse($enum->equals('last')); + $this->assertFalse($enum->equals(ValidTestEnum::lastName())); + } + + public function testEqualsWithIntValue(): void + { + $enum = ValidTestEnum::age(); + + $this->assertTrue($enum->equals(42)); + $this->assertFalse($enum->equals('42')); // Strict comparison + $this->assertFalse($enum->equals(43)); + } + + public function testIsMethodForIdentityComparison(): void + { + $enum1 = ValidTestEnum::firstName(); + $enum2 = ValidTestEnum::firstName(); + $enum3 = ValidTestEnum::lastName(); + + $this->assertTrue($enum1->is($enum2)); // Same instance + $this->assertFalse($enum1->is($enum3)); // Different instance + } + + public function testGetValuesReturnsAllValidValues(): void + { + $values = ValidTestEnum::getValues(); + + $this->assertSame([ + 'FIRST_NAME' => 'first', + 'LAST_NAME' => 'last', + 'AGE' => 42, + ], $values); + } + + public function testIsValidValue(): void + { + $this->assertTrue(ValidTestEnum::isValidValue('first')); + $this->assertTrue(ValidTestEnum::isValidValue('last')); + $this->assertTrue(ValidTestEnum::isValidValue(42)); + + $this->assertFalse(ValidTestEnum::isValidValue('invalid')); + $this->assertFalse(ValidTestEnum::isValidValue(43)); + } + + public function testFromValueDeprecatedMethod(): void + { + $enum = ValidTestEnum::fromValue('first'); + $this->assertInstanceOf(ValidTestEnum::class, $enum); + $this->assertSame('first', $enum->value); + } + + public function testPropertiesAreReadOnly(): void + { + $enum = ValidTestEnum::firstName(); + + $this->expectException(BadMethodCallException::class); + $this->expectExceptionMessage( + 'Cannot modify property WordPress\AiClient\Tests\unit\Common\ValidTestEnum::value - enum properties are read-only' + ); + $enum->value = 'modified'; + } + + public function testInvalidPropertyAccessThrowsException(): void + { + $enum = ValidTestEnum::firstName(); + + $this->expectException(BadMethodCallException::class); + $this->expectExceptionMessage( + 'Property WordPress\AiClient\Tests\unit\Common\ValidTestEnum::invalid does not exist' + ); + $enum->invalid; + } + + public function testToString(): void + { + $stringEnum = ValidTestEnum::firstName(); + $intEnum = ValidTestEnum::age(); + + $this->assertSame('first', (string) $stringEnum); + $this->assertSame('42', (string) $intEnum); + } + + public function testInvalidConstantNameThrowsException(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + 'Invalid enum constant name "invalid_name" in ' . + 'WordPress\AiClient\Tests\unit\Common\InvalidNameTestEnum. Constants must be UPPER_SNAKE_CASE.' + ); + + InvalidNameTestEnum::cases(); + } + + public function testInvalidConstantTypeThrowsException(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + 'Invalid enum value type for constant ' . + 'WordPress\AiClient\Tests\unit\Common\InvalidTypeTestEnum::FLOAT_VALUE. ' . + 'Only string and int values are allowed, double given.' + ); + + InvalidTypeTestEnum::cases(); + } +} diff --git a/tests/unit/Common/InvalidNameTestEnum.php b/tests/unit/Common/InvalidNameTestEnum.php new file mode 100644 index 0000000..c6b16c3 --- /dev/null +++ b/tests/unit/Common/InvalidNameTestEnum.php @@ -0,0 +1,17 @@ + + */ + abstract protected function getEnumClass(): string; + + /** + * Get expected enum values and their constant names + * + * @return array Array of CONSTANT_NAME => value + */ + abstract protected function getExpectedValues(): array; + + public function testEnumHasExpectedValues(): void + { + $enumClass = $this->getEnumClass(); + $expectedValues = $this->getExpectedValues(); + + $actualValues = $enumClass::getValues(); + + $this->assertEquals($expectedValues, $actualValues); + } + + public function testEnumCasesReturnCorrectInstances(): void + { + $enumClass = $this->getEnumClass(); + $expectedValues = $this->getExpectedValues(); + + $cases = $enumClass::cases(); + + $this->assertCount(count($expectedValues), $cases); + + foreach ($cases as $case) { + $this->assertInstanceOf($enumClass, $case); + $this->assertContains($case->value, $expectedValues); + $this->assertArrayHasKey($case->name, $expectedValues); + $this->assertEquals($expectedValues[$case->name], $case->value); + } + } + + public function testEnumFromMethodWorks(): void + { + $enumClass = $this->getEnumClass(); + $expectedValues = $this->getExpectedValues(); + + foreach ($expectedValues as $name => $value) { + $enum = $enumClass::from($value); + $this->assertInstanceOf($enumClass, $enum); + $this->assertEquals($value, $enum->value); + $this->assertEquals($name, $enum->name); + } + } + + public function testEnumTryFromMethodWorks(): void + { + $enumClass = $this->getEnumClass(); + $expectedValues = $this->getExpectedValues(); + + foreach ($expectedValues as $value) { + $enum = $enumClass::tryFrom($value); + $this->assertInstanceOf($enumClass, $enum); + } + + // Test invalid value + $invalidEnum = $enumClass::tryFrom('definitely_not_a_valid_value_12345'); + $this->assertNull($invalidEnum); + } + + public function testEnumSingletonBehavior(): void + { + $enumClass = $this->getEnumClass(); + $expectedValues = $this->getExpectedValues(); + + if (empty($expectedValues)) { + $this->markTestSkipped('No enum values to test'); + } + + $firstValue = reset($expectedValues); + + $enum1 = $enumClass::from($firstValue); + $enum2 = $enumClass::from($firstValue); + + $this->assertSame($enum1, $enum2); + } + + public function testEnumPropertiesAreReadOnly(): void + { + $enumClass = $this->getEnumClass(); + $expectedValues = $this->getExpectedValues(); + + if (empty($expectedValues)) { + $this->markTestSkipped('No enum values to test'); + } + + $firstValue = reset($expectedValues); + $enum = $enumClass::from($firstValue); + + $this->expectException(\BadMethodCallException::class); + $enum->value = 'modified'; + } +} diff --git a/tests/unit/Messages/Enums/MessagePartTypeEnumTest.php b/tests/unit/Messages/Enums/MessagePartTypeEnumTest.php new file mode 100644 index 0000000..5a92795 --- /dev/null +++ b/tests/unit/Messages/Enums/MessagePartTypeEnumTest.php @@ -0,0 +1,48 @@ + 'text', + 'INLINE_FILE' => 'inline_file', + 'REMOTE_FILE' => 'remote_file', + 'FUNCTION_CALL' => 'function_call', + 'FUNCTION_RESPONSE' => 'function_response', + ]; + } + + public function testSpecificEnumMethods(): void + { + $text = MessagePartTypeEnum::text(); + $this->assertTrue($text->isText()); + $this->assertFalse($text->isInlineFile()); + + $inlineFile = MessagePartTypeEnum::inlineFile(); + $this->assertTrue($inlineFile->isInlineFile()); + $this->assertFalse($inlineFile->isRemoteFile()); + + $functionCall = MessagePartTypeEnum::functionCall(); + $this->assertTrue($functionCall->isFunctionCall()); + $this->assertFalse($functionCall->isFunctionResponse()); + } +} diff --git a/tests/unit/Messages/Enums/MessageRoleEnumTest.php b/tests/unit/Messages/Enums/MessageRoleEnumTest.php new file mode 100644 index 0000000..e098a0c --- /dev/null +++ b/tests/unit/Messages/Enums/MessageRoleEnumTest.php @@ -0,0 +1,49 @@ + 'user', + 'MODEL' => 'model', + 'SYSTEM' => 'system', + ]; + } + + public function testSpecificEnumMethods(): void + { + $user = MessageRoleEnum::user(); + $this->assertTrue($user->isUser()); + $this->assertFalse($user->isModel()); + $this->assertFalse($user->isSystem()); + + $model = MessageRoleEnum::model(); + $this->assertFalse($model->isUser()); + $this->assertTrue($model->isModel()); + $this->assertFalse($model->isSystem()); + + $system = MessageRoleEnum::system(); + $this->assertFalse($system->isUser()); + $this->assertFalse($system->isModel()); + $this->assertTrue($system->isSystem()); + } +} diff --git a/tests/unit/Messages/Enums/ModalityEnumTest.php b/tests/unit/Messages/Enums/ModalityEnumTest.php new file mode 100644 index 0000000..abec982 --- /dev/null +++ b/tests/unit/Messages/Enums/ModalityEnumTest.php @@ -0,0 +1,48 @@ + 'text', + 'DOCUMENT' => 'document', + 'IMAGE' => 'image', + 'AUDIO' => 'audio', + 'VIDEO' => 'video', + ]; + } + + public function testSpecificEnumMethods(): void + { + $text = ModalityEnum::text(); + $this->assertTrue($text->isText()); + $this->assertFalse($text->isDocument()); + + $image = ModalityEnum::image(); + $this->assertTrue($image->isImage()); + $this->assertFalse($image->isAudio()); + + $video = ModalityEnum::video(); + $this->assertTrue($video->isVideo()); + $this->assertFalse($video->isText()); + } +} diff --git a/tests/unit/Operations/Enums/OperationStateEnumTest.php b/tests/unit/Operations/Enums/OperationStateEnumTest.php new file mode 100644 index 0000000..8c02c13 --- /dev/null +++ b/tests/unit/Operations/Enums/OperationStateEnumTest.php @@ -0,0 +1,48 @@ + 'starting', + 'PROCESSING' => 'processing', + 'SUCCEEDED' => 'succeeded', + 'FAILED' => 'failed', + 'CANCELED' => 'canceled', + ]; + } + + public function testSpecificEnumMethods(): void + { + $starting = OperationStateEnum::starting(); + $this->assertTrue($starting->isStarting()); + $this->assertFalse($starting->isProcessing()); + + $succeeded = OperationStateEnum::succeeded(); + $this->assertTrue($succeeded->isSucceeded()); + $this->assertFalse($succeeded->isFailed()); + + $failed = OperationStateEnum::failed(); + $this->assertTrue($failed->isFailed()); + $this->assertFalse($failed->isCanceled()); + } +} diff --git a/tests/unit/Providers/Enums/ProviderTypeEnumTest.php b/tests/unit/Providers/Enums/ProviderTypeEnumTest.php new file mode 100644 index 0000000..04be471 --- /dev/null +++ b/tests/unit/Providers/Enums/ProviderTypeEnumTest.php @@ -0,0 +1,49 @@ + 'cloud', + 'SERVER' => 'server', + 'CLIENT' => 'client', + ]; + } + + public function testSpecificEnumMethods(): void + { + $cloud = ProviderTypeEnum::cloud(); + $this->assertTrue($cloud->isCloud()); + $this->assertFalse($cloud->isServer()); + $this->assertFalse($cloud->isClient()); + + $server = ProviderTypeEnum::server(); + $this->assertFalse($server->isCloud()); + $this->assertTrue($server->isServer()); + $this->assertFalse($server->isClient()); + + $client = ProviderTypeEnum::client(); + $this->assertFalse($client->isCloud()); + $this->assertFalse($client->isServer()); + $this->assertTrue($client->isClient()); + } +} diff --git a/tests/unit/Providers/Enums/ToolTypeEnumTest.php b/tests/unit/Providers/Enums/ToolTypeEnumTest.php new file mode 100644 index 0000000..3ad8cd9 --- /dev/null +++ b/tests/unit/Providers/Enums/ToolTypeEnumTest.php @@ -0,0 +1,41 @@ + 'function_declarations', + 'WEB_SEARCH' => 'web_search', + ]; + } + + public function testSpecificEnumMethods(): void + { + $functionDeclarations = ToolTypeEnum::functionDeclarations(); + $this->assertTrue($functionDeclarations->isFunctionDeclarations()); + $this->assertFalse($functionDeclarations->isWebSearch()); + + $webSearch = ToolTypeEnum::webSearch(); + $this->assertFalse($webSearch->isFunctionDeclarations()); + $this->assertTrue($webSearch->isWebSearch()); + } +} diff --git a/tests/unit/Providers/Models/Enums/CapabilityEnumTest.php b/tests/unit/Providers/Models/Enums/CapabilityEnumTest.php new file mode 100644 index 0000000..351494a --- /dev/null +++ b/tests/unit/Providers/Models/Enums/CapabilityEnumTest.php @@ -0,0 +1,51 @@ + 'text_generation', + 'IMAGE_GENERATION' => 'image_generation', + 'TEXT_TO_SPEECH_CONVERSION' => 'text_to_speech_conversion', + 'SPEECH_GENERATION' => 'speech_generation', + 'MUSIC_GENERATION' => 'music_generation', + 'VIDEO_GENERATION' => 'video_generation', + 'EMBEDDING_GENERATION' => 'embedding_generation', + 'CHAT_HISTORY' => 'chat_history', + ]; + } + + public function testSpecificEnumMethods(): void + { + $textGen = CapabilityEnum::textGeneration(); + $this->assertTrue($textGen->isTextGeneration()); + $this->assertFalse($textGen->isImageGeneration()); + + $imageGen = CapabilityEnum::imageGeneration(); + $this->assertTrue($imageGen->isImageGeneration()); + $this->assertFalse($imageGen->isTextToSpeechConversion()); + + $chatHistory = CapabilityEnum::chatHistory(); + $this->assertTrue($chatHistory->isChatHistory()); + $this->assertFalse($chatHistory->isEmbeddingGeneration()); + } +} diff --git a/tests/unit/Providers/Models/Enums/OptionEnumTest.php b/tests/unit/Providers/Models/Enums/OptionEnumTest.php new file mode 100644 index 0000000..b8a3714 --- /dev/null +++ b/tests/unit/Providers/Models/Enums/OptionEnumTest.php @@ -0,0 +1,53 @@ + 'input_modalities', + 'OUTPUT_MODALITIES' => 'output_modalities', + 'SYSTEM_INSTRUCTION' => 'system_instruction', + 'CANDIDATE_COUNT' => 'candidate_count', + 'MAX_TOKENS' => 'max_tokens', + 'TEMPERATURE' => 'temperature', + 'TOP_K' => 'top_k', + 'TOP_P' => 'top_p', + 'OUTPUT_MIME_TYPE' => 'output_mime_type', + 'OUTPUT_SCHEMA' => 'output_schema', + ]; + } + + public function testSpecificEnumMethods(): void + { + $inputModalities = OptionEnum::inputModalities(); + $this->assertTrue($inputModalities->isInputModalities()); + $this->assertFalse($inputModalities->isOutputModalities()); + + $temperature = OptionEnum::temperature(); + $this->assertTrue($temperature->isTemperature()); + $this->assertFalse($temperature->isTopK()); + + $outputSchema = OptionEnum::outputSchema(); + $this->assertTrue($outputSchema->isOutputSchema()); + $this->assertFalse($outputSchema->isOutputMimeType()); + } +} diff --git a/tests/unit/Results/Enums/FinishReasonEnumTest.php b/tests/unit/Results/Enums/FinishReasonEnumTest.php new file mode 100644 index 0000000..610a9a3 --- /dev/null +++ b/tests/unit/Results/Enums/FinishReasonEnumTest.php @@ -0,0 +1,48 @@ + 'stop', + 'LENGTH' => 'length', + 'CONTENT_FILTER' => 'content_filter', + 'TOOL_CALLS' => 'tool_calls', + 'ERROR' => 'error', + ]; + } + + public function testSpecificEnumMethods(): void + { + $stop = FinishReasonEnum::stop(); + $this->assertTrue($stop->isStop()); + $this->assertFalse($stop->isLength()); + + $contentFilter = FinishReasonEnum::contentFilter(); + $this->assertTrue($contentFilter->isContentFilter()); + $this->assertFalse($contentFilter->isToolCalls()); + + $error = FinishReasonEnum::error(); + $this->assertTrue($error->isError()); + $this->assertFalse($error->isStop()); + } +} From 578d0af3604dac41779b292979192f93301537b0 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Thu, 17 Jul 2025 17:00:30 -0600 Subject: [PATCH 02/15] chore: ignores phpunit cache --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3a97163..a9c4bbc 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ vendor/ *.DS_store .DS_store? .claude/ +.phpunit.cache/ From e6d6ccad608adb588a48604dc363dbe8f3931549 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Thu, 17 Jul 2025 18:22:27 -0600 Subject: [PATCH 03/15] chore: adds unit tests GH workflow --- .github/workflows/unit-tests.yml | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/unit-tests.yml diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml new file mode 100644 index 0000000..5b9c9e8 --- /dev/null +++ b/.github/workflows/unit-tests.yml @@ -0,0 +1,39 @@ +name: Unit Tests + +on: + push: + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + php-version: ['7.4', '8.0', '8.1', '8.2', '8.3'] + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + coverage: xdebug + + - name: Validate composer.json and composer.lock + run: composer validate --strict + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v3 + with: + path: vendor + key: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php-${{ matrix.php-version }}- + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + - name: Run unit tests + run: composer test:unit \ No newline at end of file From 727f3d841cbf90af94c9c9ed410246d52972abfa Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Thu, 17 Jul 2025 18:25:15 -0600 Subject: [PATCH 04/15] chore: limits tests to 7.4 and latest --- .github/workflows/unit-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 5b9c9e8..b0a0abf 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-version: ['7.4', '8.0', '8.1', '8.2', '8.3'] + php-version: ['7.4', '8.3'] steps: - uses: actions/checkout@v4 @@ -36,4 +36,4 @@ jobs: run: composer install --prefer-dist --no-progress - name: Run unit tests - run: composer test:unit \ No newline at end of file + run: composer test:unit From 79dc957370e780a01621c57968a32125a57a9dc6 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Thu, 17 Jul 2025 18:26:44 -0600 Subject: [PATCH 05/15] chore: fixes composer command --- .github/workflows/unit-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index b0a0abf..9cedee2 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -36,4 +36,4 @@ jobs: run: composer install --prefer-dist --no-progress - name: Run unit tests - run: composer test:unit + run: composer phpunit From c5848ec12f013b2fd8f9a87de348fec3b3954ead Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Mon, 21 Jul 2025 13:00:26 -0600 Subject: [PATCH 06/15] test: removes fromValues method --- tests/unit/Common/AbstractEnumTest.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/unit/Common/AbstractEnumTest.php b/tests/unit/Common/AbstractEnumTest.php index 325f383..35f4f13 100644 --- a/tests/unit/Common/AbstractEnumTest.php +++ b/tests/unit/Common/AbstractEnumTest.php @@ -170,13 +170,6 @@ public function testIsValidValue(): void $this->assertFalse(ValidTestEnum::isValidValue(43)); } - public function testFromValueDeprecatedMethod(): void - { - $enum = ValidTestEnum::fromValue('first'); - $this->assertInstanceOf(ValidTestEnum::class, $enum); - $this->assertSame('first', $enum->value); - } - public function testPropertiesAreReadOnly(): void { $enum = ValidTestEnum::firstName(); From 8ca41247fe50766c319aa71ff489677ae24ce413 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Tue, 22 Jul 2025 08:12:59 -0600 Subject: [PATCH 07/15] chore: prevents running unit tests twice --- .github/workflows/unit-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 9cedee2..e5fe9ae 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -2,6 +2,8 @@ name: Unit Tests on: push: + branches: + - trunk pull_request: jobs: From ce57c5ff2d9b7b47faf58a2ab091c6ac005cb8c9 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Tue, 22 Jul 2025 08:15:40 -0600 Subject: [PATCH 08/15] chore: bump latest php version to 8.4 --- .github/workflows/unit-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index e5fe9ae..66a6dee 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-version: ['7.4', '8.3'] + php-version: ['7.4', '8.4'] steps: - uses: actions/checkout@v4 From ffe4de0202f6a28f5286549b58b663319000c521 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Tue, 22 Jul 2025 13:39:57 -0600 Subject: [PATCH 09/15] refactor: limits enums to strings --- tests/unit/Common/AbstractEnumTest.php | 90 ++++++++++++------- tests/unit/Common/InvalidNameTestEnum.php | 2 +- tests/unit/Common/InvalidTypeTestEnum.php | 4 +- tests/unit/Common/ValidTestEnum.php | 13 ++- tests/unit/EnumTestTrait.php | 28 ++++-- .../Enums/MessagePartTypeEnumTest.php | 15 ++++ .../Messages/Enums/MessageRoleEnumTest.php | 15 ++++ .../unit/Messages/Enums/ModalityEnumTest.php | 15 ++++ .../Enums/OperationStateEnumTest.php | 15 ++++ .../Providers/Enums/ProviderTypeEnumTest.php | 15 ++++ .../unit/Providers/Enums/ToolTypeEnumTest.php | 15 ++++ .../Models/Enums/CapabilityEnumTest.php | 15 ++++ .../Providers/Models/Enums/OptionEnumTest.php | 15 ++++ .../Results/Enums/FinishReasonEnumTest.php | 15 ++++ 14 files changed, 226 insertions(+), 46 deletions(-) diff --git a/tests/unit/Common/AbstractEnumTest.php b/tests/unit/Common/AbstractEnumTest.php index 35f4f13..d5c76d5 100644 --- a/tests/unit/Common/AbstractEnumTest.php +++ b/tests/unit/Common/AbstractEnumTest.php @@ -14,6 +14,9 @@ */ class AbstractEnumTest extends TestCase { + /** + * Tests that from() creates an enum instance with a valid value. + */ public function testFromWithValidValue(): void { $enum = ValidTestEnum::from('first'); @@ -22,14 +25,10 @@ public function testFromWithValidValue(): void $this->assertSame('FIRST_NAME', $enum->name); } - public function testFromWithValidIntValue(): void - { - $enum = ValidTestEnum::from(42); - $this->assertInstanceOf(ValidTestEnum::class, $enum); - $this->assertSame(42, $enum->value); - $this->assertSame('AGE', $enum->name); - } + /** + * Tests that from() throws an exception for invalid values. + */ public function testFromWithInvalidValueThrowsException(): void { $this->expectException(InvalidArgumentException::class); @@ -37,6 +36,9 @@ public function testFromWithInvalidValueThrowsException(): void ValidTestEnum::from('invalid'); } + /** + * Tests that tryFrom() returns an enum instance for valid values. + */ public function testTryFromWithValidValue(): void { $enum = ValidTestEnum::tryFrom('first'); @@ -44,28 +46,35 @@ public function testTryFromWithValidValue(): void $this->assertSame('first', $enum->value); } + /** + * Tests that tryFrom() returns null for invalid values. + */ public function testTryFromWithInvalidValueReturnsNull(): void { $enum = ValidTestEnum::tryFrom('invalid'); $this->assertNull($enum); } + /** + * Tests that cases() returns all enum instances. + */ public function testCasesReturnsAllEnumInstances(): void { $cases = ValidTestEnum::cases(); - $this->assertCount(3, $cases); + $this->assertCount(2, $cases); $values = array_map(fn($case) => $case->value, $cases); $this->assertContains('first', $values); $this->assertContains('last', $values); - $this->assertContains(42, $values); $names = array_map(fn($case) => $case->name, $cases); $this->assertContains('FIRST_NAME', $names); $this->assertContains('LAST_NAME', $names); - $this->assertContains('AGE', $names); } + /** + * Tests that enum instances are singletons. + */ public function testSingletonBehavior(): void { $enum1 = ValidTestEnum::from('first'); @@ -76,6 +85,9 @@ public function testSingletonBehavior(): void $this->assertSame($enum1, $enum3); } + /** + * Tests static factory methods for creating enum instances. + */ public function testStaticFactoryMethods(): void { $firstName = ValidTestEnum::firstName(); @@ -85,12 +97,11 @@ public function testStaticFactoryMethods(): void $lastName = ValidTestEnum::lastName(); $this->assertSame('last', $lastName->value); $this->assertSame('LAST_NAME', $lastName->name); - - $age = ValidTestEnum::age(); - $this->assertSame(42, $age->value); - $this->assertSame('AGE', $age->name); } + /** + * Tests that invalid static methods throw exceptions. + */ public function testInvalidStaticMethodThrowsException(): void { $this->expectException(BadMethodCallException::class); @@ -100,15 +111,20 @@ public function testInvalidStaticMethodThrowsException(): void ValidTestEnum::invalidMethod(); } + /** + * Tests the is* check methods. + */ public function testIsCheckMethods(): void { $enum = ValidTestEnum::firstName(); $this->assertTrue($enum->isFirstName()); $this->assertFalse($enum->isLastName()); - $this->assertFalse($enum->isAge()); } + /** + * Tests that invalid is* methods throw exceptions. + */ public function testInvalidIsMethodThrowsException(): void { $enum = ValidTestEnum::firstName(); @@ -120,6 +136,9 @@ public function testInvalidIsMethodThrowsException(): void $enum->isInvalidMethod(); } + /** + * Tests the equals() method with various values. + */ public function testEqualsWithSameValue(): void { $enum = ValidTestEnum::firstName(); @@ -130,15 +149,10 @@ public function testEqualsWithSameValue(): void $this->assertFalse($enum->equals(ValidTestEnum::lastName())); } - public function testEqualsWithIntValue(): void - { - $enum = ValidTestEnum::age(); - - $this->assertTrue($enum->equals(42)); - $this->assertFalse($enum->equals('42')); // Strict comparison - $this->assertFalse($enum->equals(43)); - } + /** + * Tests the is() method for identity comparison. + */ public function testIsMethodForIdentityComparison(): void { $enum1 = ValidTestEnum::firstName(); @@ -149,6 +163,9 @@ public function testIsMethodForIdentityComparison(): void $this->assertFalse($enum1->is($enum3)); // Different instance } + /** + * Tests that getValues() returns all valid enum values. + */ public function testGetValuesReturnsAllValidValues(): void { $values = ValidTestEnum::getValues(); @@ -156,20 +173,23 @@ public function testGetValuesReturnsAllValidValues(): void $this->assertSame([ 'FIRST_NAME' => 'first', 'LAST_NAME' => 'last', - 'AGE' => 42, ], $values); } + /** + * Tests the isValidValue() method. + */ public function testIsValidValue(): void { $this->assertTrue(ValidTestEnum::isValidValue('first')); $this->assertTrue(ValidTestEnum::isValidValue('last')); - $this->assertTrue(ValidTestEnum::isValidValue(42)); $this->assertFalse(ValidTestEnum::isValidValue('invalid')); - $this->assertFalse(ValidTestEnum::isValidValue(43)); } + /** + * Tests that enum properties are read-only. + */ public function testPropertiesAreReadOnly(): void { $enum = ValidTestEnum::firstName(); @@ -181,6 +201,9 @@ public function testPropertiesAreReadOnly(): void $enum->value = 'modified'; } + /** + * Tests that accessing invalid properties throws exceptions. + */ public function testInvalidPropertyAccessThrowsException(): void { $enum = ValidTestEnum::firstName(); @@ -192,15 +215,19 @@ public function testInvalidPropertyAccessThrowsException(): void $enum->invalid; } + /** + * Tests the __toString() method. + */ public function testToString(): void { $stringEnum = ValidTestEnum::firstName(); - $intEnum = ValidTestEnum::age(); $this->assertSame('first', (string) $stringEnum); - $this->assertSame('42', (string) $intEnum); } + /** + * Tests that invalid constant names throw exceptions. + */ public function testInvalidConstantNameThrowsException(): void { $this->expectException(RuntimeException::class); @@ -212,13 +239,16 @@ public function testInvalidConstantNameThrowsException(): void InvalidNameTestEnum::cases(); } + /** + * Tests that invalid constant types throw exceptions. + */ public function testInvalidConstantTypeThrowsException(): void { $this->expectException(RuntimeException::class); $this->expectExceptionMessage( 'Invalid enum value type for constant ' . - 'WordPress\AiClient\Tests\unit\Common\InvalidTypeTestEnum::FLOAT_VALUE. ' . - 'Only string and int values are allowed, double given.' + 'WordPress\AiClient\Tests\unit\Common\InvalidTypeTestEnum::INT_VALUE. ' . + 'Only string values are allowed, integer given.' ); InvalidTypeTestEnum::cases(); diff --git a/tests/unit/Common/InvalidNameTestEnum.php b/tests/unit/Common/InvalidNameTestEnum.php index c6b16c3..00d512e 100644 --- a/tests/unit/Common/InvalidNameTestEnum.php +++ b/tests/unit/Common/InvalidNameTestEnum.php @@ -7,7 +7,7 @@ use WordPress\AiClient\Common\AbstractEnum; /** - * Invalid test enum with lowercase constant name + * Invalid test enum with lowercase constant name. */ class InvalidNameTestEnum extends AbstractEnum { diff --git a/tests/unit/Common/InvalidTypeTestEnum.php b/tests/unit/Common/InvalidTypeTestEnum.php index b9297eb..9296fd7 100644 --- a/tests/unit/Common/InvalidTypeTestEnum.php +++ b/tests/unit/Common/InvalidTypeTestEnum.php @@ -7,10 +7,10 @@ use WordPress\AiClient\Common\AbstractEnum; /** - * Invalid test enum with float value + * Invalid test enum with float value. */ class InvalidTypeTestEnum extends AbstractEnum { public const VALID_VALUE = 'valid'; - public const FLOAT_VALUE = 3.14; // This should cause an exception + public const INT_VALUE = 42; // This should cause an exception } diff --git a/tests/unit/Common/ValidTestEnum.php b/tests/unit/Common/ValidTestEnum.php index a1ff310..b6b5c00 100644 --- a/tests/unit/Common/ValidTestEnum.php +++ b/tests/unit/Common/ValidTestEnum.php @@ -7,18 +7,15 @@ use WordPress\AiClient\Common\AbstractEnum; /** - * Valid test enum for testing AbstractEnum functionality + * Valid test enum for testing AbstractEnum functionality. * - * @method static self firstName() Create an instance for FIRST_NAME - * @method static self lastName() Create an instance for LAST_NAME - * @method static self age() Create an instance for AGE - * @method bool isFirstName() Check if the value is FIRST_NAME - * @method bool isLastName() Check if the value is LAST_NAME - * @method bool isAge() Check if the value is AGE + * @method static self firstName() Creates an instance for FIRST_NAME. + * @method static self lastName() Creates an instance for LAST_NAME. + * @method bool isFirstName() Checks if the value is FIRST_NAME. + * @method bool isLastName() Checks if the value is LAST_NAME. */ class ValidTestEnum extends AbstractEnum { public const FIRST_NAME = 'first'; public const LAST_NAME = 'last'; - public const AGE = 42; } diff --git a/tests/unit/EnumTestTrait.php b/tests/unit/EnumTestTrait.php index 8fa39d2..3d282fd 100644 --- a/tests/unit/EnumTestTrait.php +++ b/tests/unit/EnumTestTrait.php @@ -7,24 +7,27 @@ use WordPress\AiClient\Common\AbstractEnum; /** - * Trait for testing enum classes + * Trait for testing enum classes. */ trait EnumTestTrait { /** - * Get the enum class name to test + * Gets the enum class name to test. * - * @return class-string + * @return class-string The enum class name. */ abstract protected function getEnumClass(): string; /** - * Get expected enum values and their constant names + * Gets expected enum values and their constant names. * - * @return array Array of CONSTANT_NAME => value + * @return array Array of CONSTANT_NAME => value. */ abstract protected function getExpectedValues(): array; + /** + * Tests that the enum has expected values. + */ public function testEnumHasExpectedValues(): void { $enumClass = $this->getEnumClass(); @@ -35,6 +38,9 @@ public function testEnumHasExpectedValues(): void $this->assertEquals($expectedValues, $actualValues); } + /** + * Tests that enum cases return correct instances. + */ public function testEnumCasesReturnCorrectInstances(): void { $enumClass = $this->getEnumClass(); @@ -52,6 +58,9 @@ public function testEnumCasesReturnCorrectInstances(): void } } + /** + * Tests that the from() method works correctly. + */ public function testEnumFromMethodWorks(): void { $enumClass = $this->getEnumClass(); @@ -65,6 +74,9 @@ public function testEnumFromMethodWorks(): void } } + /** + * Tests that the tryFrom() method works correctly. + */ public function testEnumTryFromMethodWorks(): void { $enumClass = $this->getEnumClass(); @@ -80,6 +92,9 @@ public function testEnumTryFromMethodWorks(): void $this->assertNull($invalidEnum); } + /** + * Tests enum singleton behavior. + */ public function testEnumSingletonBehavior(): void { $enumClass = $this->getEnumClass(); @@ -97,6 +112,9 @@ public function testEnumSingletonBehavior(): void $this->assertSame($enum1, $enum2); } + /** + * Tests that enum properties are read-only. + */ public function testEnumPropertiesAreReadOnly(): void { $enumClass = $this->getEnumClass(); diff --git a/tests/unit/Messages/Enums/MessagePartTypeEnumTest.php b/tests/unit/Messages/Enums/MessagePartTypeEnumTest.php index 5a92795..937c6dc 100644 --- a/tests/unit/Messages/Enums/MessagePartTypeEnumTest.php +++ b/tests/unit/Messages/Enums/MessagePartTypeEnumTest.php @@ -15,11 +15,21 @@ class MessagePartTypeEnumTest extends TestCase { use EnumTestTrait; + /** + * Gets the enum class to test. + * + * @return string + */ protected function getEnumClass(): string { return MessagePartTypeEnum::class; } + /** + * Gets the expected enum values. + * + * @return array + */ protected function getExpectedValues(): array { return [ @@ -31,6 +41,11 @@ protected function getExpectedValues(): array ]; } + /** + * Tests the specific enum methods. + * + * @return void + */ public function testSpecificEnumMethods(): void { $text = MessagePartTypeEnum::text(); diff --git a/tests/unit/Messages/Enums/MessageRoleEnumTest.php b/tests/unit/Messages/Enums/MessageRoleEnumTest.php index e098a0c..9e35432 100644 --- a/tests/unit/Messages/Enums/MessageRoleEnumTest.php +++ b/tests/unit/Messages/Enums/MessageRoleEnumTest.php @@ -15,11 +15,21 @@ class MessageRoleEnumTest extends TestCase { use EnumTestTrait; + /** + * Gets the enum class to test. + * + * @return string + */ protected function getEnumClass(): string { return MessageRoleEnum::class; } + /** + * Gets the expected enum values. + * + * @return array + */ protected function getExpectedValues(): array { return [ @@ -29,6 +39,11 @@ protected function getExpectedValues(): array ]; } + /** + * Tests the specific enum methods. + * + * @return void + */ public function testSpecificEnumMethods(): void { $user = MessageRoleEnum::user(); diff --git a/tests/unit/Messages/Enums/ModalityEnumTest.php b/tests/unit/Messages/Enums/ModalityEnumTest.php index abec982..cea4e5f 100644 --- a/tests/unit/Messages/Enums/ModalityEnumTest.php +++ b/tests/unit/Messages/Enums/ModalityEnumTest.php @@ -15,11 +15,21 @@ class ModalityEnumTest extends TestCase { use EnumTestTrait; + /** + * Gets the enum class to test. + * + * @return string + */ protected function getEnumClass(): string { return ModalityEnum::class; } + /** + * Gets the expected enum values. + * + * @return array + */ protected function getExpectedValues(): array { return [ @@ -31,6 +41,11 @@ protected function getExpectedValues(): array ]; } + /** + * Tests the specific enum methods. + * + * @return void + */ public function testSpecificEnumMethods(): void { $text = ModalityEnum::text(); diff --git a/tests/unit/Operations/Enums/OperationStateEnumTest.php b/tests/unit/Operations/Enums/OperationStateEnumTest.php index 8c02c13..fd7f296 100644 --- a/tests/unit/Operations/Enums/OperationStateEnumTest.php +++ b/tests/unit/Operations/Enums/OperationStateEnumTest.php @@ -15,11 +15,21 @@ class OperationStateEnumTest extends TestCase { use EnumTestTrait; + /** + * Gets the enum class to test. + * + * @return string + */ protected function getEnumClass(): string { return OperationStateEnum::class; } + /** + * Gets the expected enum values. + * + * @return array + */ protected function getExpectedValues(): array { return [ @@ -31,6 +41,11 @@ protected function getExpectedValues(): array ]; } + /** + * Tests the specific enum methods. + * + * @return void + */ public function testSpecificEnumMethods(): void { $starting = OperationStateEnum::starting(); diff --git a/tests/unit/Providers/Enums/ProviderTypeEnumTest.php b/tests/unit/Providers/Enums/ProviderTypeEnumTest.php index 04be471..e658231 100644 --- a/tests/unit/Providers/Enums/ProviderTypeEnumTest.php +++ b/tests/unit/Providers/Enums/ProviderTypeEnumTest.php @@ -15,11 +15,21 @@ class ProviderTypeEnumTest extends TestCase { use EnumTestTrait; + /** + * Gets the enum class to test. + * + * @return string + */ protected function getEnumClass(): string { return ProviderTypeEnum::class; } + /** + * Gets the expected enum values. + * + * @return array + */ protected function getExpectedValues(): array { return [ @@ -29,6 +39,11 @@ protected function getExpectedValues(): array ]; } + /** + * Tests the specific enum methods. + * + * @return void + */ public function testSpecificEnumMethods(): void { $cloud = ProviderTypeEnum::cloud(); diff --git a/tests/unit/Providers/Enums/ToolTypeEnumTest.php b/tests/unit/Providers/Enums/ToolTypeEnumTest.php index 3ad8cd9..ddd1a19 100644 --- a/tests/unit/Providers/Enums/ToolTypeEnumTest.php +++ b/tests/unit/Providers/Enums/ToolTypeEnumTest.php @@ -15,11 +15,21 @@ class ToolTypeEnumTest extends TestCase { use EnumTestTrait; + /** + * Gets the enum class to test. + * + * @return string + */ protected function getEnumClass(): string { return ToolTypeEnum::class; } + /** + * Gets the expected enum values. + * + * @return array + */ protected function getExpectedValues(): array { return [ @@ -28,6 +38,11 @@ protected function getExpectedValues(): array ]; } + /** + * Tests the specific enum methods. + * + * @return void + */ public function testSpecificEnumMethods(): void { $functionDeclarations = ToolTypeEnum::functionDeclarations(); diff --git a/tests/unit/Providers/Models/Enums/CapabilityEnumTest.php b/tests/unit/Providers/Models/Enums/CapabilityEnumTest.php index 351494a..fa1e0b0 100644 --- a/tests/unit/Providers/Models/Enums/CapabilityEnumTest.php +++ b/tests/unit/Providers/Models/Enums/CapabilityEnumTest.php @@ -15,11 +15,21 @@ class CapabilityEnumTest extends TestCase { use EnumTestTrait; + /** + * Gets the enum class to test. + * + * @return string + */ protected function getEnumClass(): string { return CapabilityEnum::class; } + /** + * Gets the expected enum values. + * + * @return array + */ protected function getExpectedValues(): array { return [ @@ -34,6 +44,11 @@ protected function getExpectedValues(): array ]; } + /** + * Tests the specific enum methods. + * + * @return void + */ public function testSpecificEnumMethods(): void { $textGen = CapabilityEnum::textGeneration(); diff --git a/tests/unit/Providers/Models/Enums/OptionEnumTest.php b/tests/unit/Providers/Models/Enums/OptionEnumTest.php index b8a3714..6869898 100644 --- a/tests/unit/Providers/Models/Enums/OptionEnumTest.php +++ b/tests/unit/Providers/Models/Enums/OptionEnumTest.php @@ -15,11 +15,21 @@ class OptionEnumTest extends TestCase { use EnumTestTrait; + /** + * Gets the enum class to test. + * + * @return string + */ protected function getEnumClass(): string { return OptionEnum::class; } + /** + * Gets the expected enum values. + * + * @return array + */ protected function getExpectedValues(): array { return [ @@ -36,6 +46,11 @@ protected function getExpectedValues(): array ]; } + /** + * Tests the specific enum methods. + * + * @return void + */ public function testSpecificEnumMethods(): void { $inputModalities = OptionEnum::inputModalities(); diff --git a/tests/unit/Results/Enums/FinishReasonEnumTest.php b/tests/unit/Results/Enums/FinishReasonEnumTest.php index 610a9a3..4883203 100644 --- a/tests/unit/Results/Enums/FinishReasonEnumTest.php +++ b/tests/unit/Results/Enums/FinishReasonEnumTest.php @@ -15,11 +15,21 @@ class FinishReasonEnumTest extends TestCase { use EnumTestTrait; + /** + * Gets the enum class to test. + * + * @return string + */ protected function getEnumClass(): string { return FinishReasonEnum::class; } + /** + * Gets the expected enum values. + * + * @return array + */ protected function getExpectedValues(): array { return [ @@ -31,6 +41,11 @@ protected function getExpectedValues(): array ]; } + /** + * Tests the specific enum methods. + * + * @return void + */ public function testSpecificEnumMethods(): void { $stop = FinishReasonEnum::stop(); From c5d7ee13d31180e12a3202edf492bd0b12437286 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Tue, 22 Jul 2025 18:44:59 -0600 Subject: [PATCH 10/15] refactor: renames github test flow --- .github/workflows/{unit-tests.yml => php-test.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{unit-tests.yml => php-test.yml} (100%) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/php-test.yml similarity index 100% rename from .github/workflows/unit-tests.yml rename to .github/workflows/php-test.yml From 7df98bf5db01fc01dcda444ea78fabacfe6364e4 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Tue, 22 Jul 2025 18:46:07 -0600 Subject: [PATCH 11/15] chore: updates test workflow conditions --- .github/workflows/php-test.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/php-test.yml b/.github/workflows/php-test.yml index 66a6dee..c4918fe 100644 --- a/.github/workflows/php-test.yml +++ b/.github/workflows/php-test.yml @@ -4,7 +4,29 @@ on: push: branches: - trunk + - 'feature/**' + - 'release/**' + # Only run if PHP-related files changed. + paths: + - '.github/workflows/php-lint.yml' + - '**.php' + - 'phpcs.xml.dist' + - 'phpstan.neon.dist' + - 'composer.json' + - 'composer.lock' pull_request: + # Only run if PHP-related files changed. + paths: + - '.github/workflows/php-lint.yml' + - '**.php' + - 'phpcs.xml.dist' + - 'phpstan.neon.dist' + - 'composer.json' + - 'composer.lock' + types: + - opened + - reopened + - synchronize jobs: test: From fbc4501bf8a6d029b7787d0d3ac90c88c100a63b Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Tue, 22 Jul 2025 18:55:20 -0600 Subject: [PATCH 12/15] refactor: moves mock enums --- .../Enums}/InvalidNameTestEnum.php | 2 +- .../Enums}/InvalidTypeTestEnum.php | 2 +- .../Common => mocks/Enums}/ValidTestEnum.php | 2 +- tests/unit/Common/AbstractEnumTest.php | 17 ++++++++++------- 4 files changed, 13 insertions(+), 10 deletions(-) rename tests/{unit/Common => mocks/Enums}/InvalidNameTestEnum.php (89%) rename tests/{unit/Common => mocks/Enums}/InvalidTypeTestEnum.php (85%) rename tests/{unit/Common => mocks/Enums}/ValidTestEnum.php (91%) diff --git a/tests/unit/Common/InvalidNameTestEnum.php b/tests/mocks/Enums/InvalidNameTestEnum.php similarity index 89% rename from tests/unit/Common/InvalidNameTestEnum.php rename to tests/mocks/Enums/InvalidNameTestEnum.php index 00d512e..3023bde 100644 --- a/tests/unit/Common/InvalidNameTestEnum.php +++ b/tests/mocks/Enums/InvalidNameTestEnum.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace WordPress\AiClient\Tests\unit\Common; +namespace WordPress\AiClient\Tests\mocks\Enums; use WordPress\AiClient\Common\AbstractEnum; diff --git a/tests/unit/Common/InvalidTypeTestEnum.php b/tests/mocks/Enums/InvalidTypeTestEnum.php similarity index 85% rename from tests/unit/Common/InvalidTypeTestEnum.php rename to tests/mocks/Enums/InvalidTypeTestEnum.php index 9296fd7..de35ebc 100644 --- a/tests/unit/Common/InvalidTypeTestEnum.php +++ b/tests/mocks/Enums/InvalidTypeTestEnum.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace WordPress\AiClient\Tests\unit\Common; +namespace WordPress\AiClient\Tests\mocks\Enums; use WordPress\AiClient\Common\AbstractEnum; diff --git a/tests/unit/Common/ValidTestEnum.php b/tests/mocks/Enums/ValidTestEnum.php similarity index 91% rename from tests/unit/Common/ValidTestEnum.php rename to tests/mocks/Enums/ValidTestEnum.php index b6b5c00..b4581b0 100644 --- a/tests/unit/Common/ValidTestEnum.php +++ b/tests/mocks/Enums/ValidTestEnum.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace WordPress\AiClient\Tests\unit\Common; +namespace WordPress\AiClient\Tests\mocks\Enums; use WordPress\AiClient\Common\AbstractEnum; diff --git a/tests/unit/Common/AbstractEnumTest.php b/tests/unit/Common/AbstractEnumTest.php index d5c76d5..3aa82a1 100644 --- a/tests/unit/Common/AbstractEnumTest.php +++ b/tests/unit/Common/AbstractEnumTest.php @@ -8,6 +8,9 @@ use InvalidArgumentException; use PHPUnit\Framework\TestCase; use RuntimeException; +use WordPress\AiClient\Tests\mocks\Enums\InvalidNameTestEnum; +use WordPress\AiClient\Tests\mocks\Enums\InvalidTypeTestEnum; +use WordPress\AiClient\Tests\mocks\Enums\ValidTestEnum; /** * @covers \WordPress\AiClient\Common\AbstractEnum @@ -32,7 +35,7 @@ public function testFromWithValidValue(): void public function testFromWithInvalidValueThrowsException(): void { $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('invalid is not a valid backing value for enum WordPress\AiClient\Tests\unit\Common\ValidTestEnum'); + $this->expectExceptionMessage('invalid is not a valid backing value for enum WordPress\AiClient\Tests\mocks\Enums\ValidTestEnum'); ValidTestEnum::from('invalid'); } @@ -106,7 +109,7 @@ public function testInvalidStaticMethodThrowsException(): void { $this->expectException(BadMethodCallException::class); $this->expectExceptionMessage( - 'Method WordPress\AiClient\Tests\unit\Common\ValidTestEnum::invalidMethod does not exist' + 'Method WordPress\AiClient\Tests\mocks\Enums\ValidTestEnum::invalidMethod does not exist' ); ValidTestEnum::invalidMethod(); } @@ -131,7 +134,7 @@ public function testInvalidIsMethodThrowsException(): void $this->expectException(BadMethodCallException::class); $this->expectExceptionMessage( - 'Method WordPress\AiClient\Tests\unit\Common\ValidTestEnum::isInvalidMethod does not exist' + 'Method WordPress\AiClient\Tests\mocks\Enums\ValidTestEnum::isInvalidMethod does not exist' ); $enum->isInvalidMethod(); } @@ -196,7 +199,7 @@ public function testPropertiesAreReadOnly(): void $this->expectException(BadMethodCallException::class); $this->expectExceptionMessage( - 'Cannot modify property WordPress\AiClient\Tests\unit\Common\ValidTestEnum::value - enum properties are read-only' + 'Cannot modify property WordPress\AiClient\Tests\mocks\Enums\ValidTestEnum::value - enum properties are read-only' ); $enum->value = 'modified'; } @@ -210,7 +213,7 @@ public function testInvalidPropertyAccessThrowsException(): void $this->expectException(BadMethodCallException::class); $this->expectExceptionMessage( - 'Property WordPress\AiClient\Tests\unit\Common\ValidTestEnum::invalid does not exist' + 'Property WordPress\AiClient\Tests\mocks\Enums\ValidTestEnum::invalid does not exist' ); $enum->invalid; } @@ -233,7 +236,7 @@ public function testInvalidConstantNameThrowsException(): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage( 'Invalid enum constant name "invalid_name" in ' . - 'WordPress\AiClient\Tests\unit\Common\InvalidNameTestEnum. Constants must be UPPER_SNAKE_CASE.' + 'WordPress\AiClient\Tests\mocks\Enums\InvalidNameTestEnum. Constants must be UPPER_SNAKE_CASE.' ); InvalidNameTestEnum::cases(); @@ -247,7 +250,7 @@ public function testInvalidConstantTypeThrowsException(): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage( 'Invalid enum value type for constant ' . - 'WordPress\AiClient\Tests\unit\Common\InvalidTypeTestEnum::INT_VALUE. ' . + 'WordPress\AiClient\Tests\mocks\Enums\InvalidTypeTestEnum::INT_VALUE. ' . 'Only string values are allowed, integer given.' ); From d5bdb614517b9909296f730ff0731d17b238d254 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Wed, 23 Jul 2025 09:33:47 -0600 Subject: [PATCH 13/15] chore: adds 8.0 as a tested version --- .github/workflows/php-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/php-test.yml b/.github/workflows/php-test.yml index c4918fe..981e27e 100644 --- a/.github/workflows/php-test.yml +++ b/.github/workflows/php-test.yml @@ -33,7 +33,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-version: ['7.4', '8.4'] + php-version: ['7.4', '8.0', '8.4'] steps: - uses: actions/checkout@v4 From 830cd9e0eb4054e561b740bb8b652eec35e97dac Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Wed, 23 Jul 2025 10:45:48 -0600 Subject: [PATCH 14/15] chore: fixes workflow paths Co-authored-by: Felix Arntz --- .github/workflows/php-test.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/php-test.yml b/.github/workflows/php-test.yml index 981e27e..bfdc56b 100644 --- a/.github/workflows/php-test.yml +++ b/.github/workflows/php-test.yml @@ -8,19 +8,17 @@ on: - 'release/**' # Only run if PHP-related files changed. paths: - - '.github/workflows/php-lint.yml' + - '.github/workflows/php-test.yml' - '**.php' - - 'phpcs.xml.dist' - - 'phpstan.neon.dist' + - 'phpunit.xml.dist' - 'composer.json' - 'composer.lock' pull_request: # Only run if PHP-related files changed. paths: - - '.github/workflows/php-lint.yml' + - '.github/workflows/php-test.yml' - '**.php' - - 'phpcs.xml.dist' - - 'phpstan.neon.dist' + - 'phpunit.xml.dist' - 'composer.json' - 'composer.lock' types: From d8c2267c3db0cfb9f19f88ae69cb7fb23a37bf92 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Wed, 23 Jul 2025 10:57:19 -0600 Subject: [PATCH 15/15] chore: removes old dummy file reference --- phpunit.xml.dist | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 37e522f..035bf01 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -23,8 +23,5 @@ src - - src/DummyForAnalysis.php - - \ No newline at end of file +