Passed
Push — master ( 45ab73...eabe48 )
by Victor
45s queued 10s
created

IntegrationTestCase::addMiddleware()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Shoot\Shoot\Tests\Integration;
5
6
use Exception;
7
use LogicException;
8
use PHPUnit\Framework\MockObject\MockObject;
9
use PHPUnit\Framework\TestCase;
10
use Psr\Container\ContainerInterface;
11
use Psr\Container\NotFoundExceptionInterface;
12
use Psr\Http\Message\ServerRequestInterface;
13
use Shoot\Shoot\Installer;
14
use Shoot\Shoot\Middleware\PresenterMiddleware;
15
use Shoot\Shoot\MiddlewareInterface;
16
use Shoot\Shoot\Pipeline;
17
use Twig_Environment as Environment;
18
use Twig_Loader_Filesystem as FilesystemLoader;
19
20
abstract class IntegrationTestCase extends TestCase
21
{
22
    /** @var mixed */
23
    private $container = [];
24
25
    /** @var MiddlewareInterface[] */
26
    private $middleware = [];
27
28
    /** @var Pipeline */
29
    private $pipeline;
30
31
    /** @var ServerRequestInterface|MockObject */
32
    private $request;
33
34
    /** @var string */
35
    private $templateDirectory = '';
36
37
    /** @var Environment */
38
    private $twig;
39
40
    protected function setUp(): void
41
    {
42
        if (empty($this->templateDirectory)) {
43
            throw new LogicException('Template directory is not set in ' . static::class);
44
        }
45
46
        $container = $this->createContainer();
47
        $pipeline = new Pipeline(array_merge([new PresenterMiddleware($container)], $this->middleware));
48
        $installer = new Installer($pipeline);
49
50
        $loader = new FilesystemLoader([realpath($this->templateDirectory)]);
51
        $twig = new Environment($loader, ['cache' => false, 'strict_variables' => true]);
52
        $twig = $installer->install($twig);
53
54
        $this->pipeline = $pipeline;
55
        $this->request = $this->createMock(ServerRequestInterface::class);
56
        $this->twig = $twig;
57
58
        parent::setUp();
59
    }
60
61
    final protected function addMiddleware(MiddlewareInterface $middleware): void
62
    {
63
        $this->middleware[] = $middleware;
64
    }
65
66
    final protected function addToContainer(string $id, object $service): void
67
    {
68
        if (isset($this->container[$id])) {
69
            throw new LogicException("Service with ID '{$id}' already exists in container");
70
        }
71
72
        $this->container[$id] = $service;
73
    }
74
75
    final protected function getRequestMock(): MockObject
76
    {
77
        return $this->request;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->request could return the type Psr\Http\Message\ServerRequestInterface which is incompatible with the type-hinted return PHPUnit\Framework\MockObject\MockObject. Consider adding an additional type-check to rule them out.
Loading history...
78
    }
79
80
    final protected function renderTemplate(string $template, array $variables = []): array
81
    {
82
        return $this->pipeline->withRequest($this->request, function () use ($template, $variables): array {
83
            $output = $this->twig->render($template, $variables);
84
            $output = trim($output);
85
            $output = explode(PHP_EOL, $output);
86
            $output = array_map('trim', $output);
87
88
            return $output;
89
        });
90
    }
91
92
    final protected function setTemplateDirectory(string $templateDirectory): void
93
    {
94
        $this->templateDirectory = $templateDirectory;
95
    }
96
97
    private function createContainer(): ContainerInterface
98
    {
99
        return new class($this->container) implements ContainerInterface
100
        {
101
            private $container;
102
103
            public function __construct(array $container)
104
            {
105
                $this->container = $container;
106
            }
107
108
            public function get($id)
109
            {
110
                if (!$this->has($id)) {
111
                    throw new class extends Exception implements NotFoundExceptionInterface
112
                    {
113
                    };
114
                }
115
116
                return $this->container[$id] ?? new $id();
117
            }
118
119
            public function has($id): bool
120
            {
121
                return isset($this->container[$id]) || class_exists($id);
122
            }
123
        };
124
    }
125
}
126