mirror of
https://github.com/flarum/framework.git
synced 2025-04-26 14:44:03 +08:00
Merge remote-tracking branch 'php_packages_testing/REWRITE'
This commit is contained in:
commit
108d130354
19
php-packages/testing/.editorconfig
Normal file
19
php-packages/testing/.editorconfig
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# EditorConfig helps developers define and maintain consistent
|
||||||
|
# coding styles between different editors and IDEs
|
||||||
|
# editorconfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.{diff,md}]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.{php,xml,json}]
|
||||||
|
indent_size = 4
|
15
php-packages/testing/.gitattributes
vendored
Normal file
15
php-packages/testing/.gitattributes
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
.gitattributes export-ignore
|
||||||
|
.gitignore export-ignore
|
||||||
|
.gitmodules export-ignore
|
||||||
|
.github export-ignore
|
||||||
|
.travis export-ignore
|
||||||
|
.travis.yml export-ignore
|
||||||
|
.editorconfig export-ignore
|
||||||
|
.styleci.yml export-ignore
|
||||||
|
|
||||||
|
phpunit.xml export-ignore
|
||||||
|
tests export-ignore
|
||||||
|
|
||||||
|
js/dist/* -diff
|
||||||
|
|
||||||
|
* text=auto eol=lf
|
83
php-packages/testing/.github/workflows/test.yml
vendored
Normal file
83
php-packages/testing/.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
name: Tests
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
working-directory: tests
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
php: [7.3, 7.4, '8.0']
|
||||||
|
service: ['mysql:5.7', mariadb]
|
||||||
|
prefix: ['', flarum_]
|
||||||
|
|
||||||
|
include:
|
||||||
|
- service: 'mysql:5.7'
|
||||||
|
db: MySQL
|
||||||
|
- service: mariadb
|
||||||
|
db: MariaDB
|
||||||
|
- prefix: flarum_
|
||||||
|
prefixStr: (prefix)
|
||||||
|
|
||||||
|
exclude:
|
||||||
|
- php: 7.3
|
||||||
|
service: 'mysql:5.7'
|
||||||
|
prefix: flarum_
|
||||||
|
- php: 7.3
|
||||||
|
service: mariadb
|
||||||
|
prefix: flarum_
|
||||||
|
- php: 8.0
|
||||||
|
service: 'mysql:5.7'
|
||||||
|
prefix: flarum_
|
||||||
|
- php: 8.0
|
||||||
|
service: mariadb
|
||||||
|
prefix: flarum_
|
||||||
|
|
||||||
|
services:
|
||||||
|
mysql:
|
||||||
|
image: ${{ matrix.service }}
|
||||||
|
ports:
|
||||||
|
- 13306:3306
|
||||||
|
|
||||||
|
name: 'PHP ${{ matrix.php }} / ${{ matrix.db }} ${{ matrix.prefixStr }}'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
coverage: xdebug
|
||||||
|
extensions: curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip
|
||||||
|
tools: phpunit, composer:v2
|
||||||
|
|
||||||
|
# The authentication alter is necessary because newer mysql versions use the `caching_sha2_password` driver,
|
||||||
|
# which isn't supported prior to PHP7.4
|
||||||
|
# When we drop support for PHP7.3, we should remove this from the setup.
|
||||||
|
- name: Create MySQL Database
|
||||||
|
run: |
|
||||||
|
sudo systemctl start mysql
|
||||||
|
mysql -uroot -proot -e 'CREATE DATABASE flarum_test;' --port 13306
|
||||||
|
mysql -uroot -proot -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root';" --port 13306
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
run: composer install
|
||||||
|
|
||||||
|
- name: Setup Composer tests
|
||||||
|
run: composer test:setup
|
||||||
|
env:
|
||||||
|
DB_PORT: 13306
|
||||||
|
DB_PASSWORD: root
|
||||||
|
DB_PREFIX: ${{ matrix.prefix }}
|
||||||
|
|
||||||
|
- name: Run Composer tests
|
||||||
|
run: composer test
|
||||||
|
env:
|
||||||
|
COMPOSER_PROCESS_TIMEOUT: 600
|
10
php-packages/testing/.gitignore
vendored
Normal file
10
php-packages/testing/.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/vendor
|
||||||
|
composer.lock
|
||||||
|
composer.phar
|
||||||
|
node_modules
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
/src/integration/tmp
|
||||||
|
.vagrant
|
||||||
|
.idea/*
|
||||||
|
.vscode
|
18
php-packages/testing/.styleci.yml
Normal file
18
php-packages/testing/.styleci.yml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
preset: recommended
|
||||||
|
|
||||||
|
enabled:
|
||||||
|
- logical_not_operators_with_successor_space
|
||||||
|
|
||||||
|
disabled:
|
||||||
|
- align_double_arrow
|
||||||
|
- blank_line_after_opening_tag
|
||||||
|
- multiline_array_trailing_comma
|
||||||
|
- new_with_braces
|
||||||
|
- phpdoc_align
|
||||||
|
- phpdoc_order
|
||||||
|
- phpdoc_separation
|
||||||
|
- phpdoc_types
|
||||||
|
|
||||||
|
finder:
|
||||||
|
exclude:
|
||||||
|
- "stubs"
|
21
php-packages/testing/LICENSE
Executable file
21
php-packages/testing/LICENSE
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2020-2021 Stichting Flarum (Flarum Foundation)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
33
php-packages/testing/composer.json
Normal file
33
php-packages/testing/composer.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "flarum/testing",
|
||||||
|
"description": "Automated testing infrastructure for Flarum core and extensions.",
|
||||||
|
"keywords": [
|
||||||
|
"forum",
|
||||||
|
"discussion"
|
||||||
|
],
|
||||||
|
"homepage": "https://flarum.org/",
|
||||||
|
"license": "MIT",
|
||||||
|
"require": {
|
||||||
|
"ext-json": "*",
|
||||||
|
"mockery/mockery": "^1.4",
|
||||||
|
"phpunit/phpunit": "^9.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"flarum/core": "*@dev"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Flarum\\Testing\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"Flarum\\Testing\\Tests\\": "src/tests/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.x-dev"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
php-packages/testing/src/integration/BuildsHttpRequests.php
Normal file
69
php-packages/testing/src/integration/BuildsHttpRequests.php
Normal 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(),
|
||||||
|
'type' => 'session'
|
||||||
|
]);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
44
php-packages/testing/src/integration/ConsoleTestCase.php
Normal file
44
php-packages/testing/src/integration/ConsoleTestCase.php
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Flarum\Testing\integration\Extend;
|
||||||
|
|
||||||
|
use Flarum\Extend\ExtenderInterface;
|
||||||
|
use Flarum\Extension\Extension;
|
||||||
|
use Illuminate\Contracts\Container\Container;
|
||||||
|
use Illuminate\Database\ConnectionInterface;
|
||||||
|
|
||||||
|
class BeginTransactionAndSetDatabase implements ExtenderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A callback to set the database connection object on the test case.
|
||||||
|
*/
|
||||||
|
protected $setDbOnTestCase;
|
||||||
|
|
||||||
|
public function __construct(callable $setDbOnTestCase)
|
||||||
|
{
|
||||||
|
$this->setDbOnTestCase = $setDbOnTestCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function extend(Container $container, Extension $extension = null)
|
||||||
|
{
|
||||||
|
$db = $container->make(ConnectionInterface::class);
|
||||||
|
|
||||||
|
$db->beginTransaction();
|
||||||
|
|
||||||
|
($this->setDbOnTestCase)($db);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Flarum\Testing\integration\Extend;
|
||||||
|
|
||||||
|
use Flarum\Extend\ExtenderInterface;
|
||||||
|
use Flarum\Extension\Extension;
|
||||||
|
use Flarum\Extension\ExtensionManager;
|
||||||
|
use Flarum\Testing\integration\Extension\ExtensionManagerIncludeCurrent;
|
||||||
|
use Illuminate\Contracts\Container\Container;
|
||||||
|
|
||||||
|
class OverrideExtensionManagerForTests implements ExtenderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* IDs of extensions to boot
|
||||||
|
*/
|
||||||
|
protected $extensions;
|
||||||
|
|
||||||
|
public function __construct($extensions)
|
||||||
|
{
|
||||||
|
$this->extensions = $extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function extend(Container $container, Extension $extension = null)
|
||||||
|
{
|
||||||
|
$container->when(ExtensionManagerIncludeCurrent::class)->needs('$enabledIds')->give($this->extensions);
|
||||||
|
if (count($this->extensions)) {
|
||||||
|
$container->singleton(ExtensionManager::class, ExtensionManagerIncludeCurrent::class);
|
||||||
|
$extensionManager = $container->make(ExtensionManager::class);
|
||||||
|
|
||||||
|
foreach ($this->extensions as $extension) {
|
||||||
|
$extensionManager->enable($extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
$extensionManager->booted = true;
|
||||||
|
|
||||||
|
$extensionManager->extend($container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Flarum\Testing\integration\Extend;
|
||||||
|
|
||||||
|
use Flarum\Extend\ExtenderInterface;
|
||||||
|
use Flarum\Extension\Extension;
|
||||||
|
use Flarum\Settings\SettingsRepositoryInterface;
|
||||||
|
use Illuminate\Contracts\Container\Container;
|
||||||
|
|
||||||
|
class SetSettingsBeforeBoot implements ExtenderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* IDs of extensions to boot
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
public function __construct($settings)
|
||||||
|
{
|
||||||
|
$this->settings = $settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function extend(Container $container, Extension $extension = null)
|
||||||
|
{
|
||||||
|
if (count($this->settings)) {
|
||||||
|
$settings = $container->make(SettingsRepositoryInterface::class);
|
||||||
|
|
||||||
|
foreach ($this->settings as $key => $value) {
|
||||||
|
$settings->set($key, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
<?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\Extension;
|
||||||
|
|
||||||
|
use Flarum\Database\Migrator;
|
||||||
|
use Flarum\Extension\Extension;
|
||||||
|
use Flarum\Extension\ExtensionManager;
|
||||||
|
use Flarum\Foundation\Paths;
|
||||||
|
use Flarum\Settings\SettingsRepositoryInterface;
|
||||||
|
use Illuminate\Contracts\Container\Container;
|
||||||
|
use Illuminate\Contracts\Events\Dispatcher;
|
||||||
|
use Illuminate\Contracts\Filesystem\Cloud;
|
||||||
|
use Illuminate\Filesystem\Filesystem;
|
||||||
|
use Illuminate\Filesystem\FilesystemAdapter;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use League\Flysystem\Adapter\Local;
|
||||||
|
use League\Flysystem\Filesystem as FlysystemFilesystem;
|
||||||
|
|
||||||
|
class ExtensionManagerIncludeCurrent extends ExtensionManager
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $enabledIds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $booted = false;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
SettingsRepositoryInterface $config,
|
||||||
|
Paths $paths,
|
||||||
|
Container $container,
|
||||||
|
Migrator $migrator,
|
||||||
|
Dispatcher $dispatcher,
|
||||||
|
Filesystem $filesystem,
|
||||||
|
array $enabledIds
|
||||||
|
) {
|
||||||
|
parent::__construct($config, $paths, $container, $migrator, $dispatcher, $filesystem);
|
||||||
|
|
||||||
|
$this->enabledIds = $enabledIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @{@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getExtensions()
|
||||||
|
{
|
||||||
|
$extensions = parent::getExtensions();
|
||||||
|
|
||||||
|
$package = json_decode($this->filesystem->get($this->paths->vendor . '/../composer.json'), true);
|
||||||
|
|
||||||
|
if (Arr::get($package, 'type') === 'flarum-extension') {
|
||||||
|
$current = new Extension($this->paths->vendor . '/../', $package);
|
||||||
|
$current->setInstalled(true);
|
||||||
|
$current->setVersion(Arr::get($package, 'version'));
|
||||||
|
$current->calculateDependencies([], []);
|
||||||
|
|
||||||
|
$extensions->put($current->getId(), $current);
|
||||||
|
|
||||||
|
$this->extensions = $extensions->sortBy(function ($extension, $name) {
|
||||||
|
return $extension->composerJsonAttribute('extra.flarum-extension.title');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We assume it's not enabled during boot.
|
||||||
|
* However, since some logic needs this, as soon as we enable extensions
|
||||||
|
* we'll switch booted to on.
|
||||||
|
*/
|
||||||
|
public function isEnabled($extension)
|
||||||
|
{
|
||||||
|
if (!$this->booted) return false;
|
||||||
|
|
||||||
|
return parent::isEnabled($extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In test cases, enabled extensions are determined by the test case, not the database.
|
||||||
|
*/
|
||||||
|
public function getEnabled()
|
||||||
|
{
|
||||||
|
return $this->enabledIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enabled extensions must be specified by the test case, so this should do nothing.
|
||||||
|
*/
|
||||||
|
protected function setEnabledExtensions(array $enabledExtensions)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an instance of the assets filesystem.
|
||||||
|
* This is resolved dynamically because Flarum's filesystem configuration
|
||||||
|
* might not be booted yet when the ExtensionManager singleton initializes.
|
||||||
|
*/
|
||||||
|
protected function getAssetsFilesystem(): Cloud
|
||||||
|
{
|
||||||
|
return new FilesystemAdapter(new FlysystemFilesystem(new Local($this->paths->public . '/assets'), ['url' => resolve('flarum.config')->url() . '/assets']));
|
||||||
|
}
|
||||||
|
}
|
@ -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,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
149
php-packages/testing/src/integration/Setup/SetupScript.php
Normal file
149
php-packages/testing/src/integration/Setup/SetupScript.php
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
<?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\Setup;
|
||||||
|
|
||||||
|
use Flarum\Foundation\Paths;
|
||||||
|
use Flarum\Install\AdminUser;
|
||||||
|
use Flarum\Install\BaseUrl;
|
||||||
|
use Flarum\Install\DatabaseConfig;
|
||||||
|
use Flarum\Install\Installation;
|
||||||
|
use Flarum\Install\Steps\ConnectToDatabase;
|
||||||
|
use Flarum\Testing\integration\UsesTmpDir;
|
||||||
|
|
||||||
|
class SetupScript
|
||||||
|
{
|
||||||
|
use UsesTmpDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test database host.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $host;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test database port.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $port;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test database name.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test database username.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test database password.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $pass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test database prefix.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $pref;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var DatabaseConfig
|
||||||
|
*/
|
||||||
|
private $dbConfig;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->host = getenv('DB_HOST') ?: 'localhost';
|
||||||
|
$this->port = intval(getenv('DB_PORT') ?: 3306);
|
||||||
|
$this->name = getenv('DB_DATABASE') ?: 'flarum_test';
|
||||||
|
$this->user = getenv('DB_USERNAME') ?: 'root';
|
||||||
|
$this->pass = getenv('DB_PASSWORD') ?? 'root';
|
||||||
|
$this->pref = getenv('DB_PREFIX') ?: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$tmp = $this->tmpDir();
|
||||||
|
|
||||||
|
echo "Connecting to database $this->name at $this->host:$this->port.\n";
|
||||||
|
echo "Warning: all tables will be dropped to ensure clean state. DO NOT use your production database!\n";
|
||||||
|
echo "Logging in as $this->user with password '$this->pass'.\n";
|
||||||
|
echo "Table prefix: '$this->pref'\n";
|
||||||
|
echo "\nStoring test config in '$tmp'\n";
|
||||||
|
|
||||||
|
echo "\n\nCancel now if that's not what you want...\n";
|
||||||
|
echo "Use the following environment variables for configuration:\n";
|
||||||
|
echo "Database: DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD, DB_PREFIX\n";
|
||||||
|
echo "Test Config: FLARUM_TEST_TMP_DIR or FLARUM_TEST_TMP_DIR_LOCAL\n";
|
||||||
|
|
||||||
|
|
||||||
|
sleep(4);
|
||||||
|
|
||||||
|
echo "\nOff we go...\n";
|
||||||
|
|
||||||
|
$this->dbConfig = new DatabaseConfig('mysql', $this->host, $this->port, $this->name, $this->user, $this->pass, $this->pref);
|
||||||
|
|
||||||
|
echo "\nWiping DB to ensure clean state\n";
|
||||||
|
$this->wipeDb();
|
||||||
|
echo "Success! Proceeding to installation...\n";
|
||||||
|
|
||||||
|
$this->setupTmpDir();
|
||||||
|
|
||||||
|
$installation = new Installation(
|
||||||
|
new Paths([
|
||||||
|
'base' => $tmp,
|
||||||
|
'public' => "$tmp/public",
|
||||||
|
'storage' => "$tmp/storage",
|
||||||
|
'vendor' => getcwd() . '/vendor',
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$pipeline = $installation
|
||||||
|
->configPath('config.php')
|
||||||
|
->debugMode(true)
|
||||||
|
->baseUrl(BaseUrl::fromString('http://localhost'))
|
||||||
|
->databaseConfig($this->dbConfig)
|
||||||
|
->adminUser(new AdminUser(
|
||||||
|
'admin',
|
||||||
|
'password',
|
||||||
|
'admin@machine.local'
|
||||||
|
))
|
||||||
|
->settings(['mail_driver' => 'log'])
|
||||||
|
->extensions([])
|
||||||
|
->build();
|
||||||
|
|
||||||
|
// Run the actual configuration
|
||||||
|
$pipeline->run();
|
||||||
|
|
||||||
|
echo "Installation complete\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function wipeDb()
|
||||||
|
{
|
||||||
|
// Reuse the connection step to include version checks
|
||||||
|
(new ConnectToDatabase($this->dbConfig, function ($db) {
|
||||||
|
// Inspired by Laravel's db:wipe
|
||||||
|
$builder = $db->getSchemaBuilder();
|
||||||
|
|
||||||
|
$builder->dropAllTables();
|
||||||
|
$builder->dropAllViews();
|
||||||
|
}))->run();
|
||||||
|
}
|
||||||
|
}
|
295
php-packages/testing/src/integration/TestCase.php
Normal file
295
php-packages/testing/src/integration/TestCase.php
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
<?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 Flarum\Testing\integration\Extend\BeginTransactionAndSetDatabase;
|
||||||
|
use Flarum\Testing\integration\Extend\OverrideExtensionManagerForTests;
|
||||||
|
use Flarum\Testing\integration\Extend\SetSettingsBeforeBoot;
|
||||||
|
use Illuminate\Database\ConnectionInterface;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
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;
|
||||||
|
use UsesTmpDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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)) {
|
||||||
|
$tmp = $this->tmpDir();
|
||||||
|
|
||||||
|
$config = include "$tmp/config.php";
|
||||||
|
|
||||||
|
foreach ($this->config as $key => $value) {
|
||||||
|
Arr::set($config, $key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$site = new InstalledSite(
|
||||||
|
new Paths([
|
||||||
|
'base' => $tmp,
|
||||||
|
'public' => "$tmp/public",
|
||||||
|
'storage' => "$tmp/storage",
|
||||||
|
'vendor' => getcwd().'/vendor',
|
||||||
|
]),
|
||||||
|
new Config($config)
|
||||||
|
);
|
||||||
|
|
||||||
|
$extenders = array_merge([
|
||||||
|
new OverrideExtensionManagerForTests($this->extensions),
|
||||||
|
new BeginTransactionAndSetDatabase(function (ConnectionInterface $db) {
|
||||||
|
$this->database = $db;
|
||||||
|
}),
|
||||||
|
new SetSettingsBeforeBoot($this->settings),
|
||||||
|
], $this->extenders);
|
||||||
|
|
||||||
|
$site->extendWith($extenders);
|
||||||
|
|
||||||
|
$this->app = $site->bootApp();
|
||||||
|
|
||||||
|
$this->populateDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->app;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ExtenderInterface[]
|
||||||
|
*/
|
||||||
|
protected $extenders = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each argument should be an instance of an extender that should
|
||||||
|
* be applied at application boot.
|
||||||
|
*
|
||||||
|
* Note that this method will have no effect if called after the
|
||||||
|
* application is booted.
|
||||||
|
*/
|
||||||
|
protected function extend(ExtenderInterface ...$extenders)
|
||||||
|
{
|
||||||
|
$this->extenders = array_merge($this->extenders, $extenders);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
protected $extensions = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each argument should be an ID of an extension to be enabled.
|
||||||
|
* Extensions other than the one currently being tested must be
|
||||||
|
* listed in this extension's `composer.json` under `require` or
|
||||||
|
* `require-dev`.
|
||||||
|
*
|
||||||
|
* Note that this method will have no effect if called after the
|
||||||
|
* application is booted.
|
||||||
|
*/
|
||||||
|
protected function extension(string ...$extensions)
|
||||||
|
{
|
||||||
|
$this->extensions = array_merge($this->extensions, $extensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $config = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some Flarum code depends on config.php values. Flarum doesn't
|
||||||
|
* offer a way to set them at runtime, so this method lets you
|
||||||
|
* add/override them before boot.
|
||||||
|
*
|
||||||
|
* You can use dot-separated syntax to assign values to subarrays.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* `$this->config('a.b.c', 'value');` will result in the following:
|
||||||
|
*
|
||||||
|
* [
|
||||||
|
* 'a' => [
|
||||||
|
* 'b' => ['c' => 'value']
|
||||||
|
* ]
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
* Note that this method will have no effect if called after the
|
||||||
|
* application is booted.
|
||||||
|
*/
|
||||||
|
protected function config(string $key, $value)
|
||||||
|
{
|
||||||
|
$this->config[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $settings = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some settings are used during application boot, so setting
|
||||||
|
* them via `prepareDatabase` will be too late for the desired
|
||||||
|
* effect. For instance, in core the active display name driver
|
||||||
|
* is configured based on the `display_name_driver` setting.
|
||||||
|
* That setting should be registered using this method.
|
||||||
|
*
|
||||||
|
* Note that this method will have no effect if called after the
|
||||||
|
* application is booted.
|
||||||
|
*/
|
||||||
|
protected function setting(string $key, $value)
|
||||||
|
{
|
||||||
|
$this->settings[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
{
|
||||||
|
$this->app();
|
||||||
|
// Set in `BeginTransactionAndSetDatabase` extender.
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
44
php-packages/testing/src/integration/UsesTmpDir.php
Normal file
44
php-packages/testing/src/integration/UsesTmpDir.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Flarum\Testing\integration;
|
||||||
|
|
||||||
|
trait UsesTmpDir
|
||||||
|
{
|
||||||
|
public function tmpDir() {
|
||||||
|
return getenv('FLARUM_TEST_TMP_DIR_LOCAL') ?: getenv('FLARUM_TEST_TMP_DIR') ?: __DIR__.'/tmp';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setupTmpDir() {
|
||||||
|
$DIRS_NEEDED = [
|
||||||
|
'/',
|
||||||
|
'/public',
|
||||||
|
'/public/assets',
|
||||||
|
'/storage',
|
||||||
|
'/storage/formatter',
|
||||||
|
'/storage/sessions',
|
||||||
|
'/storage/views',
|
||||||
|
'/vendor',
|
||||||
|
'/vendor/composer'
|
||||||
|
];
|
||||||
|
|
||||||
|
$FILES_NEEDED = [
|
||||||
|
'/vendor/composer/installed.json' => '{}'
|
||||||
|
];
|
||||||
|
|
||||||
|
$tmpDir = $this->tmpDir();
|
||||||
|
|
||||||
|
foreach ($DIRS_NEEDED as $path) {
|
||||||
|
$fullPath = $tmpDir.$path;
|
||||||
|
if (!file_exists($fullPath)) {
|
||||||
|
mkdir($fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($FILES_NEEDED as $path => $contents) {
|
||||||
|
$fullPath = $tmpDir.$path;
|
||||||
|
if (!file_exists($fullPath)) {
|
||||||
|
file_put_contents($fullPath, $contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
php-packages/testing/src/unit/TestCase.php
Normal file
18
php-packages/testing/src/unit/TestCase.php
Normal 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;
|
||||||
|
}
|
1
php-packages/testing/tests/.gitignore
vendored
Normal file
1
php-packages/testing/tests/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
vendor/*
|
1
php-packages/testing/tests/README.md
Normal file
1
php-packages/testing/tests/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
A minimal extension skeleton to test the flarum/testing package.
|
35
php-packages/testing/tests/composer.json
Normal file
35
php-packages/testing/tests/composer.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "flarum/testing-tests",
|
||||||
|
"description": "Minimal extension to test the flarum/testing package",
|
||||||
|
"type": "flarum-extension",
|
||||||
|
"require": {
|
||||||
|
"flarum/core": "^0.1.0@dev"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"flarum/testing": "*@dev"
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"Flarum\\Testing\\Tests\\": "tests/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": [
|
||||||
|
"@test:unit",
|
||||||
|
"@test:integration"
|
||||||
|
],
|
||||||
|
"test:unit": "phpunit -c tests/phpunit.unit.xml",
|
||||||
|
"test:integration": "phpunit -c tests/phpunit.integration.xml",
|
||||||
|
"test:setup": "@php tests/integration/setup.php"
|
||||||
|
},
|
||||||
|
"scripts-descriptions": {
|
||||||
|
"test": "Runs all tests.",
|
||||||
|
"test:unit": "Runs all unit tests.",
|
||||||
|
"test:integration": "Runs all integration tests.",
|
||||||
|
"test:setup": "Sets up a database for use with integration tests. Execute this only once."
|
||||||
|
},
|
||||||
|
"repositories": [{
|
||||||
|
"type": "path",
|
||||||
|
"url": "../"
|
||||||
|
}]
|
||||||
|
}
|
19
php-packages/testing/tests/extend.php
Normal file
19
php-packages/testing/tests/extend.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of flarum/testing-tests.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 .
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.md
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Testing;
|
||||||
|
|
||||||
|
use Flarum\Extend;
|
||||||
|
|
||||||
|
return [
|
||||||
|
(new Extend\Settings)->serializeToForum('notARealSetting', 'not.a.real.setting'),
|
||||||
|
(new Extend\Frontend('forum'))->route('/added-by-extension', 'added-by-extension')
|
||||||
|
];
|
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Flarum\Testing;
|
||||||
|
|
||||||
|
use Flarum\Database\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
return Migration::createTable('testing_table', function (Blueprint $table) {
|
||||||
|
$table->string('id', 100)->primary();
|
||||||
|
});
|
1
php-packages/testing/tests/tests/.phpunit.result.cache
Normal file
1
php-packages/testing/tests/tests/.phpunit.result.cache
Normal file
@ -0,0 +1 @@
|
|||||||
|
C:37:"PHPUnit\Runner\DefaultTestResultCache":219:{a:2:{s:7:"defects";a:1:{s:74:"Flarum\Testing\Tests\integration\TestCaseTest::can_add_settings_via_method";i:4;}s:5:"times";a:1:{s:74:"Flarum\Testing\Tests\integration\TestCaseTest::can_add_settings_via_method";d:0.09;}}}
|
0
php-packages/testing/tests/tests/fixtures/.gitkeep
vendored
Normal file
0
php-packages/testing/tests/tests/fixtures/.gitkeep
vendored
Normal file
211
php-packages/testing/tests/tests/integration/TestCaseTest.php
Normal file
211
php-packages/testing/tests/tests/integration/TestCaseTest.php
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
<?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\Tests\integration;
|
||||||
|
|
||||||
|
use Flarum\Extend;
|
||||||
|
use Flarum\Foundation\Config;
|
||||||
|
use Flarum\Settings\SettingsRepositoryInterface;
|
||||||
|
use Flarum\Testing\integration\TestCase;
|
||||||
|
use Flarum\User\User;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Schema\Builder;
|
||||||
|
|
||||||
|
class TestCaseTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function admin_user_created_as_part_of_default_state()
|
||||||
|
{
|
||||||
|
$this->app();
|
||||||
|
|
||||||
|
$this->assertEquals(1, User::query()->count());
|
||||||
|
|
||||||
|
$user = User::find(1);
|
||||||
|
|
||||||
|
$this->assertEquals('admin', $user->username);
|
||||||
|
$this->assertEquals('admin@machine.local', $user->email);
|
||||||
|
$this->assertTrue($user->isAdmin());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function can_add_settings_via_method()
|
||||||
|
{
|
||||||
|
$this->setting('hello', 'world');
|
||||||
|
$this->setting('display_name_driver', 'something_other_than_username');
|
||||||
|
|
||||||
|
$settings = $this->app()->getContainer()->make(SettingsRepositoryInterface::class);
|
||||||
|
|
||||||
|
$this->assertEquals('world', $settings->get('hello'));
|
||||||
|
$this->assertEquals('something_other_than_username', $settings->get('display_name_driver'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function settings_cleaned_up_from_previous_method()
|
||||||
|
{
|
||||||
|
$settings = $this->app()->getContainer()->make(SettingsRepositoryInterface::class);
|
||||||
|
|
||||||
|
$this->assertEquals(null, $settings->get('hello'));
|
||||||
|
$this->assertEquals(null, $settings->get('display_name_driver'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function can_add_config_via_method()
|
||||||
|
{
|
||||||
|
$this->config('hello', 'world');
|
||||||
|
$this->config('url', 'https://flarum.org');
|
||||||
|
$this->config('level1.level2', 'value');
|
||||||
|
|
||||||
|
$config = $this->app()->getContainer()->make(Config::class);
|
||||||
|
|
||||||
|
$this->assertEquals('world', $config['hello']);
|
||||||
|
$this->assertEquals('https://flarum.org', $config['url']);
|
||||||
|
$this->assertEquals('value', $config['level1']['level2']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function config_cleaned_up_from_previous_method()
|
||||||
|
{
|
||||||
|
$config = $this->app()->getContainer()->make(Config::class);
|
||||||
|
|
||||||
|
$this->assertEquals(null, $config['hello']);
|
||||||
|
$this->assertEquals('http://localhost', $config['url']);
|
||||||
|
$this->assertFalse(isset($config['level1']['level2']));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function current_extension_not_applied_by_default()
|
||||||
|
{
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/')
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertStringNotContainsString('notARealSetting', $response->getBody()->getContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function current_extension_applied_if_specified()
|
||||||
|
{
|
||||||
|
$this->extension('flarum-testing-tests');
|
||||||
|
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/')
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertStringContainsString('notARealSetting', $response->getBody()->getContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function current_extension_migrations_applied_if_specified()
|
||||||
|
{
|
||||||
|
$this->extension('flarum-testing-tests');
|
||||||
|
|
||||||
|
$tableExists = $this->app()->getContainer()->make(Builder::class)->hasTable('testing_table');
|
||||||
|
$this->assertTrue($tableExists);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function current_extension_considered_enabled_after_boot()
|
||||||
|
{
|
||||||
|
$this->extension('flarum-testing-tests');
|
||||||
|
|
||||||
|
$enabled = $this->app()->getContainer()->make('flarum.extensions')->isEnabled('flarum-testing-tests');
|
||||||
|
$this->assertTrue($enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function can_apply_extenders()
|
||||||
|
{
|
||||||
|
$this->extend(
|
||||||
|
(new Extend\Settings)->serializeToForum('notARealSetting', 'not.a.real.setting')
|
||||||
|
);
|
||||||
|
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/')
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertStringContainsString('notARealSetting', $response->getBody()->getContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function can_apply_route_extenders()
|
||||||
|
{
|
||||||
|
$this->extend(
|
||||||
|
(new Extend\Frontend('forum'))->route('/arbitrary', 'arbitrary')
|
||||||
|
);
|
||||||
|
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/arbitrary')
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function routes_added_by_current_extension_not_accessible_by_default()
|
||||||
|
{
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/added-by-extension')
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(404, $response->getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function routes_added_by_current_extension_accessible()
|
||||||
|
{
|
||||||
|
$this->extension('flarum-testing-tests');
|
||||||
|
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/added-by-extension')
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function extension_url_correct()
|
||||||
|
{
|
||||||
|
$this->extension('flarum-testing-tests');
|
||||||
|
$expected = $this->app()->getContainer()->make('filesystem')->disk('flarum-assets')->url('/flarum-testing-tests/');
|
||||||
|
// We need to test this since we override it.
|
||||||
|
$extensions = $this->app()->getContainer()->make('flarum.extensions');
|
||||||
|
$currExtension = $extensions->getExtension('flarum-testing-tests');
|
||||||
|
$baseAssetsUrl = $extensions->getAsset($currExtension, '');
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $baseAssetsUrl);
|
||||||
|
}
|
||||||
|
}
|
16
php-packages/testing/tests/tests/integration/setup.php
Normal file
16
php-packages/testing/tests/tests/integration/setup.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?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\Testing\integration\Setup\SetupScript;
|
||||||
|
|
||||||
|
require __DIR__.'/../../vendor/autoload.php';
|
||||||
|
|
||||||
|
$setup = new SetupScript();
|
||||||
|
|
||||||
|
$setup->run();
|
24
php-packages/testing/tests/tests/phpunit.integration.xml
Normal file
24
php-packages/testing/tests/tests/phpunit.integration.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<phpunit
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
|
||||||
|
backupGlobals="false"
|
||||||
|
backupStaticAttributes="false"
|
||||||
|
colors="true"
|
||||||
|
convertErrorsToExceptions="true"
|
||||||
|
convertNoticesToExceptions="true"
|
||||||
|
convertWarningsToExceptions="true"
|
||||||
|
processIsolation="true"
|
||||||
|
stopOnFailure="false"
|
||||||
|
>
|
||||||
|
<coverage processUncoveredFiles="true">
|
||||||
|
<include>
|
||||||
|
<directory suffix=".php">../src/</directory>
|
||||||
|
</include>
|
||||||
|
</coverage>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Flarum Integration Tests">
|
||||||
|
<directory suffix="Test.php">./integration</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
</phpunit>
|
27
php-packages/testing/tests/tests/phpunit.unit.xml
Normal file
27
php-packages/testing/tests/tests/phpunit.unit.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<phpunit
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
|
||||||
|
backupGlobals="false"
|
||||||
|
backupStaticAttributes="false"
|
||||||
|
colors="true"
|
||||||
|
convertErrorsToExceptions="true"
|
||||||
|
convertNoticesToExceptions="true"
|
||||||
|
convertWarningsToExceptions="true"
|
||||||
|
processIsolation="false"
|
||||||
|
stopOnFailure="false"
|
||||||
|
>
|
||||||
|
<coverage processUncoveredFiles="true">
|
||||||
|
<include>
|
||||||
|
<directory suffix=".php">../src/</directory>
|
||||||
|
</include>
|
||||||
|
</coverage>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Flarum Unit Tests">
|
||||||
|
<directory suffix="Test.php">./unit</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
<listeners>
|
||||||
|
<listener class="\Mockery\Adapter\Phpunit\TestListener" />
|
||||||
|
</listeners>
|
||||||
|
</phpunit>
|
0
php-packages/testing/tests/tests/unit/.gitkeep
Normal file
0
php-packages/testing/tests/tests/unit/.gitkeep
Normal file
Loading…
x
Reference in New Issue
Block a user