Project Challenge: Solution
Let's look at the solution to the challenge given in the previous lesson.
We'll cover the following...
We'll cover the following...
Solution
Here is the complete implementation of the challenge. Check it out!
<?php use PHPUnit\Framework\TestCase; use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\Panther\PantherTestCaseTrait; use Symfony\Component\BrowserKit\HttpBrowser; final class TasksTest extends TestCase { use PantherTestCaseTrait; private HttpBrowser $client; // Helper function to check if current user has a task private function currentUserHasTask(string $task): bool { // Make a request for the /list-tasks page $response = $this->client->request('GET', '/list-tasks'); // Check if there is a task return strpos($response->filter('ul.tasks')->text(), $task) !== false; } protected function setUp(): void { $tasksJsonFile = __DIR__ . '/../data/tasks.json'; if (is_file($tasksJsonFile)) { unlink($tasksJsonFile); } $this->client = self::createHttpBrowserClient( [ 'webServerDir' => __DIR__ . '/../public/' ] ); } protected function tearDown(): void { $this->client->request('GET', '/logout'); } /** * @test * @dataProvider securePaths */ public function you_need_to_be_logged_in(string $path): void { // Fetching URLs $response = $this->client->request('GET', self::$baseUri . $path); // Check if redirected to /login page self::assertStringContainsString('/login', $response->getUri(), 'Expected to be redirected to the login page'); } public function securePaths(): Generator { yield ['/list-tasks']; yield ['/create-task']; } /** * @test */ public function after_logging_in_you_have_access_to_the_list_of_tasks(): void { // Login $this->login(); // Redirecting to /list-tasks page $response = $this->client->request('GET', self::$baseUri . '/list-tasks'); // Check if the page consists the right string self::assertStringContainsString('Tasks', $response->text()); } /** * @test */ public function you_can_create_a_task(): void { // Login $this->login(); // Create a task $task = 'Build some Lego'; $this->createTask($task); // Check if the task has been created self::assertTrue($this->currentUserHasTask($task)); } /** * @test */ public function you_can_edit_a_task(): void { // Login $this->login(); // Create a Task $task = 'Build some Lego'; $this->createTask($task); // Clicking edit button $response = $this->client->clickLink('Edit'); // Check if the obtained task is equal to expected task self::assertEquals($task, $response->filter('input#task')->attr('value')); // Edit task $newTask = 'Buy some Lego'; $this->client->submitForm( 'Create', [ 'task' => $newTask ] ); // Check if the task has been edited self::assertTrue($this->currentUserHasTask($newTask)); } /** * @test */ public function you_can_not_provide_an_empty_string_as_a_task(): void { // Login $this->login(); // Create an empty string as a task $response = $this->createTask(''); // Check if the right error message shows up self::assertStringContainsString( 'Task can not be empty', $response->filter('strong')->text() ); } /** * @test */ public function you_can_not_see_other_tasks_of_other_users(): void { // Login as matthias $this->loginAs('matthias'); // Create a task $task = 'Build some Lego'; $this->createTask($task); // Login as tomas $this->loginAs('tomas'); // Check if tomas can not see the task created by matthias self::assertFalse($this->currentUserHasTask($task)); } /** * @test */ public function you_can_not_edit_the_task_of_another_user(): void { // Login as matthias $this->loginAs('matthias'); // Create a task $task = 'Build some Lego'; $this->createTask($task); // Login as tomas $this->loginAs('tomas'); // Task 1 will be owned by matthias, but tomas is the logged in user $response = $this->client->request('GET', self::$baseUri . '/edit-task?id=1'); // Check if the right error is generated self::assertStringContainsString('You can not edit a task created by another user', $response->text()); } /** * @test */ public function you_can_mark_a_task_as_done_and_it_disappears_from_the_list(): void { // Log in as matthias $this->loginAs('matthias'); // Create a task $task = 'Build some Lego'; $this->createTask($task); // Click Done $this->client->submitForm('Done'); // Check if the user has no task self::assertFalse($this->currentUserHasTask($task)); } /** * @test */ public function you_can_not_mark_the_task_of_another_user_as_done(): void { // Log in as matthias $this->loginAs('matthias'); // Create a task $task = 'Build some Lego'; $this->createTask($task); // Log in as tomas $this->loginAs('tomas'); // Task 1 will be owned by matthias, but tomas is the logged in user $response = $this->client->request('POST', self::$baseUri . '/mark-as-done', ['id' => '1']); // Check if the right error message is generated self::assertStringContainsString('You can not mark a task created by another user as done', $response->text()); // Log in as matthias $this->loginAs('matthias'); // Check if the task is still there self::assertTrue($this->currentUserHasTask($task)); } // Helper functions to log in private function login(): void { $this->loginAs('matthias'); } private function loginAs(string $username): void { $this->client->request('GET', self::$baseUri . '/login'); $this->client->submitForm( 'Submit', [ 'username' => $username, 'password' => 'test' ] ); } // Helper function to create task private function createTask(string $task): Crawler { $this->client->request('GET', self::$baseUri . '/create-task'); return $this->client->submitForm( 'Create', [ 'task' => $task ] ); } }
Explanation
Let’s have a look at the solution in detail.
tests/TasksTest.php
file
Tests 1 & 2: You need to be logged in.
- At line 49, we made requests for the
/list-task
and/create-task
pages. - At line 51, we asserted if the unauthenticated user is redirected to the
/login
page.
Test 3: You get redirected to the list of tasks after logging in.
- At line 66, we called the login function.
- At line 68, we request the
/list-tasks
page. - At line 70, we