assertSame(302, $resp['status']); $this->assertSame('/foo', $resp['redirect']); $this->assertTrue($resp['set_cookie']); $this->assertSame('en', $resp['cookie_value']); $this->assertGreaterThan(time(), $resp['cookie_expires']); } public function testCookieExpiresInOneYear(): void { $before = time(); $resp = LocaleController::buildResponse('uk', '/', null, false); $after = time(); $expected = 60 * 60 * 24 * 365; $this->assertGreaterThanOrEqual($before + $expected, $resp['cookie_expires']); $this->assertLessThanOrEqual($after + $expected, $resp['cookie_expires']); } public function testCookieSecureFlagMatchesHttps(): void { $http = LocaleController::buildResponse('en', '/', null, false); $https = LocaleController::buildResponse('en', '/', null, true); $this->assertFalse($http['cookie_secure']); $this->assertTrue($https['cookie_secure']); } public function testSupportsAllFourLocales(): void { foreach (['de', 'en', 'uk', 'ru'] as $code) { $resp = LocaleController::buildResponse($code, '/', null, false); $this->assertTrue($resp['set_cookie'], "Locale {$code} should set cookie"); $this->assertSame($code, $resp['cookie_value']); } } // ────────────────────────────────────────────── // buildResponse() — invalid locale // ────────────────────────────────────────────── public function testInvalidLocaleDoesNotSetCookie(): void { $resp = LocaleController::buildResponse('fr', '/', null, false); $this->assertFalse($resp['set_cookie']); $this->assertSame('', $resp['cookie_value']); } public function testInvalidLocaleStillRedirects(): void { $resp = LocaleController::buildResponse('fr', '/safe-path', null, false); $this->assertSame(302, $resp['status']); $this->assertSame('/safe-path', $resp['redirect']); } public function testNullLocaleDoesNotSetCookie(): void { $resp = LocaleController::buildResponse(null, '/', null, false); $this->assertFalse($resp['set_cookie']); } public function testEmptyStringLocaleDoesNotSetCookie(): void { $resp = LocaleController::buildResponse('', '/', null, false); $this->assertFalse($resp['set_cookie']); } // ────────────────────────────────────────────── // safeRedirect() — return URL sanitization // ────────────────────────────────────────────── #[DataProvider('provideOpenRedirectAttempts')] public function testRejectsOpenRedirects(string $bad, string $expected): void { $resp = LocaleController::buildResponse('en', $bad, null, false); $this->assertSame($expected, $resp['redirect']); } public static function provideOpenRedirectAttempts(): array { return [ 'absolute https' => ['https://evil.com/phish', '/'], 'absolute http' => ['http://evil.com/phish', '/'], 'protocol-relative' => ['//evil.com/phish', '/'], 'scheme-relative upper' => ['//EVIL.COM/phish', '/'], 'javascript scheme' => ['javascript:alert(1)', '/'], 'data scheme' => ['data:text/html,