| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Tests; | 
					
						
							| 
									
										
										
										
											2019-10-26 19:35:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | use BookStack\Activity\ActivityType; | 
					
						
							|  |  |  | use BookStack\Activity\DispatchWebhookJob; | 
					
						
							|  |  |  | use BookStack\Activity\Models\Webhook; | 
					
						
							| 
									
										
										
										
											2022-07-17 20:28:56 +08:00
										 |  |  | use BookStack\Entities\Models\Book; | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  | use BookStack\Entities\Models\Page; | 
					
						
							|  |  |  | use BookStack\Entities\Tools\PageContent; | 
					
						
							| 
									
										
										
										
											2023-09-12 19:34:02 +08:00
										 |  |  | use BookStack\Exceptions\ThemeException; | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  | use BookStack\Facades\Theme; | 
					
						
							|  |  |  | use BookStack\Theming\ThemeEvents; | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | use BookStack\Users\Models\User; | 
					
						
							| 
									
										
										
										
											2021-11-23 03:03:04 +08:00
										 |  |  | use Illuminate\Console\Command; | 
					
						
							| 
									
										
										
										
											2021-03-17 20:56:56 +08:00
										 |  |  | use Illuminate\Http\Request; | 
					
						
							|  |  |  | use Illuminate\Http\Response; | 
					
						
							| 
									
										
										
										
											2021-11-23 03:03:04 +08:00
										 |  |  | use Illuminate\Support\Facades\Artisan; | 
					
						
							| 
									
										
										
										
											2021-09-26 22:48:22 +08:00
										 |  |  | use Illuminate\Support\Facades\File; | 
					
						
							| 
									
										
										
										
											2023-02-07 04:41:33 +08:00
										 |  |  | use League\CommonMark\Environment\Environment; | 
					
						
							| 
									
										
										
										
											2019-10-26 19:35:38 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class ThemeTest extends TestCase | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-04-28 06:40:14 +08:00
										 |  |  |     protected string $themeFolderName; | 
					
						
							|  |  |  |     protected string $themeFolderPath; | 
					
						
							| 
									
										
										
										
											2019-10-26 19:35:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |     public function test_translation_text_can_be_overridden_via_theme() | 
					
						
							| 
									
										
										
										
											2019-10-26 19:35:38 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-17 20:56:56 +08:00
										 |  |  |         $this->usingThemeFolder(function () { | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |             $translationPath = theme_path('/lang/en'); | 
					
						
							|  |  |  |             File::makeDirectory($translationPath, 0777, true); | 
					
						
							| 
									
										
										
										
											2019-10-26 19:35:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |             $customTranslations = '<?php | 
					
						
							|  |  |  |             return [\'books\' => \'Sandwiches\']; | 
					
						
							|  |  |  |         '; | 
					
						
							|  |  |  |             file_put_contents($translationPath . '/entities.php', $customTranslations); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  |             $homeRequest = $this->actingAs($this->users->viewer())->get('/'); | 
					
						
							| 
									
										
										
										
											2022-07-23 22:10:18 +08:00
										 |  |  |             $this->withHtml($homeRequest)->assertElementContains('header nav', 'Sandwiches'); | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2019-10-26 19:35:38 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |     public function test_theme_functions_file_used_and_app_boot_event_runs() | 
					
						
							| 
									
										
										
										
											2019-10-26 19:35:38 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-17 20:56:56 +08:00
										 |  |  |         $this->usingThemeFolder(function ($themeFolder) { | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |             $functionsFile = theme_path('functions.php'); | 
					
						
							|  |  |  |             app()->alias('cat', 'dog'); | 
					
						
							|  |  |  |             file_put_contents($functionsFile, "<?php\nTheme::listen(\BookStack\Theming\ThemeEvents::APP_BOOT, function(\$app) { \$app->alias('cat', 'dog');});"); | 
					
						
							| 
									
										
										
										
											2021-03-17 20:56:56 +08:00
										 |  |  |             $this->runWithEnv('APP_THEME', $themeFolder, function () { | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |                 $this->assertEquals('cat', $this->app->getAlias('dog')); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-10-26 19:35:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-12 19:34:02 +08:00
										 |  |  |     public function test_theme_functions_loads_errors_are_caught_and_logged() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->usingThemeFolder(function ($themeFolder) { | 
					
						
							|  |  |  |             $functionsFile = theme_path('functions.php'); | 
					
						
							|  |  |  |             file_put_contents($functionsFile, "<?php\n\\BookStack\\Biscuits::eat();"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $this->expectException(ThemeException::class); | 
					
						
							|  |  |  |             $this->expectExceptionMessageMatches('/Failed loading theme functions file at ".*?" with error: Class "BookStack\\\\Biscuits" not found/'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $this->runWithEnv('APP_THEME', $themeFolder, fn() => null); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |     public function test_event_commonmark_environment_configure() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $callbackCalled = false; | 
					
						
							| 
									
										
										
										
											2021-03-17 20:56:56 +08:00
										 |  |  |         $callback = function ($environment) use (&$callbackCalled) { | 
					
						
							| 
									
										
										
										
											2023-02-07 04:41:33 +08:00
										 |  |  |             $this->assertInstanceOf(Environment::class, $environment); | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |             $callbackCalled = true; | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |             return $environment; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         Theme::listen(ThemeEvents::COMMONMARK_ENVIRONMENT_CONFIGURE, $callback); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |         $content = new PageContent($page); | 
					
						
							| 
									
										
										
										
											2023-11-20 21:32:31 +08:00
										 |  |  |         $content->setNewMarkdown('# test', $this->users->editor()); | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $this->assertTrue($callbackCalled); | 
					
						
							| 
									
										
										
										
											2019-10-26 19:35:38 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-17 20:56:56 +08:00
										 |  |  |     public function test_event_web_middleware_before() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $callbackCalled = false; | 
					
						
							|  |  |  |         $requestParam = null; | 
					
						
							|  |  |  |         $callback = function ($request) use (&$callbackCalled, &$requestParam) { | 
					
						
							|  |  |  |             $requestParam = $request; | 
					
						
							|  |  |  |             $callbackCalled = true; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Theme::listen(ThemeEvents::WEB_MIDDLEWARE_BEFORE, $callback); | 
					
						
							|  |  |  |         $this->get('/login', ['Donkey' => 'cat']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->assertTrue($callbackCalled); | 
					
						
							|  |  |  |         $this->assertInstanceOf(Request::class, $requestParam); | 
					
						
							|  |  |  |         $this->assertEquals('cat', $requestParam->header('donkey')); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_event_web_middleware_before_return_val_used_as_response() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $callback = function (Request $request) { | 
					
						
							|  |  |  |             return response('cat', 412); | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Theme::listen(ThemeEvents::WEB_MIDDLEWARE_BEFORE, $callback); | 
					
						
							|  |  |  |         $resp = $this->get('/login', ['Donkey' => 'cat']); | 
					
						
							|  |  |  |         $resp->assertSee('cat'); | 
					
						
							|  |  |  |         $resp->assertStatus(412); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_event_web_middleware_after() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $callbackCalled = false; | 
					
						
							|  |  |  |         $requestParam = null; | 
					
						
							|  |  |  |         $responseParam = null; | 
					
						
							|  |  |  |         $callback = function ($request, Response $response) use (&$callbackCalled, &$requestParam, &$responseParam) { | 
					
						
							|  |  |  |             $requestParam = $request; | 
					
						
							|  |  |  |             $responseParam = $response; | 
					
						
							|  |  |  |             $callbackCalled = true; | 
					
						
							|  |  |  |             $response->header('donkey', 'cat123'); | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Theme::listen(ThemeEvents::WEB_MIDDLEWARE_AFTER, $callback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $resp = $this->get('/login', ['Donkey' => 'cat']); | 
					
						
							|  |  |  |         $this->assertTrue($callbackCalled); | 
					
						
							|  |  |  |         $this->assertInstanceOf(Request::class, $requestParam); | 
					
						
							|  |  |  |         $this->assertInstanceOf(Response::class, $responseParam); | 
					
						
							|  |  |  |         $resp->assertHeader('donkey', 'cat123'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_event_web_middleware_after_return_val_used_as_response() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $callback = function () { | 
					
						
							|  |  |  |             return response('cat456', 443); | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Theme::listen(ThemeEvents::WEB_MIDDLEWARE_AFTER, $callback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $resp = $this->get('/login', ['Donkey' => 'cat']); | 
					
						
							|  |  |  |         $resp->assertSee('cat456'); | 
					
						
							|  |  |  |         $resp->assertStatus(443); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-20 05:54:50 +08:00
										 |  |  |     public function test_event_auth_login_standard() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $args = []; | 
					
						
							|  |  |  |         $callback = function (...$eventArgs) use (&$args) { | 
					
						
							|  |  |  |             $args = $eventArgs; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Theme::listen(ThemeEvents::AUTH_LOGIN, $callback); | 
					
						
							|  |  |  |         $this->post('/login', ['email' => 'admin@admin.com', 'password' => 'password']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->assertCount(2, $args); | 
					
						
							|  |  |  |         $this->assertEquals('standard', $args[0]); | 
					
						
							|  |  |  |         $this->assertInstanceOf(User::class, $args[1]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_event_auth_register_standard() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $args = []; | 
					
						
							|  |  |  |         $callback = function (...$eventArgs) use (&$args) { | 
					
						
							|  |  |  |             $args = $eventArgs; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         Theme::listen(ThemeEvents::AUTH_REGISTER, $callback); | 
					
						
							|  |  |  |         $this->setSettings(['registration-enabled' => 'true']); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-31 04:29:59 +08:00
										 |  |  |         $user = User::factory()->make(); | 
					
						
							| 
									
										
										
										
											2021-05-24 19:55:45 +08:00
										 |  |  |         $this->post('/register', ['email' => $user->email, 'name' => $user->name, 'password' => 'password']); | 
					
						
							| 
									
										
										
										
											2021-03-20 05:54:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $this->assertCount(2, $args); | 
					
						
							|  |  |  |         $this->assertEquals('standard', $args[0]); | 
					
						
							|  |  |  |         $this->assertInstanceOf(User::class, $args[1]); | 
					
						
							| 
									
										
										
										
											2024-02-21 23:30:29 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_event_auth_pre_register() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $args = []; | 
					
						
							|  |  |  |         $callback = function (...$eventArgs) use (&$args) { | 
					
						
							|  |  |  |             $args = $eventArgs; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         Theme::listen(ThemeEvents::AUTH_PRE_REGISTER, $callback); | 
					
						
							|  |  |  |         $this->setSettings(['registration-enabled' => 'true']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $user = User::factory()->make(); | 
					
						
							|  |  |  |         $this->post('/register', ['email' => $user->email, 'name' => $user->name, 'password' => 'password']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->assertCount(2, $args); | 
					
						
							|  |  |  |         $this->assertEquals('standard', $args[0]); | 
					
						
							|  |  |  |         $this->assertEquals([ | 
					
						
							|  |  |  |             'email' => $user->email, | 
					
						
							|  |  |  |             'name' => $user->name, | 
					
						
							|  |  |  |             'password' => 'password', | 
					
						
							|  |  |  |         ], $args[1]); | 
					
						
							|  |  |  |         $this->assertDatabaseHas('users', ['email' => $user->email]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_event_auth_pre_register_with_false_return_blocks_registration() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $callback = function () { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         Theme::listen(ThemeEvents::AUTH_PRE_REGISTER, $callback); | 
					
						
							|  |  |  |         $this->setSettings(['registration-enabled' => 'true']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $user = User::factory()->make(); | 
					
						
							|  |  |  |         $resp = $this->post('/register', ['email' => $user->email, 'name' => $user->name, 'password' => 'password']); | 
					
						
							|  |  |  |         $resp->assertRedirect('/login'); | 
					
						
							|  |  |  |         $this->assertSessionError('User account could not be registered for the provided details'); | 
					
						
							|  |  |  |         $this->assertDatabaseMissing('users', ['email' => $user->email]); | 
					
						
							| 
									
										
										
										
											2021-03-20 05:54:50 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-04 02:22:03 +08:00
										 |  |  |     public function test_event_webhook_call_before() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $args = []; | 
					
						
							|  |  |  |         $callback = function (...$eventArgs) use (&$args) { | 
					
						
							|  |  |  |             $args = $eventArgs; | 
					
						
							| 
									
										
										
										
											2022-01-06 20:18:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-04 02:22:03 +08:00
										 |  |  |             return ['test' => 'hello!']; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         Theme::listen(ThemeEvents::WEBHOOK_CALL_BEFORE, $callback); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-08 21:16:09 +08:00
										 |  |  |         $responses = $this->mockHttpClient([new \GuzzleHttp\Psr7\Response(200, [], '')]); | 
					
						
							| 
									
										
										
										
											2022-01-04 02:22:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $webhook = new Webhook(['name' => 'Test webhook', 'endpoint' => 'https://example.com']); | 
					
						
							|  |  |  |         $webhook->save(); | 
					
						
							|  |  |  |         $event = ActivityType::PAGE_UPDATE; | 
					
						
							|  |  |  |         $detail = Page::query()->first(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dispatch((new DispatchWebhookJob($webhook, $event, $detail))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-27 04:38:03 +08:00
										 |  |  |         $this->assertCount(5, $args); | 
					
						
							| 
									
										
										
										
											2022-01-04 02:22:03 +08:00
										 |  |  |         $this->assertEquals($event, $args[0]); | 
					
						
							|  |  |  |         $this->assertEquals($webhook->id, $args[1]->id); | 
					
						
							|  |  |  |         $this->assertEquals($detail->id, $args[2]->id); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-08 21:16:09 +08:00
										 |  |  |         $this->assertEquals(1, $responses->requestCount()); | 
					
						
							|  |  |  |         $request = $responses->latestRequest(); | 
					
						
							|  |  |  |         $reqData = json_decode($request->getBody(), true); | 
					
						
							|  |  |  |         $this->assertEquals('hello!', $reqData['test']); | 
					
						
							| 
									
										
										
										
											2022-01-04 02:22:03 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 20:28:56 +08:00
										 |  |  |     public function test_event_activity_logged() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $book = $this->entities->book(); | 
					
						
							| 
									
										
										
										
											2022-07-17 20:28:56 +08:00
										 |  |  |         $args = []; | 
					
						
							|  |  |  |         $callback = function (...$eventArgs) use (&$args) { | 
					
						
							|  |  |  |             $args = $eventArgs; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Theme::listen(ThemeEvents::ACTIVITY_LOGGED, $callback); | 
					
						
							|  |  |  |         $this->asEditor()->put($book->getUrl(), ['name' => 'My cool update book!']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->assertCount(2, $args); | 
					
						
							|  |  |  |         $this->assertEquals(ActivityType::BOOK_UPDATE, $args[0]); | 
					
						
							|  |  |  |         $this->assertTrue($args[1] instanceof Book); | 
					
						
							|  |  |  |         $this->assertEquals($book->id, $args[1]->id); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 23:40:42 +08:00
										 |  |  |     public function test_event_page_include_parse() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         /** @var Page $page */ | 
					
						
							|  |  |  |         /** @var Page $otherPage */ | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2022-09-05 23:40:42 +08:00
										 |  |  |         $otherPage = Page::query()->where('id', '!=', $page->id)->first(); | 
					
						
							|  |  |  |         $otherPage->html = '<p id="bkmrk-cool">This is a really cool section</p>'; | 
					
						
							|  |  |  |         $page->html = "<p>{{@{$otherPage->id}#bkmrk-cool}}</p>"; | 
					
						
							|  |  |  |         $page->save(); | 
					
						
							|  |  |  |         $otherPage->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $args = []; | 
					
						
							|  |  |  |         $callback = function (...$eventArgs) use (&$args) { | 
					
						
							|  |  |  |             $args = $eventArgs; | 
					
						
							| 
									
										
										
										
											2022-09-07 00:41:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 23:40:42 +08:00
										 |  |  |             return '<strong>Big & content replace surprise!</strong>'; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Theme::listen(ThemeEvents::PAGE_INCLUDE_PARSE, $callback); | 
					
						
							|  |  |  |         $resp = $this->asEditor()->get($page->getUrl()); | 
					
						
							|  |  |  |         $this->withHtml($resp)->assertElementContains('.page-content strong', 'Big & content replace surprise!'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->assertCount(4, $args); | 
					
						
							|  |  |  |         $this->assertEquals($otherPage->id . '#bkmrk-cool', $args[0]); | 
					
						
							|  |  |  |         $this->assertEquals('This is a really cool section', $args[1]); | 
					
						
							|  |  |  |         $this->assertTrue($args[2] instanceof Page); | 
					
						
							|  |  |  |         $this->assertTrue($args[3] instanceof Page); | 
					
						
							|  |  |  |         $this->assertEquals($page->id, $args[2]->id); | 
					
						
							|  |  |  |         $this->assertEquals($otherPage->id, $args[3]->id); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-17 21:45:57 +08:00
										 |  |  |     public function test_event_routes_register_web_and_web_auth() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $functionsContent = <<<'END' | 
					
						
							|  |  |  | <?php | 
					
						
							|  |  |  | use BookStack\Theming\ThemeEvents; | 
					
						
							|  |  |  | use BookStack\Facades\Theme; | 
					
						
							|  |  |  | use Illuminate\Routing\Router; | 
					
						
							|  |  |  | Theme::listen(ThemeEvents::ROUTES_REGISTER_WEB, function (Router $router) { | 
					
						
							|  |  |  |     $router->get('/cat', fn () => 'cat')->name('say.cat'); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | Theme::listen(ThemeEvents::ROUTES_REGISTER_WEB_AUTH, function (Router $router) { | 
					
						
							|  |  |  |     $router->get('/dog', fn () => 'dog')->name('say.dog'); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | END; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->usingThemeFolder(function () use ($functionsContent) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $functionsFile = theme_path('functions.php'); | 
					
						
							|  |  |  |             file_put_contents($functionsFile, $functionsContent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $app = $this->createApplication(); | 
					
						
							|  |  |  |             /** @var \Illuminate\Routing\Router $router */ | 
					
						
							|  |  |  |             $router = $app->get('router'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             /** @var \Illuminate\Routing\Route $catRoute */ | 
					
						
							|  |  |  |             $catRoute = $router->getRoutes()->getRoutesByName()['say.cat']; | 
					
						
							|  |  |  |             $this->assertEquals(['web'], $catRoute->middleware()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             /** @var \Illuminate\Routing\Route $dogRoute */ | 
					
						
							|  |  |  |             $dogRoute = $router->getRoutes()->getRoutesByName()['say.dog']; | 
					
						
							|  |  |  |             $this->assertEquals(['web', 'auth'], $dogRoute->middleware()); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-20 00:16:26 +08:00
										 |  |  |     public function test_add_social_driver() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Theme::addSocialDriver('catnet', [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'client_id'     => 'abc123', | 
					
						
							|  |  |  |             'client_secret' => 'def456', | 
					
						
							| 
									
										
										
										
											2021-03-20 00:16:26 +08:00
										 |  |  |         ], 'SocialiteProviders\Discord\DiscordExtendSocialite@handleTesting'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->assertEquals('catnet', config('services.catnet.name')); | 
					
						
							|  |  |  |         $this->assertEquals('abc123', config('services.catnet.client_id')); | 
					
						
							|  |  |  |         $this->assertEquals(url('/login/service/catnet/callback'), config('services.catnet.redirect')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $loginResp = $this->get('/login'); | 
					
						
							|  |  |  |         $loginResp->assertSee('login/service/catnet'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_add_social_driver_uses_name_in_config_if_given() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Theme::addSocialDriver('catnet', [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'client_id'     => 'abc123', | 
					
						
							| 
									
										
										
										
											2021-03-20 00:16:26 +08:00
										 |  |  |             'client_secret' => 'def456', | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'name'          => 'Super Cat Name', | 
					
						
							| 
									
										
										
										
											2021-03-20 00:16:26 +08:00
										 |  |  |         ], 'SocialiteProviders\Discord\DiscordExtendSocialite@handleTesting'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->assertEquals('Super Cat Name', config('services.catnet.name')); | 
					
						
							|  |  |  |         $loginResp = $this->get('/login'); | 
					
						
							|  |  |  |         $loginResp->assertSee('Super Cat Name'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-24 19:55:45 +08:00
										 |  |  |     public function test_add_social_driver_allows_a_configure_for_redirect_callback_to_be_passed() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Theme::addSocialDriver( | 
					
						
							|  |  |  |             'discord', | 
					
						
							|  |  |  |             [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |                 'client_id'     => 'abc123', | 
					
						
							| 
									
										
										
										
											2021-05-24 19:55:45 +08:00
										 |  |  |                 'client_secret' => 'def456', | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |                 'name'          => 'Super Cat Name', | 
					
						
							| 
									
										
										
										
											2021-05-24 19:55:45 +08:00
										 |  |  |             ], | 
					
						
							|  |  |  |             'SocialiteProviders\Discord\DiscordExtendSocialite@handle', | 
					
						
							|  |  |  |             function ($driver) { | 
					
						
							|  |  |  |                 $driver->with(['donkey' => 'donut']); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $loginResp = $this->get('/login/service/discord'); | 
					
						
							|  |  |  |         $redirect = $loginResp->headers->get('location'); | 
					
						
							|  |  |  |         $this->assertStringContainsString('donkey=donut', $redirect); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-23 03:03:04 +08:00
										 |  |  |     public function test_register_command_allows_provided_command_to_be_usable_via_artisan() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-11-23 06:22:31 +08:00
										 |  |  |         Theme::registerCommand(new MyCustomCommand()); | 
					
						
							| 
									
										
										
										
											2021-11-23 03:03:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Artisan::call('bookstack:test-custom-command', []); | 
					
						
							|  |  |  |         $output = Artisan::output(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->assertStringContainsString('Command ran!', $output); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-09 20:49:42 +08:00
										 |  |  |     public function test_base_body_start_and_end_template_files_can_be_used() | 
					
						
							| 
									
										
										
										
											2022-06-22 19:47:31 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         $bodyStartStr = 'barry-fought-against-the-panther'; | 
					
						
							|  |  |  |         $bodyEndStr = 'barry-lost-his-fight-with-grace'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-22 19:49:58 +08:00
										 |  |  |         $this->usingThemeFolder(function (string $folder) use ($bodyStartStr, $bodyEndStr) { | 
					
						
							| 
									
										
										
										
											2022-06-22 19:47:31 +08:00
										 |  |  |             $viewDir = theme_path('layouts/parts'); | 
					
						
							|  |  |  |             mkdir($viewDir, 0777, true); | 
					
						
							|  |  |  |             file_put_contents($viewDir . '/base-body-start.blade.php', $bodyStartStr); | 
					
						
							|  |  |  |             file_put_contents($viewDir . '/base-body-end.blade.php', $bodyEndStr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $resp = $this->asEditor()->get('/'); | 
					
						
							|  |  |  |             $resp->assertSee($bodyStartStr); | 
					
						
							|  |  |  |             $resp->assertSee($bodyEndStr); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-09 20:49:42 +08:00
										 |  |  |     public function test_export_body_start_and_end_template_files_can_be_used() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-27 04:25:32 +08:00
										 |  |  |         $bodyStartStr = 'garry-fought-against-the-panther'; | 
					
						
							|  |  |  |         $bodyEndStr = 'garry-lost-his-fight-with-grace'; | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2022-08-09 20:49:42 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $this->usingThemeFolder(function (string $folder) use ($bodyStartStr, $bodyEndStr, $page) { | 
					
						
							|  |  |  |             $viewDir = theme_path('layouts/parts'); | 
					
						
							|  |  |  |             mkdir($viewDir, 0777, true); | 
					
						
							|  |  |  |             file_put_contents($viewDir . '/export-body-start.blade.php', $bodyStartStr); | 
					
						
							|  |  |  |             file_put_contents($viewDir . '/export-body-end.blade.php', $bodyEndStr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $resp = $this->asEditor()->get($page->getUrl('/export/html')); | 
					
						
							|  |  |  |             $resp->assertSee($bodyStartStr); | 
					
						
							|  |  |  |             $resp->assertSee($bodyEndStr); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-12 17:02:33 +08:00
										 |  |  |     public function test_login_and_register_message_template_files_can_be_used() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $loginMessage = 'Welcome to this instance, login below you scallywag'; | 
					
						
							|  |  |  |         $registerMessage = 'You want to register? Enter the deets below you numpty'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->usingThemeFolder(function (string $folder) use ($loginMessage, $registerMessage) { | 
					
						
							|  |  |  |             $viewDir = theme_path('auth/parts'); | 
					
						
							|  |  |  |             mkdir($viewDir, 0777, true); | 
					
						
							|  |  |  |             file_put_contents($viewDir . '/login-message.blade.php', $loginMessage); | 
					
						
							|  |  |  |             file_put_contents($viewDir . '/register-message.blade.php', $registerMessage); | 
					
						
							|  |  |  |             $this->setSettings(['registration-enabled' => 'true']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $this->get('/login')->assertSee($loginMessage); | 
					
						
							|  |  |  |             $this->get('/register')->assertSee($registerMessage); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-24 17:29:51 +08:00
										 |  |  |     public function test_header_links_start_template_file_can_be_used() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $content = 'This is added text in the header bar'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->usingThemeFolder(function (string $folder) use ($content) { | 
					
						
							|  |  |  |             $viewDir = theme_path('layouts/parts'); | 
					
						
							|  |  |  |             mkdir($viewDir, 0777, true); | 
					
						
							|  |  |  |             file_put_contents($viewDir . '/header-links-start.blade.php', $content); | 
					
						
							|  |  |  |             $this->setSettings(['registration-enabled' => 'true']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $this->get('/login')->assertSee($content); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |     protected function usingThemeFolder(callable $callback) | 
					
						
							| 
									
										
										
										
											2019-10-26 19:35:38 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |         // Create a folder and configure a theme
 | 
					
						
							| 
									
										
										
										
											2022-09-27 04:25:32 +08:00
										 |  |  |         $themeFolderName = 'testing_theme_' . str_shuffle(rtrim(base64_encode(time()), '=')); | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |         config()->set('view.theme', $themeFolderName); | 
					
						
							|  |  |  |         $themeFolderPath = theme_path(''); | 
					
						
							| 
									
										
										
										
											2022-09-27 04:25:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Create theme folder and clean it up on application tear-down
 | 
					
						
							| 
									
										
										
										
											2021-03-17 01:55:19 +08:00
										 |  |  |         File::makeDirectory($themeFolderPath); | 
					
						
							| 
									
										
										
										
											2022-09-27 04:25:32 +08:00
										 |  |  |         $this->beforeApplicationDestroyed(fn() => File::deleteDirectory($themeFolderPath)); | 
					
						
							| 
									
										
										
										
											2019-10-26 19:35:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-22 19:47:31 +08:00
										 |  |  |         // Run provided callback with theme env option set
 | 
					
						
							| 
									
										
										
										
											2022-06-22 19:49:58 +08:00
										 |  |  |         $this->runWithEnv('APP_THEME', $themeFolderName, function () use ($callback, $themeFolderName) { | 
					
						
							| 
									
										
										
										
											2022-06-22 19:47:31 +08:00
										 |  |  |             call_user_func($callback, $themeFolderName); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2019-10-26 19:35:38 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-11-23 03:03:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-23 06:22:31 +08:00
										 |  |  | class MyCustomCommand extends Command | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-11-23 03:03:04 +08:00
										 |  |  |     protected $signature = 'bookstack:test-custom-command'; | 
					
						
							| 
									
										
										
										
											2021-11-23 06:22:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public function handle() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-11-23 03:03:04 +08:00
										 |  |  |         $this->line('Command ran!'); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-23 06:22:31 +08:00
										 |  |  | } |