country); self::assertSame('Paris', $location->city); self::assertSame('192.168.1.1', $location->ip); } #[Test] public function fromIpCreatesLocationWithCountryOnly(): void { $location = Location::fromIp('10.0.0.1', 'Germany', null); self::assertSame('Germany', $location->country); self::assertNull($location->city); } #[Test] public function unknownCreatesUnknownLocation(): void { $location = Location::unknown(); self::assertNull($location->country); self::assertNull($location->city); self::assertNull($location->ip); } #[Test] public function formatReturnsCountryAndCity(): void { $location = Location::fromIp('192.168.1.1', 'France', 'Paris'); self::assertSame('France, Paris', $location->format()); } #[Test] public function formatReturnsCountryOnlyWhenNoCityAvailable(): void { $location = Location::fromIp('10.0.0.1', 'Germany', null); self::assertSame('Germany', $location->format()); } #[Test] public function formatReturnsInconnuWhenUnknown(): void { $location = Location::unknown(); self::assertSame('Inconnu', $location->format()); } #[Test] public function formatReturnsInconnuForPrivateIpRanges(): void { $location = Location::fromIp('192.168.1.1', null, null); self::assertSame('Inconnu', $location->format()); } #[Test] public function reconstituteRestoresFromStorage(): void { $location = Location::reconstitute( ip: '8.8.8.8', country: 'United States', city: 'Mountain View', ); self::assertSame('8.8.8.8', $location->ip); self::assertSame('United States', $location->country); self::assertSame('Mountain View', $location->city); } }