Passed
Push — master ( 2ed18b...d69bd8 )
by Caen
04:33 queued 17s
created

RealtimeCompilerTest   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 194
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 99
c 3
b 0
f 0
dl 0
loc 194
rs 10
wmc 17
1
<?php
2
3
declare(strict_types=1);
4
5
use Hyde\Testing\UnitTestCase;
6
use Desilva\Microserve\JsonResponse;
7
use Desilva\Microserve\Request;
8
use Desilva\Microserve\Response;
9
use Hyde\Facades\Filesystem;
10
use Hyde\Framework\Exceptions\RouteNotFoundException;
11
use Hyde\RealtimeCompiler\Http\ExceptionHandler;
12
use Desilva\Microserve\HtmlResponse;
13
use Hyde\RealtimeCompiler\Http\HttpKernel;
14
15
class RealtimeCompilerTest extends UnitTestCase
16
{
17
    public static function setUpBeforeClass(): void
18
    {
19
        putenv('SERVER_LIVE_EDIT=false');
20
21
        define('BASE_PATH', realpath(__DIR__.'/../../../'));
22
23
        if (BASE_PATH === false || ! file_exists(BASE_PATH.'/hyde')) {
24
            throw new InvalidArgumentException('This test suite must be run from the root of the hydephp/develop monorepo.');
25
        }
26
    }
27
28
    protected function setUp(): void
29
    {
30
        parent::setUp();
31
        ob_start();
32
    }
33
34
    protected function tearDown(): void
35
    {
36
        parent::tearDown();
37
        ob_end_clean();
38
    }
39
40
    public function testHandlesRoutesIndexPage()
41
    {
42
        putenv('SERVER_DASHBOARD=false');
43
        $this->mockRoute('');
44
45
        $kernel = new HttpKernel();
46
        $response = $kernel->handle(new Request());
47
48
        $this->assertInstanceOf(Response::class, $response);
49
        $this->assertEquals(200, $response->statusCode);
50
        $this->assertEquals('OK', $response->statusMessage);
51
        $this->assertStringContainsString('<title>Welcome to HydePHP!</title>', $response->body);
52
53
        $this->assertFileExists(hyde()->path('_site/index.html'));
54
        $this->assertEquals($response->body, Filesystem::get('_site/index.html'));
55
56
        Filesystem::unlink('_site/index.html');
57
    }
58
59
    public function testHandlesRoutesCustomPages()
60
    {
61
        $this->mockRoute('foo');
62
63
        Filesystem::put('_pages/foo.md', '# Hello World!');
64
65
        $kernel = new HttpKernel();
66
        $response = $kernel->handle(new Request());
67
68
        $this->assertInstanceOf(Response::class, $response);
69
        $this->assertEquals(200, $response->statusCode);
70
        $this->assertEquals('OK', $response->statusMessage);
71
        $this->assertStringContainsString('<h1>Hello World!</h1>', $response->body);
72
73
        Filesystem::unlink('_pages/foo.md');
74
        Filesystem::unlink('_site/foo.html');
75
    }
76
77
    public function testHandlesRoutesPagesWithHtmlExtension()
78
    {
79
        $this->mockRoute('foo.html');
80
81
        Filesystem::put('_pages/foo.md', '# Hello World!');
82
83
        $kernel = new HttpKernel();
84
        $response = $kernel->handle(new Request());
85
86
        $this->assertInstanceOf(Response::class, $response);
87
        $this->assertEquals(200, $response->statusCode);
88
        $this->assertEquals('OK', $response->statusMessage);
89
        $this->assertStringContainsString('<h1>Hello World!</h1>', $response->body);
90
91
        Filesystem::unlink('_pages/foo.md');
92
        Filesystem::unlink('_site/foo.html');
93
    }
94
95
    public function testHandlesRoutesStaticAssets()
96
    {
97
        $this->mockRoute('media/app.css');
98
99
        $kernel = new HttpKernel();
100
        $response = $kernel->handle(new Request());
101
102
        $this->assertInstanceOf(Response::class, $response);
103
        $this->assertEquals(200, $response->statusCode);
104
        $this->assertEquals('OK', $response->statusMessage);
105
        $this->assertEquals(file_get_contents(\Hyde\Hyde::path('_media/app.css')), $response->body);
106
    }
107
108
    public function testThrowsRouteNotFoundExceptionForMissingRoute()
109
    {
110
        $this->mockRoute('missing');
111
112
        $kernel = new HttpKernel();
113
114
        $this->expectException(RouteNotFoundException::class);
115
        $this->expectExceptionMessage('Route [missing] not found');
116
117
        $kernel->handle(new Request());
118
    }
119
120
    public function testSends404ErrorResponseForMissingAsset()
121
    {
122
        $this->mockRoute('missing.css');
123
124
        $kernel = new HttpKernel();
125
        $response = $kernel->handle(new Request());
126
127
        $this->assertInstanceOf(Response::class, $response);
128
        $this->assertEquals(404, $response->statusCode);
129
        $this->assertEquals('Not Found', $response->statusMessage);
130
    }
131
132
    public function testTrailingSlashesAreNormalizedFromRoute()
133
    {
134
        $this->mockRoute('foo/');
135
136
        Filesystem::put('_pages/foo.md', '# Hello World!');
137
138
        $kernel = new HttpKernel();
139
        $response = $kernel->handle(new Request());
140
141
        $this->assertInstanceOf(Response::class, $response);
142
        $this->assertEquals(200, $response->statusCode);
143
        $this->assertEquals('OK', $response->statusMessage);
144
        $this->assertStringContainsString('<h1>Hello World!</h1>', $response->body);
145
146
        Filesystem::unlink('_pages/foo.md');
147
        Filesystem::unlink('_site/foo.html');
148
    }
149
150
    public function testDocsUriPathIsReroutedToDocsIndex()
151
    {
152
        $this->mockRoute('docs');
153
154
        Filesystem::put('_docs/index.md', '# Hello World!');
155
156
        $kernel = new HttpKernel();
157
        $response = $kernel->handle(new Request());
158
159
        $this->assertInstanceOf(Response::class, $response);
160
        $this->assertEquals(200, $response->statusCode);
161
        $this->assertEquals('OK', $response->statusMessage);
162
        $this->assertStringContainsString('HydePHP Docs', $response->body);
163
164
        Filesystem::unlink('_docs/index.md');
165
        Filesystem::unlink('_site/docs/index.html');
166
    }
167
168
    public function testDocsSearchRendersSearchPage()
169
    {
170
        $this->mockRoute('docs/search');
171
172
        $kernel = new HttpKernel();
173
        $response = $kernel->handle(new Request());
174
175
        $this->assertInstanceOf(HtmlResponse::class, $response);
176
        $this->assertEquals(200, $response->statusCode);
177
        $this->assertEquals('OK', $response->statusMessage);
178
        $this->assertStringContainsString('Search the documentation site', $response->body);
179
180
        Filesystem::unlink('_site/docs/search.html');
181
    }
182
183
    public function testPingRouteReturnsPingResponse()
184
    {
185
        $this->mockRoute('ping');
186
187
        $kernel = new HttpKernel();
188
        $response = $kernel->handle(new Request());
189
190
        $this->assertInstanceOf(JsonResponse::class, $response);
191
        $this->assertEquals(200, $response->statusCode);
192
        $this->assertEquals('OK', $response->statusMessage);
193
    }
194
195
    public function testExceptionHandling()
196
    {
197
        $exception = new Exception('foo');
198
        $response = ExceptionHandler::handle($exception);
199
200
        $this->assertInstanceOf(Response::class, $response);
201
        $this->assertEquals(500, $response->statusCode);
202
        $this->assertEquals('Internal Server Error', $response->statusMessage);
203
    }
204
205
    protected function mockRoute(string $route, $method = 'GET'): void
206
    {
207
        $_SERVER['REQUEST_METHOD'] = $method;
208
        $_SERVER['REQUEST_URI'] = "/$route";
209
    }
210
}
211