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;
 | 
						|
    }
 | 
						|
}
 |