jpmg's avatar
Level 13

Problem with pest test factory

Hello everyone i make a test for a Livewire component in my render method I have something like this.

public function render()
{
    return view('livewire.principal.reg-usuario', [
        'listGender' => Gender::all()->sortBy('id'),
        'ListIdentity' => Identity::all()->sortBy('id'),
        'listStatus' => State::listStates([1, 2])->get(),
        'listRoles' => Role::listRoles([2, 3, 4, 5, 6])->get(),
        'listBranch' => Branch::lisBrach()->get(),
    ])
        ->extends('layouts.app', ['title' => 'Usuario'])
        ->section('workspace');
}

and my pest test is like this.

it('can call ListIdentity values', function () {
       $this->actingAs($this->user);
       $identityArray = Identity::factory()->count(2)->create();
       $component = livewire(RegUsuario::class,   ['ListIdentity' => $identityArray]);
       dd(count($component->viewData('ListIdentity')));    ------> return 3 instances
       expect($arrayIdentity)->toHaveCount(2);
 });

My question is why it returns 3 instances when I am telling it that it creates 2 instances of Identity::factory()->count(2)->create() ?

thanks for any kind of help

0 likes
4 replies
LaryAI's avatar
Level 58

It seems like there might be a misunderstanding in how the Livewire component is being tested. When you pass the 'ListIdentity' => $identityArray to the Livewire component, it doesn't replace the component's internal behavior of fetching Identity::all()->sortBy('id') within the render method. Instead, it adds to the component's parameters.

To properly test the Livewire component, you should not pass the 'ListIdentity' directly to the component. Instead, you should let the component fetch the identities itself. Here's how you can modify your test:

it('can call ListIdentity values', function () {
    $this->actingAs($this->user);
    Identity::factory()->count(2)->create();
    
    $component = Livewire::test(RegUsuario::class);
    
    $viewDataListIdentity = $component->viewData('listIdentity');
    
    // Use the actual variable name 'listIdentity' as defined in the render method
    // and ensure the count matches the number of created factory models.
    expect($viewDataListIdentity)->toHaveCount(2);
});

Make sure that the factory is creating the identities in the database and that the Livewire component is fetching them as it would during normal execution. Also, ensure that the variable names are consistent between the test and the component (listIdentity instead of ListIdentity).

If you want to control the database state explicitly and ensure that no other records are interfering with your test, you might want to run the test within a database transaction or use the DatabaseMigrations trait to refresh the database before each test.

jpmg's avatar
Level 13

@LaryAI It didn't work again, it returns an array of 3.

`Illuminate\Database\Eloquent\Collection]8;;file:///home/juanpmg/Documentos/FinalApp/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Collection.php / tests/Feature/Livewire/Principal/RegUsuarioTest.php:52 #items: array:3 [......]

jpmg's avatar
Level 13

When I do dd my test, I get the following

 it('can call ListIdentity values', function () {
      $this->actingAs($this->user);
      $v1 = Identity::factory()->count(2)->create();
      dd(count($v1))--->return 2;
      $component = Livewire::test(RegUsuario::class);
      $viewDataListIdentity = $component->viewData('listIdentity');
      dd(count($viewDataListIdentity))--->return 3;
});

I don't understand why after calling my livewire component I get an additional value in listIdentity

jpmg's avatar
Level 13

Sorry I got the problem... when I was doing the factory for User.

	User::factory()->create()
  
	 public function definition()
     {
      return [
        'role_id' => Role::factory()->make(),
        'state_id' => State::factory()->make(),
        'identity_id' => Identity::factory()->make(),
        'gender_id' => Gender::factory()->make(),
        'branch_id' => Branch::factory()->make(),
        'name' => faker()->name,
        'lastname' => faker()->lastName
      ]
  }

I was calling my other relationships with the create() method, which made me already have a record. I changed it to the make() method and now it returns the number of necessary records.

Sorry for the inconvenience, I'm still investigating if that is the best way to create the user for testing

Please or to participate in this conversation.