1
0
mirror of https://github.com/flarum/core.git synced 2025-07-25 18:51:40 +02:00

Move test infrastructure to Testing namespace in src directory

This commit is contained in:
Alexander Skvortsov
2021-01-13 01:16:59 -05:00
parent 1afbb07037
commit ba0fbd71e6
12 changed files with 6 additions and 6 deletions

View File

@@ -0,0 +1,69 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Testing\integration;
use Carbon\Carbon;
use Dflydev\FigCookies\SetCookie;
use Illuminate\Support\Str;
use Laminas\Diactoros\CallbackStream;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* A collection of helpers for building PSR-7 requests for integration tests.
*/
trait BuildsHttpRequests
{
protected function requestWithJsonBody(Request $req, array $json): Request
{
return $req
->withHeader('Content-Type', 'application/json')
->withBody(
new CallbackStream(function () use ($json) {
return json_encode($json);
})
);
}
protected function requestAsUser(Request $req, int $userId): Request
{
$token = Str::random(40);
/**
* We insert this directly instead of via `prepareDatabase`
* so that requests can be created/sent after the app is booted.
*/
$this->database()->table('access_tokens')->insert([
'token' => $token,
'user_id' => $userId,
'created_at' => Carbon::now()->toDateTimeString(),
'last_activity_at' => Carbon::now()->toDateTimeString(),
'lifetime_seconds' => 3600
]);
return $req->withAddedHeader('Authorization', "Token {$token}");
}
protected function requestWithCookiesFrom(Request $req, Response $previous): Request
{
$cookies = array_reduce(
$previous->getHeader('Set-Cookie'),
function ($memo, $setCookieString) {
$setCookie = SetCookie::fromSetCookieString($setCookieString);
$memo[$setCookie->getName()] = $setCookie->getValue();
return $memo;
},
[]
);
return $req->withCookieParams($cookies);
}
}

View File

@@ -0,0 +1,44 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Testing\integration;
use Flarum\Foundation\Application;
use Symfony\Component\Console\Application as ConsoleApplication;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
abstract class ConsoleTestCase extends TestCase
{
protected $console;
protected function console()
{
if (is_null($this->console)) {
$this->console = new ConsoleApplication('Flarum', Application::VERSION);
$this->console->setAutoExit(false);
foreach ($this->app()->getConsoleCommands() as $command) {
$this->console->add($command);
}
}
return $this->console;
}
protected function runCommand(array $inputArray)
{
$input = new ArrayInput($inputArray);
$output = new BufferedOutput();
$this->console()->run($input, $output);
return trim($output->fetch());
}
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Testing\integration;
trait RetrievesAuthorizedUsers
{
protected function normalUser(): array
{
return [
'id' => 2,
'username' => 'normal',
'password' => '$2y$10$LO59tiT7uggl6Oe23o/O6.utnF6ipngYjvMvaxo1TciKqBttDNKim', // BCrypt hash for "too-obscure"
'email' => 'normal@machine.local',
'is_email_confirmed' => 1,
];
}
}

View File

@@ -0,0 +1,204 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Testing\integration;
use Flarum\Extend\ExtenderInterface;
use Flarum\Foundation\Config;
use Flarum\Foundation\InstalledSite;
use Flarum\Foundation\Paths;
use Illuminate\Database\ConnectionInterface;
use Laminas\Diactoros\ServerRequest;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
abstract class TestCase extends \PHPUnit\Framework\TestCase
{
use BuildsHttpRequests;
/**
* @inheritDoc
*/
protected function tearDown(): void
{
parent::tearDown();
$this->database()->rollBack();
}
/**
* @var \Flarum\Foundation\InstalledApp
*/
protected $app;
/**
* @return \Flarum\Foundation\InstalledApp
*/
protected function app()
{
if (is_null($this->app)) {
$site = new InstalledSite(
new Paths([
'base' => __DIR__.'/tmp',
'vendor' => __DIR__.'/../../vendor',
'public' => __DIR__.'/tmp/public',
'storage' => __DIR__.'/tmp/storage',
]),
new Config(include __DIR__.'/tmp/config.php')
);
$site->extendWith($this->extenders);
$this->app = $site->bootApp();
$this->database()->beginTransaction();
$this->populateDatabase();
}
return $this->app;
}
/**
* @var ExtenderInterface[]
*/
protected $extenders = [];
protected function extend(ExtenderInterface ...$extenders)
{
$this->extenders = array_merge($this->extenders, $extenders);
}
/**
* @var RequestHandlerInterface
*/
protected $server;
protected function server(): RequestHandlerInterface
{
if (is_null($this->server)) {
$this->server = $this->app()->getRequestHandler();
}
return $this->server;
}
protected $database;
protected function database(): ConnectionInterface
{
if (is_null($this->database)) {
$this->database = $this->app()->getContainer()->make(
ConnectionInterface::class
);
}
return $this->database;
}
protected $databaseContent = [];
protected function prepareDatabase(array $tableData)
{
$this->databaseContent = array_merge_recursive(
$this->databaseContent,
$tableData
);
}
protected function populateDatabase()
{
// We temporarily disable foreign key checks to simplify this process.
$this->database()->getSchemaBuilder()->disableForeignKeyConstraints();
// Then, insert all rows required for this test case.
foreach ($this->databaseContent as $table => $rows) {
foreach ($rows as $row) {
if ($table === 'settings') {
$this->database()->table($table)->updateOrInsert(
['key' => $row['key']],
$row
);
} else {
$this->database()->table($table)->updateOrInsert(
isset($row['id']) ? ['id' => $row['id']] : $row,
$row
);
}
}
}
// And finally, turn on foreign key checks again.
$this->database()->getSchemaBuilder()->enableForeignKeyConstraints();
}
/**
* Send a full HTTP request through Flarum's middleware stack.
*/
protected function send(ServerRequestInterface $request): ResponseInterface
{
return $this->server()->handle($request);
}
/**
* Build a HTTP request that can be passed through middleware.
*
* This method simplifies building HTTP requests for use in our HTTP-level
* integration tests. It provides options for all features repeatedly being
* used in those tests.
*
* @param string $method
* @param string $path
* @param array $options
* An array of optional request properties.
* Currently supported:
* - "json" should point to a JSON-serializable object that will be
* serialized and used as request body. The corresponding Content-Type
* header will be set automatically.
* - "authenticatedAs" should identify an *existing* user by ID. This will
* cause an access token to be created for this user, which will be used
* to authenticate the request via the "Authorization" header.
* - "cookiesFrom" should hold a response object from a previous HTTP
* interaction. All cookies returned from the server in that response
* (via the "Set-Cookie" header) will be copied to the cookie params of
* the new request.
* @return ServerRequestInterface
*/
protected function request(string $method, string $path, array $options = []): ServerRequestInterface
{
$request = new ServerRequest([], [], $path, $method);
// Do we want a JSON request body?
if (isset($options['json'])) {
$request = $this->requestWithJsonBody(
$request,
$options['json']
);
}
// Authenticate as a given user
if (isset($options['authenticatedAs'])) {
$request = $this->requestAsUser(
$request,
$options['authenticatedAs']
);
}
// Let's copy the cookies from a previous response
if (isset($options['cookiesFrom'])) {
$request = $this->requestWithCookiesFrom(
$request,
$options['cookiesFrom']
);
}
return $request;
}
}

View File

@@ -0,0 +1,25 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Testing\integration;
use Flarum\Settings\SettingsRepositoryInterface;
trait UsesSettings
{
/**
* Removes the settings respository instance from the IoC container.
*
* This allows test cases that add/modify settings to refresh the in-memory settings cache.
*/
protected function purgeSettingsCache()
{
$this->app()->getContainer()->forgetInstance(SettingsRepositoryInterface::class);
}
}

View File

@@ -0,0 +1,71 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
use Flarum\Foundation\Paths;
use Flarum\Install\AdminUser;
use Flarum\Install\BaseUrl;
use Flarum\Install\DatabaseConfig;
use Flarum\Install\Installation;
require __DIR__.'/../../vendor/autoload.php';
$host = getenv('DB_HOST') ?: 'localhost';
$port = intval(getenv('DB_PORT') ?: 3306);
$name = getenv('DB_DATABASE') ?: 'flarum_test';
$user = getenv('DB_USERNAME') ?: 'root';
$pass = getenv('DB_PASSWORD') ?: '';
$pref = getenv('DB_PREFIX') ?: '';
echo "Connecting to database $name at $host:$port.\n";
echo "Logging in as $user with password '$pass'.\n";
echo "Table prefix: '$pref'\n";
echo "\n\nCancel now if that's not what you want...\n";
echo "Use the following environment variables for configuration:\n";
echo "DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD, DB_PREFIX\n";
sleep(5);
echo "\nOff we go...\n";
/*
* Setup installation configuration
*/
$installation = new Installation(
new Paths([
'base' => __DIR__.'/tmp',
'public' => __DIR__.'/tmp/public',
'storage' => __DIR__.'/tmp/storage',
'vendor' => __DIR__.'/../../vendor',
])
);
$pipeline = $installation
->configPath('config.php')
->debugMode(true)
->baseUrl(BaseUrl::fromString('http://localhost'))
->databaseConfig(
new DatabaseConfig('mysql', $host, $port, $name, $user, $pass, $pref)
)
->adminUser(new AdminUser(
'admin',
'password',
'admin@machine.local'
))
->settings(['mail_driver' => 'log'])
->build();
/*
* Run the actual configuration
*/
$pipeline->run();
echo "Installation complete\n";

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Testing\unit;
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
abstract class TestCase extends \PHPUnit\Framework\TestCase
{
// Ensure Mockery is always torn down automatically after each test.
use MockeryPHPUnitIntegration;
}