phpvms/tests/Feature/HasNanoIdsTest.php
Nabeel S. 20b68b8f35
ci: fix the broken test (#2252)
* ci: fix the broken test

* Fix the test fixture

* Fix the test fixture
2026-07-01 15:50:25 -05:00

92 lines
3.2 KiB
PHP

<?php
declare(strict_types=1);
use App\Contracts\Model;
use App\Models\File;
use Illuminate\Support\Str;
/*
|--------------------------------------------------------------------------
| Trait Testing: HasNanoIds
|--------------------------------------------------------------------------
|
| The model-level tests use the File model, but they verify the global
| behavior of the HasNanoIds trait. Any model using the trait—File, Flight,
| Pirep, Acars—gets the same Nano ID primary key handling.
|
*/
it('generates a nano id at the configured length and alphabet', function (): void {
$id = Str::nanoid();
expect($id)
->toBeString()
->and(strlen($id))->toBe(Model::ID_MAX_LENGTH)
->and($id)->toMatch('/^['.Model::ID_ALPHABET.']+$/');
});
it('honors a custom nano id length', function (): void {
expect(strlen(Str::nanoid(24)))->toBe(24);
});
it('validates nano ids', function (): void {
expect(Str::isNanoid(Str::nanoid()))->toBeTrue()
->and(Str::isNanoid('UPPER'.Str::nanoid(11)))->toBeFalse() // out of alphabet
->and(Str::isNanoid(Str::nanoid(8)))->toBeFalse() // wrong length
->and(Str::isNanoid(123))->toBeFalse(); // non-string
});
it('assigns a nano id primary key on create', function (): void {
$file = File::factory()->create();
expect(Str::isNanoid($file->id))->toBeTrue();
});
it('preserves an explicitly set primary key', function (): void {
$file = File::factory()->create(['id' => 'mycustomid000001']);
expect($file->id)->toBe('mycustomid000001');
});
it('reports a non-incrementing string key', function (): void {
$file = new File();
expect($file->getKeyType())->toBe('string')
->and($file->getIncrementing())->toBeFalse();
});
it('returns null for an unknown id during route-model binding', function (): void {
// Route binding no longer rejects keys purely on Nano ID format — the
// database decides existence. An id that matches no row resolves to null
// (a 404 over HTTP), it does not throw.
expect(new File()->resolveRouteBinding('not a valid id!'))->toBeNull();
});
it('resolves a valid nano id during route-model binding', function (): void {
$file = File::factory()->create();
$resolved = new File()->resolveRouteBinding($file->id);
expect($resolved)->not->toBeNull()
->and($resolved->id)->toBe($file->id);
});
it('resolves a legacy non-format primary key during route-model binding', function (): void {
// Regression guard: tables still hold pre-migration keys — older Nano IDs
// generated with a different (mixed-case) alphabet that fail today's
// lowercase-only Str::isNanoid(). These are valid rows and must still
// resolve; the strict format gate used to 404 every one of them (e.g. admin
// PIREP view/edit links). Uppercase keeps this out of the current alphabet
// while still fitting the 16-char id column.
$legacyId = 'ABCDEF0123456789';
$file = File::factory()->create(['id' => $legacyId]);
expect(Str::isNanoid($legacyId))->toBeFalse();
$resolved = new File()->resolveRouteBinding($file->id);
expect($resolved)->not->toBeNull()
->and($resolved->id)->toBe($legacyId);
});