testGivenValidPersonalDonationUuid_addressChangeIsReturned()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 7
nc 1
nop 0
dl 0
loc 10
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\Fundraising\AddressChangeContext\Tests\Unit\DataAccess;
6
7
use Doctrine\ORM\EntityManager;
8
use PHPUnit\Framework\Attributes\CoversClass;
0 ignored issues
show
Bug introduced by
The type PHPUnit\Framework\Attributes\CoversClass was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use PHPUnit\Framework\TestCase;
10
use WMDE\Fundraising\AddressChangeContext\DataAccess\DoctrineAddressChangeRepository;
11
use WMDE\Fundraising\AddressChangeContext\Domain\Model\Address;
12
use WMDE\Fundraising\AddressChangeContext\Domain\Model\AddressChange;
13
use WMDE\Fundraising\AddressChangeContext\Domain\Model\AddressChangeBuilder;
14
use WMDE\Fundraising\AddressChangeContext\Domain\Model\AddressChangeId;
15
use WMDE\Fundraising\AddressChangeContext\Tests\TestEnvironment;
16
17
#[CoversClass( DoctrineAddressChangeRepository::class )]
18
class DoctrineAddressChangeRepositoryTest extends TestCase {
19
20
	private const VALID_UPDATE_TOKEN_PERSONAL_DONATION = '2a54c0a1-fc94-4ef8-8b0a-7c2ed8565521';
21
	private const VALID_UPDATE_TOKEN_COMPANY_DONATION = 'c52258ba-fed1-476a-a7e5-c721df087c12';
22
	private const INVALID_UPDATE_TOKEN = '72dfed91-fa40-4af0-9e80-c6010ab29cd1';
23
	private const DUMMY_DONATION_ID = 0;
24
25
	/** @var EntityManager */
26
	private $em;
27
28
	public function setUp(): void {
29
		$this->em = TestEnvironment::newInstance()->getEntityManager();
30
		parent::setUp();
31
	}
32
33
	public function testGivenValidPersonalDonationUuid_addressChangeIsReturned(): void {
34
		$this->storeAddressChange( self::VALID_UPDATE_TOKEN_PERSONAL_DONATION, true );
35
		$retrievedAddressChange = $this->retrieveAddressChangeByUuid( self::VALID_UPDATE_TOKEN_PERSONAL_DONATION );
36
37
		$this->assertNotNull( $retrievedAddressChange );
38
		$this->assertSame(
39
			self::VALID_UPDATE_TOKEN_PERSONAL_DONATION,
40
			$retrievedAddressChange->getCurrentIdentifier()->__toString()
41
		);
42
		$this->assertTrue( $retrievedAddressChange->isPersonalAddress() );
43
	}
44
45
	public function testGivenValidCompanyDonationUuid_addressChangeIsReturned(): void {
46
		$this->storeAddressChange( self::VALID_UPDATE_TOKEN_COMPANY_DONATION, false );
47
		$retrievedAddressChange = $this->retrieveAddressChangeByUuid( self::VALID_UPDATE_TOKEN_COMPANY_DONATION );
48
49
		$this->assertNotNull( $retrievedAddressChange );
50
		$this->assertSame(
51
			self::VALID_UPDATE_TOKEN_COMPANY_DONATION,
52
			$retrievedAddressChange->getCurrentIdentifier()->__toString()
53
		);
54
		$this->assertTrue( $retrievedAddressChange->isCompanyAddress() );
55
	}
56
57
	public function testGivenInvalidDonationUuid_nullIsReturned(): void {
58
		$addressChangeRepository = new DoctrineAddressChangeRepository( $this->em );
59
		$addressChange = $addressChangeRepository->getAddressChangeByUuid( self::INVALID_UPDATE_TOKEN );
60
		$this->assertNull( $addressChange );
61
	}
62
63
	public function testGivenAddressChangeWithAddress_itIsStoredCorrectly(): void {
64
		$donationId = 99;
65
		$addressChangeRepository = new DoctrineAddressChangeRepository( $this->em );
66
		$addressChange = AddressChangeBuilder::create( null, $this->newPersonalAddress() )->forPerson()->forDonation( $donationId )->build();
67
		$addressChangeRepository->storeAddressChange( $addressChange );
68
		$now = new \DateTime();
69
70
		$this->em->clear();
71
		$retrievedAddressChange = $addressChangeRepository->getAddressChangeByUuid( (string)$addressChange->getCurrentIdentifier() );
72
		$this->assertNotNull( $retrievedAddressChange );
73
		$this->assertNotNull( $retrievedAddressChange->getAddress() );
74
		// avoid PHPStan errors when accessing address later
75
		$this->assertNotNull( $addressChange->getAddress() );
76
		$this->assertTrue( $retrievedAddressChange->isPersonalAddress() );
77
		$this->assertSame( $donationId, $retrievedAddressChange->getExternalId() );
78
		$this->assertSame( AddressChange::EXTERNAL_ID_TYPE_DONATION, $retrievedAddressChange->getExternalIdType() );
79
		$this->assertFalse( $retrievedAddressChange->isExported() );
80
		$this->assertDatePropertyIsSet( $now, $retrievedAddressChange, 'createdAt' );
0 ignored issues
show
Bug introduced by
It seems like $retrievedAddressChange can also be of type null; however, parameter $addressChange of WMDE\Fundraising\Address...sertDatePropertyIsSet() does only seem to accept WMDE\Fundraising\Address...ain\Model\AddressChange, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

80
		$this->assertDatePropertyIsSet( $now, /** @scrutinizer ignore-type */ $retrievedAddressChange, 'createdAt' );
Loading history...
81
		$this->assertDatePropertyIsSet( $now, $retrievedAddressChange, 'modifiedAt' );
82
		$this->assertEquals( $addressChange->getCurrentIdentifier(), $retrievedAddressChange->getCurrentIdentifier() );
83
		$this->assertNotNull( $retrievedAddressChange->getAddress() );
84
		$this->assertSame( $addressChange->getAddress()->getLastName(), $retrievedAddressChange->getAddress()->getLastName() );
85
	}
86
87
	public function testGivenAddressChangeWithReceiptOptIn_optInIsStoredCorrectly(): void {
88
		$addressChangeRepository = new DoctrineAddressChangeRepository( $this->em );
89
		$addressChange = AddressChangeBuilder::create()->forCompany()->forDonation( self::DUMMY_DONATION_ID )->build();
90
		$addressChangeRepository->storeAddressChange( $addressChange );
91
92
		$this->em->clear();
93
		$retrievedAddressChange = $addressChangeRepository->getAddressChangeByUuid( (string)$addressChange->getCurrentIdentifier() );
94
		$this->assertNotNull( $retrievedAddressChange );
95
		$this->assertTrue( $retrievedAddressChange->isOptedIntoDonationReceipt() );
96
	}
97
98
	public function testGivenAddressChangeWithReceiptOptOut_optOutIsStoredCorrectly(): void {
99
		$addressChangeRepository = new DoctrineAddressChangeRepository( $this->em );
100
		$addressChange = AddressChangeBuilder::create()->forCompany()->forDonation( self::DUMMY_DONATION_ID )->build();
101
		$addressChange->optOutOfDonationReceipt( AddressChangeId::fromString( AddressChangeBuilder::generateUuid() ) );
102
		$addressChangeRepository->storeAddressChange( $addressChange );
103
104
		$this->em->clear();
105
		$retrievedAddressChange = $addressChangeRepository->getAddressChangeByUuid( (string)$addressChange->getCurrentIdentifier() );
106
		$this->assertNotNull( $retrievedAddressChange );
107
		$this->assertFalse( $retrievedAddressChange->isOptedIntoDonationReceipt() );
108
	}
109
110
	public function testGivenExportedAddressChange_itsStateIsStoredCorrectly(): void {
111
		$addressChangeRepository = new DoctrineAddressChangeRepository( $this->em );
112
		$addressChange = AddressChangeBuilder::create( null, $this->newPersonalAddress() )->forPerson()->forDonation( self::DUMMY_DONATION_ID )->build();
113
		$addressChange->markAsExported();
114
		$addressChangeRepository->storeAddressChange( $addressChange );
115
		$now = new \DateTime();
116
117
		$this->em->clear();
118
		$retrievedAddressChange = $addressChangeRepository->getAddressChangeByUuid( (string)$addressChange->getCurrentIdentifier() );
119
		$this->assertNotNull( $retrievedAddressChange );
120
		$this->assertTrue( $retrievedAddressChange->isExported() );
121
		$this->assertDatePropertyIsSet( $now, $retrievedAddressChange, 'exportDate' );
0 ignored issues
show
Bug introduced by
It seems like $retrievedAddressChange can also be of type null; however, parameter $addressChange of WMDE\Fundraising\Address...sertDatePropertyIsSet() does only seem to accept WMDE\Fundraising\Address...ain\Model\AddressChange, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

121
		$this->assertDatePropertyIsSet( $now, /** @scrutinizer ignore-type */ $retrievedAddressChange, 'exportDate' );
Loading history...
122
	}
123
124
	public function testWhenQueriedByMultipleUuids_andGivenValidPreviousUuid_addressChangeIsReturned(): void {
125
		$addressChangeRepository = new DoctrineAddressChangeRepository( $this->em );
126
		$addressChange = AddressChangeBuilder::create(
127
			AddressChangeId::fromString( self::VALID_UPDATE_TOKEN_PERSONAL_DONATION ),
128
			$this->newPersonalAddress()
129
		)->forPerson()->forDonation( self::DUMMY_DONATION_ID )->build();
130
		$addressChangeRepository->storeAddressChange( $addressChange );
131
132
		$this->assertNotNull( $addressChange->getPreviousIdentifier() );
133
		$retrievedAddressChange = $addressChangeRepository->getAddressChangeByUuids(
134
			self::INVALID_UPDATE_TOKEN,
135
			$addressChange->getPreviousIdentifier()->__toString()
136
		);
137
138
		$this->assertNotNull( $retrievedAddressChange );
139
		$this->assertSame(
140
			self::VALID_UPDATE_TOKEN_PERSONAL_DONATION,
141
			$retrievedAddressChange->getCurrentIdentifier()->__toString()
142
		);
143
	}
144
145
	public function testWhenQueriedByMultipleUuids_andGivenValidCurrentUuid_addressChangeIsReturned(): void {
146
		$addressChangeRepository = new DoctrineAddressChangeRepository( $this->em );
147
		$addressChange = AddressChangeBuilder::create(
148
			AddressChangeId::fromString( self::VALID_UPDATE_TOKEN_PERSONAL_DONATION ),
149
			$this->newPersonalAddress()
150
		)->forPerson()->forDonation( self::DUMMY_DONATION_ID )->build();
151
		$addressChangeRepository->storeAddressChange( $addressChange );
152
153
		$retrievedAddressChange = $addressChangeRepository->getAddressChangeByUuids(
154
			$addressChange->getCurrentIdentifier()->__toString(),
155
			self::INVALID_UPDATE_TOKEN
156
		);
157
158
		$this->assertNotNull( $retrievedAddressChange );
159
		$this->assertSame(
160
			self::VALID_UPDATE_TOKEN_PERSONAL_DONATION,
161
			$retrievedAddressChange->getCurrentIdentifier()->__toString()
162
		);
163
	}
164
165
	public function testWhenQueriedByMultipleUuids_andGivenInvalidDonationUuids_nullIsReturned(): void {
166
		$addressChange = ( new DoctrineAddressChangeRepository( $this->em ) )->getAddressChangeByUuids(
167
			self::INVALID_UPDATE_TOKEN,
168
			self::INVALID_UPDATE_TOKEN
169
		);
170
171
		$this->assertNull( $addressChange );
172
	}
173
174
	private function storeAddressChange( string $uuid, bool $isPersonal = true ): void {
175
		if ( $isPersonal ) {
176
			$addressChange = AddressChangeBuilder::create(
177
				AddressChangeId::fromString( $uuid ),
178
				$this->newPersonalAddress()
179
			)
180
				->forPerson()
181
				->forDonation( self::DUMMY_DONATION_ID )
182
				->build();
183
		} else {
184
			$addressChange = AddressChangeBuilder::create(
185
				AddressChangeId::fromString( $uuid ),
186
				$this->newCompanyAddress()
187
			)
188
				->forCompany()
189
				->forDonation( self::DUMMY_DONATION_ID )
190
				->build();
191
		}
192
		$this->em->persist( $addressChange );
193
		$this->em->flush();
194
		$this->em->clear();
195
	}
196
197
	private function retrieveAddressChangeByUuid( string $uuid ): ?AddressChange {
198
		$addressChangeRepository = new DoctrineAddressChangeRepository( $this->em );
199
		return $addressChangeRepository->getAddressChangeByUuid(
200
			$uuid
201
		);
202
	}
203
204
	private function newPersonalAddress(): Address {
205
		return Address::newPersonalAddress(
206
			'Herr',
207
			'Prof. Dr.',
208
			'Test',
209
			'User',
210
			'Teststreet 12345',
211
			'98765',
212
			'Berlin',
213
			'Germany'
214
		);
215
	}
216
217
	private function newCompanyAddress(): Address {
218
		return Address::newCompanyAddress(
219
			'Test Company',
220
			'Teststreet 123',
221
			'324324',
222
			'Not Berlin',
223
			'Somewhere'
224
		);
225
	}
226
227
	private function assertDatePropertyIsSet( \DateTimeInterface $expectedDate, AddressChange $addressChange, string $propertyName, float $delta = 1.0 ): void {
228
		// We're peeking into private properties to make sure the dates, which are not exposed through getters at the domain level,
229
		// are properly written at the DB level
230
		$dateField = new \ReflectionProperty( AddressChange::class, $propertyName );
231
		$dateField->setAccessible( true );
232
		$actualDate = $dateField->getValue( $addressChange );
233
		$this->assertInstanceOf( \DateTimeInterface::class, $actualDate );
234
		$this->assertEqualsWithDelta( $actualDate->getTimestamp(), $expectedDate->getTimestamp(), $delta, 'Dates do not match.' );
235
	}
236
}
237