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