From 5c7a687d60d65c23283e96793e3b27b4e28d12fa Mon Sep 17 00:00:00 2001 From: Jordy Van der Haegen Date: Sun, 19 Oct 2025 19:04:31 +0200 Subject: [PATCH 1/4] docs: improve testing docs and provide a pest example --- README.md | 75 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 67f2b68..4de5f1b 100644 --- a/README.md +++ b/README.md @@ -589,32 +589,77 @@ To localize your post url see the example in [POST is not working](#post-is-not- ## Testing -During the test setup, the called route is not yet known. This means no language can be set. -When a request is made during a test, this results in a 404 - without the prefix set the localized route does not seem to exist. +In a typical request lifecycle, your application is bootstrapped automatically — allowing this package to detect the active route and set the appropriate locale. +However, when running tests, the application is bootstrapped before any request is made. As a result, the package can’t determine the current route, which often leads to a `404` error. -To fix this, you can use this function to manually set the language prefix: +To handle this, you can manually define the locale prefix in your tests by refreshing the application with a specific locale: + +### PHPUnit ```php -// TestCase.php -protected function refreshApplicationWithLocale($locale) +use Illuminate\Foundation\Testing\TestCase as BaseTestCase; +use Mcamara\LaravelLocalization\LaravelLocalization; + +abstract class TestCase extends BaseTestCase { - self::tearDown(); - putenv(LaravelLocalization::ENV_ROUTE_KEY . '=' . $locale); - self::setUp(); + protected function refreshApplicationWithLocale(string $locale): void + { + self::tearDown(); + putenv(LaravelLocalization::ENV_ROUTE_KEY . '=' . $locale); + self::setUp(); + } + + protected function tearDown(): void + { + putenv(LaravelLocalization::ENV_ROUTE_KEY); + parent::tearDown(); + } } +``` -protected function tearDown(): void +```php +final class HomeControllerTest extends TestCase { - putenv(LaravelLocalization::ENV_ROUTE_KEY); - parent::tearDown(); + public function it_can_visit_the_home_page() + { + $this->refreshApplicationWithLocale('en'); + + $response = $this->get('/en'); + + $response->assertStatus(200); + } } +``` -// YourTest.php -public function testBasicTest() +### Pest +```php +// Pest.php +use Mcamara\LaravelLocalization\LaravelLocalization; + +function refreshApplicationWithLocale(string $locale): void { - $this->refreshApplicationWithLocale('en'); - // Testing code + /** @var \Tests\TestCase $test */ + $test = test(); + + $test->tearDown(); + putenv(LaravelLocalization::ENV_ROUTE_KEY . '=' . $locale); + $test->setUp(); } + +pest()->afterEach(function () { + putenv(LaravelLocalization::ENV_ROUTE_KEY); +}); ``` +```php +// YourTest.php +test('it can visit the home page', function () { + refreshApplicationWithLocale('en'); + + $response = $this->get('/en'); + + $response->assertStatus(200); +}); +``` + ## Collaborators - [Adam Nielsen (iwasherefirst2)](https://github.com/iwasherefirst2) From b18d6d5dc2e151d98bee0b2f8741972dbc852338 Mon Sep 17 00:00:00 2001 From: Jordy Van der Haegen Date: Mon, 20 Oct 2025 21:17:03 +0200 Subject: [PATCH 2/4] refactor: replace testbench-browser-kit with testbench --- composer.json | 2 +- tests/LaravelLocalizationTest.php | 59 ++++++++++--------------------- tests/TestCase.php | 2 +- 3 files changed, 21 insertions(+), 42 deletions(-) diff --git a/composer.json b/composer.json index ebb9695..1e406ca 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "laravel/framework": "^10.0|^11.0|^12.0" }, "require-dev": { - "orchestra/testbench-browser-kit": "^8.5|^9.0|^10.0", + "orchestra/testbench": "^8.5|^9.0|^10.0", "phpunit/phpunit": "^10.1|^11.0" }, "suggest": { diff --git a/tests/LaravelLocalizationTest.php b/tests/LaravelLocalizationTest.php index 6281f05..d5c81d0 100644 --- a/tests/LaravelLocalizationTest.php +++ b/tests/LaravelLocalizationTest.php @@ -252,19 +252,15 @@ public function testGetLocalizedURL(): void app('laravellocalization')->setLocale('en'); - $crawler = $this->call( - 'GET', - self::TEST_URL.'about', - [], - [], - [], - ['HTTP_ACCEPT_LANGUAGE' => 'en,es'] + $response = $this->get( + uri: self::TEST_URL.'about', + headers: ['HTTP_ACCEPT_LANGUAGE' => 'en,es'] ); - $this->assertResponseOk(); + $response->assertStatus(200); $this->assertEquals( self::TEST_URL.'es/acerca', - $crawler->getContent() + $response->getContent() ); $this->refreshApplication(); @@ -281,19 +277,15 @@ public function testGetLocalizedURL(): void app('laravellocalization')->getLocalizedURL('en', self::TEST_URL.'test?a=1') ); - $crawler = $this->call( - 'GET', - app('laravellocalization')->getLocalizedURL('en', self::TEST_URL.'test'), - [], - [], - [], - ['HTTP_ACCEPT_LANGUAGE' => 'en,es'] + $response = $this->get( + uri: app('laravellocalization')->getLocalizedURL('en', self::TEST_URL.'test'), + headers: ['HTTP_ACCEPT_LANGUAGE' => 'en,es'] ); - $this->assertResponseOk(); + $response->assertStatus(200); $this->assertEquals( 'Test text', - $crawler->getContent() + $response->getContent() ); $this->refreshApplication('es'); @@ -370,19 +362,15 @@ public static function getRouteNameFromAPathDataProvider(): array } public function testGetLocalizedUrlForIgnoredUrls(): void { - $crawler = $this->call( - 'GET', - self::TEST_URL.'skipped', - [], - [], - [], - ['HTTP_ACCEPT_LANGUAGE' => 'en,es'] + $response = $this->get( + uri: self::TEST_URL.'skipped', + headers: ['HTTP_ACCEPT_LANGUAGE' => 'en,es'] ); - $this->assertResponseOk(); + $response->assertStatus(200); $this->assertEquals( self::TEST_URL.'skipped', - $crawler->getContent() + $response->getContent() ); } @@ -881,19 +869,10 @@ public function testRedirectWithHiddenDefaultLocaleInUrlAndSavedLocale() $savedLocale = 'es'; - $crawler = $this->call( - 'GET', - self::TEST_URL, - [], - ['locale' => $savedLocale], - [], - [] - ); - - $this->assertResponseStatus(302); - $this->assertRedirectedTo(self::TEST_URL . $savedLocale); + $response = $this->withUnencryptedCookie('locale', $savedLocale)->get(self::TEST_URL); - $localeCookie = $crawler->headers->getCookies()[0]; - $this->assertEquals($savedLocale, $localeCookie->getValue()); + $response->assertStatus(302); + $response->assertRedirect(self::TEST_URL . $savedLocale); + $response->assertPlainCookie('locale', $savedLocale); } } diff --git a/tests/TestCase.php b/tests/TestCase.php index 1c94233..b0e8193 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -4,7 +4,7 @@ use Mcamara\LaravelLocalization\Facades\LaravelLocalization; use Mcamara\LaravelLocalization\LaravelLocalizationServiceProvider; -use Orchestra\Testbench\BrowserKit\TestCase as BaseTestCase; +use Orchestra\Testbench\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase { From ad4ef784f6b574d082f9e0873f470ff5c19f8c24 Mon Sep 17 00:00:00 2001 From: Jordy Van der Haegen Date: Mon, 20 Oct 2025 21:20:27 +0200 Subject: [PATCH 3/4] refactor: apply correct order of arguments for assertEquals --- tests/LaravelLocalizationTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/LaravelLocalizationTest.php b/tests/LaravelLocalizationTest.php index d5c81d0..b6a2678 100644 --- a/tests/LaravelLocalizationTest.php +++ b/tests/LaravelLocalizationTest.php @@ -140,18 +140,18 @@ protected function getEnvironmentSetUp($app) public function testSetLocale(): void { - $this->assertEquals(route('about'), 'http://localhost/about'); + $this->assertEquals('http://localhost/about', route('about')); $this->refreshApplication('es'); $this->assertEquals('es', app('laravellocalization')->setLocale('es')); $this->assertEquals('es', app('laravellocalization')->getCurrentLocale()); - $this->assertEquals(route('about'), 'http://localhost/acerca'); + $this->assertEquals('http://localhost/acerca', route('about')); $this->refreshApplication(); $this->assertEquals('en', app('laravellocalization')->setLocale('en')); - $this->assertEquals(route('about'), 'http://localhost/about'); + $this->assertEquals('http://localhost/about', route('about')); $this->assertNull(app('laravellocalization')->setLocale('de')); $this->assertEquals('en', app('laravellocalization')->getCurrentLocale()); From c9d67bf1f49cc2de1d72d71ee26f9719d808c75f Mon Sep 17 00:00:00 2001 From: Jordy Van der Haegen Date: Mon, 20 Oct 2025 21:32:27 +0200 Subject: [PATCH 4/4] refactor: import namespaces and route registration --- tests/LaravelLocalizationTest.php | 82 +++++++++++++++---------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/tests/LaravelLocalizationTest.php b/tests/LaravelLocalizationTest.php index b6a2678..e156f77 100644 --- a/tests/LaravelLocalizationTest.php +++ b/tests/LaravelLocalizationTest.php @@ -4,7 +4,13 @@ use PHPUnit\Framework\Attributes\DataProvider; use Illuminate\Support\Facades\Request; +use Illuminate\Support\Facades\Route; +use Mcamara\LaravelLocalization\Facades\LaravelLocalization as LaravelLocalizationFacade; +use Mcamara\LaravelLocalization\LanguageNegotiator; use Mcamara\LaravelLocalization\LaravelLocalization; +use Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter; +use Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes; +use Mcamara\LaravelLocalization\Middleware\LocaleCookieRedirect; final class LaravelLocalizationTest extends TestCase { @@ -25,41 +31,41 @@ protected function setRoutes($locale = false) app('laravellocalization')->setLocale($locale); } - app('router')->group([ - 'prefix' => app('laravellocalization')->setLocale(), + Route::group([ + 'prefix' => LaravelLocalizationFacade::setLocale(), 'middleware' => [ - 'Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes', - 'Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter', + LaravelLocalizationRoutes::class, + LaravelLocalizationRedirectFilter::class, ], ], function () { - app('router')->get('/', ['as'=> 'index', function () { + Route::get('/', function () { return app('translator')->get('LaravelLocalization::routes.hello'); - }, ]); + })->name('index'); - app('router')->get('test', ['as'=> 'test', function () { + Route::get('test', function () { return app('translator')->get('LaravelLocalization::routes.test_text'); - }, ]); + })->name('test'); - app('router')->get(app('laravellocalization')->transRoute('LaravelLocalization::routes.about'), ['as'=> 'about', function () { + Route::get(app('laravellocalization')->transRoute('LaravelLocalization::routes.about'), function () { return app('laravellocalization')->getLocalizedURL('es') ?: 'Not url available'; - }, ]); + })->name('about'); - app('router')->get(app('laravellocalization')->transRoute('LaravelLocalization::routes.view'), ['as'=> 'view', function () { + Route::get(app('laravellocalization')->transRoute('LaravelLocalization::routes.view'), function () { return app('laravellocalization')->getLocalizedURL('es') ?: 'Not url available'; - }, ]); + })->name('view'); - app('router')->get(app('laravellocalization')->transRoute('LaravelLocalization::routes.view_project'), ['as'=> 'view_project', function () { + Route::get(app('laravellocalization')->transRoute('LaravelLocalization::routes.view_project'), function () { return app('laravellocalization')->getLocalizedURL('es') ?: 'Not url available'; - }, ]); + })->name('view_project'); - app('router')->get(app('laravellocalization')->transRoute('LaravelLocalization::routes.manage'), ['as'=> 'manage', function () { + Route::get(app('laravellocalization')->transRoute('LaravelLocalization::routes.manage'), function () { return app('laravellocalization')->getLocalizedURL('es') ?: 'Not url available'; - }, ]); + })->name('manage'); }); - app('router')->get('/skipped', ['as'=> 'skipped', function () { + Route::get('/skipped', function () { return Request::url(); - }, ]); + })->name('skipped'); } /** @@ -764,13 +770,11 @@ public function testLanguageNegotiation($accept_string, $must_resolve_to, $asd = $request = $this->createMock(\Illuminate\Http\Request::class); $request->expects($this->any())->method('header')->with('Accept-Language')->willReturn($accept_string); - $negotiator = app(\Mcamara\LaravelLocalization\LanguageNegotiator::class, - [ - 'defaultLocale' => 'wrong', - 'supportedLanguages' => $full_config['supportedLocales'], - 'request' => $request - ] - ); + $negotiator = app(LanguageNegotiator::class, [ + 'defaultLocale' => 'wrong', + 'supportedLanguages' => $full_config['supportedLocales'], + 'request' => $request + ]); $language = $negotiator->negotiateLanguage(); @@ -819,13 +823,11 @@ public function testLanguageNegotiationWithMapping(): void { $request = $this->createMock(\Illuminate\Http\Request::class); $request->expects($this->any())->method('header')->with('Accept-Language')->willReturn($accept_string); - $negotiator = app(\Mcamara\LaravelLocalization\LanguageNegotiator::class, - [ - 'defaultLocale' => 'wrong', - 'supportedLanguages' => $full_config['supportedLocales'], - 'request' => $request - ] - ); + $negotiator = app(LanguageNegotiator::class, [ + 'defaultLocale' => 'wrong', + 'supportedLanguages' => $full_config['supportedLocales'], + 'request' => $request + ]); $language = $negotiator->negotiateLanguage(); @@ -849,20 +851,18 @@ public function testSetLocaleWithMapping(): void $this->assertEquals('http://localhost/custom', app('laravellocalization')->localizeURL('http://localhost/custom', 'en')); } - - public function testRedirectWithHiddenDefaultLocaleInUrlAndSavedLocale() { - app('router')->group([ - 'prefix' => app('laravellocalization')->setLocale(), + Route::group([ + 'prefix' => LaravelLocalizationFacade::setLocale(), 'middleware' => [ - 'Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter', - 'Mcamara\LaravelLocalization\Middleware\LocaleCookieRedirect', + LaravelLocalizationRedirectFilter::class, + LocaleCookieRedirect::class, ], - ], function (){ - app('router')->get('/', ['as'=> 'index', function () { + ], function () { + Route::get('/', function () { return 'Index page'; - }, ]); + })->name('index'); }); app('config')->set('laravellocalization.hideDefaultLocaleInURL', true);