From badaf08e554e172051db0b8e210b734d8355ba58 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 13 Sep 2021 22:54:21 +0100 Subject: [PATCH] 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'); - } }