Skip to content

Commit

Permalink
[Update] Add some tests on trait
Browse files Browse the repository at this point in the history
  • Loading branch information
Neirda24 committed Jul 18, 2024
1 parent a25a0cb commit e8951b9
Show file tree
Hide file tree
Showing 5 changed files with 284 additions and 7 deletions.
2 changes: 2 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ parameters:
- 'config'
- 'src'
- 'tests'
excludePaths:
- tests/Builder/DefaultBuilderTraitTest.php
ignoreErrors:
-
message: "#^Cannot call method generate\\(\\) on Symfony\\\\Component\\\\Routing\\\\Generator\\\\UrlGeneratorInterface\\|null\\.$#"
Expand Down
2 changes: 1 addition & 1 deletion src/Builder/DefaultBuilderTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ abstract protected function getEndpoint(): string;
abstract public function setConfigurations(array $configurations): static;

/**
* @param non-empty-list<string> $validExtensions
* @param non-empty-list<string> $validExtensions eg: ['png', 'jpeg']
*/
protected function assertFileExtension(string $path, array $validExtensions): void
{
Expand Down
144 changes: 144 additions & 0 deletions tests/Builder/DefaultBuilderTraitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<?php

namespace Sensiolabs\GotenbergBundle\Tests\Builder;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\UsesClass;
use PHPUnit\Framework\TestCase;
use Sensiolabs\GotenbergBundle\Builder\DefaultBuilderTrait;
use Sensiolabs\GotenbergBundle\Enumeration\PdfFormat;
use Sensiolabs\GotenbergBundle\Exception\JsonEncodingException;
use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter;
use Symfony\Component\Filesystem\Filesystem;

#[CoversClass(DefaultBuilderTrait::class)]
#[UsesClass(AssetBaseDirFormatter::class)]
class DefaultBuilderTraitTest extends TestCase
{
public function testCanEncodeData(): void
{
$builder = $this->getBuilder();

self::assertSame([
'key' => '{"key_v1":"value_v1"}',
], $builder->encodeData('key', ['key_v1' => 'value_v1']));
}

public function testEncodeDataFailIfSomethingWentWrong(): void
{
$builder = $this->getBuilder();

$this->expectException(JsonEncodingException::class);
$this->expectExceptionMessage('Could not encode property "key" into JSON');

$builder->encodeData('key', [\INF]);
}

public static function canConvertToMultiPartProvider(): \Generator
{
yield 'simple boolean (true)' => [true, [['key' => 'true']]];
yield 'simple boolean (false)' => [false, [['key' => 'false']]];

yield 'simple int' => [12, [['key' => '12']]];

yield 'simple float' => [12.2, [['key' => '12.2']]];
yield 'rounded float' => [12.0, [['key' => '12.0']]];

yield 'any BackedEnum' => [PdfFormat::Pdf2b, [['key' => 'PDF/A-2b']]];

yield 'any Stringable' => [new class() implements \Stringable {
public function __toString(): string
{
return __FUNCTION__;
}
}, [['key' => '__toString']]];

yield 'nested array' => [[
'level1' => [
'level2' => [
'level2_rounded_float' => 12.0,
'level2_simple_float' => 12.5,
'level2_boolean' => true,
],
'simple_boolean' => true,
],
], [
['key' => '12.0'],
['key' => '12.5'],
['key' => 'true'],
['key' => 'true'],
]];

yield 'simple string' => ['hello world', [['key' => 'hello world']]];

yield 'with custom normalizer' => ['', [['key' => 'plop']], static function (): array {
return ['key' => 'plop'];
}];
}

#[DataProvider('canConvertToMultiPartProvider')]
public function testCanConvertToMultiPart(mixed $value, array $expectedResult, callable|null $normalizer = null): void
{
$builder = $this->getBuilder();
$builder->addFormField('key', $value);

if (null !== $normalizer) {
$builder->addNormalizer('key', $normalizer);
}

self::assertSame($expectedResult, $builder->getMultipartFormData());
}

public function testCanAssertFileExtensionsAndThrowIfNotValid(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('The file extension "html" is not valid in this context.');

$builder = $this->getBuilder();
$builder->assertFileExtension('content.html', ['txt']);
}

public function testCanAssertFileExtensions(): void
{
$builder = $this->getBuilder();
$builder->assertFileExtension('content.html', ['html']);

$this->addToAssertionCount(1);
}

private function getBuilder(): object
{
return new class() {
use DefaultBuilderTrait {
addNormalizer as public;
encodeData as public;
assertFileExtension as public;
}

public function __construct()
{
$this->asset = new AssetBaseDirFormatter(
new Filesystem(),
__DIR__.'/../Fixtures',
'files',
);
}

protected function getEndpoint(): string
{
// TODO: Implement getEndpoint() method.
}

public function setConfigurations(array $configurations): static
{
// TODO: Implement setConfigurations() method.
}

public function addFormField(string $key, mixed $value): void
{
$this->formFields[$key] = $value;
}
};
}
}
64 changes: 62 additions & 2 deletions tests/Builder/Pdf/AbstractChromiumPdfBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
use Sensiolabs\GotenbergBundle\Enumeration\PaperSizeInterface;
use Sensiolabs\GotenbergBundle\Enumeration\PdfFormat;
use Sensiolabs\GotenbergBundle\Enumeration\Unit;
use Sensiolabs\GotenbergBundle\Exception\InvalidBuilderConfiguration;
use Sensiolabs\GotenbergBundle\Exception\PdfPartRenderingException;
use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter;
use Sensiolabs\GotenbergBundle\Tests\Builder\AbstractBuilderTestCase;
use Sensiolabs\GotenbergBundle\Twig\GotenbergAssetExtension;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;

#[CoversClass(AbstractChromiumPdfBuilder::class)]
Expand Down Expand Up @@ -115,6 +117,17 @@ public function testConfigurationIsCorrectlySet(string $key, mixed $value, array
self::assertEquals($expected, $builder->getMultipartFormData()[0]);
}

public function testConfigurationNotFoundThrowError(): void
{
$builder = $this->getChromiumPdfBuilder();

$this->expectException(InvalidBuilderConfiguration::class);

$builder->setConfigurations([
'fake' => 'value',
]);
}

public function testPaperSizeAppliesWidthAndHeight(): void
{
$builder = $this->getChromiumPdfBuilder();
Expand Down Expand Up @@ -333,6 +346,25 @@ public function testCanAddCookies(): void
], $data[0]);
}

public function testCanForwardCookies(): void
{
$request = new Request();
$request->headers->set('Host', 'sensiolabs.com');
$request->cookies->set('MyCookie', 'Chocolate');

$requestStack = new RequestStack();
$requestStack->push($request);

$builder = $this->getChromiumPdfBuilder(requestStack: $requestStack);
$builder->forwardCookie('MyCookie');

$data = $builder->getMultipartFormData();

self::assertEquals([
'cookies' => '[{"name":"MyCookie","value":"Chocolate","domain":"sensiolabs.com"}]',
], $data[0]);
}

public function testCanAddExtraHttpHeaders(): void
{
$builder = $this->getChromiumPdfBuilder();
Expand All @@ -350,6 +382,34 @@ public function testCanAddExtraHttpHeaders(): void
], $data[0]);
}

public function testAddExtraHttpHeadersDoesNothingIfEmpty(): void
{
$builder = $this->getChromiumPdfBuilder();

$data = $builder->getMultipartFormData();
$dataCount = \count($data);

$builder->addExtraHttpHeaders([]);
self::assertCount(max($dataCount - 1, 0), $builder->getMultipartFormData());
}

public function testCanResetExtraHttpHeaders(): void
{
$builder = $this->getChromiumPdfBuilder();
$builder->addExtraHttpHeaders([
'MyHeader' => 'SomeValue',
]);

$data = $builder->getMultipartFormData();

$dataCount = \count($data);

$builder->extraHttpHeaders([]);

$data = $builder->getMultipartFormData();
self::assertCount($dataCount - 1, $data);
}

public function testCanAddMetadata(): void
{
$builder = $this->getChromiumPdfBuilder();
Expand Down Expand Up @@ -381,9 +441,9 @@ public function testThrowIfTwigTemplateIsInvalid(): void
$builder->header('templates/invalid.html.twig');
}

private function getChromiumPdfBuilder(bool $twig = true): AbstractChromiumPdfBuilder
private function getChromiumPdfBuilder(bool $twig = true, RequestStack $requestStack = new RequestStack()): AbstractChromiumPdfBuilder
{
return new class($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), true === $twig ? self::$twig : null) extends AbstractChromiumPdfBuilder {
return new class($this->gotenbergClient, self::$assetBaseDirFormatter, $requestStack, true === $twig ? self::$twig : null) extends AbstractChromiumPdfBuilder {
protected function getEndpoint(): string
{
return '/fake/endpoint';
Expand Down
79 changes: 75 additions & 4 deletions tests/Builder/Pdf/UrlPdfBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
use Sensiolabs\GotenbergBundle\Processor\NullProcessor;
use Sensiolabs\GotenbergBundle\Tests\Builder\AbstractBuilderTestCase;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

#[CoversClass(UrlPdfBuilder::class)]
#[UsesClass(AbstractChromiumPdfBuilder::class)]
Expand All @@ -37,7 +42,7 @@ public function testEndpointIsCorrect(): void
;
}

public function testUrl(): void
public function testCanProvideUrl(): void
{
$builder = $this->getUrlPdfBuilder();
$builder->url('https://google.com');
Expand All @@ -49,7 +54,57 @@ public function testUrl(): void
self::assertSame(['url' => 'https://google.com'], $multipartFormData[0]);
}

public function testRequiredFormData(): void
public function testCanProvideRoute(): void
{
$routeCollection = new RouteCollection();
$routeCollection->add('fake_route', new Route('/route'));
$urlGenerator = new UrlGenerator($routeCollection, new RequestContext());

$builder = $this->getUrlPdfBuilder(urlGenerator: $urlGenerator);
$builder->route('fake_route');

$multipartFormData = $builder->getMultipartFormData();

self::assertCount(1, $multipartFormData);
self::assertArrayHasKey(0, $multipartFormData);
self::assertSame(['url' => 'http://localhost/route'], $multipartFormData[0]);
}

public function testCanProvideRouteWithCustomContext(): void
{
$requestContext = new RequestContext();
$requestContext->setHost('sensiolabs.com');

$routeCollection = new RouteCollection();
$routeCollection->add('fake_route', new Route('/route'));
$urlGenerator = new UrlGenerator($routeCollection, new RequestContext());

$originalRequestContext = $urlGenerator->getContext();

$builder = $this->getUrlPdfBuilder(urlGenerator: $urlGenerator);
$builder->setRequestContext($requestContext);

$builder->route('fake_route');

$multipartFormData = $builder->getMultipartFormData();

self::assertCount(1, $multipartFormData);
self::assertArrayHasKey(0, $multipartFormData);
self::assertSame(['url' => 'http://sensiolabs.com/route'], $multipartFormData[0]);
self::assertSame($originalRequestContext, $urlGenerator->getContext());
}

public function testRouterIsRequired(): void
{
$builder = $this->getUrlPdfBuilder();

$this->expectException(\LogicException::class);
$this->expectExceptionMessage('Router is required to use "Sensiolabs\GotenbergBundle\Builder\Pdf\UrlPdfBuilder::route" method. Try to run "composer require symfony/routing".');

$builder->route('fake_route');
}

public function testRequiredEitherUrlOrRoute(): void
{
$builder = $this->getUrlPdfBuilder();

Expand All @@ -59,9 +114,25 @@ public function testRequiredFormData(): void
$builder->getMultipartFormData();
}

private function getUrlPdfBuilder(): UrlPdfBuilder
public function testRequiredEitherUrlOrRouteNotBoth(): void
{
$routeCollection = new RouteCollection();
$routeCollection->add('fake_route', new Route('/route'));
$urlGenerator = new UrlGenerator($routeCollection, new RequestContext());

$builder = $this->getUrlPdfBuilder(urlGenerator: $urlGenerator);
$builder->url('https://sensiolabs.com');
$builder->route('fake_route');

$this->expectException(MissingRequiredFieldException::class);
$this->expectExceptionMessage('Provide only one of ["route", "url"] parameter. Not both.');

$builder->getMultipartFormData();
}

private function getUrlPdfBuilder(UrlGeneratorInterface|null $urlGenerator = null): UrlPdfBuilder
{
return (new UrlPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack()))
return (new UrlPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), urlGenerator: $urlGenerator))
->processor(new NullProcessor())
;
}
Expand Down

0 comments on commit e8951b9

Please sign in to comment.