aboutsummaryrefslogblamecommitdiffstats
path: root/tests/unit/Module/TestCase.php
blob: 1a4cf52fcc9658281717b8ab20207f38b63e108d (plain) (tree)
1
2
3
4
5
6
7
8
9
     







                                                           


                                    
                                       










                                                                    



                                                 


                               




                                               
 



                                                                                                                 
 
                                                     
                                                         
                                                      
                                                                             
                                                       
                                








                                                    

























                                                                                                            




                                                                      
                                                                                  


           

                                          
                                                                       



                                                                              


























                                                                                  

                                                
                                                                                       







                                                                    



































                                                                                             
                                                
                                                                                       






                                                                          
 









                                                                           




                                                                        









                                           

                                                                      





                                            
<?php
/**
 * This file contains the base class for module test cases.
 *
 * SPDX-FileCopyrightText: 2024 Hubzilla Community
 * SPDX-FileContributor: Harald Eilertsen
 *
 * SPDX-License-Identifier: MIT
 */

namespace Zotlabs\Tests\Unit\Module;

use PHPUnit\Framework\Attributes\After;
use Zotlabs\Tests\Unit\UnitTestCase;
use App;

/**
 * Base class for writing module tests.
 *
 * This test class adds a number of helper methods to the base from
 * the UnitTestCase class, useful when testing Modules (Controllers)
 * that handle incoming requests.
 */
class TestCase extends UnitTestCase {

	// Import PHPMock methods into this class
	use \phpmock\phpunit\PHPMock;

	protected $killme_stub;
	protected $goaway_stub;

	#[After]
	public function cleanup_stubs(): void {
		$this->killme_stub = null;
		$this->goaway_stub = null;
	}

	protected function do_request(string $method, string $uri, array $query = [], array $params = []): void {
		$_GET['q'] = $uri;
		$_GET = array_merge($_GET, $query);
		$_POST = $params;

		$_SERVER['REQUEST_METHOD'] = $method;
		$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
		$_SERVER['QUERY_STRING'] = "q={$uri}";
		// phpcs:disable Generic.PHP.DisallowRequestSuperglobal.Found
		$_REQUEST = array_merge($_GET, $_POST);
		// phpcs::enable

		\App::init();
		\App::$page['content'] = '';

		$router = new \Zotlabs\Web\Router();
		$router->Dispatch();
	}

	/**
	 * Emulate a GET request.
	 *
	 * @param string $uri	The URI to request. Typically this will be the module
	 *						name, followed by any req args separated by slashes.
	 * @param array $query	Assciative array of query args, with the parameters
	 *						as keys.
	 */
	protected function get(string $uri, array $query = []): void {
		$this->do_request('GET', $uri, $query);
	}

	/**
	 * Emulate a POST request.
	 *
	 * @param string $uri	The URI to request. Typically this will be the module
	 *						name, followed by any req args separated by slashes.
	 * @param array $query	Associative array of query args, with the parameters
	 *						as keys.
	 * @param array $params	Associative array of POST params, with the param names
	 *						as keys.
	 */
	protected function post(string $uri, array $query = [], array $params = []): void {
		$this->do_request('POST', $uri, $query, $params);
	}

	/**
	 * Helper to simplify asserting contents in the rendered page.
	 *
	 * @param string $needle	The expected string to find.
	 */
	protected function assertPageContains(string $needle): void {
		$this->assertStringContainsString($needle, App::$page['content']);
	}

	/**
	 * Stub out the `killme` function.
	 *
	 * Useful for testing modules that call this function directly.
	 *
	 * Instead of calling exit, the stub will throw a `KillmeException`,
	 * that can be caught by the test code to regain control after request
	 * processing is terminated.
	 *
	 * **Example:**
	 *
	 *     public function test_something(): void {
	 *         $this->stub_killme();
	 *
	 *         try {
	 *             killme();
	 *         } catch (KillmeException $e) {
	 *             $this->assertSomething(...);
	 *         }
	 *     }
	 *
	 * It's also possible to use the builting PHPUnit expecations to verify
	 * that the function was called.
	 *
	 *     public function test_something(): void {
	 *         $this->stub_killme();
	 *         $this->expectException(KillmeException::class);
	 *
	 *         killme();
	 *     }
	 *
	 * This is useful if you only want to check that processing was terminated
	 * with the `killme()` function.
	 *
	 * @throws KillmeException
	 */
	protected function stub_killme(): void {
		$this->killme_stub = $this->getFunctionMock('Zotlabs\Module', 'killme')
			->expects($this->once())
			->willReturnCallback(
				function () {
					throw new KillmeException();
				}
			);
	}

	/**
	 * Stub out the `goaway` function.
	 *
	 * Useful for testing modules that calls this function directly.
	 *
	 * Instead of calling `killme()`, the stub will throw a RedirectException
	 * with the target URL as the exception message. This allows the test code
	 * to regain control after request processing is terminated.
	 *
	 * **Example:**
	 *
	 *     public function test_redirect(): void {
	 *         $this->stub_goaway();
	 *
	 *         try {
	 *             goaway('https://example.com/some_uri');
	 *         } catch (RedirectException $e) {
	 *             $this->assertEquals('https://example.com/some_uri', $e->getMessage());
	 *             $this->assertSomethingElse(...);
	 *         }
	 *     }
	 * It's also possible to use the builting PHPUnit expecations to verify
	 * that the function was called.
	 *
	 *     public function test_something(): void {
	 *         $this->stub_goaway();
	 *         $this->expectException(RedirectException::class);
	 *         $this->expectExceptionMessage('https://example.com/some_uri');
	 *
	 *         goaway('https://example.com/some_uri');
	 *     }
	 *
	 * This is useful if you only want to check that the request was redirected.
	 *
	 * @throws RedirectException
	 */
	protected function stub_goaway(): void {
		$this->goaway_stub = $this->getFunctionMock('Zotlabs\Module', 'goaway')
			->expects($this->once())
			->willReturnCallback(
				function (string $uri) {
					throw new RedirectException($uri);
				}
			);
	}

	/**
	 * Shorthand function to expect a redirect to a given URL.
	 *
	 * **Example:**
	 *
	 *     public function test_redirect(): void {
	 *         $this->expectRedirectTo('https://example.com/some_uri');
	 *         goaway('https://example.com/some_uri');
	 *     }
	 */
	protected function expectRedirectTo(string $destination): void {
		$this->stub_goaway();
		$this->expectException(RedirectException::class);
		$this->expectExceptionMessage($destination);
	}
}

/**
 * Exception class for killme stub
 */
class KillmeException extends \Exception {}

/**
 * Exception class for goaway stub.
 *
 * Takes the goaway uri as an arg, and makes it available to the catch
 * site via the `getMessage()` method.
 */
class RedirectException extends \Exception {
	function __construct(string $uri) {
		parent::__construct($uri);
	}
}