Completed
Push — master ( bd2868...16a7fa )
by Jeroen De
12s
created

testWhenAuthorizationSucceeds_donationIsStored()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 0
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\Fundraising\Frontend\DonationContext\Tests\Integration\UseCases\CreditCardPaymentNotification;
6
7
use Psr\Log\NullLogger;
8
use WMDE\Euro\Euro;
9
use WMDE\Fundraising\Frontend\DonationContext\DataAccess\DoctrineDonationRepository;
10
use WMDE\Fundraising\Frontend\DonationContext\Infrastructure\DonationConfirmationMailer;
11
use WMDE\Fundraising\Frontend\DonationContext\Infrastructure\DonationEventLogger;
12
use WMDE\Fundraising\Frontend\DonationContext\Tests\Fixtures\DonationEventLoggerSpy;
13
use WMDE\Fundraising\Frontend\DonationContext\Tests\Fixtures\DonationRepositorySpy;
14
use WMDE\Fundraising\Frontend\DonationContext\Tests\Fixtures\FailingDonationAuthorizer;
15
use WMDE\Fundraising\Frontend\DonationContext\Tests\Fixtures\FakeDonationRepository;
16
use WMDE\Fundraising\Frontend\DonationContext\Tests\Fixtures\SucceedingDonationAuthorizer;
17
use WMDE\Fundraising\Frontend\DonationContext\UseCases\CreditCardPaymentNotification\CreditCardNotificationUseCase;
18
use WMDE\Fundraising\Frontend\DonationContext\UseCases\CreditCardPaymentNotification\CreditCardPaymentHandlerException;
19
use WMDE\Fundraising\Frontend\MembershipContext\Tests\Data\ValidCreditCardNotificationRequest;
20
use WMDE\Fundraising\Frontend\DonationContext\Tests\Data\ValidDonation;
21
use WMDE\Fundraising\Frontend\Tests\Fixtures\FakeCreditCardService;
22
use WMDE\Fundraising\Frontend\Tests\Fixtures\ThrowingEntityManager;
23
24
/**
25
 * @covers WMDE\Fundraising\Frontend\DonationContext\UseCases\CreditCardPaymentNotification\CreditCardNotificationUseCase
26
 *
27
 * @licence GNU GPL v2+
28
 * @author Kai Nissen < [email protected] >
29
 */
30
class CreditCardNotificationUseCaseTest extends \PHPUnit\Framework\TestCase {
31
32
	/** @var DoctrineDonationRepository|FakeDonationRepository|DonationRepositorySpy */
33
	private $repository;
34
	private $authorizer;
35
	/** @var DonationConfirmationMailer|\PHPUnit_Framework_MockObject_MockObject */
36
	private $mailer;
37
	private $eventLogger;
38
	private $creditCardService;
39
40
	public function setUp() {
41
		$this->repository = new FakeDonationRepository();
42
		$this->authorizer = new SucceedingDonationAuthorizer();
43
		$this->mailer = $this->newMailer();
44
		$this->eventLogger = $this->newEventLogger();
45
		$this->creditCardService = new FakeCreditCardService();
46
	}
47
48
	public function testWhenRepositoryThrowsException_handlerThrowsException() {
49
		$this->repository = new DoctrineDonationRepository( ThrowingEntityManager::newInstance( $this ) );
50
		$this->authorizer = new FailingDonationAuthorizer();
51
		$useCase = $this->newCreditCardNotificationUseCase();
52
		$request = ValidCreditCardNotificationRequest::newBillingNotification( 1 );
53
54
		$this->expectException( CreditCardPaymentHandlerException::class );
55
		$useCase->handleNotification( $request );
56
	}
57
58
	public function testWhenAuthorizationFails_handlerThrowsException() {
59
		$this->authorizer = new FailingDonationAuthorizer();
60
		$this->repository->storeDonation( ValidDonation::newIncompleteCreditCardDonation() );
61
62
		$useCase = $this->newCreditCardNotificationUseCase();
63
64
		$request = ValidCreditCardNotificationRequest::newBillingNotification( 1 );
65
66
		$this->expectException( CreditCardPaymentHandlerException::class );
67
		$useCase->handleNotification( $request );
68
	}
69
70
	public function testWhenAuthorizationSucceeds_handlerDoesNotThrowException() {
71
		$this->repository->storeDonation( ValidDonation::newIncompleteCreditCardDonation() );
72
73
		$useCase = $this->newCreditCardNotificationUseCase();
74
75
		$request = ValidCreditCardNotificationRequest::newBillingNotification( 1 );
76
77
		try {
78
			$useCase->handleNotification( $request );
79
			$this->assertTrue( true );
80
		} catch ( \Exception $e ) {
81
			$this->fail();
82
		}
83
	}
84
85
	public function testWhenPaymentTypeIsIncorrect_handlerThrowsException() {
86
		$this->repository->storeDonation( ValidDonation::newDirectDebitDonation() );
87
88
		$useCase = $this->newCreditCardNotificationUseCase();
89
90
		$request = ValidCreditCardNotificationRequest::newBillingNotification( 1 );
91
92
		$this->expectException( CreditCardPaymentHandlerException::class );
93
		$useCase->handleNotification( $request );
94
	}
95
96
	public function testWhenAuthorizationSucceeds_confirmationMailIsSent() {
97
		$donation = ValidDonation::newIncompleteCreditCardDonation();
98
		$this->repository->storeDonation( $donation );
99
100
		$this->mailer->expects( $this->once() )
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in WMDE\Fundraising\Fronten...ationConfirmationMailer.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
101
			->method( 'sendConfirmationMailFor' );
102
			// TODO: assert that the correct values are passed to the mailer
103
104
		$useCase = $this->newCreditCardNotificationUseCase();
105
106
		$request = ValidCreditCardNotificationRequest::newBillingNotification( 1 );
107
		$useCase->handleNotification( $request );
108
	}
109
110
	public function testWhenAuthorizationSucceedsForAnonymousDonation_confirmationMailIsNotSent() {
111
		$donation = ValidDonation::newIncompleteAnonymousCreditCardDonation();
112
		$this->repository->storeDonation( $donation );
113
114
		$this->mailer->expects( $this->never() )
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in WMDE\Fundraising\Fronten...ationConfirmationMailer.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
115
			->method( 'sendConfirmationMailFor' );
116
117
		$useCase = $this->newCreditCardNotificationUseCase();
118
119
		$request = ValidCreditCardNotificationRequest::newBillingNotification( 1 );
120
		$useCase->handleNotification( $request );
121
	}
122
123
	public function testWhenAuthorizationSucceeds_donationIsStored() {
124
		$donation = ValidDonation::newIncompleteCreditCardDonation();
125
		$this->repository = new DonationRepositorySpy( $donation );
126
127
		$useCase = $this->newCreditCardNotificationUseCase();
128
129
		$request = ValidCreditCardNotificationRequest::newBillingNotification( 1 );
130
		$useCase->handleNotification( $request );
131
		$this->assertCount( 1, $this->repository->getStoreDonationCalls() );
132
	}
133
134
	public function testWhenAuthorizationSucceeds_donationIsBooked() {
135
		$donation = ValidDonation::newIncompleteCreditCardDonation();
136
		$this->repository = new DonationRepositorySpy( $donation );
137
138
		$useCase = $this->newCreditCardNotificationUseCase();
139
140
		$request = ValidCreditCardNotificationRequest::newBillingNotification( 1 );
141
		$useCase->handleNotification( $request );
142
		$this->assertTrue( $this->repository->getDonationById( $donation->getId() )->isBooked() );
143
	}
144
145
	public function testWhenAuthorizationSucceeds_bookingEventIsLogged() {
146
		$donation = ValidDonation::newIncompleteCreditCardDonation();
147
		$this->repository = new DonationRepositorySpy( $donation );
148
		$this->eventLogger = new DonationEventLoggerSpy();
149
150
		$useCase = $this->newCreditCardNotificationUseCase();
151
152
		$request = ValidCreditCardNotificationRequest::newBillingNotification( 1 );
153
		$useCase->handleNotification( $request );
154
155
		$this->assertEventLogContainsExpression( $this->eventLogger, $donation->getId(), '/booked/' );
156
	}
157
158
	public function testWhenSendingConfirmationMailFails_handlerDoesNotThrowException() {
159
		$this->repository->storeDonation( ValidDonation::newIncompleteCreditCardDonation() );
160
161
		$this->mailer->expects( $this->once() )
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in WMDE\Fundraising\Fronten...ationConfirmationMailer.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
162
			->method( 'sendConfirmationMailFor' )
163
			->willThrowException( new \RuntimeException( 'Oh noes!' ) );
164
165
		$useCase = $this->newCreditCardNotificationUseCase();
166
167
		$request = ValidCreditCardNotificationRequest::newBillingNotification( 1 );
168
		try {
169
			$useCase->handleNotification( $request );
170
		} catch ( \Exception $e ) {
171
			$this->fail();
172
		}
173
	}
174
175
	private function assertEventLogContainsExpression( DonationEventLoggerSpy $eventLoggerSpy, int $donationId, string $expr ) {
176
		$foundCalls = array_filter( $eventLoggerSpy->getLogCalls(), function( $call ) use ( $donationId, $expr ) {
177
			return $call[0] == $donationId && preg_match( $expr, $call[1] );
178
		} );
179
		$assertMsg = 'Failed to assert that donation event log log contained "' . $expr . '" for donation id '.$donationId;
180
		$this->assertCount( 1, $foundCalls, $assertMsg );
181
	}
182
183
	/**
184
	 * @return DonationConfirmationMailer|\PHPUnit_Framework_MockObject_MockObject
185
	 */
186
	private function newMailer(): DonationConfirmationMailer {
187
		return $this->getMockBuilder( DonationConfirmationMailer::class )->disableOriginalConstructor()->getMock();
188
	}
189
190
	/**
191
	 * @return DonationEventLogger|\PHPUnit_Framework_MockObject_MockObject
192
	 */
193
	private function newEventLogger(): DonationEventLogger {
194
		return $this->createMock( DonationEventLogger::class );
195
	}
196
197
	private function newCreditCardNotificationUseCase() {
198
		return new CreditCardNotificationUseCase(
199
			$this->repository,
200
			$this->authorizer,
201
			$this->creditCardService,
202
			$this->mailer,
203
			new NullLogger(),
204
			$this->eventLogger
205
		);
206
	}
207
208
	public function testWhenPaymentAmountMismatches_handlerThreepwoodsException() {
209
		$this->repository->storeDonation( ValidDonation::newIncompleteCreditCardDonation() );
210
211
		$useCase = $this->newCreditCardNotificationUseCase();
212
213
		$request = ValidCreditCardNotificationRequest::newBillingNotification( 1 );
214
		$request->setAmount( Euro::newFromInt( 35505 ) );
215
216
		$this->expectException( CreditCardPaymentHandlerException::class );
217
		$useCase->handleNotification( $request );
218
	}
219
220
}
221