Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
48 / 48
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\Exception\InvalidTitleException;
13use AppDemo\Library\Domain\Title;
14use Tests\Phexium\Fake\Domain\StringValueObject as FakeValueObject;
15
16describe('Creation', function (): void {
17    it('creates title using static factory method', function (): void {
18        $title = Title::fromString('Clean Architecture');
19
20        expect($title->getValue())->toBe('Clean Architecture')
21            ->and($title->jsonSerialize())->toBe('Clean Architecture')
22            ->and((string) $title)->toBe('Clean Architecture')
23        ;
24    });
25
26    it('normalizes by trimming whitespace', function (): void {
27        $title = Title::fromString('  Clean Architecture  ');
28
29        expect($title->getValue())->toBe('Clean Architecture');
30    });
31});
32
33describe('Equality', function (): void {
34    it('considers two titles with same value as equal', function (): void {
35        $title1 = Title::fromString('Clean Architecture');
36        $title2 = Title::fromString('Clean Architecture ');
37
38        expect($title1->equals($title2))->toBeTrue();
39    });
40
41    it('considers two titles with different values as not equal', function (): void {
42        $title1 = Title::fromString('Clean Architecture');
43        $title2 = Title::fromString('Clean Code');
44
45        expect($title1->equals($title2))->toBeFalse();
46    });
47
48    it('considers a title and another value object as not equal', function (): void {
49        $title = Title::fromString('Clean Code');
50        $object = FakeValueObject::fromString('Clean Code');
51
52        expect($title->equals($object))->toBeFalse();
53    });
54});
55
56describe('Validation', function (): void {
57    it('throws exception for invalid title', function (): void {
58        expect(fn (): Title => Title::fromString(''))
59            ->toThrow(InvalidTitleException::class, 'Title cannot be empty')
60        ;
61    });
62
63    it('accepts title with exactly 200 characters', function (): void {
64        $title = Title::fromString(str_repeat('a', 200));
65
66        expect(strlen($title->getValue()))->toBe(200);
67    });
68
69    it('throws exception for title exceeding 200 characters', function (): void {
70        $longTitle = str_repeat('a', 201);
71        expect(fn (): Title => Title::fromString($longTitle))
72            ->toThrow(InvalidTitleException::class, 'Title cannot exceed 200 characters')
73        ;
74    });
75});