brilo-example/tests/Web/ListPostControllerTest.php

124 lines
4.0 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Web;
use App\Entity\Database\Posts\Post;
use App\Tests\Common\DatabaseTestTrait;
use App\Tests\Common\FakerTrait;
use App\Tests\Common\Generators\PostGeneratorTrait;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\AbstractBrowser;
class ListPostControllerTest extends WebTestCase
{
use DatabaseTestTrait;
use FakerTrait;
use PostGeneratorTrait;
protected AbstractBrowser $client;
protected function setUp(): void
{
$this->client = static::createClient();
$this->bootDatabase();
$this->bootFaker();
$this->getFaker()->unique();
}
public function testPostListed(): void
{
$posts = $this->createTestPosts();
$crawler = $this->client->request('GET', '/posts/1');
$this->assertResponseIsSuccessful();
$this->assertSelectorCount(3, '.t-detail-a'); // 3 posts are listed
$displayedPosts = array_reverse(array_slice($posts, count($posts) - 3, 3)); // in ORDER by ID DESC
/**
* @var Post $post
*/
foreach ($displayedPosts as $i => $post) { // check texts
$this->assertSelectorTextContains('.t-post-detail:nth-child(' . ($i + 1) . ') .t-post-title', $this->truncateToWholeWords($post->title, 70));
$text = $crawler->filter('.t-post-detail:nth-child(' . ($i + 1) . ') .t-post-title')->text();
$this->assertLessThan(83, strlen($text), "Text $text too long"); // 80 + 3 extra characters for ellipsis
$this->assertSelectorTextContains('.t-post-detail:nth-child(' . ($i + 1) . ') .t-post-body', $this->truncateToWholeWords($post->body, 70));
$text = $crawler->filter('.t-post-detail:nth-child(' . ($i + 1) . ') .t-post-body')->text();
$this->assertLessThan(83, strlen($text), "Text $text too long"); // 80 + 3 extra characters for ellipsis
}
}
public function testPagination(): void
{
$posts = $this->createTestPosts();
$crawler = $this->client->request('GET', '/posts/1');
$this->assertResponseIsSuccessful();
$this->assertSelectorCount(4 /* 3 -> normal, 1 -> last page */, '.t-pagination .t-page-item');
$crawler = $this->client->click($crawler->filter('.t-pagination .t-page-item:nth-child(3) .t-page-link')->link());
$this->assertSelectorCount(5 /* 3 -> normal, 2 -> first page, last page */, '.t-pagination .t-page-item');
}
public function testGoToNonExistentPage(): void
{
$this->createTestPosts();
$this->client->request('GET', '/posts/999999');
$this->assertResponseStatusCodeSame(302);
$this->assertResponseHeaderSame('Location', '/posts/10' /* last page (30 posts /3 per page) */);
}
public function testGoToPageZero(): void
{
$this->createTestPosts();
$this->client->request('GET', '/posts/0');
$this->assertResponseStatusCodeSame(302);
$this->assertResponseHeaderSame('Location', '/posts' /* go to first page */);
}
public function testGoToDefault(): void
{
$this->createTestPosts();
$this->client->request('GET', '/');
$this->assertResponseIsSuccessful();
$this->assertSelectorCount(3, '.t-detail-a'); // 3 posts are listed
}
private function truncateToWholeWords(string $string, int $length): string
{
if (strlen($string) <= $length) {
return $string;
}
// Find the last space within the allowed length
$truncated = substr($string, 0, $length);
$lastSpace = strrpos($truncated, ' ');
// If there's no space, truncate to the exact length
if ($lastSpace === false) {
return substr($truncated, 0, $length);
}
return substr($truncated, 0, $lastSpace);
}
/**
* @return Post[]
*/
private function createTestPosts(): array
{
$posts = [];
for ($i = 1; $i <= 30; $i++) {
$posts[] = $this->createPost($i);
}
return $posts;
}
}