Passed
Branch master (6a00e9)
by David
02:22
created

SubscriptionManagerTest::setUp()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 33
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 21
nc 1
nop 0
dl 0
loc 33
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace Terox\SubscriptionBundle\Tests\Subscription;
4
5
use Symfony\Component\EventDispatcher\EventDispatcher;
6
use Terox\SubscriptionBundle\Exception\PermanentSubscriptionException;
7
use Terox\SubscriptionBundle\Exception\SubscriptionRenewalException;
8
use Terox\SubscriptionBundle\Model\ProductInterface;
9
use Terox\SubscriptionBundle\Model\SubscriptionInterface;
10
use Terox\SubscriptionBundle\Strategy\SubscriptionEndLastStrategy;
11
use Terox\SubscriptionBundle\Registry\SubscriptionRegistry;
12
use Terox\SubscriptionBundle\Subscription\SubscriptionManager;
13
use Terox\SubscriptionBundle\Tests\AbstractTestCaseBase;
14
use Terox\SubscriptionBundle\Tests\Mock\SubscriptionMock;
15
use Terox\SubscriptionBundle\Tests\Mock\UserMock;
16
17
class SubscriptionManagerTest extends AbstractTestCaseBase
18
{
19
    /**
20
     * @var SubscriptionManager
21
     */
22
    private $subscriptionManager;
23
24
    public function setUp()
25
    {
26
        parent::setUp();
27
28
        // Product
29
        $this->product->shouldReceive('getName')->andReturn('Test non-default product');
30
        $this->product->shouldReceive('getDuration')->andReturn(self::MONTH_SECONDS);
31
        $this->product->shouldReceive('isDefault')->andReturn(false);
32
        $this->product->shouldReceive('getExpirationDate')->andReturn(null);
33
        $this->product->shouldReceive('getQuota')->andReturn(null);
34
        $this->product->shouldReceive('isAutoRenewal')->andReturn(false);
35
36
        // Repositories
37
        $this->productRepository->shouldReceive('findDefault')->andReturn($this->product);
38
        $this->subscriptionRepository->shouldReceive('getNumberOfSubscriptionsByProducts')->andReturn(50);
39
40
        // Registry
41
        $registry = new SubscriptionRegistry();
42
        $registry->addStrategy(
43
            new SubscriptionEndLastStrategy(SubscriptionMock::class, $this->defaultProductStrategy),
44
            'end_last'
45
        );
46
47
        $eventDispatcher = \Mockery::mock(EventDispatcher::class);
48
        $eventDispatcher->shouldReceive('dispatch');
49
50
        // Manager
51
        $this->subscriptionManager = new SubscriptionManager($registry, $this->subscriptionRepository, $eventDispatcher, [
52
            'default_subscription_strategy' => 'end_last',
53
            'reasons' => [
54
                'expire'  => 'EXPIRE_TEXT',
55
                'disable' => 'DISABLE_TEXT',
56
                'renew'   => 'RENEW_TEXT'
57
            ]
58
        ]);
59
    }
60
61
    public function testConcatNewSubscriptionWithPrevious()
62
    {
63
        $this->currentSubscription1->shouldReceive('getProduct')->andReturn($this->product);
64
65
        $this->subscriptionRepository->shouldReceive('findByProduct')->andReturn([
66
            $this->currentSubscription1
67
        ]);
68
69
        // Create new subscription
70
        $subscription = $this->subscriptionManager->create($this->product, 'end_last');
71
72
        $this->assertEquals(
73
            $this->subscription1EndDate->modify('+30 days')->getTimestamp(),
74
            $subscription->getEndDate()->getTimestamp()
75
        );
76
77
        $this->assertEquals(false, $subscription->isAutoRenewal());
78
    }
79
80
    public function testConcatNewSubscriptionWithOverlapedSubscriptions()
81
    {
82
        $this->currentSubscription2->shouldReceive('getProduct')->andReturn($this->product);
83
        $this->currentSubscription3->shouldReceive('getProduct')->andReturn($this->product);
84
        $this->currentSubscription3->shouldReceive('getUser')->andReturn(new UserMock());
85
86
        $this->subscriptionRepository->shouldReceive('findByProduct')->andReturn([
87
            $this->currentSubscription2,
88
            $this->currentSubscription3
89
        ]);
90
91
        // Create new subscription
92
        $subscription = $this->subscriptionManager->create($this->product, 'end_last');
93
94
        $this->assertEquals(
95
            $this->subscription1EndDate->modify('+40 days')->getTimestamp(),
96
            $subscription->getEndDate()->getTimestamp(),
97
            sprintf('Expected %s => %s',
98
                $this->subscription1EndDate->modify('+40 days')->format('Y-m-d H:i:s'),
99
                $subscription->getEndDate()->format('Y-m-d H:i:s')
100
            )
101
        );
102
103
        $this->assertEquals(false, $subscription->isAutoRenewal());
104
    }
105
106
    public function testSameSubscriptionOnPermanentSubscription()
107
    {
108
        $this->permanentSubscription->shouldReceive('getProduct')->andReturn($this->product);
109
110
        $this->subscriptionRepository->shouldReceive('findByProduct')->andReturn([
111
            $this->permanentSubscription
112
        ]);
113
114
        $subscription = $this->subscriptionManager->create($this->product, 'end_last');
115
116
        $this->assertInstanceOf(SubscriptionInterface::class, $subscription);
117
        $this->assertEquals(null, $subscription->getEndDate());
118
        $this->assertEquals($this->permanentSubscription, $subscription);
119
    }
120
121
    public function testSameSubscriptionOnPermanentWithFiniteSubscriptions()
122
    {
123
        $this->currentSubscription1->shouldReceive('getProduct')->andReturn($this->product);
124
        $this->permanentSubscription->shouldReceive('getProduct')->andReturn($this->product);
125
126
        $this->subscriptionRepository->shouldReceive('findByProduct')->andReturn([
127
            $this->permanentSubscription,
128
            $this->currentSubscription1,
129
        ]);
130
131
        $this->expectException(PermanentSubscriptionException::class);
132
133
        $this->subscriptionManager->create($this->product, 'end_last');
134
    }
135
136
    public function testActivateSubscriptionWithValidProduct()
137
    {
138
        $subscription = new SubscriptionMock();
139
        $subscription->setActive(false);
140
        $subscription->setProduct($this->product);
141
142
        $this->subscriptionManager->activate($subscription);
143
144
        $this->assertEquals(true, $subscription->getActive());
145
        $this->assertEquals($this->product, $subscription->getProduct());
146
    }
147
148
    public function testActivateSubscriptionWithExpiredProductAndDefault()
149
    {
150
        $productExpired = \Mockery::mock(ProductInterface::class);
151
        $productExpired->shouldReceive('isDefault')->andReturn(false);
152
        $productExpired->shouldReceive('getExpirationDate')->andReturn(new \DateTime('-1 hour'));
153
        $productExpired->shouldReceive('getName')->andReturn('Test non-default product with expiration date');
154
        $productExpired->shouldReceive('getQuota')->andReturn(null);
155
156
        $subscription = new SubscriptionMock();
157
        $subscription->setProduct($productExpired);
158
159
        $this->subscriptionManager->activate($subscription);
160
161
        $this->assertEquals(true, $subscription->getActive());
162
        $this->assertEquals($this->product, $subscription->getProduct());
163
    }
164
165
    public function testActivateSubscriptionWithQuoteExceededAndDefault()
166
    {
167
        $productQuota = \Mockery::mock(ProductInterface::class);
168
        $productQuota->shouldReceive('isDefault')->andReturn(false);
169
        $productQuota->shouldReceive('getExpirationDate')->andReturn(null);
170
        $productQuota->shouldReceive('getName')->andReturn('Test non-default product with quota exceeded');
171
        $productQuota->shouldReceive('getQuota')->andReturn(50);
172
173
        $subscription = new SubscriptionMock();
174
        $subscription->setProduct($productQuota);
175
176
        $this->subscriptionManager->activate($subscription);
177
178
        $this->assertEquals(true, $subscription->getActive());
179
        $this->assertEquals($this->product, $subscription->getProduct());
180
    }
181
182
    public function testActivateSubscriptionWithoutQuoteExceededAndDefault()
183
    {
184
        $productQuota = \Mockery::mock(ProductInterface::class);
185
        $productQuota->shouldReceive('isDefault')->andReturn(false);
186
        $productQuota->shouldReceive('getExpirationDate')->andReturn(null);
187
        $productQuota->shouldReceive('getName')->andReturn('Test non-default product without quota exceeded');
188
        $productQuota->shouldReceive('getQuota')->andReturn(51);
189
        $productQuota->shouldReceive('isAutoRenewal')->andReturn(false);
190
191
        $subscription = new SubscriptionMock();
192
        $subscription->setProduct($productQuota);
193
194
        $this->subscriptionManager->activate($subscription);
195
196
        $this->assertEquals(true, $subscription->getActive());
197
        $this->assertEquals(false, $subscription->isAutoRenewal());
198
        $this->assertEquals($productQuota, $subscription->getProduct());
199
    }
200
201
    public function testRenewPermanentSubscriptionFail()
202
    {
203
        $subscription = new SubscriptionMock();
204
        $subscription->setActive(true);
205
        $subscription->setProduct($this->product);
206
        $subscription->setAutoRenewal(false);
207
        $subscription->setEndDate(null);
208
209
        $this->expectException(SubscriptionRenewalException::class);
210
        $this->expectExceptionMessage('A permanent subscription can not be renewed.');
211
212
        $this->subscriptionManager->renew($subscription);
213
    }
214
215
    public function testRenewSubscriptionNotEnabledAtSubscription()
216
    {
217
        $subscription = new SubscriptionMock();
218
        $subscription->setActive(true);
219
        $subscription->setProduct($this->product);
220
        $subscription->setAutoRenewal(false);
221
        $subscription->setEndDate(new \DateTimeImmutable());
222
223
        $this->expectException(SubscriptionRenewalException::class);
224
        $this->expectExceptionMessage('The current subscription is not auto-renewal.');
225
226
        $this->subscriptionManager->renew($subscription);
227
    }
228
229
    public function testRenewSubscriptionNotEnabledASubscription()
230
    {
231
        $subscription = new SubscriptionMock();
232
        $subscription->setActive(true);
233
        $subscription->setProduct($this->product);
234
        $subscription->setAutoRenewal(true);
235
        $subscription->setEndDate(new \DateTimeImmutable());
236
237
        $this->expectException(SubscriptionRenewalException::class);
238
        $this->expectExceptionMessage('The product "'.$this->product->getName().'" is not auto-renewal. Maybe is disabled?');
239
240
        $this->subscriptionManager->renew($subscription);
241
    }
242
243
    public function testRenewSubscriptionNotEnableAtProduct()
244
    {
245
        // Product
246
        $product = \Mockery::mock(ProductInterface::class);
247
        $product->shouldReceive('getName')->andReturn('Test non-default product without quota exceeded');
248
        $product->shouldReceive('getDuration')->andReturn(self::MONTH_SECONDS);
249
        $product->shouldReceive('isDefault')->andReturn(false);
250
        $product->shouldReceive('getExpirationDate')->andReturn(null);
251
        $product->shouldReceive('getQuota')->andReturn(null);
252
        $product->shouldReceive('isAutoRenewal')->andReturn(true);
253
        $product->shouldReceive('getNextRenewalProduct')->andReturn(null);
254
        $product->shouldReceive('getStrategyCodeName')->andReturn('end_last');
255
256
        // Subscription to renew
257
        $subscription = new SubscriptionMock();
258
        $subscription->setActive(true);
259
        $subscription->setProduct($product);
260
        $subscription->setAutoRenewal(true);
261
        $subscription->setEndDate(new \DateTimeImmutable());
262
263
        // No current active subscriptions
264
        $this->subscriptionRepository->shouldReceive('findByProduct')->andReturn([]);
265
266
        // Renew subscription
267
        $newSubscription = $this->subscriptionManager->renew($subscription);
268
269
        $this->assertEquals(false, $subscription->isActive());
270
        $this->assertEquals('RENEW_TEXT', $subscription->getReason());
271
272
        $this->assertEquals(true, $newSubscription->isActive());
273
        $this->assertEquals(true, $newSubscription->isAutoRenewal());
274
        $this->assertEquals($subscription->getUser(), $newSubscription->getUser());
275
    }
276
277
    public function testRenewSubscriptionWithSameProduct()
278
    {
279
        // Product
280
        $product = \Mockery::mock(ProductInterface::class);
281
        $product->shouldReceive('getName')->andReturn('Test non-default product without quota exceeded');
282
        $product->shouldReceive('getDuration')->andReturn(self::MONTH_SECONDS);
283
        $product->shouldReceive('isDefault')->andReturn(false);
284
        $product->shouldReceive('getExpirationDate')->andReturn(null);
285
        $product->shouldReceive('getQuota')->andReturn(null);
286
        $product->shouldReceive('isAutoRenewal')->andReturn(true);
287
        $product->shouldReceive('getNextRenewalProduct')->andReturn(null);
288
        $product->shouldReceive('getStrategyCodeName')->andReturn('end_last');
289
290
        // Subscription to renew
291
        $subscription = new SubscriptionMock();
292
        $subscription->setActive(true);
293
        $subscription->setProduct($product);
294
        $subscription->setAutoRenewal(true);
295
        $subscription->setEndDate(new \DateTimeImmutable());
296
297
        // No current active subscriptions
298
        $this->subscriptionRepository->shouldReceive('findByProduct')->andReturn([]);
299
300
        // Renew subscription
301
        $newSubscription = $this->subscriptionManager->renew($subscription);
302
303
        $this->assertEquals(false, $subscription->isActive());
304
        $this->assertEquals('RENEW_TEXT', $subscription->getReason());
305
306
        $this->assertEquals(true, $newSubscription->isActive());
307
        $this->assertEquals(true, $newSubscription->isAutoRenewal());
308
        $this->assertEquals($product, $newSubscription->getProduct());
309
        $this->assertEquals($subscription->getUser(), $newSubscription->getUser());
310
    }
311
312
    public function testRenewSubscriptionWithDifferentProduct()
313
    {
314
        // Product
315
        $product = \Mockery::mock(ProductInterface::class);
316
        $product->shouldReceive('getName')->andReturn('Test non-default product without quota exceeded');
317
        $product->shouldReceive('getDuration')->andReturn(self::MONTH_SECONDS);
318
        $product->shouldReceive('isDefault')->andReturn(false);
319
        $product->shouldReceive('getExpirationDate')->andReturn(null);
320
        $product->shouldReceive('getQuota')->andReturn(null);
321
        $product->shouldReceive('isAutoRenewal')->andReturn(true);
322
        $product->shouldReceive('getNextRenewalProduct')->andReturn($this->product); // This is the important step
323
324
        // Add to the default product strategy name
325
        $this->product->shouldReceive('getStrategyCodeName')->andReturn('end_last');
326
327
        // Subscription to renew
328
        $subscription = new SubscriptionMock();
329
        $subscription->setActive(true);
330
        $subscription->setProduct($product);
331
        $subscription->setAutoRenewal(true);
332
        $subscription->setEndDate(new \DateTimeImmutable());
333
334
        // No current active subscriptions
335
        $this->subscriptionRepository->shouldReceive('findByProduct')->andReturn([]);
336
337
        // Renew subscription
338
        $newSubscription = $this->subscriptionManager->renew($subscription);
339
340
        $this->assertEquals(false, $subscription->isActive());
341
        $this->assertEquals('RENEW_TEXT', $subscription->getReason());
342
343
        $this->assertEquals(true, $newSubscription->isActive());
344
        $this->assertEquals(true, $newSubscription->isAutoRenewal());
345
        $this->assertEquals($subscription->getUser(), $newSubscription->getUser());
346
    }
347
348
    public function testExpireSubscriptionNotEnableAtProduct()
349
    {
350
        $subscription = new SubscriptionMock();
351
        $subscription->setActive(true);
352
        $subscription->setProduct($this->product);
353
354
        $this->subscriptionManager->expire($subscription);
355
356
        $this->assertEquals(false, $subscription->getActive());
357
        $this->assertEquals('EXPIRE_TEXT', $subscription->getReason());
358
    }
359
360
    public function testDisableSubscription()
361
    {
362
        $subscription = new SubscriptionMock();
363
        $subscription->setActive(true);
364
        $subscription->setProduct($this->product);
365
366
        $this->subscriptionManager->disable($subscription);
367
368
        $this->assertEquals(false, $subscription->getActive());
369
        $this->assertEquals('DISABLE_TEXT', $subscription->getReason());
370
    }
371
}