Skip to content

Commit c02a064

Browse files
authored
[10.x] Add ulid testing helpers (#48276)
* add ulid testing helpers * fix code style
1 parent ae93199 commit c02a064

File tree

2 files changed

+194
-0
lines changed

2 files changed

+194
-0
lines changed

src/Illuminate/Support/Str.php

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ class Str
5050
*/
5151
protected static $uuidFactory;
5252

53+
/**
54+
* The callback that should be used to generate ULIDs.
55+
*
56+
* @var callable|null
57+
*/
58+
protected static $ulidFactory;
59+
5360
/**
5461
* The callback that should be used to generate random strings.
5562
*
@@ -1543,13 +1550,95 @@ public static function createUuidsNormally()
15431550
*/
15441551
public static function ulid($time = null)
15451552
{
1553+
if (static::$ulidFactory) {
1554+
return call_user_func(static::$ulidFactory);
1555+
}
1556+
15461557
if ($time === null) {
15471558
return new Ulid();
15481559
}
15491560

15501561
return new Ulid(Ulid::generate($time));
15511562
}
15521563

1564+
/**
1565+
* Indicate that ULIDs should be created normally and not using a custom factory.
1566+
*
1567+
* @return void
1568+
*/
1569+
public static function createUlidsNormally()
1570+
{
1571+
static::$ulidFactory = null;
1572+
}
1573+
1574+
/**
1575+
* Set the callable that will be used to generate ULIDs.
1576+
*
1577+
* @param callable|null $factory
1578+
* @return void
1579+
*/
1580+
public static function createUlidsUsing(callable $factory = null)
1581+
{
1582+
static::$ulidFactory = $factory;
1583+
}
1584+
1585+
/**
1586+
* Set the sequence that will be used to generate ULIDs.
1587+
*
1588+
* @param array $sequence
1589+
* @param callable|null $whenMissing
1590+
* @return void
1591+
*/
1592+
public static function createUlidsUsingSequence(array $sequence, $whenMissing = null)
1593+
{
1594+
$next = 0;
1595+
1596+
$whenMissing ??= function () use (&$next) {
1597+
$factoryCache = static::$ulidFactory;
1598+
1599+
static::$ulidFactory = null;
1600+
1601+
$ulid = static::ulid();
1602+
1603+
static::$ulidFactory = $factoryCache;
1604+
1605+
$next++;
1606+
1607+
return $ulid;
1608+
};
1609+
1610+
static::createUlidsUsing(function () use (&$next, $sequence, $whenMissing) {
1611+
if (array_key_exists($next, $sequence)) {
1612+
return $sequence[$next++];
1613+
}
1614+
1615+
return $whenMissing();
1616+
});
1617+
}
1618+
1619+
/**
1620+
* Always return the same ULID when generating new ULIDs.
1621+
*
1622+
* @param Closure|null $callback
1623+
* @return Ulid
1624+
*/
1625+
public static function freezeUlids(Closure $callback = null)
1626+
{
1627+
$ulid = Str::ulid();
1628+
1629+
Str::createUlidsUsing(fn () => $ulid);
1630+
1631+
if ($callback !== null) {
1632+
try {
1633+
$callback($ulid);
1634+
} finally {
1635+
Str::createUlidsNormally();
1636+
}
1637+
}
1638+
1639+
return $ulid;
1640+
}
1641+
15531642
/**
15541643
* Remove all strings from the casing caches.
15551644
*

tests/Support/SupportStrTest.php

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,111 @@ public function testItCanSpecifyAFallbackForASequence()
11551155
}
11561156
}
11571157

1158+
public function testItCanFreezeUlids()
1159+
{
1160+
$this->assertNotSame((string) Str::ulid(), (string) Str::ulid());
1161+
$this->assertNotSame(Str::ulid(), Str::ulid());
1162+
1163+
$ulid = Str::freezeUlids();
1164+
1165+
$this->assertSame($ulid, Str::ulid());
1166+
$this->assertSame(Str::ulid(), Str::ulid());
1167+
$this->assertSame((string) $ulid, (string) Str::ulid());
1168+
$this->assertSame((string) Str::ulid(), (string) Str::ulid());
1169+
1170+
Str::createUlidsNormally();
1171+
1172+
$this->assertNotSame(Str::ulid(), Str::ulid());
1173+
$this->assertNotSame((string) Str::ulid(), (string) Str::ulid());
1174+
}
1175+
1176+
public function testItCanFreezeUlidsInAClosure()
1177+
{
1178+
$ulids = [];
1179+
1180+
$ulid = Str::freezeUlids(function ($ulid) use (&$ulids) {
1181+
$ulids[] = $ulid;
1182+
$ulids[] = Str::ulid();
1183+
$ulids[] = Str::ulid();
1184+
});
1185+
1186+
$this->assertSame($ulid, $ulids[0]);
1187+
$this->assertSame((string) $ulid, (string) $ulids[0]);
1188+
$this->assertSame((string) $ulids[0], (string) $ulids[1]);
1189+
$this->assertSame($ulids[0], $ulids[1]);
1190+
$this->assertSame((string) $ulids[0], (string) $ulids[1]);
1191+
$this->assertSame($ulids[1], $ulids[2]);
1192+
$this->assertSame((string) $ulids[1], (string) $ulids[2]);
1193+
$this->assertNotSame(Str::ulid(), Str::ulid());
1194+
$this->assertNotSame((string) Str::ulid(), (string) Str::ulid());
1195+
1196+
Str::createUlidsNormally();
1197+
}
1198+
1199+
public function testItCreatesUlidsNormallyAfterFailureWithinFreezeMethod()
1200+
{
1201+
try {
1202+
Str::freezeUlids(function () {
1203+
Str::createUlidsUsing(fn () => Str::of('1234'));
1204+
$this->assertSame('1234', (string) Str::ulid());
1205+
throw new \Exception('Something failed');
1206+
});
1207+
} catch (\Exception) {
1208+
$this->assertNotSame('1234', (string) Str::ulid());
1209+
}
1210+
}
1211+
1212+
public function testItCanSpecifyASequenceOfUlidsToUtilise()
1213+
{
1214+
Str::createUlidsUsingSequence([
1215+
0 => ($zeroth = Str::ulid()),
1216+
1 => ($first = Str::ulid()),
1217+
// just generate a random one here...
1218+
3 => ($third = Str::ulid()),
1219+
// continue to generate random ulids...
1220+
]);
1221+
1222+
$retrieved = Str::ulid();
1223+
$this->assertSame($zeroth, $retrieved);
1224+
$this->assertSame((string) $zeroth, (string) $retrieved);
1225+
1226+
$retrieved = Str::ulid();
1227+
$this->assertSame($first, $retrieved);
1228+
$this->assertSame((string) $first, (string) $retrieved);
1229+
1230+
$retrieved = Str::ulid();
1231+
$this->assertFalse(in_array($retrieved, [$zeroth, $first, $third], true));
1232+
$this->assertFalse(in_array((string) $retrieved, [(string) $zeroth, (string) $first, (string) $third], true));
1233+
1234+
$retrieved = Str::ulid();
1235+
$this->assertSame($third, $retrieved);
1236+
$this->assertSame((string) $third, (string) $retrieved);
1237+
1238+
$retrieved = Str::ulid();
1239+
$this->assertFalse(in_array($retrieved, [$zeroth, $first, $third], true));
1240+
$this->assertFalse(in_array((string) $retrieved, [(string) $zeroth, (string) $first, (string) $third], true));
1241+
1242+
Str::createUlidsNormally();
1243+
}
1244+
1245+
public function testItCanSpecifyAFallbackForAUlidSequence()
1246+
{
1247+
Str::createUlidsUsingSequence(
1248+
[Str::ulid(), Str::ulid()],
1249+
fn () => throw new Exception('Out of Ulids'),
1250+
);
1251+
Str::ulid();
1252+
Str::ulid();
1253+
1254+
try {
1255+
$this->expectExceptionMessage('Out of Ulids');
1256+
Str::ulid();
1257+
$this->fail();
1258+
} finally {
1259+
Str::createUlidsNormally();
1260+
}
1261+
}
1262+
11581263
public function testPasswordCreation()
11591264
{
11601265
$this->assertTrue(strlen(Str::password()) === 32);

0 commit comments

Comments
 (0)