Ya hemos hablado de lo importante de tener test unitarios en nuestras aplicaciones, si lo has hecho es muy probable que alguna vez te hayas encontrado con la necesidad de Cómo realizar tests unitarios a un PDF generado y conocer si se ha generado correctamente. El problema que se nos plantea es que la respuesta que nos devuelve el backend viene renderizada, por lo que no podremos hacerles los típicos assertions
para comprobar que contienen el texto que esperábamos.
Probando la respuesta
En cambio, sí que podemos probar que el response
venga con un status 200 y además, que los headers sean los correctos y que la disposición del PDF es la que deseamos (attachment, inline, nombre del fichero, etc…)
1 2 3 4 5 6 | $response = $this->get("/reports/orders"]); $response->assertStatus(200); $this->assertEquals('application/pdf', $response->headers->get('content_type')); $this->assertEquals('attachment; filename="orders_report.pdf"', $response->headers->get('content-disposition')); //$this->assertEquals('inline; filename="orders_report.pdf"', $response->headers->get('content-disposition')); |
De esta forma sabremos que se está mostrando un PDF si el header content_type
tiene el valor de application/pdf
, del mismo modo, consultaremos el header content-disposition
para comprobar si el fichero viene como attachment
o si por el contrario se está mostrando inline
. En el mismo header podremos también ver el nombre del fichero. En nuestro caso filename="orders_report.pdf
Probando el contenido
Ahora viene donde se complica la cosa. Como hemos visto, el contenido del response no es texto, así que no podremos hacer assertions
. Vamos a necesitar una herramienta intermedia que nos convierta el PDF a texto. Aquí es donde entra Apache PDFBox, una aplicación de linea de comandos escrita en Java que precisamente se encarga de hacer este trabajo sucio.
Descarga la última version y copiala en la base de tu proyecto. Asegurate también que tengas Java configurado en tu sistema para que se pueda ejecutar.
Como wrapper para nuestros tests vamos a utilizar schmengler/PdfBox, una librería escrita en PHP que interactuará con PDFBox. Podemos instalarla via composer.
1 | composer require sgh/pdfbox |
Ya solo nos queda decirle a nuestro test dónde tenemos el ejecutable de PDFBox y qué archivo PDF vamos a convertir. El resto ya lo conoces, hacerle assertions al texto convertido.
1 2 3 4 5 | $converter = new \SGH\PdfBox\PdfBox; $converter->setPathToPdfBox(base_path() . '/pdfbox-app-2.0.5.jar'); $pdfText = $converter->textFromPdfStream($response->getContent()); $this->assertContains('CUALQUIER DATO QUE CONTENGA EL PDF', $pdfText); |
Un test completo real life
podría quedar tal que así:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | /** @test */ public function it_fills_and_returns_the_pdf() { factory(Order::class)->create(['date' => '02/01/2017', 'number' => '170001']); factory(Order::class)->create(['date' => '01/02/2017', 'number' => '170002']); factory(Order::class)->create(['date' => '01/05/2017', 'number' => '170050']); $response = $this->post("/reports/orders", [ 'date_from' => '01/01/2017', 'date_to' => '02/02/2017', ]); $response->assertStatus(200); $this->assertEquals('application/pdf', $response->headers->get('content_type')); $this->assertEquals('attachment; filename="orders_report.pdf"', $response->headers->get('content-disposition')); $converter = new \SGH\PdfBox\PdfBox; $converter->setPathToPdfBox(base_path() . '/pdfbox-app-2.0.5.jar'); $pdfText = $converter->textFromPdfStream($response->getContent()); $this->assertContains('02/01/2017', $pdfText); $this->assertContains('170001', $pdfText); $this->assertContains('01/02/2017', $pdfText); $this->assertContains('170002', $pdfText); $this->assertNotContains('01/05/2017', $pdfText); $this->assertNotContains('170050', $pdfText); } |
Si tienes alguna duda puedes dejar un comentario o pasarte por nuestro Slack 😉