Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
276
tests/Unit/Framework/Cuid/CuidGeneratorTest.php
Normal file
276
tests/Unit/Framework/Cuid/CuidGeneratorTest.php
Normal file
@@ -0,0 +1,276 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Framework\Cuid\Cuid;
|
||||
use App\Framework\Cuid\CuidGenerator;
|
||||
use App\Framework\Random\SecureRandomGenerator;
|
||||
|
||||
it('generates Cuid with current timestamp', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
$cuid = $generator->generate();
|
||||
|
||||
expect($cuid)->toBeInstanceOf(Cuid::class);
|
||||
expect($cuid->toString())->toStartWith('c');
|
||||
expect($cuid->toString())->toHaveLength(Cuid::LENGTH);
|
||||
|
||||
$currentTimeMs = intval(microtime(true) * 1000);
|
||||
expect($cuid->getTimestamp())->toBeGreaterThanOrEqual($currentTimeMs - 100);
|
||||
expect($cuid->getTimestamp())->toBeLessThanOrEqual($currentTimeMs + 100);
|
||||
});
|
||||
|
||||
it('generates Cuid at specific timestamp', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
$timestamp = 1609459200000; // 2021-01-01 00:00:00.000 UTC
|
||||
|
||||
$cuid = $generator->generateAt($timestamp);
|
||||
|
||||
expect($cuid->getTimestamp())->toBe($timestamp);
|
||||
});
|
||||
|
||||
it('generates Cuid in the past', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
$millisecondsAgo = 5000; // 5 seconds ago
|
||||
|
||||
$cuid = $generator->generateInPast($millisecondsAgo);
|
||||
|
||||
$expectedTimestamp = intval(microtime(true) * 1000) - $millisecondsAgo;
|
||||
expect($cuid->getTimestamp())->toBeGreaterThanOrEqual($expectedTimestamp - 100);
|
||||
expect($cuid->getTimestamp())->toBeLessThanOrEqual($expectedTimestamp + 100);
|
||||
});
|
||||
|
||||
it('generates batch of Cuids with incrementing counters', function () {
|
||||
$generator = CuidGenerator::createWithFingerprint(new SecureRandomGenerator(), 'test');
|
||||
$generator->resetCounter(); // Start from 0
|
||||
|
||||
$cuids = $generator->generateBatch(5);
|
||||
|
||||
expect($cuids)->toHaveCount(5);
|
||||
expect($cuids[0])->toBeInstanceOf(Cuid::class);
|
||||
|
||||
// All should have the same timestamp and fingerprint
|
||||
$firstTimestamp = $cuids[0]->getTimestamp();
|
||||
foreach ($cuids as $i => $cuid) {
|
||||
expect($cuid->getTimestamp())->toBe($firstTimestamp);
|
||||
expect($cuid->getFingerprint())->toBe('test');
|
||||
expect($cuid->getCounter())->toBe($i); // Incrementing counter
|
||||
}
|
||||
|
||||
// All should be unique
|
||||
$values = array_map(fn ($cuid) => $cuid->toString(), $cuids);
|
||||
$uniqueValues = array_unique($values);
|
||||
expect($uniqueValues)->toHaveCount(5);
|
||||
});
|
||||
|
||||
it('generates sequence of Cuids with incrementing timestamps', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
$count = 3;
|
||||
$interval = 1000; // 1 second intervals
|
||||
|
||||
$cuids = $generator->generateSequence($count, $interval);
|
||||
|
||||
expect($cuids)->toHaveCount($count);
|
||||
|
||||
// Check timestamps are incrementing
|
||||
for ($i = 1; $i < $count; $i++) {
|
||||
$timeDiff = $cuids[$i]->getTimestamp() - $cuids[$i - 1]->getTimestamp();
|
||||
expect($timeDiff)->toBe($interval);
|
||||
}
|
||||
});
|
||||
|
||||
it('generates Cuid with specific counter', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
$counter = 1234;
|
||||
|
||||
$cuid = $generator->generateWithCounter($counter);
|
||||
|
||||
expect($cuid->getCounter())->toBe($counter);
|
||||
});
|
||||
|
||||
it('increments counter correctly', function () {
|
||||
$generator = CuidGenerator::createWithFingerprint(new SecureRandomGenerator(), 'test');
|
||||
$generator->resetCounter();
|
||||
|
||||
$cuid1 = $generator->generate();
|
||||
$cuid2 = $generator->generate();
|
||||
$cuid3 = $generator->generate();
|
||||
|
||||
expect($cuid1->getCounter())->toBe(0);
|
||||
expect($cuid2->getCounter())->toBe(1);
|
||||
expect($cuid3->getCounter())->toBe(2);
|
||||
});
|
||||
|
||||
it('counter increments and resets correctly', function () {
|
||||
$generator = CuidGenerator::createWithFingerprint(new SecureRandomGenerator(), 'test');
|
||||
$generator->resetCounter();
|
||||
|
||||
// Generate a few Cuids to test counter increment
|
||||
$cuid1 = $generator->generate();
|
||||
$cuid2 = $generator->generate();
|
||||
$cuid3 = $generator->generate();
|
||||
|
||||
expect($cuid1->getCounter())->toBe(0);
|
||||
expect($cuid2->getCounter())->toBe(1);
|
||||
expect($cuid3->getCounter())->toBe(2);
|
||||
expect($generator->getCurrentCounter())->toBe(3);
|
||||
|
||||
// Test reset
|
||||
$generator->resetCounter();
|
||||
expect($generator->getCurrentCounter())->toBe(0);
|
||||
});
|
||||
|
||||
it('validates Cuid strings', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
|
||||
$validCuid = $generator->generate();
|
||||
expect($generator->isValid($validCuid->toString()))->toBeTrue();
|
||||
|
||||
expect($generator->isValid('invalid'))->toBeFalse();
|
||||
expect($generator->isValid(''))->toBeFalse();
|
||||
expect($generator->isValid('x' . str_repeat('a', 24)))->toBeFalse(); // Wrong prefix
|
||||
expect($generator->isValid('c' . str_repeat('!', 24)))->toBeFalse(); // Invalid characters
|
||||
});
|
||||
|
||||
it('parses Cuid strings', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
$original = $generator->generate();
|
||||
|
||||
$parsed = $generator->parse($original->toString());
|
||||
|
||||
expect($parsed->equals($original))->toBeTrue();
|
||||
});
|
||||
|
||||
it('generates consistent fingerprints', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
|
||||
$cuid1 = $generator->generate();
|
||||
$cuid2 = $generator->generate();
|
||||
|
||||
// Same generator should produce same fingerprint
|
||||
expect($cuid1->getFingerprint())->toBe($cuid2->getFingerprint());
|
||||
expect($generator->isSameGenerator($cuid1))->toBeTrue();
|
||||
expect($generator->isSameGenerator($cuid2))->toBeTrue();
|
||||
});
|
||||
|
||||
it('uses custom fingerprint', function () {
|
||||
$customFingerprint = 'abcd';
|
||||
$generator = CuidGenerator::createWithFingerprint(new SecureRandomGenerator(), $customFingerprint);
|
||||
|
||||
expect($generator->getFingerprint())->toBe($customFingerprint);
|
||||
|
||||
$cuid = $generator->generate();
|
||||
expect($cuid->getFingerprint())->toBe($customFingerprint);
|
||||
});
|
||||
|
||||
it('generates different fingerprints for different generators', function () {
|
||||
$generator1 = CuidGenerator::createWithFingerprint(new SecureRandomGenerator(), 'aaaa');
|
||||
$generator2 = CuidGenerator::createWithFingerprint(new SecureRandomGenerator(), 'bbbb');
|
||||
|
||||
expect($generator1->getFingerprint())->not->toBe($generator2->getFingerprint());
|
||||
|
||||
$cuid1 = $generator1->generate();
|
||||
$cuid2 = $generator2->generate();
|
||||
|
||||
expect($generator1->isSameGenerator($cuid2))->toBeFalse();
|
||||
expect($generator2->isSameGenerator($cuid1))->toBeFalse();
|
||||
});
|
||||
|
||||
it('resets counter correctly', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
|
||||
// Generate a few to increment counter
|
||||
$generator->generate();
|
||||
$generator->generate();
|
||||
expect($generator->getCurrentCounter())->toBeGreaterThan(0);
|
||||
|
||||
// Reset and check
|
||||
$generator->resetCounter();
|
||||
expect($generator->getCurrentCounter())->toBe(0);
|
||||
});
|
||||
|
||||
it('throws exception for invalid batch count', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
|
||||
expect(fn () => $generator->generateBatch(0))
|
||||
->toThrow(InvalidArgumentException::class, 'Count must be positive');
|
||||
|
||||
expect(fn () => $generator->generateBatch(10001))
|
||||
->toThrow(InvalidArgumentException::class, 'Batch size cannot exceed 10000');
|
||||
});
|
||||
|
||||
it('throws exception for invalid sequence count', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
|
||||
expect(fn () => $generator->generateSequence(0))
|
||||
->toThrow(InvalidArgumentException::class, 'Count must be positive');
|
||||
|
||||
expect(fn () => $generator->generateSequence(1001))
|
||||
->toThrow(InvalidArgumentException::class, 'Sequence size cannot exceed 1000');
|
||||
});
|
||||
|
||||
it('throws exception for negative interval', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
|
||||
expect(fn () => $generator->generateSequence(3, -1))
|
||||
->toThrow(InvalidArgumentException::class, 'Interval must be non-negative');
|
||||
});
|
||||
|
||||
it('throws exception for invalid counter value', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
$maxCounter = 36 ** Cuid::COUNTER_LENGTH;
|
||||
|
||||
expect(fn () => $generator->generateWithCounter(-1))
|
||||
->toThrow(InvalidArgumentException::class, 'Counter must be between 0 and');
|
||||
|
||||
expect(fn () => $generator->generateWithCounter($maxCounter))
|
||||
->toThrow(InvalidArgumentException::class, 'Counter must be between 0 and');
|
||||
});
|
||||
|
||||
it('throws exception for invalid fingerprint length', function () {
|
||||
expect(fn () => CuidGenerator::createWithFingerprint(new SecureRandomGenerator(), 'abc'))
|
||||
->toThrow(InvalidArgumentException::class, 'Fingerprint must be exactly 4 characters');
|
||||
|
||||
expect(fn () => CuidGenerator::createWithFingerprint(new SecureRandomGenerator(), 'abcde'))
|
||||
->toThrow(InvalidArgumentException::class, 'Fingerprint must be exactly 4 characters');
|
||||
});
|
||||
|
||||
it('creates generator using factory method', function () {
|
||||
$randomGen = new SecureRandomGenerator();
|
||||
$generator = CuidGenerator::create($randomGen);
|
||||
|
||||
expect($generator)->toBeInstanceOf(CuidGenerator::class);
|
||||
expect($generator->generate())->toBeInstanceOf(Cuid::class);
|
||||
});
|
||||
|
||||
it('generates sortable Cuids by timestamp', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
|
||||
$older = $generator->generateInPast(5000);
|
||||
$newer = $generator->generate();
|
||||
|
||||
// Lexicographic comparison should match timestamp order
|
||||
expect($older->compare($newer))->toBeLessThan(0);
|
||||
expect($older->toString() < $newer->toString())->toBeTrue();
|
||||
});
|
||||
|
||||
it('generates unique Cuids across multiple calls', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
$cuids = [];
|
||||
$count = 1000;
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$cuids[] = $generator->generate()->toString();
|
||||
}
|
||||
|
||||
$uniqueCuids = array_unique($cuids);
|
||||
expect($uniqueCuids)->toHaveCount($count);
|
||||
});
|
||||
|
||||
it('generates only lowercase characters', function () {
|
||||
$generator = new CuidGenerator(new SecureRandomGenerator());
|
||||
$cuid = $generator->generate();
|
||||
|
||||
$cuidString = $cuid->toString();
|
||||
expect($cuidString)->toBe(strtolower($cuidString)); // Should already be lowercase
|
||||
expect($cuidString)->toMatch('/^[c0-9a-z]+$/'); // Only valid Base36 chars
|
||||
});
|
||||
217
tests/Unit/Framework/Cuid/CuidTest.php
Normal file
217
tests/Unit/Framework/Cuid/CuidTest.php
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Framework\Cuid\Cuid;
|
||||
|
||||
it('creates Cuid from string', function () {
|
||||
$value = 'cjld2cjxh0000qzrmn831i7rn';
|
||||
$cuid = Cuid::fromString($value);
|
||||
|
||||
expect($cuid->toString())->toBe($value);
|
||||
expect($cuid->getValue())->toBe($value);
|
||||
});
|
||||
|
||||
it('creates Cuid from components', function () {
|
||||
$timestamp = 1609459200000; // 2021-01-01 00:00:00.000 UTC
|
||||
$counter = 1234;
|
||||
$fingerprint = 'abcd';
|
||||
$random = '12345678';
|
||||
|
||||
$cuid = Cuid::fromComponents($timestamp, $counter, $fingerprint, $random);
|
||||
|
||||
expect($cuid->getTimestamp())->toBe($timestamp);
|
||||
expect($cuid->getCounter())->toBe($counter);
|
||||
expect($cuid->getFingerprint())->toBe($fingerprint);
|
||||
expect($cuid->getRandom())->toBe($random);
|
||||
expect($cuid->toString())->toStartWith('c');
|
||||
});
|
||||
|
||||
it('validates Cuid length', function () {
|
||||
expect(fn () => Cuid::fromString('c' . str_repeat('a', 30)))
|
||||
->toThrow(InvalidArgumentException::class, 'Cuid must be exactly 25 characters long');
|
||||
|
||||
expect(fn () => Cuid::fromString('ctooshort'))
|
||||
->toThrow(InvalidArgumentException::class, 'Cuid must be exactly 25 characters long');
|
||||
});
|
||||
|
||||
it('validates Cuid prefix', function () {
|
||||
expect(fn () => Cuid::fromString('x' . str_repeat('a', 24)))
|
||||
->toThrow(InvalidArgumentException::class, 'Cuid must start with "c"');
|
||||
});
|
||||
|
||||
it('validates Cuid characters', function () {
|
||||
expect(fn () => Cuid::fromString('c' . str_repeat('!', 24)))
|
||||
->toThrow(InvalidArgumentException::class, 'Cuid contains invalid characters');
|
||||
});
|
||||
|
||||
it('validates component lengths', function () {
|
||||
$timestamp = 1609459200000;
|
||||
$counter = 1234;
|
||||
|
||||
expect(fn () => Cuid::fromComponents($timestamp, $counter, 'abc', '12345678'))
|
||||
->toThrow(InvalidArgumentException::class, 'Fingerprint must be exactly 4 characters');
|
||||
|
||||
expect(fn () => Cuid::fromComponents($timestamp, $counter, 'abcd', '1234567'))
|
||||
->toThrow(InvalidArgumentException::class, 'Random part must be exactly 8 characters');
|
||||
});
|
||||
|
||||
it('parses timestamp correctly', function () {
|
||||
$expectedTimestamp = 1609459200000; // 2021-01-01 00:00:00.000 UTC
|
||||
$cuid = Cuid::fromComponents($expectedTimestamp, 0, 'abcd', '12345678');
|
||||
|
||||
expect($cuid->getTimestamp())->toBe($expectedTimestamp);
|
||||
});
|
||||
|
||||
it('gets DateTime from timestamp', function () {
|
||||
$timestamp = 1609459200500; // 2021-01-01 00:00:00.500 UTC
|
||||
$cuid = Cuid::fromComponents($timestamp, 0, 'abcd', '12345678');
|
||||
|
||||
$dateTime = $cuid->getDateTime();
|
||||
|
||||
expect($dateTime->getTimestamp())->toBe(1609459200); // Seconds part
|
||||
expect($dateTime->format('u'))->toBe('500000'); // Microseconds part
|
||||
});
|
||||
|
||||
it('checks equality between Cuids', function () {
|
||||
$value = 'cjld2cjxh0000qzrmn831i7rn';
|
||||
$cuid1 = Cuid::fromString($value);
|
||||
$cuid2 = Cuid::fromString($value);
|
||||
$cuid3 = Cuid::fromString('cjld2cjxh0000qzrmn831i7ro');
|
||||
|
||||
expect($cuid1->equals($cuid2))->toBeTrue();
|
||||
expect($cuid1->equals($cuid3))->toBeFalse();
|
||||
});
|
||||
|
||||
it('compares Cuids for sorting', function () {
|
||||
$value1 = 'cjld2cjxh0000qzrmn831i7rn';
|
||||
$value2 = 'cjld2cjxh0000qzrmn831i7ro'; // Lexicographically greater
|
||||
|
||||
$cuid1 = Cuid::fromString($value1);
|
||||
$cuid2 = Cuid::fromString($value2);
|
||||
|
||||
expect($cuid1->compare($cuid2))->toBeLessThan(0);
|
||||
expect($cuid2->compare($cuid1))->toBeGreaterThan(0);
|
||||
expect($cuid1->compare($cuid1))->toBe(0);
|
||||
});
|
||||
|
||||
it('checks age comparisons', function () {
|
||||
$olderTimestamp = 1609459200000; // 2021-01-01 00:00:00.000 UTC
|
||||
$newerTimestamp = 1609459201000; // 1 second later
|
||||
|
||||
$olderCuid = Cuid::fromComponents($olderTimestamp, 0, 'abcd', '12345678');
|
||||
$newerCuid = Cuid::fromComponents($newerTimestamp, 0, 'abcd', '87654321');
|
||||
|
||||
expect($olderCuid->isOlderThan($newerCuid))->toBeTrue();
|
||||
expect($newerCuid->isNewerThan($olderCuid))->toBeTrue();
|
||||
expect($olderCuid->isNewerThan($newerCuid))->toBeFalse();
|
||||
expect($newerCuid->isOlderThan($olderCuid))->toBeFalse();
|
||||
});
|
||||
|
||||
it('calculates age in milliseconds', function () {
|
||||
$timestamp = intval(microtime(true) * 1000) - 5000; // 5 seconds ago
|
||||
$cuid = Cuid::fromComponents($timestamp, 0, 'abcd', '12345678');
|
||||
|
||||
$ageMs = $cuid->getAgeInMilliseconds();
|
||||
|
||||
expect($ageMs)->toBeGreaterThanOrEqual(4900); // Allow some tolerance
|
||||
expect($ageMs)->toBeLessThanOrEqual(5100);
|
||||
});
|
||||
|
||||
it('calculates age in seconds', function () {
|
||||
$timestamp = intval(microtime(true) * 1000) - 3000; // 3 seconds ago
|
||||
$cuid = Cuid::fromComponents($timestamp, 0, 'abcd', '12345678');
|
||||
|
||||
$ageSeconds = $cuid->getAgeInSeconds();
|
||||
|
||||
expect($ageSeconds)->toBeGreaterThanOrEqual(2.9);
|
||||
expect($ageSeconds)->toBeLessThanOrEqual(3.1);
|
||||
});
|
||||
|
||||
it('checks same process', function () {
|
||||
$cuid1 = Cuid::fromComponents(1609459200000, 0, 'abcd', '12345678');
|
||||
$cuid2 = Cuid::fromComponents(1609459201000, 1, 'abcd', '87654321'); // Same fingerprint
|
||||
$cuid3 = Cuid::fromComponents(1609459202000, 2, 'efgh', '11223344'); // Different fingerprint
|
||||
|
||||
expect($cuid1->isSameProcess($cuid2))->toBeTrue();
|
||||
expect($cuid1->isSameProcess($cuid3))->toBeFalse();
|
||||
});
|
||||
|
||||
it('converts to string using magic method', function () {
|
||||
$value = 'cjld2cjxh0000qzrmn831i7rn';
|
||||
$cuid = Cuid::fromString($value);
|
||||
|
||||
expect((string)$cuid)->toBe($value);
|
||||
});
|
||||
|
||||
it('parses all components correctly', function () {
|
||||
// Create a known Cuid and verify all components are parsed correctly
|
||||
$timestamp = 1609459200000;
|
||||
$counter = 1234;
|
||||
$fingerprint = 'test';
|
||||
$random = 'abcd1234';
|
||||
|
||||
$cuid = Cuid::fromComponents($timestamp, $counter, $fingerprint, $random);
|
||||
|
||||
// Parse it back
|
||||
$parsed = Cuid::fromString($cuid->toString());
|
||||
|
||||
expect($parsed->getTimestamp())->toBe($timestamp);
|
||||
expect($parsed->getCounter())->toBe($counter);
|
||||
expect($parsed->getFingerprint())->toBe($fingerprint);
|
||||
expect($parsed->getRandom())->toBe($random);
|
||||
});
|
||||
|
||||
it('handles Base36 conversion correctly', function () {
|
||||
// Test with various numbers to ensure Base36 conversion works
|
||||
$testCases = [
|
||||
['timestamp' => 1609459200000, 'counter' => 0],
|
||||
['timestamp' => 1609459200000, 'counter' => 35], // Max single digit in Base36
|
||||
['timestamp' => 1609459200000, 'counter' => 36], // Two digits in Base36
|
||||
['timestamp' => 1609459200000, 'counter' => 1295], // Multiple digits
|
||||
];
|
||||
|
||||
foreach ($testCases as $case) {
|
||||
$cuid = Cuid::fromComponents(
|
||||
$case['timestamp'],
|
||||
$case['counter'],
|
||||
'test',
|
||||
'abcd1234'
|
||||
);
|
||||
|
||||
$parsed = Cuid::fromString($cuid->toString());
|
||||
|
||||
expect($parsed->getTimestamp())->toBe($case['timestamp']);
|
||||
expect($parsed->getCounter())->toBe($case['counter']);
|
||||
}
|
||||
});
|
||||
|
||||
it('throws exception for empty Cuid', function () {
|
||||
expect(fn () => Cuid::fromString(''))
|
||||
->toThrow(InvalidArgumentException::class, 'Cuid cannot be empty');
|
||||
});
|
||||
|
||||
it('maintains lexicographic ordering by timestamp', function () {
|
||||
$timestamp1 = 1609459200000;
|
||||
$timestamp2 = 1609459201000; // 1 second later
|
||||
|
||||
$cuid1 = Cuid::fromComponents($timestamp1, 0, 'abcd', '12345678');
|
||||
$cuid2 = Cuid::fromComponents($timestamp2, 0, 'abcd', '12345678');
|
||||
|
||||
// String comparison should match timestamp order
|
||||
expect($cuid1->toString() < $cuid2->toString())->toBeTrue();
|
||||
});
|
||||
|
||||
it('handles maximum timestamp values', function () {
|
||||
$maxTimestamp = (36 ** 8) - 1; // Max value for 8 Base36 digits
|
||||
$cuid = Cuid::fromComponents($maxTimestamp, 0, 'abcd', '12345678');
|
||||
|
||||
expect($cuid->getTimestamp())->toBe($maxTimestamp);
|
||||
});
|
||||
|
||||
it('handles maximum counter values', function () {
|
||||
$maxCounter = (36 ** 4) - 1; // Max value for 4 Base36 digits
|
||||
$cuid = Cuid::fromComponents(1609459200000, $maxCounter, 'abcd', '12345678');
|
||||
|
||||
expect($cuid->getCounter())->toBe($maxCounter);
|
||||
});
|
||||
Reference in New Issue
Block a user