diff --git a/src/Http/Controllers/CP/Concerns/ResolvesUserId.php b/src/Http/Controllers/CP/Concerns/ResolvesUserId.php index 26752a5..538f8be 100644 --- a/src/Http/Controllers/CP/Concerns/ResolvesUserId.php +++ b/src/Http/Controllers/CP/Concerns/ResolvesUserId.php @@ -15,9 +15,9 @@ private function resolveUserId(): string { $user = User::current(); - /** @var string $userId */ - $userId = $user ? $user->id() : ''; - - return $userId; + // Cast to string: Statamic's User->id() returns string under the file + // users driver but int under the Eloquent driver. The trait's return + // type contract (and downstream token storage) requires string. + return $user ? (string) $user->id() : ''; } } diff --git a/tests/Unit/Http/Controllers/CP/Concerns/ResolvesUserIdTest.php b/tests/Unit/Http/Controllers/CP/Concerns/ResolvesUserIdTest.php new file mode 100644 index 0000000..5ffc576 --- /dev/null +++ b/tests/Unit/Http/Controllers/CP/Concerns/ResolvesUserIdTest.php @@ -0,0 +1,48 @@ +id() returns an int (Eloquent driver)', function () { + $user = Mockery::mock(StatamicUserContract::class, Authenticatable::class); + $user->shouldReceive('id')->andReturn(42); + + User::shouldReceive('current')->andReturn($user); + + $result = (new ResolvesUserIdSubject)->resolveUserId(); + + expect($result)->toBe('42'); +}); + +it('returns the user id as a string when User->id() returns a string (file driver)', function () { + $user = Mockery::mock(StatamicUserContract::class, Authenticatable::class); + $user->shouldReceive('id')->andReturn('019357a0-7f6a-7000-a1b2-deadbeef0000'); + + User::shouldReceive('current')->andReturn($user); + + $result = (new ResolvesUserIdSubject)->resolveUserId(); + + expect($result)->toBe('019357a0-7f6a-7000-a1b2-deadbeef0000'); +}); + +it('returns an empty string when no user is authenticated', function () { + User::shouldReceive('current')->andReturn(null); + + $result = (new ResolvesUserIdSubject)->resolveUserId(); + + expect($result)->toBe(''); +});