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