Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

El Klo's avatar
Level 11

Filament Resource::getUrl fails

I have a filament app that uses the multi-tenancy functionality from v3. I have set up my test suite to act as a user and to set the tenant:

protected function setUp(): void {
		parent::setUp();

		$this->actingAs(User::factory([
			'is_admin' => true
		])->create());
		Filament::setTenant(Team::factory()->create());
	}

I have the following (pest )test:

it( 'can render the create page', function () {
	$tenant = Filament::getTenant();
	$url = UserResource::getUrl('create');
	//This dd returns the correct url, the url taht works in my browser
	//dd($url);
	$this->get($url)->assertSuccessful();
} );

The dd() gives the correct url as output. The url that works in my browser. However, the test keeps failing with a 404 as status code. All mny other tests work fine. It's just the tests that make use of the Resource::getUrl method that fail.

0 likes
2 replies
LaryAI's avatar
Level 58

It seems like the issue you're encountering is related to the test environment not properly recognizing the tenant context when generating URLs using Resource::getUrl. Since the dd() function outputs the correct URL, it's likely that the URL is being generated correctly, but the test environment is not set up to handle multi-tenancy in the same way your application does.

Here's a potential solution to ensure that your test environment is aware of the tenant context:

  1. Make sure that the tenant is being set up correctly in your test environment. You've already included the Filament::setTenant() call in your setUp method, which is good.

  2. Ensure that any middleware or other mechanisms your application uses to handle multi-tenancy are also being applied in the test environment. This might involve setting up the tenant context before making the request in your test.

  3. If your application uses subdomains or specific routes to handle different tenants, make sure that the test client is configured to request the correct subdomain or route.

Here's an example of how you might modify your test to ensure that the tenant context is correctly set up:

it('can render the create page', function () {
    $tenant = Filament::getTenant();

    // Set the tenant context for the test environment if necessary
    // For example, if your tenants are differentiated by subdomains:
    // $this->withSubdomain($tenant->subdomain);

    $url = UserResource::getUrl('create');

    // Ensure that the test client is aware of the tenant context
    // This might involve setting a specific header or session variable
    // that your application uses to identify the tenant.

    $response = $this->get($url);

    // Use assertStatus to check for a specific status code if necessary
    $response->assertStatus(200);
});

If your application uses subdomains for tenants, you might need to simulate the subdomain in your test environment. Here's an example of how you could do that:

protected function withSubdomain($subdomain)
{
    $this->app['config']->set('session.domain', $subdomain . '.yourapp.test');
    $this->app['url']->forceRootUrl('http://' . $subdomain . '.yourapp.test');
}

You would call this withSubdomain method in your test before making the request.

If the issue persists, you may need to debug further by checking the following:

  • Ensure that the route for the 'create' page is correctly defined and accessible in the test environment.
  • Verify that any route model bindings or other route-related logic is functioning as expected in the test environment.
  • Check if there are any differences in the application state or configuration between the test environment and your local development environment that could affect routing.

Remember to clear your test cache and configuration if you make changes to your environment or routing setup, as stale configurations can sometimes cause unexpected behavior in tests.

El Klo's avatar
El Klo
OP
Best Answer
Level 11

I can't believe i did not see this earlier, but in my TestCase i was setting up 2 different tenants. So my actingAs user and the Filament::setTenant method were using 2 different tenats. Here is the fix for anyone else who might run into the same problem:

protected function setUp(): void {
		parent::setUp();

		// Create a single team instance to be used both for the user and as the tenant.
		$team = Team::factory()->create();

		// Create a user and attach the team to the user.
		$user = User::factory([
			'is_admin' => true
		])->create();
		$user->teams()->attach($team);

		// Act as the created user.
		$this->actingAs($user);

		// Set the same team as the tenant in Filament.
		Filament::setTenant($team);
	}

Please or to participate in this conversation.