From e4699d4d1932aa06836cea1d214955beea5a311b Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Wed, 4 Jan 2023 01:08:35 +0100 Subject: [PATCH] add tests for UserRecipients class --- src/Application/Model/UserRecipients.php | 58 +++-- src/Config/linkmobility4oxid.yaml | 16 +- src/Config/linkmobilityphpclient.yaml | 40 +++ src/Config/oxid.yaml | 8 + src/Config/packages.yaml | 28 +++ src/Config/services.yaml | 2 + src/Modules/LinkmobilityServices.php | 6 +- .../Application/Model/UserRecipientsTest.php | 237 ++++++++++++++++++ .../unit/Modules/LinkMobilityServicesTest.php | 3 +- 9 files changed, 376 insertions(+), 22 deletions(-) create mode 100644 src/Config/linkmobilityphpclient.yaml create mode 100644 src/Config/packages.yaml create mode 100644 src/tests/unit/Application/Model/UserRecipientsTest.php diff --git a/src/Application/Model/UserRecipients.php b/src/Application/Model/UserRecipients.php index def0a47..2e5c3a8 100644 --- a/src/Application/Model/UserRecipients.php +++ b/src/Application/Model/UserRecipients.php @@ -28,7 +28,7 @@ class UserRecipients /** * @var User */ - private $user; + protected $user; public function __construct(User $user) { @@ -42,36 +42,56 @@ class UserRecipients public function getSmsRecipient(): Recipient { foreach ($this->getSmsRecipientFields() as $fieldName) { - /** @var string $content */ - $content = $this->user->getFieldData($fieldName) ?: ''; - $content = trim($content); - $country = oxNew(Country::class); - - try { - if (strlen($content)) { - /** @var string $countryId */ - $countryId = $this->user->getFieldData('oxcountryid'); - $country->load($countryId); - return oxNew(Recipient::class, $content, $country->getFieldData('oxisoalpha2')); - } - } catch (NumberParseException $e) { - LoggerHandler::getInstance()->getLogger()->info($e->getMessage(), [$content, $country->getFieldData('oxisoalpha2')]); - } catch (RecipientException $e) { - LoggerHandler::getInstance()->getLogger()->info($e->getMessage(), [$content, $country->getFieldData('oxisoalpha2')]); + if ($recipient = $this->getSmsRecipientByField($fieldName)) { + return $recipient; } } /** @var noRecipientFoundException $exc */ - $exc = oxNew(noRecipientFoundException::class); + $exc = d3GetOxidDIC()->get(noRecipientFoundException::class); throw $exc; } + /** + * @param $fieldName + * @return Recipient|null + */ + protected function getSmsRecipientByField($fieldName): ?Recipient + { + try { + /** @var string $content */ + $content = $this->user->getFieldData($fieldName) ?: ''; + $content = trim($content); + + if (strlen($content)) { + $country = d3GetOxidDIC()->get('d3ox.linkmobility.'.Country::class); + /** @var string $countryId */ + $countryId = $this->user->getFieldData('oxcountryid'); + $country->load($countryId); + d3GetOxidDIC()->setParameter(Recipient::class.'.args.number', $content); + d3GetOxidDIC()->setParameter(Recipient::class.'.args.iso2countrycode', $country->getFieldData('oxisoalpha2')); + /** @var Recipient $recipient */ + $recipient = d3GetOxidDIC()->get(Recipient::class); + return $recipient; + } + } catch (NumberParseException|RecipientException $e) { + d3GetOxidDIC()->get(LoggerHandler::class)->getLogger()->info( + $e->getMessage(), + [$content, $country->getFieldData('oxisoalpha2')] + ); + } + + return null; + } + /** * @return string[] */ public function getSmsRecipientFields(): array { - $customFields = (oxNew(Configuration::class))->getUserRecipientFields(); + /** @var Configuration $configuration */ + $configuration = d3GetOxidDIC()->get(Configuration::class); + $customFields = $configuration->getUserRecipientFields(); return count($customFields) ? $customFields : diff --git a/src/Config/linkmobility4oxid.yaml b/src/Config/linkmobility4oxid.yaml index 7da244b..7ee6a6e 100644 --- a/src/Config/linkmobility4oxid.yaml +++ b/src/Config/linkmobility4oxid.yaml @@ -38,6 +38,13 @@ services: synthetic: true shared: false + D3\Linkmobility4OXID\Application\Model\Configuration: + class: D3\Linkmobility4OXID\Application\Model\Configuration + factory: 'oxNew' + shared: true + arguments: + - D3\Linkmobility4OXID\Application\Model\Configuration + D3\Linkmobility4OXID\Application\Model\MessageTypes\Sms: class: D3\Linkmobility4OXID\Application\Model\MessageTypes\Sms factory: 'oxNew' @@ -52,4 +59,11 @@ services: shared: false arguments: - D3\Linkmobility4OXID\Application\Model\Exceptions\successfullySentException - - '%D3\Linkmobility4OXID\Application\Model\Exceptions\successfullySentException.args.smscount%' \ No newline at end of file + - '%D3\Linkmobility4OXID\Application\Model\Exceptions\successfullySentException.args.smscount%' + + D3\Linkmobility4OXID\Application\Model\Exceptions\noRecipientFoundException: + class: D3\Linkmobility4OXID\Application\Model\Exceptions\noRecipientFoundException + factory: 'oxNew' + shared: false + arguments: + - D3\Linkmobility4OXID\Application\Model\Exceptions\noRecipientFoundException \ No newline at end of file diff --git a/src/Config/linkmobilityphpclient.yaml b/src/Config/linkmobilityphpclient.yaml new file mode 100644 index 0000000..548b971 --- /dev/null +++ b/src/Config/linkmobilityphpclient.yaml @@ -0,0 +1,40 @@ +# For the full copyright and license information, please view the LICENSE +# file that was distributed with this source code. +# +# https://www.d3data.de +# +# @copyright (C) D3 Data Development (Inh. Thomas Dartsch) +# @author D3 Data Development - Daniel Seifert +# @link https://www.oxidmodule.com + +parameters: + D3\LinkmobilityClient\ValueObject\Recipient.args.number: + D3\LinkmobilityClient\ValueObject\Recipient.args.iso2countrycode: + +services: + _defaults: + autowire: false + public: true + + D3\LinkmobilityClient\LoggerHandler: + class: D3\LinkmobilityClient\LoggerHandler + factory: + - 'D3\LinkmobilityClient\LoggerHandler' + - 'getInstance' + shared: true + + D3\LinkmobilityClient\ValueObject\Recipient: + class: D3\LinkmobilityClient\ValueObject\Recipient + factory: 'oxNew' + shared: false + arguments: + - D3\LinkmobilityClient\ValueObject\Recipient + - '%D3\LinkmobilityClient\ValueObject\Recipient.args.number%' + - '%D3\LinkmobilityClient\ValueObject\Recipient.args.iso2countrycode%' + + D3\LinkmobilityClient\Exceptions\RecipientException: + class: D3\LinkmobilityClient\Exceptions\RecipientException + factory: 'oxNew' + shared: false + arguments: + - D3\LinkmobilityClient\Exceptions\RecipientException \ No newline at end of file diff --git a/src/Config/oxid.yaml b/src/Config/oxid.yaml index 36646a0..c716851 100644 --- a/src/Config/oxid.yaml +++ b/src/Config/oxid.yaml @@ -48,4 +48,12 @@ services: factory: 'oxNew' arguments: - 'OxidEsales\Eshop\Application\Model\User' + shared: false + + # Country + d3ox.linkmobility.OxidEsales\Eshop\Application\Model\Country: + class: 'OxidEsales\Eshop\Application\Model\Country' + factory: 'oxNew' + arguments: + - 'OxidEsales\Eshop\Application\Model\Country' shared: false \ No newline at end of file diff --git a/src/Config/packages.yaml b/src/Config/packages.yaml new file mode 100644 index 0000000..2945639 --- /dev/null +++ b/src/Config/packages.yaml @@ -0,0 +1,28 @@ +# For the full copyright and license information, please view the LICENSE +# file that was distributed with this source code. +# +# https://www.d3data.de +# +# @copyright (C) D3 Data Development (Inh. Thomas Dartsch) +# @author D3 Data Development - Daniel Seifert +# @link https://www.oxidmodule.com + +parameters: + libphonenumber\NumberParseException.args.errorType: + libphonenumber\NumberParseException.args.message: + libphonenumber\NumberParseException.args.previous: + +services: + _defaults: + autowire: false + public: true + + libphonenumber\NumberParseException: + class: libphonenumber\NumberParseException + factory: 'oxNew' + shared: false + arguments: + - libphonenumber\NumberParseException + - '%libphonenumber\NumberParseException.args.errorType%' + - '%libphonenumber\NumberParseException.args.message%' + - '%libphonenumber\NumberParseException.args.previous%' \ No newline at end of file diff --git a/src/Config/services.yaml b/src/Config/services.yaml index 91fa523..46da037 100644 --- a/src/Config/services.yaml +++ b/src/Config/services.yaml @@ -9,7 +9,9 @@ imports: - { resource: php.yaml } + - { resource: packages.yaml } - { resource: oxid.yaml } + - { resource: linkmobilityphpclient.yaml } - { resource: linkmobility4oxid.yaml } diff --git a/src/Modules/LinkmobilityServices.php b/src/Modules/LinkmobilityServices.php index e8248a9..4e8c997 100644 --- a/src/Modules/LinkmobilityServices.php +++ b/src/Modules/LinkmobilityServices.php @@ -15,11 +15,15 @@ declare(strict_types=1); namespace D3\Linkmobility4OXID\Modules; +use D3\TestingTools\Production\IsMockable; + class LinkmobilityServices extends LinkmobilityServices_parent { + use IsMockable; + public function __construct() { - parent::__construct(); + $this->d3CallMockableFunction([LinkmobilityServices_parent::class, '__construct']); $this->addYamlDefinitions('d3/linkmobility/Config/services.yaml'); } } \ No newline at end of file diff --git a/src/tests/unit/Application/Model/UserRecipientsTest.php b/src/tests/unit/Application/Model/UserRecipientsTest.php new file mode 100644 index 0000000..b085e5e --- /dev/null +++ b/src/tests/unit/Application/Model/UserRecipientsTest.php @@ -0,0 +1,237 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\Linkmobility4OXID\tests\unit\Application\Model; + +use D3\Linkmobility4OXID\Application\Model\Configuration; +use D3\Linkmobility4OXID\Application\Model\Exceptions\noRecipientFoundException; +use D3\Linkmobility4OXID\Application\Model\UserRecipients; +use D3\Linkmobility4OXID\tests\unit\LMUnitTestCase; +use D3\LinkmobilityClient\Exceptions\RecipientException; +use D3\LinkmobilityClient\ValueObject\Recipient; +use D3\TestingTools\Development\CanAccessRestricted; +use libphonenumber\NumberParseException; +use OxidEsales\Eshop\Application\Model\Country; +use OxidEsales\Eshop\Application\Model\User; +use PHPUnit\Framework\MockObject\MockObject; +use ReflectionException; + +class UserRecipientsTest extends LMUnitTestCase +{ + use CanAccessRestricted; + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\Linkmobility4OXID\Application\Model\UserRecipients::__construct + */ + public function canConstruct() + { + /** @var User|MockObject $userMock */ + $userMock = $this->getMockBuilder(User::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var UserRecipients|MockObject $sut */ + $sut = $this->getMockBuilder(UserRecipients::class) + ->setConstructorArgs([$userMock]) + ->getMock(); + + $this->assertSame( + $userMock, + $this->getValue( + $sut, + 'user' + ) + ); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @dataProvider canGetSmsRecipientDataProvider + * @covers \D3\Linkmobility4OXID\Application\Model\UserRecipients::getSmsRecipient + */ + public function canGetSmsRecipient($hasRecipient) + { + /** @var Recipient|MockObject $recipient1Mock */ + $recipient1Mock = $this->getMockBuilder(Recipient::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var Recipient|MockObject $recipient2Mock */ + $recipient2Mock = $this->getMockBuilder(Recipient::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var UserRecipients|MockObject $sut */ + $sut = $this->getMockBuilder(UserRecipients::class) + ->disableOriginalConstructor() + ->onlyMethods(['getSmsRecipientFields', 'getSmsRecipientByField']) + ->getMock(); + $sut->method('getSmsRecipientFields')->willReturn(['field1', 'field2', 'field3']); + $sut->expects($this->exactly($hasRecipient ? 2 : 3))->method('getSmsRecipientByField')->willReturnOnConsecutiveCalls( + null, + $hasRecipient ? $recipient1Mock : null, + $hasRecipient ? $recipient2Mock : null + ); + + if (!$hasRecipient) { + $this->expectException(noRecipientFoundException::class); + } + + $this->assertSame( + $recipient1Mock, + $this->callMethod( + $sut, + 'getSmsRecipient' + ) + ); + } + + /** + * @return array + */ + public function canGetSmsRecipientDataProvider(): array + { + return [ + 'has recipient' => [true], + 'has no recipient' => [false], + ]; + } + + /** + * @test + * @param $userFieldValue + * @param $expected + * @param $thrownExc + * @return void + * @throws ReflectionException + * @dataProvider canGetSmsRecipientByFieldDataProvider + * @covers \D3\Linkmobility4OXID\Application\Model\UserRecipients::getSmsRecipientByField + */ + public function canGetSmsRecipientByField($userFieldValue, $expected, $thrownExc) + { + /** @var Recipient|MockObject $recipientMock */ + $recipientMock = $this->getMockBuilder(Recipient::class) + ->disableOriginalConstructor() + ->getMock(); + d3GetOxidDIC()->set(Recipient::class, $recipientMock); + + /** @var Country|MockObject $countryMock */ + $countryMock = $this->getMockBuilder(Country::class) + ->onlyMethods(['load', 'getFieldData']) + ->getMock(); + $countryMock->method('load')->will( + $thrownExc ? + $this->throwException(d3GetOxidDIC()->get($thrownExc)) : + $this->returnValue(true) + ); + $countryMock->method('getFieldData')->willReturn('de'); + d3GetOxidDIC()->set('d3ox.linkmobility.'.Country::class, $countryMock); + + /** @var User|MockObject $userMock */ + $userMock = $this->getMockBuilder(User::class) + ->disableOriginalConstructor() + ->onlyMethods(['getFieldData']) + ->getMock(); + $userMock->method('getFieldData')->willReturnMap( + [ + ['fieldName', $userFieldValue], + ['oxcountryid', 'country_de'], + ] + ); + + /** @var UserRecipients|MockObject $sut */ + $sut = $this->getMockBuilder(UserRecipients::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->setValue( + $sut, + 'user', + $userMock + ); + + $this->assertSame( + $expected === 'recipientMock' ? $recipientMock : $expected, + $this->callMethod( + $sut, + 'getSmsRecipientByField', + ['fieldName'] + ) + ); + } + + /** + * @return array + */ + public function canGetSmsRecipientByFieldDataProvider(): array + { + return [ + 'has user field value no exc' => ['fieldContent', 'recipientMock', false], + 'spaced user field value' => [' ', null, false], + 'no user field value' => [null, null, false], + 'has user field value recexc' => ['fieldContent', null, RecipientException::class], + 'has user field value nmbexc' => ['fieldContent', null, NumberParseException::class], + ]; + } + + /** + * @test + * @param $configuredFields + * @param $expected + * @return void + * @throws ReflectionException + * @dataProvider canGetSmsRecipientFieldsDataProvider + * @covers \D3\Linkmobility4OXID\Application\Model\UserRecipients::getSmsRecipientFields + */ + public function canGetSmsRecipientFields($configuredFields, $expected) + { + /** @var Configuration|MockObject $configurationMock */ + $configurationMock = $this->getMockBuilder(Configuration::class) + ->onlyMethods(['getUserRecipientFields']) + ->getMock(); + $configurationMock->method('getUserRecipientFields')->willReturn($configuredFields); + d3GetOxidDIC()->set(Configuration::class, $configurationMock); + + /** @var UserRecipients|MockObject $sut */ + $sut = $this->getMockBuilder(UserRecipients::class) + ->disableOriginalConstructor() + ->onlyMethods(['__construct']) + ->getMock(); + + $this->assertSame( + $expected, + $this->callMethod( + $sut, + 'getSmsRecipientFields' + ) + ); + } + + /** + * @return array + */ + public function canGetSmsRecipientFieldsDataProvider(): array + { + return [ + 'fields configured' => [['field1', 'field2'], ['field1', 'field2']], + 'fields not configured' => [[], ['oxmobfon', 'oxfon', 'oxprivfon']], + ]; + } +} \ No newline at end of file diff --git a/src/tests/unit/Modules/LinkMobilityServicesTest.php b/src/tests/unit/Modules/LinkMobilityServicesTest.php index 7c0f019..3f4e9c8 100644 --- a/src/tests/unit/Modules/LinkMobilityServicesTest.php +++ b/src/tests/unit/Modules/LinkMobilityServicesTest.php @@ -36,11 +36,12 @@ class LinkMobilityServicesTest extends LMUnitTestCase /** @var LinkmobilityServices|MockObject $sut */ $sut = $this->getMockBuilder(LinkmobilityServices::class) ->disableOriginalConstructor() - ->onlyMethods(['addYamlDefinitions']) + ->onlyMethods(['addYamlDefinitions', 'd3CallMockableFunction']) ->getMock(); $sut->expects($this->atLeastOnce())->method('addYamlDefinitions')->with( $this->identicalTo('d3/linkmobility/Config/services.yaml') ); + $sut->method('d3CallMockableFunction')->willReturn(true); $this->callMethod( $sut,