seed(CityWorldSeeder::class); } /** * Two viewers polling within the same second each get their own * is_me flags from the shared cache. */ public function test_is_me_is_per_viewer_with_shared_cache(): void { [$userA, $charA] = $this->makeCitizen(); [$userB, $charB] = $this->makeCitizen(); // Viewer A seeds the shared per-second cache first. $first = $this->actingAs($userA) ->getJson('/city/presence') ->assertOk() ->json('citizens'); $this->assertTrue($this->flagFor($first, $charA->id), 'A must see itself as me'); $this->assertFalse($this->flagFor($first, $charB->id), 'A must not see B as me'); // Viewer B hits the SAME cache entry moments later. $second = $this->actingAs($userB) ->getJson('/city/presence') ->assertOk() ->json('citizens'); $this->assertTrue($this->flagFor($second, $charB->id), 'B must see itself as me'); $this->assertFalse($this->flagFor($second, $charA->id), 'B must not see A as me'); } /** * Create an active user paired with its in-world character. * * @return array{0: User, 1: Character} */ private function makeCitizen(): array { $user = User::factory()->create([ 'status' => User::STATUS_ACTIVE, 'is_active' => true, ]); return [$user, Character::ensureForUser($user)]; } /** * Extract the is_me flag for a character id from a presence payload. * * @param list> $citizens */ private function flagFor(array $citizens, int $characterId): bool { foreach ($citizens as $c) { if ((int) $c['id'] === $characterId) { return (bool) $c['is_me']; } } $this->fail("Character {$characterId} missing from presence payload"); } }