diff --git a/src/Entities/Subscription.php b/src/Entities/Subscription.php index 41d242c..c44f895 100644 --- a/src/Entities/Subscription.php +++ b/src/Entities/Subscription.php @@ -21,7 +21,7 @@ use D3\KlicktippPhpClient\Exceptions\BaseException; use D3\KlicktippPhpClient\Resources\SubscriptionProcess; use Doctrine\Common\Collections\ArrayCollection; -class Subscription extends ArrayCollection +class Subscription extends Entity { private ?SubscriptionProcess $endpoint; @@ -31,14 +31,14 @@ class Subscription extends ArrayCollection parent::__construct($elements); } - public function getListId(): string + public function getListId(): ?string { - return $this->get(SubscriptionProcess::LISTID) ?? ''; + return $this->getStringOrNullValue($this->get(SubscriptionProcess::LISTID)); } - public function getName(): string + public function getName(): ?string { - return $this->get(SubscriptionProcess::NAME) ?? ''; + return $this->getStringOrNullValue($this->get(SubscriptionProcess::NAME)); } public function setName(string $name): void @@ -46,34 +46,34 @@ class Subscription extends ArrayCollection $this->set(SubscriptionProcess::NAME, $name); } - public function getPendingUrl(): string + public function getPendingUrl(): ?string { - return $this->get(SubscriptionProcess::PENDINGURL) ?? ''; + return $this->getStringOrNullValue($this->get(SubscriptionProcess::PENDINGURL)); } - public function getThankyouUrl(): string + public function getThankyouUrl(): ?string { - return $this->get(SubscriptionProcess::THANKYOUURL) ?? ''; + return $this->getStringOrNullValue($this->get(SubscriptionProcess::THANKYOUURL)); } - public function useSingleOptin(): bool + public function useSingleOptin(): ?bool { - return $this->get(SubscriptionProcess::USE_SINGLE_OPTIN); + return $this->getBooleanOrNullValue($this->get(SubscriptionProcess::USE_SINGLE_OPTIN)); } - public function useDoubleOptin(): bool + public function useDoubleOptin(): ?bool { - return !$this->useSingleOptin(); + return is_null($soi = $this->useSingleOptin()) ? null : !$soi; } - public function resendConfirmationEmail(): bool + public function resendConfirmationEmail(): ?bool { - return $this->get(SubscriptionProcess::RESEND_CONFIRMATION_EMAIL); + return $this->getBooleanOrNullValue($this->get(SubscriptionProcess::RESEND_CONFIRMATION_EMAIL)); } - public function useChangeEmail(): bool + public function useChangeEmail(): ?bool { - return $this->get(SubscriptionProcess::USE_CHANGE_EMAIL); + return $this->getBooleanOrNullValue($this->get(SubscriptionProcess::USE_CHANGE_EMAIL)); } /** diff --git a/tests/unit/Entities/SubscriptionTest.php b/tests/unit/Entities/SubscriptionTest.php new file mode 100644 index 0000000..5bfd2d1 --- /dev/null +++ b/tests/unit/Entities/SubscriptionTest.php @@ -0,0 +1,238 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\KlicktippPhpClient\tests\unit\Entities; + +use D3\KlicktippPhpClient\Entities\Subscription; +use D3\KlicktippPhpClient\Exceptions\InvalidCredentialTypeException; +use D3\KlicktippPhpClient\Resources\SubscriptionProcess as SubscriptionEndpoint; +use D3\KlicktippPhpClient\tests\TestCase; +use Generator; +use PHPUnit\Framework\MockObject\Rule\InvokedCount; +use ReflectionException; + +/** + * @covers \D3\KlicktippPhpClient\Entities\Subscriber + */ +class SubscriptionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + $this->entity = new Subscription( + [ + SubscriptionEndpoint::LISTID => "368370", + SubscriptionEndpoint::NAME => "subscriptionName", + SubscriptionEndpoint::PENDINGURL => "pendingFixture", + SubscriptionEndpoint::THANKYOUURL => "thankyouFixture", + SubscriptionEndpoint::USE_SINGLE_OPTIN => true, + SubscriptionEndpoint::RESEND_CONFIRMATION_EMAIL => false, + SubscriptionEndpoint::USE_CHANGE_EMAIL => false, + + ] + ); + } + + /** + * @test + * @throws ReflectionException + * @covers \D3\KlicktippPhpClient\Entities\Subscription::__construct + */ + public function testConstruct(): void + { + $elements = [ + 'key1' => 'value1', + 'key2' => 'value2', + ]; + + $endpoint = $this->getMockBuilder(SubscriptionEndpoint::class) + ->disableOriginalConstructor() + ->getMock(); + + $sut = new Subscription($elements, $endpoint); + + $this->assertSame( + $elements, + $sut->toArray() + ); + $this->assertSame( + $endpoint, + $this->getValue($sut, 'endpoint') + ); + } + + /** + * @test + * @throws ReflectionException + * @covers \D3\KlicktippPhpClient\Entities\Subscription::getListId + * @covers \D3\KlicktippPhpClient\Entities\Subscription::getName + * @covers \D3\KlicktippPhpClient\Entities\Subscription::getPendingUrl + * @covers \D3\KlicktippPhpClient\Entities\Subscription::getThankyouUrl + * @covers \D3\KlicktippPhpClient\Entities\Subscription::useSingleOptin + * @covers \D3\KlicktippPhpClient\Entities\Subscription::useDoubleOptin + * @covers \D3\KlicktippPhpClient\Entities\Subscription::resendConfirmationEmail + * @covers \D3\KlicktippPhpClient\Entities\Subscription::useChangeEmail + * @dataProvider getDataProvider + */ + public function testGet(string $methodName, bool|string $expectedValue): void + { + $this->assertSame( + $expectedValue, + $this->callMethod($this->entity, $methodName) + ); + } + + /** + * @test + * @throws ReflectionException + * @covers \D3\KlicktippPhpClient\Entities\Subscription::getListId + * @covers \D3\KlicktippPhpClient\Entities\Subscription::getName + * @covers \D3\KlicktippPhpClient\Entities\Subscription::getPendingUrl + * @covers \D3\KlicktippPhpClient\Entities\Subscription::getThankyouUrl + * @covers \D3\KlicktippPhpClient\Entities\Subscription::useSingleOptin + * @covers \D3\KlicktippPhpClient\Entities\Subscription::useDoubleOptin + * @covers \D3\KlicktippPhpClient\Entities\Subscription::resendConfirmationEmail + * @covers \D3\KlicktippPhpClient\Entities\Subscription::useChangeEmail + * @dataProvider getDataProvider + */ + public function testGetNull(string $testMethod): void + { + $nullProperties = []; + foreach (array_keys($this->entity->toArray()) as $key) { + $nullProperties[$key] = null; + } + + $sut = new Subscription($nullProperties); + + $this->assertNull( + $this->callMethod( + $sut, + $testMethod, + ) + ); + } + + /** + * @test + * @throws ReflectionException + * @covers \D3\KlicktippPhpClient\Entities\Subscription::getListId + * @covers \D3\KlicktippPhpClient\Entities\Subscription::getName + * @covers \D3\KlicktippPhpClient\Entities\Subscription::getPendingUrl + * @covers \D3\KlicktippPhpClient\Entities\Subscription::getThankyouUrl + * @covers \D3\KlicktippPhpClient\Entities\Subscription::useSingleOptin + * @covers \D3\KlicktippPhpClient\Entities\Subscription::useDoubleOptin + * @covers \D3\KlicktippPhpClient\Entities\Subscription::resendConfirmationEmail + * @covers \D3\KlicktippPhpClient\Entities\Subscription::useChangeEmail + * @dataProvider getDataProvider + */ + public function testGetInvalid(string $testMethod): void + { + $invalidProperties = [ + SubscriptionEndpoint::LISTID => [], + SubscriptionEndpoint::NAME => [], + SubscriptionEndpoint::PENDINGURL => false, + SubscriptionEndpoint::THANKYOUURL => [], + SubscriptionEndpoint::USE_SINGLE_OPTIN => "string", + SubscriptionEndpoint::RESEND_CONFIRMATION_EMAIL => [], + SubscriptionEndpoint::USE_CHANGE_EMAIL => 'string', + ]; + + $sut = new Subscription($invalidProperties); + + $this->expectException(InvalidCredentialTypeException::class); + + $this->assertNull( + $this->callMethod( + $sut, + $testMethod, + ) + ); + } + + public static function getDataProvider(): Generator + { + yield ['getListId', '368370']; + yield ['getName', 'subscriptionName']; + yield ['getPendingUrl', 'pendingFixture']; + yield ['getThankyouUrl', 'thankyouFixture']; + yield ['useSingleOptin', true]; + yield ['useDoubleOptin', false]; + yield ['resendConfirmationEmail', false]; + yield ['useChangeEmail', false]; + } + + /** + * @test + * @throws ReflectionException + * @covers \D3\KlicktippPhpClient\Entities\Subscription::setName + */ + public function testSetname(): void { + $sut = $this->getMockBuilder(Subscription::class) + ->onlyMethods(['set']) + ->setConstructorArgs([[SubscriptionEndpoint::LISTID => 'foo']]) + ->getMock(); + $sut->expects($this->once())->method('set')->with( + $this->identicalTo(SubscriptionEndpoint::NAME) + ); + + $this->callMethod( + $sut, + "setName", + ['newValue'] + ); + } + + /** + * @test + * @throws ReflectionException + * @covers \D3\KlicktippPhpClient\Entities\Subscription::persist + * @dataProvider persistDataProvider + */ + public function testPersist( + bool $endpointSet, + InvokedCount $endpointInvocation, + ?bool $expectedReturn + ): void { + $endpointMock = $this->getMockBuilder(SubscriptionEndpoint::class) + ->disableOriginalConstructor() + ->onlyMethods(['update']) + ->getMock(); + $endpointMock->expects($endpointInvocation)->method('update')->with( + $this->identicalTo('foo'), + $this->identicalTo('bar'), + )->willReturn(true); + + $sut = new Subscription( + [SubscriptionEndpoint::LISTID => 'foo', SubscriptionEndpoint::NAME => 'bar'], + $endpointSet ? $endpointMock : null + ); + + $this->assertSame( + $expectedReturn, + $this->callMethod( + $sut, + 'persist' + ) + ); + } + + public static function persistDataProvider(): Generator + { + yield 'has endpoint' => [true, self::once(), true]; + yield 'has no endpoint' => [false, self::never(), null]; + } +}