Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
50 / 50
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\Library\Domain\Author;
13use AppDemo\Library\Domain\Book;
14use AppDemo\Library\Domain\BookStatus;
15use AppDemo\Library\Domain\Exception\BookNotAvailableException;
16use AppDemo\Library\Domain\ISBN;
17use AppDemo\Library\Domain\Title;
18use Phexium\Domain\Id\TimestampId;
19use Tests\AppDemo\Fixture\BookMother;
20
21describe('Creation', function (): void {
22    it('has available status by default', function (): void {
23        $book = new Book(
24            new TimestampId(123),
25            Title::fromString('BookTitle'),
26            Author::fromString('BookAuthor'),
27            ISBN::fromString('9780134494166'),
28        );
29
30        expect($book->getStatus())->toBe(BookStatus::Available);
31    });
32});
33
34describe('State transitions', function (): void {
35    it('marks an available book as borrowed', function (): void {
36        $book = BookMother::available(123);
37
38        expect($book->getStatus())->toBe(BookStatus::Available);
39
40        $book->markAsBorrowed();
41
42        expect($book->getStatus())->toBe(BookStatus::Borrowed);
43    });
44
45    it('marks a borrowed book as available', function (): void {
46        $book = BookMother::borrowed(123);
47
48        expect($book->getStatus())->toBe(BookStatus::Borrowed);
49
50        $book->markAsAvailable();
51
52        expect($book->getStatus())->toBe(BookStatus::Available);
53    });
54
55    it('throws when marking a borrowed book as borrowed again', function (): void {
56        $book = BookMother::borrowed(123);
57
58        expect(fn () => $book->markAsBorrowed())
59            ->toThrow(BookNotAvailableException::class)
60        ;
61    });
62
63    it('throws when marking an available book as available again', function (): void {
64        $book = BookMother::available(123);
65
66        expect(fn () => $book->markAsAvailable())
67            ->toThrow(BookNotAvailableException::class)
68        ;
69    });
70});
71
72describe('Equality', function (): void {
73    it('considers two books with the same ID as equal', function (): void {
74        $book1 = BookMother::available(123);
75        $book2 = BookMother::available(123);
76
77        expect($book1->equals($book2))->toBeTrue();
78    });
79
80    it('considers two books with different IDs as not equal', function (): void {
81        $book1 = BookMother::available(123);
82        $book2 = BookMother::available(234);
83
84        expect($book1->equals($book2))->toBeFalse();
85    });
86});