Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"ssddanbrown/htmldiff": "^1.0.2"
},
"require-dev": {
"brianium/paratest": "^6.6",
"fakerphp/faker": "^1.16",
"itsgoingd/clockwork": "^5.1",
"mockery/mockery": "^1.4",
Expand Down Expand Up @@ -73,6 +74,8 @@
"format": "phpcbf",
"lint": "phpcs",
"test": "phpunit",
"t": "@php artisan test --parallel",
"t-reset": "@php artisan test --recreate-databases",
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
Expand Down
9 changes: 2 additions & 7 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,9 @@ npm run dev

BookStack has many integration tests that use Laravel's built-in testing capabilities which makes use of PHPUnit. There is a `mysql_testing` database defined within the app config which is what is used by PHPUnit. This database is set with the database name, user name and password all defined as `bookstack-test`. You will have to create that database and that set of credentials before testing.

The testing database will also need migrating and seeding beforehand. This can be done with the following commands:
The testing database will also need migrating and seeding beforehand. This can be done by running `composer refresh-test-database`.

``` bash
php artisan migrate --database=mysql_testing
php artisan db:seed --class=DummyContentSeeder --database=mysql_testing
```

Once done you can run `composer test` in the application root directory to run all tests.
Once done you can run `composer test` in the application root directory to run all tests. Tests can be ran in parallel by running them via `composer t`. This will use Laravel's built-in parallel testing functionality, and attempt to create and seed a database instance for each testing thread. If required these parallel testing instances can be reset, before testing again, by running `composer t-reset`.

### 📜 Code Standards

Expand Down
24 changes: 24 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Env;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Testing\Assert as PHPUnit;
use Monolog\Handler\TestHandler;
Expand All @@ -47,6 +49,21 @@ abstract class TestCase extends BaseTestCase
*/
protected string $baseUrl = 'http://localhost';

/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
/** @var \Illuminate\Foundation\Application $app */
$app = require __DIR__ . '/../bootstrap/app.php';
$app->register(TestServiceProvider::class);
$app->make(Kernel::class)->bootstrap();

return $app;
}

/**
* Set the current user context to be an admin.
*/
Expand Down Expand Up @@ -299,6 +316,8 @@ protected function &mockHttpClient(array $responses = []): array
/**
* Run a set test with the given env variable.
* Remembers the original and resets the value after test.
* Database config is juggled so the value can be restored when
* parallel testing are used, where multiple databases exist.
*/
protected function runWithEnv(string $name, $value, callable $callback)
{
Expand All @@ -311,7 +330,12 @@ protected function runWithEnv(string $name, $value, callable $callback)
$_SERVER[$name] = $value;
}

$database = config('database.connections.mysql_testing.database');
$this->refreshApplication();

DB::purge();
config()->set('database.connections.mysql_testing.database', $database);

$callback();

if (is_null($originalVal)) {
Expand Down
26 changes: 26 additions & 0 deletions tests/TestServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Tests;

use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\ParallelTesting;
use Illuminate\Support\ServiceProvider;

class TestServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
// Tell Laravel's parallel testing functionality to seed the test
// databases with the DummyContentSeeder upon creation.
// This is only done for initial database creation. Seeding
// won't occur on every run.
ParallelTesting::setUpTestDatabase(function ($database, $token) {
Artisan::call('db:seed --class=DummyContentSeeder');
});
}
}
12 changes: 6 additions & 6 deletions tests/ThemeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,8 @@ public function test_base_body_start_and_end_template_files_can_be_used()

public function test_export_body_start_and_end_template_files_can_be_used()
{
$bodyStartStr = 'barry-fought-against-the-panther';
$bodyEndStr = 'barry-lost-his-fight-with-grace';
$bodyStartStr = 'garry-fought-against-the-panther';
$bodyEndStr = 'garry-lost-his-fight-with-grace';
/** @var Page $page */
$page = Page::query()->first();

Expand All @@ -342,18 +342,18 @@ public function test_export_body_start_and_end_template_files_can_be_used()
protected function usingThemeFolder(callable $callback)
{
// Create a folder and configure a theme
$themeFolderName = 'testing_theme_' . rtrim(base64_encode(time()), '=');
$themeFolderName = 'testing_theme_' . str_shuffle(rtrim(base64_encode(time()), '='));
config()->set('view.theme', $themeFolderName);
$themeFolderPath = theme_path('');

// Create theme folder and clean it up on application tear-down
File::makeDirectory($themeFolderPath);
$this->beforeApplicationDestroyed(fn() => File::deleteDirectory($themeFolderPath));

// Run provided callback with theme env option set
$this->runWithEnv('APP_THEME', $themeFolderName, function () use ($callback, $themeFolderName) {
call_user_func($callback, $themeFolderName);
});

// Cleanup the custom theme folder we created
File::deleteDirectory($themeFolderPath);
}
}

Expand Down