Saltearse al contenido

Testing

Creando tu primer Test

Añadiendo la opción -testal comando make:livewire, puedes generar un archivo de prueba junto con un componente:

php artisan make:livewire create-post --test

Además de generar los propios archivos de componentes, el comando anterior generará el siguiente archivo de prueba tests/Feature/Livewire/CreatePostTest.php:

Si desea crear una prueba PHP de Pest, puede proporcionar la opción --pest al comando make:livewire:

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\CreatePost;
use Livewire\Livewire;
use Tests\TestCase;
class CreatePostTest extends TestCase
{
/** @test */
public function renders_successfully()
{
Livewire::test(CreatePost::class)
->assertStatus(200);
}
}

Por supuesto, siempre puedes crear estos archivos a mano o incluso utilizar las utilidades de pruebas de Livewire dentro de cualquier otra prueba PHPUnit existente en tu aplicación Laravel.

Antes de seguir leyendo, es posible que desees familiarizarte con las propias características de prueba incorporadas de Laravel.

Probar que una página contiene un componente

La prueba Livewire más simple que puede escribir es la afirmación de que un punto final dado en su aplicación incluye y renderiza correctamente un componente Livewire dado.

Livewire proporciona un método assertSeeLivewire() que puede utilizarse desde cualquier prueba de Laravel:

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\CreatePost;
use Tests\TestCase;
class CreatePostTest extends TestCase
{
/** @test */
public function component_exists_on_the_page()
{
$this->get('/posts/create')
->assertSeeLivewire(CreatePost::class);
}
}

Testing de vistas

Livewire proporciona una sencilla pero potente utilidad para comprobar la existencia de texto en la salida del componente: assertSee().

A continuación se muestra un ejemplo de uso de assertSee() para asegurar que todos los mensajes de la base de datos se muestran en la página:

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\ShowPosts;
use Livewire\Livewire;
use App\Models\Post;
use Tests\TestCase;
class ShowPostsTest extends TestCase
{
/** @test */
public function displays_posts()
{
Post::factory()->make(['title' => 'On bathing well']);
Post::factory()->make(['title' => 'There\'s no time like bathtime']);
Livewire::test(ShowPosts::class)
->assertSee('On bathing well')
->assertSee('There\'s no time like bathtime');
}
}

Comprobación de los datos de la vista

Además de comprobar la salida de una vista renderizada, a veces es útil comprobar los datos que se pasan a la vista.

Esta es la misma prueba que la anterior, pero comprobando los datos de la vista en lugar de la salida renderizada:

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\ShowPosts;
use Livewire\Livewire;
use App\Models\Post;
use Tests\TestCase;
class ShowPostsTest extends TestCase
{
/** @test */
public function displays_all_posts()
{
Post::factory()->make(['title' => 'On bathing well']);
Post::factory()->make(['title' => 'The bathtub is my sanctuary']);
Livewire::test(ShowPosts::class)
->assertViewHas('posts', function ($posts) {
return count($posts) == 2;
});
}
}

Como puede ver, assertViewHas() proporciona control sobre qué aserciones quiere hacer contra los datos especificados.

Si prefiere hacer una aserción simple, como asegurarse de que un dato de la vista coincide con un valor dado, puede pasar el valor directamente como el segundo argumento dado al método assertViewHas().

Por ejemplo, suponiendo que tiene un componente con una variable llamada $postCount que se pasa a la vista, puede hacer aserciones contra su valor literal así:

$this->assertViewHas('postCount', 3)

Establecer el usuario autenticado

La mayoría de las aplicaciones web requieren que los usuarios inicien sesión antes de utilizarlas. En lugar de autenticar manualmente un usuario falso al principio de sus pruebas, Livewire proporciona un método actingAs().

A continuación se muestra un ejemplo de una prueba donde varios usuarios tienen mensajes, sin embargo, el usuario autenticado sólo debe ser capaz de ver sus propios mensajes:

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\ShowPosts;
use Livewire\Livewire;
use App\Models\User;
use App\Models\Post;
use Tests\TestCase;
class ShowPostsTest extends TestCase
{
/** @test */
public function user_only_sees_their_own_posts()
{
$user = User::factory()
->has(Post::factory()->count(3))
->create();
$stranger = User::factory()
->has(Post::factory()->count(2))
->create();
Livewire::actingAs($user)
->test(ShowPosts::class)
->assertViewHas('posts', function ($posts) {
return count($posts) == 3;
});
}
}

Testing de propiedades

Livewire también proporciona útiles utilidades de prueba para establecer y afirmar propiedades dentro de sus componentes.

Las propiedades de los componentes se actualizan normalmente en su aplicación cuando los usuarios interactúan con las entradas del formulario que contienen wire:model. Pero, debido a que las pruebas no suelen escribirse en un navegador real, Livewire le permite establecer propiedades directamente utilizando el método set().

A continuación se muestra un ejemplo de uso de set() para actualizar la propiedad $title de un componente CreatePost:

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\CreatePost;
use Livewire\Livewire;
use Tests\TestCase;
class CreatePostTest extends TestCase
{
/** @test */
public function can_set_title()
{
Livewire::test(CreatePost::class)
->set('title', 'Confessions of a serial soaker')
->assertSet('title', 'Confessions of a serial soaker');
}
}

Inicializando Propiedades

A menudo, los componentes Livewire reciben datos que se pasan desde un componente padre o parámetros de ruta. Dado que los componentes Livewire se prueban de forma aislada, puede pasarles datos manualmente utilizando el segundo parámetro del método Livewire::test():

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\UpdatePost;
use Livewire\Livewire;
use App\Models\Post;
use Tests\TestCase;
class UpdatePostTest extends TestCase
{
/** @test */
public function title_field_is_populated()
{
$post = Post::factory()->make([
'title' => 'Top ten bath bombs',
]);
Livewire::test(UpdatePost::class, ['post' => $post])
->assertSet('title', 'Top ten bath bombs');
}
}

El componente subyacente que se está probando (UpdatePost) recibirá $post a través de su método mount(). Veamos el código fuente de UpdatePost para hacernos una idea más clara de esta función:

<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Post;
class UpdatePost extends Component
{
public Post $post;
public $title = '';
public function mount(Post $post)
{
$this->post = $post;
$this->title = $post->title;
}
// ...
}

Establecer parámetros de URL

Si su componente Livewire depende de parámetros de consulta específicos en la URL de la página en la que se carga, puede utilizar el método withQueryParams() para establecer manualmente los parámetros de consulta para su prueba.

A continuación se muestra un componente SearchPosts básico que utiliza la función URL de Livewire para almacenar y realizar un seguimiento de la consulta de búsqueda actual en la cadena de consulta:

<?php
namespace App\Livewire;
use Livewire\Component;
use Livewire\Attributes\Url;
use App\Models\Post;
class SearchPosts extends Component
{
#[Url]
public $search = '';
public function render()
{
return view('livewire.search-posts', [
'posts' => Post::search($this->search)->get(),
]);
}
}

Como puede ver, la propiedad $search utiliza el atributo #[Url] de Livewire para indicar que su valor debe almacenarse en la URL.

A continuación se muestra un ejemplo de cómo simular el escenario de carga de este componente en una página con parámetros de consulta específicos en la URL:

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\SearchPosts;
use Livewire\Livewire;
use App\Models\Post;
use Tests\TestCase;
class SearchPostsTest extends TestCase
{
/** @test */
public function can_search_posts_via_url_query_string()
{
Post::factory()->create(['title' => 'Testing the first water-proof hair dryer']);
Post::factory()->create(['title' => 'Rubber duckies that actually float']);
Livewire::withQueryParams(['search' => 'hair'])
->test(SearchPosts::class)
->assertSee('Testing the first')
->assertDontSee('Rubber duckies');
}
}

Establecer cookies

Si su componente Livewire depende de cookies, puede utilizar los métodos withCookie() o withCookies() para establecer las cookies manualmente para su prueba.

A continuación se muestra un componente Cart básico que carga un token de descuento desde una cookie al montarlo:

<?php
namespace App\Livewire;
use Livewire\Component;
use Livewire\Attributes\Url;
use App\Models\Post;
class Cart extends Component
{
public $discountToken;
public mount()
{
$this->discountToken = request()->cookie('discountToken');
}
}

Como puede ver, la propiedad $discountToken anterior obtiene su valor de una cookie en la solicitud.

A continuación se muestra un ejemplo de cómo se simularía el escenario de cargar este componente en una página con cookies:

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\Cart;
use Livewire\Livewire;
use Tests\TestCase;
class CartTest extends TestCase
{
/** @test */
public function can_load_discount_token_from_a_cookie()
{
Livewire::withCookies(['discountToken' => 'CALEB2023'])
->test(Cart::class)
->assertSet('discountToken', 'CALEB2023');
}
}

Llamada a acciones

Las acciones Livewire se llaman normalmente desde el frontend usando algo como wire:click.

Debido a que las pruebas de componentes Livewire no utilizan un navegador real, puede desencadenar acciones en sus pruebas utilizando el método call().

A continuación se muestra un ejemplo de un componente CreatePost que utiliza el método call() para activar la acción save():

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\CreatePost;
use Livewire\Livewire;
use App\Models\Post;
use Tests\TestCase;
class CreatePostTest extends TestCase
{
/** @test */
public function can_create_post()
{
$this->assertEquals(0, Post::count());
Livewire::test(CreatePost::class)
->set('title', 'Wrinkly fingers? Try this one weird trick')
->set('content', '...')
->call('save');
$this->assertEquals(1, Post::count());
}
}

En la prueba anterior, afirmamos que llamar a save() crea una nueva entrada en la base de datos.

También puedes pasar parámetros a las acciones pasando parámetros adicionales al método call():

->call('deletePost', $postId);

Validación

Para comprobar que se ha producido un error de validación, puede utilizar el método assertHasErrors() de Livewire:

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\CreatePost;
use Livewire\Livewire;
use Tests\TestCase;
class CreatePostTest extends TestCase
{
/** @test */
public function title_field_is_required()
{
Livewire::test(CreatePost::class)
->set('title', '')
->call('save')
->assertHasErrors('title');
}
}

Si quieres comprobar que una regla de validación específica ha fallado, puedes pasar un array de reglas:

$this->assertHasErrors(['title' => ['required']]);

O si prefiere afirmar que existe un mensaje de validación, también puede hacerlo:

$this->assertHasErrors(['title' => ['The title field is required.']]);

Autorización

Es esencial autorizar las acciones que dependen de entradas no confiables en sus componentes Livewire. Livewire proporciona los métodos assertUnauthorized() y assertForbidden() para asegurar que una comprobación de autenticación o autorización ha fallado:

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\UpdatePost;
use Livewire\Livewire;
use App\Models\User;
use App\Models\Post;
use Tests\TestCase;
class UpdatePostTest extends TestCase
{
/** @test */
public function cant_update_another_users_post()
{
$user = User::factory()->create();
$stranger = User::factory()->create();
$post = Post::factory()->for($stranger)->create();
Livewire::actingAs($user)
->test(UpdatePost::class, ['post' => $post])
->set('title', 'Living the lavender life')
->call('save')
->assertUnauthorized();
Livewire::actingAs($user)
->test(UpdatePost::class, ['post' => $post])
->set('title', 'Living the lavender life')
->call('save')
->assertForbidden();
}
}

Si lo prefiere, también puede comprobar los códigos de estado explícitos que una acción de su componente puede haber desencadenado utilizando assertStatus():

->assertStatus(401); // Unauthorized
->assertStatus(403); // Forbidden

Redirecciones

Puede comprobar que una acción Livewire ha realizado una redirección utilizando el método assertRedirect():

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\CreatePost;
use Livewire\Livewire;
use Tests\TestCase;
class CreatePostTest extends TestCase
{
/** @test */
public function redirected_to_all_posts_after_creating_a_post()
{
Livewire::test(CreatePost::class)
->set('title', 'Using a loofah doesn\'t make you aloof...ugh')
->set('content', '...')
->call('save')
->assertRedirect('/posts');
}
}

Como comodidad añadida, puede afirmar que el usuario fue redirigido a un componente de página específico en lugar de a una URL codificada.

->assertRedirect(CreatePost::class);

Eventos

Para afirmar que un evento ha sido enviado desde tu componente, puedes utilizar el método ->assertDispatched():

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\CreatePost;
use Livewire\Livewire;
use Tests\TestCase;
class CreatePostTest extends TestCase
{
/** @test */
public function creating_a_post_dispatches_event()
{
Livewire::test(CreatePost::class)
->set('title', 'Top 100 bubble bath brands')
->set('content', '...')
->call('save')
->assertDispatched('post-created');
}
}

A menudo es útil probar que dos componentes pueden comunicarse entre sí enviando y escuchando eventos. Utilizando el método dispatch(), simulemos que un componente CreatePost envía un evento create-post. Entonces, afirmaremos que un componente PostCountBadge, que escucha ese evento, actualiza su cuenta de post apropiadamente:

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\PostCountBadge;
use App\Livewire\CreatePost;
use Livewire\Livewire;
use Tests\TestCase;
class PostCountBadgeTest extends TestCase
{
/** @test */
public function post_count_is_updated_when_event_is_dispatched()
{
$badge = Livewire::test(PostCountBadge::class)
->assertSee("0");
Livewire::test(CreatePost::class)
->set('title', 'Tear-free: the greatest lie ever told')
->set('content', '...')
->call('save')
->assertDispatched('post-created');
$badge->dispatch('post-created')
->assertSee("1");
}
}

A veces puede ser útil afirmar que un evento fue enviado con uno o más parámetros. Veamos un componente llamado ShowPosts que envía un evento llamado banner-message con un parámetro llamado message:

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\ShowPosts;
use Livewire\Livewire;
use Tests\TestCase;
class ShowPostsTest extends TestCase
{
/** @test */
public function notification_is_dispatched_when_deleting_a_post()
{
Livewire::test(ShowPosts::class)
->call('delete', postId: 3)
->assertDispatched('notify',
message: 'The post was deleted',
);
}
}

Si su componente envía un evento cuyos valores de parámetro deben comprobarse condicionalmente, puede pasar un cierre como segundo argumento al método assertDispatched como se muestra a continuación. Recibe el nombre del evento como primer argumento, y un array que contiene los parámetros como segundo argumento. Asegúrate de que el cierre devuelve un booleano.

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\ShowPosts;
use Livewire\Livewire;
use Tests\TestCase;
class ShowPostsTest extends TestCase
{
/** @test */
public function notification_is_dispatched_when_deleting_a_post()
{
Livewire::test(ShowPosts::class)
->call('delete', postId: 3)
->assertDispatched('notify', function($eventName, $params) {
return ($params['message'] ?? '') === 'The post was deleted';
})
}
}

Todas las utilidades de prueba disponibles

Livewire proporciona muchas más utilidades de comprobación. A continuación se muestra una lista completa de todos los métodos de prueba disponibles, con una breve descripción de cómo están destinados a ser utilizados:

Métodos de instalación

MétodoDescripción
Livewire::test(CreatePost::class)Probar el componente CreatePost
Livewire::test(UpdatePost::class, ['post' => $post])Pruebe el componente UpdatePost con el parámetro post (Se recibirá a través del método mount())
Livewire::actingAs($user)Establece el usuario proporcionado como usuario autenticado de la sesión Tanto la inicial como las siguientes
Livewire::withQueryParams(['search' => '...'])valor proporcionado (ej. ?search=...). Normalmente en el contexto de una propiedad que utiliza el atributo #[Url] de Livewire
Livewire::withCookie('color', 'blue')Establece la cookie de color de la prueba en el valor proporcionado (azul).
Livewire::withCookies(['color' => 'blue', 'name' => 'Taylor])Configure las cookies de color y name de la prueba con los valores proporcionados (azul, Taylor).`
Livewire::withHeaders(['X-COLOR' => 'blue', 'X-NAME' => 'Taylor])Establezca las cabeceras X-COLOR y X-NAME de la prueba en los valores proporcionados (azul, Taylor).`
Livewire::withoutLazyLoading()Desactiva la carga lenta (lazy loading) en este y todos los componentes hijo bajo prueba.componente

Interactuando con componentes

MétodoDescripción
set('title', '...')Establece la propiedad title con el valor proporcionado
set(['title' => '...', ...])Establecer las propiedades de varios componentes mediante una matriz asociativa
toggle('sortAsc')Alterna la propiedad sortAsc entre true y false
call('save')Llamar a la acción / método de save
call('remove', $post->id)Llama al método remove y pasa el $post->id como primer parámetro (Acepta también parámetros posteriores)
refresh()Reproducir un componente
dispatch('post-created')Enviar el evento post-created desde el componente
dispatch('post-created', postId: $post->id)Despachar el evento post-created con $post->id como parámetro adicional ($event.detail de Alpine)

Afirmaciones

MétodoDescripción
assertSet('title', '...')Asegura que la propiedad title está establecida con el valor proporcionado.
assertNotSet('title', '...')Asegura que la propiedad title no está establecida con el valor proporcionado.
assertSetStrict('title', '...')Asegura que la propiedad title está establecida con el valor proporcionado utilizando una comparación estricta.
assertNotSetStrict('title', '...')Asegura que la propiedad title no está establecida con el valor proporcionado utilizando una comparación estricta.
assertReturned('...')Asegura que la llamada previa ->call(...) devolvió un valor determinado.
assertCount('posts', 3)Asegura que la propiedad posts es un valor tipo array con 3 elementos.
assertSnapshotSet('date', '08/26/1990')Asegura que el valor crudo/deshidratado (JSON) de la propiedad date está establecido en 08/26/1990. Alternativa a la aserción contra la instancia hidratada de DateTime.
assertSnapshotNotSet('date', '08/26/1990')Asegura que el valor crudo/deshidratado de date no es igual al valor proporcionado.
assertSee($post->title)Asegura que el HTML renderizado del componente contiene el valor proporcionado.
assertDontSee($post->title)Asegura que el HTML renderizado no contiene el valor proporcionado.
assertSeeHtml('<div>...</div>')Asegura que la cadena literal proporcionada está contenida en el HTML renderizado sin escapar los caracteres HTML (a diferencia de assertSee, que sí los escapa por defecto).
assertDontSeeHtml('<div>...</div>')Asegura que la cadena proporcionada está contenida en el HTML renderizado.
assertSeeText($post->title)Asegura que la cadena proporcionada está contenida en el texto del HTML renderizado. El contenido se pasará a la función strip_tags de PHP antes de la aserción.
assertDontSeeText($post->title)Asegura que la cadena proporcionada no está contenida en el texto del HTML renderizado. El contenido se pasará a la función strip_tags de PHP antes de la aserción.
assertSeeInOrder(['...', '...'])Asegura que las cadenas proporcionadas aparecen en orden en el HTML renderizado del componente.
assertSeeHtmlInOrder([$firstString, $secondString])Asegura que las cadenas HTML proporcionadas aparecen en orden en la salida renderizada del componente.
assertDispatched('post-created')Asegura que el evento dado ha sido disparado por el componente.
assertNotDispatched('post-created')Asegura que el evento dado no ha sido disparado por el componente.
assertHasErrors('title')Asegura que la validación ha fallado para la propiedad title.
assertHasErrors(['title' => ['required', 'min:6']])Asegura que las reglas de validación proporcionadas han fallado para la propiedad title.
assertHasNoErrors('title')Asegura que no hay errores de validación para la propiedad title.
assertHasNoErrors(['title' => ['required', 'min:6']])Asegura que las reglas de validación proporcionadas no han fallado para la propiedad title.
assertRedirect()Asegura que se ha activado una redirección dentro del componente.
assertRedirect('/posts')Asegura que el componente activó una redirección al endpoint /posts.
assertRedirect(ShowPosts::class)Asegura que el componente activó una redirección al componente ShowPosts.
assertRedirectToRoute('name', ['parameters'])Asegura que el componente activó una redirección a la ruta dada.
assertNoRedirect()Asegura que no se ha activado ninguna redirección.
assertViewHas('posts')Asegura que el método render() ha pasado un ítem posts a los datos de la vista.
assertViewHas('postCount', 3)Asegura que una variable postCount ha sido pasada a la vista con un valor de 3.
assertViewHas('posts', function ($posts) { ... })Asegura que los datos de vista posts existen y que cumplen con las aserciones declaradas en la función de callback.
assertViewIs('livewire.show-posts')Asegura que el método render del componente devolvió el nombre de vista proporcionado.
assertFileDownloaded()Asegura que se ha activado una descarga de archivo.
assertFileDownloaded($filename)Asegura que se ha activado una descarga de archivo con el nombre proporcionado.
assertNoFileDownloaded()Asegura que no se ha activado ninguna descarga de archivo.
assertUnauthorized()Asegura que se ha lanzado una excepción de autorización dentro del componente (código de estado: 401).
assertForbidden()Asegura que se ha activado una respuesta de error con el código de estado: 403.
assertStatus(500)Asegura que la última respuesta coincide con el código de estado proporcionado.