124 lines
4.0 KiB
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;
|
|
}
|
|
}
|