diff --git a/composer.json b/composer.json index 64ce3ebcd..1a49e365f 100644 --- a/composer.json +++ b/composer.json @@ -42,7 +42,6 @@ }, "require-dev": { "fakerphp/faker": "^1.10", - "laravel/browser-kit-testing": "^7.0", "mockery/mockery": "^1.4.4", "nunomaduro/collision": "^7.0", "pestphp/pest": "^2.0", diff --git a/tests/Feature/AdminTest.php b/tests/Feature/AdminTest.php index 560beb269..c7b748733 100644 --- a/tests/Feature/AdminTest.php +++ b/tests/Feature/AdminTest.php @@ -6,14 +6,14 @@ use App\Models\User; use Carbon\Carbon; use Illuminate\Foundation\Testing\DatabaseMigrations; -use Tests\Feature\BrowserKitTestCase; +use Tests\TestCase; -uses(BrowserKitTestCase::class); +uses(TestCase::class); uses(DatabaseMigrations::class); test('requires login', function () { - $this->visit('/admin') - ->seePageIs('/login'); + $this->get('/admin') + ->assertRedirect('/login'); }); test('normal users cannot visit the admin section', function () { @@ -83,9 +83,9 @@ $this->loginAsAdmin(); $this->put('/admin/users/'.$user->username().'/ban') - ->assertRedirectedTo('/'); + ->assertRedirect('/'); - test()->seeInDatabase('users', ['id' => $user->id(), 'banned_at' => null, 'banned_reason' => null]); + test()->assertDatabaseHas('users', ['id' => $user->id(), 'banned_at' => null, 'banned_reason' => null]); }); test('moderators cannot ban a user without a reason', function () { @@ -94,9 +94,9 @@ $this->loginAsModerator(); $this->put('/admin/users/'.$user->username().'/ban') - ->assertRedirectedTo('/'); + ->assertRedirect('/'); - test()->seeInDatabase('users', ['id' => $user->id(), 'banned_at' => null, 'banned_reason' => null]); + test()->assertDatabaseHas('users', ['id' => $user->id(), 'banned_at' => null, 'banned_reason' => null]); }); test('admins can delete a user', function () { @@ -108,14 +108,14 @@ $this->loginAsAdmin(); $this->delete('/admin/users/'.$user->username()) - ->assertRedirectedTo('/admin/users'); + ->assertRedirect('/admin/users'); - $this->notSeeInDatabase('users', ['name' => 'Freek Murze']); + $this->assertDatabaseMissing('users', ['name' => 'Freek Murze']); // Make sure associated content is deleted. - $this->notSeeInDatabase('threads', ['author_id' => $user->id()]); - $this->notSeeInDatabase('replies', ['replyable_id' => $thread->id()]); - $this->notSeeInDatabase('replies', ['author_id' => $user->id()]); + $this->assertDatabaseMissing('threads', ['author_id' => $user->id()]); + $this->assertDatabaseMissing('replies', ['replyable_id' => $thread->id()]); + $this->assertDatabaseMissing('replies', ['author_id' => $user->id()]); }); test('admins cannot delete other admins', function () { @@ -144,9 +144,9 @@ $this->loginAsAdmin(); $this->get('admin') - ->see($submittedArticle->title()) - ->dontSee($draftArticle->title()) - ->dontSee($liveArticle->title()); + ->assertSee($submittedArticle->title()) + ->assertDontSee($draftArticle->title()) + ->assertDontSee($liveArticle->title()); }); test('moderators can list submitted articles', function () { @@ -157,9 +157,9 @@ $this->loginAsModerator(); $this->get('admin') - ->see($submittedArticle->title()) - ->dontSee($draftArticle->title()) - ->dontSee($liveArticle->title()); + ->assertSee($submittedArticle->title()) + ->assertDontSee($draftArticle->title()) + ->assertDontSee($liveArticle->title()); }); test('users cannot list submitted articles', function () { @@ -171,7 +171,7 @@ test('guests cannot list submitted articles', function () { $this->get('admin') - ->assertRedirectedTo('login'); + ->assertRedirect('/login'); }); test('admins can view submitted articles', function () { @@ -180,7 +180,7 @@ $this->loginAsAdmin(); $this->get("articles/{$article->slug()}") - ->see('Awaiting Approval'); + ->assertSee('Awaiting Approval'); }); test('admins can approve articles', function () { @@ -216,7 +216,7 @@ $article = Article::factory()->create(['submitted_at' => now()]); $this->put("/admin/articles/{$article->slug()}/approve") - ->assertRedirectedTo('/login'); + ->assertRedirect('/login'); expect($article->fresh()->approvedAt())->toBeNull(); }); @@ -254,7 +254,7 @@ $article = Article::factory()->create(['submitted_at' => now(), 'approved_at' => now()]); $this->put("/admin/articles/{$article->slug()}/disapprove") - ->assertRedirectedTo('/login'); + ->assertRedirect('/login'); $this->assertNotNull($article->fresh()->approvedAt()); }); @@ -357,9 +357,9 @@ function assertCanSeeTheUserOverview() User::factory()->create(['name' => 'Freek Murze']); User::factory()->create(['name' => 'Frederick Vanbrabant']); - test()->visit('/admin/users') - ->see('Freek Murze') - ->see('Frederick Vanbrabant'); + test()->get('/admin/users') + ->assertSee('Freek Murze') + ->assertSee('Frederick Vanbrabant'); } function assertCanBanUsers() @@ -367,10 +367,10 @@ function assertCanBanUsers() $user = User::factory()->create(['name' => 'Freek Murze']); test()->put('/admin/users/'.$user->username().'/ban', ['reason' => 'A good reason']) - ->assertRedirectedTo('/user/'.$user->username()); + ->assertRedirect('/user/'.$user->username()); - test()->notSeeInDatabase('users', ['id' => $user->id(), 'banned_at' => null]); - test()->seeInDatabase('users', ['id' => $user->id(), 'banned_reason' => 'A good reason']); + test()->assertDatabaseMissing('users', ['id' => $user->id(), 'banned_at' => null]); + test()->assertDatabaseHas('users', ['id' => $user->id(), 'banned_reason' => 'A good reason']); } function assertCanUnbanUsers() @@ -378,9 +378,9 @@ function assertCanUnbanUsers() $user = User::factory()->create(['name' => 'Freek Murze', 'banned_at' => Carbon::now()]); test()->put('/admin/users/'.$user->username().'/unban') - ->assertRedirectedTo('/user/'.$user->username()); + ->assertRedirect('/user/'.$user->username()); - test()->seeInDatabase('users', ['id' => $user->id(), 'banned_at' => null, 'banned_reason' => null]); + test()->assertDatabaseHas('users', ['id' => $user->id(), 'banned_at' => null, 'banned_reason' => null]); } function assertCannotBanAdmins() diff --git a/tests/Feature/ArticleTest.php b/tests/Feature/ArticleTest.php index 9ead37bc0..b3e8ec048 100644 --- a/tests/Feature/ArticleTest.php +++ b/tests/Feature/ArticleTest.php @@ -8,14 +8,15 @@ use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Notification; -use Tests\Feature\BrowserKitTestCase; +use Illuminate\Support\HtmlString; +use Tests\TestCase; -uses(BrowserKitTestCase::class); +uses(TestCase::class); uses(DatabaseMigrations::class); test('users cannot create an article when not logged in', function () { - $this->visit('/articles/create') - ->seePageIs('/login'); + $this->get('/articles/create') + ->assertRedirect('/login'); }); test('users can create an article', function () { @@ -30,7 +31,7 @@ 'tags' => [$tag->id()], 'submitted' => '0', ]) - ->assertRedirectedTo('/articles/using-database-migrations') + ->assertRedirect('/articles/using-database-migrations') ->assertSessionHas('success', 'Article successfully created!'); }); @@ -45,7 +46,7 @@ 'tags' => [], 'submitted' => '1', ]) - ->assertRedirectedTo('/articles/using-database-migrations') + ->assertRedirect('/articles/using-database-migrations') ->assertSessionHas('success', 'Thank you for submitting, unfortunately we can\'t accept every submission. You\'ll only hear back from us when we accept your article.'); Event::assertDispatched(ArticleWasSubmittedForApproval::class); @@ -56,15 +57,16 @@ $this->login(); - $this->post('/articles', [ + $response = $this->post('/articles', [ 'title' => 'Using database migrations', 'body' => 'This article will go into depth on working with database migrations.', 'submitted' => '1', ]) - ->assertRedirectedTo('/articles/using-database-migrations') - ->followRedirects() - ->dontSee('Draft') - ->see('Awaiting approval'); + ->assertRedirect('/articles/using-database-migrations'); + + $this->followRedirects($response) + ->assertDontSee('Draft') + ->assertSee('Awaiting Approval'); Event::assertDispatched(ArticleWasSubmittedForApproval::class); }); @@ -86,14 +88,15 @@ test('users can create a draft article', function () { $this->login(); - $this->post('/articles', [ + $response = $this->post('/articles', [ 'title' => 'Using database migrations', 'body' => 'This article will go into depth on working with database migrations.', 'submitted' => '0', ]) - ->assertRedirectedTo('/articles/using-database-migrations') - ->followRedirects() - ->see('Draft'); + ->assertRedirect('/articles/using-database-migrations'); + + $this->followRedirects($response) + ->assertSee('Draft'); }); test('draft articles do not send telegram notification', function () { @@ -138,7 +141,7 @@ $article = Article::factory()->create(['slug' => 'my-first-article', 'submitted_at' => now(), 'approved_at' => now()]); $this->get('/articles/my-first-article') - ->see($article->title()); + ->assertSee($article->title()); }); test('logged in users can view an article', function () { @@ -147,7 +150,7 @@ $this->login(); $this->get('/articles/my-first-article') - ->see($article->title()); + ->assertSee($article->title()); }); test('users can edit an article', function () { @@ -167,7 +170,7 @@ 'tags' => [$tag->id()], 'submitted' => '0', ]) - ->assertRedirectedTo('/articles/using-database-migrations') + ->assertRedirect('/articles/using-database-migrations') ->assertSessionHas('success', 'Article successfully updated!'); }); @@ -212,7 +215,7 @@ 'tags' => [], 'submitted' => '1', ]) - ->assertRedirectedTo('/articles/using-database-migrations') + ->assertRedirect('/articles/using-database-migrations') ->assertSessionHas('success', 'Thank you for submitting, unfortunately we can\'t accept every submission. You\'ll only hear back from us when we accept your article.'); Event::assertDispatched(ArticleWasSubmittedForApproval::class); @@ -231,14 +234,15 @@ $this->loginAs($user); - $this->put('/articles/my-first-article', [ + $response = $this->put('/articles/my-first-article', [ 'title' => 'Using database migrations', 'body' => 'This article will go into depth on working with database migrations.', 'submitted' => '1', ]) - ->assertRedirectedTo('/articles/using-database-migrations') - ->followRedirects() - ->dontSee('Draft'); + ->assertRedirect('/articles/using-database-migrations'); + + $this->followRedirects($response) + ->assertDontSee('Draft'); Event::assertDispatched(ArticleWasSubmittedForApproval::class); }); @@ -330,7 +334,7 @@ $this->loginAs($user); $this->delete('/articles/my-first-article') - ->assertRedirectedTo('/articles') + ->assertRedirect('/articles') ->assertSessionHas('success', 'Article successfully deleted!'); }); @@ -346,8 +350,10 @@ test('canonical urls are rendered', function () { Article::factory()->create(['slug' => 'my-first-article', 'submitted_at' => now(), 'approved_at' => now()]); + $expectedHtml = new HtmlString(''); + $this->get('/articles/my-first-article') - ->see(''); + ->assertSee($expectedHtml); }); test('custom canonical urls are rendered', function () { @@ -358,15 +364,17 @@ 'approved_at' => now(), ]); + $expectedHtml = new HtmlString(''); + $this->get('/articles/my-first-article') - ->see(''); + ->assertSee($expectedHtml); }); test('draft articles cannot be viewed by guests', function () { Article::factory()->create(['slug' => 'my-first-article', 'submitted_at' => null]); $this->get('/articles/my-first-article') - ->assertResponseStatus(404); + ->assertStatus(404); }); test('draft articles can be viewed by the article owner', function () { @@ -380,8 +388,8 @@ $this->loginAs($user); $this->get('/articles/my-first-article') - ->assertResponseStatus(200) - ->see('Draft'); + ->assertStatus(200) + ->assertSee('Draft'); }); test('draft articles cannot be viewed by logged in users', function () { @@ -393,7 +401,7 @@ $this->login(); $this->get('/articles/my-first-article') - ->assertResponseStatus(404); + ->assertStatus(404); }); test('a user can view their articles', function () { @@ -405,10 +413,10 @@ $this->loginAs($user); - $this->visit('/articles/authored') - ->see($articles[0]->title()) - ->see($articles[1]->title()) - ->see($articles[2]->title()); + $this->get('/articles/authored') + ->assertSee($articles[0]->title()) + ->assertSee($articles[1]->title()) + ->assertSee($articles[2]->title()); }); test('a user can another users articles', function () { @@ -416,15 +424,15 @@ $this->login(); - $this->visit('/articles/authored') - ->dontSee($articles[0]->title()) - ->dontSee($articles[1]->title()) - ->dontSee($articles[2]->title()); + $this->get('/articles/authored') + ->assertDontSee($articles[0]->title()) + ->assertDontSee($articles[1]->title()) + ->assertDontSee($articles[2]->title()); }); test('a guest cannot see articles', function () { - $this->visit('/articles/authored') - ->seePageIs('/login'); + $this->get('/articles/authored') + ->assertRedirect('/login'); }); test('users get a mail notification when their article is approved', function () { @@ -456,7 +464,7 @@ $article->syncTags([$tag->id]); $this->get('/articles') - ->dontSee('Test Tag'); + ->assertDontSee('Test Tag'); }); test('share image url is rendered correctly', function () { @@ -467,37 +475,39 @@ ]); $this->get('/articles/my-first-article') - ->see('articles/my-first-article/social.png') - ->dontSee('images/laravelio-share.png'); + ->assertSee('articles/my-first-article/social.png') + ->assertDontSee('images/laravelio-share.png'); }); test('default share image is used on non article pages', function () { $this->get('/') - ->see('images/laravelio-share.png') - ->dontSee('articles/my-first-article/social.png'); + ->assertSee('images/laravelio-share.png') + ->assertDontSee('articles/my-first-article/social.png'); }); test('user see a tip if they have not set the twitter handle', function () { $this->login(['twitter' => null]); $this->get('/articles/authored') - ->seeLink('Twitter handle') - ->see('so we can link to your profile when we tweet out your article.'); + ->assertSeeText('Twitter handle', '') + ->assertSee('so we can link to your profile when we tweet out your article.'); }); test('user do not see tip if they have set the twitter handle', function () { $this->login(); $this->get('/articles/authored') - ->dontSeeLink('Twitter handle') - ->dontSee('so we can link to your profile when we tweet out your article.'); + ->assertDontSeeText('Twitter handle', '') + ->assertDontSee('so we can link to your profile when we tweet out your article.'); }); test('loading page with invalid sort parameter defaults to recent', function () { Article::factory()->create(['slug' => 'my-first-article', 'submitted_at' => now(), 'approved_at' => now()]); + $expectedHtml = new HtmlString(''); + $this->get('/articles?filter=invalid') - ->see(''); + ->assertSee($expectedHtml); }); test('can filter articles by tag', function () { @@ -510,20 +520,20 @@ $articleTwo->syncTags([$tagTwo->id]); $this->get('/articles?tag=one') - ->see('My First Article') - ->dontSee('My Second Article'); + ->assertSee('My First Article') + ->assertDontSee('My Second Article'); }); test('only articles with ten or more views render a view count', function () { $article = Article::factory()->create(['title' => 'My First Article', 'slug' => 'my-first-article', 'submitted_at' => now(), 'approved_at' => now(), 'view_count' => 9]); $this->get("/articles/{$article->slug()}") - ->see('My First Article') - ->dontSee('9 views'); + ->assertSee('My First Article') + ->assertDontSee('9 views'); $article->update(['view_count' => 10]); $this->get("/articles/{$article->slug()}") - ->see('My First Article') - ->see('10 views'); + ->assertSee('My First Article') + ->assertSee('10 views'); }); diff --git a/tests/Feature/AuthTest.php b/tests/Feature/AuthTest.php index 081874839..57af8f1fe 100644 --- a/tests/Feature/AuthTest.php +++ b/tests/Feature/AuthTest.php @@ -7,73 +7,76 @@ use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Notification; -use Tests\Feature\BrowserKitTestCase; +use Illuminate\Support\HtmlString; +use Tests\TestCase; -uses(BrowserKitTestCase::class); +uses(TestCase::class); uses(DatabaseMigrations::class); test('users can register', function () { Notification::fake(); - session(['githubData' => ['id' => 123, 'username' => 'johndoe']]); + $response = $this->withSession(['githubData' => ['id' => 123, 'username' => 'johndoe']]) + ->post('/register', [ + 'name' => 'John Doe', + 'email' => 'john.doe@example.com', + 'username' => 'johndoe', + 'rules' => true, + 'terms' => true, + ]); - $this->visit('/register') - ->type('John Doe', 'name') - ->type('john.doe@example.com', 'email') - ->type('johndoe', 'username') - ->check('rules') - ->check('terms') - ->press('Register') - ->seePageIs('/user/johndoe') - ->see('John Doe'); + $this->followRedirects($response) + ->assertSee('John Doe'); assertLoggedIn(); - $this->assertSessionMissing('githubData'); + $response->assertSessionMissing('githubData'); Notification::assertSentTo(Auth::user(), VerifyEmail::class); }); test('registration fails when a required field is not filled in', function () { - session(['githubData' => ['id' => 123]]); - - $this->visit('/register') - ->press('Register') - ->seePageIs('/register') - ->see('The name field is required.') - ->see('The email field is required.') - ->see('The username field is required.') - ->see('The rules must be accepted.'); + $this->withSession(['githubData' => ['id' => 123]]) + ->post('/register', []) + ->assertInvalid([ + 'name' => 'The name field is required.', + 'email' => 'The email field is required.', + 'username'=> 'The username field is required.', + 'rules'=> 'The rules must be accepted.', + ]); }); test('registration fails with non alpha dash username', function () { - session(['githubData' => ['id' => 123, 'username' => 'johndoe']]); - - $this->visit('/register') - ->type('John Doe', 'name') - ->type('john.doe@example.com', 'email') - ->type('john foo', 'username') - ->check('rules') - ->check('terms') - ->press('Register') - ->seePageIs('/register') - ->see('The username must only contain letters, numbers, dashes and underscores.'); + $this->withSession(['githubData' => ['id' => 123, 'username' => 'johndoe']]) + ->post('/register', [ + 'name' => 'Jogn Doe', + 'email' => 'john.doe@example.com', + 'username' => 'john foo', + 'rules' => true, + 'terms' => true, + ]) + ->assertInvalid([ + 'username' => 'The username must only contain letters, numbers, dashes and underscores.' + ]); }); test('registration fails with a duplicate github id', function () { User::factory()->create(['github_id' => 123, 'github_username' => 'johndoe']); - session(['githubData' => ['id' => 123, 'username' => 'johndoe']]); + $response = $this->withSession(['githubData' => ['id' => 123, 'username' => 'johndoe']]) + ->post('/register', [ + 'name'=> 'John Doe', + 'email' => 'john.doe@example.com', + 'username' => 'johndoe', + 'rules' => true, + 'terms' => true + ]); - $this->visit('/register') - ->type('John Doe', 'name') - ->type('john.doe@example.com', 'email') - ->type('johndoe', 'username') - ->check('rules') - ->check('terms') - ->press('Register') - ->seePageIs('/register') - ->see('We already found a user with the given GitHub account (@johndoe). Would you like to login instead?'); + $this->followRedirects($response) + ->assertSee(new HtmlString( + 'We already found a user with the given GitHub account (@johndoe). Would you like to login instead?' + ) + ); }); test('users can resend the email verification', function () { @@ -89,72 +92,78 @@ $response = $this->post('/email/resend'); $response->assertSessionHas('error', 'Your email address is already verified.'); - $response->followRedirects() - ->seePageIs('/user/johndoe'); + + $response->assertRedirect(); }); test('users can login with their username', function () { $this->createUser(); - $this->visit('/login') - ->type('johndoe', 'username') - ->type('password', 'password') - ->press('Sign in') - ->seePageIs('/user/johndoe') - ->see('John Doe'); + $this->post('login', [ + 'username' => 'johndoe', + 'password' => 'password' + ]); + + $this->assertAuthenticated(); }); test('users can login with their email address', function () { $this->createUser(); - $this->visit('/login') - ->type('john@example.com', 'username') - ->type('password', 'password') - ->press('Sign in') - ->seePageIs('/user/johndoe') - ->see('John Doe'); + $this->post('login', [ + 'username' => 'john@example.com', + 'password' => 'password', + ]); + + $this->assertAuthenticated(); }); test('login fails when a required field is not filled in', function () { $this->createUser(); - $this->visit('/login') - ->press('Sign in') - ->seePageIs('/login') - ->see('The username field is required.') - ->see('The password field is required.'); + $response = $this->post('login', []); + + $response->assertInvalid([ + 'username' => 'The username field is required.', + 'password' => 'The password field is required.' + ]); }); test('login fails when password is incorrect', function () { $this->createUser(); - $this->visit('/login') - ->type('johndoe', 'username') - ->type('invalidpass', 'password') - ->press('Sign in') - ->seePageIs('/login') - ->see('These credentials do not match our records.'); + $response = $this->post('login', [ + 'username' => 'johndoe', + 'password' => 'invalidpass' + ]); + + $response->assertInvalid([ + 'username' => 'These credentials do not match our records.' + ]); }); test('login fails when user is banned', function () { - $this->createUser(['banned_at' => Carbon::now()]); + $user = $this->createUser(['banned_at' => Carbon::now()]); + + $response = $this->actingAs($user) + ->post('/login', [ + 'username' => 'johndoe', + 'password' => 'password' + ]) + ->assertRedirect('/'); - $this->visit('/login') - ->type('johndoe', 'username') - ->type('password', 'password') - ->press('Sign in') - ->seePageIs('/') - ->see('This account is banned.'); + $this->followRedirects($response) + ->assertSee('This account is banned.'); }); test('users can logout', function () { - $this->login(); + $user = $this->login(); assertLoggedIn(); - $this->visit('/') - ->press('Sign out') - ->seePageIs('/'); + $this->actingAs($user) + ->post('logout') + ->assertRedirect('/'); assertLoggedOut(); }); @@ -162,10 +171,10 @@ test('users can request a password reset link', function () { $this->createUser(); - $this->visit('/password/reset') - ->type('john@example.com', 'email') - ->press('Send Password Reset Link') - ->see('We have emailed your password reset link!'); + $this->post('password/email', [ + 'email' => 'john@example.com' + ]) + ->assertSessionHas('status', 'We have emailed your password reset link!'); }); test('users can reset their password', function () { @@ -174,18 +183,25 @@ // Insert a password reset token into the database. $token = $this->app[PasswordBroker::class]->getRepository()->create($user); - $this->visit('/password/reset/'.$token) - ->type('john@example.com', 'email') - ->type('QFq^$cz#P@MZa5z7', 'password') - ->type('QFq^$cz#P@MZa5z7', 'password_confirmation') - ->press('Reset Password') - ->seePageIs('/user/johndoe') - ->press('Sign out') - ->visit('/login') - ->type('johndoe', 'username') - ->type('QFq^$cz#P@MZa5z7', 'password') - ->press('Sign in') - ->seePageIs('/user/johndoe'); + $this->post('/password/reset', [ + 'token' => $token, + 'email' => 'john@example.com', + 'password' => 'QFq^$cz#P@MZa5z7', + 'password_confirmation' => 'QFq^$cz#P@MZa5z7' + ]) + ->assertRedirect(); + + $this->actingAs($user) + ->post('logout'); + + assertLoggedOut(); + + $this->post('login', [ + 'username' => 'johndoe', + 'password' => 'QFq^$cz#P@MZa5z7' + ]); + + assertLoggedIn(); }); test('users cannot reset their password when it has been compromised in data leaks', function () { @@ -194,20 +210,27 @@ // Insert a password reset token into the database. $token = $this->app[PasswordBroker::class]->getRepository()->create($user); - $this->visit('/password/reset/'.$token) - ->type('john@example.com', 'email') - ->type('password', 'password') - ->type('password', 'password_confirmation') - ->press('Reset Password') - ->seePageIs('/password/reset/'.$token) - ->see('The given password has appeared in a data leak. Please choose a different password.'); + $response = $this->post('/password/reset', [ + 'token' => $token, + 'email' => 'john@example.com', + 'password' => 'password', + 'password_confirmation' => 'password' + ]); + + $response->assertSessionHasErrors([ + 'password' => 'The given password has appeared in a data leak. Please choose a different password.' + ]); }); test('unverified users cannot create threads', function () { - $this->login(['email_verified_at' => null]); + $user = $this->login(['email_verified_at' => null]); + + $response = $this->actingAs($user) + ->get('/forum/create-thread') + ->assertRedirect(); - $this->visit('/forum/create-thread') - ->see('Before proceeding, please check your email for a verification link.'); + $this->followRedirects($response) + ->assertSee('Before proceeding, please check your email for a verification link.'); }); // Helpers diff --git a/tests/Feature/BlockUsersTest.php b/tests/Feature/BlockUsersTest.php index 8fe884446..ccd13e75e 100644 --- a/tests/Feature/BlockUsersTest.php +++ b/tests/Feature/BlockUsersTest.php @@ -2,21 +2,21 @@ use App\Models\User; use Illuminate\Foundation\Testing\RefreshDatabase; -use Tests\Feature\BrowserKitTestCase; +use Tests\TestCase; -uses(BrowserKitTestCase::class); +uses(TestCase::class); uses(RefreshDatabase::class); test('cannot block user when not logged in', function () { $user = $this->createUser(); - $this->put("/users/{$user->username}/block")->assertRedirectedTo('login'); + $this->put("/users/{$user->username}/block")->assertRedirect('login'); }); test('cannot unblock user when not logged in', function () { $user = $this->createUser(); - $this->put("/users/{$user->username}/unblock")->assertRedirectedTo('login'); + $this->put("/users/{$user->username}/unblock")->assertRedirect('login'); }); test('cannot block self', function () { diff --git a/tests/Feature/CanonicalUrlTest.php b/tests/Feature/CanonicalUrlTest.php index bc9dd0f10..ce0d2434a 100644 --- a/tests/Feature/CanonicalUrlTest.php +++ b/tests/Feature/CanonicalUrlTest.php @@ -5,9 +5,10 @@ use App\Models\Thread; use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Support\Facades\App; -use Tests\Feature\BrowserKitTestCase; +use Illuminate\Support\HtmlString; +use Tests\TestCase; -uses(BrowserKitTestCase::class); +uses(TestCase::class); uses(DatabaseMigrations::class); function inProduction() @@ -18,54 +19,72 @@ function inProduction() afterEach(fn () => App::detectEnvironment(fn () => 'testing')); test('pages without a canonical url explicitly set fall back to the current url', function () { + $expectedHtml = new HtmlString(''); + $this->get('/register') - ->see(''); + ->assertSee($expectedHtml); }); test('pages with a canonical url are rendered correctly', function () { $thread = Thread::factory()->create(['subject' => 'The first thread']); + $expectedHtml = new HtmlString(''); + $this->get("forum/{$thread->slug()}") - ->see(''); + ->assertSee($expectedHtml); }); test('first page of paginated list removes page=1 from canonical url', function () { + $expectedHtml = new HtmlString(''); + $this->get('forum?page=1') - ->see(''); + ->assertSee($expectedHtml); }); test('subsequent pages of paginated list sets the full url as canonical', function () { + $expectedHtml = new HtmlString(''); + $this->get('forum?page=2') - ->see(''); + ->assertSee($expectedHtml); }); test('allowed params are included in the canonical url', function () { + $expectedHtml = new HtmlString(''); + $this->get('forum?filter=recent&page=1') - ->see(''); + ->assertSee($expectedHtml); }); test('non allowed params are not included in the canonical url', function () { + $expectedHtml = new HtmlString(''); + $this->get('forum?filter=recent&utm_source=twitter&utm_medium=social&utm_term=abc123&page=2') - ->see(''); + ->assertSee($expectedHtml); }); test('query_params_are_always_in_the_same_order', function () { Tag::factory()->create(['name' => 'Laravel', 'slug' => 'laravel']); + $expectedHtml = new HtmlString(''); + $this->get('articles?utm_source=twitter&utm_medium=social&utm_term=abc123&filter=trending&page=2&tag=laravel') - ->see(''); + ->assertSee($expectedHtml); }); test('standard pages always remove query params from canonical url', function () { + $expectedHtml = new HtmlString(''); + $this->get('?utm_source=twitter&utm_medium=social&utm_term=abc123') - ->see(''); + ->assertSee($expectedHtml); }); test('canonical tracking is turned off when using external url', function () { Article::factory()->create(['slug' => 'my-first-article', 'submitted_at' => now(), 'approved_at' => now(), 'original_url' => 'https://example.com/external-path']); + $expectedHtml = new HtmlString('data-canonical="false"'); + $this->get('/articles/my-first-article') - ->see('data-canonical="false"'); + ->assertSee($expectedHtml); })->inProduction(); test('canonical tracking is turned on when using external url', function () { @@ -73,6 +92,8 @@ function inProduction() Article::factory()->create(['slug' => 'my-first-article', 'submitted_at' => now(), 'approved_at' => now()]); + $expectedHtml = new HtmlString('data-canonical="false"'); + $this->get('/articles/my-first-article') - ->dontSee('data-canonical="false"'); + ->assertDontSee($expectedHtml); })->inProduction(); diff --git a/tests/Feature/ForumTest.php b/tests/Feature/ForumTest.php index d05cf9d91..91c6bf26a 100644 --- a/tests/Feature/ForumTest.php +++ b/tests/Feature/ForumTest.php @@ -12,19 +12,20 @@ use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Notifications\DatabaseNotification; use Illuminate\Support\Facades\Notification; +use Illuminate\Support\HtmlString; use Livewire\Livewire; -use Tests\Feature\BrowserKitTestCase; +use Tests\TestCase; -uses(BrowserKitTestCase::class); +uses(TestCase::class); uses(DatabaseMigrations::class); test('users can see a list of latest threads', function () { Thread::factory()->create(['subject' => 'The first thread']); Thread::factory()->create(['subject' => 'The second thread']); - $this->visit('/forum') - ->see('The first thread') - ->see('The second thread'); + $this->get('/forum') + ->assertSee('The first thread') + ->assertSee('The second thread'); }); test('users can see when a thread is resolved', function () { @@ -33,11 +34,11 @@ $reply = Reply::factory()->create(); $thread->solutionReplyRelation()->associate($reply)->save(); - $this->visit('/forum') - ->see('The first thread') - ->see('The second thread') - ->see('Resolved') - ->see(route('thread', $thread->slug()).'#'.$thread->solution_reply_id); + $this->get('/forum') + ->assertSee('The first thread') + ->assertSee('The second thread') + ->assertSee('Resolved') + ->assertSee(route('thread', $thread->slug()).'#'.$thread->solution_reply_id); }); test('users can see a single thread', function () { @@ -46,13 +47,13 @@ 'slug' => 'the-first-thread', ]); - $this->visit('/forum/the-first-thread') - ->see('The first thread'); + $this->get('/forum/the-first-thread') + ->assertSee('The first thread'); }); test('users cannot create a thread when not logged in', function () { - $this->visit('/forum/create-thread') - ->seePageIs('/login'); + $this->get('/forum/create-thread') + ->assertRedirect('/login'); }); test('the thread subject cannot be an url', function () { @@ -78,7 +79,7 @@ 'body' => 'This text explains how to work with Eloquent.', 'tags' => [$tag->id()], ]) - ->assertRedirectedTo('/forum/how-to-work-with-eloquent') + ->assertRedirect('/forum/how-to-work-with-eloquent') ->assertSessionHas('success', 'Thread successfully created!'); }); @@ -97,8 +98,8 @@ 'body' => 'This text explains how to work with Eloquent.', 'tags' => [$tag->id()], ]) - ->assertRedirectedTo('/forum/how-to-work-with-eloquent') - ->assertSessionHas('success', 'Thread successfully updated!'); + ->assertRedirect('/forum/how-to-work-with-eloquent') + ->assertSessionHas('success', 'Thread successfully updated!'); }); test('users cannot edit a thread they do not own', function () { @@ -116,7 +117,7 @@ $this->loginAs($thread->author()); $this->delete('/forum/my-first-thread') - ->assertRedirectedTo('/forum') + ->assertRedirect('/forum') ->assertSessionHas('success', 'Thread successfully deleted!'); }); @@ -138,7 +139,7 @@ Notification::fake(); $this->delete('/forum/my-first-thread', ['reason' => 'Please do not spam.']) - ->assertRedirectedTo('/forum') + ->assertRedirect('/forum') ->assertSessionHas('success', 'Thread successfully deleted!'); Notification::assertSentTo($thread->author(), ThreadDeletedNotification::class); @@ -230,8 +231,10 @@ 'replyable_id' => $thread->id(), ]); - $this->visit("/forum/{$thread->slug}") - ->see('https://github.com/laravelio/laravel.io'); + $this->get("/forum/{$thread->slug}") + ->assertSee(new HtmlString( + 'https://github.com/laravelio/laravel.io' + )); }); test('user can see standalone links in thread', function () { @@ -241,23 +244,31 @@ ]); Reply::factory()->create(['replyable_id' => $thread->id()]); - $this->visit("/forum/{$thread->slug()}") - ->see('https:\/\/github.com\/laravelio\/laravel.io<\/a>'); + $this->get("/forum/{$thread->slug()}") + ->assertSee(new HtmlString('"<p><a href=\"https:\/\/github.com\/laravelio\/laravel.io\" rel=\"nofollow\" target=\"_blank\">https:\/\/github.com\/laravelio\/laravel.io<\/a>')); }); test('an invalid filter defaults to the most recent threads', function () { Thread::factory()->create(['subject' => 'The first thread']); Thread::factory()->create(['subject' => 'The second thread']); - $this->visit('/forum?filter=something-invalid') - ->see('href="http://localhost/forum?filter=recent" aria-current="page"'); + $this->get('/forum?filter=something-invalid') + ->assertSeeInOrder([ + new HtmlString('href="http://localhost/forum?filter=recent"'), + new HtmlString('aria-current="page"'), + ]); + }); test('an invalid filter on tag view defaults to the most recent threads', function () { $tag = Tag::factory()->create(); - $this->visit("/forum/tags/{$tag->slug}?filter=something-invalid") - ->see('href="http://localhost/forum/tags/'.$tag->slug.'?filter=recent" aria-current="page"'); + $this->get("/forum/tags/{$tag->slug}?filter=something-invalid") + ->assertSeeInOrder([ + new HtmlString('href="http://localhost/forum/tags/'.$tag->slug.'?filter=recent'), + new HtmlString('aria-current="page"') + ]); + }); test('thread activity is set when a new thread is created', function () { diff --git a/tests/Feature/HomeTest.php b/tests/Feature/HomeTest.php index 32023c26a..b60056090 100644 --- a/tests/Feature/HomeTest.php +++ b/tests/Feature/HomeTest.php @@ -1,30 +1,30 @@ visit('/') - ->see('Laravel.io') - ->see('The Laravel Community Portal'); + $this->get('/') + ->assertSee('Laravel.io') + ->assertSee('The Laravel Community Portal'); }); test('users can see a login and registration link when logged out', function () { - $this->visit('/') - ->seeLink('Login') - ->seeLink('Register') - ->dontSee('Sign out'); + $this->get('/') + ->assertSeeText('Login', '') + ->assertSeeText('Register', '') + ->assertDontSee('Sign out'); }); test('users can see a logout button when logged in', function () { $this->login(); - $this->visit('/') - ->see('Sign out') - ->dontSeeLink('Login') - ->dontSeeLink('Register') - ->seeLink('Profile', '/user'); + $this->get('/') + ->assertSee('Sign out') + ->assertDontSeeText('Login', '') + ->assertDontSeeText('Register', '') + ->assertSee('Profile', '/user'); }); diff --git a/tests/Feature/ModeratorTest.php b/tests/Feature/ModeratorTest.php index d574837b6..14067386a 100644 --- a/tests/Feature/ModeratorTest.php +++ b/tests/Feature/ModeratorTest.php @@ -2,9 +2,9 @@ use App\Models\Thread; use Illuminate\Foundation\Testing\DatabaseMigrations; -use Tests\Feature\BrowserKitTestCase; +use Tests\TestCase; -uses(BrowserKitTestCase::class); +uses(TestCase::class); uses(DatabaseMigrations::class); test('moderators can edit any thread', function () { @@ -12,8 +12,8 @@ $this->loginAsModerator(); - $this->visit('/forum/'.$thread->slug().'/edit') - ->assertResponseOk(); + $this->get('/forum/'.$thread->slug().'/edit') + ->assertSuccessful(); }); test('moderators can delete any thread', function () { @@ -22,5 +22,5 @@ $this->loginAsModerator(); $this->delete('/forum/'.$thread->slug()) - ->assertRedirectedTo('/forum'); + ->assertRedirect('/forum'); }); diff --git a/tests/Feature/NavigationTest.php b/tests/Feature/NavigationTest.php index 9141edec0..d52e094a7 100644 --- a/tests/Feature/NavigationTest.php +++ b/tests/Feature/NavigationTest.php @@ -7,9 +7,9 @@ use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Support\Str; use Livewire\Livewire; -use Tests\Feature\BrowserKitTestCase; +use Tests\TestCase; -uses(BrowserKitTestCase::class); +uses(TestCase::class); uses(DatabaseMigrations::class); test('a user sees the correct number of notifications', function () { diff --git a/tests/Feature/NotificationsTest.php b/tests/Feature/NotificationsTest.php index 1c7779ae8..a8bbdde9f 100644 --- a/tests/Feature/NotificationsTest.php +++ b/tests/Feature/NotificationsTest.php @@ -8,11 +8,11 @@ use Illuminate\Support\HtmlString; use Illuminate\Support\Str; use Livewire\Livewire; -use Tests\Feature\BrowserKitTestCase; +use Tests\TestCase; use function Pest\Laravel\post; -uses(BrowserKitTestCase::class); +uses(TestCase::class); uses(DatabaseMigrations::class); test('users_can_see_notifications', function () { diff --git a/tests/Feature/ProfileTest.php b/tests/Feature/ProfileTest.php index fa3048374..76c02c49a 100644 --- a/tests/Feature/ProfileTest.php +++ b/tests/Feature/ProfileTest.php @@ -1,32 +1,32 @@ createUser(); - $this->visit('/user/johndoe') - ->see('John Doe'); + $this->get('/user/johndoe') + ->assertSee('John Doe'); }); test('admin buttons are not shown to logged out users', function () { $this->createUser(); - $this->visit('/user/johndoe') - ->dontSee('Ban user') - ->dontSee('Unban user'); + $this->get('/user/johndoe') + ->assertDontSee('Ban user') + ->assertDontSee('Unban user'); }); test('admin buttons are not shown to non admin users', function () { $this->login(); - $this->visit('/user/johndoe') - ->dontSee('Ban user') - ->dontSee('Unban user'); + $this->get('/user/johndoe') + ->assertDontSee('Ban user') + ->assertDontSee('Unban user'); }); test('admin buttons are shown to admin users', function () { @@ -36,6 +36,6 @@ ]); $this->loginAsAdmin(); - $this->visit('/user/janedoe') - ->see('Ban user'); + $this->get('/user/janedoe') + ->assertSee('Ban User'); }); diff --git a/tests/Feature/ReplyTest.php b/tests/Feature/ReplyTest.php index fa483cd44..7a1afe934 100644 --- a/tests/Feature/ReplyTest.php +++ b/tests/Feature/ReplyTest.php @@ -10,10 +10,11 @@ use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Notifications\DatabaseNotification; use Illuminate\Support\Facades\Notification; +use Illuminate\Support\HtmlString; use Livewire\Livewire; -use Tests\Feature\BrowserKitTestCase; +use Tests\TestCase; -uses(BrowserKitTestCase::class); +uses(TestCase::class); uses(DatabaseMigrations::class); test('users can add a reply to a thread', function () { @@ -36,8 +37,8 @@ $this->loginAs($user); - $this->visit("/forum/{$thread->slug()}") - ->see('Update reply'); + $this->get("/forum/{$thread->slug()}") + ->assertSee('Update reply'); }); test('edit reply component is not present on the page when not owned by user', function () { @@ -46,8 +47,8 @@ $this->login(); - $this->visit("/forum/{$thread->slug()}") - ->dontSee('Update reply'); + $this->get("/forum/{$thread->slug()}") + ->assertDontSee('Update reply'); }); test('users can edit a reply', function () { @@ -98,9 +99,9 @@ $this->login(); - $this->visit("/forum/{$thread->slug}") - ->dontSee('value="Reply"') - ->seeText( + $this->get("/forum/{$thread->slug}") + ->assertDontSee('value="Reply"') + ->assertSeeText( 'The last reply to this thread was more than six months ago. Please consider opening a new thread if you have a similar question.', ); }); @@ -122,8 +123,10 @@ $this->login(); - $this->visit("/forum/{$thread->slug}") - ->see('name="body"'); + $this->get("/forum/{$thread->slug}") + ->assertSee(new HtmlString( + 'name="body"' + )); }); test('unverified users cannot see the reply input', function () { @@ -131,11 +134,13 @@ $this->login(['email_verified_at' => null]); - $this->visit("/forum/{$thread->slug}") - ->dontSee('name="body"') - ->seeText( - 'You\'ll need to verify your account before participating in this thread.', - ); + $this->get("/forum/{$thread->slug}") + ->assertDontSee(new HtmlString( + 'name="body"' + )) + ->assertSeeText(new HtmlString( + 'You\'ll need to verify your account before participating in this thread.' + )); }); test('replyable activity is updated when reply is created', function () { diff --git a/tests/Feature/SettingsTest.php b/tests/Feature/SettingsTest.php index 1ca1ebb67..6c3899434 100644 --- a/tests/Feature/SettingsTest.php +++ b/tests/Feature/SettingsTest.php @@ -5,21 +5,21 @@ use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; -use Tests\Feature\BrowserKitTestCase; +use Tests\TestCase; -uses(BrowserKitTestCase::class); +uses(TestCase::class); uses(DatabaseMigrations::class); test('requires login', function () { - $this->visit('/settings') - ->seePageIs('/login'); + $this->get('/settings') + ->assertRedirect('/login'); }); test('users can update their profile', function () { - $this->login(); + $user = $this->login(); - $this->visit('/settings') - ->submitForm('Update Profile', [ + $response = $this->actingAs($user) + ->put('/settings', [ 'name' => 'Freek Murze', 'email' => 'freek@example.com', 'username' => 'freekmurze', @@ -27,87 +27,100 @@ 'website' => 'https://laravel.io', 'bio' => 'My bio', ]) - ->seePageIs('/settings') - ->see('Freek Murze') - ->see('freekmurze') - ->see('freektwitter') - ->see('Settings successfully saved!') - ->see('My bio'); + ->assertRedirect('/settings'); + + $this->followRedirects($response) + ->assertSee('Freek Murze') + ->assertSee('freekmurze') + ->assertSee('freektwitter') + ->assertSee('Settings successfully saved!') + ->assertSee('My bio'); }); test('users cannot choose duplicate usernames or email addresses', function () { $this->createUser(['email' => 'freek@example.com', 'username' => 'freekmurze']); - $this->login(); + $user = $this->login(); - $this->visit('/settings') - ->submitForm('Update Profile', [ + $response = $this->actingAs($user) + ->put('/settings', [ 'name' => 'Freek Murze', 'email' => 'freek@example.com', 'username' => 'freekmurze', ]) - ->seePageIs('/settings') - ->see('Something went wrong. Please review the fields below.') - ->see('The email has already been taken.') - ->see('The username has already been taken.'); + ->assertInvalid([ + 'username' => 'The username has already been taken.', + 'email' => 'The email has already been taken.', + ]); + + $this->followRedirects($response) + ->assertSee('Something went wrong. Please review the fields below.'); }); test('users can delete their account', function () { $this->login(['name' => 'Freek Murze']); $this->delete('/settings') - ->assertRedirectedTo('/'); + ->assertRedirect('/'); - $this->notSeeInDatabase('users', ['name' => 'Freek Murze']); + $this->assertDatabaseMissing('users', ['name' => 'Freek Murze']); }); test('users cannot delete their account', function () { $this->loginAsAdmin(); - $this->visit('/settings') - ->dontSee('Delete Account'); + $this->get('/settings') + ->assertDontSee('Delete Account'); }); test('users can update their password', function () { - $this->login(); + $user = $this->login(); - $this->visit('/settings') - ->submitForm('Update Password', [ + $response = $this->actingAs($user) + ->put('settings/password', [ 'current_password' => 'password', 'password' => 'QFq^$cz#P@MZa5z7', 'password_confirmation' => 'QFq^$cz#P@MZa5z7', ]) - ->seePageIs('/settings') - ->see('Password successfully changed!'); + ->assertRedirect('/settings'); + + $this->followRedirects($response) + ->assertSee('Password successfully changed!'); assertPasswordWasHashedAndSaved(); }); test('current password is required when updating your password', function () { - $this->login(); + $user = $this->login(); - $this->visit('/settings') - ->submitForm('Update Password', [ + $response = $this->actingAs($user) + ->put('settings/password', [ 'password' => 'QFq^$cz#P@MZa5z7', 'password_confirmation' => 'QFq^$cz#P@MZa5z7', ]) - ->seePageIs('/settings') - ->see('Something went wrong. Please review the fields below.') - ->see('The current password field is required.'); + ->assertInvalid([ + 'current_password' => 'The current password field is required.', + ]); + + $this->followRedirects($response) + ->assertSee('Something went wrong. Please review the fields below.'); }); test('users cannot update their password when it has been compromised in data leaks', function () { - $this->login(); + $user = $this->login(); - $this->visit('/settings') - ->submitForm('Update Password', [ + $response = $this->actingAs($user) + ->put('settings/password', [ 'current_password' => 'password', 'password' => 'newpassword', 'password_confirmation' => 'newpassword', ]) - ->seePageIs('/settings') - ->see('Something went wrong. Please review the fields below.') - ->see('The given password has appeared in a data leak. Please choose a different password.'); + ->assertInvalid([ + 'password' => 'The given password has appeared in a data leak. Please choose a different password.' + ]); + + $this->followRedirects($response) + ->assertSee('Something went wrong. Please review the fields below.'); }); test('users can set their password when they have none set yet', function () { @@ -115,13 +128,15 @@ $this->loginAs($user); - $this->visit('/settings') - ->submitForm('Update Password', [ + $response = $this->actingAs($user) + ->put('settings/password', [ 'password' => 'QFq^$cz#P@MZa5z7', 'password_confirmation' => 'QFq^$cz#P@MZa5z7', ]) - ->seePageIs('/settings') - ->see('Password successfully changed!'); + ->assertRedirect('/settings'); + + $this->followRedirects($response) + ->assertSee('Password successfully changed!'); assertPasswordWasHashedAndSaved(); }); @@ -131,15 +146,17 @@ $this->loginAs($user); - $this->visit('/settings') - ->submitForm('Update Profile', [ + $response = $this->actingAs($user) + ->put('/settings', [ 'name' => 'Freek Murze', 'email' => 'freek@example.com', 'username' => 'freekmurze', 'twitter' => '', ]) - ->seePageIs('/settings') - ->dontSee('freektwitter'); + ->assertRedirect('/settings'); + + $this->followRedirects($response) + ->assertDontSee('freektwitter'); expect($user->fresh()->twitter())->toBeEmpty(); }); @@ -149,16 +166,18 @@ $this->loginAs($user); - $this->visit('/settings') - ->submitForm('Update Profile', [ + $response = $this->actingAs($user) + ->put('/settings', [ 'name' => 'Freek Murze', 'email' => 'freek@example.com', 'username' => 'freekmurze', 'twitter' => 'freektwitter', 'website' => '', ]) - ->seePageIs('/settings') - ->dontSee('https://laravel.io'); + ->assertRedirect('/settings'); + + $this->followRedirects($response) + ->assertDontSee('https://laravel.io'); expect($user->fresh()->website())->toBeEmpty(); }); @@ -168,12 +187,14 @@ $this->loginAs($user); - $this->visit('/settings') - ->submitForm('Generate New Token', [ + $response = $this->actingAs($user) + ->post('/settings/api-tokens', [ 'token_name' => 'My API Token', ]) - ->seePageIs('/settings') - ->see('API token created! Please copy the following token as it will not be shown again:'); + ->assertRedirect('/settings'); + + $this->followRedirects($response) + ->assertSee('API token created! Please copy the following token as it will not be shown again:'); expect($user->refresh()->tokens)->toHaveCount(1); }); @@ -184,12 +205,14 @@ $this->loginAs($user); - $this->visit('/settings') - ->submitForm('Delete Token', [ + $response = $this->actingAs($user) + ->delete('/settings/api-tokens', [ 'id' => $token->accessToken->getKey(), ]) - ->seePageIs('/settings') - ->see('API token successfully removed.'); + ->assertRedirect('/settings'); + + $this->followRedirects($response) + ->assertSee('API token successfully removed.'); expect($user->refresh()->tokens)->toBeEmpty(); }); @@ -202,11 +225,11 @@ $adam->createToken('Adam\'s API Token'); $this->loginAs($adam); - $this->visit('/settings') - ->submitForm('Delete Token', [ + $this->actingAs($adam) + ->delete('/settings/api-tokens', [ 'id' => $token->accessToken->getKey(), ]) - ->seePageIs('/settings'); + ->assertRedirect('/settings'); expect($joe->refresh()->tokens)->toHaveCount(1); });