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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: PHP Unitary

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
workflow_dispatch:

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
env:
COMPOSER_ROOT_VERSION: 2.x-dev

steps:
- uses: actions/checkout@v4

- name: Cache Composer packages
uses: actions/cache@v3
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-

- name: Install dependencies
run: composer install --prefer-dist --no-progress

- name: Run test suite
run: php bin/unitary
2 changes: 1 addition & 1 deletion bin/unitary
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ $app = (new Application())
->boot([
"argv" => $argv,
"dir" => getcwd()
]);
]);
12 changes: 11 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
"homepage": "https://maplephp.github.io/Unitary/"
}
],
"scripts": {
"test": "php bin/unitary"
},
"require": {
"php": ">=8.0",
"composer/semver": "^3.4",
Expand All @@ -45,5 +48,12 @@
"bin": [
"bin/unitary"
],
"minimum-stability": "stable"
"extra": {
"branch-alias": {
"dev-main": "2.x-dev",
"dev-develop": "2.x-dev"
}
},
"minimum-stability": "dev",
"prefer-stable": true
}
6 changes: 5 additions & 1 deletion src/Config/ConfigProps.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,21 @@
*/
class ConfigProps extends AbstractConfigProps
{
public ?string $path = null;
public ?string $discoverPattern = null;
public ?string $exclude = null;
public ?string $show = null;
public ?string $timezone = null;
public ?string $locale = null;
public ?string $type = null;
public ?string $path = null;
public ?int $exitCode = null;
public ?bool $verbose = null;
public ?bool $alwaysShowFiles = null;
public ?bool $errorsOnly = null;
public ?bool $smartSearch = null;
public ?bool $failFast = null;
public ?string $helpController = null;
public ?array $configuration = null;

/**
* Hydrate the properties/object with expected data, and handle unexpected data
Expand Down Expand Up @@ -93,6 +94,9 @@ protected function propsHydration(string|bool $key, mixed $value): void
case 'failFast':
$this->failFast = $this->dataToBool($value);
break;
case 'configuration':
$this->configuration = (array)$value;
break;
}
}

Expand Down
59 changes: 52 additions & 7 deletions src/Console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@

final class Application
{
private array $middlewares = [
AddCommandMiddleware::class,
ConfigPropsMiddleware::class,
CheckAllowedProps::class,
LocalMiddleware::class,
CliInitMiddleware::class
];

public function __construct()
{
// Default config
Expand All @@ -29,6 +37,49 @@ public function __construct()
EmitronKernel::setRouterFilePath(__DIR__ . "/ConsoleRouter.php");
}

/**
* Clear the default middlewares, be careful with this
*
* @return $this
*/
public function clearDefaultMiddleware(): self
{
$inst = clone $this;
$inst->middlewares = [];
return $inst;
}

/**
* Clear the default middlewares, be careful with this
*
* @return $this
*/
public function unsetMiddleware(string $class): self
{

$inst = clone $this;
foreach($inst->middlewares as $key => $middleware) {
if($middleware === $class) {
unset($inst->middlewares[$key]);
break;
}
}
return $inst;
}

/**
* Add custom middlewares, follow PSR convention
*
* @param array $middleware
* @return $this
*/
public function withMiddleware(array $middleware): self
{
$inst = clone $this;
$inst->middlewares = array_merge($inst->middlewares, $middleware);
return $inst;
}

/**
* Change router file
*
Expand Down Expand Up @@ -84,13 +135,7 @@ public function boot(array $parts): Kernel
{
$env = new Environment();
$request = new ServerRequest(new Uri($env->getUriParts($parts)), $env);
$kernel = new Kernel(new Container(), [
AddCommandMiddleware::class,
ConfigPropsMiddleware::class,
CheckAllowedProps::class,
LocalMiddleware::class,
CliInitMiddleware::class
]);
$kernel = new Kernel(new Container(), $this->middlewares);
$kernel->run($request);
return $kernel;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Console/Controllers/DefaultController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace MaplePHP\Unitary\Console\Controllers;

use MaplePHP\Emitron\Contracts\ConfigPropsInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
Expand All @@ -10,7 +11,6 @@
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use MaplePHP\Prompts\Command;
use MaplePHP\Unitary\Config\ConfigProps;
use MaplePHP\Validate\Validator;

abstract class DefaultController
Expand All @@ -20,7 +20,7 @@ abstract class DefaultController
protected Command $command;
protected DispatchConfigInterface $configs;
protected array $args;
protected ?ConfigProps $props = null;
protected ?ConfigPropsInterface $props = null;
protected string|bool $path;

/**
Expand Down
3 changes: 2 additions & 1 deletion src/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Exception;
use MaplePHP\Emitron\Contracts\DispatchConfigInterface;
use MaplePHP\Emitron\DispatchConfig;
use MaplePHP\Unitary\Config\ConfigProps;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamInterface;
use MaplePHP\Unitary\Support\Router;
Expand Down Expand Up @@ -72,7 +73,7 @@ public function run(ServerRequestInterface $request, ?StreamInterface $stream =
*/
private function configuration(ServerRequestInterface $request): DispatchConfigInterface
{
$config = new DispatchConfig(EmitronKernel::getConfigFilePath());
$config = new DispatchConfig(EmitronKernel::getConfigFilePath(), ConfigProps::class);
return $config
->setRouter(function ($routerFile) use ($request) {
$router = new Router($request->getCliKeyword(), $request->getCliArgs());
Expand Down
13 changes: 7 additions & 6 deletions src/Console/Middlewares/ConfigPropsMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace MaplePHP\Unitary\Console\Middlewares;

use MaplePHP\Emitron\Configs\ConfigPropsFactory;
use MaplePHP\Emitron\Contracts\ConfigPropsInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
Expand All @@ -15,7 +17,7 @@
class ConfigPropsMiddleware implements MiddlewareInterface
{

protected ?ConfigProps $props = null;
protected ?ConfigPropsInterface $props = null;
private ContainerInterface $container;

/**
Expand Down Expand Up @@ -56,7 +58,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private function getInitProps(): ConfigProps
private function getInitProps(): ConfigPropsInterface
{
if ($this->props === null) {
$args = $this->container->get("args");
Expand All @@ -65,14 +67,13 @@ private function getInitProps(): ConfigProps

try {
$props = array_merge($configs->getProps()->toArray(), $args);
$this->props = new ConfigProps($props);

$this->props = ConfigPropsFactory::create($props, $configs->getConfigPropsClass());
if ($this->props->hasMissingProps() !== [] && isset($args['verbose'])) {
$command->error('The properties (' .
implode(", ", $this->props->hasMissingProps()) . ') is not exist in config props');
implode(", ", $this->props->hasMissingProps()) . ') is not exist in ' . get_class($this->props));
$command->message(
"One or more arguments you passed are not recognized as valid options.\n" .
"Check your command syntax or configuration."
"Check your command parameter syntax for spellings or configuration."
);
}

Expand Down
8 changes: 6 additions & 2 deletions src/Console/Middlewares/LocalMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ public function __construct(ContainerInterface $container)
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$props = $this->container->get("props");
Clock::setDefaultLocale($props->locale);
Clock::setDefaultTimezone($props->timezone);
if($props->locale !== null) {
Clock::setDefaultLocale($props->locale);
}
if($props->timezone !== null) {
Clock::setDefaultTimezone($props->timezone);
}
return $handler->handle($request);
}
}
4 changes: 2 additions & 2 deletions src/Console/Services/AbstractMainService.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace MaplePHP\Unitary\Console\Services;

use MaplePHP\Emitron\Contracts\ConfigPropsInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
Expand All @@ -10,7 +11,6 @@
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use MaplePHP\Prompts\Command;
use MaplePHP\Unitary\Config\ConfigProps;

abstract class AbstractMainService
{
Expand All @@ -20,7 +20,7 @@ abstract class AbstractMainService
protected Command $command;
protected DispatchConfigInterface $configs;
protected ServerRequestInterface|RequestInterface $request;
protected ?ConfigProps $props = null;
protected ?ConfigPropsInterface $props = null;

/**
* @throws NotFoundExceptionInterface
Expand Down
13 changes: 5 additions & 8 deletions src/Discovery/TestDiscovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,14 +202,11 @@ private function executeUnitFile(string $file): void
$ok = self::$unitary->execute();

if (!$ok && $verbose) {
trigger_error(
"\n\nCould not find any tests inside the test file:\n$file\n\nPossible causes:\n" .
" • There are no test in test group/case.\n" .
" • Unitary could not locate the Unit instance.\n" .
" • You did not use the `group()` function.\n" .
" • You created a new Unit in the test file but did not return it at the end.\n\n",
E_USER_WARNING
);
throw new BlunderSoftException("Could not find any tests inside the test file: $file\n\nPossible causes:\n" .
" • There are no test in test group/case.\n" .
" • Unitary could not locate the Unit instance.\n" .
" • You did not use the `group()` function.\n" .
" • You created a new Unit in the test file but did not return it at the end.\n\n", 0, 0, $file);
}

}
Expand Down
6 changes: 6 additions & 0 deletions src/Expect.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ public static function value(mixed $value): self
return new self($value);
}


public function expect(mixed $value): self
{
return $this->setValue($value);
}

/**
* We need to pass a test case to Exception to create one loop
*
Expand Down
1 change: 0 additions & 1 deletion src/Support/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

final class Helpers
{

/**
* Convert bytes to megabytes and return as a string with fixed precision.
*
Expand Down
20 changes: 17 additions & 3 deletions src/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -355,12 +355,26 @@ public function validate(mixed $expect, Closure $validation): TestUnit
*
* @param mixed $value
* @return Expect
* @throws ErrorException
*/
public function expect(mixed $value): Expect
{
$this->value = $value;
$this->expect = new Expect($value);
$this->expect->setTestCase($this, debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[0] ?? []);

if(is_callable($value)) {
$validation = $value;
$expectInst = null;
$this->testUnit = $this->expectAndValidate(null, function (mixed $value, Expect $inst) use ($validation, &$expectInst) {
$expectInst = $inst;
return $validation($inst, new Traverse($value));
}, $this->error);

$this->expect = $expectInst;
$this->testUnit->setTestValue($this->expect->getValue());
} else {
$this->value = $value;
$this->expect = new Expect($value);
$this->expect->setTestCase($this, debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[0] ?? []);
}
return $this->expect;
}

Expand Down
3 changes: 2 additions & 1 deletion src/TestItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ public function getStringifyArgs(): string
{
if ($this->hasArgs) {
$args = array_map(fn ($value) => Helpers::stringifyArgs($value), $this->args);
return "(" . implode(", ", $args) . ")";
$args = preg_replace('/\R+/', '', implode(", ", $args));
return "(" . $args . ")";
}
return "";
}
Expand Down
Loading