Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
83 / 83
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('integration');
11
12use Phexium\Domain\Id\Ulid;
13use Phexium\Plugin\IdGenerator\Adapter\UlidGenerator;
14
15describe('Generation', function (): void {
16    it('generates a Ulid object', function (): void {
17        $generator = new UlidGenerator();
18
19        $result = $generator->generate();
20
21        expect($result)->toBeInstanceOf(Ulid::class);
22    });
23
24    it('creates a Ulid from a Base32 string', function (): void {
25        $generator = new UlidGenerator();
26        $validUlid = '01GCZ05N3JFRKBRWKNGCQZGP44';
27
28        $result = $generator->from($validUlid);
29
30        expect($result)->toBeInstanceOf(Ulid::class)
31            ->and($result->getValue())->toBe($validUlid)
32        ;
33    });
34
35    it('creates a Ulid from a UUID string', function (): void {
36        $generator = new UlidGenerator();
37        $validUuid = '018e89e8-86e0-7a6c-a982-3b4e8e8d8e8e';
38
39        $result = $generator->from($validUuid);
40
41        expect($result)->toBeInstanceOf(Ulid::class)
42            ->and($result->getValue())->toMatch('/^[0-9A-Z]{26}$/')
43        ;
44    });
45
46    it('generates ULID in Base32 format with 26 characters', function (): void {
47        $generator = new UlidGenerator();
48
49        $result = $generator->generate();
50
51        expect($result)->toBeInstanceOf(Ulid::class)
52            ->and($result->getValue())->toMatch('/^[0-9A-Z]{26}$/')
53        ;
54    });
55
56    it('converts to string in Base32 format', function (): void {
57        $ulid = '01GCZ05N3JFRKBRWKNGCQZGP44';
58        $id = Ulid::from($ulid);
59
60        expect((string) $id)->toBeString()
61            ->toBe($ulid)
62            ->and($id->getValue())->toBe($ulid)
63            ->and(strlen($id->getValue()))->toBe(26)
64        ;
65    });
66
67    it('normalizes ambiguous Crockford characters I L O', function (): void {
68        $normalizationTests = [
69            '01GCZ05N3JFRKBRWKNGCQZGP4I' => '01GCZ05N3JFRKBRWKNGCQZGP41',
70            '01GCZ05N3JFRKBRWKNGCQZGP4L' => '01GCZ05N3JFRKBRWKNGCQZGP41',
71            '01GCZ05N3JFRKBRWKNGCQZGP4O' => '01GCZ05N3JFRKBRWKNGCQZGP40',
72        ];
73
74        foreach ($normalizationTests as $input => $expected) {
75            $ulid = Ulid::from($input);
76            $normalized = $ulid->getValue();
77
78            expect($normalized)->toBe(
79                $expected,
80                sprintf('ULID %s should normalize to %s but got %s', $input, $expected, $normalized)
81            );
82        }
83    });
84
85    it('throws exception when generator creates from int', function (): void {
86        $generator = new UlidGenerator();
87
88        expect(fn (): Ulid => $generator->from(123))
89            ->toThrow(LogicException::class, 'Ulid generator cannot create ULIDs from integers')
90        ;
91    });
92
93    it('throws exception when Ulid creates from int', function (): void {
94        expect(fn (): Ulid => Ulid::from(123))
95            ->toThrow(LogicException::class, 'Ulid cannot be created from an integer')
96        ;
97    });
98
99    it('throws exception with invalid string', function (): void {
100        expect(fn (): Ulid => Ulid::from('invalid-ulid'))
101            ->toThrow(InvalidArgumentException::class, 'Invalid ULID: invalid-ulid')
102        ;
103    });
104});
105
106describe('Uniqueness', function (): void {
107    it('compares by value', function (): void {
108        $ulid = '01GCZ05N3JFRKBRWKNGCQZGP44';
109        $id1 = Ulid::from($ulid);
110
111        expect($id1->equals($id1))->toBeTrue();
112
113        $anotherUlid = '01GCZ05N3JFRKBRWKNGCQZGP45';
114        $id2 = Ulid::from($anotherUlid);
115
116        expect($id1->equals($id2))->toBeFalse();
117    });
118
119    it('generates different ULIDs', function (): void {
120        $generator = new UlidGenerator();
121
122        $id1 = $generator->generate();
123        $id2 = $generator->generate();
124
125        expect($id1->equals($id2))->toBeFalse()
126            ->and($id1->getValue())->not->toBe($id2->getValue())
127        ;
128    });
129});