Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
54 / 54
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2
3// ╔════════════════════════════════════════════════════════════╗
4// ║ MIT Licence (#Expat) - https://opensource.org/licenses/MIT ║
5// ║ Copyright 2026 Frederic Poeydomenge <dyno@phexium.com>     ║
6// ╚════════════════════════════════════════════════════════════╝
7
8declare(strict_types=1);
9
10pest()->group('unit');
11
12use AppDemo\Loan\Domain\Exception\LoanAlreadyReturnedException;
13use AppDemo\Loan\Domain\LoanStatus;
14use Tests\AppDemo\Fixture\LoanMother;
15
16describe('Overdue check', function (): void {
17    it('is not overdue when the current date is before the due date', function (): void {
18        $loan = LoanMother::active(123);
19        $date = new DateTimeImmutable('2024-10-10');
20
21        expect($loan->isOverdue($date))->toBeFalse();
22    });
23
24    it('is not overdue on the exact due date', function (): void {
25        $loan = LoanMother::active(123);
26        $date = new DateTimeImmutable('2024-10-15');
27
28        expect($loan->isOverdue($date))->toBeFalse();
29    });
30
31    it('is overdue when the current date is after the due date', function (): void {
32        $loan = LoanMother::active(123);
33        $date = new DateTimeImmutable('2024-10-16');
34
35        expect($loan->isOverdue($date))->toBeTrue();
36    });
37
38    it('is never considered overdue when returned', function (): void {
39        $loan = LoanMother::returned(123);
40        $date = new DateTimeImmutable('2024-10-20');
41
42        expect($loan->isOverdue($date))->toBeFalse();
43    });
44});
45
46describe('Return', function (): void {
47    it('can be marked as returned', function (): void {
48        $loan = LoanMother::active(123);
49
50        expect($loan->getStatus())->toBe(LoanStatus::Active)
51            ->and($loan->getReturnedAt())->toBeNull()
52        ;
53
54        $returnedAt = new DateTimeImmutable('2024-10-14');
55        $loan->markAsReturned($returnedAt);
56
57        expect($loan->getStatus())->toBe(LoanStatus::Returned)
58            ->and($loan->getReturnedAt())->toBe($returnedAt)
59        ;
60    });
61
62    it('throws when a returned loan is marked as returned again', function (): void {
63        $loan = LoanMother::returned(123);
64
65        expect(fn () => $loan->markAsReturned(new DateTimeImmutable('2024-10-15')))
66            ->toThrow(LoanAlreadyReturnedException::class)
67        ;
68    });
69});
70
71describe('Equality', function (): void {
72    it('considers two loans with the same ID as equal', function (): void {
73        $loan1 = LoanMother::active(123);
74        $loan2 = LoanMother::active(123);
75
76        expect($loan1->equals($loan2))->toBeTrue();
77    });
78
79    it('considers two loans with different IDs as not equal', function (): void {
80        $loan1 = LoanMother::active(123);
81        $loan2 = LoanMother::active(234);
82
83        expect($loan1->equals($loan2))->toBeFalse();
84    });
85});