You've already forked Php-Template
tests
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
.idea/
|
.idea/
|
||||||
vendor/
|
vendor/
|
||||||
|
.phpunit.cache/
|
||||||
@@ -9,9 +9,15 @@ Unit Tests:
|
|||||||
when: always
|
when: always
|
||||||
- when: never
|
- when: never
|
||||||
image: siteworxpro/composer
|
image: siteworxpro/composer
|
||||||
|
before_script: |
|
||||||
|
bin/pcov.sh
|
||||||
script:
|
script:
|
||||||
- echo "Running unit tests..."
|
- echo "Running unit tests..."
|
||||||
- composer run tests:unit
|
- composer run tests:unit
|
||||||
|
artifacts:
|
||||||
|
expire_in: 1 day
|
||||||
|
paths:
|
||||||
|
- tests/reports/
|
||||||
|
|
||||||
Run License Check:
|
Run License Check:
|
||||||
stage: tests
|
stage: tests
|
||||||
@@ -42,15 +48,15 @@ Run Code Lint:
|
|||||||
- composer run tests:lint
|
- composer run tests:lint
|
||||||
|
|
||||||
Run Code Sniffer:
|
Run Code Sniffer:
|
||||||
stage: tests
|
stage: tests
|
||||||
needs:
|
needs:
|
||||||
- Install Composer Libraries
|
- Install Composer Libraries
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_TAG'
|
- if: '$CI_COMMIT_TAG'
|
||||||
when: never
|
when: never
|
||||||
- if: '$CI_PIPELINE_SOURCE == "push"'
|
- if: '$CI_PIPELINE_SOURCE == "push"'
|
||||||
when: on_success
|
when: on_success
|
||||||
- when: never
|
- when: never
|
||||||
image: siteworxpro/composer
|
image: siteworxpro/composer
|
||||||
script:
|
script:
|
||||||
- composer run tests:phpstan
|
- composer run tests:phpstan
|
||||||
1
.phpunit.cache/test-results
Normal file
1
.phpunit.cache/test-results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":1,"defects":[],"times":{"Siteworxpro\\Tests\\Helpers\\EnvTest::testGetReturnsStringByDefault":0.004,"Siteworxpro\\Tests\\Helpers\\EnvTest::testGetReturnsDefaultIfKeyNotSet":0,"Siteworxpro\\Tests\\Helpers\\EnvTest::testGetCastsToBoolean":0,"Siteworxpro\\Tests\\Helpers\\EnvTest::testGetCastsToInteger":0,"Siteworxpro\\Tests\\Helpers\\EnvTest::testGetCastsToFloat":0,"Siteworxpro\\Tests\\Http\\JsonResponseFactoryTest::testCreateJsonResponseReturnsValidResponse":0.002,"Siteworxpro\\Tests\\Http\\JsonResponseFactoryTest::testCreateJsonResponseHandlesEmptyData":0,"Siteworxpro\\Tests\\Http\\JsonResponseFactoryTest::testCreateJsonResponseThrowsExceptionOnInvalidData":0.001,"Siteworxpro\\Tests\\Http\\Middleware\\CorsMiddlewareTest::testAllowsConfiguredOrigin":0.015,"Siteworxpro\\Tests\\Http\\Middleware\\CorsMiddlewareTest::testBlocksUnconfiguredOrigin":0.001,"Siteworxpro\\Tests\\Http\\Middleware\\CorsMiddlewareTest::testHandlesOptionsRequest":0,"Siteworxpro\\Tests\\Http\\Middleware\\CorsMiddlewareTest::testAddsAllowCredentialsHeader":0}}
|
||||||
@@ -1 +1,5 @@
|
|||||||
# Template
|
# Template
|
||||||
|
|
||||||
|
```shell
|
||||||
|
export PHP_IDE_CONFIG=serverName=localhost
|
||||||
|
```
|
||||||
|
|||||||
19
bin/pcov.sh
Executable file
19
bin/pcov.sh
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
apk --no-cache add pcre-dev ${PHPIZE_DEPS}
|
||||||
|
|
||||||
|
git clone https://github.com/krakjoe/pcov.git
|
||||||
|
cd pcov || exec
|
||||||
|
phpize
|
||||||
|
./configure --enable-pcov
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
|
||||||
|
echo "extension=pcov.so" > /usr/local/etc/php/conf.d/docker-php-ext-pcov.ini
|
||||||
|
echo "pcov.enabled=1" >> /usr/local/etc/php/conf.d/docker-php-ext-pcov.ini
|
||||||
|
echo "pcov.directory=." >> /usr/local/etc/php/conf.d/docker-php-ext-pcov.ini
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
cd ..
|
||||||
|
rm -rf pcov
|
||||||
24
bin/xdebug.sh
Executable file
24
bin/xdebug.sh
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
echo "Installing xDebug"
|
||||||
|
|
||||||
|
apk add make gcc linux-headers autoconf alpine-sdk
|
||||||
|
|
||||||
|
curl -sL https://github.com/xdebug/xdebug/archive/3.4.0.tar.gz -o 3.4.0.tar.gz
|
||||||
|
tar -xvf 3.4.0.tar.gz
|
||||||
|
cd xdebug-3.4.0 || exit
|
||||||
|
phpize
|
||||||
|
./configure --enable-xdebug
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
|
||||||
|
echo "
|
||||||
|
zend_extension=xdebug.so
|
||||||
|
xdebug.mode=debug
|
||||||
|
xdebug.start_with_request = yes
|
||||||
|
xdebug.client_host = host.docker.internal
|
||||||
|
" > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
rm -rf xdebug-3.4.0
|
||||||
|
rm -rf 3.4.0.tar.gz
|
||||||
@@ -28,11 +28,14 @@
|
|||||||
"tests:unit": [
|
"tests:unit": [
|
||||||
"phpunit --colors=always --display-deprecations tests "
|
"phpunit --colors=always --display-deprecations tests "
|
||||||
],
|
],
|
||||||
|
"tests:unit:coverage": [
|
||||||
|
"phpunit --colors=always --display-deprecations --coverage-html tests/reports/html tests "
|
||||||
|
],
|
||||||
"tests:lint": [
|
"tests:lint": [
|
||||||
"phpcs ./src --standard=PSR12 --colors -v",
|
"phpcs ./src --standard=PSR12 --colors -v",
|
||||||
"phpcs ./tests --standard=PSR12 --colors -v"
|
"phpcs ./tests --standard=PSR12 --colors -v"
|
||||||
],
|
],
|
||||||
"tests:lint-fix": [
|
"tests:lint:fix": [
|
||||||
"phpcbf ./src --standard=PSR12 --colors -v",
|
"phpcbf ./src --standard=PSR12 --colors -v",
|
||||||
"phpcbf ./tests --standard=PSR12 --colors -v"
|
"phpcbf ./tests --standard=PSR12 --colors -v"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ return [
|
|||||||
'password' => Env::get('DB_PASSWORD', 'password'),
|
'password' => Env::get('DB_PASSWORD', 'password'),
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
'cors' => [
|
'cors' => [
|
||||||
'allowed_origins' => Env::get('CORS_ALLOWED_ORIGINS', 'http://localhost:3000'),
|
'allowed_origins' => Env::get('CORS_ALLOWED_ORIGINS', 'localhost:3000'),
|
||||||
'allow_credentials' => Env::get('CORS_ALLOW_CREDENTIALS', true, 'bool'),
|
'allow_credentials' => Env::get('CORS_ALLOW_CREDENTIALS', true, 'bool'),
|
||||||
'max_age' => Env::get('CORS_MAX_AGE', 3600, 'int'),
|
'max_age' => Env::get('CORS_MAX_AGE', ''),
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
24
phpunit.xml
Normal file
24
phpunit.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="vendor/phpunit/phpunit/phpunit.xsd"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
cacheDirectory=".phpunit.cache"
|
||||||
|
executionOrder="depends,defects"
|
||||||
|
beStrictAboutCoverageMetadata="true"
|
||||||
|
beStrictAboutOutputDuringTests="true"
|
||||||
|
displayDetailsOnPhpunitDeprecations="true"
|
||||||
|
failOnPhpunitDeprecation="true"
|
||||||
|
failOnRisky="true"
|
||||||
|
failOnWarning="true">
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="default">
|
||||||
|
<directory>tests</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
|
||||||
|
<source ignoreIndirectDeprecations="true" restrictNotices="true" restrictWarnings="true">
|
||||||
|
<include>
|
||||||
|
<directory>src</directory>
|
||||||
|
</include>
|
||||||
|
</source>
|
||||||
|
</phpunit>
|
||||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Siteworxpro\App\Facades;
|
namespace Siteworxpro\App\Facades;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||||
use Illuminate\Support\Facades\Facade;
|
use Illuminate\Support\Facades\Facade;
|
||||||
use Siteworx\Config\Exception\EmptyDirectoryException;
|
use Siteworx\Config\Exception\EmptyDirectoryException;
|
||||||
use Siteworx\Config\Exception\FileNotFoundException;
|
use Siteworx\Config\Exception\FileNotFoundException;
|
||||||
@@ -21,6 +22,10 @@ use Siteworx\Config\Exception\UnsupportedFormatException;
|
|||||||
*/
|
*/
|
||||||
class Config extends Facade
|
class Config extends Facade
|
||||||
{
|
{
|
||||||
|
|
||||||
|
protected static $cached = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws UnsupportedFormatException
|
* @throws UnsupportedFormatException
|
||||||
* @throws FileNotFoundException
|
* @throws FileNotFoundException
|
||||||
@@ -28,6 +33,17 @@ class Config extends Facade
|
|||||||
*/
|
*/
|
||||||
public static function getFacadeRoot(): \Siteworx\Config\Config
|
public static function getFacadeRoot(): \Siteworx\Config\Config
|
||||||
{
|
{
|
||||||
|
if (self::$resolvedInstance !== null) {
|
||||||
|
try {
|
||||||
|
$config = self::resolveFacadeInstance(self::getFacadeAccessor());
|
||||||
|
if ($config instanceof \Siteworx\Config\Config) {
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
} catch (BindingResolutionException) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return \Siteworx\Config\Config::load(__DIR__ . '/../../config.php');
|
return \Siteworx\Config\Config::load(__DIR__ . '/../../config.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +54,6 @@ class Config extends Facade
|
|||||||
*/
|
*/
|
||||||
protected static function getFacadeAccessor(): string
|
protected static function getFacadeAccessor(): string
|
||||||
{
|
{
|
||||||
return 'config';
|
return \Siteworx\Config\Config::class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ class Logger extends Facade
|
|||||||
{
|
{
|
||||||
public static function getFacadeRoot(): RRLogger
|
public static function getFacadeRoot(): RRLogger
|
||||||
{
|
{
|
||||||
|
if (self::$resolvedInstance !== null) {
|
||||||
|
$logger = self::resolveFacadeInstance(self::getFacadeAccessor());
|
||||||
|
|
||||||
|
if ($logger instanceof RRLogger) {
|
||||||
|
return $logger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$rpc = RPC::create('tcp://127.0.0.1:6001');
|
$rpc = RPC::create('tcp://127.0.0.1:6001');
|
||||||
|
|
||||||
return new RRLogger($rpc);
|
return new RRLogger($rpc);
|
||||||
|
|||||||
@@ -13,10 +13,11 @@ use Nyholm\Psr7\Response;
|
|||||||
*/
|
*/
|
||||||
class JsonResponseFactory
|
class JsonResponseFactory
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a JSON response with the given data and status code.
|
* Create a JSON response with the given data and status code.
|
||||||
*
|
*
|
||||||
* @param array $data The data to include in the response.
|
* @param mixed $data The data to include in the response.
|
||||||
* @param int $statusCode The HTTP status code for the response.
|
* @param int $statusCode The HTTP status code for the response.
|
||||||
* @return Response The JSON response.
|
* @return Response The JSON response.
|
||||||
* @throws \JsonException
|
* @throws \JsonException
|
||||||
@@ -31,4 +32,4 @@ class JsonResponseFactory
|
|||||||
body: json_encode($data, JSON_THROW_ON_ERROR)
|
body: json_encode($data, JSON_THROW_ON_ERROR)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ class CorsMiddleware implements MiddlewareInterface
|
|||||||
|
|
||||||
$allowOrigin = in_array($origin, $allowedOrigins, true)
|
$allowOrigin = in_array($origin, $allowedOrigins, true)
|
||||||
? $origin
|
? $origin
|
||||||
: 'null';
|
: null;
|
||||||
|
|
||||||
if ($request->getMethod() === 'OPTIONS') {
|
if ($request->getMethod() === 'OPTIONS') {
|
||||||
$response = new Response(204);
|
$response = new Response(204);
|
||||||
@@ -48,6 +48,10 @@ class CorsMiddleware implements MiddlewareInterface
|
|||||||
$response = $handler->handle($request);
|
$response = $handler->handle($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($allowOrigin === null) {
|
||||||
|
return $response; // Do not add CORS headers if origin is not allowed.
|
||||||
|
}
|
||||||
|
|
||||||
$response = $response
|
$response = $response
|
||||||
->withHeader('Access-Control-Allow-Origin', $allowOrigin)
|
->withHeader('Access-Control-Allow-Origin', $allowOrigin)
|
||||||
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS')
|
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS')
|
||||||
@@ -61,8 +65,9 @@ class CorsMiddleware implements MiddlewareInterface
|
|||||||
$response = $response->withHeader('Access-Control-Allow-Credentials', 'true');
|
$response = $response->withHeader('Access-Control-Allow-Credentials', 'true');
|
||||||
}
|
}
|
||||||
|
|
||||||
$maxAge = Config::get('CORS_MAX_AGE') !== 3600 ? Config::get('CORS_MAX_AGE') : 3600;
|
$maxAge = Config::get('cors.max_age') ?: '86400'; // Use correct configuration key.
|
||||||
|
|
||||||
return $response->withHeader('Access-Control-Max-Age', $maxAge);
|
return $response->withHeader('Access-Control-Max-Age', $maxAge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Siteworxpro\App;
|
namespace Siteworxpro\App;
|
||||||
|
|
||||||
|
use Illuminate\Container\Container;
|
||||||
|
use Illuminate\Support\Facades\Facade;
|
||||||
use League\Route\Http\Exception\MethodNotAllowedException;
|
use League\Route\Http\Exception\MethodNotAllowedException;
|
||||||
use League\Route\Http\Exception\NotFoundException;
|
use League\Route\Http\Exception\NotFoundException;
|
||||||
use League\Route\Router;
|
use League\Route\Router;
|
||||||
@@ -58,6 +60,9 @@ class Server
|
|||||||
*/
|
*/
|
||||||
private function boot(): void
|
private function boot(): void
|
||||||
{
|
{
|
||||||
|
$container = new Container();
|
||||||
|
Facade::setFacadeApplication($container);
|
||||||
|
|
||||||
$this->worker = new PSR7Worker(
|
$this->worker = new PSR7Worker(
|
||||||
Worker::create(),
|
Worker::create(),
|
||||||
new Psr17Factory(),
|
new Psr17Factory(),
|
||||||
|
|||||||
@@ -16,9 +16,12 @@ class CorsMiddlewareTest extends Unit
|
|||||||
public function testAllowsConfiguredOrigin(): void
|
public function testAllowsConfiguredOrigin(): void
|
||||||
{
|
{
|
||||||
Config::shouldReceive('get')
|
Config::shouldReceive('get')
|
||||||
->with('CORS_ALLOWED_ORIGINS', 'https://example.com,https://another.com')
|
->with('cors.allowed_origins')
|
||||||
->andReturn('https://example.com,https://another.com');
|
->andReturn('https://example.com,https://another.com');
|
||||||
|
|
||||||
|
Config::shouldReceive('get')->with('cors.allow_credentials')->andReturn(false);
|
||||||
|
Config::shouldReceive('get')->with('cors.max_age')->andReturn('');
|
||||||
|
|
||||||
$middleware = new CorsMiddleware();
|
$middleware = new CorsMiddleware();
|
||||||
$request = new ServerRequest('GET', '/')->withHeader('Origin', 'https://example.com');
|
$request = new ServerRequest('GET', '/')->withHeader('Origin', 'https://example.com');
|
||||||
$handler = $this->mockHandler(new Response(200));
|
$handler = $this->mockHandler(new Response(200));
|
||||||
@@ -31,7 +34,7 @@ class CorsMiddlewareTest extends Unit
|
|||||||
public function testBlocksUnconfiguredOrigin(): void
|
public function testBlocksUnconfiguredOrigin(): void
|
||||||
{
|
{
|
||||||
Config::shouldReceive('get')
|
Config::shouldReceive('get')
|
||||||
->with('CORS_ALLOWED_ORIGINS', 'https://example.com,https://another.com')
|
->with('cors.allowed_origins')
|
||||||
->andReturn('https://example.com,https://another.com');
|
->andReturn('https://example.com,https://another.com');
|
||||||
|
|
||||||
$middleware = new CorsMiddleware();
|
$middleware = new CorsMiddleware();
|
||||||
@@ -40,14 +43,14 @@ class CorsMiddlewareTest extends Unit
|
|||||||
|
|
||||||
$response = $middleware->process($request, $handler);
|
$response = $middleware->process($request, $handler);
|
||||||
|
|
||||||
$this->assertEquals('null', $response->getHeaderLine('Access-Control-Allow-Origin'));
|
$this->assertEmpty($response->getHeaderLine('Access-Control-Allow-Origin'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testHandlesOptionsRequest(): void
|
public function testHandlesOptionsRequest(): void
|
||||||
{
|
{
|
||||||
Config::shouldReceive('get')->with('CORS_ALLOWED_ORIGINS', '...')->andReturn('https://example.com');
|
Config::shouldReceive('get')->with('cors.allowed_origins')->andReturn('https://example.com');
|
||||||
Config::shouldReceive('get')->with('CORS_ALLOW_CREDENTIALS', 'bool')->andReturn(false);
|
Config::shouldReceive('get')->with('cors.allow_credentials')->andReturn(false);
|
||||||
Config::shouldReceive('get')->with('CORS_MAX_AGE')->andReturn('86400');
|
Config::shouldReceive('get')->with('cors.max_age')->andReturn('86400');
|
||||||
|
|
||||||
$middleware = new CorsMiddleware();
|
$middleware = new CorsMiddleware();
|
||||||
$request = new ServerRequest('OPTIONS', '/')->withHeader('Origin', 'https://example.com');
|
$request = new ServerRequest('OPTIONS', '/')->withHeader('Origin', 'https://example.com');
|
||||||
@@ -61,8 +64,13 @@ class CorsMiddlewareTest extends Unit
|
|||||||
|
|
||||||
public function testAddsAllowCredentialsHeader(): void
|
public function testAddsAllowCredentialsHeader(): void
|
||||||
{
|
{
|
||||||
Config::shouldReceive('get')->with('CORS_ALLOWED_ORIGINS', '...')->andReturn('https://example.com');
|
Config::shouldReceive('get')
|
||||||
Config::shouldReceive('get')->with('CORS_ALLOW_CREDENTIALS', 'bool')->andReturn(true);
|
->with('cors.allowed_origins')
|
||||||
|
->andReturn('https://example.com');
|
||||||
|
|
||||||
|
Config::shouldReceive('get')->with('cors.allowed_origins')->andReturn('https://example.com');
|
||||||
|
Config::shouldReceive('get')->with('cors.allow_credentials')->andReturn(true);
|
||||||
|
Config::shouldReceive('get')->with('cors.max_age')->andReturn('86400');
|
||||||
|
|
||||||
$middleware = new CorsMiddleware();
|
$middleware = new CorsMiddleware();
|
||||||
$request = new ServerRequest('GET', '/')->withHeader('Origin', 'https://example.com');
|
$request = new ServerRequest('GET', '/')->withHeader('Origin', 'https://example.com');
|
||||||
@@ -91,3 +99,4 @@ class CorsMiddlewareTest extends Unit
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,22 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Siteworxpro\Tests;
|
namespace Siteworxpro\Tests;
|
||||||
|
|
||||||
|
use Illuminate\Container\Container;
|
||||||
|
use Illuminate\Support\Facades\Facade;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Siteworxpro\App\Facades\Config;
|
||||||
|
|
||||||
abstract class Unit extends TestCase
|
abstract class Unit extends TestCase
|
||||||
{
|
{
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$container = new Container();
|
||||||
|
Facade::setFacadeApplication($container);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
Config::clearResolvedInstances();
|
||||||
|
Facade::setFacadeApplication(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
tests/reports/.gitignore
vendored
Normal file
1
tests/reports/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
html/
|
||||||
Reference in New Issue
Block a user