From 0dc959d9fe40bddce5e99b8162bb0e770fc28ed9 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Sun, 24 Mar 2024 09:58:21 +0000 Subject: Deprecate *_config() functions in core. --- tests/unit/Photo/PhotoGdTest.php | 17 ++--------------- tests/unit/Web/HttpSigTest.php | 5 ++--- 2 files changed, 4 insertions(+), 18 deletions(-) (limited to 'tests/unit') diff --git a/tests/unit/Photo/PhotoGdTest.php b/tests/unit/Photo/PhotoGdTest.php index 1324043c4..7ef07864c 100644 --- a/tests/unit/Photo/PhotoGdTest.php +++ b/tests/unit/Photo/PhotoGdTest.php @@ -130,21 +130,8 @@ class PhotoGdTest extends UnitTestCase { * Tests PhotoGd->imageString() */ public function testImagestringReturnsABinaryString() { - // Create a stub for global function get_config() - // get_config('system', 'png_quality') - // get_config('system', 'jpeg_quality'); - $gc = $this->getFunctionMock('Zotlabs\Photo', 'get_config'); - $gc->expects($this->once())->willReturnCallback( - function() { - switch($this->photoGd->getType()){ - case 'image/png': - return 7; - case 'image/jpeg': - default: - return 70; - } - } - ); + // Init config with a known value for the test + \Zotlabs\Lib\Config::Set('system', 'png_quality', 7); $this->assertIsString($this->photoGd->imageString()); } diff --git a/tests/unit/Web/HttpSigTest.php b/tests/unit/Web/HttpSigTest.php index 0a22b543a..c01e4f6a3 100644 --- a/tests/unit/Web/HttpSigTest.php +++ b/tests/unit/Web/HttpSigTest.php @@ -84,9 +84,8 @@ class HttpSigTest extends UnitTestCase { } function testDecrypt_sigheaderUseSitePrivateKey() { - // Create a stub for global function get_config() with expectation - $t = $this->getFunctionMock('Zotlabs\Web', 'get_config'); - $t->expects($this->once())->willReturn('system.prvkey'); + // Initialize config with a known value for test + \Zotlabs\Lib\Config::Set('system', 'prvkey', 'system.prvkey'); $header = 'Header: iv="value_iv" key="value_key" alg="value_alg" data="value_data"'; $result = [ -- cgit v1.2.3 From 3c0d6339bb12bd7fbf65ba7a79078e39737b4387 Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 24 Mar 2024 17:50:27 +0100 Subject: make sure we preserve linefeeds in the actual content of lists and tables also add tests --- tests/unit/includes/BBCodeTest.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'tests/unit') diff --git a/tests/unit/includes/BBCodeTest.php b/tests/unit/includes/BBCodeTest.php index fedd2df06..a6c798992 100644 --- a/tests/unit/includes/BBCodeTest.php +++ b/tests/unit/includes/BBCodeTest.php @@ -111,13 +111,25 @@ class BBCodeTest extends UnitTestCase { "some text\n[list]\n[*] item1\n[*] item2\n[/list]\nsome more text", 'some text
some more text' ], + 'list with linebreaks \n in text' => [ + "some text\n[list]\n[*] item1\nsome text[*] item2\nsome text[/list]\nsome more text", + 'some text
some more text' + ], 'list with linebreaks \r' => [ "some text\r[list]\r[*] item1\r[*] item2\r[/list]\rsome more text", 'some text
some more text' ], + 'list with linebreaks \r in text' => [ + "some text\r[list]\r[*] item1\rsome text\r[*] item2\rsome text\r[/list]\rsome more text", + 'some text
some more text' + ], 'list with linebreaks \r\n' => [ "some text\r\n[list]\r\n[*] item1\r\n[*] item2\r\n[/list]\r\nsome more text", 'some text
some more text' + ], + 'list with linebreaks \r\n in text' => [ + "some text\r\n[list]\r\n[*] item1\r\nsome text[*] item2\r\nsome text[/list]\r\nsome more text", + 'some text
some more text' ] ]; } -- cgit v1.2.3 From 53354a19304c932beea484e387d2c9536786e258 Mon Sep 17 00:00:00 2001 From: Mario Date: Mon, 25 Mar 2024 21:42:50 +0100 Subject: more remove additional linebreaks after block element plus test --- tests/unit/includes/BBCodeTest.php | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tests/unit') diff --git a/tests/unit/includes/BBCodeTest.php b/tests/unit/includes/BBCodeTest.php index a6c798992..a8aa8ee2b 100644 --- a/tests/unit/includes/BBCodeTest.php +++ b/tests/unit/includes/BBCodeTest.php @@ -107,6 +107,10 @@ class BBCodeTest extends UnitTestCase { "[code]\ntestvar = \"this is a test\"\necho \"the message is \$testvar\"\n[/code]", '
testvar = "this is a test"
echo "the message is $testvar"
', ], + 'code block with surroundin linebreaks \n' => [ + "some text\n[code]\ntestvar = \"this is a test\"\necho \"the message is \$testvar\"\n[/code]\nsome more text", + 'some text
testvar = "this is a test"
echo "the message is $testvar"
some more text', + ], 'list with linebreaks \n' => [ "some text\n[list]\n[*] item1\n[*] item2\n[/list]\nsome more text", 'some text
  • item1
  • item2
some more text' -- cgit v1.2.3 From 7c34a3676d294c9a1acc69f71ab3061074509160 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Tue, 30 Apr 2024 06:59:19 +0000 Subject: Rework Help module + begin tests for Setup module --- tests/unit/Module/HelpTest.php | 188 +++++++++++++++++++++++++++++++++++ tests/unit/Module/SetupTest.php | 74 ++++++++++++++ tests/unit/Module/TestCase.php | 74 ++++++++++++++ tests/unit/Widget/HelpindexTest.php | 80 +++++++++++++++ tests/unit/includes/LanguageTest.php | 48 --------- 5 files changed, 416 insertions(+), 48 deletions(-) create mode 100644 tests/unit/Module/HelpTest.php create mode 100644 tests/unit/Module/SetupTest.php create mode 100644 tests/unit/Module/TestCase.php create mode 100644 tests/unit/Widget/HelpindexTest.php (limited to 'tests/unit') diff --git a/tests/unit/Module/HelpTest.php b/tests/unit/Module/HelpTest.php new file mode 100644 index 000000000..0f1610db5 --- /dev/null +++ b/tests/unit/Module/HelpTest.php @@ -0,0 +1,188 @@ +getFunctionMock('Zotlabs\Lib\Traits', 'file_exists'); + $fe_stub + ->expects($this->any()) + ->willReturnCallback( + fn (string $path) => $path === "doc/en/about/help_topic.{$ext}" + ); + + // Use a value map to make the `file_get_contents` stub return the + // correct content for the file types. + $file_content_map = [ + [ 'doc/en/about/help_topic.md', "### Help heading\n\$Projectname help content" ], + [ 'doc/en/about/help_topic.bb', "[h3]Help heading[/h3]\n\n\$Projectname help content" ], + [ 'doc/en/about/help_topic.html', "

Help heading

\$Projectname help content

" ], + ]; + + // Stub `file_get_contents` to plant our own content. + $fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents'); + $fgc_stub + ->expects($this->once()) + ->willReturn($this->returnValueMap($file_content_map)); + + + $this->get("help/about/help_topic"); + + // Check that markdown content was correctly rendered + $this->assertPageContains('

Help heading

'); + + // Check that `$Projectname` has been translated properly + $this->assertPageContains('Hubzilla help content'); + + // Check that heading has been set + $this->assertPageContains('Hubzilla Documentation: About'); + + // Check that page title has been set + $this->assertTrue(isset(\App::$page['title']), 'Page title not set'); + $this->assertStringContainsString('Help', \App::$page['title']); + $this->assertStringContainsStringIgnoringCase('Help Topic', \App::$page['title']); + + // Check that nav selection has been set + $this->assertTrue(isset(\App::$nav_sel['raw_name']), 'Nav selection raw name not set'); + $this->assertEquals('Help', \App::$nav_sel['raw_name']); + + $this->assertTrue(isset(\App::$nav_sel['name']), 'Navselection name not set'); + $this->assertEquals('Help', \App::$nav_sel['name']); + } + + public function test_get_request_should_return_404_when_help_file_does_not_exist(): void { + // Stub file exists, to only retur true for the file with the current + // extension + $fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists'); + $fe_stub + ->expects($this->any()) + ->willReturn(false); + + // Make sure `file_get_contents` is never called by the code. + $fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents'); + $fgc_stub->expects($this->never()); + + $this->get("help/this_topic_does_not_exist"); + + $this->assertPageContains('not found'); + } + + public function test_get_request_without_args_redirects_to_about_page(): void { + $this->stub_goaway(); + $this->expectException(\Zotlabs\Tests\Unit\Module\RedirectException::class); + $this->expectExceptionMessage('about/about'); + + $this->get('help'); + } + + public function test_find_help_file_returns_first_match(): void { + // Stub file exists, to always return true + $fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists'); + $fe_stub + ->expects($this->once()) + ->willReturn(true); + + // Stub `file_get_contents` to plant our own content. + $fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents'); + $fgc_stub + ->expects($this->once()) + ->with('doc/en/first.md') + ->willReturn('found'); + + $this->get('help/first'); + } + + public function test_includes(): void { + // Stub `file_get_contents` to plant our own content. + $fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents'); + $fgc_stub + ->expects($this->any()) + ->willReturnCallback( + function (string $path): string { + if ($path === 'doc/en/sub.md') { + return "### This is the included file."; + } else { + return "### Main topic\n\n#include doc/en/sub.md;"; + } + } + ); + + // Stub file exists, to always return true + $fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists'); + $fe_stub + ->expects($this->any()) + ->willReturn(true); + + $this->get('help/main'); + + $this->assertPageContains('

This is the included file.

'); + } + + public function test_include_file_of_different_type_than_main_file(): void { + // Stub `file_get_contents` to plant our own content. + $fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents'); + $fgc_stub + ->expects($this->any()) + ->willReturnCallback( + function (string $path): string { + if ($path === 'doc/en/sub.md') { + return "### This is the included file."; + } else { + return "[h3]Main topic[/h3]\n\n#include doc/en/sub.md;"; + } + } + ); + + // Stub file exists, only return true for main.bb and sub.md + $fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists'); + $fe_stub + ->expects($this->any()) + ->willReturnCallback( + fn (string $path) => ( + $path === 'doc/en/main.bb' || $path === 'doc/en/sub.md' + ) + ); + + $this->get('help/main'); + + $this->assertPageContains('

This is the included file.

'); + } + + /** + * Helper to simplify asserting contents in the rendered page. + * + * @param string $needle The expected string to find. + */ + private function assertPageContains(string $needle): void { + $this->assertStringContainsString($needle, \App::$page['content']); + } +} diff --git a/tests/unit/Module/SetupTest.php b/tests/unit/Module/SetupTest.php new file mode 100644 index 000000000..96a5ef932 --- /dev/null +++ b/tests/unit/Module/SetupTest.php @@ -0,0 +1,74 @@ +with_no_accounts_in_db(); + $this->get('setup'); + + $this->assertEquals('setup', \App::$page['page_title']); + + // Assert that result _don't_ match "Permission denied" + $this->assertThat( + \App::$page['content'], + $this->logicalNot( + $this->matchesRegularExpression('/Permission denied/') + ) + ); + } + + public function test_that_setup_is_not_available_if_accounts_in_db(): void { + // The fixtures loaded by default add a couple of accounts. + $this->get('setup'); + + $this->assertEquals('setup', \App::$page['page_title']); + $this->assertMatchesRegularExpression('/Permission denied/', \App::$page['content']); + } + + public function test_that_setup_testrewrite_returns_ok(): void { + // We need to stub the `killme` function, as it is called directly from + // the code under test. + $this->stub_killme(); + + $output = ''; + + // Turn on output buffering, as code under test echoes + // directly to the output + ob_start(); + try { + $this->get('setup/testrewrite'); + } catch (\Zotlabs\Tests\Unit\Module\KillmeException) { + $output = ob_get_contents(); + } + + $this->assertEquals('ok', $output); + + ob_end_clean(); + } + + /** + * Delete all accounts from the database. + * + * This is currently needed because we automatically import the database + * fixtures on test start, which contains a couple of accounts already. + */ + private function with_no_accounts_in_db(): void { + q('DELETE FROM account;'); + } +} diff --git a/tests/unit/Module/TestCase.php b/tests/unit/Module/TestCase.php new file mode 100644 index 000000000..aa09e0596 --- /dev/null +++ b/tests/unit/Module/TestCase.php @@ -0,0 +1,74 @@ +Dispatch(); + } + + /** + * Stub out the `killme` function. + * + * Usefule for 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. + */ + protected function stub_killme(): void { + $killme_stub = $this->getFunctionMock('Zotlabs\Module', 'killme'); + $killme_stub + ->expects($this->once()) + ->willReturnCallback( + function () { + throw new KillmeException(); + } + ); + } + + protected function stub_goaway(): void { + $goaway_stub = $this->getFunctionMock('Zotlabs\Module', 'goaway'); + $goaway_stub + ->expects($this->once()) + ->willReturnCallback( + function (string $uri) { + throw new RedirectException($uri); + } + ); + } +} + +/** + * 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 as + * the public `$uri` member variable. + */ +class RedirectException extends \Exception { + function __construct(string $uri) { + parent::__construct($uri); + } +} diff --git a/tests/unit/Widget/HelpindexTest.php b/tests/unit/Widget/HelpindexTest.php new file mode 100644 index 000000000..a8b51172b --- /dev/null +++ b/tests/unit/Widget/HelpindexTest.php @@ -0,0 +1,80 @@ +getFunctionMock('Zotlabs\Widget', 'file_get_contents'); + $fgc_stub + ->expects($this->once()) + ->with($this->equalTo('doc/en/toc.html')) + ->willReturn('toc'); + + // Stub `file_exists` to only return true for the english toc file + $fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists'); + $fe_stub + ->expects($this->any()) + ->willReturnCallback(fn (string $path) => $path === 'doc/en/toc.html' ); + + $this->render_widget(); + $this->assertOutputContains('toc'); + $this->assertOutputContains('Help Content'); + } + + public function test_that_result_is_empty_when_toc_not_present(): void { + // Ensure `file_get_contents` is not called during the test. + $fgc_stub = $this->getFunctionMock('Zotlabs\Widget', 'file_get_contents'); + $fgc_stub->expects($this->never()); + + // Stub `file_exists` to always return false to simulate that we + // can't find the toc file. + $fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists'); + $fe_stub + ->expects($this->any()) + ->willReturn(false); + + $this->render_widget(); + } + + /** + * Initializes the app and calls the widget code. + */ + private function render_widget(): void { + $_GET['q'] = 'help/en/about/about'; + $_SERVER['REQUEST_METHOD'] = 'GET'; + + \App::init(); + + $widget = new \Zotlabs\Widget\Helpindex(); + $this->output = $widget->widget([]); + } + + private function assertOutputContains(string $needle): void { + $this->assertStringContainsString($needle, $this->output); + } +} diff --git a/tests/unit/includes/LanguageTest.php b/tests/unit/includes/LanguageTest.php index 9525c783d..3367232f3 100644 --- a/tests/unit/includes/LanguageTest.php +++ b/tests/unit/includes/LanguageTest.php @@ -33,54 +33,6 @@ use Text_LanguageDetect; * @author Klaus Weidenbach */ class LanguageTest extends UnitTestCase { - //use PHPMock; - - /** - * @dataProvider languageExamplesProvider - * @coversNothing - */ - public function testDetectLanguage($text, $langCode, $confidence) { - - // php-mock can not mock global functions which is called by a global function. - // If the calling function is in a namespace it would work. - //$gc = $this->getFunctionMock(__NAMESPACE__, 'get_config'); - //$gc->expects($this->once())->willReturn(10) - //$cg = $this->getFunctionMock('Zotlabs\Lib\Config', 'Get'); - //$cg->expects($this->once())->willReturn(10); - //$this->assertEquals($langCode, detect_language($text)); - - - // Can not unit test detect_language(), therefore test the used library - // only for now to find regressions on library updates. - $l = new Text_LanguageDetect; - // return 2-letter ISO 639-1 (en) language code - $l->setNameMode(2); - $lng = $l->detectConfidence($text); - - $this->assertEquals($langCode, $lng['language']); - $this->assertEquals($confidence, round($lng['confidence'], 6)); - } - - public function languageExamplesProvider() { - return [ - 'English' => [ - 'English is a West Germanic language that was first spoken in early medieval England and is now a global lingua franca.[4][5] Named after the Angles, one of the Germanic tribes that migrated to England, it ultimately derives its name from the Anglia (Angeln) peninsula in the Baltic Sea. It is closely related to the Frisian languages, but its vocabulary has been significantly influenced by other Germanic languages, particularly Norse (a North Germanic language), as well as by Latin and Romance languages, especially French.', - 'en', - 0.078422 - ], - 'German' => [ - 'Deutschland ist ein Bundesstaat in Mitteleuropa. Er besteht aus 16 Ländern und ist als freiheitlich-demokratischer und sozialer Rechtsstaat verfasst. Die Bundesrepublik Deutschland stellt die jüngste Ausprägung des deutschen Nationalstaates dar. Mit rund 82,8 Millionen Einwohnern (31. Dezember 2016) zählt Deutschland zu den dicht besiedelten Flächenstaaten.', - 'de', - 0.134339 - ], - 'Norwegian' => [ - 'Kongeriket Norge er et nordisk, europeisk land og en selvstendig stat vest på Den skandinaviske halvøy. Landet er langt og smalt, og kysten strekker seg langs Nord-Atlanteren, hvor også Norges kjente fjorder befinner seg. Totalt dekker det relativt tynt befolkede landet 385 000 kvadratkilometer med litt over fem millioner innbyggere (2016).', - 'no', - 0.007076 - ] - ]; - } - /** * @covers ::get_language_name -- cgit v1.2.3 From 4d29cffde511a7af0be8057b5f0a680285bc8f4b Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Tue, 27 Feb 2024 11:06:49 +0100 Subject: Improve docs for UnitTestCase class. --- tests/unit/UnitTestCase.php | 65 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 11 deletions(-) (limited to 'tests/unit') diff --git a/tests/unit/UnitTestCase.php b/tests/unit/UnitTestCase.php index a4ea94b13..9ab6a534a 100644 --- a/tests/unit/UnitTestCase.php +++ b/tests/unit/UnitTestCase.php @@ -33,29 +33,30 @@ require_once __DIR__ . '/../../boot.php'; require_once 'include/dba/dba_driver.php' ; /** - * @brief Base class for our Unit Tests. + * Base class for our Unit Tests. * - * Empty class at the moment, but you should extend this class for unit test - * cases, so we could and for sure we will need to implement basic behaviour - * for all of our unit tests. + * Base class for Hubzilla unit/integration tests. This extends the base + * TestCase class from PHPUnit by connecting to a test database, and making the + * database connection available to the code under test via the normal Hubzilla + * mechanisms, i.e the \DBA::$dba global variable. * - * @author Klaus Weidenbach + * It also automatically loads database fixtures from yaml files in the + * tests/unit/includes/dba/_files directory. And wraps each test run in it's + * own database transaction. */ class UnitTestCase extends TestCase { protected array $fixtures = array(); /** - * Override the PHPUnit\Framework\TestCase::run method, so we can - * wrap it in a database transaction. + * Override the run method, so we can wrap it in a database transaction. + * + * The transaction is automatically rolled back when the test completes, to + * leave the test database in a known pristine state. * * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ public function run(TestResult $result = null): TestResult { - // $myclass = get_class($this); - // logger("[*] Running test: {$myclass}::{$this->getName(true)}", LOGGER_DEBUG); - if (! \DBA::$dba) { - //logger('[*] Connecting to test db...'); $this->connect_to_test_db(); } @@ -74,6 +75,22 @@ class UnitTestCase extends TestCase { return $result; } + /** + * Connect to the test database, + * + * By default it will connect to a MySQL database with the following settings: + * + * - HZ_TEST_DB_HOST: db + * - HZ_TEST_DB_PORT: default + * - HZ_TEST_DB_USER: test_user + * - HZ_TEST_DB_PASS: hubzilla + * - HZ_TEST_DB_DATABASE: hubzilla_test_db + * - HZ_TEST_DB_TYPE: mysql (can also be "postgres") + * - HZ_TEST_DB_CHARSET: UTF8 + * + * All of these settings can be overridden by the test runner by setting ENV vars + * named as above with the values you want to override. + */ protected function connect_to_test_db() : void { if ( !\DBA::$dba ) { \DBA::dba_factory( @@ -101,6 +118,14 @@ class UnitTestCase extends TestCase { } } + /** + * Return the database type from a string. + * + * @param string $type The database type, can be either mysql or postgres. + * + * @return The database type constant matching the passed in type, or DBTYPE_MYSQL + * if $type is empty or invalid. + */ private static function dbtype(string $type): int { if (trim(strtolower($type)) === 'postgres') { return DBTYPE_POSTGRES; @@ -109,6 +134,9 @@ class UnitTestCase extends TestCase { } } + /** + * Load database fixtures from the fixture path. + */ private function loadFixtures() : void { $files = glob(__DIR__ . '/includes/dba/_files/*.yml'); if ($files === false || empty($files)) { @@ -117,6 +145,21 @@ class UnitTestCase extends TestCase { array_walk($files, fn($file) => $this->loadFixture($file)); } + /** + * Load database fixtures from a specific file. + * + * The file must be a yaml file named the same as the table in the database + * it should populate. + * + * The file also need to have a root key with the same name as the table. + * Under which it contains an array of rows that should be inserted into + * the db table. + * + * @param string $file The path and filename of the fixture to load. + * The path name is relative to the current working + * directory of the process, which should normally + * be the Hubzilla root directory. + */ private function loadFixture($file) : void { $table_name = basename($file, '.yml'); $this->fixtures[$table_name] = yaml_parse_file($file)[$table_name]; -- cgit v1.2.3 From 630cecd740762cc6111468b46644fcae85a360b3 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Tue, 5 Mar 2024 20:52:16 +0100 Subject: Libzot: get_rpost_path was broken for URL's with no port. --- tests/unit/Lib/ZotlibTest.php | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/unit/Lib/ZotlibTest.php (limited to 'tests/unit') diff --git a/tests/unit/Lib/ZotlibTest.php b/tests/unit/Lib/ZotlibTest.php new file mode 100644 index 000000000..05522678f --- /dev/null +++ b/tests/unit/Lib/ZotlibTest.php @@ -0,0 +1,34 @@ + $xchan_url ]; + + $this->assertEquals($expected, \Zotlabs\Lib\Libzot::get_rpost_path($observer)); + } + + private function get_rpost_path_provider() : array { + return [ + 'xchan_url without port' => [ + 'https://example.com/rpost?f=', + 'https://example.com' + ], + 'xchan_url with port' => [ + 'https://example.com:666/rpost?f=', + 'https://example.com:666' + ], + 'xchan_url ignores path and args' => [ + 'https://example.com/rpost?f=', + 'https://example.com/path?arg1=balle' + ], + 'xchan_url with no scheme should default to https' => [ + 'https://example.com/rpost?f=', + 'example.com', + ], + ]; + } +} -- cgit v1.2.3 From 07696d4bd144be03819122bfa2c78cd8aa3d4770 Mon Sep 17 00:00:00 2001 From: Mario Date: Thu, 2 May 2024 19:24:13 +0000 Subject: fix the test - we do not use a title anymore since it does not make much sense in combination of the sub titles --- tests/unit/Widget/HelpindexTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/unit') diff --git a/tests/unit/Widget/HelpindexTest.php b/tests/unit/Widget/HelpindexTest.php index a8b51172b..2d984985d 100644 --- a/tests/unit/Widget/HelpindexTest.php +++ b/tests/unit/Widget/HelpindexTest.php @@ -43,7 +43,7 @@ class HelpindexTest extends \Zotlabs\Tests\Unit\Module\TestCase { $this->render_widget(); $this->assertOutputContains('toc'); - $this->assertOutputContains('Help Content'); + //$this->assertOutputContains('Help Content'); } public function test_that_result_is_empty_when_toc_not_present(): void { -- cgit v1.2.3 From b25662e183fa800d13908e707e0a3f33131b9ea8 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 3 May 2024 09:39:58 +0200 Subject: fix nested lists by parsing li before ul or ol and add a test --- tests/unit/includes/BBCodeTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tests/unit') diff --git a/tests/unit/includes/BBCodeTest.php b/tests/unit/includes/BBCodeTest.php index a8aa8ee2b..e1fba9fbc 100644 --- a/tests/unit/includes/BBCodeTest.php +++ b/tests/unit/includes/BBCodeTest.php @@ -230,6 +230,14 @@ class BBCodeTest extends UnitTestCase { 'html reshares from streams' => [ '
image/photo shared something
something
', '[url=https://example.com][img=https://example.com/image.jpg]image/photo[/img][/url] shared something' . "\n" . 'something' + ], + 'list' => [ + '
  • list 1
  • list 2
  • list 3
', + '[list][*]list 1[*]list 2[*]list 3[/list]' + ], + 'nested list' => [ + '
  • list 1
  • list 2
  • list 3
    • list 1
    • list 2
    • list 3
', + '[list][*]list 1[*]list 2[*]list 3[list][*]list 1[*]list 2[*]list 3[/list][/list]' ] ]; } -- cgit v1.2.3 From 3a50a0b71572d0f5cc5c5aed1df8592c3e9e4dce Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 3 May 2024 10:23:36 +0200 Subject: deal with li tags earlier seems to be more straight forward also add test for li without closing tag --- tests/unit/includes/BBCodeTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tests/unit') diff --git a/tests/unit/includes/BBCodeTest.php b/tests/unit/includes/BBCodeTest.php index e1fba9fbc..2697c5069 100644 --- a/tests/unit/includes/BBCodeTest.php +++ b/tests/unit/includes/BBCodeTest.php @@ -238,6 +238,14 @@ class BBCodeTest extends UnitTestCase { 'nested list' => [ '
  • list 1
  • list 2
  • list 3
    • list 1
    • list 2
    • list 3
', '[list][*]list 1[*]list 2[*]list 3[list][*]list 1[*]list 2[*]list 3[/list][/list]' + ], + 'list without closing li' => [ + '
  • list 1
  • list 2
  • list 3
', + '[list][*]list 1[*]list 2[*]list 3[/list]' + ], + 'nested list without closing li' => [ + '
  • list 1
  • list 2
  • list 3
    • list 1
    • list 2
    • list 3
', + '[list][*]list 1[*]list 2[*]list 3[list][*]list 1[*]list 2[*]list 3[/list][/list]' ] ]; } -- cgit v1.2.3 From 219f0dfeca0cccc1870ca9da608d5004d43e67fb Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 3 May 2024 12:04:19 +0200 Subject: also deal with ol and ul tags earlier and add test for double nested lists --- tests/unit/includes/BBCodeTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tests/unit') diff --git a/tests/unit/includes/BBCodeTest.php b/tests/unit/includes/BBCodeTest.php index 2697c5069..34e127a30 100644 --- a/tests/unit/includes/BBCodeTest.php +++ b/tests/unit/includes/BBCodeTest.php @@ -239,6 +239,10 @@ class BBCodeTest extends UnitTestCase { '
  • list 1
  • list 2
  • list 3
    • list 1
    • list 2
    • list 3
', '[list][*]list 1[*]list 2[*]list 3[list][*]list 1[*]list 2[*]list 3[/list][/list]' ], + 'double nested list' => [ + '
  • list 1
  • list 2
  • list 3
    • list 1
    • list 2
    • list 3
      • list 1
      • list 2
      • list 3
', + '[list][*]list 1[*]list 2[*]list 3[list][*]list 1[*]list 2[*]list 3[list][*]list 1[*]list 2[*]list 3[/list][/list][/list]' + ], 'list without closing li' => [ '
  • list 1
  • list 2
  • list 3
', '[list][*]list 1[*]list 2[*]list 3[/list]' @@ -246,6 +250,10 @@ class BBCodeTest extends UnitTestCase { 'nested list without closing li' => [ '
  • list 1
  • list 2
  • list 3
    • list 1
    • list 2
    • list 3
', '[list][*]list 1[*]list 2[*]list 3[list][*]list 1[*]list 2[*]list 3[/list][/list]' + ], + 'double nested list without closing li' => [ + '
  • list 1
  • list 2
  • list 3
    • list 1
    • list 2
    • list 3
      • list 1
      • list 2
      • list 3
', + '[list][*]list 1[*]list 2[*]list 3[list][*]list 1[*]list 2[*]list 3[list][*]list 1[*]list 2[*]list 3[/list][/list][/list]' ] ]; } -- cgit v1.2.3 From 9dd63db736819ba15fd75821a8ea520f68a54ee3 Mon Sep 17 00:00:00 2001 From: Mario Date: Tue, 7 May 2024 08:56:25 +0000 Subject: add tests --- tests/unit/includes/BBCodeTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tests/unit') diff --git a/tests/unit/includes/BBCodeTest.php b/tests/unit/includes/BBCodeTest.php index 34e127a30..887374c13 100644 --- a/tests/unit/includes/BBCodeTest.php +++ b/tests/unit/includes/BBCodeTest.php @@ -134,6 +134,10 @@ class BBCodeTest extends UnitTestCase { 'list with linebreaks \r\n in text' => [ "some text\r\n[list]\r\n[*] item1\r\nsome text[*] item2\r\nsome text[/list]\r\nsome more text", 'some text
  • item1
    some text
  • item2
    some text
some more text' + ], + 'del tag' => [ + 'some [s]strike through[/s] text', + 'some strike through text' ] ]; } @@ -254,6 +258,10 @@ class BBCodeTest extends UnitTestCase { 'double nested list without closing li' => [ '
  • list 1
  • list 2
  • list 3
    • list 1
    • list 2
    • list 3
      • list 1
      • list 2
      • list 3
', '[list][*]list 1[*]list 2[*]list 3[list][*]list 1[*]list 2[*]list 3[list][*]list 1[*]list 2[*]list 3[/list][/list][/list]' + ], + 'del tag' => [ + 'some strike through text', + 'some [s]strike through[/s] text' ] ]; } -- cgit v1.2.3 From 481e08b904313b768305d82b67f5f8602713b329 Mon Sep 17 00:00:00 2001 From: Mario Date: Wed, 8 May 2024 15:41:54 +0000 Subject: remove p tags from li. otherwise we will get unwanted new lines in the list. add test. --- tests/unit/includes/BBCodeTest.php | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tests/unit') diff --git a/tests/unit/includes/BBCodeTest.php b/tests/unit/includes/BBCodeTest.php index 887374c13..94cad1367 100644 --- a/tests/unit/includes/BBCodeTest.php +++ b/tests/unit/includes/BBCodeTest.php @@ -239,6 +239,10 @@ class BBCodeTest extends UnitTestCase { '
  • list 1
  • list 2
  • list 3
', '[list][*]list 1[*]list 2[*]list 3[/list]' ], + 'list with paragraph' => [ + '
  • list 1

  • list 2

  • list 3

', + '[list][*]list 1[*]list 2[*]list 3[/list]' + ], 'nested list' => [ '
  • list 1
  • list 2
  • list 3
    • list 1
    • list 2
    • list 3
', '[list][*]list 1[*]list 2[*]list 3[list][*]list 1[*]list 2[*]list 3[/list][/list]' -- cgit v1.2.3 From 5da0cc138f4330fd07e9c117b3f4261dc1bcbc19 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Wed, 15 May 2024 08:28:19 +0000 Subject: Refactor and cleanup Rbmark module + add tests --- tests/unit/Module/HelpTest.php | 9 ----- tests/unit/Module/RbmarkTest.php | 80 ++++++++++++++++++++++++++++++++++++++++ tests/unit/Module/TestCase.php | 20 +++++++++- 3 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 tests/unit/Module/RbmarkTest.php (limited to 'tests/unit') diff --git a/tests/unit/Module/HelpTest.php b/tests/unit/Module/HelpTest.php index 0f1610db5..3fb7687d3 100644 --- a/tests/unit/Module/HelpTest.php +++ b/tests/unit/Module/HelpTest.php @@ -176,13 +176,4 @@ class HelpTest extends \Zotlabs\Tests\Unit\Module\TestCase { $this->assertPageContains('

This is the included file.

'); } - - /** - * Helper to simplify asserting contents in the rendered page. - * - * @param string $needle The expected string to find. - */ - private function assertPageContains(string $needle): void { - $this->assertStringContainsString($needle, \App::$page['content']); - } } diff --git a/tests/unit/Module/RbmarkTest.php b/tests/unit/Module/RbmarkTest.php new file mode 100644 index 000000000..594e7369b --- /dev/null +++ b/tests/unit/Module/RbmarkTest.php @@ -0,0 +1,80 @@ +getFunctionMock('Zotlabs\Module', 'local_channel'); + $lc_stub + ->expects($this->once()) + ->willReturn(false); + + $this->get('rbmark', ['url' => 'https://bookmarked.url']); + + $this->assertPageContains('value="login" />'); + + // also check that the original query is saved in the session + $this->assertEquals('https://bookmarked.url', $_SESSION['bookmark']['url']); + $this->assertEquals('rbmark', $_SESSION['bookmark']['q']); + } + + public function test_authenticated_get_request_returns_save_bookmark_form(): void { + $lc_stub = $this->getFunctionMock('Zotlabs\Module', 'local_channel'); + $lc_stub + ->expects($this->once()) + ->willReturn(42); + + $this->get('rbmark', [ + 'url' => 'https://bookmarked.url', + 'title' => 'My bookmark', + ]); + + $this->assertPageContains('
assertPageContains('URL of bookmark'); + $this->assertPageContains('value="https://bookmarked.url"'); + $this->assertPageContains('value="My bookmark"'); + } + + public function test_that_params_are_escaped_in_save_bookmark_form(): void { + $lc_stub = $this->getFunctionMock('Zotlabs\Module', 'local_channel'); + $lc_stub + ->expects($this->once()) + ->willReturn(42); + + $this->get('rbmark', [ + 'url' => 'https://bookmarked.url" onload="alert(/boom/)', + 'title' => 'My bookmark">", diff --git a/tests/unit/Lib/ActivityTest.php b/tests/unit/Lib/ActivityTest.php index c9ce79d8c..0e2703f2b 100644 --- a/tests/unit/Lib/ActivityTest.php +++ b/tests/unit/Lib/ActivityTest.php @@ -19,7 +19,7 @@ class ActivityTest extends UnitTestCase { /** * Dataprovider for test_get_textfield. */ - private function get_textfield_provider(): array { + public static function get_textfield_provider(): array { return [ 'get content field' => [ ['content' => 'Some content'], diff --git a/tests/unit/Lib/ZotlibTest.php b/tests/unit/Lib/ZotlibTest.php index 05522678f..0ab89dc2f 100644 --- a/tests/unit/Lib/ZotlibTest.php +++ b/tests/unit/Lib/ZotlibTest.php @@ -1,5 +1,9 @@ assertEquals($expected, \Zotlabs\Lib\Libzot::get_rpost_path($observer)); } - private function get_rpost_path_provider() : array { + public static function get_rpost_path_provider() : array { return [ 'xchan_url without port' => [ 'https://example.com/rpost?f=', diff --git a/tests/unit/Module/HelpTest.php b/tests/unit/Module/HelpTest.php index 3fb7687d3..c345d5e52 100644 --- a/tests/unit/Module/HelpTest.php +++ b/tests/unit/Module/HelpTest.php @@ -52,7 +52,7 @@ class HelpTest extends \Zotlabs\Tests\Unit\Module\TestCase { $fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents'); $fgc_stub ->expects($this->once()) - ->willReturn($this->returnValueMap($file_content_map)); + ->willReturnMap($file_content_map); $this->get("help/about/help_topic"); diff --git a/tests/unit/Module/SetupTest.php b/tests/unit/Module/SetupTest.php index 96a5ef932..3575dd477 100644 --- a/tests/unit/Module/SetupTest.php +++ b/tests/unit/Module/SetupTest.php @@ -6,6 +6,8 @@ * SPDX-License-Identifier: MIT */ +namespace Zotlabs\Tests\Unit\Module; + /** * SetupModuleTest * @@ -16,7 +18,7 @@ * This is a complex module, so expect the tests to grow as more of it will be * covered. */ -class SetupModuleTest extends \Zotlabs\Tests\Unit\Module\TestCase { +class SetupTest extends TestCase { public function test_that_setup_is_available_if_no_accounts_in_db(): void { $this->with_no_accounts_in_db(); diff --git a/tests/unit/Module/TestCase.php b/tests/unit/Module/TestCase.php index 5ad213e81..e7051e001 100644 --- a/tests/unit/Module/TestCase.php +++ b/tests/unit/Module/TestCase.php @@ -24,6 +24,7 @@ class TestCase extends \Zotlabs\Tests\Unit\UnitTestCase { } $_SERVER['REQUEST_METHOD'] = 'GET'; + $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1'; $_REQUEST = $_GET; \App::init(); diff --git a/tests/unit/UnitTestCase.php b/tests/unit/UnitTestCase.php index 9ab6a534a..844746a51 100644 --- a/tests/unit/UnitTestCase.php +++ b/tests/unit/UnitTestCase.php @@ -22,8 +22,8 @@ namespace Zotlabs\Tests\Unit; +use PHPUnit\Framework\Attributes\{Before, After}; use PHPUnit\Framework\TestCase; -use PHPUnit\Framework\TestResult; /* * Make sure global constants and the global App object is available to the @@ -46,33 +46,44 @@ require_once 'include/dba/dba_driver.php' ; */ class UnitTestCase extends TestCase { protected array $fixtures = array(); + protected ?\DbaTransaction $db_transacton = null; /** - * Override the run method, so we can wrap it in a database transaction. + * Connect to the test db, load fixtures and global config. * - * The transaction is automatically rolled back when the test completes, to - * leave the test database in a known pristine state. + * This function is executed before every test. * - * @SuppressWarnings(PHPMD.UnusedLocalVariable) + * The transaction is rolled back in the `cleanup_test_db()` function + * that's executed after every test. */ - public function run(TestResult $result = null): TestResult { + #[Before] + protected function setup_test_db(): void { if (! \DBA::$dba) { $this->connect_to_test_db(); } // The $transactuion variable is needed to hold the transaction until the // function returns. - $transaction = new \DbaTransaction(\DBA::$dba); + $this->db_transaction = new \DbaTransaction(\DBA::$dba); $this->loadFixtures(); // Make sure app config is reset and loaded from fixtures \App::$config = array(); \Zotlabs\Lib\Config::Load('system'); + } - $result = parent::run($result); - - return $result; + /** + * Roll back test database to it's original state, cleaning up + * any changes from the test. + * + * This function is executes after evert tests. + */ + #[After] + protected function cleanup_test_db(): void { + // Setting the transaction to `null`, runs the destructor + // which rolls backk the transacton. + $this->db_transaction = null; } /** diff --git a/tests/unit/Web/HttpSigTest.php b/tests/unit/Web/HttpSigTest.php index c01e4f6a3..d705be4ff 100644 --- a/tests/unit/Web/HttpSigTest.php +++ b/tests/unit/Web/HttpSigTest.php @@ -46,7 +46,7 @@ class HttpSigTest extends UnitTestCase { HTTPSig::generate_digest_header($text) ); } - public function generate_digestProvider() { + public static function generate_digestProvider() { return [ 'empty body text' => [ '', diff --git a/tests/unit/Widget/HelpindexTest.php b/tests/unit/Widget/HelpindexTest.php index 2d984985d..26aa34104 100644 --- a/tests/unit/Widget/HelpindexTest.php +++ b/tests/unit/Widget/HelpindexTest.php @@ -23,8 +23,8 @@ class HelpindexTest extends \Zotlabs\Tests\Unit\Module\TestCase { * @beforeClass */ public static function define_stubs(): void { - \phpmock\phpunit\PHPMock::defineFunctionMock('Zotlabs\Lib\Traits', 'file_exists'); - \phpmock\phpunit\PHPMock::defineFunctionMock('Zotlabs\Widget', 'file_get_contents'); + self::defineFunctionMock('Zotlabs\Lib\Traits', 'file_exists'); + self::defineFunctionMock('Zotlabs\Widget', 'file_get_contents'); } public function test_loading_toc(): void { diff --git a/tests/unit/includes/AccountTest.php b/tests/unit/includes/AccountTest.php index af5bcd3c1..3978f9d04 100644 --- a/tests/unit/includes/AccountTest.php +++ b/tests/unit/includes/AccountTest.php @@ -19,7 +19,7 @@ class AccountTest extends Zotlabs\Tests\Unit\UnitTestCase { $this->assertEquals($expected, check_account_email($email)); } - function check_account_email_provider() : array { + public static function check_account_email_provider() : array { return [ // Empty and valid emails return the same result ['', ['error' => false, 'message' => '']], diff --git a/tests/unit/includes/BBCodeTest.php b/tests/unit/includes/BBCodeTest.php index 94cad1367..daa66bf72 100644 --- a/tests/unit/includes/BBCodeTest.php +++ b/tests/unit/includes/BBCodeTest.php @@ -101,7 +101,7 @@ class BBCodeTest extends UnitTestCase { * * @SuppressWarnings(PHPMD.UnusedPrivateMethod) */ - private function bbcode_to_html_provider(): array { + public static function bbcode_to_html_provider(): array { return [ 'code block' => [ "[code]\ntestvar = \"this is a test\"\necho \"the message is \$testvar\"\n[/code]", @@ -153,7 +153,7 @@ class BBCodeTest extends UnitTestCase { * * @SuppressWarnings(PHPMD.UnusedPrivateMethod) */ - private function bbcode_observer_provider(): array { + public static function bbcode_observer_provider(): array { return [ 'authenticated observer' => [ '[observer=1]This should be visible[/observer][observer=0]but not this[/observer]', @@ -205,7 +205,7 @@ class BBCodeTest extends UnitTestCase { * * @SuppressWarnings(PHPMD.UnusedPrivateMethod) */ - private function html2bbcode_provider(): array { + public static function html2bbcode_provider(): array { return [ 'paragraph over multiple lines' => [ "

A paragraph over\nmultiple lines\nshould be unwrapped

", diff --git a/tests/unit/includes/FeedutilsTest.php b/tests/unit/includes/FeedutilsTest.php index bda0bf425..05bff06a3 100644 --- a/tests/unit/includes/FeedutilsTest.php +++ b/tests/unit/includes/FeedutilsTest.php @@ -47,7 +47,7 @@ class FeedutilsTest extends UnitTestCase { public function test_atom_author() { $this->assertEquals('', atom_author('', 'nick', 'name', 'uri', 72, 72, 'png', 'photourl')); - $a = ' + $expected = ' uri nick uri @@ -57,7 +57,10 @@ class FeedutilsTest extends UnitTestCase { name '; - $this->assertXmlStringEqualsXmlString($a, atom_author('tag', 'nick', 'name', 'uri', 72, 72, 'png', 'http://photourl')); + $this->assertAtomAuthorMatches( + $expected, + atom_author('tag', 'nick', 'name', 'uri', 72, 72, 'png', 'http://photourl') + ); } /** @@ -86,6 +89,63 @@ class FeedutilsTest extends UnitTestCase { Chan '; - $this->assertXmlStringEqualsXmlString($a, atom_render_author('tag', $xchan)); + $this->assertAtomAuthorMatches($a, atom_render_author('tag', $xchan)); + } + + /** + * Helper method to assert that the generated author tag matches + * what we expect. + * + * Calling `assertXmlStringEqualsXmlString` directly on the fragments + * does not work anymore in PHPUnit >= 10.x, as t will throw an XMLException + * because of undefined namespaces. + * + * To overcome that we wrap the generated tags in the proper template, + * and compare the fully generated XML from the template instead. + * + * @param string $expected The expected author XML fragment. + * @param string $actual The actually generated authr XML fragment. + */ + private function assertAtomAuthorMatches(string $expected, string $actual): void { + + // Make sure the template engine is initialized before we try to render + // the template. + // + // This may be problematic, as it will compile the template into the same + // directory as the site. Assuming that nobody is crazy enough to run the + // test suite in a production server, it should probably be fine for now. + $smarty = new \Zotlabs\Render\SmartyTemplate(); + \App::register_template_engine(get_class($smarty)); + + $feed_template = get_markup_template('atom_feed.tpl'); + $expected_xml = replace_macros($feed_template, [ + '$version' => 42, + '$generator' => 'Hubzilla test', + '$generator_uri' => 'https://hubzilla.test', + '$feed_id' => 'test_channel', + '$feed_title' => 'Test channel', + '$feed_updated' => 'Sometime', + '$author' => $expected, + '$owner' => $expected, + '$profile_page' => xmlify('https://hubzilla.test/channel/test'), + ]); + + $expected_xml .= ''; + + $actual_xml = replace_macros($feed_template, [ + '$version' => 42, + '$generator' => 'Hubzilla test', + '$generator_uri' => 'https://hubzilla.test', + '$feed_id' => 'test_channel', + '$feed_title' => 'Test channel', + '$feed_updated' => 'Sometime', + '$author' => $actual, + '$owner' => $actual, + '$profile_page' => xmlify('https://hubzilla.test/channel/test'), + ]); + + $actual_xml .= ''; + + $this->assertXmlStringEqualsXmlString($expected_xml, $actual_xml); } } diff --git a/tests/unit/includes/LanguageTest.php b/tests/unit/includes/LanguageTest.php index 3367232f3..8f62e71e2 100644 --- a/tests/unit/includes/LanguageTest.php +++ b/tests/unit/includes/LanguageTest.php @@ -46,7 +46,7 @@ class LanguageTest extends UnitTestCase { } } - public function getLanguageNameProvider() { + public static function getLanguageNameProvider() { return [ 'empty language code' => [ '', diff --git a/tests/unit/includes/MarkdownTest.php b/tests/unit/includes/MarkdownTest.php index 960c15139..310130bf1 100644 --- a/tests/unit/includes/MarkdownTest.php +++ b/tests/unit/includes/MarkdownTest.php @@ -39,7 +39,7 @@ class MarkdownTest extends UnitTestCase { $this->assertEquals($expected, markdown_to_bb($src)); } - private function markdown_to_bbcode_provider(): array { + public static function markdown_to_bbcode_provider(): array { return [ 'empty text' => [ '', @@ -104,7 +104,7 @@ class MarkdownTest extends UnitTestCase { $this->assertEquals($markdown, html2markdown($html)); } - public function html2markdownProvider(): array { + public static function html2markdownProvider(): array { return [ 'empty text' => [ '', diff --git a/tests/unit/includes/NetworkTest.php b/tests/unit/includes/NetworkTest.php index 9fb00e9d3..5bf175953 100644 --- a/tests/unit/includes/NetworkTest.php +++ b/tests/unit/includes/NetworkTest.php @@ -20,7 +20,7 @@ class NetworkTest extends Zotlabs\Tests\Unit\UnitTestCase { $this->assertEquals($expected, is_local_url($url)); } - public function localUrlTestProvider() : array { + public static function localUrlTestProvider() : array { return [ [ '/some/path', true ], [ 'https://mytest.org/some/path', true ], @@ -47,7 +47,7 @@ class NetworkTest extends Zotlabs\Tests\Unit\UnitTestCase { $this->assertTrue(validate_email($email)); } - function validate_email_provider() : array { + public static function validate_email_provider() : array { return [ // First some invalid email addresses ['', false], diff --git a/tests/unit/includes/TextTest.php b/tests/unit/includes/TextTest.php index b76b15dcf..1e80d71d8 100644 --- a/tests/unit/includes/TextTest.php +++ b/tests/unit/includes/TextTest.php @@ -85,7 +85,7 @@ empty line above'; public function testNotags($string, $expected) { $this->assertEquals($expected, notags($string)); } - public function notagsProvider() { + public static function notagsProvider() { return [ 'empty string' => ['', ''], 'simple tag' => ['', '[value]'], @@ -102,7 +102,7 @@ empty line above'; sanitise_acl($string); $this->assertEquals($expected, $string); } - public function sanitise_aclProvider() { + public static function sanitise_aclProvider() { return [ 'text' => ['value', ''], 'text with angle bracket' => ['', '<[value]>'], diff --git a/tests/unit/includes/dba/TransactionTest.php b/tests/unit/includes/dba/TransactionTest.php index 99e3f459d..0b986c6aa 100644 --- a/tests/unit/includes/dba/TransactionTest.php +++ b/tests/unit/includes/dba/TransactionTest.php @@ -24,8 +24,8 @@ require_once 'tests/fakes/fake_dba.php'; require_once 'include/dba/dba_transaction.php'; -use \PHPUnit\Framework\TestCase; -use \Zotlabs\Tests\Fakes\FakeDba; +use PHPUnit\Framework\TestCase; +use Zotlabs\Tests\Fakes\FakeDba; /** * Test database transactions. @@ -39,7 +39,7 @@ class DbaTransactionTest extends TestCase { private $pdo_stub; public function setUp(): void { - $this->pdo_stub = $this->createStub(PDO::class); + $this->pdo_stub = $this->createMock(PDO::class); } -- cgit v1.2.3 From 350f84913a9390ac67f800a51f6c4d319331149c Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Wed, 5 Jun 2024 07:59:42 +0000 Subject: Skip checking MFA status for WebDAV and CardDAV requests. --- tests/unit/UnitTestCase.php | 1 + tests/unit/includes/AuthTest.php | 81 ++++++++++++++++++++++++++++++ tests/unit/includes/dba/_files/account.yml | 2 + 3 files changed, 84 insertions(+) create mode 100644 tests/unit/includes/AuthTest.php (limited to 'tests/unit') diff --git a/tests/unit/UnitTestCase.php b/tests/unit/UnitTestCase.php index 844746a51..afc309205 100644 --- a/tests/unit/UnitTestCase.php +++ b/tests/unit/UnitTestCase.php @@ -31,6 +31,7 @@ use PHPUnit\Framework\TestCase; */ require_once __DIR__ . '/../../boot.php'; require_once 'include/dba/dba_driver.php' ; +require_once 'include/dba/dba_transaction.php'; /** * Base class for our Unit Tests. diff --git a/tests/unit/includes/AuthTest.php b/tests/unit/includes/AuthTest.php new file mode 100644 index 000000000..fa9726fe8 --- /dev/null +++ b/tests/unit/includes/AuthTest.php @@ -0,0 +1,81 @@ +fixtures['account']['0']['account_id']; + + $_SESSION = [ + 'authenticated' => true, + 'account_id' => $account_id, + + // Trick the code to not warn that $_SESSION['uid'] is not set, + // but also not trigger the code that tries to change to the + // given channel. *Remove when code is fixed!* + 'uid' => 0, + ]; + + $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; + + App::$session = $this->create_session_stub(); + App::$module = $module; + App::$argv = $args; + App::$argc = count($args); + + // Enable multi factor authentication for this account + AConfig::Set($account_id, 'system', 'mfa_enabled', true); + + require 'include/auth.php'; + + $this->assertEquals(1, $_SESSION['authenticated']); + } + + /** + * Data provider for testing modules excluded from mfa + * @SuppressWarnings(PHPMD.UnusedPrivateMethod) + */ + public static function modules_excluded_from_mfa(): array { + return [ + ['totp_check', []], + ['cdav', []], + ['cdav', ['calendar']], + ['cdav', ['addressbook']], + ['dav', []], + ]; + } + + private function create_session_stub(): \Zotlabs\Web\Session { + return $this->createStub('Zotlabs\Web\Session'); + } +} diff --git a/tests/unit/includes/dba/_files/account.yml b/tests/unit/includes/dba/_files/account.yml index 344bdb799..88e59056e 100644 --- a/tests/unit/includes/dba/_files/account.yml +++ b/tests/unit/includes/dba/_files/account.yml @@ -3,7 +3,9 @@ account: account_id: 42 account_email: "hubzilla@example.com" account_language: "no" + account_flags: 0 - account_id: 43 account_email: "hubzilla@example.org" account_language: "de" + account_flags: 1 -- cgit v1.2.3 From 62aefadc27002f9d47f391b15520a82d5c3d6ecc Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Sat, 18 May 2024 11:30:29 +0200 Subject: Module\Rpost: Add basic test and fix session access. Just a basic test to ensure that the module `get()` method behaves somewhat reasonable when no query params are given. Had to make a small change to the Rpost module itself. Since the `$_SESSION` superglobal may not always be set (and is not in the test), use `isset` instead of `array_key_exists` to check if we have saved query params in the session. In general, isset is safer than array_key_exists if there's a chance that the array itself may not exist. --- tests/unit/Module/RpostTest.php | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/unit/Module/RpostTest.php (limited to 'tests/unit') diff --git a/tests/unit/Module/RpostTest.php b/tests/unit/Module/RpostTest.php new file mode 100644 index 000000000..796901520 --- /dev/null +++ b/tests/unit/Module/RpostTest.php @@ -0,0 +1,31 @@ +getFunctionMock('Zotlabs\Module', 'local_channel') + ->expects($this->any()) + ->willReturn(42); + + // Set basic access controls to keep AccessList happy. + \App::$channel = [ + 'channel_allow_cid' => null, + 'channel_allow_gid' => null, + 'channel_deny_cid' => null, + 'channel_deny_gid' => null, + ]; + + $this->get('rpost'); + + $this->assertPageContains('assertPageContains(' Date: Sat, 18 May 2024 20:58:09 +0200 Subject: tests: Configure system.baseurl for tests. --- tests/unit/includes/NetworkTest.php | 8 +------- tests/unit/includes/dba/_files/config.yml | 4 ++++ 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'tests/unit') diff --git a/tests/unit/includes/NetworkTest.php b/tests/unit/includes/NetworkTest.php index 5bf175953..a41075f25 100644 --- a/tests/unit/includes/NetworkTest.php +++ b/tests/unit/includes/NetworkTest.php @@ -7,12 +7,6 @@ class NetworkTest extends Zotlabs\Tests\Unit\UnitTestCase { - public function setUp() : void { - parent::setUp(); - - \App::set_baseurl("https://mytest.org"); - } - /** * @dataProvider localUrlTestProvider */ @@ -23,7 +17,7 @@ class NetworkTest extends Zotlabs\Tests\Unit\UnitTestCase { public static function localUrlTestProvider() : array { return [ [ '/some/path', true ], - [ 'https://mytest.org/some/path', true ], + [ 'https://hubzilla.test/some/path', true ], [ 'https://other.site/some/path', false ], ]; } diff --git a/tests/unit/includes/dba/_files/config.yml b/tests/unit/includes/dba/_files/config.yml index e93486857..ac3c8acb0 100644 --- a/tests/unit/includes/dba/_files/config.yml +++ b/tests/unit/includes/dba/_files/config.yml @@ -1,5 +1,9 @@ --- config: + - + cat: system + k: baseurl + v: https://hubzilla.test - cat: system k: do_not_check_dns -- cgit v1.2.3 From 93a45be1816b33651fb2138c87aae083cfd480b9 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Sat, 18 May 2024 20:59:08 +0200 Subject: tests: Set query string in Module\TestCase::get method. --- tests/unit/Module/TestCase.php | 1 + 1 file changed, 1 insertion(+) (limited to 'tests/unit') diff --git a/tests/unit/Module/TestCase.php b/tests/unit/Module/TestCase.php index e7051e001..f2e19f265 100644 --- a/tests/unit/Module/TestCase.php +++ b/tests/unit/Module/TestCase.php @@ -25,6 +25,7 @@ class TestCase extends \Zotlabs\Tests\Unit\UnitTestCase { $_SERVER['REQUEST_METHOD'] = 'GET'; $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1'; + $_SERVER['QUERY_STRING'] = "q={$uri}"; $_REQUEST = $_GET; \App::init(); -- cgit v1.2.3 From 7c688de9cd9bfbccab60d77396f0f879acd4a52d Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Sat, 18 May 2024 21:00:28 +0200 Subject: tests: Add comment to Tests\Unit\Module\RpostTest. --- tests/unit/Module/RpostTest.php | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tests/unit') diff --git a/tests/unit/Module/RpostTest.php b/tests/unit/Module/RpostTest.php index 796901520..115894026 100644 --- a/tests/unit/Module/RpostTest.php +++ b/tests/unit/Module/RpostTest.php @@ -9,6 +9,10 @@ */ class RpostTest extends \Zotlabs\Tests\Unit\Module\TestCase { + + /** + * Basic test of a get request with no args as an authenticated user. + */ public function test_get_with_no_args(): void { // Mock `local_chanel()` to emulate a valid logged in channel $lc_mock = $this->getFunctionMock('Zotlabs\Module', 'local_channel') -- cgit v1.2.3 From 76a92ac2e1ed2d22ad960739e56e5832872cfe23 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Sat, 18 May 2024 21:08:30 +0200 Subject: tests: Module\Rpost shows login form if not authenticated. --- tests/unit/Module/RpostTest.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tests/unit') diff --git a/tests/unit/Module/RpostTest.php b/tests/unit/Module/RpostTest.php index 115894026..2f277e66d 100644 --- a/tests/unit/Module/RpostTest.php +++ b/tests/unit/Module/RpostTest.php @@ -32,4 +32,17 @@ class RpostTest extends \Zotlabs\Tests\Unit\Module\TestCase { $this->assertPageContains('assertPageContains('getFunctionMock('Zotlabs\Module', 'local_channel') + ->expects($this->any()) + ->willReturn(false); + + $this->get('rpost'); + + $this->assertPageContains(' Date: Sun, 19 May 2024 11:41:45 +0200 Subject: tests: More tests for Module\Rpost. Also refactor the tests a bit to avoid duplicatng code. --- tests/unit/Module/RpostTest.php | 58 +++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 14 deletions(-) (limited to 'tests/unit') diff --git a/tests/unit/Module/RpostTest.php b/tests/unit/Module/RpostTest.php index 2f277e66d..106f06fde 100644 --- a/tests/unit/Module/RpostTest.php +++ b/tests/unit/Module/RpostTest.php @@ -14,20 +14,7 @@ class RpostTest extends \Zotlabs\Tests\Unit\Module\TestCase { * Basic test of a get request with no args as an authenticated user. */ public function test_get_with_no_args(): void { - // Mock `local_chanel()` to emulate a valid logged in channel - $lc_mock = $this->getFunctionMock('Zotlabs\Module', 'local_channel') - ->expects($this->any()) - ->willReturn(42); - - // Set basic access controls to keep AccessList happy. - \App::$channel = [ - 'channel_allow_cid' => null, - 'channel_allow_gid' => null, - 'channel_deny_cid' => null, - 'channel_deny_gid' => null, - ]; - - $this->get('rpost'); + $this->get_authenticated(); $this->assertPageContains('assertPageContains('assertPageContains('get_authenticated([ + 'title' => 'This is my title', + 'body' => 'The body of the post', + 'source' => 'The temple of the Dagon', + ]); + + $this->assertPageContains('value="This is my title"'); + $this->assertPageContains('>The body of the post'); + $this->assertPageContains('value="The temple of the Dagon"'); + } + + public function test_convert_body_from_html_to_bbcode(): void { + $this->get_authenticated([ + 'body' => "

Awesome page

\r\n

Awesome content!

", + 'type' => 'html', + ]); + + $this->assertPageContains(">[h1]Awesome page[/h1]\n\nAwesome content!"); + } + + /** + * Private helper method to perform an authenticated GET request. + * + * @param array $query An associative array of query parameters. + */ + private function get_authenticated(array $query = []): void { + // Mock `local_chanel()` to emulate a valid logged in channel + $lc_mock = $this->getFunctionMock('Zotlabs\Module', 'local_channel') + ->expects($this->any()) + ->willReturn(42); + + // Set basic access controls to keep AccessList happy. + \App::$channel = [ + 'channel_allow_cid' => null, + 'channel_allow_gid' => null, + 'channel_deny_cid' => null, + 'channel_deny_gid' => null, + ]; + + $this->get('rpost', $query); + } } -- cgit v1.2.3 From fb1c66fbc9705961454d86770511642b97b41c1a Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Wed, 12 Jun 2024 17:08:29 +0200 Subject: Fix warnings exposed by tests. Mainly missing variables for templates, and channel entries. --- tests/unit/Module/RpostTest.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'tests/unit') diff --git a/tests/unit/Module/RpostTest.php b/tests/unit/Module/RpostTest.php index 106f06fde..ad94f2f06 100644 --- a/tests/unit/Module/RpostTest.php +++ b/tests/unit/Module/RpostTest.php @@ -67,10 +67,13 @@ class RpostTest extends \Zotlabs\Tests\Unit\Module\TestCase { // Set basic access controls to keep AccessList happy. \App::$channel = [ - 'channel_allow_cid' => null, - 'channel_allow_gid' => null, - 'channel_deny_cid' => null, - 'channel_deny_gid' => null, + 'channel_id' => 42, + 'channel_location' => null, + 'channel_address' => '', + 'channel_allow_cid' => '', + 'channel_allow_gid' => '', + 'channel_deny_cid' => '', + 'channel_deny_gid' => '', ]; $this->get('rpost', $query); -- cgit v1.2.3 From 20a8da0683dc296860528873f28a8f766c3f328b Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Mon, 26 Feb 2024 14:08:54 +0100 Subject: tests: Remove obsolete stubs from Permissions tests These stubs are no longer needed, as the tests have a db now. --- tests/unit/Access/PermissionsTest.php | 26 -------------------------- tests/unit/Lib/PermissionDescriptionTest.php | 20 -------------------- 2 files changed, 46 deletions(-) (limited to 'tests/unit') diff --git a/tests/unit/Access/PermissionsTest.php b/tests/unit/Access/PermissionsTest.php index dd001e68a..f9cb25b64 100644 --- a/tests/unit/Access/PermissionsTest.php +++ b/tests/unit/Access/PermissionsTest.php @@ -63,14 +63,6 @@ class PermissionsTest extends UnitTestCase { // There are 17 default perms $permsCount = 17; - // Create a stub for global function t() with expectation - $t = $this->getFunctionMock('Zotlabs\Access', 't'); - $t->expects($this->exactly(2*$permsCount))->willReturnCallback( - function ($string) { - return $string; - } - ); - // static method Perms() $perms = Permissions::Perms(); @@ -97,14 +89,6 @@ class PermissionsTest extends UnitTestCase { // There are 17 default perms $permsCount = 17; - // Create a stub for global function t() with expectation - $t = $this->getFunctionMock('Zotlabs\Access', 't'); - $t->expects($this->exactly(2*$permsCount))->willReturnCallback( - function ($string) { - return $string; - } - ); - $perms = Permissions::Perms('view_'); $this->assertEquals($permsCount, count($perms)); @@ -125,9 +109,6 @@ class PermissionsTest extends UnitTestCase { * @param array $expected The expected result perms array */ public function testFilledPerms($permarr, $expected) { - // Create a stub for global function t() - $t = $this->getFunctionMock('Zotlabs\Access', 't'); - $this->assertEquals($expected, Permissions::FilledPerms($permarr)); } /** @@ -209,13 +190,6 @@ class PermissionsTest extends UnitTestCase { * @uses ::call_hooks */ public function testFilledPermsNull() { - // Create a stub for global function t() with expectation - $t = $this->getFunctionMock('Zotlabs\Access', 't'); - $t->expects($this->atLeastOnce()); - // Create a stub for global function bt() with expectations - $bt = $this->getFunctionMock('Zotlabs\Access', 'btlogger'); - $bt->expects($this->once())->with($this->equalTo('FilledPerms: null')); - $result = [ 'view_stream' => 0, 'send_stream' => 0, diff --git a/tests/unit/Lib/PermissionDescriptionTest.php b/tests/unit/Lib/PermissionDescriptionTest.php index fdd676f61..1e4b5292c 100644 --- a/tests/unit/Lib/PermissionDescriptionTest.php +++ b/tests/unit/Lib/PermissionDescriptionTest.php @@ -46,16 +46,6 @@ class PermissionDescriptionTest extends UnitTestCase { } public function testFromStandalonePermission() { - // Create a stub for global function t() - $t = $this->getFunctionMock('Zotlabs\Lib', 't'); - $t->expects($this->atLeastOnce())->willReturnCallback( - function ($string) { - return $string; - } - ); - // Create a mock for global function logger() - $this->getFunctionMock('Zotlabs\Lib', 'logger'); - $permDescUnknown = PermissionDescription::fromStandalonePermission(-1); $permDescSelf = PermissionDescription::fromStandalonePermission(0); @@ -113,16 +103,6 @@ class PermissionDescriptionTest extends UnitTestCase { } public function testGetPermissionDescription() { - // Create a stub for global function t() - $t = $this->getFunctionMock('Zotlabs\Lib', 't'); - $t->expects($this->atLeastOnce())->willReturnCallback( - function ($string) { - return $string; - } - ); - // Create a mock for global function logger() - $this->getFunctionMock('Zotlabs\Lib', 'logger'); - // Create a stub for the PermissionDescription class $stub = $this->createMock(PermissionDescription::class); $stub->method('get_permission_description') -- cgit v1.2.3 From 1ed8383c33530b221ef34ad1c5e9b3b80eab94fa Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Fri, 14 Jun 2024 16:31:42 +0200 Subject: Allow passing callable as array to hooks. --- tests/unit/CallHooksTest.php | 65 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tests/unit/CallHooksTest.php (limited to 'tests/unit') diff --git a/tests/unit/CallHooksTest.php b/tests/unit/CallHooksTest.php new file mode 100644 index 000000000..0170f31d0 --- /dev/null +++ b/tests/unit/CallHooksTest.php @@ -0,0 +1,65 @@ +assertHookInvoked(); + } + + public function test_static_class_function_as_string(): void { + insert_hook('test_hook', 'Zotlabs\Tests\Unit\CallHooksTest::static_test_hook'); + $this->assertHookInvoked(); + } + + public function test_static_class_function_as_array(): void { + insert_hook('test_hook', ['Zotlabs\Tests\Unit\CallHooksTest', 'static_test_hook']); + $this->assertHookInvoked(); + } + + public function test_static_class_function_as_serialized_array(): void { + insert_hook('test_hook', serialize(['Zotlabs\Tests\Unit\CallHooksTest', 'static_test_hook'])); + $this->assertHookInvoked(); + } + + public function test_instance_function_as_array(): void { + insert_hook('test_hook', [$this, 'instance_test_hook']); + $this->assertHookInvoked(); + } + + + public function assertHookInvoked(): void { + $test_hook_args = ['called' => false]; + call_hooks('test_hook', $test_hook_args); + + $this->assertTrue($test_hook_args['called']); + } + + public function instance_test_hook(array &$args): void { + $args['called'] = true; + } + public static function static_test_hook(array &$args): void { + $args['called'] = true; + } +} + -- cgit v1.2.3 From d7607906430242d45fd1526abd7c2cdc7b49990f Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Fri, 14 Jun 2024 16:41:38 +0200 Subject: Add basic test for create_identity function. Not an exhaustive test for now, but does at least excercise some of the code. --- tests/unit/CreateIdentityTest.php | 65 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tests/unit/CreateIdentityTest.php (limited to 'tests/unit') diff --git a/tests/unit/CreateIdentityTest.php b/tests/unit/CreateIdentityTest.php new file mode 100644 index 000000000..a5e0f278a --- /dev/null +++ b/tests/unit/CreateIdentityTest.php @@ -0,0 +1,65 @@ +assertEquals( + ['success' => false, 'message' => 'No account identifier'], + $result); + + $this->assertFalse($this->queueworker_started); + } + + public function test_create_new_channel_with_valid_account_id(): void { + insert_hook('proc_run', [$this, 'proc_run_hook']); + $result = create_identity([ + 'account_id' => $this->fixtures['account'][0]['account_id'], + 'nickname' => 'testuser', + 'name' => 'Olga Testuser', + ]); + + $this->assertTrue($result['success']); + $this->assertTrue($this->queueworker_started); + } + + public function test_create_new_channel_with_nnexistant_account_id(): void { + insert_hook('proc_run', [$this, 'proc_run_hook']); + $result = create_identity([ + 'account_id' => 666, + 'nickname' => 'testuser', + 'name' => 'Olga Testuser', + ]); + + /* + * We would expect this fo fail, but... + * + * The create_identity function will happily create a new channel with an + * non-existent account_id. The New_channel module will perform a check + * to ensure that only valid (and logged in) accounts can create a new channel. + * + * This is a bit weak, but for now we let it pass... + */ + $this->assertTrue($result['success']); + $this->assertTrue($this->queueworker_started); + } + + public function proc_run_hook(array &$args): void { + $args['run_cmd'] = false; + $this->queueworker_started = + $args['args'] === ['php', 'Zotlabs/Daemon/Master.php', 'Queueworker']; + } +} -- cgit v1.2.3 From 72453c49f8d3467e6599f01cecbf8e5926b6bd65 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Sat, 15 Jun 2024 11:37:32 +0200 Subject: tests: Add helper expectRedirectTo to module test class. Just a shorthand for manually stubbing `goaway` and setting the expectations on the test case. --- tests/unit/Module/TestCase.php | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tests/unit') diff --git a/tests/unit/Module/TestCase.php b/tests/unit/Module/TestCase.php index f2e19f265..2959eab79 100644 --- a/tests/unit/Module/TestCase.php +++ b/tests/unit/Module/TestCase.php @@ -74,6 +74,12 @@ class TestCase extends \Zotlabs\Tests\Unit\UnitTestCase { } ); } + + protected function expectRedirectTo(string $destination): void { + $this->stub_goaway(); + $this->expectException(RedirectException::class); + $this->expectExceptionMessage($destination); + } } /** -- cgit v1.2.3 From 62cbd87e71591bdd4c04f8cad07d6395d7f206c2 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Sat, 15 Jun 2024 13:00:19 +0200 Subject: Update API docs for Module test case base class. --- tests/unit/Module/TestCase.php | 104 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 98 insertions(+), 6 deletions(-) (limited to 'tests/unit') diff --git a/tests/unit/Module/TestCase.php b/tests/unit/Module/TestCase.php index 2959eab79..e92bc7083 100644 --- a/tests/unit/Module/TestCase.php +++ b/tests/unit/Module/TestCase.php @@ -1,8 +1,26 @@ assertStringContainsString($needle, \App::$page['content']); + $this->assertStringContainsString($needle, App::$page['content']); } /** * Stub out the `killme` function. * - * Usefule for modules that call this function directly. + * 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 { $killme_stub = $this->getFunctionMock('Zotlabs\Module', 'killme'); @@ -64,6 +110,42 @@ class TestCase extends \Zotlabs\Tests\Unit\UnitTestCase { ); } + /** + * 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 { $goaway_stub = $this->getFunctionMock('Zotlabs\Module', 'goaway'); $goaway_stub @@ -75,6 +157,16 @@ class TestCase extends \Zotlabs\Tests\Unit\UnitTestCase { ); } + /** + * 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); @@ -90,8 +182,8 @@ class KillmeException extends \Exception {} /** * Exception class for goaway stub. * - * Takes the goaway uri as an arg, and makes it available as - * the public `$uri` member variable. + * 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) { -- cgit v1.2.3