kianaassenheimer's avatar

How to test SelectColumn in a Filament table?

I am using Filament and I am trying to test my SelectColum that when I change a role, that user's role is updated in the database. From the testing docs https://filamentphp.com/docs/3.x/tables/testing#select-columns , it doesn't seem like this type of functionality is testable through a method much like a filter can be applied with ->filterTable(... I'm wondering if there is a method such as selectColumn that I just can't find in the docs/through the ide.

edit I am using Filament tables in my Livewire component

Here is a barebones test:

/** @test */
    public function it_will_correctly_reassign_a_users_role(): void
    {
        // Given I have a user with an 'Admin' role
        $superadmin_role_id = Role::where('name', 'Superadmin')->first()->id;
        $admin_role_id = Role::where('name', 'Admin')->first()->id;
        $user          = User::factory()->create(['role_id' => $admin_role_id]);
        
        // When I change the role to 'Superadmin'
        Livewire::test(AdminClinicPageComponent::class, ['clinic' => $this->clinicA])
            ->selectColumn('role_id', $superadmin_role_id, record: $user);

        // Then my user's role should be 'Superadmin'
        $this->assertEquals($superadmin_role_id, $user->fresh()->role_id);
    }

Here is my code snippet

public function table(Table $table): Table
    {
        return $table
            ->query(
                User::query()
            )
            ->columns([
                // other text columns in my tables
                SelectColumn::make('role_id')
                    ->options($this->allowed_roles)
                    ->afterStateUpdated(function ($record, $state): void
                    {
                        $record->assignRole($state);
                        $record->refresh();
                    }),
            ]);
    }
0 likes
5 replies
tisuchi's avatar

@kianaassenheimer How about this?


/** @test */
public function it_will_correctly_reassign_a_users_role()
{
    $superadmin = Role::firstOrCreate(['name' => 'Superadmin']);
    $admin = Role::firstOrCreate(['name' => 'Admin']);
    $user = User::factory()->create(['role_id' => $admin->id]);
    
    Livewire::test(AdminClinicPageComponent::class)
        ->set('records.' . $user->id . '.role_id', $superadmin->id)
        ->call('save', $user->id) 
        ->assertEmitted('saved'); 

    $this->assertEquals($superadmin->id, $user->fresh()->role_id);
}
kianaassenheimer's avatar

@tisuchi That's what the automated Laracasts bot and openAI gave me. The issue is that record is not a public property on the livewire component, so cannot be accessed like you have with the ->set('records'. Also, there is no save method on the component, with Filament it happens automagically, so it would fail at that point too

ImpactLab's avatar

@kianaassenheimer I have got this working in a round-about way with updateTableColumnState:

$this->record->assign($user, MemberPosition::ANALYST);

$component = livewire(MembersTable::class, ['record' => $this->record]);

$component->call('updateTableColumnState', 'position', (string)$user->id, MemberPosition::QUALITY_ASSURANCE->value);

// Assert change has persisted
  	$pivot = $this->record->members()->where('user_id', $user->id)->first()->pivot;
    expect($pivot->position)->toBe(MemberPosition::QUALITY_ASSURANCE);

Please or to participate in this conversation.