diff --git a/framework/core/.editorconfig b/framework/core/.editorconfig index 87694ddab..658a43499 100644 --- a/framework/core/.editorconfig +++ b/framework/core/.editorconfig @@ -15,5 +15,5 @@ indent_size = 2 [*.{diff,md}] trim_trailing_whitespace = false -[*.php] +[*.{php,xml}] indent_size = 4 diff --git a/framework/core/.gitignore b/framework/core/.gitignore index dea5121b7..afb97426c 100644 --- a/framework/core/.gitignore +++ b/framework/core/.gitignore @@ -3,6 +3,6 @@ composer.lock composer.phar .DS_Store Thumbs.db -tests/_output/* +/tests/tmp .vagrant .idea/* diff --git a/framework/core/.travis.yml b/framework/core/.travis.yml index 7d99d4e9e..3a288f4c7 100644 --- a/framework/core/.travis.yml +++ b/framework/core/.travis.yml @@ -1,5 +1,10 @@ language: php +env: + - DB_USERNAME=travis +services: + - mysql + php: - 7.0 - 7.1 @@ -7,9 +12,9 @@ php: matrix: fast_finish: true - +before_install: + - mysql -e 'CREATE DATABASE flarum;' before_script: - - if [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then phpenv config-rm xdebug.ini; fi; - composer self-update - composer install diff --git a/framework/core/phpunit.xml b/framework/core/phpunit.xml index c16f17554..6bdd4b7c7 100644 --- a/framework/core/phpunit.xml +++ b/framework/core/phpunit.xml @@ -11,9 +11,12 @@ syntaxCheck="false"> + + ./tests/Install + ./tests + ./tests/Install - diff --git a/framework/core/src/Install/Console/DataProviderInterface.php b/framework/core/src/Install/Console/DataProviderInterface.php index 11fc191c1..9976598e2 100644 --- a/framework/core/src/Install/Console/DataProviderInterface.php +++ b/framework/core/src/Install/Console/DataProviderInterface.php @@ -20,4 +20,6 @@ interface DataProviderInterface public function getAdminUser(); public function getSettings(); + + public function isDebugMode(): bool; } diff --git a/framework/core/src/Install/Console/DefaultsDataProvider.php b/framework/core/src/Install/Console/DefaultsDataProvider.php index c14d3aabd..70f300071 100644 --- a/framework/core/src/Install/Console/DefaultsDataProvider.php +++ b/framework/core/src/Install/Console/DefaultsDataProvider.php @@ -23,6 +23,8 @@ class DefaultsDataProvider implements DataProviderInterface 'port' => '3306', ]; + protected $debug = false; + protected $baseUrl = 'http://flarum.local'; protected $adminUser = [ @@ -96,4 +98,14 @@ class DefaultsDataProvider implements DataProviderInterface { $this->settings[$key] = $value; } + + public function isDebugMode(): bool + { + return $this->debug; + } + + public function setDebugMode(bool $debug = true) + { + $this->debug = $debug; + } } diff --git a/framework/core/src/Install/Console/FileDataProvider.php b/framework/core/src/Install/Console/FileDataProvider.php index 17bb9c5e9..0eb8886f0 100644 --- a/framework/core/src/Install/Console/FileDataProvider.php +++ b/framework/core/src/Install/Console/FileDataProvider.php @@ -18,6 +18,7 @@ use Symfony\Component\Yaml\Yaml; class FileDataProvider implements DataProviderInterface { protected $default; + protected $debug = false; protected $baseUrl = null; protected $databaseConfiguration = []; protected $adminUser = []; @@ -44,10 +45,11 @@ class FileDataProvider implements DataProviderInterface } // Define configuration variables + $this->debug = $configuration['debug'] ?? false; $this->baseUrl = isset($configuration['baseUrl']) ? rtrim($configuration['baseUrl'], '/') : null; - $this->databaseConfiguration = isset($configuration['databaseConfiguration']) ? $configuration['databaseConfiguration'] : []; - $this->adminUser = isset($configuration['adminUser']) ? $configuration['adminUser'] : []; - $this->settings = isset($configuration['settings']) ? $configuration['settings'] : []; + $this->databaseConfiguration = $configuration['databaseConfiguration'] ?? []; + $this->adminUser = $configuration['adminUser'] ?? []; + $this->settings = $configuration['settings'] ?? []; } else { throw new Exception('Configuration file does not exist.'); } @@ -72,4 +74,9 @@ class FileDataProvider implements DataProviderInterface { return $this->settings + $this->default->getSettings(); } + + public function isDebugMode(): bool + { + return $this->debug; + } } diff --git a/framework/core/src/Install/Console/InstallCommand.php b/framework/core/src/Install/Console/InstallCommand.php index 1ce1a2c0a..f3137454e 100644 --- a/framework/core/src/Install/Console/InstallCommand.php +++ b/framework/core/src/Install/Console/InstallCommand.php @@ -138,6 +138,7 @@ class InstallCommand extends AbstractCommand protected function install() { try { + $this->debug = $this->dataSource->isDebugMode(); $this->dbConfig = $this->dataSource->getDatabaseConfiguration(); $validation = $this->getValidator()->make( @@ -214,7 +215,7 @@ class InstallCommand extends AbstractCommand $dbConfig = $this->dbConfig; $config = [ - 'debug' => false, + 'debug' => $this->debug, 'database' => [ 'driver' => $dbConfig['driver'], 'host' => $dbConfig['host'], diff --git a/framework/core/src/Install/Console/UserDataProvider.php b/framework/core/src/Install/Console/UserDataProvider.php index 529e9d8e8..a84df2050 100644 --- a/framework/core/src/Install/Console/UserDataProvider.php +++ b/framework/core/src/Install/Console/UserDataProvider.php @@ -109,4 +109,9 @@ class UserDataProvider implements DataProviderInterface return $this->questionHelper->ask($this->input, $this->output, $question); } + + public function isDebugMode(): bool + { + return false; + } } diff --git a/framework/core/tests/Install/DefaultInstallationCommandTest.php b/framework/core/tests/Install/DefaultInstallationCommandTest.php new file mode 100644 index 000000000..7a8014fc0 --- /dev/null +++ b/framework/core/tests/Install/DefaultInstallationCommandTest.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Tests\Install; + +use Flarum\Install\Console\InstallCommand; +use Flarum\Install\InstallServiceProvider; +use Flarum\Tests\Test\TestCase; +use Flarum\User\User; +use Symfony\Component\Console\Input\StringInput; +use Symfony\Component\Console\Output\StreamOutput; + +class DefaultInstallationCommandTest extends TestCase +{ + protected $isInstalled = false; + + /** + * @test + */ + public function allows_forum_installation() + { + if (file_exists($this->app->basePath().DIRECTORY_SEPARATOR.'config.php')) { + unlink($this->app->basePath().DIRECTORY_SEPARATOR.'config.php'); + } + + $this->app->register(InstallServiceProvider::class); + /** @var InstallCommand $command */ + $command = $this->app->make(InstallCommand::class); + $command->setDataSource($this->configuration); + + $body = fopen('php://temp', 'wb+'); + $input = new StringInput(''); + $output = new StreamOutput($body); + + $command->run($input, $output); + + $this->assertFileExists($this->app->basePath().DIRECTORY_SEPARATOR.'config.php'); + + $admin = $this->configuration->getAdminUser(); + + $this->assertEquals(User::find(1)->username, $admin['username']); + } +} diff --git a/framework/core/tests/Test/Concerns/CreatesForum.php b/framework/core/tests/Test/Concerns/CreatesForum.php new file mode 100644 index 000000000..6be88436d --- /dev/null +++ b/framework/core/tests/Test/Concerns/CreatesForum.php @@ -0,0 +1,150 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Tests\Test\Concerns; + +use Flarum\Database\Migrator; +use Flarum\Foundation\Application; +use Flarum\Foundation\Site; +use Flarum\Http\Server; +use Flarum\Install\Console\DataProviderInterface; +use Flarum\Install\Console\DefaultsDataProvider; +use Illuminate\Database\ConnectionInterface; +use Illuminate\Database\Schema\Builder; + +trait CreatesForum +{ + /** + * @var Server + */ + protected $http; + + /** + * @var Site + */ + protected $site; + + /** + * @var Application + */ + protected $app; + + /** + * @var DataProviderInterface + */ + protected $configuration; + + /** + * Make the test set up Flarum as an installed app. + * + * @var bool + */ + protected $isInstalled = true; + + protected function createsSite() + { + $this->site = (new Site) + ->setBasePath(__DIR__.'/../../tmp') + ->setPublicPath(__DIR__.'/../../tmp/public'); + } + + protected function createsHttpForum() + { + $this->http = Server::fromSite( + $this->site + ); + + $this->app = $this->http->app; + } + + protected function refreshApplication() + { + $this->createsSite(); + + $data = new DefaultsDataProvider(); + + $data->setDebugMode(); + $data->setSetting('mail_driver', 'log'); + + $database = $data->getDatabaseConfiguration(); + $database['database'] = env('DB_DATABASE', 'flarum'); + $database['username'] = env('DB_USERNAME', 'root'); + $database['password'] = env('DB_PASSWORD', ''); + $data->setDatabaseConfiguration($database); + + $this->configuration = $data; + + $this->setsApplicationConfiguration($data); + + $this->seedsApplication(); + + $this->createsHttpForum(); + } + + protected function teardownApplication() + { + /** @var ConnectionInterface $connection */ + $connection = $this->app->make(ConnectionInterface::class); + $connection->rollBack(); + } + + protected function setsApplicationConfiguration(DataProviderInterface $data) + { + if ($this->isInstalled) { + $dbConfig = $data->getDatabaseConfiguration(); + $this->site->setConfig( + $config = [ + 'debug' => $data->isDebugMode(), + 'database' => [ + 'driver' => $dbConfig['driver'], + 'host' => $dbConfig['host'], + 'database' => $dbConfig['database'], + 'username' => $dbConfig['username'], + 'password' => $dbConfig['password'], + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', + 'prefix' => $dbConfig['prefix'], + 'port' => $dbConfig['port'], + 'strict' => false + ], + 'url' => $data->getBaseUrl(), + 'paths' => [ + 'api' => 'api', + 'admin' => 'admin', + ], + ] + ); + } + } + + protected function seedsApplication() + { + if ($this->isInstalled) { + $app = app(\Illuminate\Contracts\Foundation\Application::class); + + $app->bind(Builder::class, function ($container) { + return $container->make(ConnectionInterface::class)->getSchemaBuilder(); + }); + + /** @var Migrator $migrator */ + $migrator = $app->make(Migrator::class); + if (! $migrator->getRepository()->repositoryExists()) { + $migrator->getRepository()->createRepository(); + } + + $migrator->run(__DIR__.'/../../../migrations'); + + /** @var ConnectionInterface $connection */ + $connection = $app->make(\Illuminate\Database\ConnectionInterface::class); + $connection->beginTransaction(); + } + } +} diff --git a/framework/core/tests/Test/Concerns/MakesApiRequests.php b/framework/core/tests/Test/Concerns/MakesApiRequests.php new file mode 100644 index 000000000..270e501fb --- /dev/null +++ b/framework/core/tests/Test/Concerns/MakesApiRequests.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Tests\Test\Concerns; + +use Flarum\Api\ApiServiceProvider; +use Flarum\Api\Client; +use Flarum\User\Guest; +use Flarum\User\User; +use Psr\Http\Message\ResponseInterface; + +trait MakesApiRequests +{ + public function call(string $controller, User $actor = null, array $queryParams = [], array $body = []): ResponseInterface + { + $this->app->register(ApiServiceProvider::class); + $this->app->make('flarum.api.middleware'); + /** @var Client $api */ + $api = $this->app->make(Client::class); + + return $api->send($controller, $actor ?? new Guest, $queryParams, $body); + } +} diff --git a/framework/core/tests/Test/Concerns/RetrievesAuthorizedUsers.php b/framework/core/tests/Test/Concerns/RetrievesAuthorizedUsers.php new file mode 100644 index 000000000..ca4bf581c --- /dev/null +++ b/framework/core/tests/Test/Concerns/RetrievesAuthorizedUsers.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Tests\Test\Concerns; + +use Flarum\User\User; + +trait RetrievesAuthorizedUsers +{ + protected $userAttributes = [ + 'username' => 'normal', + 'password' => 'too-obscure', + 'email' => 'normal@machine.local' + ]; + + public function getAdminUser() + { + return User::find(1); + } + + public function getNormalUser() + { + User::unguarded(function () { + return User::firstOrCreate([ + 'username' => $this->userAttributes['username'] + ], $this->userAttributes); + }); + } +} diff --git a/framework/core/tests/Test/TestCase.php b/framework/core/tests/Test/TestCase.php index b9f2459e2..21dbfff7b 100644 --- a/framework/core/tests/Test/TestCase.php +++ b/framework/core/tests/Test/TestCase.php @@ -11,20 +11,21 @@ namespace Flarum\Tests\Test; -use Mockery; use PHPUnit\Framework\TestCase as Test; abstract class TestCase extends Test { + use Concerns\CreatesForum, + Concerns\MakesApiRequests; + public function setUp() { - Mockery::close(); - + $this->refreshApplication(); $this->init(); } protected function init() { - // To be overloaded by children - saves having to do setUp/mockery::close every time + // .. allows implementation by children without the need to call the parent. } } diff --git a/framework/core/tests/tmp/public/assets/.gitkeep b/framework/core/tests/tmp/public/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/framework/core/tests/tmp/storage/.gitkeep b/framework/core/tests/tmp/storage/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/framework/core/tests/tmp/vendor/composer/installed.json b/framework/core/tests/tmp/vendor/composer/installed.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/framework/core/tests/tmp/vendor/composer/installed.json @@ -0,0 +1 @@ +{}