]> BookStack Code Mirror - bookstack/blob - tests/BrowserKitTest.php
Cleaned up DB usage in migration
[bookstack] / tests / BrowserKitTest.php
1 <?php
2
3 namespace Tests;
4
5 use BookStack\Auth\Permissions\PermissionService;
6 use BookStack\Auth\User;
7 use BookStack\Entities\Models\Book;
8 use BookStack\Entities\Models\Chapter;
9 use BookStack\Entities\Models\Entity;
10 use BookStack\Entities\Models\Page;
11 use BookStack\Settings\SettingService;
12 use DB;
13 use Illuminate\Contracts\Console\Kernel;
14 use Illuminate\Foundation\Application;
15 use Illuminate\Foundation\Testing\DatabaseTransactions;
16 use Laravel\BrowserKitTesting\TestCase;
17 use Symfony\Component\DomCrawler\Crawler;
18
19 abstract class BrowserKitTest extends TestCase
20 {
21     use DatabaseTransactions;
22     use SharedTestHelpers;
23
24     /**
25      * The base URL to use while testing the application.
26      *
27      * @var string
28      */
29     protected $baseUrl = 'http://localhost';
30
31     public function tearDown(): void
32     {
33         DB::disconnect();
34         parent::tearDown();
35     }
36
37     /**
38      * Creates the application.
39      *
40      * @return Application
41      */
42     public function createApplication()
43     {
44         $app = require __DIR__ . '/../bootstrap/app.php';
45
46         $app->make(Kernel::class)->bootstrap();
47
48         return $app;
49     }
50
51     /**
52      * Quickly sets an array of settings.
53      *
54      * @param $settingsArray
55      */
56     protected function setSettings($settingsArray)
57     {
58         $settings = app(SettingService::class);
59         foreach ($settingsArray as $key => $value) {
60             $settings->put($key, $value);
61         }
62     }
63
64     /**
65      * Create a group of entities that belong to a specific user.
66      */
67     protected function createEntityChainBelongingToUser(User $creatorUser, ?User $updaterUser = null): array
68     {
69         if (empty($updaterUser)) {
70             $updaterUser = $creatorUser;
71         }
72
73         $userAttrs = ['created_by' => $creatorUser->id, 'owned_by' => $creatorUser->id, 'updated_by' => $updaterUser->id];
74         $book = factory(Book::class)->create($userAttrs);
75         $chapter = factory(Chapter::class)->create(array_merge(['book_id' => $book->id], $userAttrs));
76         $page = factory(Page::class)->create(array_merge(['book_id' => $book->id, 'chapter_id' => $chapter->id], $userAttrs));
77         $restrictionService = $this->app[PermissionService::class];
78         $restrictionService->buildJointPermissionsForEntity($book);
79
80         return compact('book', 'chapter', 'page');
81     }
82
83     /**
84      * Helper for updating entity permissions.
85      *
86      * @param Entity $entity
87      */
88     protected function updateEntityPermissions(Entity $entity)
89     {
90         $restrictionService = $this->app[PermissionService::class];
91         $restrictionService->buildJointPermissionsForEntity($entity);
92     }
93
94     /**
95      * Quick way to create a new user without any permissions.
96      *
97      * @param array $attributes
98      *
99      * @return mixed
100      */
101     protected function getNewBlankUser($attributes = [])
102     {
103         $user = factory(User::class)->create($attributes);
104
105         return $user;
106     }
107
108     /**
109      * Assert that a given string is seen inside an element.
110      *
111      * @param bool|string|null $element
112      * @param int              $position
113      * @param string           $text
114      * @param bool             $negate
115      *
116      * @return $this
117      */
118     protected function seeInNthElement($element, $position, $text, $negate = false)
119     {
120         $method = $negate ? 'assertDoesNotMatchRegularExpression' : 'assertMatchesRegularExpression';
121
122         $rawPattern = preg_quote($text, '/');
123
124         $escapedPattern = preg_quote(e($text), '/');
125
126         $content = $this->crawler->filter($element)->eq($position)->html();
127
128         $pattern = $rawPattern == $escapedPattern
129             ? $rawPattern : "({$rawPattern}|{$escapedPattern})";
130
131         $this->$method("/$pattern/i", $content);
132
133         return $this;
134     }
135
136     /**
137      * Assert that the current page matches a given URI.
138      *
139      * @param string $uri
140      *
141      * @return $this
142      */
143     protected function seePageUrlIs($uri)
144     {
145         $this->assertEquals(
146             $uri,
147             $this->currentUri,
148             "Did not land on expected page [{$uri}].\n"
149         );
150
151         return $this;
152     }
153
154     /**
155      * Do a forced visit that does not error out on exception.
156      *
157      * @param string $uri
158      * @param array  $parameters
159      * @param array  $cookies
160      * @param array  $files
161      *
162      * @return $this
163      */
164     protected function forceVisit($uri, $parameters = [], $cookies = [], $files = [])
165     {
166         $method = 'GET';
167         $uri = $this->prepareUrlForRequest($uri);
168         $this->call($method, $uri, $parameters, $cookies, $files);
169         $this->clearInputs()->followRedirects();
170         $this->currentUri = $this->app->make('request')->fullUrl();
171         $this->crawler = new Crawler($this->response->getContent(), $uri);
172
173         return $this;
174     }
175
176     /**
177      * Click the text within the selected element.
178      *
179      * @param $parentElement
180      * @param $linkText
181      *
182      * @return $this
183      */
184     protected function clickInElement($parentElement, $linkText)
185     {
186         $elem = $this->crawler->filter($parentElement);
187         $link = $elem->selectLink($linkText);
188         $this->visit($link->link()->getUri());
189
190         return $this;
191     }
192
193     /**
194      * Check if the page contains the given element.
195      *
196      * @param string $selector
197      */
198     protected function pageHasElement($selector)
199     {
200         $elements = $this->crawler->filter($selector);
201         $this->assertTrue(count($elements) > 0, 'The page does not contain an element matching ' . $selector);
202
203         return $this;
204     }
205
206     /**
207      * Check if the page contains the given element.
208      *
209      * @param string $selector
210      */
211     protected function pageNotHasElement($selector)
212     {
213         $elements = $this->crawler->filter($selector);
214         $this->assertFalse(count($elements) > 0, 'The page contains ' . count($elements) . ' elements matching ' . $selector);
215
216         return $this;
217     }
218 }