Skip to content

Commit 205e077

Browse files
committed
Add Test support
1 parent 3040ba3 commit 205e077

File tree

3 files changed

+236
-1
lines changed

3 files changed

+236
-1
lines changed

composer.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,34 @@
2222
"ext-gd": "*",
2323
"ext-pdo": "*"
2424
},
25+
"require-dev": {
26+
"phpunit/phpunit": "^10.5"
27+
},
2528
"scripts": {
2629
"dev": [
2730
"Composer\\Config::disableProcessTimeout",
2831
"node start-dev.js"
2932
],
33+
"test": [
34+
"@php vendor/bin/phpunit"
35+
],
3036
"post-create-project-cmd": [
3137
"npm install",
3238
"php post-setup-info.php"
3339
]
3440
},
3541
"scripts-descriptions": {
36-
"dev": "Start PHP server with hot reload (by using BrowserSync concurrently)"
42+
"dev": "Start PHP server with hot reload (by using BrowserSync concurrently)",
43+
"test": "Start PHPUnit test"
3744
},
3845
"autoload": {
3946
"psr-4": {
4047
"\\": "/"
4148
}
49+
},
50+
"autoload-dev": {
51+
"psr-4": {
52+
"Tests\\": "tests/"
53+
}
4254
}
4355
}

phpunit.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit bootstrap="vendor/autoload.php"
3+
colors="true"
4+
verbose="true">
5+
<testsuites>
6+
<testsuite name="WebMVC Framework Test Suite">
7+
<directory>tests</directory>
8+
</testsuite>
9+
</testsuites>
10+
</phpunit>
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
<?php
2+
3+
use PHPUnit\Framework\TestCase;
4+
use framework\Controller;
5+
use framework\Model;
6+
use framework\View;
7+
8+
// Define minimal configuration constants required by the framework.
9+
$rootPath = realpath(__DIR__ . '/..');
10+
$projectRoot = dirname($rootPath);
11+
12+
if (!defined('RELATIVE_PATH')) {
13+
define('RELATIVE_PATH', $projectRoot . DIRECTORY_SEPARATOR);
14+
}
15+
if (!defined('SECURING_OUTSIDE_HTTP_FOLDER')) {
16+
define('SECURING_OUTSIDE_HTTP_FOLDER', '');
17+
}
18+
if (!defined('APP_CONTROLLERS_PATH')) {
19+
define('APP_CONTROLLERS_PATH', $projectRoot . DIRECTORY_SEPARATOR . 'controllers');
20+
}
21+
if (!defined('APP_LOCALE_PATH')) {
22+
define('APP_LOCALE_PATH', $projectRoot . DIRECTORY_SEPARATOR . 'locales');
23+
}
24+
if (!defined('JSFRAMEWORK')) {
25+
define('JSFRAMEWORK', 'framework/js');
26+
}
27+
if (!defined('SITEURL')) {
28+
define('SITEURL', 'http://localhost');
29+
}
30+
if (!defined('SERVER_OS_ENCODING')) {
31+
define('SERVER_OS_ENCODING', 'Linux');
32+
}
33+
if (!defined('DEFAULT_LOGIN_PAGE')) {
34+
define('DEFAULT_LOGIN_PAGE', 'common/login');
35+
}
36+
if (!defined('LoginRBACWarningMessage')) {
37+
define('LoginRBACWarningMessage', 'login-rbac-warning');
38+
}
39+
if (!defined('LoginAuthWarningMessage')) {
40+
define('LoginAuthWarningMessage', 'login-auth-warning');
41+
}
42+
if (!defined('COMPRESS_OUTPUT')) {
43+
define('COMPRESS_OUTPUT', false);
44+
}
45+
if (!defined('CHARSET')) {
46+
define('CHARSET', 'UTF-8');
47+
}
48+
if (!defined('SUBSYSTEMS')) {
49+
define('SUBSYSTEMS', serialize(['sub']));
50+
}
51+
52+
require_once $projectRoot . '/framework/Loader.php';
53+
require_once $projectRoot . '/framework/Model.php';
54+
require_once $projectRoot . '/framework/View.php';
55+
require_once $projectRoot . '/framework/Controller.php';
56+
57+
class FakeModel extends Model
58+
{
59+
public function __construct()
60+
{
61+
// Avoid opening a database connection during tests.
62+
}
63+
}
64+
65+
class FakeView extends View
66+
{
67+
private $content;
68+
69+
public function __construct($content)
70+
{
71+
parent::__construct(null);
72+
$this->content = $content;
73+
$this->tpl = $content;
74+
}
75+
76+
public function parse()
77+
{
78+
return $this->content;
79+
}
80+
}
81+
82+
class TestableController extends Controller
83+
{
84+
public $autorunCalled = false;
85+
86+
protected function autorun($parameters = null)
87+
{
88+
$this->autorunCalled = true;
89+
}
90+
}
91+
92+
final class ControllerTest extends TestCase
93+
{
94+
protected function setUp(): void
95+
{
96+
parent::setUp();
97+
$_GET = [];
98+
$_SESSION = [];
99+
}
100+
101+
public function testGetNameReturnsFullyQualifiedClassName(): void
102+
{
103+
$view = new FakeView('<div id="all">content</div>');
104+
$model = new FakeModel();
105+
$controller = new TestableController($view, $model);
106+
107+
$this->assertSame(TestableController::class, $controller->getName());
108+
}
109+
110+
public function testSetViewUpdatesCurrentView(): void
111+
{
112+
$initialView = new FakeView('<div>initial</div>');
113+
$replacementView = new FakeView('<div>replacement</div>');
114+
$controller = new TestableController($initialView, new FakeModel());
115+
116+
$controller->setView($replacementView);
117+
118+
$this->assertSame($replacementView, $controller->getView());
119+
}
120+
121+
public function testSetModelUpdatesCurrentModel(): void
122+
{
123+
$initialModel = new FakeModel();
124+
$replacementModel = new FakeModel();
125+
$controller = new TestableController(new FakeView('<div>test</div>'), $initialModel);
126+
127+
$controller->setModel($replacementModel);
128+
129+
$this->assertSame($replacementModel, $controller->getModel());
130+
}
131+
132+
public function testSetObserverPollingIntervalChangesOnlyWhenUnset(): void
133+
{
134+
$controller = new TestableController(new FakeView('<div>test</div>'), new FakeModel());
135+
136+
$controller->setObserverPollingInterval(1500);
137+
$controller->setObserverPollingInterval(2500);
138+
139+
$reflection = new ReflectionClass($controller);
140+
$property = $reflection->getProperty('observerPollingInterval');
141+
$property->setAccessible(true);
142+
143+
$this->assertSame(1500, $property->getValue($controller));
144+
}
145+
146+
public function testResetObserversClearsInternalCounters(): void
147+
{
148+
$controller = new TestableController(new FakeView('<div>test</div>'), new FakeModel());
149+
150+
$reflection = new ReflectionClass($controller);
151+
$counterProperty = $reflection->getProperty('observersCounter');
152+
$counterProperty->setAccessible(true);
153+
$counterProperty->setValue($controller, 3);
154+
155+
$intervalProperty = $reflection->getProperty('observerPollingInterval');
156+
$intervalProperty->setAccessible(true);
157+
$intervalProperty->setValue($controller, 1500);
158+
159+
$controller->resetObservers();
160+
161+
$this->assertSame(0, $counterProperty->getValue($controller));
162+
$this->assertSame(0, $intervalProperty->getValue($controller));
163+
}
164+
165+
public function testGetReturnsFullContentWhenAllRequested(): void
166+
{
167+
$content = '<html><body><div id="content">Hello</div></body></html>';
168+
$controller = new TestableController(new FakeView($content), new FakeModel());
169+
170+
$this->assertSame($content, $controller->get('all'));
171+
}
172+
173+
public function testGetReturnsSpecificSectionWhenRequested(): void
174+
{
175+
$controller = new TestableController(
176+
new FakeView('<html><body><div id="content">Hello</div></body></html>'),
177+
new FakeModel()
178+
);
179+
180+
$section = $controller->get('content');
181+
182+
$this->assertStringContainsString('<div id="content">Hello</div>', $section);
183+
}
184+
185+
public function testAutorunIsInvokedForMainController(): void
186+
{
187+
$controller = new TestableController(new FakeView('<div>test</div>'), new FakeModel());
188+
189+
$this->assertTrue($controller->autorunCalled);
190+
}
191+
192+
public function testGetSubSystemDetectsCurrentSubsystem(): void
193+
{
194+
$_GET['url'] = 'sub/example';
195+
196+
$controller = new TestableController(new FakeView('<div>test</div>'), new FakeModel());
197+
198+
$this->assertSame('sub', $controller->getSubSystem());
199+
}
200+
201+
public function testSetAsChildControllerSwitchesRootFlag(): void
202+
{
203+
$controller = new TestableController(new FakeView('<div>test</div>'), new FakeModel());
204+
205+
$this->assertTrue($controller->isRootController());
206+
$this->assertFalse($controller->isChildController());
207+
208+
$controller->setAsChildController();
209+
210+
$this->assertFalse($controller->isRootController());
211+
$this->assertTrue($controller->isChildController());
212+
}
213+
}

0 commit comments

Comments
 (0)