Skip to content

Commit

Permalink
tests: initial Generator tests (#141)
Browse files Browse the repository at this point in the history
  • Loading branch information
dkarlovi authored Jul 19, 2022
1 parent 10c112c commit f4156ea
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 29 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"league/commonmark": "^2.3",
"phpdocumentor/type-resolver": "^1.0",
"phpstan/phpdoc-parser": "^1.0",
"sigwin/infra": "^0.6",
"sigwin/infra": "^0.7",
"spatie/commonmark-highlighter": "^3.0",
"symfony/console": "^5.4 || ^6.0",
"symfony/expression-language": "^5.4 || ^6.0",
Expand Down Expand Up @@ -38,7 +38,7 @@
"autoload-dev": {
"psr-4": {
"App\\": "tests/functional/init/src/",
"Sigwin\\YASSG\\Test\\": "tests/",
"Sigwin\\YASSG\\Test\\": "tests/unit",
"Sigwin\\YASSG\\Test\\Functional\\Site\\": "tests/functional/site/src/"
}
},
Expand Down
5 changes: 4 additions & 1 deletion infection.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
"mutators": {
"@default": true,
"IdenticalEqual": false,
"NotIdenticalNotEqual": false
"NotIdenticalNotEqual": false,
"UnwrapRtrim": false,
"CastBool": false,
"MBString": false
}
}
36 changes: 18 additions & 18 deletions src/Bridge/Symfony/ExpressionLanguage/FunctionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,30 @@ public function getFunctions(): array
return [
new ExpressionFunction('yassg_find_all', static function (string $name): string {
return sprintf('$provider->getDatabase(%s)', $name);
}, static function (array $variables, string $name, array $arguments = []) {
/** @var DatabaseProvider $provider */
$provider = $variables['provider'];
}, static function (array $variables, string $name, array $arguments = []) {
/** @var DatabaseProvider $provider */
$provider = $variables['provider'];

return $provider->getDatabase($name)->findAll(...$arguments);
}),
return $provider->getDatabase($name)->findAll(...$arguments);
}),
new ExpressionFunction('yassg_pages', static function (string $name): string {
return sprintf('$provider->getDatabase(%s)', $name);
}, static function (array $variables, string $name, ?string $condition = null, ?int $limit = null) {
/** @var DatabaseProvider $provider */
$provider = $variables['provider'];
$database = $provider->getDatabase($name);
$count = $database->count($condition);

return range(1, ceil($count / ($limit ?? $database->getPageLimit())));
}),
}, static function (array $variables, string $name, ?string $condition = null, ?int $limit = null) {
/** @var DatabaseProvider $provider */
$provider = $variables['provider'];
$database = $provider->getDatabase($name);
$count = $database->count($condition);

return range(1, ceil($count / ($limit ?? $database->getPageLimit())));
}),
new ExpressionFunction('yassg_get', static function (string $name): string {
return sprintf('$provider->getDatabase(%s)', $name);
}, static function (array $variables, string $name, string $id) {
/** @var DatabaseProvider $provider */
$provider = $variables['provider'];
}, static function (array $variables, string $name, string $id) {
/** @var DatabaseProvider $provider */
$provider = $variables['provider'];

return $provider->getDatabase($name)->get($id);
}),
return $provider->getDatabase($name)->get($id);
}),
];
}
}
6 changes: 3 additions & 3 deletions src/DatabaseProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@

namespace Sigwin\YASSG;

use Symfony\Component\DependencyInjection\ServiceLocator;
use Psr\Container\ContainerInterface;

final class DatabaseProvider
{
private ServiceLocator $locator;
private ContainerInterface $locator;

public function __construct(ServiceLocator $locator)
public function __construct(ContainerInterface $locator)
{
$this->locator = $locator;
}
Expand Down
11 changes: 6 additions & 5 deletions src/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use Sigwin\YASSG\Bridge\Symfony\Routing\Request;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

Expand Down Expand Up @@ -47,15 +46,17 @@ public function generate(callable $callable): void
$indexFile = (bool) ($requestContext->getParameter('index-file') ?? false);

foreach ($this->permutator->permute() as $routeName => $parameters) {
$this->dumpFile($callable, $this->urlGenerator->generate($routeName, $parameters + ($indexFile ? ['_filename' => 'index.html'] : []), UrlGeneratorInterface::ABSOLUTE_URL));
$url = $this->urlGenerator->generate($routeName, $parameters + ($indexFile ? ['_filename' => 'index.html'] : []), UrlGeneratorInterface::ABSOLUTE_URL);
$request = Request::create(rtrim($url, '/'))->withBaseUrl($requestContext->getBaseUrl());

$this->dumpFile($callable, $request);
}
}

private function dumpFile(callable $callable, string $url, int $expectedStatusCode = 200): void
private function dumpFile(callable $callable, Request $request, int $expectedStatusCode = 200): void
{
$request = Request::create(rtrim($url, '/'))->withBaseUrl($this->urlGenerator->getContext()->getBaseUrl());
try {
$response = $this->kernel->handle($request, HttpKernelInterface::MAIN_REQUEST, false);
$response = $this->kernel->handle($request);
} catch (HttpException $exception) {
throw $exception;
}
Expand Down
1 change: 1 addition & 0 deletions src/Permutator.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace Sigwin\YASSG;

use function BenTools\CartesianProduct\cartesian_product;

use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

final class Permutator
Expand Down
184 changes: 184 additions & 0 deletions tests/unit/GeneratorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
<?php

declare(strict_types=1);

/*
* This file is part of the yassg project.
*
* (c) sigwin.hr
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sigwin\YASSG\Test;

use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Sigwin\YASSG\DatabaseProvider;
use Sigwin\YASSG\Generator;
use Sigwin\YASSG\Permutator;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RequestContext;

/**
* @internal
*
* @small
*
* @covers \Sigwin\YASSG\Generator
*
* @uses \Sigwin\YASSG\DatabaseProvider
* @uses \Sigwin\YASSG\Permutator
* @uses \Sigwin\YASSG\Bridge\Symfony\Routing\Request
*/
final class GeneratorTest extends TestCase
{
public function testGenerator(): void
{
$routes = [
'foo' => [],
];
$urlGenerator = $this->mockUrlGenerator('/', $routes);
$kernel = $this->mockKernel('/', 'body');
$filesystem = $this->mockFilesystem('respublica//index.html', 'body');

$this->generate(new Generator(
'respublica',
$this->createPermutator($routes),
$urlGenerator,
$kernel,
$filesystem
));
}

public function testGeneratorWithIndexFile(): void
{
$routes = [
'foo' => ['_filename' => 'index.html'],
];
$urlGenerator = $this->mockUrlGenerator('/', $routes, true);
$kernel = $this->mockKernel('/', 'body');
$filesystem = $this->mockFilesystem('respublica//index.html', 'body');

$this->generate(new Generator(
'respublica',
$this->createPermutator($routes),
$urlGenerator,
$kernel,
$filesystem
));
}

public function testGeneratorWithInvalidResponseBody(): void
{
$routes = [
'foo' => ['_filename' => 'index.html'],
];
$urlGenerator = $this->mockUrlGenerator('/', $routes, true);
$kernel = $this->mockKernel('/', false);

$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('No body in response');

$this->generate(new Generator(
'respublica',
$this->createPermutator($routes),
$urlGenerator,
$kernel,
$this->getMockBuilder(Filesystem::class)->getMock()
));
}

private function generate(Generator $generator): void
{
$called = false;
$generator->generate(static function () use (&$called): void {
$called = true;
});
if ( ! $called) {
static::fail('Callback not called');
}
}

private function createPermutator(array $routes): Permutator
{
return new Permutator(
$routes,
new DatabaseProvider($this->getMockBuilder(ContainerInterface::class)->getMock()),
$this->getMockBuilder(ExpressionLanguage::class)->getMock()
);
}

private function mockUrlGenerator(string $baseUrl, array $routes, mixed $indexFile = null): UrlGeneratorInterface
{
$requestContext = $this->getMockBuilder(RequestContext::class)->getMock();
$requestContext
->expects(static::once())
->method('getBaseUrl')
->willReturn($baseUrl);
$requestContext
->expects(static::once())
->method('getParameter')
->with('index-file')
->willReturn($indexFile);

$urlGenerator = $this->getMockBuilder(UrlGeneratorInterface::class)->getMock();
$urlGenerator
->expects(static::once())
->method('getContext')
->willReturn($requestContext);

$remapped = [];
foreach ($routes as $name => $params) {
$remapped[] = array_merge([$name], [$params], [UrlGeneratorInterface::ABSOLUTE_URL]);
}

$urlGenerator
->expects(static::exactly(\count($routes)))
->method('generate')
->withConsecutive(...$remapped)
->willReturn('/////');

return $urlGenerator;
}

private function mockKernel(string $baseUrl, string|false $body, int $status = 200): KernelInterface
{
$response = $this->getMockBuilder(Response::class)->getMock();
$response
->expects(static::once())
->method('getStatusCode')
->willReturn($status);
$response
->expects(static::once())
->method('getContent')
->willReturn($body);

$kernel = $this->getMockBuilder(KernelInterface::class)->getMock();
$kernel
->expects(static::once())
->method('handle')
->with(static::callback(static function (\Symfony\Component\HttpFoundation\Request $request) use ($baseUrl): bool {
return $request->getUri() === 'http://localhost/'.$baseUrl;
}))
->willReturn($response);

return $kernel;
}

private function mockFilesystem(?string $path, string $content): Filesystem
{
$filesystem = $this->getMockBuilder(Filesystem::class)->getMock();
$filesystem
->expects(static::once())
->method('dumpFile')
->with($path, $content);

return $filesystem;
}
}

0 comments on commit f4156ea

Please sign in to comment.