Summer Sale! All accounts are 50% off this week.

sebastiansulinski's avatar

Testing conditional route existence

I have some routes that are only added to the routes file based on the condition that's coming from one of the config files.

What I'm trying to do is to reload routes before the test. Here's what I have:

/**
 * @test
 */
public function routes_are_not_available_if_module_is_disabled()
{
    config(['module.active' => []]);
    
    // here is where I would need to rebind/reload routes
    // to take into account configuration change

    $this->seed();

    $this->assertDatabaseMissing('pages', ['module' => Gallery::class]);
    
    try {
        
        $this->get(route('front.gallery'));
        
    } catch (\InvalidArgumentException $exception) {
        
        return;
        
    }
    
    $this->fail('Route was present even though it was disabled.');
}

The config file config/module.php contains index active, which lists active modules:

'active' => [
    App\Components\Module\Home::class,
    App\Components\Module\Gallery::class
],

Routes are bound via method call routes/front.php

//...
Gallery::routes();

And the Gallery and Module classes:

class Gallery extends Module 
{
    
    public static function routes(): void
    {
        if (!static::isActive()) {
            return;
        }

        app('router')->get('gallery', 'GalleryController@index')
            ->name('front.gallery');

        app('router')->get('gallery/{gallery_slug}', 'GalleryController@show')
            ->name('front.gallery.show');
    }
    
}

abstract class Module
{
    public static function isActive(): bool
    {
        return in_array(static::class, config('module.active'));
    }
}

Test is only passing when I manually remove App\Components\Module\Gallery::class from the config's active index, but I obviously want it to work regardless of the change in the live configuration.

Does anyone know of a way of reloading routes after configuration change during tests?

0 likes
2 replies
sebastiansulinski's avatar

Ok - in case anyone is interested in resolving similar issue - I've changed the strategy a little and moved the check to the App\Http\Middleware\VerifyModule middleware - although routes will actually get registered, they will return 404 when someone tries to call them.

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Response;

class VerifyModule
{
    public function handle($request, Closure $next, string $module)
    {
        if (!in_array($module, config('module.active'))) {
            return abort(Response::HTTP_NOT_FOUND);
        }

        return $next($request);
    }
}

Then, removed check from within Gallery::routes() method, leaving just route binding, but this time with the middleware

public static function routes(): void
{
    app('router')->get('gallery', 'GalleryController@index')
        ->name('front.gallery')
        ->middleware('module:App\Components\Module\Gallery');

    app('router')->get('gallery/{gallery_slug}', 'GalleryController@show')
        ->name('front.gallery.show')
        ->middleware('module:App\Components\Module\Gallery');
} 

and my test is now changed to

/**
 * @test
 */
public function routes_return_404_if_module_is_disabled()
{
    config(['module.active' => []]);

    $this->seed();

    $this->assertDatabaseMissing('pages', ['module' => Gallery::class]);

    $response = $this->get(route('front.gallery'));

    $this->assertResponseNotFound($response);
}
1 like

Please or to participate in this conversation.