From badaf08e554e172051db0b8e210b734d8355ba58 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 13 Sep 2021 22:54:21 +0100 Subject: [PATCH 1/9] Removed browserkit from a couple of classess Done a little reorganisation while there of misplaced tests. Moved MarkdownTest to a new PageEditorTest to avoid confusion with other markdown elements and to align with other page tests. --- app/Entities/Models/Book.php | 3 + tests/BrowserKitTest.php | 33 -------- tests/Entity/MarkdownTest.php | 53 ------------ tests/Entity/PageDraftTest.php | 86 ++++++++++--------- tests/Entity/PageEditorTest.php | 52 ++++++++++++ tests/SharedTestHelpers.php | 19 +++++ tests/User/UserManagementTest.php | 22 +++++ tests/User/UserPreferencesTest.php | 41 +++++++++ tests/User/UserProfileTest.php | 132 ++++++++--------------------- 9 files changed, 220 insertions(+), 221 deletions(-) delete mode 100644 tests/Entity/MarkdownTest.php create mode 100644 tests/Entity/PageEditorTest.php diff --git a/app/Entities/Models/Book.php b/app/Entities/Models/Book.php index df30c1c71..f77135480 100644 --- a/app/Entities/Models/Book.php +++ b/app/Entities/Models/Book.php @@ -15,6 +15,9 @@ use Illuminate\Support\Collection; * @property string $description * @property int $image_id * @property Image|null $cover + * @property \Illuminate\Database\Eloquent\Collection $chapters + * @property \Illuminate\Database\Eloquent\Collection $pages + * @property \Illuminate\Database\Eloquent\Collection $directPages */ class Book extends Entity implements HasCoverImage { diff --git a/tests/BrowserKitTest.php b/tests/BrowserKitTest.php index 23eb10887..a4f12d5ea 100644 --- a/tests/BrowserKitTest.php +++ b/tests/BrowserKitTest.php @@ -61,25 +61,6 @@ abstract class BrowserKitTest extends TestCase } } - /** - * Create a group of entities that belong to a specific user. - */ - protected function createEntityChainBelongingToUser(User $creatorUser, ?User $updaterUser = null): array - { - if (empty($updaterUser)) { - $updaterUser = $creatorUser; - } - - $userAttrs = ['created_by' => $creatorUser->id, 'owned_by' => $creatorUser->id, 'updated_by' => $updaterUser->id]; - $book = factory(Book::class)->create($userAttrs); - $chapter = factory(Chapter::class)->create(array_merge(['book_id' => $book->id], $userAttrs)); - $page = factory(Page::class)->create(array_merge(['book_id' => $book->id, 'chapter_id' => $chapter->id], $userAttrs)); - $restrictionService = $this->app[PermissionService::class]; - $restrictionService->buildJointPermissionsForEntity($book); - - return compact('book', 'chapter', 'page'); - } - /** * Helper for updating entity permissions. * @@ -91,20 +72,6 @@ abstract class BrowserKitTest extends TestCase $restrictionService->buildJointPermissionsForEntity($entity); } - /** - * Quick way to create a new user without any permissions. - * - * @param array $attributes - * - * @return mixed - */ - protected function getNewBlankUser($attributes = []) - { - $user = factory(User::class)->create($attributes); - - return $user; - } - /** * Assert that a given string is seen inside an element. * diff --git a/tests/Entity/MarkdownTest.php b/tests/Entity/MarkdownTest.php deleted file mode 100644 index 7de7ea11b..000000000 --- a/tests/Entity/MarkdownTest.php +++ /dev/null @@ -1,53 +0,0 @@ -page = \BookStack\Entities\Models\Page::first(); - } - - protected function setMarkdownEditor() - { - $this->setSettings(['app-editor' => 'markdown']); - } - - public function test_default_editor_is_wysiwyg() - { - $this->assertEquals(setting('app-editor'), 'wysiwyg'); - $this->asAdmin()->visit($this->page->getUrl() . '/edit') - ->pageHasElement('#html-editor'); - } - - public function test_markdown_setting_shows_markdown_editor() - { - $this->setMarkdownEditor(); - $this->asAdmin()->visit($this->page->getUrl() . '/edit') - ->pageNotHasElement('#html-editor') - ->pageHasElement('#markdown-editor'); - } - - public function test_markdown_content_given_to_editor() - { - $this->setMarkdownEditor(); - $mdContent = '# hello. This is a test'; - $this->page->markdown = $mdContent; - $this->page->save(); - $this->asAdmin()->visit($this->page->getUrl() . '/edit') - ->seeInField('markdown', $mdContent); - } - - public function test_html_content_given_to_editor_if_no_markdown() - { - $this->setMarkdownEditor(); - $this->asAdmin()->visit($this->page->getUrl() . '/edit') - ->seeInField('markdown', $this->page->html); - } -} diff --git a/tests/Entity/PageDraftTest.php b/tests/Entity/PageDraftTest.php index 68059af6e..b2fa4bb31 100644 --- a/tests/Entity/PageDraftTest.php +++ b/tests/Entity/PageDraftTest.php @@ -2,12 +2,16 @@ namespace Tests\Entity; +use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Page; use BookStack\Entities\Repos\PageRepo; -use Tests\BrowserKitTest; +use Tests\TestCase; -class PageDraftTest extends BrowserKitTest +class PageDraftTest extends TestCase { + /** + * @var Page + */ protected $page; /** @@ -18,99 +22,101 @@ class PageDraftTest extends BrowserKitTest public function setUp(): void { parent::setUp(); - $this->page = \BookStack\Entities\Models\Page::first(); - $this->pageRepo = app(PageRepo::class); + $this->page = Page::query()->first(); + $this->pageRepo = app()->make(PageRepo::class); } public function test_draft_content_shows_if_available() { $addedContent = '

test message content

'; - $this->asAdmin()->visit($this->page->getUrl('/edit')) - ->dontSeeInField('html', $addedContent); + + $this->asAdmin()->get($this->page->getUrl('/edit')) + ->assertElementNotContains('[name="html"]', $addedContent); $newContent = $this->page->html . $addedContent; $this->pageRepo->updatePageDraft($this->page, ['html' => $newContent]); - $this->asAdmin()->visit($this->page->getUrl('/edit')) - ->seeInField('html', $newContent); + $this->asAdmin()->get($this->page->getUrl('/edit')) + ->assertElementContains('[name="html"]', $newContent); } public function test_draft_not_visible_by_others() { $addedContent = '

test message content

'; - $this->asAdmin()->visit($this->page->getUrl('/edit')) - ->dontSeeInField('html', $addedContent); + $this->asAdmin()->get($this->page->getUrl('/edit')) + ->assertElementNotContains('[name="html"]', $addedContent); $newContent = $this->page->html . $addedContent; $newUser = $this->getEditor(); $this->pageRepo->updatePageDraft($this->page, ['html' => $newContent]); - $this->actingAs($newUser)->visit($this->page->getUrl('/edit')) - ->dontSeeInField('html', $newContent); + $this->actingAs($newUser)->get($this->page->getUrl('/edit')) + ->assertElementNotContains('[name="html"]', $newContent); } public function test_alert_message_shows_if_editing_draft() { $this->asAdmin(); $this->pageRepo->updatePageDraft($this->page, ['html' => 'test content']); - $this->asAdmin()->visit($this->page->getUrl('/edit')) - ->see('You are currently editing a draft'); + $this->asAdmin()->get($this->page->getUrl('/edit')) + ->assertSee('You are currently editing a draft'); } public function test_alert_message_shows_if_someone_else_editing() { - $nonEditedPage = \BookStack\Entities\Models\Page::take(10)->get()->last(); + $nonEditedPage = Page::query()->take(10)->get()->last(); $addedContent = '

test message content

'; - $this->asAdmin()->visit($this->page->getUrl('/edit')) - ->dontSeeInField('html', $addedContent); + $this->asAdmin()->get($this->page->getUrl('/edit')) + ->assertElementNotContains('[name="html"]', $addedContent); $newContent = $this->page->html . $addedContent; $newUser = $this->getEditor(); $this->pageRepo->updatePageDraft($this->page, ['html' => $newContent]); $this->actingAs($newUser) - ->visit($this->page->getUrl('/edit')) - ->see('Admin has started editing this page'); + ->get($this->page->getUrl('/edit')) + ->assertSee('Admin has started editing this page'); $this->flushSession(); - $this->visit($nonEditedPage->getUrl() . '/edit') - ->dontSeeInElement('.notification', 'Admin has started editing this page'); + $this->get($nonEditedPage->getUrl() . '/edit') + ->assertElementNotContains('.notification', 'Admin has started editing this page'); } public function test_draft_pages_show_on_homepage() { - $book = \BookStack\Entities\Models\Book::first(); - $this->asAdmin()->visit('/') - ->dontSeeInElement('#recent-drafts', 'New Page') - ->visit($book->getUrl() . '/create-page') - ->visit('/') - ->seeInElement('#recent-drafts', 'New Page'); + /** @var Book $book */ + $book = Book::query()->first(); + $this->asAdmin()->get('/') + ->assertElementNotContains('#recent-drafts', 'New Page'); + + $this->get($book->getUrl() . '/create-page'); + + $this->get('/')->assertElementContains('#recent-drafts', 'New Page'); } public function test_draft_pages_not_visible_by_others() { - $book = \BookStack\Entities\Models\Book::first(); + /** @var Book $book */ + $book = Book::query()->first(); $chapter = $book->chapters->first(); $newUser = $this->getEditor(); - $this->actingAs($newUser)->visit('/') - ->visit($book->getUrl('/create-page')) - ->visit($chapter->getUrl('/create-page')) - ->visit($book->getUrl()) - ->seeInElement('.book-contents', 'New Page'); + $this->actingAs($newUser)->get($book->getUrl('/create-page')); + $this->get($chapter->getUrl('/create-page')); + $this->get($book->getUrl()) + ->assertElementContains('.book-contents', 'New Page'); - $this->asAdmin() - ->visit($book->getUrl()) - ->dontSeeInElement('.book-contents', 'New Page') - ->visit($chapter->getUrl()) - ->dontSeeInElement('.book-contents', 'New Page'); + $this->asAdmin()->get($book->getUrl()) + ->assertElementNotContains('.book-contents', 'New Page'); + $this->get($chapter->getUrl()) + ->assertElementNotContains('.book-contents', 'New Page'); } public function test_page_html_in_ajax_fetch_response() { $this->asAdmin(); + /** @var Page $page */ $page = Page::query()->first(); - $this->getJson('/ajax/page/' . $page->id); - $this->seeJson([ + $this->getJson('/ajax/page/' . $page->id)->assertJson([ 'html' => $page->html, ]); } diff --git a/tests/Entity/PageEditorTest.php b/tests/Entity/PageEditorTest.php new file mode 100644 index 000000000..8d1c56e16 --- /dev/null +++ b/tests/Entity/PageEditorTest.php @@ -0,0 +1,52 @@ +page = Page::query()->first(); + } + + public function test_default_editor_is_wysiwyg() + { + $this->assertEquals('wysiwyg', setting('app-editor')); + $this->asAdmin()->get($this->page->getUrl() . '/edit') + ->assertElementExists('#html-editor'); + } + + public function test_markdown_setting_shows_markdown_editor() + { + $this->setSettings(['app-editor' => 'markdown']); + $this->asAdmin()->get($this->page->getUrl() . '/edit') + ->assertElementNotExists('#html-editor') + ->assertElementExists('#markdown-editor'); + } + + public function test_markdown_content_given_to_editor() + { + $this->setSettings(['app-editor' => 'markdown']); + + $mdContent = '# hello. This is a test'; + $this->page->markdown = $mdContent; + $this->page->save(); + + $this->asAdmin()->get($this->page->getUrl() . '/edit') + ->assertElementContains('[name="markdown"]', $mdContent); + } + + public function test_html_content_given_to_editor_if_no_markdown() + { + $this->setSettings(['app-editor' => 'markdown']); + $this->asAdmin()->get($this->page->getUrl() . '/edit') + ->assertElementContains('[name="markdown"]', $this->page->html); + } +} \ No newline at end of file diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php index df6c613df..b39509b06 100644 --- a/tests/SharedTestHelpers.php +++ b/tests/SharedTestHelpers.php @@ -211,6 +211,25 @@ trait SharedTestHelpers return $permissionRepo->saveNewRole($roleData); } + /** + * Create a group of entities that belong to a specific user. + */ + protected function createEntityChainBelongingToUser(User $creatorUser, ?User $updaterUser = null): array + { + if (empty($updaterUser)) { + $updaterUser = $creatorUser; + } + + $userAttrs = ['created_by' => $creatorUser->id, 'owned_by' => $creatorUser->id, 'updated_by' => $updaterUser->id]; + $book = factory(Book::class)->create($userAttrs); + $chapter = factory(Chapter::class)->create(array_merge(['book_id' => $book->id], $userAttrs)); + $page = factory(Page::class)->create(array_merge(['book_id' => $book->id, 'chapter_id' => $chapter->id], $userAttrs)); + $restrictionService = $this->app[PermissionService::class]; + $restrictionService->buildJointPermissionsForEntity($book); + + return compact('book', 'chapter', 'page'); + } + /** * Mock the HttpFetcher service and return the given data on fetch. */ diff --git a/tests/User/UserManagementTest.php b/tests/User/UserManagementTest.php index 4fd7bacc7..b7331d870 100644 --- a/tests/User/UserManagementTest.php +++ b/tests/User/UserManagementTest.php @@ -42,4 +42,26 @@ class UserManagementTest extends TestCase 'owned_by' => $newOwner->id, ]); } + + public function test_guest_profile_shows_limited_form() + { + $guest = User::getDefault(); + $resp = $this->asAdmin()->get('/settings/users/' . $guest->id); + $resp->assertSee('Guest'); + $resp->assertElementNotExists('#password'); + } + + public function test_guest_profile_cannot_be_deleted() + { + $guestUser = User::getDefault(); + $resp = $this->asAdmin()->get('/settings/users/' . $guestUser->id . '/delete'); + $resp->assertSee('Delete User'); + $resp->assertSee('Guest'); + $resp->assertElementContains('form[action$="/settings/users/' . $guestUser->id . '"] button', 'Confirm'); + + $resp = $this->delete('/settings/users/' . $guestUser->id); + $resp->assertRedirect('/settings/users/' . $guestUser->id); + $resp = $this->followRedirects($resp); + $resp->assertSee('cannot delete the guest user'); + } } diff --git a/tests/User/UserPreferencesTest.php b/tests/User/UserPreferencesTest.php index 1d5d3e729..b39c2c47c 100644 --- a/tests/User/UserPreferencesTest.php +++ b/tests/User/UserPreferencesTest.php @@ -2,6 +2,7 @@ namespace Tests\User; +use BookStack\Entities\Models\Bookshelf; use Tests\TestCase; class UserPreferencesTest extends TestCase @@ -106,4 +107,44 @@ class UserPreferencesTest extends TestCase $home = $this->get('/login'); $home->assertElementExists('.dark-mode'); } + + public function test_books_view_type_preferences_when_list() + { + $editor = $this->getEditor(); + setting()->putUser($editor, 'books_view_type', 'list'); + + $this->actingAs($editor)->get('/books') + ->assertElementNotExists('.featured-image-container') + ->assertElementExists('.content-wrap .entity-list-item'); + } + + public function test_books_view_type_preferences_when_grid() + { + $editor = $this->getEditor(); + setting()->putUser($editor, 'books_view_type', 'grid'); + + $this->actingAs($editor)->get('/books') + ->assertElementExists('.featured-image-container'); + } + + public function test_shelf_view_type_change() + { + $editor = $this->getEditor(); + /** @var Bookshelf $shelf */ + $shelf = Bookshelf::query()->first(); + setting()->putUser($editor, 'bookshelf_view_type', 'list'); + + $this->actingAs($editor)->get($shelf->getUrl()) + ->assertElementNotExists('.featured-image-container') + ->assertElementExists('.content-wrap .entity-list-item') + ->assertSee('Grid View'); + + $req = $this->patch("/settings/users/{$editor->id}/switch-shelf-view", ['view_type' => 'grid']); + $req->assertRedirect($shelf->getUrl()); + + $this->actingAs($editor)->get($shelf->getUrl()) + ->assertElementExists('.featured-image-container') + ->assertElementNotExists('.content-wrap .entity-list-item') + ->assertSee('List View'); + } } diff --git a/tests/User/UserProfileTest.php b/tests/User/UserProfileTest.php index 859a036e0..3942efa8e 100644 --- a/tests/User/UserProfileTest.php +++ b/tests/User/UserProfileTest.php @@ -5,11 +5,13 @@ namespace Tests\User; use Activity; use BookStack\Actions\ActivityType; use BookStack\Auth\User; -use BookStack\Entities\Models\Bookshelf; -use Tests\BrowserKitTest; +use Tests\TestCase; -class UserProfileTest extends BrowserKitTest +class UserProfileTest extends TestCase { + /** + * @var User + */ protected $user; public function setUp(): void @@ -21,74 +23,73 @@ class UserProfileTest extends BrowserKitTest public function test_profile_page_shows_name() { $this->asAdmin() - ->visit('/user/' . $this->user->slug) - ->see($this->user->name); + ->get('/user/' . $this->user->slug) + ->assertSee($this->user->name); } public function test_profile_page_shows_recent_entities() { $content = $this->createEntityChainBelongingToUser($this->user, $this->user); - $this->asAdmin() - ->visit('/user/' . $this->user->slug) - // Check the recently created page is shown - ->see($content['page']->name) - // Check the recently created chapter is shown - ->see($content['chapter']->name) - // Check the recently created book is shown - ->see($content['book']->name); + $resp = $this->asAdmin()->get('/user/' . $this->user->slug); + // Check the recently created page is shown + $resp->assertSee($content['page']->name); + // Check the recently created chapter is shown + $resp->assertSee($content['chapter']->name); + // Check the recently created book is shown + $resp->assertSee($content['book']->name); } public function test_profile_page_shows_created_content_counts() { - $newUser = $this->getNewBlankUser(); + $newUser = factory(User::class)->create(); - $this->asAdmin()->visit('/user/' . $newUser->slug) - ->see($newUser->name) - ->seeInElement('#content-counts', '0 Books') - ->seeInElement('#content-counts', '0 Chapters') - ->seeInElement('#content-counts', '0 Pages'); + $this->asAdmin()->get('/user/' . $newUser->slug) + ->assertSee($newUser->name) + ->assertElementContains('#content-counts', '0 Books') + ->assertElementContains('#content-counts', '0 Chapters') + ->assertElementContains('#content-counts', '0 Pages'); $this->createEntityChainBelongingToUser($newUser, $newUser); - $this->asAdmin()->visit('/user/' . $newUser->slug) - ->see($newUser->name) - ->seeInElement('#content-counts', '1 Book') - ->seeInElement('#content-counts', '1 Chapter') - ->seeInElement('#content-counts', '1 Page'); + $this->asAdmin()->get('/user/' . $newUser->slug) + ->assertSee($newUser->name) + ->assertElementContains('#content-counts', '1 Book') + ->assertElementContains('#content-counts', '1 Chapter') + ->assertElementContains('#content-counts', '1 Page'); } public function test_profile_page_shows_recent_activity() { - $newUser = $this->getNewBlankUser(); + $newUser = factory(User::class)->create(); $this->actingAs($newUser); $entities = $this->createEntityChainBelongingToUser($newUser, $newUser); Activity::addForEntity($entities['book'], ActivityType::BOOK_UPDATE); Activity::addForEntity($entities['page'], ActivityType::PAGE_CREATE); - $this->asAdmin()->visit('/user/' . $newUser->slug) - ->seeInElement('#recent-user-activity', 'updated book') - ->seeInElement('#recent-user-activity', 'created page') - ->seeInElement('#recent-user-activity', $entities['page']->name); + $this->asAdmin()->get('/user/' . $newUser->slug) + ->assertElementContains('#recent-user-activity', 'updated book') + ->assertElementContains('#recent-user-activity', 'created page') + ->assertElementContains('#recent-user-activity', $entities['page']->name); } - public function test_clicking_user_name_in_activity_leads_to_profile_page() + public function test_user_activity_has_link_leading_to_profile() { - $newUser = $this->getNewBlankUser(); + $newUser = factory(User::class)->create(); $this->actingAs($newUser); $entities = $this->createEntityChainBelongingToUser($newUser, $newUser); Activity::addForEntity($entities['book'], ActivityType::BOOK_UPDATE); Activity::addForEntity($entities['page'], ActivityType::PAGE_CREATE); - $this->asAdmin()->visit('/')->clickInElement('#recent-activity', $newUser->name) - ->seePageIs('/user/' . $newUser->slug) - ->see($newUser->name); + $linkSelector = '#recent-activity a[href$="/user/' . $newUser->slug . '"]'; + $this->asAdmin()->get('/') + ->assertElementContains($linkSelector, $newUser->name); } public function test_profile_has_search_links_in_created_entity_lists() { $user = $this->getEditor(); - $resp = $this->actingAs($this->getAdmin())->visit('/user/' . $user->slug); + $resp = $this->actingAs($this->getAdmin())->get('/user/' . $user->slug); $expectedLinks = [ '/search?term=%7Bcreated_by%3A' . $user->slug . '%7D+%7Btype%3Apage%7D', @@ -98,66 +99,7 @@ class UserProfileTest extends BrowserKitTest ]; foreach ($expectedLinks as $link) { - $resp->seeInElement('[href$="' . $link . '"]', 'View All'); + $resp->assertElementContains('[href$="' . $link . '"]', 'View All'); } } - - public function test_guest_profile_shows_limited_form() - { - $this->asAdmin() - ->visit('/settings/users') - ->click('Guest') - ->dontSeeElement('#password'); - } - - public function test_guest_profile_cannot_be_deleted() - { - $guestUser = User::getDefault(); - $this->asAdmin()->visit('/settings/users/' . $guestUser->id . '/delete') - ->see('Delete User')->see('Guest') - ->press('Confirm') - ->seePageIs('/settings/users/' . $guestUser->id) - ->see('cannot delete the guest user'); - } - - public function test_books_view_is_list() - { - $editor = $this->getEditor(); - setting()->putUser($editor, 'books_view_type', 'list'); - - $this->actingAs($editor) - ->visit('/books') - ->pageNotHasElement('.featured-image-container') - ->pageHasElement('.content-wrap .entity-list-item'); - } - - public function test_books_view_is_grid() - { - $editor = $this->getEditor(); - setting()->putUser($editor, 'books_view_type', 'grid'); - - $this->actingAs($editor) - ->visit('/books') - ->pageHasElement('.featured-image-container'); - } - - public function test_shelf_view_type_change() - { - $editor = $this->getEditor(); - $shelf = Bookshelf::query()->first(); - setting()->putUser($editor, 'bookshelf_view_type', 'list'); - - $this->actingAs($editor)->visit($shelf->getUrl()) - ->pageNotHasElement('.featured-image-container') - ->pageHasElement('.content-wrap .entity-list-item') - ->see('Grid View'); - - $req = $this->patch("/settings/users/{$editor->id}/switch-shelf-view", ['view_type' => 'grid']); - $req->assertRedirectedTo($shelf->getUrl()); - - $this->actingAs($editor)->visit($shelf->getUrl()) - ->pageHasElement('.featured-image-container') - ->pageNotHasElement('.content-wrap .entity-list-item') - ->see('List View'); - } } From 121a746d591e2f79d7426a63645b37c73ad8f2ba Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 13 Sep 2021 23:26:39 +0100 Subject: [PATCH 2/9] Moved/Updated old Activity tracking tests, started on entity tests Started moving old EntityTests into more appropriate places within non-browserkit-test classes. Still many more to do. --- tests/ActivityTrackingTest.php | 37 ------------------ tests/Entity/BookShelfTest.php | 8 ++++ tests/Entity/BookTest.php | 71 ++++++++++++++++++++++++++++++++++ tests/Entity/EntityTest.php | 45 --------------------- 4 files changed, 79 insertions(+), 82 deletions(-) delete mode 100644 tests/ActivityTrackingTest.php diff --git a/tests/ActivityTrackingTest.php b/tests/ActivityTrackingTest.php deleted file mode 100644 index 494a1f506..000000000 --- a/tests/ActivityTrackingTest.php +++ /dev/null @@ -1,37 +0,0 @@ -take(10); - - $this->asAdmin()->visit('/books') - ->dontSeeInElement('#recents', $books[0]->name) - ->dontSeeInElement('#recents', $books[1]->name) - ->visit($books[0]->getUrl()) - ->visit($books[1]->getUrl()) - ->visit('/books') - ->seeInElement('#recents', $books[0]->name) - ->seeInElement('#recents', $books[1]->name); - } - - public function test_popular_books() - { - $books = Book::all()->take(10); - - $this->asAdmin()->visit('/books') - ->dontSeeInElement('#popular', $books[0]->name) - ->dontSeeInElement('#popular', $books[1]->name) - ->visit($books[0]->getUrl()) - ->visit($books[1]->getUrl()) - ->visit($books[0]->getUrl()) - ->visit('/books') - ->seeInNthElement('#popular .book', 0, $books[0]->name) - ->seeInNthElement('#popular .book', 1, $books[1]->name); - } -} diff --git a/tests/Entity/BookShelfTest.php b/tests/Entity/BookShelfTest.php index 480d29002..1780ddee8 100644 --- a/tests/Entity/BookShelfTest.php +++ b/tests/Entity/BookShelfTest.php @@ -369,4 +369,12 @@ class BookShelfTest extends TestCase $resp = $this->asEditor()->get($newBook->getUrl()); $resp->assertDontSee($shelfInfo['name']); } + + public function test_cancel_on_child_book_creation_returns_to_original_shelf() + { + /** @var Bookshelf $shelf */ + $shelf = Bookshelf::query()->first(); + $resp = $this->asEditor()->get($shelf->getUrl('/create-book')); + $resp->assertElementContains('form a[href="' . $shelf->getUrl() . '"]', 'Cancel'); + } } diff --git a/tests/Entity/BookTest.php b/tests/Entity/BookTest.php index b4ba2fa82..a2d4aee20 100644 --- a/tests/Entity/BookTest.php +++ b/tests/Entity/BookTest.php @@ -3,6 +3,7 @@ namespace Tests\Entity; use BookStack\Entities\Models\Book; +use BookStack\Entities\Models\Bookshelf; use Tests\TestCase; class BookTest extends TestCase @@ -34,6 +35,20 @@ class BookTest extends TestCase $redirectReq->assertNotificationContains('Book Successfully Deleted'); } + public function test_cancel_on_create_page_leads_back_to_books_listing() + { + $resp = $this->asEditor()->get('/create-book'); + $resp->assertElementContains('form a[href="' . url('/books') . '"]', 'Cancel'); + } + + public function test_cancel_on_edit_book_page_leads_back_to_book() + { + /** @var Book $book */ + $book = Book::query()->first(); + $resp = $this->asEditor()->get($book->getUrl('/edit')); + $resp->assertElementContains('form a[href="' . $book->getUrl() . '"]', 'Cancel'); + } + public function test_next_previous_navigation_controls_show_within_book_content() { $book = Book::query()->first(); @@ -48,4 +63,60 @@ class BookTest extends TestCase $resp->assertElementContains('#sibling-navigation', 'Previous'); $resp->assertElementContains('#sibling-navigation', substr($chapter->name, 0, 20)); } + + public function test_recently_viewed_books_updates_as_expected() + { + $books = Book::all()->take(2); + + $this->asAdmin()->get('/books') + ->assertElementNotContains('#recents', $books[0]->name) + ->assertElementNotContains('#recents', $books[1]->name); + + $this->get($books[0]->getUrl()); + $this->get($books[1]->getUrl()); + + $this->get('/books') + ->assertElementContains('#recents', $books[0]->name) + ->assertElementContains('#recents', $books[1]->name); + } + + public function test_popular_books_updates_upon_visits() + { + $books = Book::all()->take(2); + + $this->asAdmin()->get('/books') + ->assertElementNotContains('#popular', $books[0]->name) + ->assertElementNotContains('#popular', $books[1]->name); + + $this->get($books[0]->getUrl()); + $this->get($books[1]->getUrl()); + $this->get($books[0]->getUrl()); + + $this->get('/books') + ->assertElementContains('#popular .book:nth-child(1)', $books[0]->name) + ->assertElementContains('#popular .book:nth-child(2)', $books[1]->name); + } + + public function test_books_view_shows_view_toggle_option() + { + /** @var Book $book */ + $editor = $this->getEditor(); + setting()->putUser($editor, 'books_view_type', 'list'); + + $resp = $this->actingAs($editor)->get('/books'); + $resp->assertElementContains('form[action$="/settings/users/' . $editor->id . '/switch-books-view"]', 'Grid View'); + $resp->assertElementExists('input[name="view_type"][value="grid"]'); + + $resp = $this->patch("/settings/users/{$editor->id}/switch-books-view", ['view_type' => 'grid']); + $resp->assertRedirect(); + $this->assertEquals('grid', setting()->getUser($editor, 'books_view_type')); + + $resp = $this->actingAs($editor)->get('/books'); + $resp->assertElementContains('form[action$="/settings/users/' . $editor->id . '/switch-books-view"]', 'List View'); + $resp->assertElementExists('input[name="view_type"][value="list"]'); + + $resp = $this->patch("/settings/users/{$editor->id}/switch-books-view", ['view_type' => 'list']); + $resp->assertRedirect(); + $this->assertEquals('list', setting()->getUser($editor, 'books_view_type')); + } } diff --git a/tests/Entity/EntityTest.php b/tests/Entity/EntityTest.php index f8c88b1fe..60d66d07f 100644 --- a/tests/Entity/EntityTest.php +++ b/tests/Entity/EntityTest.php @@ -67,26 +67,6 @@ class EntityTest extends BrowserKitTest ->see($firstChapter->name); } - public function test_toggle_book_view() - { - $editor = $this->getEditor(); - setting()->putUser($editor, 'books_view_type', 'grid'); - - $this->actingAs($editor) - ->visit('/books') - ->pageHasElement('.featured-image-container') - ->submitForm('List View') - // Check redirection. - ->seePageIs('/books') - ->pageNotHasElement('.featured-image-container'); - - $this->actingAs($editor) - ->visit('/books') - ->submitForm('Grid View') - ->seePageIs('/books') - ->pageHasElement('.featured-image-container'); - } - public function pageCreation($chapter) { $page = factory(Page::class)->make([ @@ -282,31 +262,6 @@ class EntityTest extends BrowserKitTest $this->assertEquals('parta-partb-partc', $book->slug); } - public function test_shelf_cancel_creation_returns_to_correct_place() - { - $shelf = Bookshelf::first(); - - // Cancel button from shelf goes back to shelf - $this->asEditor()->visit($shelf->getUrl('/create-book')) - ->see('Cancel') - ->click('Cancel') - ->seePageIs($shelf->getUrl()); - - // Cancel button from books goes back to books - $this->asEditor()->visit('/create-book') - ->see('Cancel') - ->click('Cancel') - ->seePageIs('/books'); - - // Cancel button from book edit goes back to book - $book = Book::first(); - - $this->asEditor()->visit($book->getUrl('/edit')) - ->see('Cancel') - ->click('Cancel') - ->seePageIs($book->getUrl()); - } - public function test_page_within_chapter_deletion_returns_to_chapter() { $chapter = Chapter::query()->first(); From de8cceb0f72f19ed0b3aa43d7a139639fa634bd2 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 15 Sep 2021 22:18:37 +0100 Subject: [PATCH 3/9] Moved more tests out of EntityTest --- tests/Entity/BookTest.php | 24 +++++++ tests/Entity/EntityTest.php | 110 -------------------------------- tests/Entity/PageEditorTest.php | 25 ++++++++ tests/Entity/PageTest.php | 78 ++++++++++++++++------ tests/Entity/SortTest.php | 28 ++++++++ tests/SharedTestHelpers.php | 1 + 6 files changed, 138 insertions(+), 128 deletions(-) diff --git a/tests/Entity/BookTest.php b/tests/Entity/BookTest.php index a2d4aee20..a3effe779 100644 --- a/tests/Entity/BookTest.php +++ b/tests/Entity/BookTest.php @@ -119,4 +119,28 @@ class BookTest extends TestCase $resp->assertRedirect(); $this->assertEquals('list', setting()->getUser($editor, 'books_view_type')); } + + public function test_slug_multi_byte_url_safe() + { + $book = $this->newBook([ + 'name' => 'информация', + ]); + + $this->assertEquals('informatsiya', $book->slug); + + $book = $this->newBook([ + 'name' => '¿Qué?', + ]); + + $this->assertEquals('que', $book->slug); + } + + public function test_slug_format() + { + $book = $this->newBook([ + 'name' => 'PartA / PartB / PartC', + ]); + + $this->assertEquals('parta-partb-partc', $book->slug); + } } diff --git a/tests/Entity/EntityTest.php b/tests/Entity/EntityTest.php index 60d66d07f..16f21bd5d 100644 --- a/tests/Entity/EntityTest.php +++ b/tests/Entity/EntityTest.php @@ -4,11 +4,9 @@ namespace Tests\Entity; use BookStack\Auth\UserRepo; use BookStack\Entities\Models\Book; -use BookStack\Entities\Models\Bookshelf; use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Page; use BookStack\Entities\Repos\PageRepo; -use Carbon\Carbon; use Tests\BrowserKitTest; class EntityTest extends BrowserKitTest @@ -41,32 +39,6 @@ class EntityTest extends BrowserKitTest return Book::find($book->id); } - public function test_book_sort_page_shows() - { - $books = Book::all(); - $bookToSort = $books[0]; - $this->asAdmin() - ->visit($bookToSort->getUrl()) - ->click('Sort') - ->seePageIs($bookToSort->getUrl() . '/sort') - ->seeStatusCode(200) - ->see($bookToSort->name); - } - - public function test_book_sort_item_returns_book_content() - { - $books = Book::all(); - $bookToSort = $books[0]; - $firstPage = $bookToSort->pages[0]; - $firstChapter = $bookToSort->chapters[0]; - $this->asAdmin() - ->visit($bookToSort->getUrl() . '/sort-item') - // Ensure book details are returned - ->see($bookToSort->name) - ->see($firstPage->name) - ->see($firstChapter->name); - } - public function pageCreation($chapter) { $page = factory(Page::class)->make([ @@ -189,86 +161,4 @@ class EntityTest extends BrowserKitTest ->click('Revisions')->seeStatusCode(200); } - public function test_recently_updated_pages_view() - { - $user = $this->getEditor(); - $content = $this->createEntityChainBelongingToUser($user); - - $this->asAdmin()->visit('/pages/recently-updated') - ->seeInNthElement('.entity-list .page', 0, $content['page']->name); - } - - public function test_old_page_slugs_redirect_to_new_pages() - { - $page = Page::first(); - $pageUrl = $page->getUrl(); - $newPageUrl = '/books/' . $page->book->slug . '/page/super-test-page'; - // Need to save twice since revisions are not generated in seeder. - $this->asAdmin()->visit($pageUrl) - ->clickInElement('#content', 'Edit') - ->type('super test', '#name') - ->press('Save Page'); - - $page = Page::first(); - $pageUrl = $page->getUrl(); - - // Second Save - $this->visit($pageUrl) - ->clickInElement('#content', 'Edit') - ->type('super test page', '#name') - ->press('Save Page') - // Check redirect - ->seePageIs($newPageUrl); - - $this->visit($pageUrl) - ->seePageIs($newPageUrl); - } - - public function test_recently_updated_pages_on_home() - { - $page = Page::orderBy('updated_at', 'asc')->first(); - Page::where('id', '!=', $page->id)->update([ - 'updated_at' => Carbon::now()->subSecond(1), - ]); - $this->asAdmin()->visit('/') - ->dontSeeInElement('#recently-updated-pages', $page->name); - $this->visit($page->getUrl() . '/edit') - ->press('Save Page') - ->visit('/') - ->seeInElement('#recently-updated-pages', $page->name); - } - - public function test_slug_multi_byte_url_safe() - { - $book = $this->newBook([ - 'name' => 'информация', - ]); - - $this->assertEquals('informatsiya', $book->slug); - - $book = $this->newBook([ - 'name' => '¿Qué?', - ]); - - $this->assertEquals('que', $book->slug); - } - - public function test_slug_format() - { - $book = $this->newBook([ - 'name' => 'PartA / PartB / PartC', - ]); - - $this->assertEquals('parta-partb-partc', $book->slug); - } - - public function test_page_within_chapter_deletion_returns_to_chapter() - { - $chapter = Chapter::query()->first(); - $page = $chapter->pages()->first(); - - $this->asEditor()->visit($page->getUrl('/delete')) - ->submitForm('Confirm') - ->seePageIs($chapter->getUrl()); - } } diff --git a/tests/Entity/PageEditorTest.php b/tests/Entity/PageEditorTest.php index 8d1c56e16..588de4f17 100644 --- a/tests/Entity/PageEditorTest.php +++ b/tests/Entity/PageEditorTest.php @@ -2,6 +2,7 @@ namespace Tests\Entity; +use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Page; use Tests\TestCase; @@ -49,4 +50,28 @@ class PageEditorTest extends TestCase $this->asAdmin()->get($this->page->getUrl() . '/edit') ->assertElementContains('[name="markdown"]', $this->page->html); } + + public function test_empty_markdown_still_saves_without_error() + { + $this->setSettings(['app-editor' => 'markdown']); + /** @var Book $book */ + $book = Book::query()->first(); + + $this->asEditor()->get($book->getUrl('/create-page')); + $draft = Page::query()->where('book_id', '=', $book->id) + ->where('draft', '=', true)->first(); + + $details = [ + 'name' => 'my page', + 'markdown' => '', + ]; + $resp = $this->post($book->getUrl("/draft/{$draft->id}"), $details); + $resp->assertRedirect(); + + $this->assertDatabaseHas('pages', [ + 'markdown' => $details['markdown'], + 'id' => $draft->id, + 'draft' => false, + ]); + } } \ No newline at end of file diff --git a/tests/Entity/PageTest.php b/tests/Entity/PageTest.php index 2721c225c..3fb847e42 100644 --- a/tests/Entity/PageTest.php +++ b/tests/Entity/PageTest.php @@ -3,7 +3,9 @@ namespace Tests\Entity; use BookStack\Entities\Models\Book; +use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Page; +use Carbon\Carbon; use Tests\TestCase; class PageTest extends TestCase @@ -190,26 +192,66 @@ class PageTest extends TestCase ]); } - public function test_empty_markdown_still_saves_without_error() + public function test_old_page_slugs_redirect_to_new_pages() { - $this->setSettings(['app-editor' => 'markdown']); - $book = Book::query()->first(); + /** @var Page $page */ + $page = Page::query()->first(); - $this->asEditor()->get($book->getUrl('/create-page')); - $draft = Page::query()->where('book_id', '=', $book->id) - ->where('draft', '=', true)->first(); - - $details = [ - 'name' => 'my page', - 'markdown' => '', - ]; - $resp = $this->post($book->getUrl("/draft/{$draft->id}"), $details); - $resp->assertRedirect(); - - $this->assertDatabaseHas('pages', [ - 'markdown' => $details['markdown'], - 'id' => $draft->id, - 'draft' => false, + // Need to save twice since revisions are not generated in seeder. + $this->asAdmin()->put($page->getUrl(), [ + 'name' => 'super test', + 'html' => '

' ]); + + $page->refresh(); + $pageUrl = $page->getUrl(); + + $this->put($pageUrl, [ + 'name' => 'super test page', + 'html' => '

' + ]); + + $this->get($pageUrl) + ->assertRedirect("/books/{$page->book->slug}/page/super-test-page"); } + + public function test_page_within_chapter_deletion_returns_to_chapter() + { + /** @var Chapter $chapter */ + $chapter = Chapter::query()->first(); + $page = $chapter->pages()->first(); + + $this->asEditor()->delete($page->getUrl()) + ->assertRedirect($chapter->getUrl()); + } + + public function test_recently_updated_pages_view() + { + $user = $this->getEditor(); + $content = $this->createEntityChainBelongingToUser($user); + + $this->asAdmin()->get('/pages/recently-updated') + ->assertElementContains('.entity-list .page:nth-child(1)', $content['page']->name); + } + + public function test_recently_updated_pages_on_home() + { + /** @var Page $page */ + $page = Page::query()->orderBy('updated_at', 'asc')->first(); + Page::query()->where('id', '!=', $page->id)->update([ + 'updated_at' => Carbon::now()->subSecond(1), + ]); + + $this->asAdmin()->get('/') + ->assertElementNotContains('#recently-updated-pages', $page->name); + + $this->put($page->getUrl(), [ + 'name' => $page->name, + 'html' => $page->html, + ]); + + $this->get('/') + ->assertElementContains('#recently-updated-pages', $page->name); + } + } diff --git a/tests/Entity/SortTest.php b/tests/Entity/SortTest.php index e058b39aa..5cfc5c3c5 100644 --- a/tests/Entity/SortTest.php +++ b/tests/Entity/SortTest.php @@ -216,6 +216,19 @@ class SortTest extends TestCase $this->assertEquals($newBook->id, $pageToCheck->book_id); } + public function test_book_sort_page_shows() + { + /** @var Book $bookToSort */ + $bookToSort = Book::query()->first(); + + $resp = $this->asAdmin()->get($bookToSort->getUrl()); + $resp->assertElementExists('a[href="' . $bookToSort->getUrl('/sort') . '"]'); + + $resp = $this->get($bookToSort->getUrl('/sort')); + $resp->assertStatus(200); + $resp->assertSee($bookToSort->name); + } + public function test_book_sort() { $oldBook = Book::query()->first(); @@ -259,6 +272,21 @@ class SortTest extends TestCase $checkResp->assertSee($newBook->name); } + public function test_book_sort_item_returns_book_content() + { + $books = Book::all(); + $bookToSort = $books[0]; + $firstPage = $bookToSort->pages[0]; + $firstChapter = $bookToSort->chapters[0]; + + $resp = $this->asAdmin()->get($bookToSort->getUrl() . '/sort-item'); + + // Ensure book details are returned + $resp->assertSee($bookToSort->name); + $resp->assertSee($firstPage->name); + $resp->assertSee($firstChapter->name); + } + public function test_pages_in_book_show_sorted_by_priority() { /** @var Book $book */ diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php index b39509b06..cd0d244c9 100644 --- a/tests/SharedTestHelpers.php +++ b/tests/SharedTestHelpers.php @@ -213,6 +213,7 @@ trait SharedTestHelpers /** * Create a group of entities that belong to a specific user. + * @return array{book: Book, chapter: Chapter, page: Page} */ protected function createEntityChainBelongingToUser(User $creatorUser, ?User $updaterUser = null): array { From 5d93dd258ebc7fe5f63567597fea75c3059ddbf0 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 17 Sep 2021 21:29:16 +0100 Subject: [PATCH 4/9] Finished moving EntityTests out to new TestCase files --- tests/Entity/BookTest.php | 65 +++++++++++- tests/Entity/ChapterTest.php | 26 ++++- tests/Entity/EntityAccessTest.php | 52 ++++++++++ tests/Entity/EntityTest.php | 164 ------------------------------ tests/Entity/PageTest.php | 27 +++++ 5 files changed, 167 insertions(+), 167 deletions(-) create mode 100644 tests/Entity/EntityAccessTest.php delete mode 100644 tests/Entity/EntityTest.php diff --git a/tests/Entity/BookTest.php b/tests/Entity/BookTest.php index a3effe779..fa63c0bf9 100644 --- a/tests/Entity/BookTest.php +++ b/tests/Entity/BookTest.php @@ -3,12 +3,73 @@ namespace Tests\Entity; use BookStack\Entities\Models\Book; -use BookStack\Entities\Models\Bookshelf; use Tests\TestCase; class BookTest extends TestCase { - public function test_book_delete() + public function test_create() + { + $book = factory(Book::class)->make([ + 'name' => 'My First Book', + ]); + + $resp = $this->asEditor()->get('/books'); + $resp->assertElementContains('a[href="' . url('/create-book') . '"]', 'Create New Book'); + + $resp = $this->get('/create-book'); + $resp->assertElementContains('form[action="' . url('/books') . '"][method="POST"]', 'Save Book'); + + $resp = $this->post('/books', $book->only('name', 'description')); + $resp->assertRedirect('/books/my-first-book'); + + $resp = $this->get('/books/my-first-book'); + $resp->assertSee($book->name); + $resp->assertSee($book->description); + } + + public function test_create_uses_different_slugs_when_name_reused() + { + $book = factory(Book::class)->make([ + 'name' => 'My First Book', + ]); + + $this->asEditor()->post('/books', $book->only('name', 'description')); + $this->asEditor()->post('/books', $book->only('name', 'description')); + + $books = Book::query()->where('name', '=', $book->name) + ->orderBy('id', 'desc') + ->take(2) + ->get(); + + $this->assertMatchesRegularExpression('/my-first-book-[0-9a-zA-Z]{3}/', $books[0]->slug); + $this->assertEquals('my-first-book', $books[1]->slug); + } + + public function test_update() + { + /** @var Book $book */ + $book = Book::query()->first(); + // Cheeky initial update to refresh slug + $this->asEditor()->put($book->getUrl(), ['name' => $book->name . '5', 'description' => $book->description]); + $book->refresh(); + + $newName = $book->name . ' Updated'; + $newDesc = $book->description . ' with more content'; + + $resp = $this->get($book->getUrl('/edit')); + $resp->assertSee($book->name); + $resp->assertSee($book->description); + $resp->assertElementContains('form[action="' . $book->getUrl() . '"]', 'Save Book'); + + $resp = $this->put($book->getUrl(), ['name' => $newName, 'description' => $newDesc]); + $resp->assertRedirect($book->getUrl() . '-updated'); + + $resp = $this->get($book->getUrl() . '-updated'); + $resp->assertSee($newName); + $resp->assertSee($newDesc); + } + + public function test_delete() { $book = Book::query()->whereHas('pages')->whereHas('chapters')->first(); $this->assertNull($book->deleted_at); diff --git a/tests/Entity/ChapterTest.php b/tests/Entity/ChapterTest.php index 45c132e89..ea29ece5d 100644 --- a/tests/Entity/ChapterTest.php +++ b/tests/Entity/ChapterTest.php @@ -2,12 +2,36 @@ namespace Tests\Entity; +use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Chapter; use Tests\TestCase; class ChapterTest extends TestCase { - public function test_chapter_delete() + public function test_create() + { + /** @var Book $book */ + $book = Book::query()->first(); + + $chapter = factory(Chapter::class)->make([ + 'name' => 'My First Chapter', + ]); + + $resp = $this->asEditor()->get($book->getUrl()); + $resp->assertElementContains('a[href="' . $book->getUrl('/create-chapter') . '"]', 'New Chapter'); + + $resp = $this->get($book->getUrl('/create-chapter')); + $resp->assertElementContains('form[action="' . $book->getUrl('/create-chapter') . '"][method="POST"]', 'Save Chapter'); + + $resp = $this->post($book->getUrl('/create-chapter'), $chapter->only('name', 'description')); + $resp->assertRedirect($book->getUrl('/chapter/my-first-chapter')); + + $resp = $this->get($book->getUrl('/chapter/my-first-chapter')); + $resp->assertSee($chapter->name); + $resp->assertSee($chapter->description); + } + + public function test_delete() { $chapter = Chapter::query()->whereHas('pages')->first(); $this->assertNull($chapter->deleted_at); diff --git a/tests/Entity/EntityAccessTest.php b/tests/Entity/EntityAccessTest.php new file mode 100644 index 000000000..f2f244538 --- /dev/null +++ b/tests/Entity/EntityAccessTest.php @@ -0,0 +1,52 @@ +getEditor(); + $updater = $this->getViewer(); + $entities = $this->createEntityChainBelongingToUser($creator, $updater); + app()->make(UserRepo::class)->destroy($creator); + app()->make(PageRepo::class)->update($entities['page'], ['html' => '

hello!

>']); + + $this->checkEntitiesViewable($entities); + } + + public function test_entities_viewable_after_updater_deletion() + { + // Create required assets and revisions + $creator = $this->getViewer(); + $updater = $this->getEditor(); + $entities = $this->createEntityChainBelongingToUser($creator, $updater); + app()->make(UserRepo::class)->destroy($updater); + app()->make(PageRepo::class)->update($entities['page'], ['html' => '

Hello there!

']); + + $this->checkEntitiesViewable($entities); + } + + /** + * @param array $entities + */ + private function checkEntitiesViewable(array $entities) + { + // Check pages and books are visible. + $this->asAdmin(); + foreach ($entities as $entity) { + $this->get($entity->getUrl()) + ->assertStatus(200) + ->assertSee($entity->name); + } + + // Check revision listing shows no errors. + $this->get($entities['page']->getUrl('/revisions'))->assertStatus(200); + } +} diff --git a/tests/Entity/EntityTest.php b/tests/Entity/EntityTest.php deleted file mode 100644 index 16f21bd5d..000000000 --- a/tests/Entity/EntityTest.php +++ /dev/null @@ -1,164 +0,0 @@ -bookCreation(); - $chapter = $this->chapterCreation($book); - $this->pageCreation($chapter); - - // Test Updating - $this->bookUpdate($book); - } - - public function bookUpdate(Book $book) - { - $newName = $book->name . ' Updated'; - $this->asAdmin() - // Go to edit screen - ->visit($book->getUrl() . '/edit') - ->see($book->name) - // Submit new name - ->type($newName, '#name') - ->press('Save Book') - // Check page url and text - ->seePageIs($book->getUrl() . '-updated') - ->see($newName); - - return Book::find($book->id); - } - - public function pageCreation($chapter) - { - $page = factory(Page::class)->make([ - 'name' => 'My First Page', - ]); - - $this->asAdmin() - // Navigate to page create form - ->visit($chapter->getUrl()) - ->click('New Page'); - - $draftPage = Page::where('draft', '=', true)->orderBy('created_at', 'desc')->first(); - - $this->seePageIs($draftPage->getUrl()) - // Fill out form - ->type($page->name, '#name') - ->type($page->html, '#html') - ->press('Save Page') - // Check redirect and page - ->seePageIs($chapter->book->getUrl() . '/page/my-first-page') - ->see($page->name); - - $page = Page::where('slug', '=', 'my-first-page')->where('chapter_id', '=', $chapter->id)->first(); - - return $page; - } - - public function chapterCreation(Book $book) - { - $chapter = factory(Chapter::class)->make([ - 'name' => 'My First Chapter', - ]); - - $this->asAdmin() - // Navigate to chapter create page - ->visit($book->getUrl()) - ->click('New Chapter') - ->seePageIs($book->getUrl() . '/create-chapter') - // Fill out form - ->type($chapter->name, '#name') - ->type($chapter->description, '#description') - ->press('Save Chapter') - // Check redirect and landing page - ->seePageIs($book->getUrl() . '/chapter/my-first-chapter') - ->see($chapter->name)->see($chapter->description); - - $chapter = Chapter::where('slug', '=', 'my-first-chapter')->where('book_id', '=', $book->id)->first(); - - return $chapter; - } - - public function bookCreation() - { - $book = factory(Book::class)->make([ - 'name' => 'My First Book', - ]); - $this->asAdmin() - ->visit('/books') - // Choose to create a book - ->click('Create New Book') - ->seePageIs('/create-book') - // Fill out form & save - ->type($book->name, '#name') - ->type($book->description, '#description') - ->press('Save Book') - // Check it redirects correctly - ->seePageIs('/books/my-first-book') - ->see($book->name)->see($book->description); - - // Ensure duplicate names are given different slugs - $this->asAdmin() - ->visit('/create-book') - ->type($book->name, '#name') - ->type($book->description, '#description') - ->press('Save Book'); - - $expectedPattern = '/\/books\/my-first-book-[0-9a-zA-Z]{3}/'; - $this->assertMatchesRegularExpression($expectedPattern, $this->currentUri, "Did not land on expected page [$expectedPattern].\n"); - - $book = Book::where('slug', '=', 'my-first-book')->first(); - - return $book; - } - - public function test_entities_viewable_after_creator_deletion() - { - // Create required assets and revisions - $creator = $this->getEditor(); - $updater = $this->getEditor(); - $entities = $this->createEntityChainBelongingToUser($creator, $updater); - $this->actingAs($creator); - app(UserRepo::class)->destroy($creator); - app(PageRepo::class)->update($entities['page'], ['html' => '

hello!

>']); - - $this->checkEntitiesViewable($entities); - } - - public function test_entities_viewable_after_updater_deletion() - { - // Create required assets and revisions - $creator = $this->getEditor(); - $updater = $this->getEditor(); - $entities = $this->createEntityChainBelongingToUser($creator, $updater); - $this->actingAs($updater); - app(UserRepo::class)->destroy($updater); - app(PageRepo::class)->update($entities['page'], ['html' => '

Hello there!

']); - - $this->checkEntitiesViewable($entities); - } - - private function checkEntitiesViewable($entities) - { - // Check pages and books are visible. - $this->asAdmin(); - $this->visit($entities['book']->getUrl())->seeStatusCode(200) - ->visit($entities['chapter']->getUrl())->seeStatusCode(200) - ->visit($entities['page']->getUrl())->seeStatusCode(200); - // Check revision listing shows no errors. - $this->visit($entities['page']->getUrl()) - ->click('Revisions')->seeStatusCode(200); - } - -} diff --git a/tests/Entity/PageTest.php b/tests/Entity/PageTest.php index 3fb847e42..e7118aae5 100644 --- a/tests/Entity/PageTest.php +++ b/tests/Entity/PageTest.php @@ -10,6 +10,33 @@ use Tests\TestCase; class PageTest extends TestCase { + public function test_create() + { + /** @var Chapter $chapter */ + $chapter = Chapter::query()->first(); + $page = factory(Page::class)->make([ + 'name' => 'My First Page', + ]); + + $resp = $this->asEditor()->get($chapter->getUrl()); + $resp->assertElementContains('a[href="' . $chapter->getUrl('/create-page') . '"]', 'New Page'); + + $resp = $this->get($chapter->getUrl('/create-page')); + /** @var Page $draftPage */ + $draftPage = Page::query() + ->where('draft', '=', true) + ->orderBy('created_at', 'desc') + ->first(); + $resp->assertRedirect($draftPage->getUrl()); + + $resp = $this->get($draftPage->getUrl()); + $resp->assertElementContains('form[action="' . $draftPage->getUrl() . '"][method="POST"]', 'Save Page'); + + $resp = $this->post($draftPage->getUrl(), $draftPage->only('name', 'html')); + $draftPage->refresh(); + $resp->assertRedirect($draftPage->getUrl()); + } + public function test_page_view_when_creator_is_deleted_but_owner_exists() { $page = Page::query()->first(); From 90c759e5caf489bd0524c988cb89b593c7259ff7 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 17 Sep 2021 22:35:28 +0100 Subject: [PATCH 5/9] Rewrote entity permissions tests to be non-browser-kit --- tests/Permissions/EntityPermissionsTest.php | 647 ++++++++++---------- 1 file changed, 321 insertions(+), 326 deletions(-) diff --git a/tests/Permissions/EntityPermissionsTest.php b/tests/Permissions/EntityPermissionsTest.php index 77c62fdb5..97d9074b7 100644 --- a/tests/Permissions/EntityPermissionsTest.php +++ b/tests/Permissions/EntityPermissionsTest.php @@ -9,9 +9,9 @@ use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Page; use Illuminate\Support\Str; -use Tests\BrowserKitTest; +use Tests\TestCase; -class EntityPermissionsTest extends BrowserKitTest +class EntityPermissionsTest extends TestCase { /** * @var User @@ -41,608 +41,600 @@ class EntityPermissionsTest extends BrowserKitTest public function test_bookshelf_view_restriction() { - $shelf = Bookshelf::first(); + /** @var Bookshelf $shelf */ + $shelf = Bookshelf::query()->first(); $this->actingAs($this->user) - ->visit($shelf->getUrl()) - ->seePageIs($shelf->getUrl()); + ->get($shelf->getUrl()) + ->assertStatus(200); $this->setRestrictionsForTestRoles($shelf, []); - $this->forceVisit($shelf->getUrl()) - ->see('Bookshelf not found'); + $this->followingRedirects()->get($shelf->getUrl()) + ->assertSee('Bookshelf not found'); $this->setRestrictionsForTestRoles($shelf, ['view']); - $this->visit($shelf->getUrl()) - ->see($shelf->name); + $this->get($shelf->getUrl()) + ->assertSee($shelf->name); } public function test_bookshelf_update_restriction() { - $shelf = Bookshelf::first(); + /** @var Bookshelf $shelf */ + $shelf = Bookshelf::query()->first(); $this->actingAs($this->user) - ->visit($shelf->getUrl('/edit')) - ->see('Edit Book'); + ->get($shelf->getUrl('/edit')) + ->assertSee('Edit Book'); $this->setRestrictionsForTestRoles($shelf, ['view', 'delete']); - $this->forceVisit($shelf->getUrl('/edit')) - ->see('You do not have permission')->seePageIs('/'); + $resp = $this->get($shelf->getUrl('/edit')) + ->assertRedirect('/'); + $this->followRedirects($resp)->assertSee('You do not have permission'); $this->setRestrictionsForTestRoles($shelf, ['view', 'update']); - $this->visit($shelf->getUrl('/edit')) - ->seePageIs($shelf->getUrl('/edit')); + $this->get($shelf->getUrl('/edit')) + ->assertOk(); } public function test_bookshelf_delete_restriction() { - $shelf = Book::first(); + /** @var Bookshelf $shelf */ + $shelf = Bookshelf::query()->first(); $this->actingAs($this->user) - ->visit($shelf->getUrl('/delete')) - ->see('Delete Book'); + ->get($shelf->getUrl('/delete')) + ->assertSee('Delete Book'); $this->setRestrictionsForTestRoles($shelf, ['view', 'update']); - $this->forceVisit($shelf->getUrl('/delete')) - ->see('You do not have permission')->seePageIs('/'); + $this->get($shelf->getUrl('/delete'))->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); $this->setRestrictionsForTestRoles($shelf, ['view', 'delete']); - $this->visit($shelf->getUrl('/delete')) - ->seePageIs($shelf->getUrl('/delete'))->see('Delete Book'); + $this->get($shelf->getUrl('/delete')) + ->assertOk() + ->assertSee('Delete Book'); } public function test_book_view_restriction() { - $book = Book::first(); + /** @var Book $book */ + $book = Book::query()->first(); $bookPage = $book->pages->first(); $bookChapter = $book->chapters->first(); $bookUrl = $book->getUrl(); $this->actingAs($this->user) - ->visit($bookUrl) - ->seePageIs($bookUrl); + ->get($bookUrl) + ->assertOk(); $this->setRestrictionsForTestRoles($book, []); - $this->forceVisit($bookUrl) - ->see('Book not found'); - $this->forceVisit($bookPage->getUrl()) - ->see('Page not found'); - $this->forceVisit($bookChapter->getUrl()) - ->see('Chapter not found'); + $this->followingRedirects()->get($bookUrl) + ->assertSee('Book not found'); + $this->followingRedirects()->get($bookPage->getUrl()) + ->assertSee('Page not found'); + $this->followingRedirects()->get($bookChapter->getUrl()) + ->assertSee('Chapter not found'); $this->setRestrictionsForTestRoles($book, ['view']); - $this->visit($bookUrl) - ->see($book->name); - $this->visit($bookPage->getUrl()) - ->see($bookPage->name); - $this->visit($bookChapter->getUrl()) - ->see($bookChapter->name); + $this->get($bookUrl) + ->assertSee($book->name); + $this->get($bookPage->getUrl()) + ->assertSee($bookPage->name); + $this->get($bookChapter->getUrl()) + ->assertSee($bookChapter->name); } public function test_book_create_restriction() { - $book = Book::first(); + /** @var Book $book */ + $book = Book::query()->first(); $bookUrl = $book->getUrl(); $this->actingAs($this->viewer) - ->visit($bookUrl) - ->dontSeeInElement('.actions', 'New Page') - ->dontSeeInElement('.actions', 'New Chapter'); + ->get($bookUrl) + ->assertElementNotContains('.actions', 'New Page') + ->assertElementNotContains('.actions', 'New Chapter'); $this->actingAs($this->user) - ->visit($bookUrl) - ->seeInElement('.actions', 'New Page') - ->seeInElement('.actions', 'New Chapter'); + ->get($bookUrl) + ->assertElementContains('.actions', 'New Page') + ->assertElementContains('.actions', 'New Chapter'); $this->setRestrictionsForTestRoles($book, ['view', 'delete', 'update']); - $this->forceVisit($bookUrl . '/create-chapter') - ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($bookUrl . '/create-page') - ->see('You do not have permission')->seePageIs('/'); - $this->visit($bookUrl)->dontSeeInElement('.actions', 'New Page') - ->dontSeeInElement('.actions', 'New Chapter'); + $this->get($bookUrl . '/create-chapter')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + + $this->get($bookUrl . '/create-page')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + + $this->get($bookUrl) + ->assertElementNotContains('.actions', 'New Page') + ->assertElementNotContains('.actions', 'New Chapter'); $this->setRestrictionsForTestRoles($book, ['view', 'create']); - $this->visit($bookUrl . '/create-chapter') - ->type('test chapter', 'name') - ->type('test description for chapter', 'description') - ->press('Save Chapter') - ->seePageIs($bookUrl . '/chapter/test-chapter'); - $this->visit($bookUrl . '/create-page') - ->type('test page', 'name') - ->type('test content', 'html') - ->press('Save Page') - ->seePageIs($bookUrl . '/page/test-page'); - $this->visit($bookUrl)->seeInElement('.actions', 'New Page') - ->seeInElement('.actions', 'New Chapter'); + $resp = $this->post($book->getUrl('/create-chapter'), [ + 'name' => 'test chapter', + 'description' => 'desc', + ]); + $resp->assertRedirect($book->getUrl('/chapter/test-chapter')); + + + $this->get($book->getUrl('/create-page')); + /** @var Page $page */ + $page = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first(); + $resp = $this->post($page->getUrl(), [ + 'name' => 'test page', + 'html' => 'test content', + ]); + $resp->assertRedirect($book->getUrl('/page/test-page')); + + $this->get($bookUrl) + ->assertElementContains('.actions', 'New Page') + ->assertElementContains('.actions', 'New Chapter'); } public function test_book_update_restriction() { - $book = Book::first(); + /** @var Book $book */ + $book = Book::query()->first(); $bookPage = $book->pages->first(); $bookChapter = $book->chapters->first(); $bookUrl = $book->getUrl(); $this->actingAs($this->user) - ->visit($bookUrl . '/edit') - ->see('Edit Book'); + ->get($bookUrl . '/edit') + ->assertSee('Edit Book'); $this->setRestrictionsForTestRoles($book, ['view', 'delete']); - $this->forceVisit($bookUrl . '/edit') - ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($bookPage->getUrl() . '/edit') - ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($bookChapter->getUrl() . '/edit') - ->see('You do not have permission')->seePageIs('/'); + $this->get($bookUrl . '/edit')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($bookPage->getUrl() . '/edit')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($bookChapter->getUrl() . '/edit')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); $this->setRestrictionsForTestRoles($book, ['view', 'update']); - $this->visit($bookUrl . '/edit') - ->seePageIs($bookUrl . '/edit'); - $this->visit($bookPage->getUrl() . '/edit') - ->seePageIs($bookPage->getUrl() . '/edit'); - $this->visit($bookChapter->getUrl() . '/edit') - ->see('Edit Chapter'); + $this->get($bookUrl . '/edit')->assertOk(); + $this->get($bookPage->getUrl() . '/edit')->assertOk(); + $this->get($bookChapter->getUrl() . '/edit')->assertSee('Edit Chapter'); } public function test_book_delete_restriction() { - $book = Book::first(); + /** @var Book $book */ + $book = Book::query()->first(); $bookPage = $book->pages->first(); $bookChapter = $book->chapters->first(); $bookUrl = $book->getUrl(); - $this->actingAs($this->user) - ->visit($bookUrl . '/delete') - ->see('Delete Book'); + $this->actingAs($this->user)->get($bookUrl . '/delete') + ->assertSee('Delete Book'); $this->setRestrictionsForTestRoles($book, ['view', 'update']); - $this->forceVisit($bookUrl . '/delete') - ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($bookPage->getUrl() . '/delete') - ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($bookChapter->getUrl() . '/delete') - ->see('You do not have permission')->seePageIs('/'); + $this->get($bookUrl . '/delete')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($bookPage->getUrl() . '/delete')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($bookChapter->getUrl() . '/delete')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); $this->setRestrictionsForTestRoles($book, ['view', 'delete']); - $this->visit($bookUrl . '/delete') - ->seePageIs($bookUrl . '/delete')->see('Delete Book'); - $this->visit($bookPage->getUrl() . '/delete') - ->seePageIs($bookPage->getUrl() . '/delete')->see('Delete Page'); - $this->visit($bookChapter->getUrl() . '/delete') - ->see('Delete Chapter'); + $this->get($bookUrl . '/delete')->assertOk()->assertSee('Delete Book'); + $this->get($bookPage->getUrl('/delete'))->assertOk()->assertSee('Delete Page'); + $this->get($bookChapter->getUrl('/delete'))->assertSee('Delete Chapter'); } public function test_chapter_view_restriction() { - $chapter = Chapter::first(); + /** @var Chapter $chapter */ + $chapter = Chapter::query()->first(); $chapterPage = $chapter->pages->first(); $chapterUrl = $chapter->getUrl(); - $this->actingAs($this->user) - ->visit($chapterUrl) - ->seePageIs($chapterUrl); + $this->actingAs($this->user)->get($chapterUrl)->assertOk(); $this->setRestrictionsForTestRoles($chapter, []); - $this->forceVisit($chapterUrl) - ->see('Chapter not found'); - $this->forceVisit($chapterPage->getUrl()) - ->see('Page not found'); + $this->followingRedirects()->get($chapterUrl)->assertSee('Chapter not found'); + $this->followingRedirects()->get($chapterPage->getUrl())->assertSee('Page not found'); $this->setRestrictionsForTestRoles($chapter, ['view']); - $this->visit($chapterUrl) - ->see($chapter->name); - $this->visit($chapterPage->getUrl()) - ->see($chapterPage->name); + $this->get($chapterUrl)->assertSee($chapter->name); + $this->get($chapterPage->getUrl())->assertSee($chapterPage->name); } public function test_chapter_create_restriction() { - $chapter = Chapter::first(); + /** @var Chapter $chapter */ + $chapter = Chapter::query()->first(); $chapterUrl = $chapter->getUrl(); $this->actingAs($this->user) - ->visit($chapterUrl) - ->seeInElement('.actions', 'New Page'); + ->get($chapterUrl) + ->assertElementContains('.actions', 'New Page'); $this->setRestrictionsForTestRoles($chapter, ['view', 'delete', 'update']); - $this->forceVisit($chapterUrl . '/create-page') - ->see('You do not have permission')->seePageIs('/'); - $this->visit($chapterUrl)->dontSeeInElement('.actions', 'New Page'); + $this->get($chapterUrl . '/create-page')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($chapterUrl)->assertElementNotContains('.actions', 'New Page'); $this->setRestrictionsForTestRoles($chapter, ['view', 'create']); - $this->visit($chapterUrl . '/create-page') - ->type('test page', 'name') - ->type('test content', 'html') - ->press('Save Page') - ->seePageIs($chapter->book->getUrl() . '/page/test-page'); + $this->get($chapter->getUrl('/create-page')); + /** @var Page $page */ + $page = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first(); + $resp = $this->post($page->getUrl(), [ + 'name' => 'test page', + 'html' => 'test content', + ]); + $resp->assertRedirect($chapter->book->getUrl('/page/test-page')); - $this->visit($chapterUrl)->seeInElement('.actions', 'New Page'); + $this->get($chapterUrl)->assertElementContains('.actions', 'New Page'); } public function test_chapter_update_restriction() { - $chapter = Chapter::first(); + /** @var Chapter $chapter */ + $chapter = Chapter::query()->first(); $chapterPage = $chapter->pages->first(); $chapterUrl = $chapter->getUrl(); - $this->actingAs($this->user) - ->visit($chapterUrl . '/edit') - ->see('Edit Chapter'); + $this->actingAs($this->user)->get($chapterUrl . '/edit') + ->assertSee('Edit Chapter'); $this->setRestrictionsForTestRoles($chapter, ['view', 'delete']); - $this->forceVisit($chapterUrl . '/edit') - ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($chapterPage->getUrl() . '/edit') - ->see('You do not have permission')->seePageIs('/'); + $this->get($chapterUrl . '/edit')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($chapterPage->getUrl() . '/edit')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); $this->setRestrictionsForTestRoles($chapter, ['view', 'update']); - $this->visit($chapterUrl . '/edit') - ->seePageIs($chapterUrl . '/edit')->see('Edit Chapter'); - $this->visit($chapterPage->getUrl() . '/edit') - ->seePageIs($chapterPage->getUrl() . '/edit'); + $this->get($chapterUrl . '/edit')->assertOk()->assertSee('Edit Chapter'); + $this->get($chapterPage->getUrl() . '/edit')->assertOk(); } public function test_chapter_delete_restriction() { - $chapter = Chapter::first(); + /** @var Chapter $chapter */ + $chapter = Chapter::query()->first(); $chapterPage = $chapter->pages->first(); $chapterUrl = $chapter->getUrl(); $this->actingAs($this->user) - ->visit($chapterUrl . '/delete') - ->see('Delete Chapter'); + ->get($chapterUrl . '/delete') + ->assertSee('Delete Chapter'); $this->setRestrictionsForTestRoles($chapter, ['view', 'update']); - $this->forceVisit($chapterUrl . '/delete') - ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($chapterPage->getUrl() . '/delete') - ->see('You do not have permission')->seePageIs('/'); + $this->get($chapterUrl . '/delete')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($chapterPage->getUrl() . '/delete')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); $this->setRestrictionsForTestRoles($chapter, ['view', 'delete']); - $this->visit($chapterUrl . '/delete') - ->seePageIs($chapterUrl . '/delete')->see('Delete Chapter'); - $this->visit($chapterPage->getUrl() . '/delete') - ->seePageIs($chapterPage->getUrl() . '/delete')->see('Delete Page'); + $this->get($chapterUrl . '/delete')->assertOk()->assertSee('Delete Chapter'); + $this->get($chapterPage->getUrl() . '/delete')->assertOk()->assertSee('Delete Page'); } public function test_page_view_restriction() { - $page = Page::first(); + /** @var Page $page */ + $page = Page::query()->first(); $pageUrl = $page->getUrl(); - $this->actingAs($this->user) - ->visit($pageUrl) - ->seePageIs($pageUrl); + $this->actingAs($this->user)->get($pageUrl)->assertOk(); $this->setRestrictionsForTestRoles($page, ['update', 'delete']); - $this->forceVisit($pageUrl) - ->see('Page not found'); + $this->get($pageUrl)->assertSee('Page not found'); $this->setRestrictionsForTestRoles($page, ['view']); - $this->visit($pageUrl) - ->see($page->name); + $this->get($pageUrl)->assertSee($page->name); } public function test_page_update_restriction() { - $page = Chapter::first(); + /** @var Page $page */ + $page = Page::query()->first(); $pageUrl = $page->getUrl(); $this->actingAs($this->user) - ->visit($pageUrl . '/edit') - ->seeInField('name', $page->name); + ->get($pageUrl . '/edit') + ->assertElementExists('input[name="name"][value="' . $page->name . '"]'); $this->setRestrictionsForTestRoles($page, ['view', 'delete']); - $this->forceVisit($pageUrl . '/edit') - ->see('You do not have permission')->seePageIs('/'); + $this->get($pageUrl . '/edit')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); $this->setRestrictionsForTestRoles($page, ['view', 'update']); - $this->visit($pageUrl . '/edit') - ->seePageIs($pageUrl . '/edit')->seeInField('name', $page->name); + $this->get($pageUrl . '/edit') + ->assertOk() + ->assertElementExists('input[name="name"][value="' . $page->name . '"]'); } public function test_page_delete_restriction() { - $page = Page::first(); + /** @var Page $page */ + $page = Page::query()->first(); $pageUrl = $page->getUrl(); $this->actingAs($this->user) - ->visit($pageUrl . '/delete') - ->see('Delete Page'); + ->get($pageUrl . '/delete') + ->assertSee('Delete Page'); $this->setRestrictionsForTestRoles($page, ['view', 'update']); - $this->forceVisit($pageUrl . '/delete') - ->see('You do not have permission')->seePageIs('/'); + $this->get($pageUrl . '/delete')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); $this->setRestrictionsForTestRoles($page, ['view', 'delete']); - $this->visit($pageUrl . '/delete') - ->seePageIs($pageUrl . '/delete')->see('Delete Page'); + $this->get($pageUrl . '/delete')->assertOk()->assertSee('Delete Page'); + } + + protected function entityRestrictionFormTest(string $model, string $title, string $permission, string $roleId) + { + /** @var Entity $modelInstance */ + $modelInstance = $model::query()->first(); + $this->asAdmin()->get($modelInstance->getUrl('/permissions')) + ->assertSee($title); + + $this->put($modelInstance->getUrl('/permissions'), [ + 'restricted' => 'true', + 'restrictions' => [ + $roleId => [ + $permission => 'true' + ] + ], + ]); + + $this->assertDatabaseHas($modelInstance->getTable(), ['id' => $modelInstance->id, 'restricted' => true]); + $this->assertDatabaseHas('entity_permissions', [ + 'restrictable_id' => $modelInstance->id, + 'restrictable_type' => $modelInstance->getMorphClass(), + 'role_id' => $roleId, + 'action' => $permission, + ]); } public function test_bookshelf_restriction_form() { - $shelf = Bookshelf::first(); - $this->asAdmin()->visit($shelf->getUrl('/permissions')) - ->see('Bookshelf Permissions') - ->check('restricted') - ->check('restrictions[2][view]') - ->press('Save Permissions') - ->seeInDatabase('bookshelves', ['id' => $shelf->id, 'restricted' => true]) - ->seeInDatabase('entity_permissions', [ - 'restrictable_id' => $shelf->id, - 'restrictable_type' => Bookshelf::newModelInstance()->getMorphClass(), - 'role_id' => '2', - 'action' => 'view', - ]); + $this->entityRestrictionFormTest(Bookshelf::class, 'Bookshelf Permissions', 'view', '2'); } public function test_book_restriction_form() { - $book = Book::first(); - $this->asAdmin()->visit($book->getUrl() . '/permissions') - ->see('Book Permissions') - ->check('restricted') - ->check('restrictions[2][view]') - ->press('Save Permissions') - ->seeInDatabase('books', ['id' => $book->id, 'restricted' => true]) - ->seeInDatabase('entity_permissions', [ - 'restrictable_id' => $book->id, - 'restrictable_type' => Book::newModelInstance()->getMorphClass(), - 'role_id' => '2', - 'action' => 'view', - ]); + $this->entityRestrictionFormTest(Book::class, 'Book Permissions', 'view', '2'); } public function test_chapter_restriction_form() { - $chapter = Chapter::first(); - $this->asAdmin()->visit($chapter->getUrl() . '/permissions') - ->see('Chapter Permissions') - ->check('restricted') - ->check('restrictions[2][update]') - ->press('Save Permissions') - ->seeInDatabase('chapters', ['id' => $chapter->id, 'restricted' => true]) - ->seeInDatabase('entity_permissions', [ - 'restrictable_id' => $chapter->id, - 'restrictable_type' => Chapter::newModelInstance()->getMorphClass(), - 'role_id' => '2', - 'action' => 'update', - ]); + $this->entityRestrictionFormTest(Chapter::class, 'Chapter Permissions', 'update', '2'); } public function test_page_restriction_form() { - $page = Page::first(); - $this->asAdmin()->visit($page->getUrl() . '/permissions') - ->see('Page Permissions') - ->check('restricted') - ->check('restrictions[2][delete]') - ->press('Save Permissions') - ->seeInDatabase('pages', ['id' => $page->id, 'restricted' => true]) - ->seeInDatabase('entity_permissions', [ - 'restrictable_id' => $page->id, - 'restrictable_type' => Page::newModelInstance()->getMorphClass(), - 'role_id' => '2', - 'action' => 'delete', - ]); + $this->entityRestrictionFormTest(Page::class, 'Page Permissions', 'delete', '2'); } public function test_restricted_pages_not_visible_in_book_navigation_on_pages() { - $chapter = Chapter::first(); + /** @var Chapter $chapter */ + $chapter = Chapter::query()->first(); $page = $chapter->pages->first(); $page2 = $chapter->pages[2]; $this->setRestrictionsForTestRoles($page, []); $this->actingAs($this->user) - ->visit($page2->getUrl()) - ->dontSeeInElement('.sidebar-page-list', $page->name); + ->get($page2->getUrl()) + ->assertElementNotContains('.sidebar-page-list', $page->name); } public function test_restricted_pages_not_visible_in_book_navigation_on_chapters() { - $chapter = Chapter::first(); + /** @var Chapter $chapter */ + $chapter = Chapter::query()->first(); $page = $chapter->pages->first(); $this->setRestrictionsForTestRoles($page, []); $this->actingAs($this->user) - ->visit($chapter->getUrl()) - ->dontSeeInElement('.sidebar-page-list', $page->name); + ->get($chapter->getUrl()) + ->assertElementNotContains('.sidebar-page-list', $page->name); } public function test_restricted_pages_not_visible_on_chapter_pages() { - $chapter = Chapter::first(); + /** @var Chapter $chapter */ + $chapter = Chapter::query()->first(); $page = $chapter->pages->first(); $this->setRestrictionsForTestRoles($page, []); $this->actingAs($this->user) - ->visit($chapter->getUrl()) - ->dontSee($page->name); + ->get($chapter->getUrl()) + ->assertDontSee($page->name); } public function test_restricted_chapter_pages_not_visible_on_book_page() { + /** @var Chapter $chapter */ $chapter = Chapter::query()->first(); $this->actingAs($this->user) - ->visit($chapter->book->getUrl()) - ->see($chapter->pages->first()->name); + ->get($chapter->book->getUrl()) + ->assertSee($chapter->pages->first()->name); foreach ($chapter->pages as $page) { $this->setRestrictionsForTestRoles($page, []); } $this->actingAs($this->user) - ->visit($chapter->book->getUrl()) - ->dontSee($chapter->pages->first()->name); + ->get($chapter->book->getUrl()) + ->assertDontSee($chapter->pages->first()->name); } public function test_bookshelf_update_restriction_override() { - $shelf = Bookshelf::first(); + /** @var Bookshelf $shelf */ + $shelf = Bookshelf::query()->first(); $this->actingAs($this->viewer) - ->visit($shelf->getUrl('/edit')) - ->dontSee('Edit Book'); + ->get($shelf->getUrl('/edit')) + ->assertDontSee('Edit Book'); $this->setRestrictionsForTestRoles($shelf, ['view', 'delete']); - $this->forceVisit($shelf->getUrl('/edit')) - ->see('You do not have permission')->seePageIs('/'); + $this->get($shelf->getUrl('/edit'))->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); $this->setRestrictionsForTestRoles($shelf, ['view', 'update']); - $this->visit($shelf->getUrl('/edit')) - ->seePageIs($shelf->getUrl('/edit')); + $this->get($shelf->getUrl('/edit'))->assertOk(); } public function test_bookshelf_delete_restriction_override() { - $shelf = Bookshelf::first(); + /** @var Bookshelf $shelf */ + $shelf = Bookshelf::query()->first(); $this->actingAs($this->viewer) - ->visit($shelf->getUrl('/delete')) - ->dontSee('Delete Book'); + ->get($shelf->getUrl('/delete')) + ->assertDontSee('Delete Book'); $this->setRestrictionsForTestRoles($shelf, ['view', 'update']); - $this->forceVisit($shelf->getUrl('/delete')) - ->see('You do not have permission')->seePageIs('/'); + $this->get($shelf->getUrl('/delete'))->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); $this->setRestrictionsForTestRoles($shelf, ['view', 'delete']); - $this->visit($shelf->getUrl('/delete')) - ->seePageIs($shelf->getUrl('/delete'))->see('Delete Book'); + $this->get($shelf->getUrl('/delete'))->assertOk()->assertSee('Delete Book'); } public function test_book_create_restriction_override() { - $book = Book::first(); + /** @var Book $book */ + $book = Book::query()->first(); $bookUrl = $book->getUrl(); $this->actingAs($this->viewer) - ->visit($bookUrl) - ->dontSeeInElement('.actions', 'New Page') - ->dontSeeInElement('.actions', 'New Chapter'); + ->get($bookUrl) + ->assertElementNotContains('.actions', 'New Page') + ->assertElementNotContains('.actions', 'New Chapter'); $this->setRestrictionsForTestRoles($book, ['view', 'delete', 'update']); - $this->forceVisit($bookUrl . '/create-chapter') - ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($bookUrl . '/create-page') - ->see('You do not have permission')->seePageIs('/'); - $this->visit($bookUrl)->dontSeeInElement('.actions', 'New Page') - ->dontSeeInElement('.actions', 'New Chapter'); + $this->get($bookUrl . '/create-chapter')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($bookUrl . '/create-page')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($bookUrl)->assertElementNotContains('.actions', 'New Page') + ->assertElementNotContains('.actions', 'New Chapter'); $this->setRestrictionsForTestRoles($book, ['view', 'create']); - $this->visit($bookUrl . '/create-chapter') - ->type('test chapter', 'name') - ->type('test description for chapter', 'description') - ->press('Save Chapter') - ->seePageIs($bookUrl . '/chapter/test-chapter'); - $this->visit($bookUrl . '/create-page') - ->type('test page', 'name') - ->type('test content', 'html') - ->press('Save Page') - ->seePageIs($bookUrl . '/page/test-page'); - $this->visit($bookUrl)->seeInElement('.actions', 'New Page') - ->seeInElement('.actions', 'New Chapter'); + $resp = $this->post($book->getUrl('/create-chapter'), [ + 'name' => 'test chapter', + 'description' => 'test desc', + ]); + $resp->assertRedirect($book->getUrl('/chapter/test-chapter')); + + + $this->get($book->getUrl('/create-page')); + /** @var Page $page */ + $page = Page::query()->where('draft', '=', true)->orderByDesc('id')->first(); + $resp = $this->post($page->getUrl(), [ + 'name' => 'test page', + 'html' => 'test desc', + ]); + $resp->assertRedirect($book->getUrl('/page/test-page')); + + $this->get($bookUrl) + ->assertElementContains('.actions', 'New Page') + ->assertElementContains('.actions', 'New Chapter'); } public function test_book_update_restriction_override() { - $book = Book::first(); + /** @var Book $book */ + $book = Book::query()->first(); $bookPage = $book->pages->first(); $bookChapter = $book->chapters->first(); $bookUrl = $book->getUrl(); - $this->actingAs($this->viewer) - ->visit($bookUrl . '/edit') - ->dontSee('Edit Book'); + $this->actingAs($this->viewer)->get($bookUrl . '/edit') + ->assertDontSee('Edit Book'); $this->setRestrictionsForTestRoles($book, ['view', 'delete']); - $this->forceVisit($bookUrl . '/edit') - ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($bookPage->getUrl() . '/edit') - ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($bookChapter->getUrl() . '/edit') - ->see('You do not have permission')->seePageIs('/'); + $this->get($bookUrl . '/edit')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($bookPage->getUrl() . '/edit')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($bookChapter->getUrl() . '/edit')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); $this->setRestrictionsForTestRoles($book, ['view', 'update']); - $this->visit($bookUrl . '/edit') - ->seePageIs($bookUrl . '/edit'); - $this->visit($bookPage->getUrl() . '/edit') - ->seePageIs($bookPage->getUrl() . '/edit'); - $this->visit($bookChapter->getUrl() . '/edit') - ->see('Edit Chapter'); + $this->get($bookUrl . '/edit')->assertOk(); + $this->get($bookPage->getUrl() . '/edit')->assertOk(); + $this->get($bookChapter->getUrl() . '/edit')->assertSee('Edit Chapter'); } public function test_book_delete_restriction_override() { - $book = Book::first(); + /** @var Book $book */ + $book = Book::query()->first(); $bookPage = $book->pages->first(); $bookChapter = $book->chapters->first(); $bookUrl = $book->getUrl(); $this->actingAs($this->viewer) - ->visit($bookUrl . '/delete') - ->dontSee('Delete Book'); + ->get($bookUrl . '/delete') + ->assertDontSee('Delete Book'); $this->setRestrictionsForTestRoles($book, ['view', 'update']); - $this->forceVisit($bookUrl . '/delete') - ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($bookPage->getUrl() . '/delete') - ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($bookChapter->getUrl() . '/delete') - ->see('You do not have permission')->seePageIs('/'); + $this->get($bookUrl . '/delete')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($bookPage->getUrl() . '/delete')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); + $this->get($bookChapter->getUrl() . '/delete')->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); $this->setRestrictionsForTestRoles($book, ['view', 'delete']); - $this->visit($bookUrl . '/delete') - ->seePageIs($bookUrl . '/delete')->see('Delete Book'); - $this->visit($bookPage->getUrl() . '/delete') - ->seePageIs($bookPage->getUrl() . '/delete')->see('Delete Page'); - $this->visit($bookChapter->getUrl() . '/delete') - ->see('Delete Chapter'); + $this->get($bookUrl . '/delete')->assertOk()->assertSee('Delete Book'); + $this->get($bookPage->getUrl() . '/delete')->assertOk()->assertSee('Delete Page'); + $this->get($bookChapter->getUrl() . '/delete')->assertSee('Delete Chapter'); } public function test_page_visible_if_has_permissions_when_book_not_visible() { - $book = Book::first(); + /** @var Book $book */ + $book = Book::query()->first(); $bookChapter = $book->chapters->first(); $bookPage = $bookChapter->pages->first(); @@ -655,34 +647,37 @@ class EntityPermissionsTest extends BrowserKitTest $this->setRestrictionsForTestRoles($bookPage, ['view']); $this->actingAs($this->viewer); - $this->get($bookPage->getUrl()); - $this->assertResponseOk(); - $this->see($bookPage->name); - $this->dontSee(substr($book->name, 0, 15)); - $this->dontSee(substr($bookChapter->name, 0, 15)); + $resp = $this->get($bookPage->getUrl()); + $resp->assertOk(); + $resp->assertSee($bookPage->name); + $resp->assertDontSee(substr($book->name, 0, 15)); + $resp->assertDontSee(substr($bookChapter->name, 0, 15)); } public function test_book_sort_view_permission() { - $firstBook = Book::first(); - $secondBook = Book::find(2); + /** @var Book $firstBook */ + $firstBook = Book::query()->first(); + /** @var Book $secondBook */ + $secondBook = Book::query()->find(2); $this->setRestrictionsForTestRoles($firstBook, ['view', 'update']); $this->setRestrictionsForTestRoles($secondBook, ['view']); // Test sort page visibility - $this->actingAs($this->user)->visit($secondBook->getUrl() . '/sort') - ->see('You do not have permission') - ->seePageIs('/'); + $this->actingAs($this->user)->get($secondBook->getUrl('/sort'))->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); // Check sort page on first book - $this->actingAs($this->user)->visit($firstBook->getUrl() . '/sort'); + $this->actingAs($this->user)->get($firstBook->getUrl('/sort')); } public function test_book_sort_permission() { - $firstBook = Book::first(); - $secondBook = Book::find(2); + /** @var Book $firstBook */ + $firstBook = Book::query()->first(); + /** @var Book $secondBook */ + $secondBook = Book::query()->find(2); $this->setRestrictionsForTestRoles($firstBook, ['view', 'update']); $this->setRestrictionsForTestRoles($secondBook, ['view']); @@ -703,9 +698,8 @@ class EntityPermissionsTest extends BrowserKitTest // Move chapter from first book to a second book $this->actingAs($this->user)->put($firstBook->getUrl() . '/sort', ['sort-tree' => json_encode($reqData)]) - ->followRedirects() - ->see('You do not have permission') - ->seePageIs('/'); + ->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); $reqData = [ [ @@ -719,30 +713,31 @@ class EntityPermissionsTest extends BrowserKitTest // Move chapter from second book to first book $this->actingAs($this->user)->put($firstBook->getUrl() . '/sort', ['sort-tree' => json_encode($reqData)]) - ->followRedirects() - ->see('You do not have permission') - ->seePageIs('/'); + ->assertRedirect('/'); + $this->get('/')->assertSee('You do not have permission'); } public function test_can_create_page_if_chapter_has_permissions_when_book_not_visible() { - $book = Book::first(); + /** @var Book $book */ + $book = Book::query()->first(); $this->setRestrictionsForTestRoles($book, []); $bookChapter = $book->chapters->first(); $this->setRestrictionsForTestRoles($bookChapter, ['view']); - $this->actingAs($this->user)->visit($bookChapter->getUrl()) - ->dontSee('New Page'); + $this->actingAs($this->user)->get($bookChapter->getUrl()) + ->assertDontSee('New Page'); $this->setRestrictionsForTestRoles($bookChapter, ['view', 'create']); - $this->actingAs($this->user)->visit($bookChapter->getUrl()) - ->click('New Page') - ->seeStatusCode(200) - ->type('test page', 'name') - ->type('test content', 'html') - ->press('Save Page') - ->seePageIs($book->getUrl('/page/test-page')) - ->seeStatusCode(200); + + $this->get($bookChapter->getUrl('/create-page')); + /** @var Page $page */ + $page = Page::query()->where('draft', '=', true)->orderByDesc('id')->first(); + $resp = $this->post($page->getUrl(), [ + 'name' => 'test page', + 'html' => 'test content', + ]); + $resp->assertRedirect($book->getUrl('/page/test-page')); } } From a4d9bca9e1dd90615bf9ad5c3ad1811614440423 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 17 Sep 2021 23:44:54 +0100 Subject: [PATCH 6/9] Converted AuthTest away from BrowserKit Moved some user managment tests out to more relevant classess along the way. Found some tweaks to make for email confirmation routing as part of this. --- app/Auth/Role.php | 1 + .../StoppedAuthenticationException.php | 2 +- tests/Auth/AuthTest.php | 407 +++++++----------- tests/SharedTestHelpers.php | 2 +- tests/User/UserManagementTest.php | 102 +++++ 5 files changed, 249 insertions(+), 265 deletions(-) diff --git a/app/Auth/Role.php b/app/Auth/Role.php index dcd960948..2918fce52 100644 --- a/app/Auth/Role.php +++ b/app/Auth/Role.php @@ -19,6 +19,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; * @property string $external_auth_id * @property string $system_name * @property bool $mfa_enforced + * @property Collection $users */ class Role extends Model implements Loggable { diff --git a/app/Exceptions/StoppedAuthenticationException.php b/app/Exceptions/StoppedAuthenticationException.php index ef7f24017..d10a6da5e 100644 --- a/app/Exceptions/StoppedAuthenticationException.php +++ b/app/Exceptions/StoppedAuthenticationException.php @@ -55,7 +55,7 @@ class StoppedAuthenticationException extends \Exception implements Responsable ], 401); } - if (session()->get('sent-email-confirmation') === true) { + if (session()->pull('sent-email-confirmation') === true) { return redirect('/register/confirm'); } diff --git a/tests/Auth/AuthTest.php b/tests/Auth/AuthTest.php index 2380aad7b..acf67cb9a 100644 --- a/tests/Auth/AuthTest.php +++ b/tests/Auth/AuthTest.php @@ -3,49 +3,41 @@ namespace Tests\Auth; use BookStack\Auth\Access\Mfa\MfaSession; -use BookStack\Auth\Role; use BookStack\Auth\User; use BookStack\Entities\Models\Page; use BookStack\Notifications\ConfirmEmail; use BookStack\Notifications\ResetPassword; -use BookStack\Settings\SettingService; use DB; -use Hash; use Illuminate\Support\Facades\Notification; -use Illuminate\Support\Str; -use Tests\BrowserKitTest; +use Tests\TestCase; +use Tests\TestResponse; -class AuthTest extends BrowserKitTest +class AuthTest extends TestCase { public function test_auth_working() { - $this->visit('/') - ->seePageIs('/login'); + $this->get('/')->assertRedirect('/login'); } public function test_login() { - $this->login('admin@admin.com', 'password') - ->seePageIs('/'); + $this->login('admin@admin.com', 'password')->assertRedirect('/'); } public function test_public_viewing() { - $settings = app(SettingService::class); - $settings->put('app-public', 'true'); - $this->visit('/') - ->seePageIs('/') - ->see('Log In'); + $this->setSettings(['app-public' => 'true']); + $this->get('/') + ->assertOk() + ->assertSee('Log in'); } public function test_registration_showing() { // Ensure registration form is showing $this->setSettings(['registration-enabled' => 'true']); - $this->visit('/login') - ->see('Sign up') - ->click('Sign up') - ->seePageIs('/register'); + $this->get('/login') + ->assertElementContains('a[href="' . url('/register') . '"]', 'Sign up'); } public function test_normal_registration() @@ -55,15 +47,17 @@ class AuthTest extends BrowserKitTest $user = factory(User::class)->make(); // Test form and ensure user is created - $this->visit('/register') - ->see('Sign Up') - ->type($user->name, '#name') - ->type($user->email, '#email') - ->type($user->password, '#password') - ->press('Create Account') - ->seePageIs('/') - ->see($user->name) - ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email]); + $this->get('/register') + ->assertSee('Sign Up') + ->assertElementContains('form[action="' . url('/register') . '"]', 'Create Account'); + + $resp = $this->post('/register', $user->only('password', 'name', 'email')); + $resp->assertRedirect('/'); + + $resp = $this->get('/'); + $resp->assertOk(); + $resp->assertSee($user->name); + $this->assertDatabaseHas('users', ['name' => $user->name, 'email' => $user->email]); } public function test_empty_registration_redirects_back_with_errors() @@ -72,36 +66,33 @@ class AuthTest extends BrowserKitTest $this->setSettings(['registration-enabled' => 'true']); // Test form and ensure user is created - $this->visit('/register') - ->press('Create Account') - ->see('The name field is required') - ->seePageIs('/register'); + $this->get('/register'); + $this->post('/register', [])->assertRedirect('/register'); + $this->get('/register')->assertSee('The name field is required'); } public function test_registration_validation() { $this->setSettings(['registration-enabled' => 'true']); - $this->visit('/register') - ->type('1', '#name') - ->type('1', '#email') - ->type('1', '#password') - ->press('Create Account') - ->see('The name must be at least 2 characters.') - ->see('The email must be a valid email address.') - ->see('The password must be at least 8 characters.') - ->seePageIs('/register'); + $this->get('/register'); + $resp = $this->followingRedirects()->post('/register', [ + 'name' => '1', + 'email' => '1', + 'password' => '1', + ]); + $resp->assertSee('The name must be at least 2 characters.'); + $resp->assertSee('The email must be a valid email address.'); + $resp->assertSee('The password must be at least 8 characters.'); } public function test_sign_up_link_on_login() { - $this->visit('/login') - ->dontSee('Sign up'); + $this->get('/login')->assertDontSee('Sign up'); $this->setSettings(['registration-enabled' => 'true']); - $this->visit('/login') - ->see('Sign up'); + $this->get('/login')->assertSee('Sign up'); } public function test_confirmed_registration() @@ -114,27 +105,24 @@ class AuthTest extends BrowserKitTest $user = factory(User::class)->make(); // Go through registration process - $this->visit('/register') - ->see('Sign Up') - ->type($user->name, '#name') - ->type($user->email, '#email') - ->type($user->password, '#password') - ->press('Create Account') - ->seePageIs('/register/confirm') - ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]); + $resp = $this->post('/register', $user->only('name', 'email', 'password')); + $resp->assertRedirect('/register/confirm'); + $this->assertDatabaseHas('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]); // Ensure notification sent - $dbUser = User::where('email', '=', $user->email)->first(); + /** @var User $dbUser */ + $dbUser = User::query()->where('email', '=', $user->email)->first(); Notification::assertSentTo($dbUser, ConfirmEmail::class); // Test access and resend confirmation email - $this->login($user->email, $user->password) - ->seePageIs('/register/confirm/awaiting') - ->see('Resend') - ->visit('/books') - ->seePageIs('/login') - ->visit('/register/confirm/awaiting') - ->press('Resend Confirmation Email'); + $resp = $this->login($user->email, $user->password); + $resp->assertRedirect('/register/confirm/awaiting'); + + $resp = $this->get('/register/confirm/awaiting'); + $resp->assertElementContains('form[action="' . url('/register/confirm/resend') . '"]', 'Resend'); + + $this->get('/books')->assertRedirect('/login'); + $this->post('/register/confirm/resend', $user->only('email')); // Get confirmation and confirm notification matches $emailConfirmation = DB::table('email_confirmations')->where('user_id', '=', $dbUser->id)->first(); @@ -143,188 +131,69 @@ class AuthTest extends BrowserKitTest }); // Check confirmation email confirmation activation. - $this->visit('/register/confirm/' . $emailConfirmation->token) - ->seePageIs('/') - ->see($user->name) - ->notSeeInDatabase('email_confirmations', ['token' => $emailConfirmation->token]) - ->seeInDatabase('users', ['name' => $dbUser->name, 'email' => $dbUser->email, 'email_confirmed' => true]); + $this->get('/register/confirm/' . $emailConfirmation->token)->assertRedirect('/'); + $this->get('/')->assertSee($user->name); + $this->assertDatabaseMissing('email_confirmations', ['token' => $emailConfirmation->token]); + $this->assertDatabaseHas('users', ['name' => $dbUser->name, 'email' => $dbUser->email, 'email_confirmed' => true]); } public function test_restricted_registration() { $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true', 'registration-restrict' => 'example.com']); $user = factory(User::class)->make(); + // Go through registration process - $this->visit('/register') - ->type($user->name, '#name') - ->type($user->email, '#email') - ->type($user->password, '#password') - ->press('Create Account') - ->seePageIs('/register') - ->dontSeeInDatabase('users', ['email' => $user->email]) - ->see('That email domain does not have access to this application'); + $this->post('/register', $user->only('name', 'email', 'password')) + ->assertRedirect('/register'); + $resp = $this->get('/register'); + $resp->assertSee('That email domain does not have access to this application'); + $this->assertDatabaseMissing('users', $user->only('email')); $user->email = 'barry@example.com'; - $this->visit('/register') - ->type($user->name, '#name') - ->type($user->email, '#email') - ->type($user->password, '#password') - ->press('Create Account') - ->seePageIs('/register/confirm') - ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]); + $this->post('/register', $user->only('name', 'email', 'password')) + ->assertRedirect('/register/confirm'); + $this->assertDatabaseHas('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]); $this->assertNull(auth()->user()); - $this->visit('/')->seePageIs('/login') - ->type($user->email, '#email') - ->type($user->password, '#password') - ->press('Log In') - ->seePageIs('/register/confirm/awaiting') - ->seeText('Email Address Not Confirmed'); + $this->get('/')->assertRedirect('/login'); + $resp = $this->followingRedirects()->post('/login', $user->only('email', 'password')); + $resp->assertSee('Email Address Not Confirmed'); + $this->assertNull(auth()->user()); } public function test_restricted_registration_with_confirmation_disabled() { $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'false', 'registration-restrict' => 'example.com']); $user = factory(User::class)->make(); + // Go through registration process - $this->visit('/register') - ->type($user->name, '#name') - ->type($user->email, '#email') - ->type($user->password, '#password') - ->press('Create Account') - ->seePageIs('/register') - ->dontSeeInDatabase('users', ['email' => $user->email]) - ->see('That email domain does not have access to this application'); + $this->post('/register', $user->only('name', 'email', 'password')) + ->assertRedirect('/register'); + $this->assertDatabaseMissing('users', $user->only('email')); + $this->get('/register')->assertSee('That email domain does not have access to this application'); $user->email = 'barry@example.com'; - $this->visit('/register') - ->type($user->name, '#name') - ->type($user->email, '#email') - ->type($user->password, '#password') - ->press('Create Account') - ->seePageIs('/register/confirm') - ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]); + $this->post('/register', $user->only('name', 'email', 'password')) + ->assertRedirect('/register/confirm'); + $this->assertDatabaseHas('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]); $this->assertNull(auth()->user()); - $this->visit('/')->seePageIs('/login') - ->type($user->email, '#email') - ->type($user->password, '#password') - ->press('Log In') - ->seePageIs('/register/confirm/awaiting') - ->seeText('Email Address Not Confirmed'); - } - - public function test_user_creation() - { - /** @var User $user */ - $user = factory(User::class)->make(); - $adminRole = Role::getRole('admin'); - - $this->asAdmin() - ->visit('/settings/users') - ->click('Add New User') - ->type($user->name, '#name') - ->type($user->email, '#email') - ->check("roles[{$adminRole->id}]") - ->type($user->password, '#password') - ->type($user->password, '#password-confirm') - ->press('Save') - ->seePageIs('/settings/users') - ->seeInDatabase('users', $user->only(['name', 'email'])) - ->see($user->name); - - $user->refresh(); - $this->assertStringStartsWith(Str::slug($user->name), $user->slug); - } - - public function test_user_updating() - { - $user = $this->getNormalUser(); - $password = $user->password; - $this->asAdmin() - ->visit('/settings/users') - ->click($user->name) - ->seePageIs('/settings/users/' . $user->id) - ->see($user->email) - ->type('Barry Scott', '#name') - ->press('Save') - ->seePageIs('/settings/users') - ->seeInDatabase('users', ['id' => $user->id, 'name' => 'Barry Scott', 'password' => $password]) - ->notSeeInDatabase('users', ['name' => $user->name]); - - $user->refresh(); - $this->assertStringStartsWith(Str::slug($user->name), $user->slug); - } - - public function test_user_password_update() - { - $user = $this->getNormalUser(); - $userProfilePage = '/settings/users/' . $user->id; - $this->asAdmin() - ->visit($userProfilePage) - ->type('newpassword', '#password') - ->press('Save') - ->seePageIs($userProfilePage) - ->see('Password confirmation required') - - ->type('newpassword', '#password') - ->type('newpassword', '#password-confirm') - ->press('Save') - ->seePageIs('/settings/users'); - - $userPassword = User::find($user->id)->password; - $this->assertTrue(Hash::check('newpassword', $userPassword)); - } - - public function test_user_deletion() - { - $userDetails = factory(User::class)->make(); - $user = $this->getEditor($userDetails->toArray()); - - $this->asAdmin() - ->visit('/settings/users/' . $user->id) - ->click('Delete User') - ->see($user->name) - ->press('Confirm') - ->seePageIs('/settings/users') - ->notSeeInDatabase('users', ['name' => $user->name]); - } - - public function test_user_cannot_be_deleted_if_last_admin() - { - $adminRole = Role::getRole('admin'); - - // Delete all but one admin user if there are more than one - $adminUsers = $adminRole->users; - if (count($adminUsers) > 1) { - foreach ($adminUsers->splice(1) as $user) { - $user->delete(); - } - } - - // Ensure we currently only have 1 admin user - $this->assertEquals(1, $adminRole->users()->count()); - $user = $adminRole->users->first(); - - $this->asAdmin()->visit('/settings/users/' . $user->id) - ->click('Delete User') - ->press('Confirm') - ->seePageIs('/settings/users/' . $user->id) - ->see('You cannot delete the only admin'); + $this->get('/')->assertRedirect('/login'); + $resp = $this->post('/login', $user->only('email', 'password')); + $resp->assertRedirect('/register/confirm/awaiting'); + $this->get('/register/confirm/awaiting')->assertSee('Email Address Not Confirmed'); + $this->assertNull(auth()->user()); } public function test_logout() { - $this->asAdmin() - ->visit('/') - ->seePageIs('/') - ->visit('/logout') - ->visit('/') - ->seePageIs('/login'); + $this->asAdmin()->get('/')->assertOk(); + $this->get('/logout')->assertRedirect('/'); + $this->get('/')->assertRedirect('/login'); } public function test_mfa_session_cleared_on_logout() @@ -335,7 +204,7 @@ class AuthTest extends BrowserKitTest $mfaSession->markVerifiedForUser($user); $this->assertTrue($mfaSession->isVerifiedForUser($user)); - $this->asAdmin()->visit('/logout'); + $this->asAdmin()->get('/logout'); $this->assertFalse($mfaSession->isVerifiedForUser($user)); } @@ -343,69 +212,86 @@ class AuthTest extends BrowserKitTest { Notification::fake(); - $this->visit('/login')->click('Forgot Password?') - ->seePageIs('/password/email') - ->type('admin@admin.com', 'email') - ->press('Send Reset Link') - ->see('A password reset link will be sent to admin@admin.com if that email address is found in the system.'); + $this->get('/login') + ->assertElementContains('a[href="' . url('/password/email') . '"]', 'Forgot Password?'); - $this->seeInDatabase('password_resets', [ + $this->get('/password/email') + ->assertElementContains('form[action="' . url('/password/email') . '"]', 'Send Reset Link'); + + $resp = $this->post('/password/email', [ + 'email' => 'admin@admin.com', + ]); + $resp->assertRedirect('/password/email'); + + $resp = $this->get('/password/email'); + $resp->assertSee('A password reset link will be sent to admin@admin.com if that email address is found in the system.'); + + $this->assertDatabaseHas('password_resets', [ 'email' => 'admin@admin.com', ]); - $user = User::where('email', '=', 'admin@admin.com')->first(); + /** @var User $user */ + $user = User::query()->where('email', '=', 'admin@admin.com')->first(); Notification::assertSentTo($user, ResetPassword::class); $n = Notification::sent($user, ResetPassword::class); - $this->visit('/password/reset/' . $n->first()->token) - ->see('Reset Password') - ->submitForm('Reset Password', [ - 'email' => 'admin@admin.com', - 'password' => 'randompass', - 'password_confirmation' => 'randompass', - ])->seePageIs('/') - ->see('Your password has been successfully reset'); + $this->get('/password/reset/' . $n->first()->token) + ->assertOk() + ->assertSee('Reset Password'); + + $resp = $this->post('/password/reset', [ + 'email' => 'admin@admin.com', + 'password' => 'randompass', + 'password_confirmation' => 'randompass', + 'token' => $n->first()->token + ]); + $resp->assertRedirect('/'); + + $this->get('/')->assertSee('Your password has been successfully reset'); } public function test_reset_password_flow_shows_success_message_even_if_wrong_password_to_prevent_user_discovery() { - $this->visit('/login')->click('Forgot Password?') - ->seePageIs('/password/email') - ->type('barry@admin.com', 'email') - ->press('Send Reset Link') - ->see('A password reset link will be sent to barry@admin.com if that email address is found in the system.') - ->dontSee('We can\'t find a user'); + $this->get('/password/email'); + $resp = $this->followingRedirects()->post('/password/email', [ + 'email' => 'barry@admin.com', + ]); + $resp->assertSee('A password reset link will be sent to barry@admin.com if that email address is found in the system.'); + $resp->assertDontSee('We can\'t find a user'); - $this->visit('/password/reset/arandometokenvalue') - ->see('Reset Password') - ->submitForm('Reset Password', [ - 'email' => 'barry@admin.com', - 'password' => 'randompass', - 'password_confirmation' => 'randompass', - ])->followRedirects() - ->seePageIs('/password/reset/arandometokenvalue') - ->dontSee('We can\'t find a user') - ->see('The password reset token is invalid for this email address.'); + + $this->get('/password/reset/arandometokenvalue')->assertSee('Reset Password'); + $resp = $this->post('/password/reset', [ + 'email' => 'barry@admin.com', + 'password' => 'randompass', + 'password_confirmation' => 'randompass', + 'token' => 'arandometokenvalue' + ]); + $resp->assertRedirect('/password/reset/arandometokenvalue'); + + $this->get('/password/reset/arandometokenvalue') + ->assertDontSee('We can\'t find a user') + ->assertSee('The password reset token is invalid for this email address.'); } public function test_reset_password_page_shows_sign_links() { $this->setSettings(['registration-enabled' => 'true']); - $this->visit('/password/email') - ->seeLink('Log in') - ->seeLink('Sign up'); + $this->get('/password/email') + ->assertElementContains('a', 'Log in') + ->assertElementContains('a', 'Sign up'); } public function test_login_redirects_to_initially_requested_url_correctly() { config()->set('app.url', 'http://localhost'); + /** @var Page $page */ $page = Page::query()->first(); - $this->visit($page->getUrl()) - ->seePageUrlIs(url('/login')); + $this->get($page->getUrl())->assertRedirect(url('/login')); $this->login('admin@admin.com', 'password') - ->seePageUrlIs($page->getUrl()); + ->assertRedirect($page->getUrl()); } public function test_login_intended_redirect_does_not_redirect_to_external_pages() @@ -416,15 +302,15 @@ class AuthTest extends BrowserKitTest $this->get('/login', ['referer' => 'https://example.com']); $login = $this->post('/login', ['email' => 'admin@admin.com', 'password' => 'password']); - $login->assertRedirectedTo('http://localhost'); + $login->assertRedirect('http://localhost'); } public function test_login_intended_redirect_does_not_factor_mfa_routes() { - $this->get('/books')->assertRedirectedTo('/login'); - $this->get('/mfa/setup')->assertRedirectedTo('/login'); + $this->get('/books')->assertRedirect('/login'); + $this->get('/mfa/setup')->assertRedirect('/login'); $login = $this->post('/login', ['email' => 'admin@admin.com', 'password' => 'password']); - $login->assertRedirectedTo('/books'); + $login->assertRedirect('/books'); } public function test_login_authenticates_admins_on_all_guards() @@ -469,20 +355,15 @@ class AuthTest extends BrowserKitTest auth()->login($user); $this->assertTrue(auth()->check()); - $this->get('/books'); - $this->assertRedirectedTo('/'); - + $this->get('/books')->assertRedirect('/'); $this->assertFalse(auth()->check()); } /** * Perform a login. */ - protected function login(string $email, string $password): AuthTest + protected function login(string $email, string $password): TestResponse { - return $this->visit('/login') - ->type($email, '#email') - ->type($password, '#password') - ->press('Log In'); + return $this->post('/login', compact('email', 'password')); } } diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php index cd0d244c9..77bd5076b 100644 --- a/tests/SharedTestHelpers.php +++ b/tests/SharedTestHelpers.php @@ -89,7 +89,7 @@ trait SharedTestHelpers /** * Get a user that's not a system user such as the guest user. */ - public function getNormalUser() + public function getNormalUser(): User { return User::query()->where('system_name', '=', null)->get()->last(); } diff --git a/tests/User/UserManagementTest.php b/tests/User/UserManagementTest.php index b7331d870..f52a78a13 100644 --- a/tests/User/UserManagementTest.php +++ b/tests/User/UserManagementTest.php @@ -3,12 +3,114 @@ namespace Tests\User; use BookStack\Actions\ActivityType; +use BookStack\Auth\Role; use BookStack\Auth\User; use BookStack\Entities\Models\Page; +use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Str; use Tests\TestCase; class UserManagementTest extends TestCase { + + public function test_user_creation() + { + /** @var User $user */ + $user = factory(User::class)->make(); + $adminRole = Role::getRole('admin'); + + $resp = $this->asAdmin()->get('/settings/users'); + $resp->assertElementContains('a[href="' . url('/settings/users/create') . '"]', 'Add New User'); + + $this->get('/settings/users/create') + ->assertElementContains('form[action="' . url('/settings/users/create') . '"]', 'Save'); + + $resp = $this->post('/settings/users/create', [ + 'name' => $user->name, + 'email' => $user->email, + 'password' => $user->password, + 'password-confirm' => $user->password, + 'roles[' . $adminRole->id . ']' => 'true', + ]); + $resp->assertRedirect('/settings/users'); + + $resp = $this->get('/settings/users'); + $resp->assertSee($user->name); + + $this->assertDatabaseHas('users', $user->only('name', 'email')); + + $user->refresh(); + $this->assertStringStartsWith(Str::slug($user->name), $user->slug); + } + + public function test_user_updating() + { + $user = $this->getNormalUser(); + $password = $user->password; + + + $resp = $this->asAdmin()->get('/settings/users/' . $user->id); + $resp->assertSee($user->email); + + $this->put($user->getEditUrl(), [ + 'name' => 'Barry Scott' + ])->assertRedirect('/settings/users'); + + $this->assertDatabaseHas('users', ['id' => $user->id, 'name' => 'Barry Scott', 'password' => $password]); + $this->assertDatabaseMissing('users', ['name' => $user->name]); + + $user->refresh(); + $this->assertStringStartsWith(Str::slug($user->name), $user->slug); + } + + public function test_user_password_update() + { + $user = $this->getNormalUser(); + $userProfilePage = '/settings/users/' . $user->id; + + $this->asAdmin()->get($userProfilePage); + $this->put($userProfilePage, [ + 'password' => 'newpassword' + ])->assertRedirect($userProfilePage); + + $this->get($userProfilePage)->assertSee('Password confirmation required'); + + $this->put($userProfilePage, [ + 'password' => 'newpassword', + 'password-confirm' => 'newpassword', + ])->assertRedirect('/settings/users'); + + $userPassword = User::query()->find($user->id)->password; + $this->assertTrue(Hash::check('newpassword', $userPassword)); + } + + public function test_user_cannot_be_deleted_if_last_admin() + { + $adminRole = Role::getRole('admin'); + + // Delete all but one admin user if there are more than one + $adminUsers = $adminRole->users; + if (count($adminUsers) > 1) { + /** @var User $user */ + foreach ($adminUsers->splice(1) as $user) { + $user->delete(); + } + } + + // Ensure we currently only have 1 admin user + $this->assertEquals(1, $adminRole->users()->count()); + /** @var User $user */ + $user = $adminRole->users->first(); + + $resp = $this->asAdmin()->delete('/settings/users/' . $user->id); + $resp->assertRedirect('/settings/users/' . $user->id); + + $resp = $this->get('/settings/users/' . $user->id); + $resp->assertSee('You cannot delete the only admin'); + + $this->assertDatabaseHas('users', ['id' => $user->id]); + } + public function test_delete() { $editor = $this->getEditor(); From d74255df5db46c8d57907e793a99bf3d167113c7 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 18 Sep 2021 00:33:03 +0100 Subject: [PATCH 7/9] Started updating RolesTest away from Browserkit --- app/Actions/Comment.php | 9 +- tests/Permissions/RolesTest.php | 450 ++++++++++++++++---------------- 2 files changed, 231 insertions(+), 228 deletions(-) diff --git a/app/Actions/Comment.php b/app/Actions/Comment.php index ef390939e..e652bf8a8 100644 --- a/app/Actions/Comment.php +++ b/app/Actions/Comment.php @@ -7,10 +7,11 @@ use BookStack\Traits\HasCreatorAndUpdater; use Illuminate\Database\Eloquent\Relations\MorphTo; /** - * @property string text - * @property string html - * @property int|null parent_id - * @property int local_id + * @property int $id + * @property string $text + * @property string $html + * @property int|null $parent_id + * @property int $local_id */ class Comment extends Model { diff --git a/tests/Permissions/RolesTest.php b/tests/Permissions/RolesTest.php index b9b1805b6..c9c3195a9 100644 --- a/tests/Permissions/RolesTest.php +++ b/tests/Permissions/RolesTest.php @@ -10,10 +10,10 @@ use BookStack\Entities\Models\Bookshelf; use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Page; use BookStack\Uploads\Image; -use Laravel\BrowserKitTesting\HttpException; -use Tests\BrowserKitTest; +use Tests\TestCase; +use Tests\TestResponse; -class RolesTest extends BrowserKitTest +class RolesTest extends TestCase { protected $user; @@ -25,17 +25,17 @@ class RolesTest extends BrowserKitTest public function test_admin_can_see_settings() { - $this->asAdmin()->visit('/settings')->see('Settings'); + $this->asAdmin()->get('/settings')->assertSee('Settings'); } public function test_cannot_delete_admin_role() { $adminRole = Role::getRole('admin'); $deletePageUrl = '/settings/roles/delete/' . $adminRole->id; - $this->asAdmin()->visit($deletePageUrl) - ->press('Confirm') - ->seePageIs($deletePageUrl) - ->see('cannot be deleted'); + + $this->asAdmin()->get($deletePageUrl); + $this->delete($deletePageUrl)->assertRedirect($deletePageUrl); + $this->get($deletePageUrl)->assertSee('cannot be deleted'); } public function test_role_cannot_be_deleted_if_default() @@ -44,10 +44,9 @@ class RolesTest extends BrowserKitTest $this->setSettings(['registration-role' => $newRole->id]); $deletePageUrl = '/settings/roles/delete/' . $newRole->id; - $this->asAdmin()->visit($deletePageUrl) - ->press('Confirm') - ->seePageIs($deletePageUrl) - ->see('cannot be deleted'); + $this->asAdmin()->get($deletePageUrl); + $this->delete($deletePageUrl)->assertRedirect($deletePageUrl); + $this->get($deletePageUrl)->assertSee('cannot be deleted'); } public function test_role_create_update_delete_flow() @@ -57,35 +56,37 @@ class RolesTest extends BrowserKitTest $testRoleUpdateName = 'An Super Updated role'; // Creation - $this->asAdmin()->visit('/settings') + $this->asAdmin()->get('/settings') ->click('Roles') ->seePageIs('/settings/roles') ->click('Create New Role') ->type('Test Role', 'display_name') ->type('A little test description', 'description') ->press('Save Role') - ->seeInDatabase('roles', ['display_name' => $testRoleName, 'description' => $testRoleDesc, 'mfa_enforced' => false]) + ->assertDatabaseHas('roles', ['display_name' => $testRoleName, 'description' => $testRoleDesc, 'mfa_enforced' => false]) ->seePageIs('/settings/roles'); + // Updating - $this->asAdmin()->visit('/settings/roles') - ->see($testRoleDesc) + $this->asAdmin()->get('/settings/roles') + ->assertSee($testRoleDesc) ->click($testRoleName) ->type($testRoleUpdateName, '#display_name') ->check('#mfa_enforced') ->press('Save Role') - ->seeInDatabase('roles', ['display_name' => $testRoleUpdateName, 'description' => $testRoleDesc, 'mfa_enforced' => true]) + ->assertDatabaseHas('roles', ['display_name' => $testRoleUpdateName, 'description' => $testRoleDesc, 'mfa_enforced' => true]) ->seePageIs('/settings/roles'); + // Deleting - $this->asAdmin()->visit('/settings/roles') + $this->asAdmin()->get('/settings/roles') ->click($testRoleUpdateName) ->click('Delete Role') - ->see($testRoleUpdateName) + ->assertSee($testRoleUpdateName) ->press('Confirm') ->seePageIs('/settings/roles') - ->dontSee($testRoleUpdateName); + ->assertDontSee($testRoleUpdateName); } - public function test_admin_role_cannot_be_removed_if_last_admin() + public function test_admin_role_cannot_be_removed_if_user_last_admin() { $adminRole = Role::where('system_name', '=', 'admin')->first(); $adminUser = $this->getAdmin(); @@ -104,7 +105,7 @@ class RolesTest extends BrowserKitTest ])->followRedirects(); $this->seePageIs($editUrl); - $this->see('This user is the only user assigned to the administrator role'); + $this->assertSee('This user is the only user assigned to the administrator role'); } public function test_migrate_users_on_delete_works() @@ -117,7 +118,7 @@ class RolesTest extends BrowserKitTest $this->assertCount(1, $roleB->users()->get()); $deletePage = $this->asAdmin()->get("/settings/roles/delete/{$roleB->id}"); - $deletePage->seeElement('select[name=migrate_role_id]'); + $deletePage->assertElementExists('select[name=migrate_role_id]'); $this->asAdmin()->delete("/settings/roles/delete/{$roleB->id}", [ 'migrate_role_id' => $roleA->id, ]); @@ -128,21 +129,21 @@ class RolesTest extends BrowserKitTest public function test_manage_user_permission() { - $this->actingAs($this->user)->visit('/settings/users') + $this->actingAs($this->user)->get('/settings/users') ->seePageIs('/'); $this->giveUserPermissions($this->user, ['users-manage']); - $this->actingAs($this->user)->visit('/settings/users') + $this->actingAs($this->user)->get('/settings/users') ->seePageIs('/settings/users'); } public function test_manage_users_permission_shows_link_in_header_if_does_not_have_settings_manage_permision() { $usersLink = 'href="' . url('/settings/users') . '"'; - $this->actingAs($this->user)->visit('/')->dontSee($usersLink); + $this->actingAs($this->user)->get('/')->assertDontSee($usersLink); $this->giveUserPermissions($this->user, ['users-manage']); - $this->actingAs($this->user)->visit('/')->see($usersLink); + $this->actingAs($this->user)->get('/')->assertSee($usersLink); $this->giveUserPermissions($this->user, ['settings-manage', 'users-manage']); - $this->actingAs($this->user)->visit('/')->dontSee($usersLink); + $this->actingAs($this->user)->get('/')->assertDontSee($usersLink); } public function test_user_cannot_change_email_unless_they_have_manage_users_permission() @@ -151,14 +152,14 @@ class RolesTest extends BrowserKitTest $originalEmail = $this->user->email; $this->actingAs($this->user); - $this->visit($userProfileUrl) - ->assertResponseOk() - ->seeElement('input[name=email][disabled]'); + $this->get($userProfileUrl) + ->assertOk() + ->assertElementExists('input[name=email][disabled]'); $this->put($userProfileUrl, [ 'name' => 'my_new_name', 'email' => 'new_email@example.com', ]); - $this->seeInDatabase('users', [ + $this->assertDatabaseHas('users', [ 'id' => $this->user->id, 'email' => $originalEmail, 'name' => 'my_new_name', @@ -166,16 +167,16 @@ class RolesTest extends BrowserKitTest $this->giveUserPermissions($this->user, ['users-manage']); - $this->visit($userProfileUrl) - ->assertResponseOk() - ->dontSeeElement('input[name=email][disabled]') - ->seeElement('input[name=email]'); + $this->get($userProfileUrl) + ->assertOk() + ->assertElementNotExists('input[name=email][disabled]') + ->assertElementExists('input[name=email]'); $this->put($userProfileUrl, [ 'name' => 'my_new_name_2', 'email' => 'new_email@example.com', ]); - $this->seeInDatabase('users', [ + $this->assertDatabaseHas('users', [ 'id' => $this->user->id, 'email' => 'new_email@example.com', 'name' => 'my_new_name_2', @@ -184,40 +185,41 @@ class RolesTest extends BrowserKitTest public function test_user_roles_manage_permission() { - $this->actingAs($this->user)->visit('/settings/roles') - ->seePageIs('/')->visit('/settings/roles/1')->seePageIs('/'); + $this->actingAs($this->user)->get('/settings/roles') + ->seePageIs('/')->get('/settings/roles/1')->seePageIs('/'); $this->giveUserPermissions($this->user, ['user-roles-manage']); - $this->actingAs($this->user)->visit('/settings/roles') + $this->actingAs($this->user)->get('/settings/roles') ->seePageIs('/settings/roles')->click('Admin') - ->see('Edit Role'); + ->assertSee('Edit Role'); } public function test_settings_manage_permission() { - $this->actingAs($this->user)->visit('/settings') + $this->actingAs($this->user)->get('/settings') ->seePageIs('/'); $this->giveUserPermissions($this->user, ['settings-manage']); - $this->actingAs($this->user)->visit('/settings') - ->seePageIs('/settings')->press('Save Settings')->see('Settings Saved'); + $this->actingAs($this->user)->get('/settings') + ->seePageIs('/settings')->press('Save Settings')->assertSee('Settings Saved'); } public function test_restrictions_manage_all_permission() { $page = Page::take(1)->get()->first(); - $this->actingAs($this->user)->visit($page->getUrl()) - ->dontSee('Permissions') - ->visit($page->getUrl() . '/permissions') + $this->actingAs($this->user)->get($page->getUrl()) + ->assertDontSee('Permissions') + ->get($page->getUrl() . '/permissions') ->seePageIs('/'); $this->giveUserPermissions($this->user, ['restrictions-manage-all']); - $this->actingAs($this->user)->visit($page->getUrl()) - ->see('Permissions') + $this->actingAs($this->user)->get($page->getUrl()) + ->assertSee('Permissions') ->click('Permissions') - ->see('Page Permissions')->seePageIs($page->getUrl() . '/permissions'); + ->assertSee('Page Permissions')->seePageIs($page->getUrl() . '/permissions'); } public function test_restrictions_manage_own_permission() { - $otherUsersPage = Page::first(); + /** @var Page $otherUsersPage */ + $otherUsersPage = Page::query()->first(); $content = $this->createEntityChainBelongingToUser($this->user); // Set a different creator on the page we're checking to ensure @@ -228,26 +230,26 @@ class RolesTest extends BrowserKitTest $page->save(); // Check can't restrict other's content - $this->actingAs($this->user)->visit($otherUsersPage->getUrl()) - ->dontSee('Permissions') - ->visit($otherUsersPage->getUrl() . '/permissions') + $this->actingAs($this->user)->get($otherUsersPage->getUrl()) + ->assertDontSee('Permissions') + ->get($otherUsersPage->getUrl() . '/permissions') ->seePageIs('/'); // Check can't restrict own content - $this->actingAs($this->user)->visit($page->getUrl()) - ->dontSee('Permissions') - ->visit($page->getUrl() . '/permissions') + $this->actingAs($this->user)->get($page->getUrl()) + ->assertDontSee('Permissions') + ->get($page->getUrl() . '/permissions') ->seePageIs('/'); $this->giveUserPermissions($this->user, ['restrictions-manage-own']); // Check can't restrict other's content - $this->actingAs($this->user)->visit($otherUsersPage->getUrl()) - ->dontSee('Permissions') - ->visit($otherUsersPage->getUrl() . '/permissions') + $this->actingAs($this->user)->get($otherUsersPage->getUrl()) + ->assertDontSee('Permissions') + ->get($otherUsersPage->getUrl() . '/permissions') ->seePageIs('/'); // Check can restrict own content - $this->actingAs($this->user)->visit($page->getUrl()) - ->see('Permissions') + $this->actingAs($this->user)->get($page->getUrl()) + ->assertSee('Permissions') ->click('Permissions') ->seePageIs($page->getUrl() . '/permissions'); } @@ -262,23 +264,23 @@ class RolesTest extends BrowserKitTest private function checkAccessPermission($permission, $accessUrls = [], $visibles = []) { foreach ($accessUrls as $url) { - $this->actingAs($this->user)->visit($url) + $this->actingAs($this->user)->get($url) ->seePageIs('/'); } foreach ($visibles as $url => $text) { - $this->actingAs($this->user)->visit($url) - ->dontSeeInElement('.action-buttons', $text); + $this->actingAs($this->user)->get($url) + ->assertElementNotContains('.action-buttons', $text); } $this->giveUserPermissions($this->user, [$permission]); foreach ($accessUrls as $url) { - $this->actingAs($this->user)->visit($url) + $this->actingAs($this->user)->get($url) ->seePageIs($url); } foreach ($visibles as $url => $text) { - $this->actingAs($this->user)->visit($url) - ->see($text); + $this->actingAs($this->user)->get($url) + ->assertSee($text); } } @@ -290,7 +292,7 @@ class RolesTest extends BrowserKitTest '/shelves' => 'New Shelf', ]); - $this->visit('/create-shelf') + $this->get('/create-shelf') ->type('test shelf', 'name') ->type('shelf desc', 'description') ->press('Save Shelf') @@ -299,7 +301,8 @@ class RolesTest extends BrowserKitTest public function test_bookshelves_edit_own_permission() { - $otherShelf = Bookshelf::first(); + /** @var Bookshelf $otherShelf */ + $otherShelf = Bookshelf::query()->first(); $ownShelf = $this->newShelf(['name' => 'test-shelf', 'slug' => 'test-shelf']); $ownShelf->forceFill(['owned_by' => $this->user->id, 'updated_by' => $this->user->id])->save(); $this->regenEntityPermissions($ownShelf); @@ -310,15 +313,16 @@ class RolesTest extends BrowserKitTest $ownShelf->getUrl() => 'Edit', ]); - $this->visit($otherShelf->getUrl()) - ->dontSeeInElement('.action-buttons', 'Edit') - ->visit($otherShelf->getUrl('/edit')) + $this->get($otherShelf->getUrl()) + ->assertElementNotContains('.action-buttons', 'Edit') + ->get($otherShelf->getUrl('/edit')) ->seePageIs('/'); } public function test_bookshelves_edit_all_permission() { - $otherShelf = Bookshelf::first(); + /** @var Bookshelf $otherShelf */ + $otherShelf = Bookshelf::query()->first(); $this->checkAccessPermission('bookshelf-update-all', [ $otherShelf->getUrl('/edit'), ], [ @@ -329,7 +333,8 @@ class RolesTest extends BrowserKitTest public function test_bookshelves_delete_own_permission() { $this->giveUserPermissions($this->user, ['bookshelf-update-all']); - $otherShelf = Bookshelf::first(); + /** @var Bookshelf $otherShelf */ + $otherShelf = Bookshelf::query()->first(); $ownShelf = $this->newShelf(['name' => 'test-shelf', 'slug' => 'test-shelf']); $ownShelf->forceFill(['owned_by' => $this->user->id, 'updated_by' => $this->user->id])->save(); $this->regenEntityPermissions($ownShelf); @@ -340,30 +345,31 @@ class RolesTest extends BrowserKitTest $ownShelf->getUrl() => 'Delete', ]); - $this->visit($otherShelf->getUrl()) - ->dontSeeInElement('.action-buttons', 'Delete') - ->visit($otherShelf->getUrl('/delete')) + $this->get($otherShelf->getUrl()) + ->assertElementNotContains('.action-buttons', 'Delete') + ->get($otherShelf->getUrl('/delete')) ->seePageIs('/'); - $this->visit($ownShelf->getUrl())->visit($ownShelf->getUrl('/delete')) + $this->get($ownShelf->getUrl())->get($ownShelf->getUrl('/delete')) ->press('Confirm') ->seePageIs('/shelves') - ->dontSee($ownShelf->name); + ->assertDontSee($ownShelf->name); } public function test_bookshelves_delete_all_permission() { $this->giveUserPermissions($this->user, ['bookshelf-update-all']); - $otherShelf = Bookshelf::first(); + /** @var Bookshelf $otherShelf */ + $otherShelf = Bookshelf::query()->first(); $this->checkAccessPermission('bookshelf-delete-all', [ $otherShelf->getUrl('/delete'), ], [ $otherShelf->getUrl() => 'Delete', ]); - $this->visit($otherShelf->getUrl())->visit($otherShelf->getUrl('/delete')) + $this->get($otherShelf->getUrl())->get($otherShelf->getUrl('/delete')) ->press('Confirm') ->seePageIs('/shelves') - ->dontSee($otherShelf->name); + ->assertDontSee($otherShelf->name); } public function test_books_create_all_permissions() @@ -374,7 +380,7 @@ class RolesTest extends BrowserKitTest '/books' => 'Create New Book', ]); - $this->visit('/create-book') + $this->get('/create-book') ->type('test book', 'name') ->type('book desc', 'description') ->press('Save Book') @@ -383,7 +389,8 @@ class RolesTest extends BrowserKitTest public function test_books_edit_own_permission() { - $otherBook = Book::take(1)->get()->first(); + /** @var Book $otherBook */ + $otherBook = Book::query()->take(1)->get()->first(); $ownBook = $this->createEntityChainBelongingToUser($this->user)['book']; $this->checkAccessPermission('book-update-own', [ $ownBook->getUrl() . '/edit', @@ -391,15 +398,16 @@ class RolesTest extends BrowserKitTest $ownBook->getUrl() => 'Edit', ]); - $this->visit($otherBook->getUrl()) - ->dontSeeInElement('.action-buttons', 'Edit') - ->visit($otherBook->getUrl() . '/edit') + $this->get($otherBook->getUrl()) + ->assertElementNotContains('.action-buttons', 'Edit') + ->get($otherBook->getUrl() . '/edit') ->seePageIs('/'); } public function test_books_edit_all_permission() { - $otherBook = Book::take(1)->get()->first(); + /** @var Book $otherBook */ + $otherBook = Book::query()->take(1)->get()->first(); $this->checkAccessPermission('book-update-all', [ $otherBook->getUrl() . '/edit', ], [ @@ -410,7 +418,8 @@ class RolesTest extends BrowserKitTest public function test_books_delete_own_permission() { $this->giveUserPermissions($this->user, ['book-update-all']); - $otherBook = Book::take(1)->get()->first(); + /** @var Book $otherBook */ + $otherBook = Book::query()->take(1)->get()->first(); $ownBook = $this->createEntityChainBelongingToUser($this->user)['book']; $this->checkAccessPermission('book-delete-own', [ $ownBook->getUrl() . '/delete', @@ -418,35 +427,37 @@ class RolesTest extends BrowserKitTest $ownBook->getUrl() => 'Delete', ]); - $this->visit($otherBook->getUrl()) - ->dontSeeInElement('.action-buttons', 'Delete') - ->visit($otherBook->getUrl() . '/delete') + $this->get($otherBook->getUrl()) + ->assertElementNotContains('.action-buttons', 'Delete') + ->get($otherBook->getUrl() . '/delete') ->seePageIs('/'); - $this->visit($ownBook->getUrl())->visit($ownBook->getUrl() . '/delete') + $this->get($ownBook->getUrl())->get($ownBook->getUrl() . '/delete') ->press('Confirm') ->seePageIs('/books') - ->dontSee($ownBook->name); + ->assertDontSee($ownBook->name); } public function test_books_delete_all_permission() { $this->giveUserPermissions($this->user, ['book-update-all']); - $otherBook = Book::take(1)->get()->first(); + /** @var Book $otherBook */ + $otherBook = Book::query()->take(1)->get()->first(); $this->checkAccessPermission('book-delete-all', [ $otherBook->getUrl() . '/delete', ], [ $otherBook->getUrl() => 'Delete', ]); - $this->visit($otherBook->getUrl())->visit($otherBook->getUrl() . '/delete') + $this->get($otherBook->getUrl())->get($otherBook->getUrl() . '/delete') ->press('Confirm') ->seePageIs('/books') - ->dontSee($otherBook->name); + ->assertDontSee($otherBook->name); } public function test_chapter_create_own_permissions() { - $book = Book::take(1)->get()->first(); + /** @var Book $book */ + $book = Book::query()->take(1)->get()->first(); $ownBook = $this->createEntityChainBelongingToUser($this->user)['book']; $this->checkAccessPermission('chapter-create-own', [ $ownBook->getUrl('/create-chapter'), @@ -454,15 +465,15 @@ class RolesTest extends BrowserKitTest $ownBook->getUrl() => 'New Chapter', ]); - $this->visit($ownBook->getUrl('/create-chapter')) + $this->get($ownBook->getUrl('/create-chapter')) ->type('test chapter', 'name') ->type('chapter desc', 'description') ->press('Save Chapter') ->seePageIs($ownBook->getUrl('/chapter/test-chapter')); - $this->visit($book->getUrl()) - ->dontSeeInElement('.action-buttons', 'New Chapter') - ->visit($book->getUrl('/create-chapter')) + $this->get($book->getUrl()) + ->assertElementNotContains('.action-buttons', 'New Chapter') + ->get($book->getUrl('/create-chapter')) ->seePageIs('/'); } @@ -475,7 +486,7 @@ class RolesTest extends BrowserKitTest $book->getUrl() => 'New Chapter', ]); - $this->visit($book->getUrl('/create-chapter')) + $this->get($book->getUrl('/create-chapter')) ->type('test chapter', 'name') ->type('chapter desc', 'description') ->press('Save Chapter') @@ -492,15 +503,16 @@ class RolesTest extends BrowserKitTest $ownChapter->getUrl() => 'Edit', ]); - $this->visit($otherChapter->getUrl()) - ->dontSeeInElement('.action-buttons', 'Edit') - ->visit($otherChapter->getUrl() . '/edit') + $this->get($otherChapter->getUrl()) + ->assertElementNotContains('.action-buttons', 'Edit') + ->get($otherChapter->getUrl() . '/edit') ->seePageIs('/'); } public function test_chapter_edit_all_permission() { - $otherChapter = Chapter::take(1)->get()->first(); + /** @var Chapter $otherChapter */ + $otherChapter = Chapter::query()->take(1)->get()->first(); $this->checkAccessPermission('chapter-update-all', [ $otherChapter->getUrl() . '/edit', ], [ @@ -511,7 +523,8 @@ class RolesTest extends BrowserKitTest public function test_chapter_delete_own_permission() { $this->giveUserPermissions($this->user, ['chapter-update-all']); - $otherChapter = Chapter::take(1)->get()->first(); + /** @var Chapter $otherChapter */ + $otherChapter = Chapter::query()->take(1)->get()->first(); $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter']; $this->checkAccessPermission('chapter-delete-own', [ $ownChapter->getUrl() . '/delete', @@ -520,14 +533,14 @@ class RolesTest extends BrowserKitTest ]); $bookUrl = $ownChapter->book->getUrl(); - $this->visit($otherChapter->getUrl()) - ->dontSeeInElement('.action-buttons', 'Delete') - ->visit($otherChapter->getUrl() . '/delete') + $this->get($otherChapter->getUrl()) + ->assertElementNotContains('.action-buttons', 'Delete') + ->get($otherChapter->getUrl() . '/delete') ->seePageIs('/'); - $this->visit($ownChapter->getUrl())->visit($ownChapter->getUrl() . '/delete') + $this->get($ownChapter->getUrl())->get($ownChapter->getUrl() . '/delete') ->press('Confirm') ->seePageIs($bookUrl) - ->dontSeeInElement('.book-content', $ownChapter->name); + ->assertElementNotContains('.book-content', $ownChapter->name); } public function test_chapter_delete_all_permission() @@ -541,16 +554,18 @@ class RolesTest extends BrowserKitTest ]); $bookUrl = $otherChapter->book->getUrl(); - $this->visit($otherChapter->getUrl())->visit($otherChapter->getUrl() . '/delete') + $this->get($otherChapter->getUrl())->get($otherChapter->getUrl() . '/delete') ->press('Confirm') ->seePageIs($bookUrl) - ->dontSeeInElement('.book-content', $otherChapter->name); + ->assertElementNotContains('.book-content', $otherChapter->name); } public function test_page_create_own_permissions() { - $book = Book::first(); - $chapter = Chapter::first(); + /** @var Book $book */ + $book = Book::query()->first(); + /** @var Chapter $chapter */ + $chapter = Chapter::query()->first(); $entities = $this->createEntityChainBelongingToUser($this->user); $ownBook = $entities['book']; @@ -561,7 +576,7 @@ class RolesTest extends BrowserKitTest $accessUrls = [$createUrl, $createUrlChapter]; foreach ($accessUrls as $url) { - $this->actingAs($this->user)->visit($url) + $this->actingAs($this->user)->get($url) ->seePageIs('/'); } @@ -573,24 +588,24 @@ class RolesTest extends BrowserKitTest $this->giveUserPermissions($this->user, ['page-create-own']); foreach ($accessUrls as $index => $url) { - $this->actingAs($this->user)->visit($url); + $this->actingAs($this->user)->get($url); $expectedUrl = Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl(); $this->seePageIs($expectedUrl); } - $this->visit($createUrl) + $this->get($createUrl) ->type('test page', 'name') ->type('page desc', 'html') ->press('Save Page') ->seePageIs($ownBook->getUrl('/page/test-page')); - $this->visit($book->getUrl()) - ->dontSeeInElement('.action-buttons', 'New Page') - ->visit($book->getUrl() . '/create-page') + $this->get($book->getUrl()) + ->assertElementNotContains('.action-buttons', 'New Page') + ->get($book->getUrl() . '/create-page') ->seePageIs('/'); - $this->visit($chapter->getUrl()) - ->dontSeeInElement('.action-buttons', 'New Page') - ->visit($chapter->getUrl() . '/create-page') + $this->get($chapter->getUrl()) + ->assertElementNotContains('.action-buttons', 'New Page') + ->get($chapter->getUrl() . '/create-page') ->seePageIs('/'); } @@ -598,14 +613,13 @@ class RolesTest extends BrowserKitTest { $book = Book::take(1)->get()->first(); $chapter = Chapter::take(1)->get()->first(); - $baseUrl = $book->getUrl() . '/page'; $createUrl = $book->getUrl('/create-page'); $createUrlChapter = $chapter->getUrl('/create-page'); $accessUrls = [$createUrl, $createUrlChapter]; foreach ($accessUrls as $url) { - $this->actingAs($this->user)->visit($url) + $this->actingAs($this->user)->get($url) ->seePageIs('/'); } @@ -617,18 +631,18 @@ class RolesTest extends BrowserKitTest $this->giveUserPermissions($this->user, ['page-create-all']); foreach ($accessUrls as $index => $url) { - $this->actingAs($this->user)->visit($url); + $this->actingAs($this->user)->get($url); $expectedUrl = Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl(); $this->seePageIs($expectedUrl); } - $this->visit($createUrl) + $this->get($createUrl) ->type('test page', 'name') ->type('page desc', 'html') ->press('Save Page') ->seePageIs($book->getUrl('/page/test-page')); - $this->visit($chapter->getUrl('/create-page')) + $this->get($chapter->getUrl('/create-page')) ->type('new test page', 'name') ->type('page desc', 'html') ->press('Save Page') @@ -645,9 +659,9 @@ class RolesTest extends BrowserKitTest $ownPage->getUrl() => 'Edit', ]); - $this->visit($otherPage->getUrl()) - ->dontSeeInElement('.action-buttons', 'Edit') - ->visit($otherPage->getUrl() . '/edit') + $this->get($otherPage->getUrl()) + ->assertElementNotContains('.action-buttons', 'Edit') + ->get($otherPage->getUrl() . '/edit') ->seePageIs('/'); } @@ -673,14 +687,14 @@ class RolesTest extends BrowserKitTest ]); $parent = $ownPage->chapter ?? $ownPage->book; - $this->visit($otherPage->getUrl()) - ->dontSeeInElement('.action-buttons', 'Delete') - ->visit($otherPage->getUrl() . '/delete') + $this->get($otherPage->getUrl()) + ->assertElementNotContains('.action-buttons', 'Delete') + ->get($otherPage->getUrl() . '/delete') ->seePageIs('/'); - $this->visit($ownPage->getUrl())->visit($ownPage->getUrl() . '/delete') + $this->get($ownPage->getUrl())->get($ownPage->getUrl() . '/delete') ->press('Confirm') ->seePageIs($parent->getUrl()) - ->dontSeeInElement('.book-content', $ownPage->name); + ->assertElementNotContains('.book-content', $ownPage->name); } public function test_page_delete_all_permission() @@ -694,10 +708,10 @@ class RolesTest extends BrowserKitTest ]); $parent = $otherPage->chapter ?? $otherPage->book; - $this->visit($otherPage->getUrl())->visit($otherPage->getUrl() . '/delete') + $this->get($otherPage->getUrl())->get($otherPage->getUrl() . '/delete') ->press('Confirm') ->seePageIs($parent->getUrl()) - ->dontSeeInElement('.book-content', $otherPage->name); + ->assertElementNotContains('.book-content', $otherPage->name); } public function test_public_role_visible_in_user_edit_screen() @@ -705,34 +719,34 @@ class RolesTest extends BrowserKitTest $user = User::first(); $adminRole = Role::getSystemRole('admin'); $publicRole = Role::getSystemRole('public'); - $this->asAdmin()->visit('/settings/users/' . $user->id) - ->seeElement('[name="roles[' . $adminRole->id . ']"]') - ->seeElement('[name="roles[' . $publicRole->id . ']"]'); + $this->asAdmin()->get('/settings/users/' . $user->id) + ->assertElementExists('[name="roles[' . $adminRole->id . ']"]') + ->assertElementExists('[name="roles[' . $publicRole->id . ']"]'); } public function test_public_role_visible_in_role_listing() { - $this->asAdmin()->visit('/settings/roles') - ->see('Admin') - ->see('Public'); + $this->asAdmin()->get('/settings/roles') + ->assertSee('Admin') + ->assertSee('Public'); } public function test_public_role_visible_in_default_role_setting() { - $this->asAdmin()->visit('/settings') - ->seeElement('[data-system-role-name="admin"]') - ->seeElement('[data-system-role-name="public"]'); + $this->asAdmin()->get('/settings') + ->assertElementExists('[data-system-role-name="admin"]') + ->assertElementExists('[data-system-role-name="public"]'); } public function test_public_role_not_deleteable() { - $this->asAdmin()->visit('/settings/roles') + $this->asAdmin()->get('/settings/roles') ->click('Public') - ->see('Edit Role') + ->assertSee('Edit Role') ->click('Delete Role') ->press('Confirm') - ->see('Delete Role') - ->see('Cannot be deleted'); + ->assertSee('Delete Role') + ->assertSee('Cannot be deleted'); } public function test_image_delete_own_permission() @@ -742,13 +756,13 @@ class RolesTest extends BrowserKitTest $image = factory(Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $this->user->id, 'updated_by' => $this->user->id]); $this->actingAs($this->user)->json('delete', '/images/' . $image->id) - ->seeStatusCode(403); + ->assertStatus(403); $this->giveUserPermissions($this->user, ['image-delete-own']); $this->actingAs($this->user)->json('delete', '/images/' . $image->id) - ->seeStatusCode(200) - ->dontSeeInDatabase('images', ['id' => $image->id]); + ->assertOk() + ->assertDatabaseMissing('images', ['id' => $image->id]); } public function test_image_delete_all_permission() @@ -759,36 +773,36 @@ class RolesTest extends BrowserKitTest $image = factory(Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]); $this->actingAs($this->user)->json('delete', '/images/' . $image->id) - ->seeStatusCode(403); + ->assertStatus(403); $this->giveUserPermissions($this->user, ['image-delete-own']); $this->actingAs($this->user)->json('delete', '/images/' . $image->id) - ->seeStatusCode(403); + ->assertStatus(403); $this->giveUserPermissions($this->user, ['image-delete-all']); $this->actingAs($this->user)->json('delete', '/images/' . $image->id) - ->seeStatusCode(200) - ->dontSeeInDatabase('images', ['id' => $image->id]); + ->assertOk() + ->assertDatabaseMissing('images', ['id' => $image->id]); } public function test_role_permission_removal() { // To cover issue fixed in f99c8ff99aee9beb8c692f36d4b84dc6e651e50a. - $page = Page::first(); + /** @var Page $page */ + $page = Page::query()->first(); $viewerRole = Role::getRole('viewer'); $viewer = $this->getViewer(); - $this->actingAs($viewer)->visit($page->getUrl())->assertResponseStatus(200); + $this->actingAs($viewer)->get($page->getUrl())->assertOk(); $this->asAdmin()->put('/settings/roles/' . $viewerRole->id, [ 'display_name' => $viewerRole->display_name, 'description' => $viewerRole->description, 'permission' => [], - ])->assertResponseStatus(302); + ])->assertStatus(302); - $this->expectException(HttpException::class); - $this->actingAs($viewer)->visit($page->getUrl())->assertResponseStatus(404); + $this->actingAs($viewer)->get($page->getUrl())->assertStatus(404); } public function test_empty_state_actions_not_visible_without_permission() @@ -796,130 +810,118 @@ class RolesTest extends BrowserKitTest $admin = $this->getAdmin(); // Book links $book = factory(Book::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id]); - $this->updateEntityPermissions($book); - $this->actingAs($this->getViewer())->visit($book->getUrl()) - ->dontSee('Create a new page') - ->dontSee('Add a chapter'); + $this->regenEntityPermissions($book); + $this->actingAs($this->getViewer())->get($book->getUrl()) + ->assertDontSee('Create a new page') + ->assertDontSee('Add a chapter'); // Chapter links $chapter = factory(Chapter::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]); - $this->updateEntityPermissions($chapter); - $this->actingAs($this->getViewer())->visit($chapter->getUrl()) - ->dontSee('Create a new page') - ->dontSee('Sort the current book'); + $this->regenEntityPermissions($chapter); + $this->actingAs($this->getViewer())->get($chapter->getUrl()) + ->assertDontSee('Create a new page') + ->assertDontSee('Sort the current book'); } public function test_comment_create_permission() { $ownPage = $this->createEntityChainBelongingToUser($this->user)['page']; - $this->actingAs($this->user)->addComment($ownPage); - - $this->assertResponseStatus(403); + $this->actingAs($this->user) + ->addComment($ownPage) + ->assertStatus(403); $this->giveUserPermissions($this->user, ['comment-create-all']); - $this->actingAs($this->user)->addComment($ownPage); - $this->assertResponseStatus(200); + $this->actingAs($this->user) + ->addComment($ownPage) + ->assertOk(); } public function test_comment_update_own_permission() { $ownPage = $this->createEntityChainBelongingToUser($this->user)['page']; $this->giveUserPermissions($this->user, ['comment-create-all']); - $commentId = $this->actingAs($this->user)->addComment($ownPage); + $this->actingAs($this->user)->addComment($ownPage); + /** @var Comment $comment */ + $comment = $ownPage->comments()->latest()->first(); // no comment-update-own - $this->actingAs($this->user)->updateComment($commentId); - $this->assertResponseStatus(403); + $this->actingAs($this->user)->updateComment($comment)->assertStatus(403); $this->giveUserPermissions($this->user, ['comment-update-own']); // now has comment-update-own - $this->actingAs($this->user)->updateComment($commentId); - $this->assertResponseStatus(200); + $this->actingAs($this->user)->updateComment($comment)->assertOk(); } public function test_comment_update_all_permission() { + /** @var Page $ownPage */ $ownPage = $this->createEntityChainBelongingToUser($this->user)['page']; - $commentId = $this->asAdmin()->addComment($ownPage); + $this->asAdmin()->addComment($ownPage); + /** @var Comment $comment */ + $comment = $ownPage->comments()->latest()->first(); // no comment-update-all - $this->actingAs($this->user)->updateComment($commentId); - $this->assertResponseStatus(403); + $this->actingAs($this->user)->updateComment($comment)->assertStatus(403); $this->giveUserPermissions($this->user, ['comment-update-all']); // now has comment-update-all - $this->actingAs($this->user)->updateComment($commentId); - $this->assertResponseStatus(200); + $this->actingAs($this->user)->updateComment($comment)->assertOk(); } public function test_comment_delete_own_permission() { + /** @var Page $ownPage */ $ownPage = $this->createEntityChainBelongingToUser($this->user)['page']; $this->giveUserPermissions($this->user, ['comment-create-all']); - $commentId = $this->actingAs($this->user)->addComment($ownPage); + $this->actingAs($this->user)->addComment($ownPage); + + /** @var Comment $comment */ + $comment = $ownPage->comments()->latest()->first(); // no comment-delete-own - $this->actingAs($this->user)->deleteComment($commentId); - $this->assertResponseStatus(403); + $this->actingAs($this->user)->deleteComment($comment)->assertStatus(403); $this->giveUserPermissions($this->user, ['comment-delete-own']); // now has comment-update-own - $this->actingAs($this->user)->deleteComment($commentId); - $this->assertResponseStatus(200); + $this->actingAs($this->user)->deleteComment($comment)->assertOk(); } public function test_comment_delete_all_permission() { + /** @var Page $ownPage */ $ownPage = $this->createEntityChainBelongingToUser($this->user)['page']; - $commentId = $this->asAdmin()->addComment($ownPage); + $this->asAdmin()->addComment($ownPage); + /** @var Comment $comment */ + $comment = $ownPage->comments()->latest()->first(); // no comment-delete-all - $this->actingAs($this->user)->deleteComment($commentId); - $this->assertResponseStatus(403); + $this->actingAs($this->user)->deleteComment($comment)->assertStatus(403); $this->giveUserPermissions($this->user, ['comment-delete-all']); // now has comment-delete-all - $this->actingAs($this->user)->deleteComment($commentId); - $this->assertResponseStatus(200); + $this->actingAs($this->user)->deleteComment($comment)->assertOk(); } - private function addComment($page) + private function addComment(Page $page): TestResponse { $comment = factory(Comment::class)->make(); - $url = "/comment/$page->id"; - $request = [ - 'text' => $comment->text, - 'html' => $comment->html, - ]; - - $this->postJson($url, $request); - $comment = $page->comments()->first(); - - return $comment === null ? null : $comment->id; + return $this->postJson("/comment/$page->id", $comment->only('text', 'html')); } - private function updateComment($commentId) + private function updateComment(Comment $comment): TestResponse { - $comment = factory(Comment::class)->make(); - $url = "/comment/$commentId"; - $request = [ - 'text' => $comment->text, - 'html' => $comment->html, - ]; - - return $this->putJson($url, $request); + $commentData = factory(Comment::class)->make(); + return $this->putJson("/comment/{$comment->id}", $commentData->only('text', 'html')); } - private function deleteComment($commentId) + private function deleteComment(Comment $comment): TestResponse { - $url = '/comment/' . $commentId; - - return $this->json('DELETE', $url); + return $this->json('DELETE', '/comment/' . $comment->id); } } From 6454e246574a6bdb75a5a908a29a06214af7cc60 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 18 Sep 2021 21:15:39 +0100 Subject: [PATCH 8/9] Removed browserkit testing from project Converted last bits of the roles tests and removed dependancies. Updated other PHP dependancies at the same time. --- composer.json | 6 +- composer.lock | 342 +++++++++++----------- tests/BrowserKitTest.php | 185 ------------ tests/Permissions/RolesTest.php | 490 +++++++++++++++++--------------- 4 files changed, 423 insertions(+), 600 deletions(-) delete mode 100644 tests/BrowserKitTest.php diff --git a/composer.json b/composer.json index 7362a085d..31ecbef84 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "facade/ignition": "^1.16.4", "fideloper/proxy": "^4.4.1", "intervention/image": "^2.5.1", - "laravel/framework": "^6.20.16", + "laravel/framework": "^6.20.33", "laravel/socialite": "^5.1", "league/commonmark": "^1.5", "league/flysystem-aws-s3-v3": "^1.0.29", @@ -41,9 +41,9 @@ "barryvdh/laravel-debugbar": "^3.5.1", "barryvdh/laravel-ide-helper": "^2.8.2", "fakerphp/faker": "^1.13.0", - "laravel/browser-kit-testing": "^5.2", "mockery/mockery": "^1.3.3", - "phpunit/phpunit": "^9.5.3" + "phpunit/phpunit": "^9.5.3", + "symfony/dom-crawler": "^5.3" }, "autoload": { "classmap": [ diff --git a/composer.lock b/composer.lock index b2ad6b691..d267d13d6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,23 +4,74 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4d845f3c8b77c8d73bf92c9223ddd805", + "content-hash": "10825887b8f66d1d412b92bcc0ca864f", "packages": [ { - "name": "aws/aws-sdk-php", - "version": "3.191.8", + "name": "aws/aws-crt-php", + "version": "v1.0.2", "source": { "type": "git", - "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "949feb83cc0db46f07b12aa3128d47be3b9cca63" + "url": "https://github.com/awslabs/aws-crt-php.git", + "reference": "3942776a8c99209908ee0b287746263725685732" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/949feb83cc0db46f07b12aa3128d47be3b9cca63", - "reference": "949feb83cc0db46f07b12aa3128d47be3b9cca63", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/3942776a8c99209908ee0b287746263725685732", + "reference": "3942776a8c99209908ee0b287746263725685732", "shasum": "" }, "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|^5.4.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "AWS SDK Common Runtime Team", + "email": "aws-sdk-common-runtime@amazon.com" + } + ], + "description": "AWS Common Runtime for PHP", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "crt", + "sdk" + ], + "support": { + "issues": "https://github.com/awslabs/aws-crt-php/issues", + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.0.2" + }, + "time": "2021-09-03T22:57:30+00:00" + }, + { + "name": "aws/aws-sdk-php", + "version": "3.194.1", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "67bdee05acef9e8ad60098090996690b49babd09" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/67bdee05acef9e8ad60098090996690b49babd09", + "reference": "67bdee05acef9e8ad60098090996690b49babd09", + "shasum": "" + }, + "require": { + "aws/aws-crt-php": "^1.0.2", "ext-json": "*", "ext-pcre": "*", "ext-simplexml": "*", @@ -92,9 +143,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.191.8" + "source": "https://github.com/aws/aws-sdk-php/tree/3.194.1" }, - "time": "2021-08-31T18:18:02+00:00" + "time": "2021-09-17T18:15:42+00:00" }, { "name": "bacon/bacon-qr-code", @@ -428,16 +479,16 @@ }, { "name": "doctrine/dbal", - "version": "2.13.2", + "version": "2.13.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "8dd39d2ead4409ce652fd4f02621060f009ea5e4" + "reference": "0d7adf4cadfee6f70850e5b163e6cdd706417838" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/8dd39d2ead4409ce652fd4f02621060f009ea5e4", - "reference": "8dd39d2ead4409ce652fd4f02621060f009ea5e4", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/0d7adf4cadfee6f70850e5b163e6cdd706417838", + "reference": "0d7adf4cadfee6f70850e5b163e6cdd706417838", "shasum": "" }, "require": { @@ -449,13 +500,14 @@ }, "require-dev": { "doctrine/coding-standard": "9.0.0", - "jetbrains/phpstorm-stubs": "2020.2", - "phpstan/phpstan": "0.12.81", + "jetbrains/phpstorm-stubs": "2021.1", + "phpstan/phpstan": "0.12.96", "phpunit/phpunit": "^7.5.20|^8.5|9.5.5", + "psalm/plugin-phpunit": "0.16.1", "squizlabs/php_codesniffer": "3.6.0", "symfony/cache": "^4.4", "symfony/console": "^2.0.5|^3.0|^4.0|^5.0", - "vimeo/psalm": "4.6.4" + "vimeo/psalm": "4.10.0" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." @@ -516,7 +568,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/2.13.2" + "source": "https://github.com/doctrine/dbal/tree/2.13.3" }, "funding": [ { @@ -532,7 +584,7 @@ "type": "tidelift" } ], - "time": "2021-06-18T21:48:39+00:00" + "time": "2021-09-12T19:11:48+00:00" }, { "name": "doctrine/deprecations", @@ -1052,16 +1104,16 @@ }, { "name": "facade/flare-client-php", - "version": "1.8.1", + "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/facade/flare-client-php.git", - "reference": "47b639dc02bcfdfc4ebb83de703856fa01e35f5f" + "reference": "b2adf1512755637d0cef4f7d1b54301325ac78ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/flare-client-php/zipball/47b639dc02bcfdfc4ebb83de703856fa01e35f5f", - "reference": "47b639dc02bcfdfc4ebb83de703856fa01e35f5f", + "url": "https://api.github.com/repos/facade/flare-client-php/zipball/b2adf1512755637d0cef4f7d1b54301325ac78ed", + "reference": "b2adf1512755637d0cef4f7d1b54301325ac78ed", "shasum": "" }, "require": { @@ -1105,7 +1157,7 @@ ], "support": { "issues": "https://github.com/facade/flare-client-php/issues", - "source": "https://github.com/facade/flare-client-php/tree/1.8.1" + "source": "https://github.com/facade/flare-client-php/tree/1.9.1" }, "funding": [ { @@ -1113,7 +1165,7 @@ "type": "github" } ], - "time": "2021-05-31T19:23:29+00:00" + "time": "2021-09-13T12:16:46+00:00" }, { "name": "facade/ignition", @@ -1762,16 +1814,16 @@ }, { "name": "laravel/framework", - "version": "v6.20.33", + "version": "v6.20.34", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "49aa211f2dd1d419bfd9dbbd6f590d57a1dfda58" + "reference": "72a6da88c90cee793513b3fe49cf0fcb368eefa0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/49aa211f2dd1d419bfd9dbbd6f590d57a1dfda58", - "reference": "49aa211f2dd1d419bfd9dbbd6f590d57a1dfda58", + "url": "https://api.github.com/repos/laravel/framework/zipball/72a6da88c90cee793513b3fe49cf0fcb368eefa0", + "reference": "72a6da88c90cee793513b3fe49cf0fcb368eefa0", "shasum": "" }, "require": { @@ -1911,7 +1963,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-08-31T13:56:36+00:00" + "time": "2021-09-07T13:28:55+00:00" }, { "name": "laravel/socialite", @@ -2230,16 +2282,16 @@ }, { "name": "league/html-to-markdown", - "version": "5.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/thephpleague/html-to-markdown.git", - "reference": "c4dbebbebe0fe454b6b38e6c683a977615bd7dc2" + "reference": "e5600a2c5ce7b7571b16732c7086940f56f7abec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/c4dbebbebe0fe454b6b38e6c683a977615bd7dc2", - "reference": "c4dbebbebe0fe454b6b38e6c683a977615bd7dc2", + "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/e5600a2c5ce7b7571b16732c7086940f56f7abec", + "reference": "e5600a2c5ce7b7571b16732c7086940f56f7abec", "shasum": "" }, "require": { @@ -2295,7 +2347,7 @@ ], "support": { "issues": "https://github.com/thephpleague/html-to-markdown/issues", - "source": "https://github.com/thephpleague/html-to-markdown/tree/5.0.0" + "source": "https://github.com/thephpleague/html-to-markdown/tree/5.0.1" }, "funding": [ { @@ -2311,11 +2363,11 @@ "type": "github" }, { - "url": "https://www.patreon.com/colinodell", - "type": "patreon" + "url": "https://tidelift.com/funding/github/packagist/league/html-to-markdown", + "type": "tidelift" } ], - "time": "2021-03-29T01:29:08+00:00" + "time": "2021-09-17T20:00:27+00:00" }, { "name": "league/mime-type-detection", @@ -2451,24 +2503,24 @@ }, { "name": "monolog/monolog", - "version": "2.3.2", + "version": "2.3.4", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "71312564759a7db5b789296369c1a264efc43aad" + "reference": "437e7a1c50044b92773b361af77620efb76fff59" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/71312564759a7db5b789296369c1a264efc43aad", - "reference": "71312564759a7db5b789296369c1a264efc43aad", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/437e7a1c50044b92773b361af77620efb76fff59", + "reference": "437e7a1c50044b92773b361af77620efb76fff59", "shasum": "" }, "require": { "php": ">=7.2", - "psr/log": "^1.0.1" + "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "provide": { - "psr/log-implementation": "1.0.0" + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" }, "require-dev": { "aws/aws-sdk-php": "^2.4.9 || ^3.0", @@ -2483,7 +2535,7 @@ "phpunit/phpunit": "^8.5", "predis/predis": "^1.1", "rollbar/rollbar": "^1.3", - "ruflin/elastica": ">=0.90 <7.0.1", + "ruflin/elastica": ">=0.90@dev", "swiftmailer/swiftmailer": "^5.3|^6.0" }, "suggest": { @@ -2491,8 +2543,11 @@ "doctrine/couchdb": "Allow sending log messages to a CouchDB server", "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", "ext-mbstring": "Allow to work properly with unicode symbols", "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", @@ -2531,7 +2586,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/2.3.2" + "source": "https://github.com/Seldaek/monolog/tree/2.3.4" }, "funding": [ { @@ -2543,7 +2598,7 @@ "type": "tidelift" } ], - "time": "2021-07-23T07:42:52+00:00" + "time": "2021-09-15T11:27:21+00:00" }, { "name": "mtdowling/jmespath.php", @@ -2608,16 +2663,16 @@ }, { "name": "nesbot/carbon", - "version": "2.52.0", + "version": "2.53.1", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "369c0e2737c56a0f39c946dd261855255a6fccbe" + "reference": "f4655858a784988f880c1b8c7feabbf02dfdf045" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/369c0e2737c56a0f39c946dd261855255a6fccbe", - "reference": "369c0e2737c56a0f39c946dd261855255a6fccbe", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f4655858a784988f880c1b8c7feabbf02dfdf045", + "reference": "f4655858a784988f880c1b8c7feabbf02dfdf045", "shasum": "" }, "require": { @@ -2629,7 +2684,7 @@ }, "require-dev": { "doctrine/orm": "^2.7", - "friendsofphp/php-cs-fixer": "^2.14 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.0", "kylekatarnls/multi-tester": "^2.0", "phpmd/phpmd": "^2.9", "phpstan/extension-installer": "^1.0", @@ -2698,7 +2753,7 @@ "type": "tidelift" } ], - "time": "2021-08-14T19:10:52+00:00" + "time": "2021-09-06T09:29:23+00:00" }, { "name": "nunomaduro/collision", @@ -4492,20 +4547,20 @@ }, { "name": "symfony/css-selector", - "version": "v4.4.27", + "version": "v5.3.4", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "5194f18bd80d106f11efa8f7cd0fbdcc3af96ce6" + "reference": "7fb120adc7f600a59027775b224c13a33530dd90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/5194f18bd80d106f11efa8f7cd0fbdcc3af96ce6", - "reference": "5194f18bd80d106f11efa8f7cd0fbdcc3af96ce6", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/7fb120adc7f600a59027775b224c13a33530dd90", + "reference": "7fb120adc7f600a59027775b224c13a33530dd90", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "symfony/polyfill-php80": "^1.16" }, "type": "library", @@ -4538,7 +4593,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v4.4.27" + "source": "https://github.com/symfony/css-selector/tree/v5.3.4" }, "funding": [ { @@ -4554,7 +4609,7 @@ "type": "tidelift" } ], - "time": "2021-07-21T12:19:41+00:00" + "time": "2021-07-21T12:38:00+00:00" }, { "name": "symfony/debug", @@ -6884,16 +6939,16 @@ }, { "name": "composer/composer", - "version": "2.1.6", + "version": "2.1.8", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "e5cac5f9d2354d08b67f1d21c664ae70d748c603" + "reference": "24d38e9686092de05214cafa187dc282a5d89497" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/e5cac5f9d2354d08b67f1d21c664ae70d748c603", - "reference": "e5cac5f9d2354d08b67f1d21c664ae70d748c603", + "url": "https://api.github.com/repos/composer/composer/zipball/24d38e9686092de05214cafa187dc282a5d89497", + "reference": "24d38e9686092de05214cafa187dc282a5d89497", "shasum": "" }, "require": { @@ -6962,7 +7017,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", - "source": "https://github.com/composer/composer/tree/2.1.6" + "source": "https://github.com/composer/composer/tree/2.1.8" }, "funding": [ { @@ -6978,7 +7033,7 @@ "type": "tidelift" } ], - "time": "2021-08-19T15:11:08+00:00" + "time": "2021-09-15T11:55:15+00:00" }, { "name": "composer/metadata-minifier", @@ -7344,21 +7399,21 @@ }, { "name": "fakerphp/faker", - "version": "v1.15.0", + "version": "v1.16.0", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "89c6201c74db25fa759ff16e78a4d8f32547770e" + "reference": "271d384d216e5e5c468a6b28feedf95d49f83b35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/89c6201c74db25fa759ff16e78a4d8f32547770e", - "reference": "89c6201c74db25fa759ff16e78a4d8f32547770e", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/271d384d216e5e5c468a6b28feedf95d49f83b35", + "reference": "271d384d216e5e5c468a6b28feedf95d49f83b35", "shasum": "" }, "require": { "php": "^7.1 || ^8.0", - "psr/container": "^1.0", + "psr/container": "^1.0 || ^2.0", "symfony/deprecation-contracts": "^2.2" }, "conflict": { @@ -7378,7 +7433,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "v1.15-dev" + "dev-main": "v1.16-dev" } }, "autoload": { @@ -7403,9 +7458,9 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.15.0" + "source": "https://github.com/FakerPHP/Faker/tree/v1.16.0" }, - "time": "2021-07-06T20:39:40+00:00" + "time": "2021-09-06T14:53:37+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -7528,71 +7583,6 @@ }, "time": "2021-07-22T09:24:00+00:00" }, - { - "name": "laravel/browser-kit-testing", - "version": "v5.2.0", - "source": { - "type": "git", - "url": "https://github.com/laravel/browser-kit-testing.git", - "reference": "fa0efb279c009e2a276f934f8aff946caf66edc7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/browser-kit-testing/zipball/fa0efb279c009e2a276f934f8aff946caf66edc7", - "reference": "fa0efb279c009e2a276f934f8aff946caf66edc7", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "illuminate/contracts": "~5.7.0|~5.8.0|^6.0", - "illuminate/database": "~5.7.0|~5.8.0|^6.0", - "illuminate/http": "~5.7.0|~5.8.0|^6.0", - "illuminate/support": "~5.7.0|~5.8.0|^6.0", - "mockery/mockery": "^1.0", - "php": "^7.1.3|^8.0", - "phpunit/phpunit": "^7.5|^8.0|^9.3", - "symfony/console": "^4.2", - "symfony/css-selector": "^4.2", - "symfony/dom-crawler": "^4.2", - "symfony/http-foundation": "^4.2", - "symfony/http-kernel": "^4.2" - }, - "require-dev": { - "laravel/framework": "~5.7.0|~5.8.0|^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "Laravel\\BrowserKitTesting\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Provides backwards compatibility for BrowserKit testing in the latest Laravel release.", - "keywords": [ - "laravel", - "testing" - ], - "support": { - "issues": "https://github.com/laravel/browser-kit-testing/issues", - "source": "https://github.com/laravel/browser-kit-testing/tree/v5.2.0" - }, - "time": "2020-10-30T08:49:09+00:00" - }, { "name": "maximebf/debugbar", "version": "v1.17.1", @@ -7660,16 +7650,16 @@ }, { "name": "mockery/mockery", - "version": "1.4.3", + "version": "1.4.4", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "d1339f64479af1bee0e82a0413813fe5345a54ea" + "reference": "e01123a0e847d52d186c5eb4b9bf58b0c6d00346" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/d1339f64479af1bee0e82a0413813fe5345a54ea", - "reference": "d1339f64479af1bee0e82a0413813fe5345a54ea", + "url": "https://api.github.com/repos/mockery/mockery/zipball/e01123a0e847d52d186c5eb4b9bf58b0c6d00346", + "reference": "e01123a0e847d52d186c5eb4b9bf58b0c6d00346", "shasum": "" }, "require": { @@ -7726,9 +7716,9 @@ ], "support": { "issues": "https://github.com/mockery/mockery/issues", - "source": "https://github.com/mockery/mockery/tree/1.4.3" + "source": "https://github.com/mockery/mockery/tree/1.4.4" }, - "time": "2021-02-24T09:51:49+00:00" + "time": "2021-09-13T15:28:59+00:00" }, { "name": "myclabs/deep-copy", @@ -8066,16 +8056,16 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" + "reference": "30f38bffc6f24293dadd1823936372dfa9e86e2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/30f38bffc6f24293dadd1823936372dfa9e86e2f", + "reference": "30f38bffc6f24293dadd1823936372dfa9e86e2f", "shasum": "" }, "require": { @@ -8083,7 +8073,8 @@ "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "ext-tokenizer": "*" + "ext-tokenizer": "*", + "psalm/phar": "^4.8" }, "type": "library", "extra": { @@ -8109,39 +8100,39 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.5.0" }, - "time": "2020-09-17T18:55:26+00:00" + "time": "2021-09-17T15:28:14+00:00" }, { "name": "phpspec/prophecy", - "version": "1.13.0", + "version": "1.14.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea" + "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be1996ed8adc35c3fd795488a653f4b518be70ea", - "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e", + "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e", "shasum": "" }, "require": { "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.1", + "php": "^7.2 || ~8.0, <8.2", "phpdocumentor/reflection-docblock": "^5.2", "sebastian/comparator": "^3.0 || ^4.0", "sebastian/recursion-context": "^3.0 || ^4.0" }, "require-dev": { - "phpspec/phpspec": "^6.0", + "phpspec/phpspec": "^6.0 || ^7.0", "phpunit/phpunit": "^8.0 || ^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { @@ -8176,29 +8167,29 @@ ], "support": { "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/1.13.0" + "source": "https://github.com/phpspec/prophecy/tree/1.14.0" }, - "time": "2021-03-17T13:42:18+00:00" + "time": "2021-09-10T09:02:12+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.6", + "version": "9.2.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f6293e1b30a2354e8428e004689671b83871edde" + "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f6293e1b30a2354e8428e004689671b83871edde", - "reference": "f6293e1b30a2354e8428e004689671b83871edde", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d4c798ed8d51506800b441f7a13ecb0f76f12218", + "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.10.2", + "nikic/php-parser": "^4.12.0", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -8247,7 +8238,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.6" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.7" }, "funding": [ { @@ -8255,7 +8246,7 @@ "type": "github" } ], - "time": "2021-03-28T07:26:59+00:00" + "time": "2021-09-17T05:39:03+00:00" }, { "name": "phpunit/php-file-iterator", @@ -9728,20 +9719,21 @@ }, { "name": "symfony/dom-crawler", - "version": "v4.4.30", + "version": "v5.3.7", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "4632ae3567746c7e915c33c67a2fb6ab746090c4" + "reference": "c7eef3a60ccfdd8eafe07f81652e769ac9c7146c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/4632ae3567746c7e915c33c67a2fb6ab746090c4", - "reference": "4632ae3567746c7e915c33c67a2fb6ab746090c4", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/c7eef3a60ccfdd8eafe07f81652e769ac9c7146c", + "reference": "c7eef3a60ccfdd8eafe07f81652e769ac9c7146c", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php80": "^1.16" @@ -9751,7 +9743,7 @@ }, "require-dev": { "masterminds/html5": "^2.6", - "symfony/css-selector": "^3.4|^4.0|^5.0" + "symfony/css-selector": "^4.4|^5.0" }, "suggest": { "symfony/css-selector": "" @@ -9782,7 +9774,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v4.4.30" + "source": "https://github.com/symfony/dom-crawler/tree/v5.3.7" }, "funding": [ { @@ -9798,7 +9790,7 @@ "type": "tidelift" } ], - "time": "2021-08-28T15:40:01+00:00" + "time": "2021-08-29T19:32:13+00:00" }, { "name": "symfony/filesystem", diff --git a/tests/BrowserKitTest.php b/tests/BrowserKitTest.php deleted file mode 100644 index a4f12d5ea..000000000 --- a/tests/BrowserKitTest.php +++ /dev/null @@ -1,185 +0,0 @@ -make(Kernel::class)->bootstrap(); - - return $app; - } - - /** - * Quickly sets an array of settings. - * - * @param $settingsArray - */ - protected function setSettings($settingsArray) - { - $settings = app(SettingService::class); - foreach ($settingsArray as $key => $value) { - $settings->put($key, $value); - } - } - - /** - * Helper for updating entity permissions. - * - * @param Entity $entity - */ - protected function updateEntityPermissions(Entity $entity) - { - $restrictionService = $this->app[PermissionService::class]; - $restrictionService->buildJointPermissionsForEntity($entity); - } - - /** - * Assert that a given string is seen inside an element. - * - * @param bool|string|null $element - * @param int $position - * @param string $text - * @param bool $negate - * - * @return $this - */ - protected function seeInNthElement($element, $position, $text, $negate = false) - { - $method = $negate ? 'assertDoesNotMatchRegularExpression' : 'assertMatchesRegularExpression'; - - $rawPattern = preg_quote($text, '/'); - - $escapedPattern = preg_quote(e($text), '/'); - - $content = $this->crawler->filter($element)->eq($position)->html(); - - $pattern = $rawPattern == $escapedPattern - ? $rawPattern : "({$rawPattern}|{$escapedPattern})"; - - $this->$method("/$pattern/i", $content); - - return $this; - } - - /** - * Assert that the current page matches a given URI. - * - * @param string $uri - * - * @return $this - */ - protected function seePageUrlIs($uri) - { - $this->assertEquals( - $uri, - $this->currentUri, - "Did not land on expected page [{$uri}].\n" - ); - - return $this; - } - - /** - * Do a forced visit that does not error out on exception. - * - * @param string $uri - * @param array $parameters - * @param array $cookies - * @param array $files - * - * @return $this - */ - protected function forceVisit($uri, $parameters = [], $cookies = [], $files = []) - { - $method = 'GET'; - $uri = $this->prepareUrlForRequest($uri); - $this->call($method, $uri, $parameters, $cookies, $files); - $this->clearInputs()->followRedirects(); - $this->currentUri = $this->app->make('request')->fullUrl(); - $this->crawler = new Crawler($this->response->getContent(), $uri); - - return $this; - } - - /** - * Click the text within the selected element. - * - * @param $parentElement - * @param $linkText - * - * @return $this - */ - protected function clickInElement($parentElement, $linkText) - { - $elem = $this->crawler->filter($parentElement); - $link = $elem->selectLink($linkText); - $this->visit($link->link()->getUri()); - - return $this; - } - - /** - * Check if the page contains the given element. - * - * @param string $selector - */ - protected function pageHasElement($selector) - { - $elements = $this->crawler->filter($selector); - $this->assertTrue(count($elements) > 0, 'The page does not contain an element matching ' . $selector); - - return $this; - } - - /** - * Check if the page contains the given element. - * - * @param string $selector - */ - protected function pageNotHasElement($selector) - { - $elements = $this->crawler->filter($selector); - $this->assertFalse(count($elements) > 0, 'The page contains ' . count($elements) . ' elements matching ' . $selector); - - return $this; - } -} diff --git a/tests/Permissions/RolesTest.php b/tests/Permissions/RolesTest.php index c9c3195a9..5689caf7b 100644 --- a/tests/Permissions/RolesTest.php +++ b/tests/Permissions/RolesTest.php @@ -2,12 +2,14 @@ namespace Tests\Permissions; +use BookStack\Actions\ActivityType; use BookStack\Actions\Comment; use BookStack\Auth\Role; use BookStack\Auth\User; use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Bookshelf; use BookStack\Entities\Models\Chapter; +use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Page; use BookStack\Uploads\Image; use Tests\TestCase; @@ -56,70 +58,104 @@ class RolesTest extends TestCase $testRoleUpdateName = 'An Super Updated role'; // Creation - $this->asAdmin()->get('/settings') - ->click('Roles') - ->seePageIs('/settings/roles') - ->click('Create New Role') - ->type('Test Role', 'display_name') - ->type('A little test description', 'description') - ->press('Save Role') - ->assertDatabaseHas('roles', ['display_name' => $testRoleName, 'description' => $testRoleDesc, 'mfa_enforced' => false]) - ->seePageIs('/settings/roles'); + $resp = $this->asAdmin()->get('/settings'); + $resp->assertElementContains('a[href="' . url('/settings/roles') . '"]', 'Roles'); + + $resp = $this->get('/settings/roles'); + $resp->assertElementContains('a[href="' . url('/settings/roles/new') . '"]', 'Create New Role'); + + $resp = $this->get('/settings/roles/new'); + $resp->assertElementContains('form[action="' . url('/settings/roles/new') . '"]', 'Save Role'); + + $resp = $this->post('/settings/roles/new', [ + 'display_name' => $testRoleName, + 'description' => $testRoleDesc, + ]); + $resp->assertRedirect('/settings/roles'); + + $resp = $this->get('/settings/roles'); + $resp->assertSee($testRoleName); + $resp->assertSee($testRoleDesc); + $this->assertDatabaseHas('roles', [ + 'display_name' => $testRoleName, + 'description' => $testRoleDesc, + 'mfa_enforced' => false, + ]); + + /** @var Role $role */ + $role = Role::query()->where('display_name', '=', $testRoleName)->first(); // Updating - $this->asAdmin()->get('/settings/roles') - ->assertSee($testRoleDesc) - ->click($testRoleName) - ->type($testRoleUpdateName, '#display_name') - ->check('#mfa_enforced') - ->press('Save Role') - ->assertDatabaseHas('roles', ['display_name' => $testRoleUpdateName, 'description' => $testRoleDesc, 'mfa_enforced' => true]) - ->seePageIs('/settings/roles'); + $resp = $this->get('/settings/roles/' . $role->id); + $resp->assertSee($testRoleName); + $resp->assertSee($testRoleDesc); + $resp->assertElementContains('form[action="' . url('/settings/roles/' . $role->id) . '"]', 'Save Role'); + + $resp = $this->put('/settings/roles/' . $role->id, [ + 'display_name' => $testRoleUpdateName, + 'description' => $testRoleDesc, + 'mfa_enforced' => 'true', + ]); + $resp->assertRedirect('/settings/roles'); + $this->assertDatabaseHas('roles', [ + 'display_name' => $testRoleUpdateName, + 'description' => $testRoleDesc, + 'mfa_enforced' => true, + ]); // Deleting - $this->asAdmin()->get('/settings/roles') - ->click($testRoleUpdateName) - ->click('Delete Role') - ->assertSee($testRoleUpdateName) - ->press('Confirm') - ->seePageIs('/settings/roles') - ->assertDontSee($testRoleUpdateName); + $resp = $this->get('/settings/roles/' . $role->id); + $resp->assertElementContains('a[href="' . url("/settings/roles/delete/$role->id") . '"]', 'Delete Role'); + + $resp = $this->get("/settings/roles/delete/$role->id"); + $resp->assertSee($testRoleUpdateName); + $resp->assertElementContains('form[action="' . url("/settings/roles/delete/$role->id") . '"]', 'Confirm'); + + $resp = $this->delete("/settings/roles/delete/$role->id"); + $resp->assertRedirect('/settings/roles'); + $this->get('/settings/roles')->assertSee('Role successfully deleted'); + $this->assertActivityExists(ActivityType::ROLE_DELETE); } public function test_admin_role_cannot_be_removed_if_user_last_admin() { - $adminRole = Role::where('system_name', '=', 'admin')->first(); + /** @var Role $adminRole */ + $adminRole = Role::query()->where('system_name', '=', 'admin')->first(); $adminUser = $this->getAdmin(); $adminRole->users()->where('id', '!=', $adminUser->id)->delete(); - $this->assertEquals($adminRole->users()->count(), 1); + $this->assertEquals(1, $adminRole->users()->count()); $viewerRole = $this->getViewer()->roles()->first(); $editUrl = '/settings/users/' . $adminUser->id; - $this->actingAs($adminUser)->put($editUrl, [ + $resp = $this->actingAs($adminUser)->put($editUrl, [ 'name' => $adminUser->name, 'email' => $adminUser->email, 'roles' => [ 'viewer' => strval($viewerRole->id), ], - ])->followRedirects(); + ]); - $this->seePageIs($editUrl); - $this->assertSee('This user is the only user assigned to the administrator role'); + $resp->assertRedirect($editUrl); + + $resp = $this->get($editUrl); + $resp->assertSee('This user is the only user assigned to the administrator role'); } public function test_migrate_users_on_delete_works() { + /** @var Role $roleA */ $roleA = Role::query()->create(['display_name' => 'Delete Test A']); + /** @var Role $roleB */ $roleB = Role::query()->create(['display_name' => 'Delete Test B']); $this->user->attachRole($roleB); $this->assertCount(0, $roleA->users()->get()); $this->assertCount(1, $roleB->users()->get()); - $deletePage = $this->asAdmin()->get("/settings/roles/delete/{$roleB->id}"); + $deletePage = $this->asAdmin()->get("/settings/roles/delete/$roleB->id"); $deletePage->assertElementExists('select[name=migrate_role_id]'); - $this->asAdmin()->delete("/settings/roles/delete/{$roleB->id}", [ + $this->asAdmin()->delete("/settings/roles/delete/$roleB->id", [ 'migrate_role_id' => $roleA->id, ]); @@ -129,11 +165,9 @@ class RolesTest extends TestCase public function test_manage_user_permission() { - $this->actingAs($this->user)->get('/settings/users') - ->seePageIs('/'); + $this->actingAs($this->user)->get('/settings/users')->assertRedirect('/'); $this->giveUserPermissions($this->user, ['users-manage']); - $this->actingAs($this->user)->get('/settings/users') - ->seePageIs('/settings/users'); + $this->actingAs($this->user)->get('/settings/users')->assertOk(); } public function test_manage_users_permission_shows_link_in_header_if_does_not_have_settings_manage_permision() @@ -185,35 +219,41 @@ class RolesTest extends TestCase public function test_user_roles_manage_permission() { - $this->actingAs($this->user)->get('/settings/roles') - ->seePageIs('/')->get('/settings/roles/1')->seePageIs('/'); + $this->actingAs($this->user)->get('/settings/roles')->assertRedirect('/'); + $this->get('/settings/roles/1')->assertRedirect('/'); $this->giveUserPermissions($this->user, ['user-roles-manage']); - $this->actingAs($this->user)->get('/settings/roles') - ->seePageIs('/settings/roles')->click('Admin') - ->assertSee('Edit Role'); + $this->actingAs($this->user)->get('/settings/roles')->assertOk(); + $this->get('/settings/roles/1') + ->assertOk() + ->assertSee('Admin'); } public function test_settings_manage_permission() { - $this->actingAs($this->user)->get('/settings') - ->seePageIs('/'); + $this->actingAs($this->user)->get('/settings')->assertRedirect('/'); $this->giveUserPermissions($this->user, ['settings-manage']); - $this->actingAs($this->user)->get('/settings') - ->seePageIs('/settings')->press('Save Settings')->assertSee('Settings Saved'); + $this->get('/settings')->assertOk(); + + $resp = $this->post('/settings', []); + $resp->assertRedirect('/settings'); + $resp = $this->get('/settings'); + $resp->assertSee('Settings saved'); } public function test_restrictions_manage_all_permission() { - $page = Page::take(1)->get()->first(); - $this->actingAs($this->user)->get($page->getUrl()) - ->assertDontSee('Permissions') - ->get($page->getUrl() . '/permissions') - ->seePageIs('/'); + $page = Page::query()->get()->first(); + + $this->actingAs($this->user)->get($page->getUrl())->assertDontSee('Permissions'); + $this->get($page->getUrl('/permissions'))->assertRedirect('/'); + $this->giveUserPermissions($this->user, ['restrictions-manage-all']); - $this->actingAs($this->user)->get($page->getUrl()) - ->assertSee('Permissions') - ->click('Permissions') - ->assertSee('Page Permissions')->seePageIs($page->getUrl() . '/permissions'); + + $this->actingAs($this->user)->get($page->getUrl())->assertSee('Permissions'); + + $this->get($page->getUrl('/permissions')) + ->assertOk() + ->assertSee('Page Permissions'); } public function test_restrictions_manage_own_permission() @@ -230,43 +270,33 @@ class RolesTest extends TestCase $page->save(); // Check can't restrict other's content - $this->actingAs($this->user)->get($otherUsersPage->getUrl()) - ->assertDontSee('Permissions') - ->get($otherUsersPage->getUrl() . '/permissions') - ->seePageIs('/'); + $this->actingAs($this->user)->get($otherUsersPage->getUrl())->assertDontSee('Permissions'); + $this->get($otherUsersPage->getUrl('/permissions'))->assertRedirect('/'); + // Check can't restrict own content - $this->actingAs($this->user)->get($page->getUrl()) - ->assertDontSee('Permissions') - ->get($page->getUrl() . '/permissions') - ->seePageIs('/'); + $this->actingAs($this->user)->get($page->getUrl())->assertDontSee('Permissions'); + $this->get($page->getUrl('/permissions'))->assertRedirect('/'); $this->giveUserPermissions($this->user, ['restrictions-manage-own']); // Check can't restrict other's content - $this->actingAs($this->user)->get($otherUsersPage->getUrl()) - ->assertDontSee('Permissions') - ->get($otherUsersPage->getUrl() . '/permissions') - ->seePageIs('/'); + $this->actingAs($this->user)->get($otherUsersPage->getUrl())->assertDontSee('Permissions'); + $this->get($otherUsersPage->getUrl('/permissions'))->assertRedirect(); + // Check can restrict own content - $this->actingAs($this->user)->get($page->getUrl()) - ->assertSee('Permissions') - ->click('Permissions') - ->seePageIs($page->getUrl() . '/permissions'); + $this->actingAs($this->user)->get($page->getUrl())->assertSee('Permissions'); + $this->get($page->getUrl('/permissions'))->assertOk(); } /** * Check a standard entity access permission. - * - * @param string $permission - * @param array $accessUrls Urls that are only accessible after having the permission - * @param array $visibles Check this text, In the buttons toolbar, is only visible with the permission */ - private function checkAccessPermission($permission, $accessUrls = [], $visibles = []) + private function checkAccessPermission(string $permission, array $accessUrls = [], array $visibles = []) { foreach ($accessUrls as $url) { - $this->actingAs($this->user)->get($url) - ->seePageIs('/'); + $this->actingAs($this->user)->get($url)->assertRedirect('/'); } + foreach ($visibles as $url => $text) { $this->actingAs($this->user)->get($url) ->assertElementNotContains('.action-buttons', $text); @@ -275,12 +305,10 @@ class RolesTest extends TestCase $this->giveUserPermissions($this->user, [$permission]); foreach ($accessUrls as $url) { - $this->actingAs($this->user)->get($url) - ->seePageIs($url); + $this->actingAs($this->user)->get($url)->assertOk(); } foreach ($visibles as $url => $text) { - $this->actingAs($this->user)->get($url) - ->assertSee($text); + $this->actingAs($this->user)->get($url)->assertSee($text); } } @@ -292,11 +320,10 @@ class RolesTest extends TestCase '/shelves' => 'New Shelf', ]); - $this->get('/create-shelf') - ->type('test shelf', 'name') - ->type('shelf desc', 'description') - ->press('Save Shelf') - ->seePageIs('/shelves/test-shelf'); + $this->post('/shelves', [ + 'name' => 'test shelf', + 'description' => 'shelf desc', + ])->assertRedirect('/shelves/test-shelf'); } public function test_bookshelves_edit_own_permission() @@ -313,10 +340,8 @@ class RolesTest extends TestCase $ownShelf->getUrl() => 'Edit', ]); - $this->get($otherShelf->getUrl()) - ->assertElementNotContains('.action-buttons', 'Edit') - ->get($otherShelf->getUrl('/edit')) - ->seePageIs('/'); + $this->get($otherShelf->getUrl())->assertElementNotContains('.action-buttons', 'Edit'); + $this->get($otherShelf->getUrl('/edit'))->assertRedirect('/'); } public function test_bookshelves_edit_all_permission() @@ -345,14 +370,12 @@ class RolesTest extends TestCase $ownShelf->getUrl() => 'Delete', ]); - $this->get($otherShelf->getUrl()) - ->assertElementNotContains('.action-buttons', 'Delete') - ->get($otherShelf->getUrl('/delete')) - ->seePageIs('/'); - $this->get($ownShelf->getUrl())->get($ownShelf->getUrl('/delete')) - ->press('Confirm') - ->seePageIs('/shelves') - ->assertDontSee($ownShelf->name); + $this->get($otherShelf->getUrl())->assertElementNotContains('.action-buttons', 'Delete'); + $this->get($otherShelf->getUrl('/delete'))->assertRedirect('/'); + + $this->get($ownShelf->getUrl()); + $this->delete($ownShelf->getUrl())->assertRedirect('/shelves'); + $this->get('/shelves')->assertDontSee($ownShelf->name); } public function test_bookshelves_delete_all_permission() @@ -366,10 +389,8 @@ class RolesTest extends TestCase $otherShelf->getUrl() => 'Delete', ]); - $this->get($otherShelf->getUrl())->get($otherShelf->getUrl('/delete')) - ->press('Confirm') - ->seePageIs('/shelves') - ->assertDontSee($otherShelf->name); + $this->delete($otherShelf->getUrl())->assertRedirect('/shelves'); + $this->get('/shelves')->assertDontSee($otherShelf->name); } public function test_books_create_all_permissions() @@ -380,11 +401,10 @@ class RolesTest extends TestCase '/books' => 'Create New Book', ]); - $this->get('/create-book') - ->type('test book', 'name') - ->type('book desc', 'description') - ->press('Save Book') - ->seePageIs('/books/test-book'); + $this->post('/books', [ + 'name' => 'test book', + 'description' => 'book desc', + ])->assertRedirect('/books/test-book'); } public function test_books_edit_own_permission() @@ -398,10 +418,8 @@ class RolesTest extends TestCase $ownBook->getUrl() => 'Edit', ]); - $this->get($otherBook->getUrl()) - ->assertElementNotContains('.action-buttons', 'Edit') - ->get($otherBook->getUrl() . '/edit') - ->seePageIs('/'); + $this->get($otherBook->getUrl())->assertElementNotContains('.action-buttons', 'Edit'); + $this->get($otherBook->getUrl('/edit'))->assertRedirect('/'); } public function test_books_edit_all_permission() @@ -427,14 +445,11 @@ class RolesTest extends TestCase $ownBook->getUrl() => 'Delete', ]); - $this->get($otherBook->getUrl()) - ->assertElementNotContains('.action-buttons', 'Delete') - ->get($otherBook->getUrl() . '/delete') - ->seePageIs('/'); - $this->get($ownBook->getUrl())->get($ownBook->getUrl() . '/delete') - ->press('Confirm') - ->seePageIs('/books') - ->assertDontSee($ownBook->name); + $this->get($otherBook->getUrl())->assertElementNotContains('.action-buttons', 'Delete'); + $this->get($otherBook->getUrl('/delete'))->assertRedirect('/'); + $this->get($ownBook->getUrl()); + $this->delete($ownBook->getUrl())->assertRedirect('/books'); + $this->get('/books')->assertDontSee($ownBook->name); } public function test_books_delete_all_permission() @@ -448,10 +463,9 @@ class RolesTest extends TestCase $otherBook->getUrl() => 'Delete', ]); - $this->get($otherBook->getUrl())->get($otherBook->getUrl() . '/delete') - ->press('Confirm') - ->seePageIs('/books') - ->assertDontSee($otherBook->name); + $this->get($otherBook->getUrl()); + $this->delete($otherBook->getUrl())->assertRedirect('/books'); + $this->get('/books')->assertDontSee($otherBook->name); } public function test_chapter_create_own_permissions() @@ -465,37 +479,35 @@ class RolesTest extends TestCase $ownBook->getUrl() => 'New Chapter', ]); - $this->get($ownBook->getUrl('/create-chapter')) - ->type('test chapter', 'name') - ->type('chapter desc', 'description') - ->press('Save Chapter') - ->seePageIs($ownBook->getUrl('/chapter/test-chapter')); + $this->post($ownBook->getUrl('/create-chapter'), [ + 'name' => 'test chapter', + 'description' => 'chapter desc', + ])->assertRedirect($ownBook->getUrl('/chapter/test-chapter')); - $this->get($book->getUrl()) - ->assertElementNotContains('.action-buttons', 'New Chapter') - ->get($book->getUrl('/create-chapter')) - ->seePageIs('/'); + $this->get($book->getUrl())->assertElementNotContains('.action-buttons', 'New Chapter'); + $this->get($book->getUrl('/create-chapter'))->assertRedirect('/'); } public function test_chapter_create_all_permissions() { - $book = Book::take(1)->get()->first(); + /** @var Book $book */ + $book = Book::query()->first(); $this->checkAccessPermission('chapter-create-all', [ $book->getUrl('/create-chapter'), ], [ $book->getUrl() => 'New Chapter', ]); - $this->get($book->getUrl('/create-chapter')) - ->type('test chapter', 'name') - ->type('chapter desc', 'description') - ->press('Save Chapter') - ->seePageIs($book->getUrl('/chapter/test-chapter')); + $this->post($book->getUrl('/create-chapter'), [ + 'name' => 'test chapter', + 'description' => 'chapter desc', + ])->assertRedirect($book->getUrl('/chapter/test-chapter')); } public function test_chapter_edit_own_permission() { - $otherChapter = Chapter::take(1)->get()->first(); + /** @var Chapter $otherChapter */ + $otherChapter = Chapter::query()->first(); $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter']; $this->checkAccessPermission('chapter-update-own', [ $ownChapter->getUrl() . '/edit', @@ -503,10 +515,8 @@ class RolesTest extends TestCase $ownChapter->getUrl() => 'Edit', ]); - $this->get($otherChapter->getUrl()) - ->assertElementNotContains('.action-buttons', 'Edit') - ->get($otherChapter->getUrl() . '/edit') - ->seePageIs('/'); + $this->get($otherChapter->getUrl())->assertElementNotContains('.action-buttons', 'Edit'); + $this->get($otherChapter->getUrl('/edit'))->assertRedirect('/'); } public function test_chapter_edit_all_permission() @@ -524,7 +534,7 @@ class RolesTest extends TestCase { $this->giveUserPermissions($this->user, ['chapter-update-all']); /** @var Chapter $otherChapter */ - $otherChapter = Chapter::query()->take(1)->get()->first(); + $otherChapter = Chapter::query()->first(); $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter']; $this->checkAccessPermission('chapter-delete-own', [ $ownChapter->getUrl() . '/delete', @@ -533,20 +543,18 @@ class RolesTest extends TestCase ]); $bookUrl = $ownChapter->book->getUrl(); - $this->get($otherChapter->getUrl()) - ->assertElementNotContains('.action-buttons', 'Delete') - ->get($otherChapter->getUrl() . '/delete') - ->seePageIs('/'); - $this->get($ownChapter->getUrl())->get($ownChapter->getUrl() . '/delete') - ->press('Confirm') - ->seePageIs($bookUrl) - ->assertElementNotContains('.book-content', $ownChapter->name); + $this->get($otherChapter->getUrl())->assertElementNotContains('.action-buttons', 'Delete'); + $this->get($otherChapter->getUrl('/delete'))->assertRedirect('/'); + $this->get($ownChapter->getUrl()); + $this->delete($ownChapter->getUrl())->assertRedirect($bookUrl); + $this->get($bookUrl)->assertElementNotContains('.book-content', $ownChapter->name); } public function test_chapter_delete_all_permission() { $this->giveUserPermissions($this->user, ['chapter-update-all']); - $otherChapter = Chapter::take(1)->get()->first(); + /** @var Chapter $otherChapter */ + $otherChapter = Chapter::query()->first(); $this->checkAccessPermission('chapter-delete-all', [ $otherChapter->getUrl() . '/delete', ], [ @@ -554,10 +562,9 @@ class RolesTest extends TestCase ]); $bookUrl = $otherChapter->book->getUrl(); - $this->get($otherChapter->getUrl())->get($otherChapter->getUrl() . '/delete') - ->press('Confirm') - ->seePageIs($bookUrl) - ->assertElementNotContains('.book-content', $otherChapter->name); + $this->get($otherChapter->getUrl()); + $this->delete($otherChapter->getUrl())->assertRedirect($bookUrl); + $this->get($bookUrl)->assertElementNotContains('.book-content', $otherChapter->name); } public function test_page_create_own_permissions() @@ -576,8 +583,7 @@ class RolesTest extends TestCase $accessUrls = [$createUrl, $createUrlChapter]; foreach ($accessUrls as $url) { - $this->actingAs($this->user)->get($url) - ->seePageIs('/'); + $this->actingAs($this->user)->get($url)->assertRedirect('/'); } $this->checkAccessPermission('page-create-own', [], [ @@ -588,39 +594,39 @@ class RolesTest extends TestCase $this->giveUserPermissions($this->user, ['page-create-own']); foreach ($accessUrls as $index => $url) { - $this->actingAs($this->user)->get($url); - $expectedUrl = Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl(); - $this->seePageIs($expectedUrl); + $resp = $this->actingAs($this->user)->get($url); + $expectedUrl = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl(); + $resp->assertRedirect($expectedUrl); } - $this->get($createUrl) - ->type('test page', 'name') - ->type('page desc', 'html') - ->press('Save Page') - ->seePageIs($ownBook->getUrl('/page/test-page')); + $this->get($createUrl); + /** @var Page $draft */ + $draft = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first(); + $this->post($draft->getUrl(), [ + 'name' => 'test page', + 'html' => 'page desc', + ])->assertRedirect($ownBook->getUrl('/page/test-page')); - $this->get($book->getUrl()) - ->assertElementNotContains('.action-buttons', 'New Page') - ->get($book->getUrl() . '/create-page') - ->seePageIs('/'); - $this->get($chapter->getUrl()) - ->assertElementNotContains('.action-buttons', 'New Page') - ->get($chapter->getUrl() . '/create-page') - ->seePageIs('/'); + $this->get($book->getUrl())->assertElementNotContains('.action-buttons', 'New Page'); + $this->get($book->getUrl('/create-page'))->assertRedirect('/'); + + $this->get($chapter->getUrl())->assertElementNotContains('.action-buttons', 'New Page'); + $this->get($chapter->getUrl('/create-page'))->assertRedirect('/'); } public function test_page_create_all_permissions() { - $book = Book::take(1)->get()->first(); - $chapter = Chapter::take(1)->get()->first(); + /** @var Book $book */ + $book = Book::query()->first(); + /** @var Chapter $chapter */ + $chapter = Chapter::query()->first(); $createUrl = $book->getUrl('/create-page'); $createUrlChapter = $chapter->getUrl('/create-page'); $accessUrls = [$createUrl, $createUrlChapter]; foreach ($accessUrls as $url) { - $this->actingAs($this->user)->get($url) - ->seePageIs('/'); + $this->actingAs($this->user)->get($url)->assertRedirect('/'); } $this->checkAccessPermission('page-create-all', [], [ @@ -631,27 +637,32 @@ class RolesTest extends TestCase $this->giveUserPermissions($this->user, ['page-create-all']); foreach ($accessUrls as $index => $url) { - $this->actingAs($this->user)->get($url); - $expectedUrl = Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl(); - $this->seePageIs($expectedUrl); + $resp = $this->actingAs($this->user)->get($url); + $expectedUrl = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl(); + $resp->assertRedirect($expectedUrl); } - $this->get($createUrl) - ->type('test page', 'name') - ->type('page desc', 'html') - ->press('Save Page') - ->seePageIs($book->getUrl('/page/test-page')); + $this->get($createUrl); + /** @var Page $draft */ + $draft = Page::query()->where('draft', '=', true)->orderByDesc('id')->first(); + $this->post($draft->getUrl(), [ + 'name' => 'test page', + 'html' => 'page desc', + ])->assertRedirect($book->getUrl('/page/test-page')); - $this->get($chapter->getUrl('/create-page')) - ->type('new test page', 'name') - ->type('page desc', 'html') - ->press('Save Page') - ->seePageIs($book->getUrl('/page/new-test-page')); + $this->get($chapter->getUrl('/create-page')); + /** @var Page $draft */ + $draft = Page::query()->where('draft', '=', true)->orderByDesc('id')->first(); + $this->post($draft->getUrl(), [ + 'name' => 'new test page', + 'html' => 'page desc', + ])->assertRedirect($book->getUrl('/page/new-test-page')); } public function test_page_edit_own_permission() { - $otherPage = Page::take(1)->get()->first(); + /** @var Page $otherPage */ + $otherPage = Page::query()->first(); $ownPage = $this->createEntityChainBelongingToUser($this->user)['page']; $this->checkAccessPermission('page-update-own', [ $ownPage->getUrl() . '/edit', @@ -659,17 +670,16 @@ class RolesTest extends TestCase $ownPage->getUrl() => 'Edit', ]); - $this->get($otherPage->getUrl()) - ->assertElementNotContains('.action-buttons', 'Edit') - ->get($otherPage->getUrl() . '/edit') - ->seePageIs('/'); + $this->get($otherPage->getUrl())->assertElementNotContains('.action-buttons', 'Edit'); + $this->get($otherPage->getUrl() . '/edit')->assertRedirect('/'); } public function test_page_edit_all_permission() { - $otherPage = Page::take(1)->get()->first(); + /** @var Page $otherPage */ + $otherPage = Page::query()->first(); $this->checkAccessPermission('page-update-all', [ - $otherPage->getUrl() . '/edit', + $otherPage->getUrl('/edit'), ], [ $otherPage->getUrl() => 'Edit', ]); @@ -678,7 +688,8 @@ class RolesTest extends TestCase public function test_page_delete_own_permission() { $this->giveUserPermissions($this->user, ['page-update-all']); - $otherPage = Page::take(1)->get()->first(); + /** @var Page $otherPage */ + $otherPage = Page::query()->first(); $ownPage = $this->createEntityChainBelongingToUser($this->user)['page']; $this->checkAccessPermission('page-delete-own', [ $ownPage->getUrl() . '/delete', @@ -687,36 +698,37 @@ class RolesTest extends TestCase ]); $parent = $ownPage->chapter ?? $ownPage->book; - $this->get($otherPage->getUrl()) - ->assertElementNotContains('.action-buttons', 'Delete') - ->get($otherPage->getUrl() . '/delete') - ->seePageIs('/'); - $this->get($ownPage->getUrl())->get($ownPage->getUrl() . '/delete') - ->press('Confirm') - ->seePageIs($parent->getUrl()) - ->assertElementNotContains('.book-content', $ownPage->name); + $this->get($otherPage->getUrl())->assertElementNotContains('.action-buttons', 'Delete'); + $this->get($otherPage->getUrl('/delete'))->assertRedirect('/'); + $this->get($ownPage->getUrl()); + $this->delete($ownPage->getUrl())->assertRedirect($parent->getUrl()); + $this->get($parent->getUrl())->assertElementNotContains('.book-content', $ownPage->name); } public function test_page_delete_all_permission() { $this->giveUserPermissions($this->user, ['page-update-all']); - $otherPage = Page::take(1)->get()->first(); + /** @var Page $otherPage */ + $otherPage = Page::query()->first(); + $this->checkAccessPermission('page-delete-all', [ $otherPage->getUrl() . '/delete', ], [ $otherPage->getUrl() => 'Delete', ]); + /** @var Entity $parent */ $parent = $otherPage->chapter ?? $otherPage->book; - $this->get($otherPage->getUrl())->get($otherPage->getUrl() . '/delete') - ->press('Confirm') - ->seePageIs($parent->getUrl()) - ->assertElementNotContains('.book-content', $otherPage->name); + $this->get($otherPage->getUrl()); + + $this->delete($otherPage->getUrl())->assertRedirect($parent->getUrl()); + $this->get($parent->getUrl())->assertDontSee($otherPage->name); } public function test_public_role_visible_in_user_edit_screen() { - $user = User::first(); + /** @var User $user */ + $user = User::query()->first(); $adminRole = Role::getSystemRole('admin'); $publicRole = Role::getSystemRole('public'); $this->asAdmin()->get('/settings/users/' . $user->id) @@ -738,53 +750,57 @@ class RolesTest extends TestCase ->assertElementExists('[data-system-role-name="public"]'); } - public function test_public_role_not_deleteable() + public function test_public_role_not_deletable() { - $this->asAdmin()->get('/settings/roles') - ->click('Public') - ->assertSee('Edit Role') - ->click('Delete Role') - ->press('Confirm') - ->assertSee('Delete Role') - ->assertSee('Cannot be deleted'); + /** @var Role $publicRole */ + $publicRole = Role::getSystemRole('public'); + $resp = $this->asAdmin()->delete('/settings/roles/delete/' . $publicRole->id); + $resp->assertRedirect('/'); + + $this->get('/settings/roles/delete/' . $publicRole->id); + $resp = $this->delete('/settings/roles/delete/' . $publicRole->id); + $resp->assertRedirect('/settings/roles/delete/' . $publicRole->id); + $resp = $this->get('/settings/roles/delete/' . $publicRole->id); + $resp->assertSee('This role is a system role and cannot be deleted'); } public function test_image_delete_own_permission() { $this->giveUserPermissions($this->user, ['image-update-all']); - $page = Page::first(); - $image = factory(Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $this->user->id, 'updated_by' => $this->user->id]); + /** @var Page $page */ + $page = Page::query()->first(); + $image = factory(Image::class)->create([ + 'uploaded_to' => $page->id, + 'created_by' => $this->user->id, + 'updated_by' => $this->user->id, + ]); - $this->actingAs($this->user)->json('delete', '/images/' . $image->id) - ->assertStatus(403); + $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertStatus(403); $this->giveUserPermissions($this->user, ['image-delete-own']); - $this->actingAs($this->user)->json('delete', '/images/' . $image->id) - ->assertOk() - ->assertDatabaseMissing('images', ['id' => $image->id]); + $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertOk(); + $this->assertDatabaseMissing('images', ['id' => $image->id]); } public function test_image_delete_all_permission() { $this->giveUserPermissions($this->user, ['image-update-all']); $admin = $this->getAdmin(); - $page = Page::first(); + /** @var Page $page */ + $page = Page::query()->first(); $image = factory(Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]); - $this->actingAs($this->user)->json('delete', '/images/' . $image->id) - ->assertStatus(403); + $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertStatus(403); $this->giveUserPermissions($this->user, ['image-delete-own']); - $this->actingAs($this->user)->json('delete', '/images/' . $image->id) - ->assertStatus(403); + $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertStatus(403); $this->giveUserPermissions($this->user, ['image-delete-all']); - $this->actingAs($this->user)->json('delete', '/images/' . $image->id) - ->assertOk() - ->assertDatabaseMissing('images', ['id' => $image->id]); + $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertOk(); + $this->assertDatabaseMissing('images', ['id' => $image->id]); } public function test_role_permission_removal() From c08c8d7aa32a66742fe44e6f6b271accf6a35591 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 18 Sep 2021 21:21:44 +0100 Subject: [PATCH 9/9] Applied styleci style changes --- app/Actions/Comment.php | 8 ++++---- app/Auth/Role.php | 12 +++++------ app/Entities/Models/Book.php | 6 +++--- tests/Auth/AuthTest.php | 17 ++++++++-------- tests/Entity/PageEditorTest.php | 4 ++-- tests/Entity/PageTest.php | 5 ++--- tests/Permissions/EntityPermissionsTest.php | 13 +++++------- tests/Permissions/RolesTest.php | 22 +++++++++++---------- tests/SharedTestHelpers.php | 1 + tests/User/UserManagementTest.php | 18 ++++++++--------- 10 files changed, 51 insertions(+), 55 deletions(-) diff --git a/app/Actions/Comment.php b/app/Actions/Comment.php index e652bf8a8..34fd84709 100644 --- a/app/Actions/Comment.php +++ b/app/Actions/Comment.php @@ -7,11 +7,11 @@ use BookStack\Traits\HasCreatorAndUpdater; use Illuminate\Database\Eloquent\Relations\MorphTo; /** - * @property int $id - * @property string $text - * @property string $html + * @property int $id + * @property string $text + * @property string $html * @property int|null $parent_id - * @property int $local_id + * @property int $local_id */ class Comment extends Model { diff --git a/app/Auth/Role.php b/app/Auth/Role.php index 2918fce52..46921caeb 100644 --- a/app/Auth/Role.php +++ b/app/Auth/Role.php @@ -13,12 +13,12 @@ use Illuminate\Database\Eloquent\Relations\HasMany; /** * Class Role. * - * @property int $id - * @property string $display_name - * @property string $description - * @property string $external_auth_id - * @property string $system_name - * @property bool $mfa_enforced + * @property int $id + * @property string $display_name + * @property string $description + * @property string $external_auth_id + * @property string $system_name + * @property bool $mfa_enforced * @property Collection $users */ class Role extends Model implements Loggable diff --git a/app/Entities/Models/Book.php b/app/Entities/Models/Book.php index f77135480..1e4591bd7 100644 --- a/app/Entities/Models/Book.php +++ b/app/Entities/Models/Book.php @@ -12,9 +12,9 @@ use Illuminate\Support\Collection; /** * Class Book. * - * @property string $description - * @property int $image_id - * @property Image|null $cover + * @property string $description + * @property int $image_id + * @property Image|null $cover * @property \Illuminate\Database\Eloquent\Collection $chapters * @property \Illuminate\Database\Eloquent\Collection $pages * @property \Illuminate\Database\Eloquent\Collection $directPages diff --git a/tests/Auth/AuthTest.php b/tests/Auth/AuthTest.php index acf67cb9a..a718b14b6 100644 --- a/tests/Auth/AuthTest.php +++ b/tests/Auth/AuthTest.php @@ -77,8 +77,8 @@ class AuthTest extends TestCase $this->get('/register'); $resp = $this->followingRedirects()->post('/register', [ - 'name' => '1', - 'email' => '1', + 'name' => '1', + 'email' => '1', 'password' => '1', ]); $resp->assertSee('The name must be at least 2 characters.'); @@ -241,10 +241,10 @@ class AuthTest extends TestCase ->assertSee('Reset Password'); $resp = $this->post('/password/reset', [ - 'email' => 'admin@admin.com', - 'password' => 'randompass', + 'email' => 'admin@admin.com', + 'password' => 'randompass', 'password_confirmation' => 'randompass', - 'token' => $n->first()->token + 'token' => $n->first()->token, ]); $resp->assertRedirect('/'); @@ -260,13 +260,12 @@ class AuthTest extends TestCase $resp->assertSee('A password reset link will be sent to barry@admin.com if that email address is found in the system.'); $resp->assertDontSee('We can\'t find a user'); - $this->get('/password/reset/arandometokenvalue')->assertSee('Reset Password'); $resp = $this->post('/password/reset', [ - 'email' => 'barry@admin.com', - 'password' => 'randompass', + 'email' => 'barry@admin.com', + 'password' => 'randompass', 'password_confirmation' => 'randompass', - 'token' => 'arandometokenvalue' + 'token' => 'arandometokenvalue', ]); $resp->assertRedirect('/password/reset/arandometokenvalue'); diff --git a/tests/Entity/PageEditorTest.php b/tests/Entity/PageEditorTest.php index 588de4f17..9b0a8f188 100644 --- a/tests/Entity/PageEditorTest.php +++ b/tests/Entity/PageEditorTest.php @@ -8,7 +8,7 @@ use Tests\TestCase; class PageEditorTest extends TestCase { - /** @var Page */ + /** @var Page */ protected $page; public function setUp(): void @@ -74,4 +74,4 @@ class PageEditorTest extends TestCase 'draft' => false, ]); } -} \ No newline at end of file +} diff --git a/tests/Entity/PageTest.php b/tests/Entity/PageTest.php index e7118aae5..313fc77f0 100644 --- a/tests/Entity/PageTest.php +++ b/tests/Entity/PageTest.php @@ -227,7 +227,7 @@ class PageTest extends TestCase // Need to save twice since revisions are not generated in seeder. $this->asAdmin()->put($page->getUrl(), [ 'name' => 'super test', - 'html' => '

' + 'html' => '

', ]); $page->refresh(); @@ -235,7 +235,7 @@ class PageTest extends TestCase $this->put($pageUrl, [ 'name' => 'super test page', - 'html' => '

' + 'html' => '

', ]); $this->get($pageUrl) @@ -280,5 +280,4 @@ class PageTest extends TestCase $this->get('/') ->assertElementContains('#recently-updated-pages', $page->name); } - } diff --git a/tests/Permissions/EntityPermissionsTest.php b/tests/Permissions/EntityPermissionsTest.php index 97d9074b7..bb011cfc6 100644 --- a/tests/Permissions/EntityPermissionsTest.php +++ b/tests/Permissions/EntityPermissionsTest.php @@ -162,12 +162,11 @@ class EntityPermissionsTest extends TestCase $this->setRestrictionsForTestRoles($book, ['view', 'create']); $resp = $this->post($book->getUrl('/create-chapter'), [ - 'name' => 'test chapter', + 'name' => 'test chapter', 'description' => 'desc', ]); $resp->assertRedirect($book->getUrl('/chapter/test-chapter')); - $this->get($book->getUrl('/create-page')); /** @var Page $page */ $page = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first(); @@ -401,11 +400,11 @@ class EntityPermissionsTest extends TestCase ->assertSee($title); $this->put($modelInstance->getUrl('/permissions'), [ - 'restricted' => 'true', + 'restricted' => 'true', 'restrictions' => [ $roleId => [ - $permission => 'true' - ] + $permission => 'true', + ], ], ]); @@ -556,12 +555,11 @@ class EntityPermissionsTest extends TestCase $this->setRestrictionsForTestRoles($book, ['view', 'create']); $resp = $this->post($book->getUrl('/create-chapter'), [ - 'name' => 'test chapter', + 'name' => 'test chapter', 'description' => 'test desc', ]); $resp->assertRedirect($book->getUrl('/chapter/test-chapter')); - $this->get($book->getUrl('/create-page')); /** @var Page $page */ $page = Page::query()->where('draft', '=', true)->orderByDesc('id')->first(); @@ -730,7 +728,6 @@ class EntityPermissionsTest extends TestCase $this->setRestrictionsForTestRoles($bookChapter, ['view', 'create']); - $this->get($bookChapter->getUrl('/create-page')); /** @var Page $page */ $page = Page::query()->where('draft', '=', true)->orderByDesc('id')->first(); diff --git a/tests/Permissions/RolesTest.php b/tests/Permissions/RolesTest.php index 5689caf7b..5248ae152 100644 --- a/tests/Permissions/RolesTest.php +++ b/tests/Permissions/RolesTest.php @@ -69,7 +69,7 @@ class RolesTest extends TestCase $resp = $this->post('/settings/roles/new', [ 'display_name' => $testRoleName, - 'description' => $testRoleDesc, + 'description' => $testRoleDesc, ]); $resp->assertRedirect('/settings/roles'); @@ -78,7 +78,7 @@ class RolesTest extends TestCase $resp->assertSee($testRoleDesc); $this->assertDatabaseHas('roles', [ 'display_name' => $testRoleName, - 'description' => $testRoleDesc, + 'description' => $testRoleDesc, 'mfa_enforced' => false, ]); @@ -93,13 +93,13 @@ class RolesTest extends TestCase $resp = $this->put('/settings/roles/' . $role->id, [ 'display_name' => $testRoleUpdateName, - 'description' => $testRoleDesc, + 'description' => $testRoleDesc, 'mfa_enforced' => 'true', ]); $resp->assertRedirect('/settings/roles'); $this->assertDatabaseHas('roles', [ 'display_name' => $testRoleUpdateName, - 'description' => $testRoleDesc, + 'description' => $testRoleDesc, 'mfa_enforced' => true, ]); @@ -321,7 +321,7 @@ class RolesTest extends TestCase ]); $this->post('/shelves', [ - 'name' => 'test shelf', + 'name' => 'test shelf', 'description' => 'shelf desc', ])->assertRedirect('/shelves/test-shelf'); } @@ -402,7 +402,7 @@ class RolesTest extends TestCase ]); $this->post('/books', [ - 'name' => 'test book', + 'name' => 'test book', 'description' => 'book desc', ])->assertRedirect('/books/test-book'); } @@ -480,7 +480,7 @@ class RolesTest extends TestCase ]); $this->post($ownBook->getUrl('/create-chapter'), [ - 'name' => 'test chapter', + 'name' => 'test chapter', 'description' => 'chapter desc', ])->assertRedirect($ownBook->getUrl('/chapter/test-chapter')); @@ -499,7 +499,7 @@ class RolesTest extends TestCase ]); $this->post($book->getUrl('/create-chapter'), [ - 'name' => 'test chapter', + 'name' => 'test chapter', 'description' => 'chapter desc', ])->assertRedirect($book->getUrl('/chapter/test-chapter')); } @@ -771,8 +771,8 @@ class RolesTest extends TestCase $page = Page::query()->first(); $image = factory(Image::class)->create([ 'uploaded_to' => $page->id, - 'created_by' => $this->user->id, - 'updated_by' => $this->user->id, + 'created_by' => $this->user->id, + 'updated_by' => $this->user->id, ]); $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertStatus(403); @@ -927,12 +927,14 @@ class RolesTest extends TestCase private function addComment(Page $page): TestResponse { $comment = factory(Comment::class)->make(); + return $this->postJson("/comment/$page->id", $comment->only('text', 'html')); } private function updateComment(Comment $comment): TestResponse { $commentData = factory(Comment::class)->make(); + return $this->putJson("/comment/{$comment->id}", $commentData->only('text', 'html')); } diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php index 77bd5076b..e4d27c849 100644 --- a/tests/SharedTestHelpers.php +++ b/tests/SharedTestHelpers.php @@ -213,6 +213,7 @@ trait SharedTestHelpers /** * Create a group of entities that belong to a specific user. + * * @return array{book: Book, chapter: Chapter, page: Page} */ protected function createEntityChainBelongingToUser(User $creatorUser, ?User $updaterUser = null): array diff --git a/tests/User/UserManagementTest.php b/tests/User/UserManagementTest.php index f52a78a13..ed2fb5f04 100644 --- a/tests/User/UserManagementTest.php +++ b/tests/User/UserManagementTest.php @@ -12,7 +12,6 @@ use Tests\TestCase; class UserManagementTest extends TestCase { - public function test_user_creation() { /** @var User $user */ @@ -26,10 +25,10 @@ class UserManagementTest extends TestCase ->assertElementContains('form[action="' . url('/settings/users/create') . '"]', 'Save'); $resp = $this->post('/settings/users/create', [ - 'name' => $user->name, - 'email' => $user->email, - 'password' => $user->password, - 'password-confirm' => $user->password, + 'name' => $user->name, + 'email' => $user->email, + 'password' => $user->password, + 'password-confirm' => $user->password, 'roles[' . $adminRole->id . ']' => 'true', ]); $resp->assertRedirect('/settings/users'); @@ -48,12 +47,11 @@ class UserManagementTest extends TestCase $user = $this->getNormalUser(); $password = $user->password; - $resp = $this->asAdmin()->get('/settings/users/' . $user->id); $resp->assertSee($user->email); $this->put($user->getEditUrl(), [ - 'name' => 'Barry Scott' + 'name' => 'Barry Scott', ])->assertRedirect('/settings/users'); $this->assertDatabaseHas('users', ['id' => $user->id, 'name' => 'Barry Scott', 'password' => $password]); @@ -70,13 +68,13 @@ class UserManagementTest extends TestCase $this->asAdmin()->get($userProfilePage); $this->put($userProfilePage, [ - 'password' => 'newpassword' + 'password' => 'newpassword', ])->assertRedirect($userProfilePage); $this->get($userProfilePage)->assertSee('Password confirmation required'); $this->put($userProfilePage, [ - 'password' => 'newpassword', + 'password' => 'newpassword', 'password-confirm' => 'newpassword', ])->assertRedirect('/settings/users'); @@ -161,7 +159,7 @@ class UserManagementTest extends TestCase $resp->assertSee('Guest'); $resp->assertElementContains('form[action$="/settings/users/' . $guestUser->id . '"] button', 'Confirm'); - $resp = $this->delete('/settings/users/' . $guestUser->id); + $resp = $this->delete('/settings/users/' . $guestUser->id); $resp->assertRedirect('/settings/users/' . $guestUser->id); $resp = $this->followRedirects($resp); $resp->assertSee('cannot delete the guest user');