diff options
| author | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
|---|---|---|
| committer | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
| commit | 4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch) | |
| tree | 5c07151ae61276d334e88f6309c30d439a85c12e /tests/unit/lib | |
| parent | da0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff) | |
| parent | 97a188592c679890a25c37ab78463add76a52ff7 (diff) | |
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'tests/unit/lib')
25 files changed, 1064 insertions, 98 deletions
diff --git a/tests/unit/lib/CalendarcolumnClassTest.php b/tests/unit/lib/CalendarcolumnClassTest.php index 063f97e..d2ac9e0 100644 --- a/tests/unit/lib/CalendarcolumnClassTest.php +++ b/tests/unit/lib/CalendarcolumnClassTest.php @@ -9,7 +9,7 @@ * the License, or (at your option) any later version. */ -require_once 'lib/calendar/CalendarColumn.class.php'; +require_once 'lib/calendar/CalendarColumn.php'; class CalendarColumnCase extends \Codeception\Test\Unit { diff --git a/tests/unit/lib/CalendarviewClassTest.php b/tests/unit/lib/CalendarviewClassTest.php index 962cd06..d810575 100644 --- a/tests/unit/lib/CalendarviewClassTest.php +++ b/tests/unit/lib/CalendarviewClassTest.php @@ -9,7 +9,7 @@ * the License, or (at your option) any later version. */ -require_once 'lib/calendar/CalendarView.class.php'; +require_once 'lib/calendar/CalendarView.php'; class CalendarViewCase extends \Codeception\Test\Unit { diff --git a/tests/unit/lib/FunctionsTest.php b/tests/unit/lib/FunctionsTest.php index 9a92f1a..c254fda 100644 --- a/tests/unit/lib/FunctionsTest.php +++ b/tests/unit/lib/FunctionsTest.php @@ -75,16 +75,35 @@ class FunctionsTest extends \Codeception\Test\Unit } /** - * @covers Trails_Controller::extract_action_and_args() + * @covers Trails\Controller::extract_action_and_args() */ public function testTrailsControllerExtractActionAndArgs() { - $controller = new Trails_Controller(null); - list($action, $args, $format) = $controller->extract_action_and_args('foo/bar//42.html'); + $dispatcher = new Trails\Dispatcher('', '', ''); + $controller = new Trails\Controller($dispatcher); + [$action, $args, $format] = $controller->extract_action_and_args('foo/bar//42.html'); $this->assertEquals('foo', $action); $this->assertEquals(['bar', '', '42'], $args); $this->assertEquals('html', $format); } + + /** + * @covers ::studip_interpolate + */ + public function testStudipInterpolate() + { + $this->assertEquals( + '12bar34', + studip_interpolate('12%{foo}34', ['foo' => 'bar']) + ); + $this->assertEquals( + 'foo', + studip_interpolate('%{ bar }', ['bar' => 'foo']) + ); + + $this->expectException(Exception::class); + studip_interpolate('%{foo}', []); + } } diff --git a/tests/unit/lib/VisualTest.php b/tests/unit/lib/VisualTest.php index dfa2945..2ea8334 100644 --- a/tests/unit/lib/VisualTest.php +++ b/tests/unit/lib/VisualTest.php @@ -9,10 +9,9 @@ * the License, or (at your option) any later version. */ -require_once 'lib/models/SimpleORMap.class.php'; -require_once 'lib/models/OpenGraphURL.class.php'; +require_once 'lib/classes/SimpleORMap.php'; require_once 'lib/visual.inc.php'; -require_once 'lib/classes/Config.class.php'; +require_once 'lib/classes/Config.php'; class VisualFunctionsTest extends \Codeception\Test\Unit { @@ -21,6 +20,7 @@ class VisualFunctionsTest extends \Codeception\Test\Unit static $config = [ 'LOAD_EXTERNAL_MEDIA' => 'allow', 'OPENGRAPH_ENABLE' => false, + 'CONVERT_IDNA_URL' => true, ]; Config::set(new Config($config)); @@ -224,6 +224,16 @@ class VisualFunctionsTest extends \Codeception\Test\Unit $this->assertEquals($expected, formatReady($input)); } + public function testIdnaLink() + { + $input = htmlentities('https://www.täst-dömäne-mit-ümläuten.de'); + + $this->assertEquals( + 'https://www.xn--tst-dmne-mit-mluten-gwbfj61b7e.de', + idna_link($input) + ); + } + private function wrap($string) { return sprintf(FORMATTED_CONTENT_WRAPPER, $string); diff --git a/tests/unit/lib/classes/AvatarClassTest.php b/tests/unit/lib/classes/AvatarClassTest.php index 8172e20..e09a3c2 100644 --- a/tests/unit/lib/classes/AvatarClassTest.php +++ b/tests/unit/lib/classes/AvatarClassTest.php @@ -9,7 +9,7 @@ * the License, or (at your option) any later version. */ -require_once 'lib/phplib/Seminar_Perm.class.php'; +require_once 'lib/phplib/Seminar_Perm.php'; abstract class AvatarTest extends \Codeception\Test\Unit { diff --git a/tests/unit/lib/classes/CronjobScheduleTest.php b/tests/unit/lib/classes/CronjobScheduleTest.php index a97872e..b6fd573 100644 --- a/tests/unit/lib/classes/CronjobScheduleTest.php +++ b/tests/unit/lib/classes/CronjobScheduleTest.php @@ -26,69 +26,15 @@ class CronjobScheduleTest extends \Codeception\Test\Unit StudipTestHelper::tear_down_tables(); } - function testOnceSchedule() - { - $schedule = new CronjobSchedule(); - $schedule->type = 'once'; - - $this->assertEquals('once', $schedule->type); - - return $schedule; - } - - /** - * @depends testOnceSchedule - */ - function testNextExecutionOncePast($schedule) - { - $now = strtotime('10.11.2013 01:02:00'); - $then = strtotime('-2 weeks', $now); - - $schedule->next_execution = $then; - $schedule->calculateNextExecution(); - - $this->assertEquals($then, $schedule->next_execution); - } - - /** - * @depends testOnceSchedule - */ - function testNextExecutionOncePresent($schedule) - { - $now = strtotime('10.11.2013 01:02:00'); - - $schedule->next_execution = $now; - $schedule->calculateNextExecution(); - - $this->assertEquals($now, $schedule->next_execution); - } - - /** - * @depends testOnceSchedule - */ - function testNextExecutionOnceFuture(CronjobSchedule $schedule) - { - $now = strtotime('10.11.2013 01:02:00'); - $then = strtotime('+2 weeks', $now); - - $schedule->next_execution = $then; - $schedule->calculateNextExecution($now); - - $this->assertEquals($then, $schedule->next_execution); - } - function testPeriodicSchedule() { $schedule = new CronjobSchedule(); - $schedule->type = 'periodic'; $schedule->minute = null; $schedule->hour = null; $schedule->day = null; $schedule->month = null; $schedule->day_of_week = null; - $this->assertEquals('periodic', $schedule->type); - return $schedule; } diff --git a/tests/unit/lib/classes/IconClassTest.php b/tests/unit/lib/classes/IconClassTest.php index eb743b9..0e79df9 100644 --- a/tests/unit/lib/classes/IconClassTest.php +++ b/tests/unit/lib/classes/IconClassTest.php @@ -27,7 +27,7 @@ class IconClassTest extends \Codeception\Test\Unit { $this->assertEquals( '<img width="16" height="16" src="images/icons/blue/vote.svg" alt="" class="icon-role-clickable icon-shape-vote">', - Icon::create('vote', 'clickable')->asImg() + Icon::create('vote')->asImg() ); } @@ -35,7 +35,7 @@ class IconClassTest extends \Codeception\Test\Unit { $this->assertEquals( '<img width="16" height="16" src="images/icons/blue/vote.svg" alt="" class="icon-role-clickable icon-shape-vote">', - Icon::create('vote', 'clickable')->asImg() + Icon::create('vote')->asImg() ); } @@ -43,7 +43,7 @@ class IconClassTest extends \Codeception\Test\Unit { $this->assertEquals( '<img width="20" height="20" src="images/icons/blue/vote.svg" alt="" class="icon-role-clickable icon-shape-vote">', - Icon::create('vote', 'clickable')->asImg(20) + Icon::create('vote')->asImg(20) ); } @@ -51,7 +51,7 @@ class IconClassTest extends \Codeception\Test\Unit { $this->assertEquals( '<img title="Mit Anhang" width="20" height="20" src="images/icons/blue/vote.svg" class="icon-role-clickable icon-shape-vote">', - Icon::create('vote', 'clickable', ['title' => _("Mit Anhang")])->asImg(20) + Icon::create('vote')->asImg(20, ['title' => _('Mit Anhang')]) ); } @@ -59,7 +59,7 @@ class IconClassTest extends \Codeception\Test\Unit { $this->assertEquals( '<img hspace="3" width="16" height="16" src="images/icons/blue/arr_2left.svg" alt="" class="icon-role-clickable icon-shape-arr_2left">', - Icon::create('arr_2left', 'clickable')->asImg(['hspace' => 3]) + Icon::create('arr_2left')->asImg(['hspace' => 3]) ); } @@ -67,7 +67,7 @@ class IconClassTest extends \Codeception\Test\Unit { $this->assertEquals( '<img class="text-bottom icon-role-info icon-shape-staple" width="20" height="20" src="images/icons/black/staple.svg" alt="">', - Icon::create('staple', 'info')->asImg(20, ['class' => 'text-bottom']) + Icon::create('staple', Icon::ROLE_INFO)->asImg(20, ['class' => 'text-bottom']) ); } @@ -75,7 +75,7 @@ class IconClassTest extends \Codeception\Test\Unit { $this->assertEquals( '<img title="Datei hochladen" class="text-bottom icon-role-new icon-shape-upload" width="20" height="20" src="images/icons/red/upload.svg">', - Icon::create('upload', 'new', ['title' => _("Datei hochladen")]) + Icon::create('upload', Icon::ROLE_NEW, ['title' => _("Datei hochladen")]) ->asImg(20, ['class' => 'text-bottom']) ); } @@ -84,22 +84,22 @@ class IconClassTest extends \Codeception\Test\Unit { $this->assertEquals( '<input type="image" class="text-bottom icon-role-clickable icon-shape-upload" width="20" height="20" src="images/icons/blue/upload.svg" alt="">', - Icon::create('upload', 'clickable')->asInput(20, ['class' => 'text-bottom']) + Icon::create('upload')->asInput(20, ['class' => 'text-bottom']) ); } function testIconIsImmutable() { - $icon = Icon::create('upload', 'clickable', ['title' => _('a title')]); - $copy = $icon->copyWithRole('clickable'); + $icon = Icon::create('upload', Icon::ROLE_CLICKABLE, ['title' => _('a title')]); + $copy = $icon->copyWithRole(Icon::ROLE_CLICKABLE); $this->assertNotSame($icon, $copy); } function testIconCopyWithRole() { - $icon = Icon::create('upload', 'clickable', ['title' => _('a title')]); - $copy = $icon->copyWithRole('info'); + $icon = Icon::create('upload', Icon::ROLE_CLICKABLE, ['title' => _('a title')]); + $copy = $icon->copyWithRole(Icon::ROLE_INFO); $this->assertEquals($icon->getShape(), $copy->getShape()); $this->assertNotEquals($icon->getRole(), $copy->getRole()); @@ -108,7 +108,7 @@ class IconClassTest extends \Codeception\Test\Unit function testIconCopyWithShape() { - $icon = Icon::create('upload', 'clickable', ['title' => _('a title')]); + $icon = Icon::create('upload', Icon::ROLE_CLICKABLE, ['title' => _('a title')]); $copy = $icon->copyWithShape('staple'); $this->assertNotEquals($icon->getShape(), $copy->getShape()); @@ -118,7 +118,7 @@ class IconClassTest extends \Codeception\Test\Unit function testIconCopyWithAttributes() { - $icon = Icon::create('upload', 'clickable', ['title' => _('a title')]); + $icon = Icon::create('upload', Icon::ROLE_CLICKABLE, ['title' => _('a title')]); $copy = $icon->copyWithAttributes(['title' => _('another title')]); $this->assertEquals($icon->getShape(), $copy->getShape()); @@ -136,7 +136,7 @@ class IconClassTest extends \Codeception\Test\Unit { $this->assertEquals( 'background-image:url(images/icons/blue/vote.svg);background-size:17px 17px;', - Icon::create('vote', 'clickable')->asCSS(17) + Icon::create('vote')->asCSS(17) ); } @@ -144,7 +144,7 @@ class IconClassTest extends \Codeception\Test\Unit { $this->assertEquals( 'images/icons/blue/vote.svg', - Icon::create('vote', 'clickable')->asImagePath() + Icon::create('vote')->asImagePath() ); } @@ -152,7 +152,7 @@ class IconClassTest extends \Codeception\Test\Unit { $this->assertEquals( '<img src="images/icons/blue/vote.svg" alt="" class="icon-role-clickable icon-shape-vote">', - Icon::create('vote', 'clickable')->asImg(false) + Icon::create('vote')->asImg(false) ); } @@ -160,7 +160,19 @@ class IconClassTest extends \Codeception\Test\Unit { $this->assertEquals( '<input type="image" src="images/icons/blue/upload.svg" alt="" class="icon-role-clickable icon-shape-upload">', - Icon::create('upload', 'clickable')->asInput(false) + Icon::create('upload')->asInput(false) + ); + } + + function testIconCreateRemovedExtras() + { + $this->assertEquals( + '<img src="images/icons/blue/vote.svg" alt="" class="icon-role-clickable icon-shape-vote">', + Icon::create('add/vote')->asImg(false) + ); + $this->assertEquals( + '<img src="images/icons/blue/vote.svg" alt="" class="icon-role-clickable icon-shape-vote">', + Icon::create('vote+add')->asImg(false) ); } } diff --git a/tests/unit/lib/classes/MarkupClassTest.php b/tests/unit/lib/classes/MarkupClassTest.php index d1c35b1..347e453 100644 --- a/tests/unit/lib/classes/MarkupClassTest.php +++ b/tests/unit/lib/classes/MarkupClassTest.php @@ -21,15 +21,15 @@ require_once 'tests/unit/fakeserver.php'; # needed by visual.inc.php -require_once 'lib/classes/DbView.class.php'; -require_once 'lib/classes/TreeAbstract.class.php'; +require_once 'lib/classes/DbView.php'; +require_once 'lib/classes/TreeAbstract.php'; -# needed by Markup.class.php +# needed by Markup.php require_once 'lib/visual.inc.php'; -require_once 'lib/classes/Config.class.php'; +require_once 'lib/classes/Config.php'; # class and functions that are tested by this script -require_once 'lib/classes/Markup.class.php'; +require_once 'lib/classes/Markup.php'; # Seminar_Session cannot be mocked since it uses static functions. # Also, including phplib_local.inc.php, where Seminar_Session is diff --git a/tests/unit/lib/classes/MigrationTest.php b/tests/unit/lib/classes/MigrationTest.php index 444ebf2..12df120 100644 --- a/tests/unit/lib/classes/MigrationTest.php +++ b/tests/unit/lib/classes/MigrationTest.php @@ -16,11 +16,6 @@ class MigrationTest extends \Codeception\Test\Unit $this->before = $GLOBALS['CACHING_ENABLE'] ?? null; $GLOBALS['CACHING_ENABLE'] = false; - require_once 'lib/classes/StudipCache.class.php'; - require_once 'lib/classes/StudipMemoryCache.class.php'; - require_once 'lib/classes/StudipCacheFactory.class.php'; - require_once 'lib/models/SimpleORMap.class.php'; - require_once 'lib/migrations/Migration.php'; require_once 'lib/migrations/Migrator.php'; require_once 'lib/migrations/SchemaVersion.php'; diff --git a/tests/unit/lib/classes/OAuth1Test.php b/tests/unit/lib/classes/OAuth1Test.php new file mode 100644 index 0000000..84d4fb2 --- /dev/null +++ b/tests/unit/lib/classes/OAuth1Test.php @@ -0,0 +1,118 @@ +<?php + +use Psr\Http\Message\ServerRequestInterface; +use Studip\OAuth1; + +/** + * All values are from the OAuth 1.0 Authentication Sandbox (using the example + * used in the OAuth Specification). + * + * @see http://lti.tools/oauth/ + */ +final class OAuth1Test extends \Codeception\Test\Unit +{ + /** + * @covers OAuth1::getSignatureBaseString + */ + public function testCreationOfBaseString(): void + { + $this->assertEquals( + 'GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal', + OAuth1::getSignatureBaseString($this->getDefaultTestRequest()) + ); + } + + /** + * @covers OAuth1::signRequest + */ + public function testSigningARequest(): void + { + $this->assertEquals( + 'tR3+Ty81lMeYAr/Fid0kMTYa/WM=', + OAuth1::signRequest( + $this->getDefaultTestRequest(), + 'kd94hf93k423kf44', + 'pfkkdhi9sl3r4s00', + 'HMAC-SHA1' + ) + ); + } + + /** + * @covers OAuth1::verifyRequest + */ + public function testVerifyingARequest(): void + { + $this->assertTrue( + OAuth1::verifyRequest( + $this->getDefaultTestRequest(['oauth_signature' => 'tR3+Ty81lMeYAr/Fid0kMTYa/WM=']), + 'kd94hf93k423kf44', + 'pfkkdhi9sl3r4s00' + ) + ); + } + + /** + * @covers OAuth1::verifyRequest + * @covers OAuth1::extractParameters + */ + public function testVerifyingARequestFromAuthorizationHeader(): void + { + $parameters = [ + ...$this->getDefaultParameters(), + 'oauth_signature' => 'tR3+Ty81lMeYAr/Fid0kMTYa/WM=' + ]; + + + $request = $this->getTestRequest()->withHeader( + 'Authorization', + 'OAuth ' . implode(',', array_map( + fn($key, $value) => sprintf('%s="%s"', $key, $value), + array_keys($parameters), + array_values($parameters) + )) + ); + + $this->assertTrue( + OAuth1::verifyRequest( + $request, + 'kd94hf93k423kf44', + 'pfkkdhi9sl3r4s00' + ) + ); + } + + private function getTestRequest(): ServerRequestInterface + { + $factory = new Slim\Psr7\Factory\ServerRequestFactory(); + return $factory->createServerRequest( + 'GET', + 'http://photos.example.net/photos' + )->withQueryParams([ + 'size' => 'original', + 'file' => 'vacation.jpg', + ]); + } + + private function getDefaultTestRequest(array $parameters = []): ServerRequestInterface + { + $request = $this->getTestRequest(); + return $request->withQueryParams([ + ...$request->getQueryParams(), + ...$this->getDefaultParameters(), + ...$parameters, + ]); + } + + private function getDefaultParameters(): array + { + return [ + 'oauth_consumer_key' => 'dpf43f3p2l4k3l03', + 'oauth_token' => 'nnch734d00sl2jdk', + 'oauth_nonce' => 'kllo9940pd9333jh', + 'oauth_timestamp' => '1191242096', + 'oauth_signature_method' => 'HMAC-SHA1', + 'oauth_version' => '1.0', + ]; + } +} diff --git a/tests/unit/lib/classes/OpenGraphTest.php b/tests/unit/lib/classes/OpenGraphTest.php new file mode 100644 index 0000000..416660b --- /dev/null +++ b/tests/unit/lib/classes/OpenGraphTest.php @@ -0,0 +1,34 @@ +<?php +/** + * @author Jan-Hendrik Willms <tleilax+studip@gmail.com> + * @license GPL2 or any later version + */ +class OpenGraphTest extends \Codeception\Test\Unit +{ + public function setUp(): void + { + static $config = [ + 'OPENGRAPH_ENABLE' => true, + ]; + + Config::set(new Config($config)); + } + + public function testURLExtraction() + { + $text = 'this is a link: https://example.org?foo=bar&bar=foo - believe it or not'; + $urls = OpenGraph::extractUrlsFromText($text); + + $this->assertCount(1, $urls); + $this->assertEquals('https://example.org?foo=bar&bar=foo', $urls[0]); + } + + public function testURLExtractionFromHTML() + { + $html = Studip\Markup::HTML_MARKER . '<a href="https://example.org?foo=bar&bar=foo">this is a link</a> - believe it or not'; + $urls = OpenGraph::extractUrlsFromHtml($html); + + $this->assertCount(1, $urls); + $this->assertEquals('https://example.org?foo=bar&bar=foo', $urls[0]); + } +} diff --git a/tests/unit/lib/classes/PluginRepositoryTest.php b/tests/unit/lib/classes/PluginRepositoryTest.php index 6676b7c..d045d3f 100644 --- a/tests/unit/lib/classes/PluginRepositoryTest.php +++ b/tests/unit/lib/classes/PluginRepositoryTest.php @@ -10,7 +10,7 @@ * the License, or (at your option) any later version. */ -require_once 'lib/plugins/engine/PluginRepository.class.php'; +require_once 'lib/plugins/engine/PluginRepository.php'; class PluginRepositoryTest extends \Codeception\Test\Unit { diff --git a/tests/unit/lib/classes/RequestParametersTest.php b/tests/unit/lib/classes/RequestParametersTest.php index 85194c4..85ef33c 100644 --- a/tests/unit/lib/classes/RequestParametersTest.php +++ b/tests/unit/lib/classes/RequestParametersTest.php @@ -33,12 +33,20 @@ class RequestParametersTest extends Codeception\Test\Unit $_GET['v3'] = ['root@studip', 'hotte.testfreund', 42, '!"$%&/()']; $_POST['v4'] = ['0', '1', '', 'foo']; + $_GET['date'] = '2025-03-25'; + $_GET['time'] = '17:39:04'; + $_GET['datetime'] = '2025-03-25 17:39:04'; + $_GET['invalid_date'] = 'foobar'; + $testconfig = new Config([ 'USERNAME_REGULAR_EXPRESSION' => '/^([a-zA-Z0-9_@.-]{4,})$/', ]); Config::set($testconfig); } + /** + * @covers Request::offsetGet + */ public function testArrayAccess () { $request = Request::getInstance(); @@ -49,6 +57,9 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertSame($request['c'], '-23'); } + /** + * @covers Request::set + */ public function testSetParam () { Request::set('yyy', 'xyzzy'); @@ -58,6 +69,10 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertSame(Request::getArray('zzz'), [1, 2]); } + /** + * @covers Request::get + * @covers Request::quoted + */ public function testStringParam () { $this->assertNull(Request::get('null')); @@ -74,6 +89,9 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertNull(Request::quoted('v2')); } + /** + * @covers Request::option + */ public function testOptionParam () { $this->assertNull(Request::option('null')); @@ -82,6 +100,9 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertNull(Request::option('v1')); } + /** + * @covers Request::int + */ public function testIntParam () { $this->assertNull(Request::int('null')); @@ -92,6 +113,9 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertNull(Request::int('v1')); } + /** + * @covers Request::float + */ public function testFloatParam () { $this->assertNull(Request::float('null')); @@ -102,6 +126,9 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertNull(Request::float('v1')); } + /** + * @covers Request::bool + */ public function testBoolParam () { $this->assertNull(Request::bool('null')); @@ -115,6 +142,9 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertNull(Request::bool('v1')); } + /** + * @covers Request::username + */ public function testUsernameParam () { $this->assertNull(Request::username('null')); @@ -124,6 +154,10 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertNull(Request::username('v1')); } + /** + * @covers Request::getArray + * @covers Request::quotedArray + */ public function testStringArrayParam () { $this->assertSame(Request::getArray('null'), []); @@ -137,6 +171,9 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertSame(Request::quotedArray('v2'), ['on\\\'e', 'two', 'thr33']); } + /** + * @covers Request::optionArray + */ public function testOptionArrayParam () { $this->assertSame(Request::optionArray('null'), []); @@ -145,6 +182,9 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertSame(Request::optionArray('v2'), [1 => 'two', 2 => 'thr33']); } + /** + * @covers Request::intArray + */ public function testIntArrayParam () { $this->assertSame(Request::intArray('null'), []); @@ -153,6 +193,9 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertSame(Request::intArray('v2'), [0, 0, 0]); } + /** + * @covers Request::floatArray + */ public function testFloatArrayParam () { $this->assertSame(Request::floatArray('null'), []); @@ -161,6 +204,9 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertSame(Request::floatArray('v2'), [0.0, 0.0, 0.0]); } + /** + * @covers Request::boolArray + */ public function testBoolArrayParam () { $this->assertSame(Request::boolArray('null'), []); @@ -168,6 +214,9 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertSame(Request::boolArray('v4'), [false, true, false, true]); } + /** + * @covers Request::usernameArray + */ public function testUsernameArrayParam () { $this->assertSame(Request::usernameArray('null'), []); @@ -177,6 +226,9 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertSame(Request::usernameArray('v3'), ['root@studip', 'hotte.testfreund']); } + /** + * @covers Request::submitted + */ public function testSubmitted () { $this->assertFalse(Request::submitted('null')); @@ -184,12 +236,54 @@ class RequestParametersTest extends Codeception\Test\Unit $this->assertTrue(Request::submitted('v1')); } + /** + * @covers Request::submittedSome + */ public function testSubmittedSome () { $this->assertFalse(Request::submittedSome('null', 'null')); $this->assertTrue(Request::submittedSome('null', 's', 'v')); } + /** + * @covers Request::getDateTime + */ + public function testGetDatetimeWithDate() + { + $date = Request::getDateTime(); + $this->assertNotFalse($date); + $this->assertEquals('2025-03-25 00:00:00', $date->format('Y-m-d H:i:s')); + } + + /** + * @covers Request::getDateTime + */ + public function testGetDatetimeWithDateAndTime() + { + $datetime = Request::getDateTime('datetime', 'Y-m-d H:i:s'); + $this->assertNotFalse($datetime); + $this->assertEquals('2025-03-25 17:39:04', $datetime->format('Y-m-d H:i:s')); + } + + /** + * @covers Request::getDateTime + */ + public function testGetDatetimeWithDateAndTimeInTwoParameters() + { + $date = Request::getDateTime('date', 'Y-m-d', 'time', 'H:i:s'); + $this->assertNotFalse($date); + $this->assertEquals('2025-03-25 17:39:04', $date->format('Y-m-d H:i:s')); + } + + /** + * @covers Request::getDateTime + */ + public function testGetDatetimeWithInvalidDate() + { + $invalid_date = Request::getDateTime('invalid_date'); + $this->assertFalse($invalid_date); + } + public function tearDown(): void { Config::set(null); diff --git a/tests/unit/lib/classes/SimpleOrMapNodbTest.php b/tests/unit/lib/classes/SimpleOrMapNodbTest.php index 4c35d27..3ede1aa 100644 --- a/tests/unit/lib/classes/SimpleOrMapNodbTest.php +++ b/tests/unit/lib/classes/SimpleOrMapNodbTest.php @@ -46,10 +46,17 @@ class auth_user_md5 extends SimpleORMap } } +/** + * @backupGlobals enabled + */ class SimpleOrMapNodbTest extends \Codeception\Test\Unit { protected static function setupFixture(): void { + if (count($GLOBALS['CONTENT_LANGUAGES']) < 2) { + $GLOBALS['CONTENT_LANGUAGES']['en_GB'] = ['picture' => 'lang_en.gif', 'name' => 'English']; + } + StudipTestHelper::set_up_tables(['auth_user_md5']); } diff --git a/tests/unit/lib/classes/StudipCachedArrayTest.php b/tests/unit/lib/classes/StudipCachedArrayTest.php index c98c1bd..5fd39f2 100644 --- a/tests/unit/lib/classes/StudipCachedArrayTest.php +++ b/tests/unit/lib/classes/StudipCachedArrayTest.php @@ -1,4 +1,7 @@ <?php + +use Studip\Cache\MemoryCache; + /** * StudipCachedArrayTest.php - unit tests for the StudipCachedArray class * @@ -6,7 +9,7 @@ * @license GPL2 or any later version * * @covers StudipCachedArray - * @uses StudipMemoryCache + * @uses MemoryCache */ class StudipCachedArrayTest extends \Codeception\Test\Unit diff --git a/tests/unit/lib/classes/StudipControllerTest.php b/tests/unit/lib/classes/StudipControllerTest.php index f7e4ef4..51359ab 100644 --- a/tests/unit/lib/classes/StudipControllerTest.php +++ b/tests/unit/lib/classes/StudipControllerTest.php @@ -27,13 +27,13 @@ final class StudipControllerTest extends Codeception\Test\Unit parent::tearDown(); } - private function getDispatcher(): Trails_Dispatcher + private function getDispatcher(): Trails\Dispatcher { $trails_root = $GLOBALS['STUDIP_BASE_PATH'] . DIRECTORY_SEPARATOR . 'app'; $trails_uri = rtrim($GLOBALS['ABSOLUTE_URI_STUDIP'], '/') . '/dispatch.php'; $default_controller = 'default'; - return new Trails_Dispatcher($trails_root, $trails_uri, $default_controller); + return new Trails\Dispatcher($trails_root, $trails_uri, $default_controller); } private function getController(): StudipController @@ -247,7 +247,7 @@ final class StudipControllerTest extends Codeception\Test\Unit { $args = [$should_fail]; - $this->expectException(Trails_Exception::class); + $this->expectException(Trails\Exception::class); $this->getController()->validate_args($args); } diff --git a/tests/unit/lib/classes/StudipFileloaderTest.php b/tests/unit/lib/classes/StudipFileloaderTest.php index 1ffe6b5..102aaac 100644 --- a/tests/unit/lib/classes/StudipFileloaderTest.php +++ b/tests/unit/lib/classes/StudipFileloaderTest.php @@ -20,7 +20,7 @@ class StudipFileloaderTestCase extends \Codeception\Test\Unit ]); if (!stream_wrapper_register('var', 'ArrayFileStream')) { - new Exception('Failed to register protocol'); + throw new Exception('Failed to register protocol'); } } @@ -56,7 +56,7 @@ class StudipFileloaderTestCase extends \Codeception\Test\Unit public function test_should_balk_upon_file_not_found() { - $this->expectException(\PHPUnit\Framework\Exception::class); + $this->expectException(Exception::class); StudipFileloader::load('var://pathto/not-there.php', $container); } } diff --git a/tests/unit/lib/classes/TrailsTest.php b/tests/unit/lib/classes/TrailsTest.php new file mode 100644 index 0000000..d51b795 --- /dev/null +++ b/tests/unit/lib/classes/TrailsTest.php @@ -0,0 +1,25 @@ +<?php +class TrailsTest extends \Codeception\Test\Unit +{ + /** + * @covers Trails\Inflector::camelize + */ + public function testInflectorCamelize(): void + { + $this->assertEquals( + 'Path_SubPath_UnderscoreController', + Trails\Inflector::camelize('path/sub_path/underscore_controller') + ); + } + + /** + * @covers Trails\Inflector::underscore + */ + public function testInflectorUnderscore(): void + { + $this->assertEquals( + 'path/sub_path/underscore_controller', + Trails\Inflector::underscore('Path_SubPath_UnderscoreController') + ); + } +} diff --git a/tests/unit/lib/classes/extTPLTemplateTest.php b/tests/unit/lib/classes/extTPLTemplateTest.php new file mode 100644 index 0000000..43a9629 --- /dev/null +++ b/tests/unit/lib/classes/extTPLTemplateTest.php @@ -0,0 +1,213 @@ +<?php +/* + * template_test.php - expression template unit tests + * + * Copyright (c) 2013 Elmar Ludwig + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +use exTpl\Template; + +class extTplTemplateTest extends \Codeception\Test\Unit +{ + public function testSimpleString() + { + $bindings = []; + $template = 'The quick brown fox jumps over the layz dog.'; + $expected = $template; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testConstantExpression() + { + $bindings = array(); + $template = '17 + 4 = {"foo" != "bar" ? 17 + 4 : 42.0}'; + $expected = '17 + 4 = 21'; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testConditionExpression() + { + $bindings = array('a' => 0, 'b' => 42); + $template = 'answer is {"" ?: a ?: b}'; + $expected = 'answer is 42'; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testStringEscapes() + { + $bindings = array(); + $template = '"{"\\tfoo\'\\"\\n"}{\'{"bar"}\'}"'; + $expected = "\"\tfoo'\"\n{\"bar\"}\""; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testOperatorPrecedence() + { + $bindings = array('val' => array(array(42))); + $template = '{-val[0][0] / (17+4) + 8 > 6 && "foo" == "f"~"o"~"o" ? 1 : 2}'; + $expected = '2'; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testSimpleBindings() + { + $bindings = array('foo' => 'bar', 'val' => array(17, 4), 'pi' => 3.14159); + $template = 'foo = "{foo}", sum = {val[0] + val[1]}, pi^2 = {pi * pi}, x = {x}'; + $expected = 'foo = "bar", sum = 21, pi^2 = 9.8695877281, x = '; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testConditional() + { + $bindings = array('foo' => 'bar', 'pi' => 3.14159); + $template = '{if foo == "foo"}NO{elseif foo == "bar"}pi = {pi}{else}NO{endif}'; + $expected = 'pi = 3.14159'; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testConditionalIteration() + { + $bindings = array('foo' => 'bar', 'pi' => 3.14159); + $template = '{foreach foo}{if foo}{foo}{endif}{endforeach}'; + $expected = 'bar'; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testIteration() + { + $bindings = array('persons' => array( + 1 => array('user' => 'jane', 'phone' => '555-81281'), + 2 => array('user' => 'mike', 'phone' => '230-28382'), + 3 => array('user' => 'john', 'phone' => '911-19212') + )); + $template = '<ul>{foreach persons as person}<li>{index~":"~person.user~":"~phone}</li>{endforeach}</ul>'; + $expected = '<ul>' . + '<li>1:jane:555-81281</li>' . + '<li>2:mike:230-28382</li>' . + '<li>3:john:911-19212</li>' . + '</ul>'; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testEmptyIteration() + { + $bindings = array('foo' => array(), 'bar' => false); + $template = '{foreach foo}foo{endforeach}:{foreach bar}bar{endforeach}'; + $expected = ':'; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testVariableScope() + { + $bindings = array('value' => 42, 'test' => array( + array(), + array('value' => 17), + array('test' => array( + array(), + array('value' => 4) + )) + )); + $template = '{foreach test}{value}:{foreach test}{value}~{endforeach}{endforeach}'; + $expected = '42:42~17~42~17:17~17~17~42:42~4~'; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testNestedStatements() + { + foreach (range(0, 9) as $i) { + $bindings['loop'][$i]['i'] = "$i"; + } + $template = '{foreach loop}' . + '{if i+1>4 && i<(1+10/2)}{i==4*1 ? \'foo\'~i : "bar"}' . + '{elseif !(i<=+4)}+{elseif i==""}..{else}{"-"}{endif}' . + '{endforeach}'; + $expected = '----foo4bar++++'; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testFunctionCall() + { + $bindings = array('val' => array(0, 1, 2, 3)); + $template = '{strlen("foobar") + count(val)}'; + $expected = '10'; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testFilters() + { + $bindings = array( + 'pi' => 3.14159, + 'format' => function($a, $b) { return number_format($a, $b); }, + 'upper' => function($a) { return strtoupper($a); } + ); + $template = '{pi|format(3) ~ ":" ~ "foobar"|upper}'; + $expected = '3.142:FOOBAR'; + $tmpl_obj = new Template($template); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testRawFilter() + { + $bindings = array('foo' => '<img>', 'upper' => function($a) { return strtoupper($a); }); + $template = '{foo}:{foo|upper|raw}'; + $expected = '<img>:<IMG>'; + $tmpl_obj = new Template($template); + $tmpl_obj->autoescape('html'); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testHtmlAutoEscape() + { + $bindings = array('foo' => '<img>', 'pi' => 3.14159); + $template = '{foo}:{pi}'; + $expected = '<img>:3.14159'; + $tmpl_obj = new Template($template); + $tmpl_obj->autoescape('html'); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } + + public function testJsonAutoEscape() + { + $bindings = array('foo' => '<img>', 'pi' => 3.14159); + $template = '{foo}:{pi}'; + $expected = '"<img>":3.14159'; + $tmpl_obj = new Template($template); + $tmpl_obj->autoescape('json'); + + $this->assertEquals($expected, $tmpl_obj->render($bindings)); + } +} diff --git a/tests/unit/lib/flexi/FactoryTest.php b/tests/unit/lib/flexi/FactoryTest.php new file mode 100644 index 0000000..f8b9b87 --- /dev/null +++ b/tests/unit/lib/flexi/FactoryTest.php @@ -0,0 +1,119 @@ +<?php + +use Flexi\Factory; +use Flexi\TemplateNotFoundException; +use Flexi\PhpTemplate; + +final class FactoryTestCase extends \Codeception\Test\Unit +{ + private Factory $factory; + + public function setUp(): void + { + $this->setUpFS(); + + $this->factory = new Factory('var://templates'); + } + + public function tearDown(): void + { + unset($this->factory); + stream_wrapper_unregister('var'); + } + + public function setUpFS(): void + { + ArrayFileStream::set_filesystem([ + 'templates' => [ + 'foo.php' => 'some content', + 'baz.unknown' => 'some content', + 'multiplebasenames' => [ + 'foo.txt' => 'there is no matching template class', + 'foo.php' => 'some content', + 'bar.txt' => 'there is no matching template class', + ], + 'baz.known-ext' => 'some content', + ], + ]); + if (!stream_wrapper_register('var', ArrayFileStream::class)) { + die('Failed to register protocol'); + } + } + + public function testShouldCreateFactory() + { + $factory = new Factory('.'); + $this->assertNotNull($factory); + } + + public function testShouldCreateFactoryUsingPath() + { + $path = 'var://'; + $factory = new Factory($path); + $this->assertNotNull($factory); + } + + public function testShouldOpenTemplateUsingRelativePath() + { + $foo = $this->factory->open('foo'); + $this->assertNotNull($foo); + } + + public function testShouldOpenTemplateUsingAbsolutePath() + { + $foo = $this->factory->open('var://templates/foo'); + $this->assertNotNull($foo); + } + + public function testShouldThrowAnExceptionOpeningAMissingTemplateWithoutFileExtension() + { + $this->expectException(TemplateNotFoundException::class); + $this->factory->open('bar'); + } + + public function testShouldThrowAnExceptionOpeningAMissingTemplateWithFileExtension() + { + $this->expectException(TemplateNotFoundException::class); + $this->factory->open('bar.php'); + } + + public function testShouldOpenTemplateUsingExtension() + { + $this->assertInstanceOf( + PhpTemplate::class, + $this->factory->open('foo.php') + ); + } + + public function testShouldThrowAnExceptionWhenOpeningATemplateWithUnknownExtension() + { + $this->expectException(TemplateNotFoundException::class); + $this->factory->open('baz'); + } + + public function testShouldThrowAnExceptionOpeningATemplateInANonExistingDirectory() + { + $this->expectException(TemplateNotFoundException::class); + $this->factory->open('doesnotexist/foo'); + } + + public function testShouldSearchForASupportedTemplate() + { + $this->assertInstanceOf( + PhpTemplate::class, + $this->factory->open('multiplebasenames/foo') + ); + } + + public function testShouldRespondToAddedHandlers() + { + $handler = new class('', $this->factory) extends Flexi\Template { + protected function _render(): string + { + return ''; + } + }; + $this->factory->add_handler('known-ext', $handler::class); + $this->factory->open('baz.known-ext'); + } +} diff --git a/tests/unit/lib/flexi/PHPTemplatePartialBugTest.php b/tests/unit/lib/flexi/PHPTemplatePartialBugTest.php new file mode 100644 index 0000000..ef265cf --- /dev/null +++ b/tests/unit/lib/flexi/PHPTemplatePartialBugTest.php @@ -0,0 +1,45 @@ +<?php + +use Flexi\Factory; + +final class PhpTemplatePartialBugTestCase extends Codeception\Test\Unit +{ + public function setUp(): void + { + $this->setUpFS(); + $this->factory = new Factory('var://templates/'); + } + + public function tearDown(): void + { + unset($this->factory); + + stream_wrapper_unregister("var"); + } + + public function setUpFS(): void + { + ArrayFileStream::set_filesystem([ + 'templates' => [ + 'layout.php' => + '<? $do_not_echo_this = $this->render_partial_collection("partial", range(1, 5));' . + 'echo $content_for_layout;', + 'partial.php' => + 'partial', + 'template.php' => + 'template', + ] + ]); + if (!stream_wrapper_register('var', ArrayFileStream::class)) { + die('Failed to register protocol'); + } + } + + public function testPartialBug() + { + $template = $this->factory->open('template'); + $template->set_layout('layout'); + $result = $template->render(); + $this->assertEquals($result, "template"); + } +} diff --git a/tests/unit/lib/flexi/PHPTemplateTest.php b/tests/unit/lib/flexi/PHPTemplateTest.php new file mode 100644 index 0000000..5dfd247 --- /dev/null +++ b/tests/unit/lib/flexi/PHPTemplateTest.php @@ -0,0 +1,136 @@ +<?php + +use Flexi\Factory; +use Flexi\TemplateNotFoundException; + +final class PhpTemplateTestCase extends Codeception\Test\Unit +{ + private Factory $factory; + + public function setUp(): void + { + $this->setUpFS(); + $this->factory = new Factory('var://templates/'); + } + + + public function tearDown(): void + { + unset($this->factory); + + stream_wrapper_unregister('var'); + } + + public function setUpFS() + { + ArrayFileStream::set_filesystem([ + 'templates' => [ + 'foo_using_partial.php' => + 'Hello, <?= $this->render_partial("foos_partial") ?>!', + + 'foos_partial.php' => + '<h1><?= $whom ?> at <?= $when ?></h1>', + + 'foo_with_partial_collection.php' => + '[<?= $this->render_partial_collection("item", $items, "spacer") ?>]', + + 'item.php' => + '"<?= $item ?>"', + + 'spacer.php' => + ', ', + + 'attributes.php' => + '<? foreach (get_defined_vars() as $name => $value) : ?>' . + '<?= $name ?><?= $value ?>' . + '<? endforeach ?>', + + 'foo.php' => + 'Hello, <?= $whom ?>!', + + 'layout.php' => + '[<?= $content_for_layout ?>]', + ] + ]); + if (!stream_wrapper_register('var', ArrayFileStream::class)) { + die('Failed to register protocol'); + } + } + + public function testRenderPartial() + { + $template = $this->factory->open('foo_using_partial'); + $template->set_attribute('whom', 'bar'); + $this->assertEquals( + 'Hello, <h1>bar at now</h1>!', + $template->render(['when' => 'now']) + ); + } + + public function testRenderPartialCollection() + { + $template = $this->factory->open('foo_with_partial_collection'); + $result = $template->render_partial_collection( + 'item', + range(1, 3), + 'spacer' + ); + $this->assertEquals('"1", "2", "3"', $result); + } + + public function testShouldOverrideAttributesWithThosePassedToRender() + { + $template = $this->factory->open('attributes'); + $template->set_attribute('foo', 'baz'); + + $template->render(['foo' => 'bar']); + $this->assertEquals('bar', $template->get_attribute('foo')); + + $template->render(); + $this->assertEquals('bar', $template->get_attribute('foo')); + } + + public function testRenderWithoutLayout() + { + $foo = $this->factory->open('foo'); + $foo->set_attribute('whom', 'bar'); + $this->assertEquals('Hello, bar!', $foo->render()); + } + + public function testRenderWithLayout() + { + $foo = $this->factory->open('foo'); + $foo->set_attribute('whom', 'bar'); + $foo->set_layout('layout'); + $out = $foo->render(); + $this->assertEquals('[Hello, bar!]', $out); + } + + public function testRenderWithLayoutInline() + { + $this->assertEquals( + '[Hello, bar!]', + $this->factory->render('foo', ['whom' => 'bar'], 'layout') + ); + } + + public function testRenderWithMissingLayout() + { + $foo = $this->factory->open('foo'); + $this->expectException(TemplateNotFoundException::class); + $foo->set_layout('nosuchlayout'); + } + + public function testRenderWithAttributes() + { + $foo = $this->factory->open('foo'); + $foo->set_attribute('whom', 'bar'); + $foo->set_layout('layout'); + $foo_out = $foo->render(); + + $bar = $this->factory->open('foo'); + $bar_out = $bar->render(['whom' => 'bar'], 'layout'); + + $this->assertEquals($foo_out, $bar_out); + } +} diff --git a/tests/unit/lib/flexi/TemplateEmptyTest.php b/tests/unit/lib/flexi/TemplateEmptyTest.php new file mode 100644 index 0000000..c5ebd79 --- /dev/null +++ b/tests/unit/lib/flexi/TemplateEmptyTest.php @@ -0,0 +1,44 @@ +<?php + +use Flexi\Factory; +use Flexi\Template; + +final class TemplateEmptyTestCase extends \Codeception\Test\Unit +{ + private Factory $factory; + + public function setUp(): void + { + $this->factory = $this->make(Factory::class, [ + 'open' => $this->make(Template::class), + ]); + } + + public function tearDown(): void + { + unset($this->factory); + } + + public function testShouldHaveNoAttributes() + { + $template = $this->factory->open(''); + $this->assertCount(0, $template->get_attributes()); + } + + public function testShouldNotBeEmptyAfterSettingAnAttribute() + { + $template = $this->factory->open(''); + $template->set_attribute('foo', 'bar'); + $this->assertNotEmpty($template->get_attributes()); + } + + public function testShouldBeEmptyAfterClear() + { + $template = $this->factory->open('foo'); + + $this->assertEmpty($template->get_attributes()); + + $template->clear_attributes(); + $this->assertEmpty($template->get_attributes()); + } +} diff --git a/tests/unit/lib/flexi/TemplateMagicMethodsTest.php b/tests/unit/lib/flexi/TemplateMagicMethodsTest.php new file mode 100644 index 0000000..ad2690a --- /dev/null +++ b/tests/unit/lib/flexi/TemplateMagicMethodsTest.php @@ -0,0 +1,78 @@ +<?php + +use Flexi\Factory; +use Flexi\Template; + +final class TemplateMagicMethodsTestCase extends \Codeception\Test\Unit +{ + private Factory $factory; + + public function setUp(): void + { + $this->factory = $this->make(Factory::class, [ + 'open' => $this->make(Template::class), + ]); + $this->template = $this->factory->open(''); + } + + public function tearDown(): void + { + unset($this->factory); + unset($this->template); + } + + public function testShouldSetAnAttributeUsingTheMagicMethods() + { + $this->template->foo = 'bar'; + $this->assertEquals('bar', $this->template->get_attribute('foo')); + } + + public function testShouldNotSetAProtectedMemberFieldAsAnAttribute() + { + $this->template->layout = 'bar'; + $this->assertEquals('bar', $this->template->layout); + $this->assertNotEquals('bar', $this->template->get_layout()); + } + + public function testShouldOverwriteAnAttribute() + { + $this->template->set_attribute('foo', 'bar'); + $this->template->foo = 'baz'; + $this->assertEquals('baz', $this->template->get_attribute('foo')); + } + + public function testShouldReturnAnExistingAttributeUsingTheMagicMethods() + { + $this->template->set_attribute('foo', 'bar'); + $this->assertEquals('bar', $this->template->foo); + } + + public function testShouldReturnNullForANonExistingAttributeUsingTheMagicMethods() + { + $this->assertNull($this->template->foo); + } + + public function testShouldUnsetAnAttributeUsingTheMagicMethods() + { + $this->template->foo = 'bar'; + unset($this->template->foo); + $this->assertNull($this->template->foo); + } + + public function testShouldReturnNullOnUnsettingANonAttribute() + { + unset($this->template->foo); + $this->assertNull($this->template->foo); + } + + public function testShouldReturnTrueOnIssetForAnAttribute() + { + $this->template->foo = 'bar'; + $this->assertTrue(isset($this->template->foo)); + } + + public function testShouldReturnFalseOnIssetForANonExistingAttribute() + { + $this->assertFalse(isset($this->template->foo)); + } +} diff --git a/tests/unit/lib/flexi/TemplateTest.php b/tests/unit/lib/flexi/TemplateTest.php new file mode 100644 index 0000000..95e9145 --- /dev/null +++ b/tests/unit/lib/flexi/TemplateTest.php @@ -0,0 +1,68 @@ +<?php + +use Flexi\Factory; +use Flexi\Template; + +final class TemplateTestCase extends \Codeception\Test\Unit +{ + private Factory $factory; + + public function setUp(): void + { + $this->factory = $this->make(Factory::class, [ + 'open' => $this->make(Template::class), + ]); + } + + public function tearDown(): void + { + unset($this->factory); + } + + public function testShouldReturnAPreviouslySetAttribute() + { + $template = $this->factory->open('foo'); + $template->set_attribute('whom', 'bar'); + $this->assertEquals('bar', $template->get_attribute('whom')); + } + + public function testShouldReturnPreviouslySetAttributes() + { + $template = $this->factory->open('foo'); + $template->set_attributes(['whom' => 'bar', 'foo' => 'baz']); + + $attributes = $template->get_attributes(); + $this->assertIsArray($attributes); + $this->assertCount(2, $attributes); + $this->assertEquals('bar', $attributes['whom']); + $this->assertEquals('baz', $attributes['foo']); + } + + public function testShouldMergeAttributesWithSetAttributes() + { + $template = $this->factory->open('foo'); + $template->set_attributes(['a' => 1, 'b' => 2]); + + $this->assertCount(2, $template->get_attributes()); + $this->assertEquals(1, $template->get_attribute('a')); + $this->assertEquals(2, $template->get_attribute('b')); + + $template->set_attributes(['b' => 8, 'c' => 9]); + + $this->assertCount(3, $template->get_attributes()); + $this->assertEquals(1, $template->get_attribute('a')); + $this->assertEquals(8, $template->get_attribute('b')); + $this->assertEquals(9, $template->get_attribute('c')); + } + + public function testShouldBeEmptyAfterClear() + { + $template = $this->factory->open('foo'); + + $template->set_attributes(['a' => 1, 'b' => 2]); + $this->assertNotEmpty($template->get_attributes()); + + $template->clear_attributes(); + $this->assertCount(0, $template->get_attributes()); + } +} |
