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