Completed
Push — master ( 25648a...558e7e )
by Jeroen De
14s
created

testWhenDonationDoesNotExist_persistingCausesException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 0
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\Fundraising\Frontend\DonationContext\Tests\Integration\DataAccess;
6
7
use Doctrine\ORM\EntityManager;
8
use PHPUnit\Framework\TestCase;
9
use WMDE\Fundraising\Entities\Donation as DoctrineDonation;
10
use WMDE\Fundraising\Frontend\DonationContext\DataAccess\DoctrineDonationRepository;
11
use WMDE\Fundraising\Frontend\DonationContext\Domain\Model\Donation;
12
use WMDE\Fundraising\Frontend\DonationContext\Domain\Repositories\GetDonationException;
13
use WMDE\Fundraising\Frontend\DonationContext\Domain\Repositories\StoreDonationException;
14
use WMDE\Fundraising\Frontend\DonationContext\Tests\Data\IncompleteDoctrineDonation;
15
use WMDE\Fundraising\Frontend\DonationContext\Tests\Data\ValidDoctrineDonation;
16
use WMDE\Fundraising\Frontend\DonationContext\Tests\Data\ValidDonation;
17
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\BankTransferPayment;
18
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\CreditCardPayment;
19
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\DirectDebitPayment;
20
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\PayPalPayment;
21
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\SofortPayment;
22
use WMDE\Fundraising\Frontend\Tests\Fixtures\ThrowingEntityManager;
23
use WMDE\Fundraising\Frontend\Tests\TestEnvironment;
24
25
/**
26
 * @covers \WMDE\Fundraising\Frontend\DonationContext\DataAccess\DoctrineDonationRepository
27
 *
28
 * @licence GNU GPL v2+
29
 * @author Jeroen De Dauw < [email protected] >
30
 */
31
class DoctrineDonationRepositoryTest extends TestCase {
32
33
	private const ID_OF_DONATION_NOT_IN_DB = 35505;
34
35
	/**
36
	 * @var EntityManager
37
	 */
38
	private $entityManager;
39
40
	public function setUp(): void {
41
		$factory = TestEnvironment::newInstance()->getFactory();
42
		$factory->disableDoctrineSubscribers();
43
		$this->entityManager = $factory->getEntityManager();
44
		parent::setUp();
45
	}
46
47
	public function testValidDonationGetPersisted(): void {
48
		$donation = ValidDonation::newDirectDebitDonation();
49
50
		$this->newRepository()->storeDonation( $donation );
51
52
		$expectedDoctrineEntity = ValidDoctrineDonation::newDirectDebitDoctrineDonation();
53
		$expectedDoctrineEntity->setId( $donation->getId() );
54
55
		$this->assertDoctrineEntityIsInDatabase( $expectedDoctrineEntity );
56
	}
57
58
	private function newRepository(): DoctrineDonationRepository {
59
		return new DoctrineDonationRepository( $this->entityManager );
60
	}
61
62
	private function assertDoctrineEntityIsInDatabase( DoctrineDonation $expected ): void {
63
		$actual = $this->getDoctrineDonationById( $expected->getId() );
64
65
		$this->assertNotNull( $actual->getCreationTime() );
66
		$actual->setCreationTime( null );
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a object<DateTime>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
67
68
		$this->assertEquals( $expected->getDecodedData(), $actual->getDecodedData() );
69
70
		$this->assertEquals( $expected, $actual );
71
	}
72
73
	private function getDoctrineDonationById( int $id ): DoctrineDonation {
74
		$donationRepo = $this->entityManager->getRepository( DoctrineDonation::class );
75
		$donation = $donationRepo->find( $id );
76
		$this->assertInstanceOf( DoctrineDonation::class, $donation );
77
		return $donation;
78
	}
79
80
	public function testWhenPersistenceFails_domainExceptionIsThrown(): void {
81
		$donation = ValidDonation::newDirectDebitDonation();
82
83
		$repository = new DoctrineDonationRepository( ThrowingEntityManager::newInstance( $this ) );
84
85
		$this->expectException( StoreDonationException::class );
86
		$repository->storeDonation( $donation );
87
	}
88
89
	public function testNewDonationPersistenceRoundTrip(): void {
90
		$donation = ValidDonation::newDirectDebitDonation();
91
92
		$repository = $this->newRepository();
93
94
		$repository->storeDonation( $donation );
95
96
		$this->assertEquals(
97
			$donation,
98
			$repository->getDonationById( $donation->getId() )
99
		);
100
	}
101
102
	public function testNewBankTransferPayment_persistingSavesBankTransferCode(): void {
103
		$donation = ValidDonation::newBankTransferDonation();
104
105
		$repository = $this->newRepository();
106
107
		$repository->storeDonation( $donation );
108
109
		$retrievedDonation = $repository->getDonationById( $donation->getId() );
110
		/**
111
		 * @var $payment BankTransferPayment
112
		 */
113
		$payment = $retrievedDonation->getPaymentMethod();
114
		$this->assertSame( ValidDonation::PAYMENT_BANK_TRANSFER_CODE, $payment->getBankTransferCode() );
115
	}
116
117
	public function testNewSofortPayment_persistingSavesBankTransferCode(): void {
118
		$donation = ValidDonation::newSofortDonation();
119
120
		$repository = $this->newRepository();
121
122
		$repository->storeDonation( $donation );
123
124
		$retrievedDonation = $repository->getDonationById( $donation->getId() );
125
		/**
126
		 * @var $payment SofortPayment
127
		 */
128
		$payment = $retrievedDonation->getPaymentMethod();
129
		$this->assertSame( ValidDonation::PAYMENT_BANK_TRANSFER_CODE, $payment->getBankTransferCode() );
130
	}
131
132
	public function testWhenDonationAlreadyExists_persistingCausesUpdate(): void {
133
		$repository = $this->newRepository();
134
135
		$donation = ValidDonation::newDirectDebitDonation();
136
		$repository->storeDonation( $donation );
137
138
		// It is important a new instance is created here to test "detached entity" handling
139
		$newDonation = ValidDonation::newDirectDebitDonation();
140
		$newDonation->assignId( $donation->getId() );
141
		$newDonation->cancel();
142
		$repository->storeDonation( $newDonation );
143
144
		$this->assertEquals( $newDonation, $repository->getDonationById( $newDonation->getId() ) );
145
	}
146
147
	public function testWhenDonationDoesNotExist_getDonationReturnsNull(): void {
148
		$repository = $this->newRepository();
149
150
		$this->assertNull( $repository->getDonationById( self::ID_OF_DONATION_NOT_IN_DB ) );
151
	}
152
153
	public function testWhenDoctrineThrowsException_domainExceptionIsThrown(): void {
154
		$repository = new DoctrineDonationRepository( ThrowingEntityManager::newInstance( $this ) );
155
156
		$this->expectException( GetDonationException::class );
157
		$repository->getDonationById( self::ID_OF_DONATION_NOT_IN_DB );
158
	}
159
160
	public function testWhenDonationDoesNotExist_persistingCausesException(): void {
161
		$donation = ValidDonation::newDirectDebitDonation();
162
		$donation->assignId( self::ID_OF_DONATION_NOT_IN_DB );
163
164
		$repository = $this->newRepository();
165
166
		$this->expectException( StoreDonationException::class );
167
		$repository->storeDonation( $donation );
168
	}
169
170
	public function testWhenDeletionDateGetsSet_repositoryNoLongerReturnsEntity(): void {
171
		$donation = $this->createDeletedDonation();
172
		$repository = $this->newRepository();
173
174
		$this->assertNull( $repository->getDonationById( $donation->getId() ) );
175
	}
176
177
	private function createDeletedDonation(): Donation {
178
		$donation = ValidDonation::newDirectDebitDonation();
179
		$repository = $this->newRepository();
180
		$repository->storeDonation( $donation );
181
		$doctrineDonation = $repository->getDoctrineDonationById( $donation->getId() );
182
		$doctrineDonation->setDeletionTime( new \DateTime() );
183
		$this->entityManager->flush();
184
		return $donation;
185
	}
186
187
	public function testWhenDeletionDateGetsSet_repositoryNoLongerPersistsEntity(): void {
188
		$donation = $this->createDeletedDonation();
189
		$repository = $this->newRepository();
190
191
		$this->expectException( StoreDonationException::class );
192
		$repository->storeDonation( $donation );
193
	}
194
195
	public function testDataFieldsAreRetainedOrUpdatedOnUpdate(): void {
196
		$doctrineDonation = $this->getNewlyCreatedDoctrineDonation();
197
198
		$doctrineDonation->encodeAndSetData( array_merge(
199
			$doctrineDonation->getDecodedData(),
200
			[
201
				'untouched' => 'value',
202
				'vorname' => 'potato',
203
				'another' => 'untouched',
204
			]
205
		) );
206
207
		$this->entityManager->flush();
208
209
		$donation = ValidDonation::newDirectDebitDonation();
210
		$donation->assignId( $doctrineDonation->getId() );
211
212
		$this->newRepository()->storeDonation( $donation );
213
214
		$data = $this->getDoctrineDonationById( $donation->getId() )->getDecodedData();
215
216
		$this->assertSame( 'value', $data['untouched'] );
217
		$this->assertNotSame( 'potato', $data['vorname'] );
218
		$this->assertSame( 'untouched', $data['another'] );
219
	}
220
221
	/**
222
	 * The backend application data purge script sets the personal information to empty strings
223
	 */
224
	public function testGivenPurgedDonationNoDonorIsCreated(): void {
225
		$doctrineDonation = $this->getNewlyCreatedDoctrineDonation();
226
		$doctrineDonation->setDtBackup( new \DateTime() );
227
		$this->entityManager->persist( $doctrineDonation );
228
		$this->entityManager->flush();
229
230
		$donation = $this->newRepository()->getDonationById( $doctrineDonation->getId() );
231
232
		$this->assertNull( $donation->getDonor() );
233
	}
234
235
	public function testGivenDonationUpdateWithoutDonorInformation_DonorNameStaysTheSame(): void {
236
		$donation = ValidDonation::newBookedPayPalDonation();
237
		$this->newRepository()->storeDonation( $donation );
238
239
		$anonymousDonation = ValidDonation::newBookedAnonymousPayPalDonationUpdate( $donation->getId() );
240
		$this->newRepository()->storeDonation( $anonymousDonation );
241
242
		$doctrineDonation = $this->getDoctrineDonationById( $donation->getId() );
243
244
		$this->assertSame( $donation->getDonor()->getName()->getFullName(), $doctrineDonation->getDonorFullName() );
245
	}
246
247
	private function getNewlyCreatedDoctrineDonation(): DoctrineDonation {
248
		$donation = ValidDonation::newDirectDebitDonation();
249
		$this->newRepository()->storeDonation( $donation );
250
		return $this->getDoctrineDonationById( $donation->getId() );
251
	}
252
253
	public function testCommentGetPersistedAndRetrieved(): void {
254
		$donation = ValidDonation::newDirectDebitDonation();
255
		$donation->addComment( ValidDonation::newPublicComment() );
256
257
		$repository = $this->newRepository();
258
		$repository->storeDonation( $donation );
259
260
		$retrievedDonation = $repository->getDonationById( $donation->getId() );
261
262
		$this->assertEquals( $donation, $retrievedDonation );
263
	}
264
265
	public function testPersistingDonationWithoutCommentCausesCommentToBeCleared(): void {
266
		$donation = ValidDonation::newDirectDebitDonation();
267
		$donation->addComment( ValidDonation::newPublicComment() );
268
269
		$repository = $this->newRepository();
270
		$repository->storeDonation( $donation );
271
272
		$newDonation = ValidDonation::newDirectDebitDonation();
273
		$newDonation->assignId( $donation->getId() );
274
275
		$repository->storeDonation( $newDonation );
276
277
		$expectedDoctrineEntity = ValidDoctrineDonation::newDirectDebitDoctrineDonation();
278
		$expectedDoctrineEntity->setId( $donation->getId() );
279
		$expectedDoctrineEntity->setComment( '' );
280
		$expectedDoctrineEntity->setIsPublic( false );
281
		$expectedDoctrineEntity->setPublicRecord( '' );
282
283
		$this->assertDoctrineEntityIsInDatabase( $expectedDoctrineEntity );
284
	}
285
286
	public function testDonationWithIncompletePaypalDataCanBeLoaded(): void {
287
		$donationId = $this->createPaypalDonationWithMissingFields();
288
		$repository = $this->newRepository();
289
		$donation = $repository->getDonationById( $donationId );
290
		/** @var PayPalPayment $paypalPayment */
291
		$paypalPayment = $donation->getPaymentMethod();
292
		$this->assertNotNull( $paypalPayment->getPayPalData() );
293
		$this->assertSame( '', $paypalPayment->getPayPalData()->getFirstName() );
294
	}
295
296
	private function createPaypalDonationWithMissingFields(): int {
297
		$doctrineDonation = IncompleteDoctrineDonation::newPaypalDonationWithMissingFields();
298
		$this->entityManager->persist( $doctrineDonation );
299
		$this->entityManager->flush();
300
		return $doctrineDonation->getId();
301
	}
302
303
	public function testDonationWithMissingTrackingInformationDataCanBeLoaded(): void {
304
		$donationId = $this->createPaypalDonationWithMissingTracking();
305
		$repository = $this->newRepository();
306
		$donation = $repository->getDonationById( $donationId );
307
		$info = $donation->getTrackingInfo();
308
		$this->assertNotNull( $info );
309
		$this->assertSame( '', $info->getColor() );
310
		$this->assertSame( 0, $info->getTotalImpressionCount() );
311
	}
312
313
	private function createPaypalDonationWithMissingTracking(): int {
314
		$doctrineDonation = IncompleteDoctrineDonation::newPaypalDonationWithMissingTrackingData();
315
		$this->entityManager->persist( $doctrineDonation );
316
		$this->entityManager->flush();
317
		return $doctrineDonation->getId();
318
	}
319
320
	public function testDonationWithIncompleteBankDataCanBeLoaded(): void {
321
		$donationId = $this->createDonationWithIncompleteBankData();
322
		$repository = $this->newRepository();
323
		$donation = $repository->getDonationById( $donationId );
324
		/** @var DirectDebitPayment $paymentMethod */
325
		$paymentMethod = $donation->getPaymentMethod();
326
		$this->assertNotNull( $paymentMethod->getBankData() );
327
		$this->assertSame( '', $paymentMethod->getBankData()->getIban()->toString() );
328
	}
329
330
	private function createDonationWithIncompleteBankData(): ?int {
331
		$doctrineDonation = IncompleteDoctrineDonation::newDirectDebitDonationWithMissingFields();
332
		$this->entityManager->persist( $doctrineDonation );
333
		$this->entityManager->flush();
334
		return $doctrineDonation->getId();
335
	}
336
337
	public function testDonationWithIncompleteCreditcardDataCanBeLoaded(): void {
338
		$donationId = $this->createDonationWithIncompleteCreditcardData();
339
		$repository = $this->newRepository();
340
		$donation = $repository->getDonationById( $donationId );
341
		/** @var CreditCardPayment $paymentMethod */
342
		$paymentMethod = $donation->getPaymentMethod();
343
		$this->assertNotNull( $paymentMethod->getCreditCardData() );
344
		$this->assertSame( '', $paymentMethod->getCreditCardData()->getTitle() );
345
	}
346
347
	private function createDonationWithIncompleteCreditcardData(): ?int {
348
		$doctrineDonation = IncompleteDoctrineDonation::newCreditcardDonationWithMissingFields();
349
		$this->entityManager->persist( $doctrineDonation );
350
		$this->entityManager->flush();
351
		return $doctrineDonation->getId();
352
	}
353
354
}
355