From 69e8b49b15620858b1af7ad7820de35581d2b8b6 Mon Sep 17 00:00:00 2001 From: Hannes Papenberg Date: Wed, 16 Jul 2025 13:09:56 +0200 Subject: [PATCH 01/17] Initial update to phpunit 12 --- Tests/AbstractApplicationTest.php | 39 +--- Tests/AbstractWebApplicationTest.php | 171 +++++++++--------- Tests/SessionAwareWebApplicationTraitTest.php | 24 +-- Tests/Stubs/TestAbstractApplicationObject.php | 19 ++ .../TestAbstractWebApplicationObject.php | 19 ++ ...tSessionAwareWebApplicationTraitObject.php | 21 +++ Tests/Web/WebClientTest.php | 22 +-- composer.json | 2 +- src/AbstractWebApplication.php | 4 +- 9 files changed, 174 insertions(+), 147 deletions(-) create mode 100644 Tests/Stubs/TestAbstractApplicationObject.php create mode 100644 Tests/Stubs/TestAbstractWebApplicationObject.php create mode 100644 Tests/Stubs/TestSessionAwareWebApplicationTraitObject.php diff --git a/Tests/AbstractApplicationTest.php b/Tests/AbstractApplicationTest.php index 79392610..ea4f5f80 100644 --- a/Tests/AbstractApplicationTest.php +++ b/Tests/AbstractApplicationTest.php @@ -7,7 +7,7 @@ namespace Joomla\Application\Tests; -use Joomla\Application\AbstractApplication; +use Joomla\Application\Tests\Stubs\TestAbstractApplicationObject; use Joomla\Event\DispatcherInterface; use Joomla\Registry\Registry; use Joomla\Test\TestHelper; @@ -32,7 +32,7 @@ public function testConstructDefaultBehaviour() $startTime = \time(); $startMicrotime = \microtime(true); - $object = $this->getMockForAbstractClass(AbstractApplication::class); + $object = new TestAbstractApplicationObject(); $this->assertInstanceOf( Registry::class, @@ -56,7 +56,7 @@ public function testConstructDefaultBehaviour() public function testConstructDependencyInjection() { $mockConfig = $this->createMock(Registry::class); - $object = $this->getMockForAbstractClass(AbstractApplication::class, [$mockConfig]); + $object = new TestAbstractApplicationObject($mockConfig); $this->assertSame( $mockConfig, @@ -65,25 +65,6 @@ public function testConstructDependencyInjection() ); } - /** - * @testdox Tests that \close() exits the application with the given code - * - * @covers Joomla\Application\AbstractApplication - */ - public function testClose() - { - $object = $this->getMockBuilder(AbstractApplication::class) - ->onlyMethods(['close']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - - $object->expects($this->any()) - ->method('close') - ->willReturnArgument(0); - - $this->assertSame(3, $object->close(3)); - } - /** * @testdox Tests that the application is executed successfully. * @@ -91,7 +72,7 @@ public function testClose() */ public function testExecute() { - $object = $this->getMockForAbstractClass(AbstractApplication::class); + $object = $this->createMock(TestAbstractApplicationObject::class); $object->expects($this->once()) ->method('doExecute'); @@ -110,7 +91,7 @@ public function testExecuteWithEvents() $dispatcher->expects($this->exactly(2)) ->method('dispatch'); - $object = $this->getMockForAbstractClass(AbstractApplication::class); + $object = $this->createMock(TestAbstractApplicationObject::class); $object->expects($this->once()) ->method('doExecute'); @@ -131,7 +112,7 @@ public function testGet() ->enableProxyingToOriginalMethods() ->getMock(); - $object = $this->getMockForAbstractClass(AbstractApplication::class, [$mockConfig]); + $object = new TestAbstractApplicationObject($mockConfig); $this->assertSame('bar', $object->get('foo', 'car'), 'Checks a known configuration setting is returned.'); $this->assertSame('car', $object->get('goo', 'car'), 'Checks an unknown configuration setting returns the default.'); @@ -144,7 +125,7 @@ public function testGet() */ public function testGetLogger() { - $object = $this->getMockForAbstractClass(AbstractApplication::class); + $object = new TestAbstractApplicationObject(); $this->assertInstanceOf(NullLogger::class, $object->getLogger()); } @@ -160,7 +141,7 @@ public function testSet() ->enableProxyingToOriginalMethods() ->getMock(); - $object = $this->getMockForAbstractClass(AbstractApplication::class, [$mockConfig]); + $object = new TestAbstractApplicationObject($mockConfig); $this->assertNull($object->set('foo', 'car'), 'Checks set returns the previous value.'); $this->assertEquals('car', $object->get('foo'), 'Checks the new value has been set.'); @@ -173,7 +154,7 @@ public function testSet() */ public function testSetConfiguration() { - $object = $this->getMockForAbstractClass(AbstractApplication::class); + $object = new TestAbstractApplicationObject(); $mockConfig = $this->createMock(Registry::class); $this->assertSame($object, $object->setConfiguration($mockConfig), 'The setConfiguration method has a fluent interface'); @@ -192,7 +173,7 @@ public function testSetConfiguration() */ public function testSetLogger() { - $object = $this->getMockForAbstractClass(AbstractApplication::class); + $object = new TestAbstractApplicationObject(); $mockLogger = $this->createMock(LoggerInterface::class); $object->setLogger($mockLogger); diff --git a/Tests/AbstractWebApplicationTest.php b/Tests/AbstractWebApplicationTest.php index 36908989..2a6792e2 100644 --- a/Tests/AbstractWebApplicationTest.php +++ b/Tests/AbstractWebApplicationTest.php @@ -8,12 +8,14 @@ namespace Joomla\Application\Tests; use Joomla\Application\AbstractWebApplication; +use Joomla\Application\Tests\Stubs\TestAbstractWebApplicationObject; use Joomla\Application\Web\WebClient; use Joomla\Event\DispatcherInterface; use Joomla\Input\Input; use Joomla\Registry\Registry; use Joomla\Test\TestHelper; use Laminas\Diactoros\Response\TextResponse; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; /** @@ -63,49 +65,51 @@ protected function tearDown(): void /** * Data for detectRequestUri method. * - * @return \Generator + * @return array */ - public static function getDetectRequestUriData(): \Generator + public static function getDetectRequestUriData(): array { - // HTTPS, PHP_SELF, REQUEST_URI, HTTP_HOST, SCRIPT_NAME, QUERY_STRING, (resulting uri) - yield 'HTTP connection with path in PHP_SELF and query string set in REQUEST_URI' => [ - null, - '/j/index.php', - '/j/index.php?foo=bar', - 'joom.la:3', - '/j/index.php', - '', - 'http://joom.la:3/j/index.php?foo=bar', - ]; + return [ + // HTTPS, PHP_SELF, REQUEST_URI, HTTP_HOST, SCRIPT_NAME, QUERY_STRING, (resulting uri) + 'HTTP connection with path in PHP_SELF and query string set in REQUEST_URI' => [ + null, + '/j/index.php', + '/j/index.php?foo=bar', + 'joom.la:3', + '/j/index.php', + '', + 'http://joom.la:3/j/index.php?foo=bar', + ], - yield 'HTTPS connection with path in PHP_SELF and query string set in REQUEST_URI' => [ - 'on', - '/j/index.php', - '/j/index.php?foo=bar', - 'joom.la:3', - '/j/index.php', - '', - 'https://joom.la:3/j/index.php?foo=bar', - ]; + 'HTTPS connection with path in PHP_SELF and query string set in REQUEST_URI' => [ + 'on', + '/j/index.php', + '/j/index.php?foo=bar', + 'joom.la:3', + '/j/index.php', + '', + 'https://joom.la:3/j/index.php?foo=bar', + ], - yield 'HTTP connection with path in SCRIPT_NAME and no query string' => [ - null, - '', - '', - 'joom.la:3', - '/j/index.php', - '', - 'http://joom.la:3/j/index.php', - ]; + 'HTTP connection with path in SCRIPT_NAME and no query string' => [ + null, + '', + '', + 'joom.la:3', + '/j/index.php', + '', + 'http://joom.la:3/j/index.php', + ], - yield 'HTTP connection with path in SCRIPT_NAME and query string set in QUERY_STRING' => [ - null, - '', - '', - 'joom.la:3', - '/j/index.php', - 'foo=bar', - 'http://joom.la:3/j/index.php?foo=bar', + 'HTTP connection with path in SCRIPT_NAME and query string set in QUERY_STRING' => [ + null, + '', + '', + 'joom.la:3', + '/j/index.php', + 'foo=bar', + 'http://joom.la:3/j/index.php?foo=bar', + ], ]; } @@ -146,7 +150,7 @@ public static function mockHeader($string, $replace = true, $code = null) */ public function testConstructDefaultBehaviour() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = new TestAbstractWebApplicationObject(); // Validate default objects unique to the web application are created $this->assertInstanceOf(WebClient::class, $object->client); @@ -168,13 +172,11 @@ public function testConstructDependencyInjection() $mockInput = new Input([]); - $mockConfig = $this->getMockBuilder(Registry::class) - ->enableProxyingToOriginalMethods() - ->getMock(); + $mockConfig = $this->createMock(Registry::class); $mockClient = $this->createMock(WebClient::class); - $object = $this->getMockForAbstractClass(AbstractWebApplication::class, [$mockInput, $mockConfig, $mockClient]); + $object = new TestAbstractWebApplicationObject($mockInput, $mockConfig, $mockClient); $this->assertSame($mockInput, $object->getInput()); @@ -198,7 +200,7 @@ public function testConstructDependencyInjection() */ public function testGetDeprecatedInputReadAccess() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = $this->createMock(TestAbstractWebApplicationObject::class); // Validate default objects unique to the web application are created $this->assertInstanceOf(Input::class, $object->getInput()); @@ -213,7 +215,7 @@ public function testGetDeprecatedInputReadAccess() */ public function testExecute() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = $this->createMock(TestAbstractWebApplicationObject::class); $object->expects($this->once()) ->method('doExecute'); @@ -248,7 +250,7 @@ public function testExecuteWithEvents() $dispatcher->expects($this->exactly(4)) ->method('dispatch'); - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = $this->createMock(TestAbstractWebApplicationObject::class); $object->expects($this->once()) ->method('doExecute'); @@ -285,12 +287,9 @@ public function testExecuteWithCompression() $this->markTestSkipped('Output compression is unsupported in this environment.'); } - $mockConfig = $this->getMockBuilder(Registry::class) - ->setConstructorArgs([['gzip' => true]]) - ->enableProxyingToOriginalMethods() - ->getMock(); + $mockConfig = new Registry(['gzip' => true]); - $object = $this->getMockForAbstractClass(AbstractWebApplication::class, [null, $mockConfig]); + $object = $this->createMock(TestAbstractWebApplicationObject::class, [null, $mockConfig]); $object->expects($this->once()) ->method('doExecute'); @@ -322,7 +321,7 @@ public function testCompressWithGzipEncoding() { $mockClient = $this->getMockBuilder(WebClient::class) ->setConstructorArgs([null, 'gzip, deflate']) - ->enableProxyingToOriginalMethods() + ->getMock(); // Mock the client internals to show encoding has been detected. @@ -392,7 +391,7 @@ public function testCompressWithDeflateEncoding() { $mockClient = $this->getMockBuilder(WebClient::class) ->setConstructorArgs([null, 'deflate']) - ->enableProxyingToOriginalMethods() + ->getMock(); // Mock the client internals to show encoding has been detected. @@ -437,7 +436,7 @@ public function testCompressWithDeflateEncoding() // Ensure that the compressed body is shorter than the raw body. $this->assertLessThan( - \strlen($response->getBody()), + \strlen($response->getBody()->getContents()), \strlen($object->getBody()) ); @@ -461,7 +460,7 @@ public function testCompressWithDeflateEncoding() public function testCompressWithNoAcceptEncodings() { $mockClient = $this->getMockBuilder(WebClient::class) - ->enableProxyingToOriginalMethods() + ->getMock(); // Mock the client internals to show encoding has been detected. @@ -516,7 +515,7 @@ public function testCompressWithHeadersSent() { $mockClient = $this->getMockBuilder(WebClient::class) ->setConstructorArgs([null, 'deflate']) - ->enableProxyingToOriginalMethods() + ->getMock(); // Mock the client internals to show encoding has been detected. @@ -580,7 +579,7 @@ public function testCompressWithHeadersSent() public function testCompressWithUnsupportedEncodings() { $mockClient = $this->getMockBuilder(WebClient::class) - ->enableProxyingToOriginalMethods() + ->getMock(); // Mock the client internals to show encoding has been detected. @@ -635,7 +634,7 @@ public function testCompressWithUnsupportedEncodings() */ public function testRespond() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = $this->createMock(TestAbstractWebApplicationObject::class); TestHelper::invoke($object, 'respond'); @@ -665,7 +664,7 @@ public function testRespondWithAllowedCaching() { $modifiedDate = new \DateTime('now', new \DateTimeZone('GMT')); - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = $this->createMock(TestAbstractWebApplicationObject::class); $object->allowCache(true); $object->modifiedDate = $modifiedDate; @@ -704,7 +703,7 @@ public function testRedirectLegacyBehavior() $mockInput = new Input([]); $mockConfig = $this->getMockBuilder(Registry::class) - ->enableProxyingToOriginalMethods() + ->getMock(); $mockClient = $this->createMock(WebClient::class); @@ -779,7 +778,7 @@ public function testRedirect() $mockInput = new Input([]); $mockConfig = $this->getMockBuilder(Registry::class) - ->enableProxyingToOriginalMethods() + ->getMock(); $mockClient = $this->getMockBuilder(WebClient::class)->getMock(); @@ -853,7 +852,7 @@ public function testRedirectWithExistingStatusCode() $mockInput = new Input([]); $mockConfig = $this->getMockBuilder(Registry::class) - ->enableProxyingToOriginalMethods() + ->getMock(); $mockClient = $this->getMockBuilder(WebClient::class)->getMock(); @@ -929,7 +928,7 @@ public function testRedirectWithAdditionalHeaders() $mockInput = new Input([]); $mockConfig = $this->getMockBuilder(Registry::class) - ->enableProxyingToOriginalMethods() + ->getMock(); $mockClient = $this->getMockBuilder(WebClient::class)->getMock(); @@ -1006,7 +1005,7 @@ public function testRedirectWithHeadersSent() $mockInput = new Input([]); $mockConfig = $this->getMockBuilder(Registry::class) - ->enableProxyingToOriginalMethods() + ->getMock(); $object = $this->getMockForAbstractClass( @@ -1059,12 +1058,12 @@ public function testRedirectWithJavascriptRedirect() $mockInput = new Input([]); $mockConfig = $this->getMockBuilder(Registry::class) - ->enableProxyingToOriginalMethods() + ->getMock(); $mockClient = $this->getMockBuilder(WebClient::class) ->setConstructorArgs(['MSIE']) - ->enableProxyingToOriginalMethods() + ->getMock(); // Mock the client internals to show engine has been detected. @@ -1127,7 +1126,7 @@ public function testRedirectWithMoved() $mockInput = new Input([]); $mockConfig = $this->getMockBuilder(Registry::class) - ->enableProxyingToOriginalMethods() + ->getMock(); $mockClient = $this->getMockBuilder(WebClient::class)->getMock(); @@ -1206,7 +1205,7 @@ public function testRedirectWithUrl(string $url, string $expected) $mockInput = new Input([]); $mockConfig = $this->getMockBuilder(Registry::class) - ->enableProxyingToOriginalMethods() + ->getMock(); $mockClient = $this->getMockBuilder(WebClient::class)->getMock(); @@ -1259,7 +1258,7 @@ public function testRedirectWithUrl(string $url, string $expected) */ public function testAllowCache() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = new TestAbstractWebApplicationObject(); $this->assertFalse($object->allowCache()); $this->assertTrue($object->allowCache(true)); @@ -1274,7 +1273,7 @@ public function testAllowCache() */ public function testSetHeader() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = new TestAbstractWebApplicationObject(); $object->setHeader('foo', 'bar'); @@ -1305,7 +1304,7 @@ public function testSetHeader() */ public function testClearHeaders() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = new TestAbstractWebApplicationObject(); $object->setHeader('foo', 'bar'); $oldHeaders = $object->getHeaders(); @@ -1322,8 +1321,8 @@ public function testClearHeaders() */ public function testSendHeaders() { - $object = $this->getMockForAbstractClass( - AbstractWebApplication::class, + $object = $this->createMock( + TestAbstractWebApplicationObject::class, [], '', true, @@ -1361,7 +1360,7 @@ public function testSendHeaders() */ public function testSetBody() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = new TestAbstractWebApplicationObject(); $this->assertSame($object, $object->setBody('Testing')); $this->assertSame('Testing', $object->getBody()); @@ -1376,7 +1375,7 @@ public function testSetBody() */ public function testPrependBody() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = new TestAbstractWebApplicationObject(); $object->setBody('Testing'); $this->assertSame($object, $object->prependBody('Pre-')); @@ -1392,7 +1391,7 @@ public function testPrependBody() */ public function testAppendBody() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = new TestAbstractWebApplicationObject(); $object->setBody('Testing'); $this->assertSame($object, $object->appendBody(' Later')); @@ -1408,7 +1407,7 @@ public function testAppendBody() */ public function testGetBody() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = new TestAbstractWebApplicationObject(); $this->assertSame('', $object->getBody(), 'Returns an empty string by default'); } @@ -1428,9 +1427,9 @@ public function testGetBody() * @uses \Joomla\Application\AbstractApplication * @uses \Joomla\Application\Web\WebClient * - * @dataProvider getDetectRequestUriData * @backupGlobals enabled */ + #[DataProvider('getDetectRequestUriData')] public function testDetectRequestUri( ?string $https, string $phpSelf, @@ -1452,7 +1451,7 @@ public function testDetectRequestUri( $_SERVER['HTTPS'] = $https; } - $object = $this->getMockForAbstractClass(AbstractWebApplication::class, [$mockInput]); + $object = new TestAbstractWebApplicationObject($mockInput); $this->assertSame( $expects, @@ -1471,7 +1470,7 @@ public function testLoadSystemUrisWithSiteUriSet() { $mockConfig = $this->getMockBuilder(Registry::class) ->setConstructorArgs([['site_uri' => 'http://test.joomla.org/path/']]) - ->enableProxyingToOriginalMethods() + ->getMock(); $object = $this->getMockForAbstractClass(AbstractWebApplication::class, [null, $mockConfig]); @@ -1520,7 +1519,7 @@ public function testLoadSystemUrisWithoutSiteUriSet() $mockInput = new Input([]); - $object = $this->getMockForAbstractClass(AbstractWebApplication::class, [$mockInput]); + $object = new TestAbstractWebApplicationObject($mockInput); TestHelper::invoke($object, 'loadSystemUris', 'http://joom.la/application'); @@ -1569,7 +1568,7 @@ public function testLoadSystemUrisWithoutSiteUriWithMediaUriSet() $mockConfig = $this->getMockBuilder(Registry::class) ->setConstructorArgs([['media_uri' => 'http://cdn.joomla.org/media/']]) - ->enableProxyingToOriginalMethods() + ->getMock(); $object = $this->getMockForAbstractClass(AbstractWebApplication::class, [$mockInput, $mockConfig]); @@ -1621,7 +1620,7 @@ public function testLoadSystemUrisWithoutSiteUriWithRelativeMediaUriSet() $mockConfig = $this->getMockBuilder(Registry::class) ->setConstructorArgs([['media_uri' => '/media/']]) - ->enableProxyingToOriginalMethods() + ->getMock(); $object = $this->getMockForAbstractClass(AbstractWebApplication::class, [$mockInput, $mockConfig]); @@ -1665,7 +1664,7 @@ public function testLoadSystemUrisWithoutSiteUriWithRelativeMediaUriSet() */ public function testisSslConnection() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = new TestAbstractWebApplicationObject(); $this->assertFalse($object->isSslConnection()); @@ -1683,7 +1682,7 @@ public function testisSslConnection() */ public function testGetHttpStatusValue() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = new TestAbstractWebApplicationObject(); $this->assertTrue($object->isValidHttpStatus(500)); } @@ -1697,7 +1696,7 @@ public function testGetHttpStatusValue() */ public function testInvalidHttpStatusValue() { - $object = $this->getMockForAbstractClass(AbstractWebApplication::class); + $object = new TestAbstractWebApplicationObject(); $this->assertFalse($object->isValidHttpStatus(460)); } diff --git a/Tests/SessionAwareWebApplicationTraitTest.php b/Tests/SessionAwareWebApplicationTraitTest.php index bbf1b3d2..73628d01 100644 --- a/Tests/SessionAwareWebApplicationTraitTest.php +++ b/Tests/SessionAwareWebApplicationTraitTest.php @@ -7,7 +7,7 @@ namespace Joomla\Application\Tests; -use Joomla\Application\SessionAwareWebApplicationTrait; +use Joomla\Application\Tests\Stubs\TestSessionAwareWebApplicationTraitObject; use Joomla\Input\Input; use Joomla\Session\SessionInterface; use PHPUnit\Framework\TestCase; @@ -24,7 +24,7 @@ class SessionAwareWebApplicationTraitTest extends TestCase */ public function testSetSession() { - $object = $this->getMockForTrait(SessionAwareWebApplicationTrait::class); + $object = new TestSessionAwareWebApplicationTraitObject(); $mockSession = $this->createMock(SessionInterface::class); $this->assertSame($object, $object->setSession($mockSession), 'The setSession method has a fluent interface.'); @@ -40,7 +40,7 @@ public function testGetSessionForAnException() { $this->expectException(\RuntimeException::class); - $object = $this->getMockForTrait(SessionAwareWebApplicationTrait::class); + $object = new TestSessionAwareWebApplicationTraitObject(); $object->getSession(); } @@ -71,13 +71,9 @@ public function testCheckTokenForHttpHeader() ->with('testing') ->willReturn(true); - $object = $this->getMockForTrait(SessionAwareWebApplicationTrait::class); + $object = new TestSessionAwareWebApplicationTraitObject(); $object->setSession($mockSession); - $object->expects($this->any()) - ->method('getInput') - ->willReturn($mockInput); - $this->assertTrue($object->checkToken()); } @@ -108,13 +104,9 @@ public function testCheckTokenForRequestBody() ->with('testing') ->willReturn(true); - $object = $this->getMockForTrait(SessionAwareWebApplicationTrait::class); + $object = new TestSessionAwareWebApplicationTraitObject(); $object->setSession($mockSession); - $object->expects($this->any()) - ->method('getInput') - ->willReturn($mockInput); - $this->assertTrue($object->checkToken()); } @@ -141,13 +133,9 @@ public function testCheckTokenFailsWhenNotPresent() $mockSession->expects($this->never()) ->method('hasToken'); - $object = $this->getMockForTrait(SessionAwareWebApplicationTrait::class); + $object = new TestSessionAwareWebApplicationTraitObject(); $object->setSession($mockSession); - $object->expects($this->any()) - ->method('getInput') - ->willReturn($mockInput); - $this->assertFalse($object->checkToken()); } } diff --git a/Tests/Stubs/TestAbstractApplicationObject.php b/Tests/Stubs/TestAbstractApplicationObject.php new file mode 100644 index 00000000..47a353ce --- /dev/null +++ b/Tests/Stubs/TestAbstractApplicationObject.php @@ -0,0 +1,19 @@ + + * @license GNU General Public License version 2 or later; see LICENSE + */ + +namespace Joomla\Application\Tests\Stubs; + +use Joomla\Application\AbstractApplication; + +class TestAbstractApplicationObject extends AbstractApplication +{ + + protected function doExecute() + { + // TODO: Implement doExecute() method. + } +} diff --git a/Tests/Stubs/TestAbstractWebApplicationObject.php b/Tests/Stubs/TestAbstractWebApplicationObject.php new file mode 100644 index 00000000..c0ea4a3d --- /dev/null +++ b/Tests/Stubs/TestAbstractWebApplicationObject.php @@ -0,0 +1,19 @@ + + * @license GNU General Public License version 2 or later; see LICENSE + */ + +namespace Joomla\Application\Tests\Stubs; + +use Joomla\Application\AbstractWebApplication; + +class TestAbstractWebApplicationObject extends AbstractWebApplication +{ + + protected function doExecute() + { + // TODO: Implement doExecute() method. + } +} diff --git a/Tests/Stubs/TestSessionAwareWebApplicationTraitObject.php b/Tests/Stubs/TestSessionAwareWebApplicationTraitObject.php new file mode 100644 index 00000000..6ba0cb02 --- /dev/null +++ b/Tests/Stubs/TestSessionAwareWebApplicationTraitObject.php @@ -0,0 +1,21 @@ + + * @license GNU General Public License version 2 or later; see LICENSE + */ + +namespace Joomla\Application\Tests\Stubs; + +use Joomla\Application\SessionAwareWebApplicationTrait; +use Joomla\Input\Input; + +class TestSessionAwareWebApplicationTraitObject +{ + use SessionAwareWebApplicationTrait; + + public function getInput(): Input + { + return new Input([]); + } +} diff --git a/Tests/Web/WebClientTest.php b/Tests/Web/WebClientTest.php index 832c630a..0b816a42 100644 --- a/Tests/Web/WebClientTest.php +++ b/Tests/Web/WebClientTest.php @@ -8,6 +8,7 @@ namespace Joomla\Application\Tests\Web; use Joomla\Application\Web\WebClient; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; /** @@ -26,7 +27,7 @@ class WebClientTest extends TestCase * * @since 1.0.0 */ - public static function getUserAgentData() + public static function getUserAgentData(): array { // Platform, Mobile, Engine, Browser, Version, User Agent return [ @@ -408,7 +409,7 @@ public static function getUserAgentData() * * @since 1.0.0 */ - public static function getEncodingData() + public static function getEncodingData(): array { // HTTP_ACCEPT_ENCODING, Supported Encodings return [ @@ -429,7 +430,7 @@ public static function getEncodingData() * * @since 1.0.0 */ - public static function getLanguageData() + public static function getLanguageData(): array { // HTTP_ACCEPT_LANGUAGE, Supported Language return [ @@ -450,7 +451,7 @@ public static function getLanguageData() * * @since 1.0.0 */ - public static function detectRobotData() + public static function detectRobotData(): array { return [ ['Googlebot/2.1 (+http://www.google.com/bot.html)', true], @@ -512,10 +513,10 @@ public function setUp(): void * * @return void * - * @dataProvider getUserAgentData * @since 1.0.0 * @covers \Joomla\Application\Web\WebClient */ + #[DataProvider('getUserAgentData')] public function testDetectBrowser($p, $m, $e, $b, $v, $ua) { $client = new WebClient($ua); @@ -553,10 +554,10 @@ public function testDetectHeaders() * * @return void * - * @dataProvider getEncodingData * @since 1.0.0 * @covers \Joomla\Application\Web\WebClient */ + #[DataProvider('getEncodingData')] public function testDetectEncoding($ae, $e) { $client = new WebClient(null, $ae); @@ -577,10 +578,10 @@ public function testDetectEncoding($ae, $e) * * @return void * - * @dataProvider getUserAgentData * @since 1.0.0 * @covers \Joomla\Application\Web\WebClient */ + #[DataProvider('getUserAgentData')] public function testDetectEngine($p, $m, $e, $b, $v, $ua) { $client = new WebClient($ua); @@ -597,10 +598,10 @@ public function testDetectEngine($p, $m, $e, $b, $v, $ua) * * @return void * - * @dataProvider getLanguageData * @since 1.0.0 * @covers \Joomla\Application\Web\WebClient */ + #[DataProvider('getLanguageData')] public function testDetectLanguage($al, $l) { $client = new WebClient(null, null, $al); @@ -620,11 +621,10 @@ public function testDetectLanguage($al, $l) * @param string $ua The input user agent. * * @return void - * - * @dataProvider getUserAgentData * @since 1.0.0 * @covers \Joomla\Application\Web\WebClient */ + #[DataProvider('getUserAgentData')] public function testDetectPlatform($p, $m, $e, $b, $v, $ua) { $client = new WebClient($ua); @@ -642,10 +642,10 @@ public function testDetectPlatform($p, $m, $e, $b, $v, $ua) * * @return void * - * @dataProvider detectRobotData * @since 1.0.0 * @covers \Joomla\Application\Web\WebClient */ + #[DataProvider('detectRobotData')] public function testDetectRobot($userAgent, $expected) { $client = new WebClient($userAgent); diff --git a/composer.json b/composer.json index 1e97cdaa..6e9eb20d 100644 --- a/composer.json +++ b/composer.json @@ -52,7 +52,7 @@ "joomla/session": "dev-4.x-dev", "joomla/test": "dev-4.x-dev", "joomla/uri": "dev-4.x-dev", - "phpunit/phpunit": "^10.0", + "phpunit/phpunit": "^12.2.7", "symfony/phpunit-bridge": "^7.0", "squizlabs/php_codesniffer": "~3.10.2", "phpstan/phpstan": "^2.1.17", diff --git a/src/AbstractWebApplication.php b/src/AbstractWebApplication.php index a4eeedcd..3ec49466 100644 --- a/src/AbstractWebApplication.php +++ b/src/AbstractWebApplication.php @@ -611,7 +611,7 @@ public function prependBody($content) } $stream = new Stream('php://memory', 'rw'); - $stream->write((string) $content . (string) $currentBody); + $stream->write((string) $content . $currentBody->getContents()); $this->setResponse($this->getResponse()->withBody($stream)); return $this; @@ -653,7 +653,7 @@ public function appendBody($content) */ public function getBody() { - return (string) $this->getResponse()->getBody(); + return $this->getResponse()->getBody()->getContents(); } /** From 75bd7af4435b4763c9c628c3eb0b2574226b8973 Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 14:45:30 +0200 Subject: [PATCH 02/17] Revert AbstractWebApplication.php --- src/AbstractWebApplication.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AbstractWebApplication.php b/src/AbstractWebApplication.php index 3ec49466..a4eeedcd 100644 --- a/src/AbstractWebApplication.php +++ b/src/AbstractWebApplication.php @@ -611,7 +611,7 @@ public function prependBody($content) } $stream = new Stream('php://memory', 'rw'); - $stream->write((string) $content . $currentBody->getContents()); + $stream->write((string) $content . (string) $currentBody); $this->setResponse($this->getResponse()->withBody($stream)); return $this; @@ -653,7 +653,7 @@ public function appendBody($content) */ public function getBody() { - return $this->getResponse()->getBody()->getContents(); + return (string) $this->getResponse()->getBody(); } /** From 8f52d6b0f0df3141e4b735c1bac8faf0eb063d0f Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 14:59:05 +0200 Subject: [PATCH 03/17] convert metadata doc-comment to attribute --- Tests/AbstractApplicationTest.php | 66 +--- Tests/AbstractWebApplicationTest.php | 357 ++++-------------- .../ContainerControllerResolverTest.php | 20 +- Tests/Controller/ControllerResolverTest.php | 45 +-- Tests/SessionAwareWebApplicationTraitTest.php | 65 ++-- Tests/Web/WebClientTest.php | 14 +- Tests/WebApplicationTest.php | 20 +- 7 files changed, 139 insertions(+), 448 deletions(-) diff --git a/Tests/AbstractApplicationTest.php b/Tests/AbstractApplicationTest.php index ea4f5f80..2ed01099 100644 --- a/Tests/AbstractApplicationTest.php +++ b/Tests/AbstractApplicationTest.php @@ -8,9 +8,15 @@ namespace Joomla\Application\Tests; use Joomla\Application\Tests\Stubs\TestAbstractApplicationObject; +use Joomla\Application\AbstractApplication; +use Joomla\Application\Event\ApplicationEvent; +use Joomla\Application\Web\WebClient; use Joomla\Event\DispatcherInterface; use Joomla\Registry\Registry; use Joomla\Test\TestHelper; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\Attributes\UsesClass; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; @@ -18,15 +24,12 @@ /** * Test class for Joomla\Application\AbstractApplication. */ +#[CoversClass(AbstractApplication::class)] +#[UsesClass(ApplicationEvent::class)] +#[UsesClass(WebClient::class)] class AbstractApplicationTest extends TestCase { - /** - * @testdox Tests the constructor creates default object instances - * - * @covers Joomla\Application\AbstractApplication - * @uses Joomla\Application\AbstractApplication - * @uses Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the constructor creates default object instances')] public function testConstructDefaultBehaviour() { $startTime = \time(); @@ -48,11 +51,7 @@ public function testConstructDefaultBehaviour() $this->assertGreaterThanOrEqual($startMicrotime, $object->get('execution.microtimestamp')); } - /** - * @testdox Tests the correct objects are stored when injected - * - * @covers Joomla\Application\AbstractApplication - */ + #[TestDox('Tests the correct objects are stored when injected')] public function testConstructDependencyInjection() { $mockConfig = $this->createMock(Registry::class); @@ -65,11 +64,7 @@ public function testConstructDependencyInjection() ); } - /** - * @testdox Tests that the application is executed successfully. - * - * @covers Joomla\Application\AbstractApplication - */ + #[TestDox('Tests that the application is executed successfully.')] public function testExecute() { $object = $this->createMock(TestAbstractApplicationObject::class); @@ -79,12 +74,7 @@ public function testExecute() $object->execute(); } - /** - * @testdox Tests that the application is executed successfully when an event dispatcher is registered. - * - * @covers Joomla\Application\AbstractApplication - * @uses Joomla\Application\Event\ApplicationEvent - */ + #[TestDox('Tests that the application is executed successfully when an event dispatcher is registered.')] public function testExecuteWithEvents() { $dispatcher = $this->createMock(DispatcherInterface::class); @@ -100,11 +90,7 @@ public function testExecuteWithEvents() $object->execute(); } - /** - * @testdox Tests that data is read from the application configuration successfully. - * - * @covers Joomla\Application\AbstractApplication - */ + #[TestDox('Tests that data is read from the application configuration successfully.')] public function testGet() { $mockConfig = $this->getMockBuilder(Registry::class) @@ -118,11 +104,7 @@ public function testGet() $this->assertSame('car', $object->get('goo', 'car'), 'Checks an unknown configuration setting returns the default.'); } - /** - * @testdox Tests that a default LoggerInterface object is returned. - * - * @covers Joomla\Application\AbstractApplication - */ + #[TestDox('Tests that a default LoggerInterface object is returned.')] public function testGetLogger() { $object = new TestAbstractApplicationObject(); @@ -130,11 +112,7 @@ public function testGetLogger() $this->assertInstanceOf(NullLogger::class, $object->getLogger()); } - /** - * @testdox Tests that data is set to the application configuration successfully. - * - * @covers Joomla\Application\AbstractApplication - */ + #[TestDox('Tests that data is set to the application configuration successfully.')] public function testSet() { $mockConfig = $this->getMockBuilder(Registry::class) @@ -147,11 +125,7 @@ public function testSet() $this->assertEquals('car', $object->get('foo'), 'Checks the new value has been set.'); } - /** - * @testdox Tests that the application configuration is overwritten successfully. - * - * @covers Joomla\Application\AbstractApplication - */ + #[TestDox('Tests that the application configuration is overwritten successfully.')] public function testSetConfiguration() { $object = new TestAbstractApplicationObject(); @@ -166,11 +140,7 @@ public function testSetConfiguration() ); } - /** - * @testdox Tests that a LoggerInterface object is correctly set to the application. - * - * @covers Joomla\Application\AbstractApplication - */ + #[TestDox('Tests that a LoggerInterface object is correctly set to the application.')] public function testSetLogger() { $object = new TestAbstractApplicationObject(); diff --git a/Tests/AbstractWebApplicationTest.php b/Tests/AbstractWebApplicationTest.php index 2a6792e2..67532e99 100644 --- a/Tests/AbstractWebApplicationTest.php +++ b/Tests/AbstractWebApplicationTest.php @@ -7,7 +7,9 @@ namespace Joomla\Application\Tests; +use Joomla\Application\AbstractApplication; use Joomla\Application\AbstractWebApplication; +use Joomla\Application\Event\ApplicationEvent; use Joomla\Application\Tests\Stubs\TestAbstractWebApplicationObject; use Joomla\Application\Web\WebClient; use Joomla\Event\DispatcherInterface; @@ -15,12 +17,22 @@ use Joomla\Registry\Registry; use Joomla\Test\TestHelper; use Laminas\Diactoros\Response\TextResponse; +use PHPUnit\Framework\Attributes\BackupGlobals; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\PreserveGlobalState; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\Attributes\UsesClass; use PHPUnit\Framework\TestCase; /** * Test class for Joomla\Application\AbstractWebApplication. */ +#[CoversClass(AbstractWebApplication::class)] +#[UsesClass(AbstractApplication::class)] +#[UsesClass(ApplicationEvent::class)] +#[UsesClass(WebClient::class)] class AbstractWebApplicationTest extends TestCase { /** @@ -141,13 +153,7 @@ public static function mockHeader($string, $replace = true, $code = null) self::$headers[] = [$string, $replace, $code]; } - /** - * @testdox Tests the constructor creates default object instances - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the constructor creates default object instances')] public function testConstructDefaultBehaviour() { $object = new TestAbstractWebApplicationObject(); @@ -156,14 +162,8 @@ public function testConstructDefaultBehaviour() $this->assertInstanceOf(WebClient::class, $object->client); } - /** - * @testdox Tests the correct objects are stored when injected - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests the correct objects are stored when injected')] public function testConstructDependencyInjection() { $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; @@ -191,13 +191,7 @@ public function testConstructDependencyInjection() $this->assertEquals('http://' . self::TEST_HTTP_HOST, $object->get('uri.base.host')); } - /** - * @testdox Tests access to the input property is allowed - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests access to the input property is allowed')] public function testGetDeprecatedInputReadAccess() { $object = $this->createMock(TestAbstractWebApplicationObject::class); @@ -206,13 +200,7 @@ public function testGetDeprecatedInputReadAccess() $this->assertInstanceOf(Input::class, $object->getInput()); } - /** - * @testdox Tests that the application is executed successfully. - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests that the application is executed successfully.')] public function testExecute() { $object = $this->createMock(TestAbstractWebApplicationObject::class); @@ -236,14 +224,7 @@ public function testExecute() $this->assertEmpty($object->getBody()); } - /** - * @testdox Tests that the application is executed successfully when an event dispatcher is registered. - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Event\ApplicationEvent - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests that the application is executed successfully when an event dispatcher is registered.')] public function testExecuteWithEvents() { $dispatcher = $this->createMock(DispatcherInterface::class); @@ -273,13 +254,7 @@ public function testExecuteWithEvents() $this->assertEmpty($object->getBody()); } - /** - * @testdox Tests that the application with compression enabled is executed successfully. - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests that the application with compression enabled is executed successfully.')] public function testExecuteWithCompression() { // Verify compression is supported in this environment @@ -310,13 +285,7 @@ public function testExecuteWithCompression() $this->assertEmpty($object->getBody()); } - /** - * @testdox Tests the \compress() method correctly compresses data with gzip encoding - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the \compress() method correctly compresses data with gzip encoding')] public function testCompressWithGzipEncoding() { $mockClient = $this->getMockBuilder(WebClient::class) @@ -380,13 +349,7 @@ public function testCompressWithGzipEncoding() ); } - /** - * @testdox Tests the compress() method correctly compresses data with deflate encoding - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the compress() method correctly compresses data with deflate encoding')] public function testCompressWithDeflateEncoding() { $mockClient = $this->getMockBuilder(WebClient::class) @@ -450,13 +413,7 @@ public function testCompressWithDeflateEncoding() ); } - /** - * @testdox Tests the \compress() method does not compress data when no encoding methods are supported - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the \compress() method does not compress data when no encoding methods are supported')] public function testCompressWithNoAcceptEncodings() { $mockClient = $this->getMockBuilder(WebClient::class) @@ -504,13 +461,7 @@ public function testCompressWithNoAcceptEncodings() $this->assertEmpty($object->getHeaders()); } - /** - * @testdox Tests the \compress() method does not compress data when the response headers have already been sent - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the \compress() method does not compress data when the response headers have already been sent')] public function testCompressWithHeadersSent() { $mockClient = $this->getMockBuilder(WebClient::class) @@ -568,14 +519,7 @@ public function testCompressWithHeadersSent() $this->assertEmpty($object->getHeaders()); } - /** - * @testdox Tests the \compress() method does not compress data when the application does not support the client's - * encoding methods - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the \compress() method does not compress data when the application does not support the client\'s encoding methods')] public function testCompressWithUnsupportedEncodings() { $mockClient = $this->getMockBuilder(WebClient::class) @@ -625,13 +569,7 @@ public function testCompressWithUnsupportedEncodings() $this->assertEmpty($object->getHeaders()); } - /** - * @testdox Tests that the application sends the response successfully. - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests that the application sends the response successfully.')] public function testRespond() { $object = $this->createMock(TestAbstractWebApplicationObject::class); @@ -653,13 +591,7 @@ public function testRespond() $this->assertEmpty($object->getBody()); } - /** - * @testdox Tests that the application sends the response successfully with allowed caching. - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests that the application sends the response successfully with allowed caching.')] public function testRespondWithAllowedCaching() { $modifiedDate = new \DateTime('now', new \DateTimeZone('GMT')); @@ -685,15 +617,8 @@ public function testRespondWithAllowedCaching() $this->assertEmpty($object->getBody()); } - /** - * @testdox Tests that the application redirects successfully with the legacy behavior. - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests that the application redirects successfully with the legacy behavior.')] public function testRedirectLegacyBehavior() { $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; @@ -760,15 +685,8 @@ public function testRedirectLegacyBehavior() ); } - /** - * @testdox Tests that the application redirects successfully. - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests that the application redirects successfully.')] public function testRedirect() { $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; @@ -834,15 +752,8 @@ public function testRedirect() ); } - /** - * @testdox Tests that the application redirects successfully when there is already a status code set. - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests that the application redirects successfully when there is already a status code set.')] public function testRedirectWithExistingStatusCode() { $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; @@ -910,15 +821,8 @@ public function testRedirectWithExistingStatusCode() ); } - /** - * @testdox Tests that the application redirects and sends additional headers successfully. - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests that the application redirects and sends additional headers successfully.')] public function testRedirectWithAdditionalHeaders() { $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; @@ -985,17 +889,10 @@ public function testRedirectWithAdditionalHeaders() ); } - /** - * @testdox Tests that the application redirects successfully when the headers have already been sent. - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[PreserveGlobalState(false)] + #[RunInSeparateProcess] + #[TestDox('Tests that the application redirects successfully when the headers have already been sent.')] public function testRedirectWithHeadersSent() { $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; @@ -1040,15 +937,8 @@ public function testRedirectWithHeadersSent() ); } - /** - * @testdox Tests that the application redirects successfully with a JavaScript redirect. - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests that the application redirects successfully with a JavaScript redirect.')] public function testRedirectWithJavascriptRedirect() { $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; @@ -1108,15 +998,8 @@ public function testRedirectWithJavascriptRedirect() ); } - /** - * @testdox Tests that the application redirects successfully with the moved parameter set to true. - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests that the application redirects successfully with the moved parameter set to true.')] public function testRedirectWithMoved() { $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; @@ -1184,18 +1067,12 @@ public function testRedirectWithMoved() } /** - * @testdox Tests that the application redirects successfully with the moved parameter set to true. - * * @param string $url The URL to redirect to * @param string $expected The expected redirect URL - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @dataProvider getRedirectData - * @backupGlobals enabled */ + #[BackupGlobals(true)] + #[DataProvider('getRedirectData')] + #[TestDox('Tests that the application redirects successfully with the moved parameter set to true.')] public function testRedirectWithUrl(string $url, string $expected) { $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; @@ -1249,13 +1126,7 @@ public function testRedirectWithUrl(string $url, string $expected) ); } - /** - * @testdox Tests the \allowCache() method returns the allowed cache state - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the \allowCache() method returns the allowed cache state')] public function testAllowCache() { $object = new TestAbstractWebApplicationObject(); @@ -1264,13 +1135,7 @@ public function testAllowCache() $this->assertTrue($object->allowCache(true)); } - /** - * @testdox Tests the \setHeader() method correctly sets and replaces a specified header - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the \setHeader() method correctly sets and replaces a specified header')] public function testSetHeader() { $object = new TestAbstractWebApplicationObject(); @@ -1295,13 +1160,7 @@ public function testSetHeader() ); } - /** - * @testdox Tests the \clearHeaders() method resets the internal headers array - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the \clearHeaders() method resets the internal headers array')] public function testClearHeaders() { $object = new TestAbstractWebApplicationObject(); @@ -1312,13 +1171,7 @@ public function testClearHeaders() $this->assertNotSame($oldHeaders, $object->getHeaders()); } - /** - * @testdox Tests the \sendHeaders() method correctly sends the response headers - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the \sendHeaders() method correctly sends the response headers')] public function testSendHeaders() { $object = $this->createMock( @@ -1351,13 +1204,7 @@ public function testSendHeaders() ); } - /** - * @testdox Tests the \setBody() method correctly sets the response body - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the \setBody() method correctly sets the response body')] public function testSetBody() { $object = new TestAbstractWebApplicationObject(); @@ -1366,13 +1213,7 @@ public function testSetBody() $this->assertSame('Testing', $object->getBody()); } - /** - * @testdox Tests the \prependBody() method correctly prepends content to the response body - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the \prependBody() method correctly prepends content to the response body')] public function testPrependBody() { $object = new TestAbstractWebApplicationObject(); @@ -1382,13 +1223,7 @@ public function testPrependBody() $this->assertSame('Pre-Testing', $object->getBody()); } - /** - * @testdox Tests the \appendBody() method correctly appends content to the response body - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the \appendBody() method correctly appends content to the response body')] public function testAppendBody() { $object = new TestAbstractWebApplicationObject(); @@ -1398,13 +1233,7 @@ public function testAppendBody() $this->assertSame('Testing Later', $object->getBody()); } - /** - * @testdox Tests the \getBody() method correctly retrieves the response body - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the \getBody() method correctly retrieves the response body')] public function testGetBody() { $object = new TestAbstractWebApplicationObject(); @@ -1413,8 +1242,6 @@ public function testGetBody() } /** - * @testdox Tests that the application correctly detects the request URI based on the injected data - * * @param string|null $https Value for $_SERVER['HTTPS'] or null to not set it * @param string $phpSelf Value for $_SERVER['PHP_SELF'] * @param string $requestUri Value for $_SERVER['REQUEST_URI'] @@ -1422,14 +1249,10 @@ public function testGetBody() * @param string $scriptName Value for $_SERVER['SCRIPT_NAME'] * @param string $queryString Value for $_SERVER['QUERY_STRING'] * @param string $expects Expected full URI string - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @backupGlobals enabled */ + #[BackupGlobals(true)] #[DataProvider('getDetectRequestUriData')] + #[TestDox('Tests that the application correctly detects the request URI based on the injected data')] public function testDetectRequestUri( ?string $https, string $phpSelf, @@ -1459,13 +1282,7 @@ public function testDetectRequestUri( ); } - /** - * @testdox Tests the system URIs are correctly loaded when a URI is set in the application configuration - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the system URIs are correctly loaded when a URI is set in the application configuration')] public function testLoadSystemUrisWithSiteUriSet() { $mockConfig = $this->getMockBuilder(Registry::class) @@ -1503,15 +1320,8 @@ public function testLoadSystemUrisWithSiteUriSet() ); } - /** - * @testdox Tests the system URIs are correctly loaded when a URI is passed into the method - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests the system URIs are correctly loaded when a URI is passed into the method')] public function testLoadSystemUrisWithoutSiteUriSet() { $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; @@ -1549,16 +1359,8 @@ public function testLoadSystemUrisWithoutSiteUriSet() ); } - /** - * @testdox Tests the system URIs are correctly loaded when a media URI is set in the application - * configuration - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests the system URIs are correctly loaded when a media URI is set in the application configuration')] public function testLoadSystemUrisWithoutSiteUriWithMediaUriSet() { $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; @@ -1601,16 +1403,8 @@ public function testLoadSystemUrisWithoutSiteUriWithMediaUriSet() ); } - /** - * @testdox Tests the system URIs are correctly loaded when a relative media URI is set in the application - * configuration - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests the system URIs are correctly loaded when a relative media URI is set in the application configuration')] public function testLoadSystemUrisWithoutSiteUriWithRelativeMediaUriSet() { $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; @@ -1653,15 +1447,8 @@ public function testLoadSystemUrisWithoutSiteUriWithRelativeMediaUriSet() ); } - /** - * @testdox Tests the application correctly detects if a SSL connection is active - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests the application correctly detects if a SSL connection is active')] public function testisSslConnection() { $object = new TestAbstractWebApplicationObject(); @@ -1673,13 +1460,7 @@ public function testisSslConnection() $this->assertTrue($object->isSslConnection()); } - /** - * @testdox Tests the application correctly approves a valid HTTP Status Code - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the application correctly approves a valid HTTP Status Code')] public function testGetHttpStatusValue() { $object = new TestAbstractWebApplicationObject(); @@ -1687,13 +1468,7 @@ public function testGetHttpStatusValue() $this->assertTrue($object->isValidHttpStatus(500)); } - /** - * @testdox Tests the application correctly rejects a valid HTTP Status Code - * - * @covers \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests the application correctly rejects a valid HTTP Status Code')] public function testInvalidHttpStatusValue() { $object = new TestAbstractWebApplicationObject(); diff --git a/Tests/Controller/ContainerControllerResolverTest.php b/Tests/Controller/ContainerControllerResolverTest.php index a0350c7d..94416d63 100644 --- a/Tests/Controller/ContainerControllerResolverTest.php +++ b/Tests/Controller/ContainerControllerResolverTest.php @@ -8,15 +8,21 @@ namespace Joomla\Application\Tests\Controller; use Joomla\Application\Controller\ContainerControllerResolver; +use Joomla\Application\Controller\ControllerResolver; use Joomla\Application\Tests\Stubs\Controller; use Joomla\Application\Tests\Stubs\HasArgumentsController; use Joomla\DI\Container; use Joomla\Router\ResolvedRoute; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\Attributes\UsesClass; use PHPUnit\Framework\TestCase; /** * Test class for Joomla\Application\Controller\ContainerControllerResolver. */ +#[CoversClass(ContainerControllerResolver::class)] +#[UsesClass(ControllerResolver::class)] class ContainerControllerResolverTest extends TestCase { /** @@ -43,12 +49,7 @@ function () { $this->resolver = new ContainerControllerResolver($container); } - /** - * @testdox Tests the resolver resolves a ControllerInterface - * - * @covers Joomla\Application\Controller\ContainerControllerResolver - * @uses Joomla\Application\Controller\ControllerResolver - */ + #[TestDox('Tests the resolver resolves a ControllerInterface')] public function testResolvingAControllerInterface() { $callable = $this->resolver->resolve(new ResolvedRoute(Controller::class, [], '/')); @@ -57,12 +58,7 @@ public function testResolvingAControllerInterface() $this->assertInstanceOf(Controller::class, $callable[0]); } - /** - * @testdox Tests the resolver resolves a ControllerInterface but fails instantiating a class with required arguments - * - * @covers Joomla\Application\Controller\ContainerControllerResolver - * @uses Joomla\Application\Controller\ControllerResolver - */ + #[TestDox('Tests the resolver resolves a ControllerInterface but fails instantiating a class with required arguments')] public function testResolvingControllerInterfaceFailsOnAClassWithRequiredArguments() { $this->expectException(\InvalidArgumentException::class); diff --git a/Tests/Controller/ControllerResolverTest.php b/Tests/Controller/ControllerResolverTest.php index a9741eed..cb2352f2 100644 --- a/Tests/Controller/ControllerResolverTest.php +++ b/Tests/Controller/ControllerResolverTest.php @@ -12,18 +12,17 @@ use Joomla\Application\Tests\Stubs\HasArgumentsController; use Joomla\Registry\Registry; use Joomla\Router\ResolvedRoute; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; /** * Test class for Joomla\Application\Controller\ControllerResolver. */ +#[CoversClass(ControllerResolver::class)] class ControllerResolverTest extends TestCase { - /** - * @testdox Tests the resolver resolves a callable array - * - * @covers Joomla\Application\Controller\ControllerResolver - */ + #[TestDox('Tests the resolver resolves a callable array')] public function testResolvingACallableArray() { $callable = (new ControllerResolver())->resolve(new ResolvedRoute([Registry::class, 'get'], [], '/')); @@ -32,11 +31,7 @@ public function testResolvingACallableArray() $this->assertInstanceOf(Registry::class, $callable[0]); } - /** - * @testdox Tests the resolver fails to resolve an array that is not callable - * - * @covers Joomla\Application\Controller\ControllerResolver - */ + #[TestDox('Tests the resolver fails to resolve an array that is not callable')] public function testResolvingAnArrayFailsWhenNonCollable() { $this->expectException(\InvalidArgumentException::class); @@ -45,11 +40,7 @@ public function testResolvingAnArrayFailsWhenNonCollable() (new ControllerResolver())->resolve(new ResolvedRoute([Registry::class, 'noWayThisWillEverExist'], [], '/')); } - /** - * @testdox Tests the resolver resolves a callable array but fails instantiating a class with required arguments - * - * @covers Joomla\Application\Controller\ControllerResolver - */ + #[TestDox('Tests the resolver resolves a callable array but fails instantiating a class with required arguments')] public function testResolvingACallableArrayFailsOnAClassWithRequiredArguments() { $this->expectException(\InvalidArgumentException::class); @@ -58,11 +49,7 @@ public function testResolvingACallableArrayFailsOnAClassWithRequiredArguments() (new ControllerResolver())->resolve(new ResolvedRoute([HasArgumentsController::class, 'execute'], [], '/')); } - /** - * @testdox Tests the resolver resolves a callable object - * - * @covers Joomla\Application\Controller\ControllerResolver - */ + #[TestDox('Tests the resolver resolves a callable object')] public function testResolvingACallableObject() { $controller = function () { @@ -72,21 +59,13 @@ public function testResolvingACallableObject() $this->assertSame($controller, (new ControllerResolver())->resolve(new ResolvedRoute($controller, [], '/'))); } - /** - * @testdox Tests the resolver resolves a callable function - * - * @covers Joomla\Application\Controller\ControllerResolver - */ + #[TestDox('Tests the resolver resolves a callable function')] public function testResolvingACallableFunction() { $this->assertSame('str_replace', (new ControllerResolver())->resolve(new ResolvedRoute('str_replace', [], '/'))); } - /** - * @testdox Tests the resolver resolves a ControllerInterface - * - * @covers Joomla\Application\Controller\ControllerResolver - */ + #[TestDox('Tests the resolver resolves a ControllerInterface')] public function testResolvingAControllerInterface() { $callable = (new ControllerResolver())->resolve(new ResolvedRoute(Controller::class, [], '/')); @@ -95,11 +74,7 @@ public function testResolvingAControllerInterface() $this->assertInstanceOf(Controller::class, $callable[0]); } - /** - * @testdox Tests the resolver resolves a ControllerInterface but fails instantiating a class with required arguments - * - * @covers Joomla\Application\Controller\ControllerResolver - */ + #[TestDox('Tests the resolver resolves a ControllerInterface but fails instantiating a class with required arguments')] public function testResolvingControllerInterfaceFailsOnAClassWithRequiredArguments() { $this->expectException(\InvalidArgumentException::class); diff --git a/Tests/SessionAwareWebApplicationTraitTest.php b/Tests/SessionAwareWebApplicationTraitTest.php index 73628d01..82a23746 100644 --- a/Tests/SessionAwareWebApplicationTraitTest.php +++ b/Tests/SessionAwareWebApplicationTraitTest.php @@ -7,21 +7,31 @@ namespace Joomla\Application\Tests; +use Joomla\Application\AbstractApplication; +use Joomla\Application\AbstractWebApplication; +use Joomla\Application\SessionAwareWebApplicationTrait; use Joomla\Application\Tests\Stubs\TestSessionAwareWebApplicationTraitObject; +use Joomla\Application\Web\WebClient; +use Joomla\Application\WebApplication; use Joomla\Input\Input; use Joomla\Session\SessionInterface; +use PHPUnit\Framework\Attributes\BackupGlobals; +use PHPUnit\Framework\Attributes\CoversTrait; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\Attributes\UsesClass; use PHPUnit\Framework\TestCase; /** * Test class for Joomla\Application\SessionAwareWebApplicationTrait. */ +#[CoversTrait(SessionAwareWebApplicationTrait::class)] +#[UsesClass(AbstractApplication::class)] +#[UsesClass(AbstractWebApplication::class)] +#[UsesClass(WebApplication::class)] +#[UsesClass(WebClient::class)] class SessionAwareWebApplicationTraitTest extends TestCase { - /** - * @testdox Tests a session object is correctly injected into the application and retrieved - * - * @covers Joomla\Application\SessionAwareWebApplicationTrait - */ + #[TestDox('Tests a session object is correctly injected into the application and retrieved')] public function testSetSession() { $object = new TestSessionAwareWebApplicationTraitObject(); @@ -31,11 +41,7 @@ public function testSetSession() $this->assertSame($mockSession, $object->getSession()); } - /** - * @testdox Tests a RuntimeException is thrown when a Session object is not set to the application - * - * @covers Joomla\Application\SessionAwareWebApplicationTrait - */ + #[TestDox('Tests a RuntimeException is thrown when a Session object is not set to the application')] public function testGetSessionForAnException() { $this->expectException(\RuntimeException::class); @@ -44,17 +50,8 @@ public function testGetSessionForAnException() $object->getSession(); } - /** - * @testdox Tests the CSRF token can be checked from the `X-CSRF-Token` header - * - * @covers Joomla\Application\SessionAwareWebApplicationTrait - * @uses Joomla\Application\AbstractApplication - * @uses Joomla\Application\AbstractWebApplication - * @uses Joomla\Application\WebApplication - * @uses Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests the CSRF token can be checked from the `X-CSRF-Token` header')] public function testCheckTokenForHttpHeader() { $_SERVER['HTTP_X_CSRF_TOKEN'] = 'token'; @@ -77,17 +74,8 @@ public function testCheckTokenForHttpHeader() $this->assertTrue($object->checkToken()); } - /** - * @testdox Tests the CSRF token can be checked from the request body - * - * @covers Joomla\Application\SessionAwareWebApplicationTrait - * @uses Joomla\Application\AbstractApplication - * @uses Joomla\Application\AbstractWebApplication - * @uses Joomla\Application\WebApplication - * @uses Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests the CSRF token can be checked from the request body')] public function testCheckTokenForRequestBody() { $_POST['testing'] = 'token'; @@ -110,17 +98,8 @@ public function testCheckTokenForRequestBody() $this->assertTrue($object->checkToken()); } - /** - * @testdox Tests checking the CSRF token fails when it does not exist in the request - * - * @covers Joomla\Application\SessionAwareWebApplicationTrait - * @uses Joomla\Application\AbstractApplication - * @uses Joomla\Application\AbstractWebApplication - * @uses Joomla\Application\WebApplication - * @uses Joomla\Application\Web\WebClient - * - * @backupGlobals enabled - */ + #[BackupGlobals(true)] + #[TestDox('Tests checking the CSRF token fails when it does not exist in the request')] public function testCheckTokenFailsWhenNotPresent() { $mockInput = new Input([]); diff --git a/Tests/Web/WebClientTest.php b/Tests/Web/WebClientTest.php index 0b816a42..0f252b78 100644 --- a/Tests/Web/WebClientTest.php +++ b/Tests/Web/WebClientTest.php @@ -8,6 +8,8 @@ namespace Joomla\Application\Tests\Web; use Joomla\Application\Web\WebClient; +use PHPUnit\Framework\Attributes\BackupGlobals; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -15,9 +17,9 @@ * Test class for Joomla\Application\Web\WebClient. * * @since 1.0.0 - * - * @backupGlobals enabled */ +#[CoversClass(WebClient::class)] +#[BackupGlobals(true)] class WebClientTest extends TestCase { /** @@ -514,7 +516,6 @@ public function setUp(): void * @return void * * @since 1.0.0 - * @covers \Joomla\Application\Web\WebClient */ #[DataProvider('getUserAgentData')] public function testDetectBrowser($p, $m, $e, $b, $v, $ua) @@ -532,7 +533,6 @@ public function testDetectBrowser($p, $m, $e, $b, $v, $ua) * @return void * * @since 1.0.0 - * @covers \Joomla\Application\Web\WebClient */ public function testDetectHeaders() { @@ -555,7 +555,6 @@ public function testDetectHeaders() * @return void * * @since 1.0.0 - * @covers \Joomla\Application\Web\WebClient */ #[DataProvider('getEncodingData')] public function testDetectEncoding($ae, $e) @@ -579,7 +578,6 @@ public function testDetectEncoding($ae, $e) * @return void * * @since 1.0.0 - * @covers \Joomla\Application\Web\WebClient */ #[DataProvider('getUserAgentData')] public function testDetectEngine($p, $m, $e, $b, $v, $ua) @@ -599,7 +597,6 @@ public function testDetectEngine($p, $m, $e, $b, $v, $ua) * @return void * * @since 1.0.0 - * @covers \Joomla\Application\Web\WebClient */ #[DataProvider('getLanguageData')] public function testDetectLanguage($al, $l) @@ -621,8 +618,8 @@ public function testDetectLanguage($al, $l) * @param string $ua The input user agent. * * @return void + * * @since 1.0.0 - * @covers \Joomla\Application\Web\WebClient */ #[DataProvider('getUserAgentData')] public function testDetectPlatform($p, $m, $e, $b, $v, $ua) @@ -643,7 +640,6 @@ public function testDetectPlatform($p, $m, $e, $b, $v, $ua) * @return void * * @since 1.0.0 - * @covers \Joomla\Application\Web\WebClient */ #[DataProvider('detectRobotData')] public function testDetectRobot($userAgent, $expected) diff --git a/Tests/WebApplicationTest.php b/Tests/WebApplicationTest.php index f28287ad..653629c4 100644 --- a/Tests/WebApplicationTest.php +++ b/Tests/WebApplicationTest.php @@ -12,23 +12,23 @@ use Joomla\Input\Input; use Joomla\Router\ResolvedRoute; use Joomla\Router\RouterInterface; +use PHPUnit\Framework\Attributes\BackupGlobals; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\Attributes\UsesClass; use PHPUnit\Framework\TestCase; /** * Test class for Joomla\Application\WebApplication. - * - * @backupGlobals enabled */ +#[CoversClass(WebApplication::class)] +#[BackupGlobals(true)] +#[UsesClass('\Joomla\Application\AbstractApplication')] +#[UsesClass('\Joomla\Application\AbstractWebApplication')] +#[UsesClass('\Joomla\Application\Web\WebClient')] class WebApplicationTest extends TestCase { - /** - * @testdox Tests that the application is executed successfully. - * - * @covers \Joomla\Application\WebApplication - * @uses \Joomla\Application\AbstractApplication - * @uses \Joomla\Application\AbstractWebApplication - * @uses \Joomla\Application\Web\WebClient - */ + #[TestDox('Tests that the application is executed successfully.')] public function testExecute() { $_SERVER['REQUEST_METHOD'] = 'GET'; From 7dd9b3e4abbea224b84f6ce8d511f4f36c75a404 Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:04:29 +0200 Subject: [PATCH 04/17] replace TestAbstractApplicationObject --- Tests/AbstractApplicationTest.php | 55 +++++++++++++++---- Tests/Stubs/TestAbstractApplicationObject.php | 19 ------- 2 files changed, 45 insertions(+), 29 deletions(-) delete mode 100644 Tests/Stubs/TestAbstractApplicationObject.php diff --git a/Tests/AbstractApplicationTest.php b/Tests/AbstractApplicationTest.php index 2ed01099..13b03476 100644 --- a/Tests/AbstractApplicationTest.php +++ b/Tests/AbstractApplicationTest.php @@ -7,7 +7,6 @@ namespace Joomla\Application\Tests; -use Joomla\Application\Tests\Stubs\TestAbstractApplicationObject; use Joomla\Application\AbstractApplication; use Joomla\Application\Event\ApplicationEvent; use Joomla\Application\Web\WebClient; @@ -29,13 +28,33 @@ #[UsesClass(WebClient::class)] class AbstractApplicationTest extends TestCase { + /** + * Returns a lightweight AbstractApplication instance for testing. + * + * The anonymous class forwards all constructor arguments to the parent + * and provides an empty doExecute() implementation. + * + * @param mixed ...$args Constructor arguments for AbstractApplication + * + * @return AbstractApplication + */ + private function getAbstractApplication(...$args): AbstractApplication + { + return new class (...$args) extends AbstractApplication + { + protected function doExecute() + { + } + }; + } + #[TestDox('Tests the constructor creates default object instances')] public function testConstructDefaultBehaviour() { $startTime = \time(); $startMicrotime = \microtime(true); - $object = new TestAbstractApplicationObject(); + $object = $this->getAbstractApplication(); $this->assertInstanceOf( Registry::class, @@ -55,7 +74,7 @@ public function testConstructDefaultBehaviour() public function testConstructDependencyInjection() { $mockConfig = $this->createMock(Registry::class); - $object = new TestAbstractApplicationObject($mockConfig); + $object = $this->getAbstractApplication($mockConfig); $this->assertSame( $mockConfig, @@ -64,10 +83,24 @@ public function testConstructDependencyInjection() ); } + #[TestDox('Tests that \close() exits the application with the given code')] + public function testClose() + { + $object = $this->createMock(AbstractApplication::class); + + $object->expects($this->once()) + ->method('close') + ->willReturnArgument(0); + + $this->assertSame(3, $object->close(3)); + } + #[TestDox('Tests that the application is executed successfully.')] public function testExecute() { - $object = $this->createMock(TestAbstractApplicationObject::class); + $object = $this->getMockBuilder(AbstractApplication::class) + ->onlyMethods(['doExecute']) + ->getMock(); $object->expects($this->once()) ->method('doExecute'); @@ -81,7 +114,9 @@ public function testExecuteWithEvents() $dispatcher->expects($this->exactly(2)) ->method('dispatch'); - $object = $this->createMock(TestAbstractApplicationObject::class); + $object = $this->getMockBuilder(AbstractApplication::class) + ->onlyMethods(['doExecute']) + ->getMock(); $object->expects($this->once()) ->method('doExecute'); @@ -98,7 +133,7 @@ public function testGet() ->enableProxyingToOriginalMethods() ->getMock(); - $object = new TestAbstractApplicationObject($mockConfig); + $object = $this->getAbstractApplication($mockConfig); $this->assertSame('bar', $object->get('foo', 'car'), 'Checks a known configuration setting is returned.'); $this->assertSame('car', $object->get('goo', 'car'), 'Checks an unknown configuration setting returns the default.'); @@ -107,7 +142,7 @@ public function testGet() #[TestDox('Tests that a default LoggerInterface object is returned.')] public function testGetLogger() { - $object = new TestAbstractApplicationObject(); + $object = $this->getAbstractApplication(); $this->assertInstanceOf(NullLogger::class, $object->getLogger()); } @@ -119,7 +154,7 @@ public function testSet() ->enableProxyingToOriginalMethods() ->getMock(); - $object = new TestAbstractApplicationObject($mockConfig); + $object = $this->getAbstractApplication($mockConfig); $this->assertNull($object->set('foo', 'car'), 'Checks set returns the previous value.'); $this->assertEquals('car', $object->get('foo'), 'Checks the new value has been set.'); @@ -128,7 +163,7 @@ public function testSet() #[TestDox('Tests that the application configuration is overwritten successfully.')] public function testSetConfiguration() { - $object = new TestAbstractApplicationObject(); + $object = $this->getAbstractApplication(); $mockConfig = $this->createMock(Registry::class); $this->assertSame($object, $object->setConfiguration($mockConfig), 'The setConfiguration method has a fluent interface'); @@ -143,7 +178,7 @@ public function testSetConfiguration() #[TestDox('Tests that a LoggerInterface object is correctly set to the application.')] public function testSetLogger() { - $object = new TestAbstractApplicationObject(); + $object = $this->getAbstractApplication(); $mockLogger = $this->createMock(LoggerInterface::class); $object->setLogger($mockLogger); diff --git a/Tests/Stubs/TestAbstractApplicationObject.php b/Tests/Stubs/TestAbstractApplicationObject.php deleted file mode 100644 index 47a353ce..00000000 --- a/Tests/Stubs/TestAbstractApplicationObject.php +++ /dev/null @@ -1,19 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE - */ - -namespace Joomla\Application\Tests\Stubs; - -use Joomla\Application\AbstractApplication; - -class TestAbstractApplicationObject extends AbstractApplication -{ - - protected function doExecute() - { - // TODO: Implement doExecute() method. - } -} From bc7338bbddede0932f0544ccedaaeef23d31396a Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:08:22 +0200 Subject: [PATCH 05/17] replace TestAbstractWebApplicationObject --- Tests/AbstractWebApplicationTest.php | 83 ++++++++++++------- .../TestAbstractWebApplicationObject.php | 19 ----- 2 files changed, 52 insertions(+), 50 deletions(-) delete mode 100644 Tests/Stubs/TestAbstractWebApplicationObject.php diff --git a/Tests/AbstractWebApplicationTest.php b/Tests/AbstractWebApplicationTest.php index 67532e99..97f7668a 100644 --- a/Tests/AbstractWebApplicationTest.php +++ b/Tests/AbstractWebApplicationTest.php @@ -10,7 +10,6 @@ use Joomla\Application\AbstractApplication; use Joomla\Application\AbstractWebApplication; use Joomla\Application\Event\ApplicationEvent; -use Joomla\Application\Tests\Stubs\TestAbstractWebApplicationObject; use Joomla\Application\Web\WebClient; use Joomla\Event\DispatcherInterface; use Joomla\Input\Input; @@ -74,6 +73,26 @@ protected function tearDown(): void parent::tearDown(); } + /** + * Returns a lightweight AbstractWebApplication instance for testing. + * + * The anonymous class forwards all constructor arguments to the parent + * and provides an empty doExecute() implementation. + * + * @param mixed ...$args Constructor arguments for AbstractWebApplication + * + * @return AbstractWebApplication + */ + private function getAbstractWebApplication(...$args): AbstractWebApplication + { + return new class (...$args) extends AbstractWebApplication + { + protected function doExecute() + { + } + }; + } + /** * Data for detectRequestUri method. * @@ -156,7 +175,7 @@ public static function mockHeader($string, $replace = true, $code = null) #[TestDox('Tests the constructor creates default object instances')] public function testConstructDefaultBehaviour() { - $object = new TestAbstractWebApplicationObject(); + $object = $this->getAbstractWebApplication(); // Validate default objects unique to the web application are created $this->assertInstanceOf(WebClient::class, $object->client); @@ -176,7 +195,7 @@ public function testConstructDependencyInjection() $mockClient = $this->createMock(WebClient::class); - $object = new TestAbstractWebApplicationObject($mockInput, $mockConfig, $mockClient); + $object = $this->getAbstractWebApplication($mockInput, $mockConfig, $mockClient); $this->assertSame($mockInput, $object->getInput()); @@ -194,7 +213,7 @@ public function testConstructDependencyInjection() #[TestDox('Tests access to the input property is allowed')] public function testGetDeprecatedInputReadAccess() { - $object = $this->createMock(TestAbstractWebApplicationObject::class); + $object = $this->getAbstractWebApplication(); // Validate default objects unique to the web application are created $this->assertInstanceOf(Input::class, $object->getInput()); @@ -203,7 +222,9 @@ public function testGetDeprecatedInputReadAccess() #[TestDox('Tests that the application is executed successfully.')] public function testExecute() { - $object = $this->createMock(TestAbstractWebApplicationObject::class); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->onlyMethods(['doExecute']) + ->getMock(); $object->expects($this->once()) ->method('doExecute'); @@ -231,7 +252,9 @@ public function testExecuteWithEvents() $dispatcher->expects($this->exactly(4)) ->method('dispatch'); - $object = $this->createMock(TestAbstractWebApplicationObject::class); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->onlyMethods(['doExecute']) + ->getMock(); $object->expects($this->once()) ->method('doExecute'); @@ -264,9 +287,14 @@ public function testExecuteWithCompression() $mockConfig = new Registry(['gzip' => true]); - $object = $this->createMock(TestAbstractWebApplicationObject::class, [null, $mockConfig]); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->setConstructorArgs([null, $mockConfig]) + ->onlyMethods(['doExecute', 'compress']) + ->getMock(); $object->expects($this->once()) ->method('doExecute'); + $object->expects($this->once()) + ->method('compress'); $object->execute(); @@ -572,7 +600,7 @@ public function testCompressWithUnsupportedEncodings() #[TestDox('Tests that the application sends the response successfully.')] public function testRespond() { - $object = $this->createMock(TestAbstractWebApplicationObject::class); + $object = $this->getAbstractWebApplication(); TestHelper::invoke($object, 'respond'); @@ -596,7 +624,7 @@ public function testRespondWithAllowedCaching() { $modifiedDate = new \DateTime('now', new \DateTimeZone('GMT')); - $object = $this->createMock(TestAbstractWebApplicationObject::class); + $object = $this->getAbstractWebApplication(); $object->allowCache(true); $object->modifiedDate = $modifiedDate; @@ -1129,7 +1157,7 @@ public function testRedirectWithUrl(string $url, string $expected) #[TestDox('Tests the \allowCache() method returns the allowed cache state')] public function testAllowCache() { - $object = new TestAbstractWebApplicationObject(); + $object = $this->getAbstractWebApplication(); $this->assertFalse($object->allowCache()); $this->assertTrue($object->allowCache(true)); @@ -1138,7 +1166,7 @@ public function testAllowCache() #[TestDox('Tests the \setHeader() method correctly sets and replaces a specified header')] public function testSetHeader() { - $object = new TestAbstractWebApplicationObject(); + $object = $this->getAbstractWebApplication(); $object->setHeader('foo', 'bar'); @@ -1163,7 +1191,7 @@ public function testSetHeader() #[TestDox('Tests the \clearHeaders() method resets the internal headers array')] public function testClearHeaders() { - $object = new TestAbstractWebApplicationObject(); + $object = $this->getAbstractWebApplication(); $object->setHeader('foo', 'bar'); $oldHeaders = $object->getHeaders(); @@ -1174,15 +1202,9 @@ public function testClearHeaders() #[TestDox('Tests the \sendHeaders() method correctly sends the response headers')] public function testSendHeaders() { - $object = $this->createMock( - TestAbstractWebApplicationObject::class, - [], - '', - true, - true, - true, - ['checkHeadersSent', 'header'] - ); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->onlyMethods(['checkHeadersSent', 'header', 'doExecute']) + ->getMock(); $object->expects($this->any()) ->method('checkHeadersSent') @@ -1207,7 +1229,7 @@ public function testSendHeaders() #[TestDox('Tests the \setBody() method correctly sets the response body')] public function testSetBody() { - $object = new TestAbstractWebApplicationObject(); + $object = $this->getAbstractWebApplication(); $this->assertSame($object, $object->setBody('Testing')); $this->assertSame('Testing', $object->getBody()); @@ -1216,7 +1238,7 @@ public function testSetBody() #[TestDox('Tests the \prependBody() method correctly prepends content to the response body')] public function testPrependBody() { - $object = new TestAbstractWebApplicationObject(); + $object = $this->getAbstractWebApplication(); $object->setBody('Testing'); $this->assertSame($object, $object->prependBody('Pre-')); @@ -1226,7 +1248,7 @@ public function testPrependBody() #[TestDox('Tests the \appendBody() method correctly appends content to the response body')] public function testAppendBody() { - $object = new TestAbstractWebApplicationObject(); + $object = $this->getAbstractWebApplication(); $object->setBody('Testing'); $this->assertSame($object, $object->appendBody(' Later')); @@ -1236,7 +1258,7 @@ public function testAppendBody() #[TestDox('Tests the \getBody() method correctly retrieves the response body')] public function testGetBody() { - $object = new TestAbstractWebApplicationObject(); + $object = $this->getAbstractWebApplication(); $this->assertSame('', $object->getBody(), 'Returns an empty string by default'); } @@ -1274,7 +1296,7 @@ public function testDetectRequestUri( $_SERVER['HTTPS'] = $https; } - $object = new TestAbstractWebApplicationObject($mockInput); + $object = $this->getAbstractWebApplication($mockInput); $this->assertSame( $expects, @@ -1328,8 +1350,7 @@ public function testLoadSystemUrisWithoutSiteUriSet() $_SERVER['SCRIPT_NAME'] = self::TEST_REQUEST_URI; $mockInput = new Input([]); - - $object = new TestAbstractWebApplicationObject($mockInput); + $object = $this->getAbstractWebApplication($mockInput); TestHelper::invoke($object, 'loadSystemUris', 'http://joom.la/application'); @@ -1451,7 +1472,7 @@ public function testLoadSystemUrisWithoutSiteUriWithRelativeMediaUriSet() #[TestDox('Tests the application correctly detects if a SSL connection is active')] public function testisSslConnection() { - $object = new TestAbstractWebApplicationObject(); + $object = $this->getAbstractWebApplication(); $this->assertFalse($object->isSslConnection()); @@ -1463,7 +1484,7 @@ public function testisSslConnection() #[TestDox('Tests the application correctly approves a valid HTTP Status Code')] public function testGetHttpStatusValue() { - $object = new TestAbstractWebApplicationObject(); + $object = $this->getAbstractWebApplication(); $this->assertTrue($object->isValidHttpStatus(500)); } @@ -1471,7 +1492,7 @@ public function testGetHttpStatusValue() #[TestDox('Tests the application correctly rejects a valid HTTP Status Code')] public function testInvalidHttpStatusValue() { - $object = new TestAbstractWebApplicationObject(); + $object = $this->getAbstractWebApplication(); $this->assertFalse($object->isValidHttpStatus(460)); } diff --git a/Tests/Stubs/TestAbstractWebApplicationObject.php b/Tests/Stubs/TestAbstractWebApplicationObject.php deleted file mode 100644 index c0ea4a3d..00000000 --- a/Tests/Stubs/TestAbstractWebApplicationObject.php +++ /dev/null @@ -1,19 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE - */ - -namespace Joomla\Application\Tests\Stubs; - -use Joomla\Application\AbstractWebApplication; - -class TestAbstractWebApplicationObject extends AbstractWebApplication -{ - - protected function doExecute() - { - // TODO: Implement doExecute() method. - } -} From 1a4c3f6a7ac0a84c30688cbb7b1b0c400220ae6e Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:09:26 +0200 Subject: [PATCH 06/17] replace TestSessionAwareWebApplicationTraitObject --- Tests/SessionAwareWebApplicationTraitTest.php | 32 +++++++++++++++---- ...tSessionAwareWebApplicationTraitObject.php | 21 ------------ 2 files changed, 26 insertions(+), 27 deletions(-) delete mode 100644 Tests/Stubs/TestSessionAwareWebApplicationTraitObject.php diff --git a/Tests/SessionAwareWebApplicationTraitTest.php b/Tests/SessionAwareWebApplicationTraitTest.php index 82a23746..9bdc04b0 100644 --- a/Tests/SessionAwareWebApplicationTraitTest.php +++ b/Tests/SessionAwareWebApplicationTraitTest.php @@ -10,7 +10,6 @@ use Joomla\Application\AbstractApplication; use Joomla\Application\AbstractWebApplication; use Joomla\Application\SessionAwareWebApplicationTrait; -use Joomla\Application\Tests\Stubs\TestSessionAwareWebApplicationTraitObject; use Joomla\Application\Web\WebClient; use Joomla\Application\WebApplication; use Joomla\Input\Input; @@ -31,10 +30,31 @@ #[UsesClass(WebClient::class)] class SessionAwareWebApplicationTraitTest extends TestCase { + /** + * Returns a lightweight object using SessionAwareWebApplicationTrait. + * + * The anonymous class provides a simple getInput() implementation, + * making it suitable for tests that require a minimal trait consumer. + * + * @return object An object using SessionAwareWebApplicationTrait + */ + private function getSessionAwareWebApplicationTrait() + { + return new class () + { + use SessionAwareWebApplicationTrait; + + public function getInput(): Input + { + return new Input([]); + } + }; + } + #[TestDox('Tests a session object is correctly injected into the application and retrieved')] public function testSetSession() { - $object = new TestSessionAwareWebApplicationTraitObject(); + $object = $this->getSessionAwareWebApplicationTrait(); $mockSession = $this->createMock(SessionInterface::class); $this->assertSame($object, $object->setSession($mockSession), 'The setSession method has a fluent interface.'); @@ -46,7 +66,7 @@ public function testGetSessionForAnException() { $this->expectException(\RuntimeException::class); - $object = new TestSessionAwareWebApplicationTraitObject(); + $object = $this->getSessionAwareWebApplicationTrait(); $object->getSession(); } @@ -68,7 +88,7 @@ public function testCheckTokenForHttpHeader() ->with('testing') ->willReturn(true); - $object = new TestSessionAwareWebApplicationTraitObject(); + $object = $this->getSessionAwareWebApplicationTrait(); $object->setSession($mockSession); $this->assertTrue($object->checkToken()); @@ -92,7 +112,7 @@ public function testCheckTokenForRequestBody() ->with('testing') ->willReturn(true); - $object = new TestSessionAwareWebApplicationTraitObject(); + $object = $this->getSessionAwareWebApplicationTrait(); $object->setSession($mockSession); $this->assertTrue($object->checkToken()); @@ -112,7 +132,7 @@ public function testCheckTokenFailsWhenNotPresent() $mockSession->expects($this->never()) ->method('hasToken'); - $object = new TestSessionAwareWebApplicationTraitObject(); + $object = $this->getSessionAwareWebApplicationTrait(); $object->setSession($mockSession); $this->assertFalse($object->checkToken()); diff --git a/Tests/Stubs/TestSessionAwareWebApplicationTraitObject.php b/Tests/Stubs/TestSessionAwareWebApplicationTraitObject.php deleted file mode 100644 index 6ba0cb02..00000000 --- a/Tests/Stubs/TestSessionAwareWebApplicationTraitObject.php +++ /dev/null @@ -1,21 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE - */ - -namespace Joomla\Application\Tests\Stubs; - -use Joomla\Application\SessionAwareWebApplicationTrait; -use Joomla\Input\Input; - -class TestSessionAwareWebApplicationTraitObject -{ - use SessionAwareWebApplicationTrait; - - public function getInput(): Input - { - return new Input([]); - } -} From 40e024dd7f3752d9338e6e811860f7a0f2724735 Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:32:19 +0200 Subject: [PATCH 07/17] getMockForAbstractClass was removed --- Tests/AbstractWebApplicationTest.php | 128 +++++++++------------------ 1 file changed, 44 insertions(+), 84 deletions(-) diff --git a/Tests/AbstractWebApplicationTest.php b/Tests/AbstractWebApplicationTest.php index 97f7668a..0b87170e 100644 --- a/Tests/AbstractWebApplicationTest.php +++ b/Tests/AbstractWebApplicationTest.php @@ -335,8 +335,8 @@ public function testCompressWithGzipEncoding() $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([null, null, $mockClient]) - ->onlyMethods(['checkHeadersSent']) - ->getMockForAbstractClass(); + ->onlyMethods(['checkHeadersSent', 'doExecute']) + ->getMock(); $object->expects($this->once()) ->method('checkHeadersSent') @@ -399,8 +399,8 @@ public function testCompressWithDeflateEncoding() $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([null, null, $mockClient]) - ->onlyMethods(['checkHeadersSent']) - ->getMockForAbstractClass(); + ->onlyMethods(['checkHeadersSent', 'doExecute']) + ->getMock(); $object->expects($this->once()) ->method('checkHeadersSent') @@ -457,8 +457,8 @@ public function testCompressWithNoAcceptEncodings() $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([null, null, $mockClient]) - ->onlyMethods(['checkHeadersSent']) - ->getMockForAbstractClass(); + ->onlyMethods(['checkHeadersSent', 'doExecute']) + ->getMock(); // Mock a response. $response = new TextResponse( @@ -511,8 +511,8 @@ public function testCompressWithHeadersSent() $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([null, null, $mockClient]) - ->onlyMethods(['checkHeadersSent']) - ->getMockForAbstractClass(); + ->onlyMethods(['checkHeadersSent', 'doExecute']) + ->getMock(); $object->expects($this->once()) ->method('checkHeadersSent') @@ -566,7 +566,7 @@ public function testCompressWithUnsupportedEncodings() ['foo', 'bar'] ); - $object = $this->getMockForAbstractClass(AbstractWebApplication::class, [null, null, $mockClient]); + $object = $this->getAbstractWebApplication(null, null, $mockClient); // Mock a response. $response = new TextResponse( @@ -673,15 +673,10 @@ public function testRedirectLegacyBehavior() WebClient::GECKO ); - $object = $this->getMockForAbstractClass( - AbstractWebApplication::class, - [$mockInput, $mockConfig, $mockClient], - '', - true, - true, - true, - ['checkHeadersSent', 'close', 'header'] - ); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) + ->onlyMethods(['checkHeadersSent', 'close', 'header', 'doExecute']) + ->getMock(); $object->expects($this->once()) ->method('close'); @@ -741,15 +736,10 @@ public function testRedirect() WebClient::GECKO ); - $object = $this->getMockForAbstractClass( - AbstractWebApplication::class, - [$mockInput, $mockConfig, $mockClient], - '', - true, - true, - true, - ['checkHeadersSent', 'close', 'header'] - ); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) + ->onlyMethods(['checkHeadersSent', 'close', 'header', 'doExecute']) + ->getMock(); $object->expects($this->once()) ->method('close'); @@ -808,15 +798,10 @@ public function testRedirectWithExistingStatusCode() WebClient::GECKO ); - $object = $this->getMockForAbstractClass( - AbstractWebApplication::class, - [$mockInput, $mockConfig, $mockClient], - '', - true, - true, - true, - ['checkHeadersSent', 'close', 'header'] - ); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) + ->onlyMethods(['checkHeadersSent', 'close', 'header', 'doExecute']) + ->getMock(); $object->expects($this->once()) ->method('close'); @@ -877,15 +862,10 @@ public function testRedirectWithAdditionalHeaders() WebClient::GECKO ); - $object = $this->getMockForAbstractClass( - AbstractWebApplication::class, - [$mockInput, $mockConfig, $mockClient], - '', - true, - true, - true, - ['checkHeadersSent', 'close', 'header'] - ); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) + ->onlyMethods(['checkHeadersSent', 'close', 'header', 'doExecute']) + ->getMock(); $object->expects($this->once()) ->method('close'); @@ -933,15 +913,10 @@ public function testRedirectWithHeadersSent() ->getMock(); - $object = $this->getMockForAbstractClass( - AbstractWebApplication::class, - [$mockInput, $mockConfig], - '', - true, - true, - true, - ['checkHeadersSent', 'close'] - ); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->setConstructorArgs([$mockInput, $mockConfig]) + ->onlyMethods(['checkHeadersSent', 'close', 'doExecute']) + ->getMock(); $object->expects($this->once()) ->method('close') @@ -996,15 +971,10 @@ public function testRedirectWithJavascriptRedirect() WebClient::TRIDENT ); - $object = $this->getMockForAbstractClass( - AbstractWebApplication::class, - [$mockInput, $mockConfig, $mockClient], - '', - true, - true, - true, - ['checkHeadersSent', 'close', 'header'] - ); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) + ->onlyMethods(['checkHeadersSent', 'close', 'doExecute']) + ->getMock(); $object->expects($this->once()) ->method('close'); @@ -1054,15 +1024,10 @@ public function testRedirectWithMoved() WebClient::GECKO ); - $object = $this->getMockForAbstractClass( - AbstractWebApplication::class, - [$mockInput, $mockConfig, $mockClient], - '', - true, - true, - true, - ['checkHeadersSent', 'close', 'header'] - ); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) + ->onlyMethods(['checkHeadersSent', 'close', 'header', 'doExecute']) + ->getMock(); $object->expects($this->once()) ->method('close'); @@ -1127,15 +1092,10 @@ public function testRedirectWithUrl(string $url, string $expected) WebClient::GECKO ); - $object = $this->getMockForAbstractClass( - AbstractWebApplication::class, - [$mockInput, $mockConfig, $mockClient], - '', - true, - true, - true, - ['checkHeadersSent', 'close', 'header'] - ); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) + ->onlyMethods(['checkHeadersSent', 'close', 'header', 'doExecute']) + ->getMock(); $object->expects($this->once()) ->method('close'); @@ -1312,7 +1272,7 @@ public function testLoadSystemUrisWithSiteUriSet() ->getMock(); - $object = $this->getMockForAbstractClass(AbstractWebApplication::class, [null, $mockConfig]); + $object = $this->getAbstractWebApplication(null, $mockConfig); TestHelper::invoke($object, 'loadSystemUris'); @@ -1394,7 +1354,7 @@ public function testLoadSystemUrisWithoutSiteUriWithMediaUriSet() ->getMock(); - $object = $this->getMockForAbstractClass(AbstractWebApplication::class, [$mockInput, $mockConfig]); + $object = $this->getAbstractWebApplication($mockInput, $mockConfig); TestHelper::invoke($object, 'loadSystemUris', 'http://joom.la/application'); @@ -1438,7 +1398,7 @@ public function testLoadSystemUrisWithoutSiteUriWithRelativeMediaUriSet() ->getMock(); - $object = $this->getMockForAbstractClass(AbstractWebApplication::class, [$mockInput, $mockConfig]); + $object = $this->getAbstractWebApplication($mockInput, $mockConfig); TestHelper::invoke($object, 'loadSystemUris', 'http://joom.la/application'); From 8614612efd98adecab3cf04ce31f9e34d3f01af4 Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:37:26 +0200 Subject: [PATCH 08/17] replace mocks with objects --- Tests/AbstractApplicationTest.php | 19 +- Tests/AbstractWebApplicationTest.php | 281 +++--------------- Tests/SessionAwareWebApplicationTraitTest.php | 8 +- 3 files changed, 45 insertions(+), 263 deletions(-) diff --git a/Tests/AbstractApplicationTest.php b/Tests/AbstractApplicationTest.php index 13b03476..a3114ccb 100644 --- a/Tests/AbstractApplicationTest.php +++ b/Tests/AbstractApplicationTest.php @@ -73,7 +73,7 @@ public function testConstructDefaultBehaviour() #[TestDox('Tests the correct objects are stored when injected')] public function testConstructDependencyInjection() { - $mockConfig = $this->createMock(Registry::class); + $mockConfig = new Registry(); $object = $this->getAbstractApplication($mockConfig); $this->assertSame( @@ -128,11 +128,7 @@ public function testExecuteWithEvents() #[TestDox('Tests that data is read from the application configuration successfully.')] public function testGet() { - $mockConfig = $this->getMockBuilder(Registry::class) - ->setConstructorArgs([['foo' => 'bar']]) - ->enableProxyingToOriginalMethods() - ->getMock(); - + $mockConfig = new Registry(['foo' => 'bar']); $object = $this->getAbstractApplication($mockConfig); $this->assertSame('bar', $object->get('foo', 'car'), 'Checks a known configuration setting is returned.'); @@ -150,10 +146,7 @@ public function testGetLogger() #[TestDox('Tests that data is set to the application configuration successfully.')] public function testSet() { - $mockConfig = $this->getMockBuilder(Registry::class) - ->enableProxyingToOriginalMethods() - ->getMock(); - + $mockConfig = new Registry(); $object = $this->getAbstractApplication($mockConfig); $this->assertNull($object->set('foo', 'car'), 'Checks set returns the previous value.'); @@ -164,7 +157,7 @@ public function testSet() public function testSetConfiguration() { $object = $this->getAbstractApplication(); - $mockConfig = $this->createMock(Registry::class); + $mockConfig = new Registry(); $this->assertSame($object, $object->setConfiguration($mockConfig), 'The setConfiguration method has a fluent interface'); @@ -178,8 +171,8 @@ public function testSetConfiguration() #[TestDox('Tests that a LoggerInterface object is correctly set to the application.')] public function testSetLogger() { - $object = $this->getAbstractApplication(); - $mockLogger = $this->createMock(LoggerInterface::class); + $object = $this->getAbstractApplication(); + $mockLogger = $this->createStub(LoggerInterface::class); $object->setLogger($mockLogger); diff --git a/Tests/AbstractWebApplicationTest.php b/Tests/AbstractWebApplicationTest.php index 0b87170e..772f8fc3 100644 --- a/Tests/AbstractWebApplicationTest.php +++ b/Tests/AbstractWebApplicationTest.php @@ -189,11 +189,9 @@ public function testConstructDependencyInjection() $_SERVER['REQUEST_URI'] = self::TEST_REQUEST_URI; $_SERVER['SCRIPT_NAME'] = self::TEST_REQUEST_URI; - $mockInput = new Input([]); - - $mockConfig = $this->createMock(Registry::class); - - $mockClient = $this->createMock(WebClient::class); + $mockInput = new Input([]); + $mockConfig = new Registry(); + $mockClient = new WebClient(); $object = $this->getAbstractWebApplication($mockInput, $mockConfig, $mockClient); @@ -316,22 +314,7 @@ public function testExecuteWithCompression() #[TestDox('Tests the \compress() method correctly compresses data with gzip encoding')] public function testCompressWithGzipEncoding() { - $mockClient = $this->getMockBuilder(WebClient::class) - ->setConstructorArgs([null, 'gzip, deflate']) - - ->getMock(); - - // Mock the client internals to show encoding has been detected. - TestHelper::setValue( - $mockClient, - 'detection', - ['acceptEncoding' => true] - ); - TestHelper::setValue( - $mockClient, - 'encodings', - ['gzip', 'deflate'] - ); + $mockClient = new WebClient(null, 'gzip, deflate'); $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([null, null, $mockClient]) @@ -380,22 +363,7 @@ public function testCompressWithGzipEncoding() #[TestDox('Tests the compress() method correctly compresses data with deflate encoding')] public function testCompressWithDeflateEncoding() { - $mockClient = $this->getMockBuilder(WebClient::class) - ->setConstructorArgs([null, 'deflate']) - - ->getMock(); - - // Mock the client internals to show encoding has been detected. - TestHelper::setValue( - $mockClient, - 'detection', - ['acceptEncoding' => true] - ); - TestHelper::setValue( - $mockClient, - 'encodings', - ['deflate', 'gzip'] - ); + $mockClient = new WebClient(null, 'deflate'); $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([null, null, $mockClient]) @@ -427,7 +395,7 @@ public function testCompressWithDeflateEncoding() // Ensure that the compressed body is shorter than the raw body. $this->assertLessThan( - \strlen($response->getBody()->getContents()), + \strlen($response->getBody()), \strlen($object->getBody()) ); @@ -444,21 +412,9 @@ public function testCompressWithDeflateEncoding() #[TestDox('Tests the \compress() method does not compress data when no encoding methods are supported')] public function testCompressWithNoAcceptEncodings() { - $mockClient = $this->getMockBuilder(WebClient::class) - - ->getMock(); - - // Mock the client internals to show encoding has been detected. - TestHelper::setValue( - $mockClient, - 'detection', - ['acceptEncoding' => true] - ); + $mockClient = new WebClient(); - $object = $this->getMockBuilder(AbstractWebApplication::class) - ->setConstructorArgs([null, null, $mockClient]) - ->onlyMethods(['checkHeadersSent', 'doExecute']) - ->getMock(); + $object = $this->getAbstractWebApplication(null, null, $mockClient); // Mock a response. $response = new TextResponse( @@ -492,22 +448,7 @@ public function testCompressWithNoAcceptEncodings() #[TestDox('Tests the \compress() method does not compress data when the response headers have already been sent')] public function testCompressWithHeadersSent() { - $mockClient = $this->getMockBuilder(WebClient::class) - ->setConstructorArgs([null, 'deflate']) - - ->getMock(); - - // Mock the client internals to show encoding has been detected. - TestHelper::setValue( - $mockClient, - 'detection', - ['acceptEncoding' => true] - ); - TestHelper::setValue( - $mockClient, - 'encodings', - ['deflate', 'gzip'] - ); + $mockClient = new WebClient(null, 'deflate'); $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([null, null, $mockClient]) @@ -550,21 +491,7 @@ public function testCompressWithHeadersSent() #[TestDox('Tests the \compress() method does not compress data when the application does not support the client\'s encoding methods')] public function testCompressWithUnsupportedEncodings() { - $mockClient = $this->getMockBuilder(WebClient::class) - - ->getMock(); - - // Mock the client internals to show encoding has been detected. - TestHelper::setValue( - $mockClient, - 'detection', - ['acceptEncoding' => true] - ); - TestHelper::setValue( - $mockClient, - 'encodings', - ['foo', 'bar'] - ); + $mockClient = new WebClient(); $object = $this->getAbstractWebApplication(null, null, $mockClient); @@ -653,25 +580,9 @@ public function testRedirectLegacyBehavior() $_SERVER['REQUEST_URI'] = self::TEST_REQUEST_URI; $_SERVER['SCRIPT_NAME'] = self::TEST_REQUEST_URI; - $mockInput = new Input([]); - - $mockConfig = $this->getMockBuilder(Registry::class) - - ->getMock(); - - $mockClient = $this->createMock(WebClient::class); - - // Mock the client internals to show engine has been detected. - TestHelper::setValue( - $mockClient, - 'detection', - ['engine' => true] - ); - TestHelper::setValue( - $mockClient, - 'engine', - WebClient::GECKO - ); + $mockInput = new Input([]); + $mockConfig = new Registry(); + $mockClient = new WebClient(); $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) @@ -716,25 +627,9 @@ public function testRedirect() $_SERVER['REQUEST_URI'] = self::TEST_REQUEST_URI; $_SERVER['SCRIPT_NAME'] = self::TEST_REQUEST_URI; - $mockInput = new Input([]); - - $mockConfig = $this->getMockBuilder(Registry::class) - - ->getMock(); - - $mockClient = $this->getMockBuilder(WebClient::class)->getMock(); - - // Mock the client internals to show engine has been detected. - TestHelper::setValue( - $mockClient, - 'detection', - ['engine' => true] - ); - TestHelper::setValue( - $mockClient, - 'engine', - WebClient::GECKO - ); + $mockInput = new Input([]); + $mockConfig = new Registry(); + $mockClient = new WebClient(); $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) @@ -778,25 +673,9 @@ public function testRedirectWithExistingStatusCode() $_SERVER['REQUEST_URI'] = self::TEST_REQUEST_URI; $_SERVER['SCRIPT_NAME'] = self::TEST_REQUEST_URI; - $mockInput = new Input([]); - - $mockConfig = $this->getMockBuilder(Registry::class) - - ->getMock(); - - $mockClient = $this->getMockBuilder(WebClient::class)->getMock(); - - // Mock the client internals to show engine has been detected. - TestHelper::setValue( - $mockClient, - 'detection', - ['engine' => true] - ); - TestHelper::setValue( - $mockClient, - 'engine', - WebClient::GECKO - ); + $mockInput = new Input([]); + $mockConfig = new Registry(); + $mockClient = new WebClient(); $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) @@ -842,25 +721,9 @@ public function testRedirectWithAdditionalHeaders() $_SERVER['REQUEST_URI'] = self::TEST_REQUEST_URI; $_SERVER['SCRIPT_NAME'] = self::TEST_REQUEST_URI; - $mockInput = new Input([]); - - $mockConfig = $this->getMockBuilder(Registry::class) - - ->getMock(); - - $mockClient = $this->getMockBuilder(WebClient::class)->getMock(); - - // Mock the client internals to show engine has been detected. - TestHelper::setValue( - $mockClient, - 'detection', - ['engine' => true] - ); - TestHelper::setValue( - $mockClient, - 'engine', - WebClient::GECKO - ); + $mockInput = new Input([]); + $mockConfig = new Registry(); + $mockClient = new WebClient(); $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) @@ -907,11 +770,8 @@ public function testRedirectWithHeadersSent() $_SERVER['REQUEST_URI'] = self::TEST_REQUEST_URI; $_SERVER['SCRIPT_NAME'] = self::TEST_REQUEST_URI; - $mockInput = new Input([]); - - $mockConfig = $this->getMockBuilder(Registry::class) - - ->getMock(); + $mockInput = new Input([]); + $mockConfig = new Registry(); $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([$mockInput, $mockConfig]) @@ -948,28 +808,9 @@ public function testRedirectWithJavascriptRedirect() $_SERVER['REQUEST_URI'] = self::TEST_REQUEST_URI; $_SERVER['SCRIPT_NAME'] = self::TEST_REQUEST_URI; - $mockInput = new Input([]); - - $mockConfig = $this->getMockBuilder(Registry::class) - - ->getMock(); - - $mockClient = $this->getMockBuilder(WebClient::class) - ->setConstructorArgs(['MSIE']) - - ->getMock(); - - // Mock the client internals to show engine has been detected. - TestHelper::setValue( - $mockClient, - 'detection', - ['engine' => true] - ); - TestHelper::setValue( - $mockClient, - 'engine', - WebClient::TRIDENT - ); + $mockInput = new Input([]); + $mockConfig = new Registry(); + $mockClient = new WebClient('MSIE'); $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) @@ -1004,25 +845,9 @@ public function testRedirectWithMoved() $_SERVER['REQUEST_URI'] = self::TEST_REQUEST_URI; $_SERVER['SCRIPT_NAME'] = self::TEST_REQUEST_URI; - $mockInput = new Input([]); - - $mockConfig = $this->getMockBuilder(Registry::class) - - ->getMock(); - - $mockClient = $this->getMockBuilder(WebClient::class)->getMock(); - - // Mock the client internals to show engine has been detected. - TestHelper::setValue( - $mockClient, - 'detection', - ['engine' => true] - ); - TestHelper::setValue( - $mockClient, - 'engine', - WebClient::GECKO - ); + $mockInput = new Input([]); + $mockConfig = new Registry(); + $mockClient = new WebClient(); $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) @@ -1072,25 +897,9 @@ public function testRedirectWithUrl(string $url, string $expected) $_SERVER['REQUEST_URI'] = self::TEST_REQUEST_URI; $_SERVER['SCRIPT_NAME'] = self::TEST_REQUEST_URI; - $mockInput = new Input([]); - - $mockConfig = $this->getMockBuilder(Registry::class) - - ->getMock(); - - $mockClient = $this->getMockBuilder(WebClient::class)->getMock(); - - // Mock the client internals to show engine has been detected. - TestHelper::setValue( - $mockClient, - 'detection', - ['engine' => true] - ); - TestHelper::setValue( - $mockClient, - 'engine', - WebClient::GECKO - ); + $mockInput = new Input([]); + $mockConfig = new Registry(); + $mockClient = new WebClient(); $object = $this->getMockBuilder(AbstractWebApplication::class) ->setConstructorArgs([$mockInput, $mockConfig, $mockClient]) @@ -1267,11 +1076,7 @@ public function testDetectRequestUri( #[TestDox('Tests the system URIs are correctly loaded when a URI is set in the application configuration')] public function testLoadSystemUrisWithSiteUriSet() { - $mockConfig = $this->getMockBuilder(Registry::class) - ->setConstructorArgs([['site_uri' => 'http://test.joomla.org/path/']]) - - ->getMock(); - + $mockConfig = new Registry(['site_uri' => 'http://test.joomla.org/path/']); $object = $this->getAbstractWebApplication(null, $mockConfig); TestHelper::invoke($object, 'loadSystemUris'); @@ -1347,13 +1152,8 @@ public function testLoadSystemUrisWithoutSiteUriWithMediaUriSet() $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; $_SERVER['SCRIPT_NAME'] = self::TEST_REQUEST_URI; - $mockInput = new Input([]); - - $mockConfig = $this->getMockBuilder(Registry::class) - ->setConstructorArgs([['media_uri' => 'http://cdn.joomla.org/media/']]) - - ->getMock(); - + $mockInput = new Input([]); + $mockConfig = new Registry(['media_uri' => 'http://cdn.joomla.org/media/']); $object = $this->getAbstractWebApplication($mockInput, $mockConfig); TestHelper::invoke($object, 'loadSystemUris', 'http://joom.la/application'); @@ -1391,13 +1191,8 @@ public function testLoadSystemUrisWithoutSiteUriWithRelativeMediaUriSet() $_SERVER['HTTP_HOST'] = self::TEST_HTTP_HOST; $_SERVER['SCRIPT_NAME'] = self::TEST_REQUEST_URI; - $mockInput = new Input([]); - - $mockConfig = $this->getMockBuilder(Registry::class) - ->setConstructorArgs([['media_uri' => '/media/']]) - - ->getMock(); - + $mockInput = new Input([]); + $mockConfig = new Registry(['media_uri' => '/media/']); $object = $this->getAbstractWebApplication($mockInput, $mockConfig); TestHelper::invoke($object, 'loadSystemUris', 'http://joom.la/application'); diff --git a/Tests/SessionAwareWebApplicationTraitTest.php b/Tests/SessionAwareWebApplicationTraitTest.php index 9bdc04b0..d0c40bad 100644 --- a/Tests/SessionAwareWebApplicationTraitTest.php +++ b/Tests/SessionAwareWebApplicationTraitTest.php @@ -55,7 +55,7 @@ public function getInput(): Input public function testSetSession() { $object = $this->getSessionAwareWebApplicationTrait(); - $mockSession = $this->createMock(SessionInterface::class); + $mockSession = $this->createStub(SessionInterface::class); $this->assertSame($object, $object->setSession($mockSession), 'The setSession method has a fluent interface.'); $this->assertSame($mockSession, $object->getSession()); @@ -76,8 +76,6 @@ public function testCheckTokenForHttpHeader() { $_SERVER['HTTP_X_CSRF_TOKEN'] = 'token'; - $mockInput = new Input([]); - $mockSession = $this->createMock(SessionInterface::class); $mockSession->expects($this->once()) ->method('getToken') @@ -100,8 +98,6 @@ public function testCheckTokenForRequestBody() { $_POST['testing'] = 'token'; - $mockInput = new Input([]); - $mockSession = $this->createMock(SessionInterface::class); $mockSession->expects($this->once()) ->method('getToken') @@ -122,8 +118,6 @@ public function testCheckTokenForRequestBody() #[TestDox('Tests checking the CSRF token fails when it does not exist in the request')] public function testCheckTokenFailsWhenNotPresent() { - $mockInput = new Input([]); - $mockSession = $this->createMock(SessionInterface::class); $mockSession->expects($this->once()) ->method('getToken') From 94862d187c75973ea5518147841acfda0a612e22 Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:41:46 +0200 Subject: [PATCH 09/17] replace any() matcher --- Tests/AbstractWebApplicationTest.php | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Tests/AbstractWebApplicationTest.php b/Tests/AbstractWebApplicationTest.php index 772f8fc3..1e8c9dd7 100644 --- a/Tests/AbstractWebApplicationTest.php +++ b/Tests/AbstractWebApplicationTest.php @@ -591,10 +591,10 @@ public function testRedirectLegacyBehavior() $object->expects($this->once()) ->method('close'); - $object->expects($this->any()) + $object->expects($this->exactly(2)) ->method('checkHeadersSent') ->willReturn(false); - $object->expects($this->any()) + $object->expects($this->exactly(7)) ->method('header') ->willReturnCallback([$this, 'mockHeader']); @@ -638,10 +638,10 @@ public function testRedirect() $object->expects($this->once()) ->method('close'); - $object->expects($this->any()) + $object->expects($this->exactly(2)) ->method('checkHeadersSent') ->willReturn(false); - $object->expects($this->any()) + $object->expects($this->exactly(7)) ->method('header') ->willReturnCallback([$this, 'mockHeader']); @@ -684,10 +684,10 @@ public function testRedirectWithExistingStatusCode() $object->expects($this->once()) ->method('close'); - $object->expects($this->any()) + $object->expects($this->exactly(2)) ->method('checkHeadersSent') ->willReturn(false); - $object->expects($this->any()) + $object->expects($this->exactly(7)) ->method('header') ->willReturnCallback([$this, 'mockHeader']); @@ -732,10 +732,10 @@ public function testRedirectWithAdditionalHeaders() $object->expects($this->once()) ->method('close'); - $object->expects($this->any()) + $object->expects($this->exactly(2)) ->method('checkHeadersSent') ->willReturn(false); - $object->expects($this->any()) + $object->expects($this->exactly(7)) ->method('header') ->willReturnCallback([$this, 'mockHeader']); @@ -781,7 +781,7 @@ public function testRedirectWithHeadersSent() $object->expects($this->once()) ->method('close') ->willReturn(true); - $object->expects($this->any()) + $object->expects($this->exactly(2)) ->method('checkHeadersSent') ->willReturn(true); @@ -819,7 +819,7 @@ public function testRedirectWithJavascriptRedirect() $object->expects($this->once()) ->method('close'); - $object->expects($this->any()) + $object->expects($this->exactly(2)) ->method('checkHeadersSent') ->willReturn(false); @@ -856,10 +856,10 @@ public function testRedirectWithMoved() $object->expects($this->once()) ->method('close'); - $object->expects($this->any()) + $object->expects($this->exactly(2)) ->method('checkHeadersSent') ->willReturn(false); - $object->expects($this->any()) + $object->expects($this->exactly(7)) ->method('header') ->willReturnCallback([$this, 'mockHeader']); @@ -908,10 +908,10 @@ public function testRedirectWithUrl(string $url, string $expected) $object->expects($this->once()) ->method('close'); - $object->expects($this->any()) + $object->expects($this->exactly(2)) ->method('checkHeadersSent') ->willReturn(false); - $object->expects($this->any()) + $object->expects($this->exactly(7)) ->method('header') ->willReturnCallback([$this, 'mockHeader']); @@ -975,10 +975,10 @@ public function testSendHeaders() ->onlyMethods(['checkHeadersSent', 'header', 'doExecute']) ->getMock(); - $object->expects($this->any()) + $object->expects($this->once()) ->method('checkHeadersSent') ->willReturn(false); - $object->expects($this->any()) + $object->expects($this->exactly(2)) ->method('header') ->willReturnCallback([$this, 'mockHeader']); From eb1c3b0423cef962e258a50b99fe4db6a8a706da Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:43:42 +0200 Subject: [PATCH 10/17] Update AbstractWebApplicationTest.php --- Tests/AbstractWebApplicationTest.php | 82 +++++++++------------------- 1 file changed, 26 insertions(+), 56 deletions(-) diff --git a/Tests/AbstractWebApplicationTest.php b/Tests/AbstractWebApplicationTest.php index 1e8c9dd7..4f97e7ad 100644 --- a/Tests/AbstractWebApplicationTest.php +++ b/Tests/AbstractWebApplicationTest.php @@ -316,15 +316,6 @@ public function testCompressWithGzipEncoding() { $mockClient = new WebClient(null, 'gzip, deflate'); - $object = $this->getMockBuilder(AbstractWebApplication::class) - ->setConstructorArgs([null, null, $mockClient]) - ->onlyMethods(['checkHeadersSent', 'doExecute']) - ->getMock(); - - $object->expects($this->once()) - ->method('checkHeadersSent') - ->willReturn(false); - // Mock a response. $response = new TextResponse( 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do @@ -336,11 +327,14 @@ public function testCompressWithGzipEncoding() ); $response = $response->withoutHeader('content-type'); - TestHelper::setValue( - $object, - 'response', - $response - ); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->setConstructorArgs([null, null, $mockClient, $response]) + ->onlyMethods(['checkHeadersSent', 'doExecute']) + ->getMock(); + + $object->expects($this->once()) + ->method('checkHeadersSent') + ->willReturn(false); TestHelper::invoke($object, 'compress'); @@ -365,15 +359,6 @@ public function testCompressWithDeflateEncoding() { $mockClient = new WebClient(null, 'deflate'); - $object = $this->getMockBuilder(AbstractWebApplication::class) - ->setConstructorArgs([null, null, $mockClient]) - ->onlyMethods(['checkHeadersSent', 'doExecute']) - ->getMock(); - - $object->expects($this->once()) - ->method('checkHeadersSent') - ->willReturn(false); - // Mock a response. $response = new TextResponse( 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do @@ -385,11 +370,14 @@ public function testCompressWithDeflateEncoding() ); $response = $response->withoutHeader('content-type'); - TestHelper::setValue( - $object, - 'response', - $response - ); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->setConstructorArgs([null, null, $mockClient, $response]) + ->onlyMethods(['checkHeadersSent', 'doExecute']) + ->getMock(); + + $object->expects($this->once()) + ->method('checkHeadersSent') + ->willReturn(false); TestHelper::invoke($object, 'compress'); @@ -414,8 +402,6 @@ public function testCompressWithNoAcceptEncodings() { $mockClient = new WebClient(); - $object = $this->getAbstractWebApplication(null, null, $mockClient); - // Mock a response. $response = new TextResponse( 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do @@ -427,11 +413,7 @@ public function testCompressWithNoAcceptEncodings() ); $response = $response->withoutHeader('content-type'); - TestHelper::setValue( - $object, - 'response', - $response - ); + $object = $this->getAbstractWebApplication(null, null, $mockClient, $response); TestHelper::invoke($object, 'compress'); @@ -450,15 +432,6 @@ public function testCompressWithHeadersSent() { $mockClient = new WebClient(null, 'deflate'); - $object = $this->getMockBuilder(AbstractWebApplication::class) - ->setConstructorArgs([null, null, $mockClient]) - ->onlyMethods(['checkHeadersSent', 'doExecute']) - ->getMock(); - - $object->expects($this->once()) - ->method('checkHeadersSent') - ->willReturn(true); - // Mock a response. $response = new TextResponse( 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do @@ -470,11 +443,14 @@ public function testCompressWithHeadersSent() ); $response = $response->withoutHeader('content-type'); - TestHelper::setValue( - $object, - 'response', - $response - ); + $object = $this->getMockBuilder(AbstractWebApplication::class) + ->setConstructorArgs([null, null, $mockClient, $response]) + ->onlyMethods(['checkHeadersSent', 'doExecute']) + ->getMock(); + + $object->expects($this->once()) + ->method('checkHeadersSent') + ->willReturn(true); TestHelper::invoke($object, 'compress'); @@ -493,8 +469,6 @@ public function testCompressWithUnsupportedEncodings() { $mockClient = new WebClient(); - $object = $this->getAbstractWebApplication(null, null, $mockClient); - // Mock a response. $response = new TextResponse( 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do @@ -506,11 +480,7 @@ public function testCompressWithUnsupportedEncodings() ); $response = $response->withoutHeader('content-type'); - TestHelper::setValue( - $object, - 'response', - $response - ); + $object = $this->getAbstractWebApplication(null, null, $mockClient, $response); TestHelper::invoke($object, 'compress'); From 5fdfd0920cadd853ab6aebbc59173d0467113d80 Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:44:01 +0200 Subject: [PATCH 11/17] better assert --- Tests/Controller/ContainerControllerResolverTest.php | 2 +- Tests/Controller/ControllerResolverTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/Controller/ContainerControllerResolverTest.php b/Tests/Controller/ContainerControllerResolverTest.php index 94416d63..7d8c908c 100644 --- a/Tests/Controller/ContainerControllerResolverTest.php +++ b/Tests/Controller/ContainerControllerResolverTest.php @@ -54,7 +54,7 @@ public function testResolvingAControllerInterface() { $callable = $this->resolver->resolve(new ResolvedRoute(Controller::class, [], '/')); - $this->assertTrue(\is_callable($callable)); + $this->assertIsCallable($callable); $this->assertInstanceOf(Controller::class, $callable[0]); } diff --git a/Tests/Controller/ControllerResolverTest.php b/Tests/Controller/ControllerResolverTest.php index cb2352f2..98ebec73 100644 --- a/Tests/Controller/ControllerResolverTest.php +++ b/Tests/Controller/ControllerResolverTest.php @@ -27,7 +27,7 @@ public function testResolvingACallableArray() { $callable = (new ControllerResolver())->resolve(new ResolvedRoute([Registry::class, 'get'], [], '/')); - $this->assertTrue(\is_callable($callable)); + $this->assertIsCallable($callable); $this->assertInstanceOf(Registry::class, $callable[0]); } @@ -70,7 +70,7 @@ public function testResolvingAControllerInterface() { $callable = (new ControllerResolver())->resolve(new ResolvedRoute(Controller::class, [], '/')); - $this->assertTrue(\is_callable($callable)); + $this->assertIsCallable($callable); $this->assertInstanceOf(Controller::class, $callable[0]); } From b2dd360bf0b62ed70e0c2c250ac4f2ecc35388e4 Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:44:39 +0200 Subject: [PATCH 12/17] unify other packages --- phpunit.xml.dist | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 18cd6a92..2ce3a57f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,14 +1,11 @@ - - - - Tests - - - - - + + + + Tests + + + + + From 4257ce03f247317f2a67c01978d5cc70e8d47c47 Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:45:48 +0200 Subject: [PATCH 13/17] allow phpunit 13 --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 9adfd28b..353596b6 100644 --- a/composer.json +++ b/composer.json @@ -52,8 +52,8 @@ "joomla/session": "^4.0", "joomla/test": "^4.0", "joomla/uri": "^4.0", - "phpunit/phpunit": "^12.2.7", - "symfony/phpunit-bridge": "^7.0", + "phpunit/phpunit": "^12.5 || ^13.0", + "symfony/phpunit-bridge": "^7.0 || ^8.0", "squizlabs/php_codesniffer": "~3.10.2", "phpstan/phpstan": "^2.1.17", "phpstan/phpstan-deprecation-rules": "^2.0.3" From 0b973fa33c140debcb3b79d1b00ef79002d78d28 Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:50:53 +0200 Subject: [PATCH 14/17] fix squizlabs/php_codesniffer security https://packagist.org/security-advisories/PKSA-rdkp-vv9z-mjkg --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 353596b6..eeea4ace 100644 --- a/composer.json +++ b/composer.json @@ -54,7 +54,7 @@ "joomla/uri": "^4.0", "phpunit/phpunit": "^12.5 || ^13.0", "symfony/phpunit-bridge": "^7.0 || ^8.0", - "squizlabs/php_codesniffer": "~3.10.2", + "squizlabs/php_codesniffer": "^3.10.2", "phpstan/phpstan": "^2.1.17", "phpstan/phpstan-deprecation-rules": "^2.0.3" }, From ef830744ff8063543b3af65baf822a2b6c973c8c Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Mon, 10 Aug 2026 17:50:47 +0200 Subject: [PATCH 15/17] missed --- Tests/WebApplicationTest.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Tests/WebApplicationTest.php b/Tests/WebApplicationTest.php index 653629c4..5eb799b0 100644 --- a/Tests/WebApplicationTest.php +++ b/Tests/WebApplicationTest.php @@ -7,7 +7,10 @@ namespace Joomla\Application\Tests; +use Joomla\Application\AbstractApplication; +use Joomla\Application\AbstractWebApplication; use Joomla\Application\Controller\ControllerResolverInterface; +use Joomla\Application\Web\WebClient; use Joomla\Application\WebApplication; use Joomla\Input\Input; use Joomla\Router\ResolvedRoute; @@ -23,9 +26,9 @@ */ #[CoversClass(WebApplication::class)] #[BackupGlobals(true)] -#[UsesClass('\Joomla\Application\AbstractApplication')] -#[UsesClass('\Joomla\Application\AbstractWebApplication')] -#[UsesClass('\Joomla\Application\Web\WebClient')] +#[UsesClass(AbstractApplication::class)] +#[UsesClass(AbstractWebApplication::class)] +#[UsesClass(WebClient::class)] class WebApplicationTest extends TestCase { #[TestDox('Tests that the application is executed successfully.')] From d69b43363c0d81f11f72fd549e4a4807172d6d77 Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Mon, 10 Aug 2026 20:45:35 +0200 Subject: [PATCH 16/17] codestyle --- Tests/AbstractApplicationTest.php | 3 +-- Tests/AbstractWebApplicationTest.php | 3 +-- Tests/SessionAwareWebApplicationTraitTest.php | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Tests/AbstractApplicationTest.php b/Tests/AbstractApplicationTest.php index a3114ccb..41991efc 100644 --- a/Tests/AbstractApplicationTest.php +++ b/Tests/AbstractApplicationTest.php @@ -40,8 +40,7 @@ class AbstractApplicationTest extends TestCase */ private function getAbstractApplication(...$args): AbstractApplication { - return new class (...$args) extends AbstractApplication - { + return new class (...$args) extends AbstractApplication { protected function doExecute() { } diff --git a/Tests/AbstractWebApplicationTest.php b/Tests/AbstractWebApplicationTest.php index 4f97e7ad..abca9e5c 100644 --- a/Tests/AbstractWebApplicationTest.php +++ b/Tests/AbstractWebApplicationTest.php @@ -85,8 +85,7 @@ protected function tearDown(): void */ private function getAbstractWebApplication(...$args): AbstractWebApplication { - return new class (...$args) extends AbstractWebApplication - { + return new class (...$args) extends AbstractWebApplication { protected function doExecute() { } diff --git a/Tests/SessionAwareWebApplicationTraitTest.php b/Tests/SessionAwareWebApplicationTraitTest.php index d0c40bad..569b5b03 100644 --- a/Tests/SessionAwareWebApplicationTraitTest.php +++ b/Tests/SessionAwareWebApplicationTraitTest.php @@ -40,8 +40,7 @@ class SessionAwareWebApplicationTraitTest extends TestCase */ private function getSessionAwareWebApplicationTrait() { - return new class () - { + return new class () { use SessionAwareWebApplicationTrait; public function getInput(): Input From d2f871a1bca1b2968d3dcad8fda3bd6408392238 Mon Sep 17 00:00:00 2001 From: Christian Heel <66922325+heelc29@users.noreply.github.com> Date: Mon, 10 Aug 2026 20:46:06 +0200 Subject: [PATCH 17/17] ordered_attributes --- Tests/Web/WebClientTest.php | 2 +- Tests/WebApplicationTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Web/WebClientTest.php b/Tests/Web/WebClientTest.php index 0f252b78..8dab5f61 100644 --- a/Tests/Web/WebClientTest.php +++ b/Tests/Web/WebClientTest.php @@ -18,8 +18,8 @@ * * @since 1.0.0 */ -#[CoversClass(WebClient::class)] #[BackupGlobals(true)] +#[CoversClass(WebClient::class)] class WebClientTest extends TestCase { /** diff --git a/Tests/WebApplicationTest.php b/Tests/WebApplicationTest.php index 5eb799b0..f88f11ac 100644 --- a/Tests/WebApplicationTest.php +++ b/Tests/WebApplicationTest.php @@ -24,8 +24,8 @@ /** * Test class for Joomla\Application\WebApplication. */ -#[CoversClass(WebApplication::class)] #[BackupGlobals(true)] +#[CoversClass(WebApplication::class)] #[UsesClass(AbstractApplication::class)] #[UsesClass(AbstractWebApplication::class)] #[UsesClass(WebClient::class)]