Completed
Pull Request — master (#976)
by wiese
61:34
created

newFailingPolicyValidator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 0
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\Fundraising\Frontend\MembershipContext\Tests\Integration\UseCases\ApplyForMembership;
6
7
use WMDE\Fundraising\Frontend\Infrastructure\TokenGenerator;
8
use WMDE\Fundraising\Frontend\MembershipContext\Authorization\ApplicationTokenFetcher;
9
use WMDE\Fundraising\Frontend\MembershipContext\Authorization\MembershipApplicationTokens;
10
use WMDE\Fundraising\Frontend\Infrastructure\EmailAddress;
11
use WMDE\Fundraising\Frontend\MembershipContext\Domain\Repositories\ApplicationRepository;
12
use WMDE\Fundraising\Frontend\MembershipContext\Tests\Data\ValidMembershipApplication;
13
use WMDE\Fundraising\Frontend\MembershipContext\Tests\Fixtures\FixedApplicationTokenFetcher;
14
use WMDE\Fundraising\Frontend\MembershipContext\Tests\Fixtures\InMemoryApplicationRepository;
15
use WMDE\Fundraising\Frontend\MembershipContext\Tracking\ApplicationPiwikTracker;
16
use WMDE\Fundraising\Frontend\MembershipContext\Tracking\ApplicationTracker;
17
use WMDE\Fundraising\Frontend\MembershipContext\Tracking\MembershipApplicationTrackingInfo;
18
use WMDE\Fundraising\Frontend\MembershipContext\UseCases\ApplyForMembership\ApplicationValidationResult;
19
use WMDE\Fundraising\Frontend\MembershipContext\UseCases\ApplyForMembership\ApplyForMembershipPolicyValidator;
20
use WMDE\Fundraising\Frontend\MembershipContext\UseCases\ApplyForMembership\ApplyForMembershipRequest;
21
use WMDE\Fundraising\Frontend\MembershipContext\UseCases\ApplyForMembership\ApplyForMembershipUseCase;
22
use WMDE\Fundraising\Frontend\MembershipContext\UseCases\ApplyForMembership\MembershipApplicationValidator;
23
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\BankData;
24
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\Iban;
25
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\PayPalPayment;
26
use WMDE\Fundraising\Frontend\PaymentContext\Domain\PaymentDelayCalculator;
27
use WMDE\Fundraising\Frontend\Tests\Fixtures\FixedPaymentDelayCalculator;
28
use WMDE\Fundraising\Frontend\Tests\Fixtures\FixedTokenGenerator;
29
use WMDE\Fundraising\Frontend\Tests\Fixtures\TemplateBasedMailerSpy;
30
use PHPUnit\Framework\TestCase;
31
32
/**
33
 * @covers \WMDE\Fundraising\Frontend\MembershipContext\UseCases\ApplyForMembership\ApplyForMembershipUseCase
34
 *
35
 * @license GNU GPL v2+
36
 * @author Jeroen De Dauw < [email protected] >
37
 */
38
class ApplyForMembershipUseCaseTest extends TestCase {
39
40
	const ID_OF_NON_EXISTING_APPLICATION = 1337;
41
	const FIRST_APPLICATION_ID = 1;
42
	const ACCESS_TOKEN = 'Gimmeh all the access';
43
	const UPDATE_TOKEN = 'Lemme change all the stuff';
44
	const FIRST_PAYMENT_DATE = '2017-08-07';
45
46
	/**
47
	 * @var ApplicationRepository
48
	 */
49
	private $repository;
50
51
	/**
52
	 * @var TemplateBasedMailerSpy
53
	 */
54
	private $mailer;
55
56
	/**
57
	 * @var TokenGenerator
58
	 */
59
	private $tokenGenerator;
60
61
	/**
62
	 * @var MembershipApplicationValidator
63
	 */
64
	private $validator;
65
66
	/**
67
	 * @var ApplicationTracker
68
	 */
69
	private $tracker;
70
71
	/**
72
	 * @var ApplicationPiwikTracker
73
	 */
74
	private $piwikTracker;
75
76
	/** @var  ApplyForMembershipPolicyValidator */
77
	private $policyValidator;
78
79
	public function setUp(): void {
80
		$this->repository = new InMemoryApplicationRepository();
81
		$this->mailer = new TemplateBasedMailerSpy( $this );
82
		$this->tokenGenerator = new FixedTokenGenerator( self::ACCESS_TOKEN );
83
		$this->validator = $this->newSucceedingValidator();
84
		$this->policyValidator = $this->newSucceedingPolicyValidator();
85
		$this->tracker = $this->createMock( ApplicationTracker::class );
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(\WMDE\...licationTracker::class) of type object<PHPUnit_Framework_MockObject_MockObject> is incompatible with the declared type object<WMDE\Fundraising\...ing\ApplicationTracker> of property $tracker.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
86
		$this->piwikTracker = $this->createMock( ApplicationPiwikTracker::class );
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(\WMDE\...ionPiwikTracker::class) of type object<PHPUnit_Framework_MockObject_MockObject> is incompatible with the declared type object<WMDE\Fundraising\...pplicationPiwikTracker> of property $piwikTracker.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
87
	}
88
89
	private function newSucceedingValidator(): MembershipApplicationValidator {
90
		$validator = $this->getMockBuilder( MembershipApplicationValidator::class )
91
			->disableOriginalConstructor()->getMock();
92
93
		$validator->expects( $this->any() )
94
			->method( 'validate' )
95
			->willReturn( new ApplicationValidationResult() );
96
97
		return $validator;
98
	}
99
100
	public function testGivenValidRequest_applicationSucceeds(): void {
101
		$response = $this->newUseCase()->applyForMembership( $this->newValidRequest() );
102
103
		$this->assertTrue( $response->isSuccessful() );
104
	}
105
106
	private function newUseCase(): ApplyForMembershipUseCase {
107
		return new ApplyForMembershipUseCase(
108
			$this->repository,
109
			$this->newTokenFetcher(),
110
			$this->mailer,
111
			$this->validator,
112
			$this->policyValidator,
113
			$this->tracker,
114
			$this->piwikTracker,
115
			$this->newFixedPaymentDelayCalculator()
116
		);
117
	}
118
119
	private function newTokenFetcher(): ApplicationTokenFetcher {
120
		return new FixedApplicationTokenFetcher( new MembershipApplicationTokens(
121
			self::ACCESS_TOKEN,
122
			self::UPDATE_TOKEN
123
		) );
124
	}
125
126
	private function newFixedPaymentDelayCalculator(): PaymentDelayCalculator {
127
		return new FixedPaymentDelayCalculator(
128
			new \DateTime( self::FIRST_PAYMENT_DATE )
129
		);
130
	}
131
132
	private function newValidRequest(): ApplyForMembershipRequest {
133
		$request = new ApplyForMembershipRequest();
134
135
		$request->setMembershipType( ValidMembershipApplication::MEMBERSHIP_TYPE );
136
		$request->setApplicantCompanyName( '' );
137
		$request->setMembershipType( ValidMembershipApplication::MEMBERSHIP_TYPE );
138
		$request->setApplicantSalutation( ValidMembershipApplication::APPLICANT_SALUTATION );
139
		$request->setApplicantTitle( ValidMembershipApplication::APPLICANT_TITLE );
140
		$request->setApplicantFirstName( ValidMembershipApplication::APPLICANT_FIRST_NAME );
141
		$request->setApplicantLastName( ValidMembershipApplication::APPLICANT_LAST_NAME );
142
		$request->setApplicantStreetAddress( ValidMembershipApplication::APPLICANT_STREET_ADDRESS );
143
		$request->setApplicantPostalCode( ValidMembershipApplication::APPLICANT_POSTAL_CODE );
144
		$request->setApplicantCity( ValidMembershipApplication::APPLICANT_CITY );
145
		$request->setApplicantCountryCode( ValidMembershipApplication::APPLICANT_COUNTRY_CODE );
146
		$request->setApplicantEmailAddress( ValidMembershipApplication::APPLICANT_EMAIL_ADDRESS );
147
		$request->setApplicantPhoneNumber( ValidMembershipApplication::APPLICANT_PHONE_NUMBER );
148
		$request->setApplicantDateOfBirth( ValidMembershipApplication::APPLICANT_DATE_OF_BIRTH );
149
		$request->setPaymentType( ValidMembershipApplication::PAYMENT_TYPE_DIRECT_DEBIT );
150
		$request->setPaymentIntervalInMonths( ValidMembershipApplication::PAYMENT_PERIOD_IN_MONTHS );
151
		$request->setPaymentAmountInEuros( (string)ValidMembershipApplication::PAYMENT_AMOUNT_IN_EURO );
152
153
		$request->setBankData( $this->newValidBankData() );
154
155
		$request->setTrackingInfo( $this->newTrackingInfo() );
156
		$request->setPiwikTrackingString( 'foo/bar' );
157
158
		$request->setOptsIntoDonationReceipt( true );
159
160
		return $request->assertNoNullFields();
161
	}
162
163
	private function newValidBankData(): BankData {
164
		$bankData = new BankData();
165
166
		$bankData->setIban( new Iban( ValidMembershipApplication::PAYMENT_IBAN ) );
167
		$bankData->setBic( ValidMembershipApplication::PAYMENT_BIC );
168
		$bankData->setAccount( ValidMembershipApplication::PAYMENT_BANK_ACCOUNT );
169
		$bankData->setBankCode( ValidMembershipApplication::PAYMENT_BANK_CODE );
170
		$bankData->setBankName( ValidMembershipApplication::PAYMENT_BANK_NAME );
171
172
		return $bankData->assertNoNullFields()->freeze();
173
	}
174
175
	private function newTrackingInfo(): MembershipApplicationTrackingInfo {
176
		return new MembershipApplicationTrackingInfo(
177
			ValidMembershipApplication::TEMPLATE_CAMPAIGN,
178
			ValidMembershipApplication::TEMPLATE_NAME
179
		);
180
	}
181
182
	public function testGivenValidRequest_applicationGetsPersisted(): void {
183
		$this->newUseCase()->applyForMembership( $this->newValidRequest() );
184
185
		$expectedApplication = ValidMembershipApplication::newDomainEntity();
186
		$expectedApplication->assignId( self::FIRST_APPLICATION_ID );
187
188
		$application = $this->repository->getApplicationById( $expectedApplication->getId() );
189
		$this->assertNotNull( $application );
190
191
		$this->assertEquals( $expectedApplication, $application );
192
	}
193
194
	public function testGivenValidRequest_confirmationEmailIsSend(): void {
195
		$this->newUseCase()->applyForMembership( $this->newValidRequest() );
196
197
		$this->mailer->assertCalledOnceWith(
198
			new EmailAddress( ValidMembershipApplication::APPLICANT_EMAIL_ADDRESS ),
199
			[
200
				'membershipType' => 'sustaining',
201
				'membershipFee' => '10.00',
202
				'paymentIntervalInMonths' => 3,
203
				'salutation' => 'Herr',
204
				'title' => '',
205
				'lastName' => 'The Great',
206
				'paymentType' => 'BEZ'
207
			]
208
		);
209
	}
210
211
	public function testGivenValidRequest_tokenIsGeneratedAndReturned(): void {
212
		$response = $this->newUseCase()->applyForMembership( $this->newValidRequest() );
213
214
		$this->assertSame( self::ACCESS_TOKEN, $response->getAccessToken() );
215
		$this->assertSame( self::UPDATE_TOKEN, $response->getUpdateToken() );
216
	}
217
218
	public function testWhenValidationFails_failureResultIsReturned(): void {
219
		$this->validator = $this->newFailingValidator();
220
221
		$response = $this->newUseCase()->applyForMembership( $this->newValidRequest() );
222
223
		$this->assertFalse( $response->isSuccessful() );
224
	}
225
226
	private function newFailingValidator(): MembershipApplicationValidator {
227
		$validator = $this->getMockBuilder( MembershipApplicationValidator::class )
228
			->disableOriginalConstructor()->getMock();
229
230
		$validator->expects( $this->any() )
231
			->method( 'validate' )
232
			->willReturn( $this->newInvalidValidationResult() );
233
234
		return $validator;
235
	}
236
237
	private function newInvalidValidationResult(): ApplicationValidationResult {
238
		$invalidResult = $this->createMock( ApplicationValidationResult::class );
239
240
		$invalidResult->expects( $this->any() )
241
			->method( 'isSuccessful' )
242
			->willReturn( false );
243
244
		return $invalidResult;
245
	}
246
247
	public function testGivenValidRequest_moderationIsNotNeeded(): void {
248
		$response = $this->newUseCase()->applyForMembership( $this->newValidRequest() );
249
250
		$this->assertFalse( $response->getMembershipApplication()->needsModeration() );
251
	}
252
253
	public function testGivenFailingPolicyValidator_moderationIsNeeded(): void {
254
		$this->policyValidator = $this->newFailingPolicyValidator();
255
256
		$response = $this->newUseCase()->applyForMembership( $this->newValidRequest() );
257
		$this->assertTrue( $response->getMembershipApplication()->needsModeration() );
258
	}
259
260
	private function newSucceedingPolicyValidator(): ApplyForMembershipPolicyValidator {
261
		$policyValidator = $this->getMockBuilder( ApplyForMembershipPolicyValidator::class )
262
			->disableOriginalConstructor()->getMock();
263
		$policyValidator->method( 'needsModeration' )->willReturn( false );
264
		return $policyValidator;
265
	}
266
267
	private function newFailingPolicyValidator(): ApplyForMembershipPolicyValidator {
268
		$policyValidator = $this->getMockBuilder( ApplyForMembershipPolicyValidator::class )
269
			->disableOriginalConstructor()->getMock();
270
		$policyValidator->method( 'needsModeration' )->willReturn( true );
271
		return $policyValidator;
272
	}
273
274
	public function testWhenApplicationIsUnconfirmed_confirmationEmailIsNotSent(): void {
275
		$this->newUseCase()->applyForMembership( $this->newValidRequestForUnconfirmedApplication() );
276
277
		$this->assertSame( 0, count( $this->mailer->getSendMailCalls() ) );
278
	}
279
280
	private function newValidRequestForUnconfirmedApplication(): ApplyForMembershipRequest {
281
		$request = new ApplyForMembershipRequest();
282
283
		$request->setMembershipType( ValidMembershipApplication::MEMBERSHIP_TYPE );
284
		$request->setApplicantCompanyName( '' );
285
		$request->setMembershipType( ValidMembershipApplication::MEMBERSHIP_TYPE );
286
		$request->setApplicantSalutation( ValidMembershipApplication::APPLICANT_SALUTATION );
287
		$request->setApplicantTitle( ValidMembershipApplication::APPLICANT_TITLE );
288
		$request->setApplicantFirstName( ValidMembershipApplication::APPLICANT_FIRST_NAME );
289
		$request->setApplicantLastName( ValidMembershipApplication::APPLICANT_LAST_NAME );
290
		$request->setApplicantStreetAddress( ValidMembershipApplication::APPLICANT_STREET_ADDRESS );
291
		$request->setApplicantPostalCode( ValidMembershipApplication::APPLICANT_POSTAL_CODE );
292
		$request->setApplicantCity( ValidMembershipApplication::APPLICANT_CITY );
293
		$request->setApplicantCountryCode( ValidMembershipApplication::APPLICANT_COUNTRY_CODE );
294
		$request->setApplicantEmailAddress( ValidMembershipApplication::APPLICANT_EMAIL_ADDRESS );
295
		$request->setApplicantPhoneNumber( ValidMembershipApplication::APPLICANT_PHONE_NUMBER );
296
		$request->setApplicantDateOfBirth( ValidMembershipApplication::APPLICANT_DATE_OF_BIRTH );
297
		$request->setPaymentType( ValidMembershipApplication::PAYMENT_TYPE_PAYPAL );
298
		$request->setPaymentIntervalInMonths( ValidMembershipApplication::PAYMENT_PERIOD_IN_MONTHS );
299
		$request->setPaymentAmountInEuros( (string)ValidMembershipApplication::PAYMENT_AMOUNT_IN_EURO );
300
		$request->setBankData( new BankData() );
301
302
		$request->setTrackingInfo( $this->newTrackingInfo() );
303
		$request->setPiwikTrackingString( 'foo/bar' );
304
305
		return $request->assertNoNullFields();
306
	}
307
308
	private function newAutoDeletingPolicyValidator(): ApplyForMembershipPolicyValidator {
309
		$policyValidator = $this->getMockBuilder( ApplyForMembershipPolicyValidator::class )
310
			->disableOriginalConstructor()->getMock();
311
		$policyValidator->method( 'isAutoDeleted' )->willReturn( true );
312
		return $policyValidator;
313
	}
314
315
	public function testWhenUsingBlacklistedEmailAddress_moderationIsAutomaticallyDeleted(): void {
316
		$this->policyValidator = $this->newAutoDeletingPolicyValidator();
317
		$this->newUseCase()->applyForMembership( $this->newValidRequest() );
318
		$this->assertTrue( $this->repository->getApplicationById( 1 )->isDeleted() );
319
	}
320
321
	public function testWhenUsingPayPalPayment_delayInDaysIsPersisted(): void {
322
		$request = $this->newValidRequest();
323
		$request->setPaymentType( 'PPL' );
324
		$this->newUseCase()->applyForMembership( $request );
325
		/** @var PayPalPayment $payPalPayment */
326
		$payPalPayment = $this->repository->getApplicationById( 1 )->getPayment()->getPaymentMethod();
327
		$this->assertSame( self::FIRST_PAYMENT_DATE, $payPalPayment->getPayPalData()->getFirstPaymentDate() );
328
	}
329
330
	public function testGivenDonationReceiptOptOutRequest_applicationHoldsThisValue(): void {
331
		$request = $this->newValidRequest();
332
		$request->setOptsIntoDonationReceipt( false );
333
		$this->newUseCase()->applyForMembership( $request );
334
335
		$application = $this->repository->getApplicationById( self::FIRST_APPLICATION_ID );
336
		$this->assertFalse( $application->getDonationReceipt() );
337
	}
338
339
}
340