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