Files
core/tests/unit/Module/TestCase.php
Harald Eilertsen d85c737db7 tests: Add ajax request helper to module test case
This is a bit crude, but serves the purpose for now. To emulate an AJAX
request we set the `Content-Type` header to `application/json`, and json
encode the params in the body of the request.
2026-01-26 23:03:07 +01:00

243 lines
6.6 KiB
PHP

<?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(array $args): void {
// string $uri, array $query = [], array $params = []): void {
$_GET['q'] = $args['uri'];
$_GET = array_merge($_GET, $args['query'] ?? []);
$_POST = $args['post_params'] ?? [];
$_SERVER['REQUEST_METHOD'] = $args['method'];
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
$_SERVER['QUERY_STRING'] = "q={$args['uri']}";
$_SERVER['REQUEST_URI'] = $args['uri'];
$_SERVER['HTTP_CONTENT_TYPE'] = $args['content_type'] ?? 'text/html';
$_SERVER['HTTP_CONTENT_LENGTH'] = strlen($args['body'] ?? 0);
if (!empty($args['body'])) {
$_SERVER['HTTP_POST_BODY'] = $args['body'];
}
// 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();
}
protected function ajax_request(string $method, string $uri, array $params): void {
$this->do_request([
'method' => $method,
'uri' => $uri,
'content_type' => 'application/json',
'body' => json_encode($params),
]);
}
/**
* 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([
'method' => 'GET',
'uri' => $uri,
'query' => $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([
'method' => 'POST',
'uri' => $uri,
'query' => $query,
'post_params' => $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);
}
}