clock = new SystemClock(); }); it('generates valid ULID', function () { $id = SmartLinkId::generate($this->clock); expect($id->toString())->toHaveLength(26); expect($id->toString())->toMatch('/^[0-9A-HJKMNP-TV-Z]{26}$/'); }); it('creates from valid ULID string', function () { $ulidString = '01ARZ3NDEK0MBY01ENPMVEW9WG'; $id = SmartLinkId::fromString($ulidString); expect($id->toString())->toBe($ulidString); }); it('throws exception for invalid format', function () { expect(fn() => SmartLinkId::fromString('invalid-format')) ->toThrow(\InvalidArgumentException::class, 'Invalid SmartLink ID format'); }); it('throws exception for too short string', function () { expect(fn() => SmartLinkId::fromString('01ARZ3NDEK0MBY')) ->toThrow(\InvalidArgumentException::class, 'Invalid SmartLink ID format'); }); it('throws exception for empty string', function () { expect(fn() => SmartLinkId::fromString('')) ->toThrow(\InvalidArgumentException::class, 'Invalid SmartLink ID format'); }); it('compares IDs correctly', function () { $id1 = SmartLinkId::fromString('01ARZ3NDEK0MBY01ENPMVEW9WG'); $id2 = SmartLinkId::fromString('01ARZ3NDEK0MBY01ENPMVEW9WG'); $id3 = SmartLinkId::fromString('01ARZ3NDEK0MBY01ENPMVEW9WH'); expect($id1->equals($id2))->toBeTrue(); expect($id1->equals($id3))->toBeFalse(); }); it('converts to string via toString', function () { $ulidString = '01ARZ3NDEK0MBY01ENPMVEW9WG'; $id = SmartLinkId::fromString($ulidString); expect($id->toString())->toBe($ulidString); }); it('converts to string via __toString', function () { $ulidString = '01ARZ3NDEK0MBY01ENPMVEW9WG'; $id = SmartLinkId::fromString($ulidString); expect((string) $id)->toBe($ulidString); }); it('generates unique IDs', function () { $ids = []; for ($i = 0; $i < 10; $i++) { $ids[] = SmartLinkId::generate($this->clock)->toString(); usleep(1000); // Small delay to ensure uniqueness } $uniqueIds = array_unique($ids); expect(count($uniqueIds))->toBe(10); }); });