Skip to content

Commit 28dee6a

Browse files
committed
test: view tests
1 parent 212f6ff commit 28dee6a

File tree

5 files changed

+144
-61
lines changed

5 files changed

+144
-61
lines changed

src/Middleware/ErrorRequestHandler.php

Lines changed: 0 additions & 50 deletions
This file was deleted.

src/Service/ContainerFactory.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
use Gt\Config\Config;
55
use Gt\ServiceContainer\Container;
6-
use Gt\WebEngine\Middleware\DefaultServiceLoader;
76

87
class ContainerFactory {
98
public function create(Config $config):Container {

src/Middleware/DefaultServiceLoader.php renamed to src/Service/DefaultServiceLoader.php

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
<?php /** @noinspection PhpUnused */
2-
namespace Gt\WebEngine\Middleware;
1+
<?php
2+
namespace GT\WebEngine\Service;
33

44
use Gt\Config\Config;
55
use Gt\DomTemplate\HTMLAttributeBinder;
66
use Gt\Database\Connection\DefaultSettings;
77
use Gt\Database\Connection\Settings;
88
use Gt\Database\Database;
99
use Gt\Dom\Document;
10-
use Gt\Dom\HTMLDocument;
1110
use Gt\DomTemplate\BindableCache;
1211
use Gt\DomTemplate\Binder;
1312
use Gt\DomTemplate\DocumentBinder;
@@ -23,13 +22,6 @@
2322
use Gt\Http\Uri;
2423
use Gt\ServiceContainer\Container;
2524

26-
/**
27-
* @SuppressWarnings("PHPMD.CouplingBetweenObjects")
28-
* Reason: This loader is the central place that defines and provides core
29-
* framework services to the container. It references many service classes by
30-
* design, but each is created lazily via dedicated factory methods, keeping
31-
* responsibilities focused and testable.
32-
*/
3325
class DefaultServiceLoader {
3426
protected string $uniqid;
3527

test/phpunit/View/BaseViewTest.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
namespace GT\WebEngine\Test\View;
3+
4+
use GT\WebEngine\View\BaseView;
5+
use PHPUnit\Framework\TestCase;
6+
use Psr\Http\Message\StreamInterface;
7+
8+
class BaseViewTest extends TestCase {
9+
private function newRecordingStream(): StreamInterface {
10+
return new class implements StreamInterface {
11+
public string $buffer = "";
12+
public function __toString():string { return $this->buffer; }
13+
public function close():void {}
14+
public function detach() {}
15+
public function getSize():?int { return strlen($this->buffer); }
16+
public function tell():int { return strlen($this->buffer); }
17+
public function eof():bool { return true; }
18+
public function isSeekable():bool { return false; }
19+
public function seek($offset, $whence = SEEK_SET):void {}
20+
public function rewind():void {}
21+
public function isWritable():bool { return true; }
22+
public function write($string):int { $this->buffer .= (string)$string; return strlen((string)$string); }
23+
public function isReadable():bool { return false; }
24+
public function read($length):string { return ""; }
25+
public function getContents():string { return $this->buffer; }
26+
public function getMetadata($key = null) { return null; }
27+
};
28+
}
29+
30+
private function newTestableView(StreamInterface $stream): BaseView {
31+
return new class($stream) extends BaseView {
32+
public function createViewModel():mixed { return ""; }
33+
public function getViewFiles(): array { return $this->viewFileArray; }
34+
};
35+
}
36+
37+
public function testStream_writesStringToOutput():void {
38+
$stream = $this->newRecordingStream();
39+
$sut = $this->newTestableView($stream);
40+
$sut->stream("hello world");
41+
self::assertSame("hello world", (string)$stream);
42+
}
43+
44+
public function testStream_castsNonStringToString():void {
45+
$stream = $this->newRecordingStream();
46+
$sut = $this->newTestableView($stream);
47+
$object = new class(){ public function __toString():string { return "obj-str"; } };
48+
$sut->stream($object);
49+
self::assertSame("obj-str", (string)$stream);
50+
}
51+
52+
public function testAddViewFile_appendsInOrder():void {
53+
$stream = $this->newRecordingStream();
54+
/** @var BaseView&object{getViewFiles: callable():array} $sut */
55+
$sut = $this->newTestableView($stream);
56+
$sut->addViewFile("one.html");
57+
$sut->addViewFile("two.html");
58+
/** @noinspection PhpUndefinedMethodInspection */
59+
self::assertSame(["one.html", "two.html"], $sut->getViewFiles());
60+
}
61+
}

test/phpunit/View/HTMLViewTest.php

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
namespace GT\WebEngine\Test\View;
3+
4+
use Gt\Dom\HTMLDocument;
5+
use GT\WebEngine\View\HTMLView;
6+
use PHPUnit\Framework\TestCase;
7+
use Psr\Http\Message\StreamInterface;
8+
9+
class HTMLViewTest extends TestCase {
10+
private string $tmpDir;
11+
12+
protected function setUp():void {
13+
parent::setUp();
14+
$this->tmpDir = sys_get_temp_dir() . "/phpgt-webengine-test--View-HTMLView-" . uniqid();
15+
if(!is_dir($this->tmpDir)) {
16+
mkdir($this->tmpDir, recursive: true);
17+
}
18+
}
19+
20+
protected function tearDown():void {
21+
foreach(scandir($this->tmpDir) ?: [] as $f) {
22+
if($f === '.' || $f === '..') { continue; }
23+
@unlink($this->tmpDir . DIRECTORY_SEPARATOR . $f);
24+
}
25+
@rmdir($this->tmpDir);
26+
parent::tearDown();
27+
}
28+
29+
private function newRecordingStream(): StreamInterface {
30+
return new class implements StreamInterface {
31+
public string $buffer = "";
32+
public function __toString():string { return $this->buffer; }
33+
public function close():void {}
34+
public function detach() {}
35+
public function getSize():?int { return strlen($this->buffer); }
36+
public function tell():int { return strlen($this->buffer); }
37+
public function eof():bool { return true; }
38+
public function isSeekable():bool { return false; }
39+
public function seek($offset, $whence = SEEK_SET):void {}
40+
public function rewind():void {}
41+
public function isWritable():bool { return true; }
42+
public function write($string):int { $this->buffer .= (string)$string; return strlen((string)$string); }
43+
public function isReadable():bool { return false; }
44+
public function read($length):string { return ""; }
45+
public function getContents():string { return $this->buffer; }
46+
public function getMetadata($key = null) { return null; }
47+
};
48+
}
49+
50+
public function testCreateViewModel_concatenatesFilesIntoHtmlDocument():void {
51+
$file1 = $this->tmpDir . "/one.html";
52+
$file2 = $this->tmpDir . "/two.html";
53+
file_put_contents($file1, "<div id=one>One</div>");
54+
file_put_contents($file2, "<p id=two>Two</p>");
55+
56+
$sut = new HTMLView($this->newRecordingStream());
57+
$sut->addViewFile($file1);
58+
$sut->addViewFile($file2);
59+
60+
$doc = $sut->createViewModel();
61+
self::assertInstanceOf(HTMLDocument::class, $doc);
62+
$docStr = (string)$doc;
63+
self::assertTrue(strpos($docStr, 'One') !== false);
64+
self::assertTrue(strpos($docStr, 'Two') !== false);
65+
}
66+
67+
public function testStream_serialisesHtmlDocumentToOutput():void {
68+
$stream = $this->newRecordingStream();
69+
$sut = new HTMLView($stream);
70+
$doc = new HTMLDocument("<main>Content</main>");
71+
$sut->stream($doc);
72+
self::assertSame((string)$doc, (string)$stream);
73+
}
74+
75+
public function testCreateViewModel_withNoFiles_returnsEmptyDocument():void {
76+
$sut = new HTMLView($this->newRecordingStream());
77+
$doc = $sut->createViewModel();
78+
self::assertInstanceOf(HTMLDocument::class, $doc);
79+
self::assertIsString((string)$doc);
80+
}
81+
}

0 commit comments

Comments
 (0)