From 354c2d828a4a76ce542582e12aff06d38a253f6c Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 20:53:29 +0100
Subject: [PATCH 01/17] Simplify json testing

---
 tests/src/Module/Api/ApiTest.php              | 22 ++++++++++++++++++-
 .../Module/Api/Friendica/NotificationTest.php |  3 ++-
 .../Module/Api/Friendica/Photo/DeleteTest.php |  6 +----
 .../Api/Friendica/Photoalbum/DeleteTest.php   |  6 +----
 .../Api/Friendica/Photoalbum/UpdateTest.php   |  6 +----
 .../Api/GnuSocial/GnuSocial/ConfigTest.php    |  7 +-----
 .../Module/Api/GnuSocial/Help/TestTest.php    |  4 +++-
 .../Accounts/VerifyCredentialsTest.php        |  6 +----
 .../Twitter/Account/RateLimitStatusTest.php   |  2 +-
 .../Api/Twitter/Account/UpdateProfileTest.php |  6 +----
 .../Module/Api/Twitter/Blocks/ListsTest.php   |  6 +----
 .../Api/Twitter/Followers/ListsTest.php       |  6 +----
 .../Module/Api/Twitter/Friends/ListsTest.php  |  6 +----
 .../Api/Twitter/Friendships/IncomingTest.php  |  6 +----
 .../Module/Api/Twitter/Lists/StatusesTest.php |  6 +----
 .../Module/Api/Twitter/Media/UploadTest.php   | 11 +++++-----
 .../Module/Api/Twitter/SavedSearchesTest.php  |  2 +-
 17 files changed, 45 insertions(+), 66 deletions(-)

diff --git a/tests/src/Module/Api/ApiTest.php b/tests/src/Module/Api/ApiTest.php
index 154f54a1cf..9d690b1af3 100644
--- a/tests/src/Module/Api/ApiTest.php
+++ b/tests/src/Module/Api/ApiTest.php
@@ -22,6 +22,7 @@
 namespace Friendica\Test\src\Module\Api;
 
 use Friendica\App;
+use Friendica\Capabilities\ICanCreateResponses;
 use Friendica\Core\Addon;
 use Friendica\Core\Hook;
 use Friendica\Database\Database;
@@ -32,6 +33,7 @@ use Friendica\Test\FixtureTest;
 use Friendica\Test\Util\AppDouble;
 use Friendica\Test\Util\AuthenticationDouble;
 use Friendica\Test\Util\AuthTestConfig;
+use Psr\Http\Message\ResponseInterface;
 
 abstract class ApiTest extends FixtureTest
 {
@@ -50,6 +52,24 @@ abstract class ApiTest extends FixtureTest
 		// We could probably do more checks here.
 	}
 
+	/**
+	 * Transforms a response into a JSON class
+	 *
+	 * @param ResponseInterface $response
+	 *
+	 * @return mixed
+	 */
+	protected function toJson(ResponseInterface $response)
+	{
+		self::assertEquals(ICanCreateResponses::TYPE_JSON, $response->getHeaderLine(ICanCreateResponses::X_HEADER));
+
+		$body = (string)$response->getBody();
+
+		self::assertJson($body);
+
+		return json_decode($body);
+	}
+
 	protected function setUp(): void
 	{
 		parent::setUp(); // TODO: Change the autogenerated stub
@@ -63,7 +83,7 @@ abstract class ApiTest extends FixtureTest
 		DI::app()->setIsLoggedIn(true);
 
 		AuthTestConfig::$authenticated = true;
-		AuthTestConfig::$user_id = 42;
+		AuthTestConfig::$user_id       = 42;
 
 		$this->installAuthTest();
 	}
diff --git a/tests/src/Module/Api/Friendica/NotificationTest.php b/tests/src/Module/Api/Friendica/NotificationTest.php
index b5e2a41665..c9ab001418 100644
--- a/tests/src/Module/Api/Friendica/NotificationTest.php
+++ b/tests/src/Module/Api/Friendica/NotificationTest.php
@@ -78,7 +78,8 @@ XML;
 		$notification = new Notification(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']);
 		$response = $notification->run();
 
-		self::assertJson($response->getBody());
+		$this->toJson($response);
+
 		self::assertEquals(['Content-type' => ['application/json'], ICanCreateResponses::X_HEADER => ['json']], $response->getHeaders());
 	}
 }
diff --git a/tests/src/Module/Api/Friendica/Photo/DeleteTest.php b/tests/src/Module/Api/Friendica/Photo/DeleteTest.php
index 8c49456b36..05808d56c4 100644
--- a/tests/src/Module/Api/Friendica/Photo/DeleteTest.php
+++ b/tests/src/Module/Api/Friendica/Photo/DeleteTest.php
@@ -53,11 +53,7 @@ class DeleteTest extends ApiTest
 		$delete   = new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
 		$response = $delete->run(['photo_id' => '709057080661a283a6aa598501504178']);
 
-		$responseText = (string)$response->getBody();
-
-		self::assertJson($responseText);
-
-		$json = json_decode($responseText);
+		$json = $this->toJson($response);
 
 		self::assertEquals('deleted', $json->result);
 		self::assertEquals('photo with id `709057080661a283a6aa598501504178` has been deleted from server.', $json->message);
diff --git a/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php b/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php
index 88355483a3..230ba70c89 100644
--- a/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php
+++ b/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php
@@ -49,11 +49,7 @@ class DeleteTest extends ApiTest
 		$delete   = new Delete(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
 		$response = $delete->run(['album' => 'test_album']);
 
-		$responseText = (string)$response->getBody();
-
-		self::assertJson($responseText);
-
-		$json = json_decode($responseText);
+		$json = $this->toJson($response);
 
 		self::assertEquals('deleted', $json->result);
 		self::assertEquals('album `test_album` with all containing photos has been deleted.', $json->message);
diff --git a/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php b/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php
index 22ca155cbb..fa4638e370 100644
--- a/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php
+++ b/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php
@@ -58,11 +58,7 @@ class UpdateTest extends ApiTest
 
 		$response = (new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]))->run(['album' => 'test_album', 'album_new' => 'test_album_2']);
 
-		$responseBody = (string)$response->getBody();
-
-		self::assertJson($responseBody);
-
-		$json = json_decode($responseBody);
+		$json = $this->toJson($response);
 
 		self::assertEquals('updated', $json->result);
 		self::assertEquals('album `test_album` with all containing photos has been renamed to `test_album_2`.', $json->message);
diff --git a/tests/src/Module/Api/GnuSocial/GnuSocial/ConfigTest.php b/tests/src/Module/Api/GnuSocial/GnuSocial/ConfigTest.php
index 3cc1df2961..b1874d8386 100644
--- a/tests/src/Module/Api/GnuSocial/GnuSocial/ConfigTest.php
+++ b/tests/src/Module/Api/GnuSocial/GnuSocial/ConfigTest.php
@@ -19,13 +19,8 @@ class ConfigTest extends ApiTest
 
 		$config   = new Config(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
 		$response = $config->run();
-		$body     = (string)$response->getBody();
 
-		self::assertJson($body);
-
-		$json = json_decode($body);
-
-		self::assertEquals(1, 1);
+		$json = $this->toJson($response);
 
 		self::assertEquals('localhost', $json->site->server);
 		self::assertEquals('frio', $json->site->theme);
diff --git a/tests/src/Module/Api/GnuSocial/Help/TestTest.php b/tests/src/Module/Api/GnuSocial/Help/TestTest.php
index 5aa4286812..858c9b6cdc 100644
--- a/tests/src/Module/Api/GnuSocial/Help/TestTest.php
+++ b/tests/src/Module/Api/GnuSocial/Help/TestTest.php
@@ -14,8 +14,10 @@ class TestTest extends ApiTest
 		$test = new Test(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']);
 		$response = $test->run();
 
+		$json = $this->toJson($response);
+
 		self::assertEquals(['Content-type' => ['application/json'], ICanCreateResponses::X_HEADER => ['json']], $response->getHeaders());
-		self::assertEquals('"ok"', $response->getBody());
+		self::assertEquals('ok', $json);
 	}
 
 	public function testXml()
diff --git a/tests/src/Module/Api/Mastodon/Accounts/VerifyCredentialsTest.php b/tests/src/Module/Api/Mastodon/Accounts/VerifyCredentialsTest.php
index 5170f1cb2f..51d76696f6 100644
--- a/tests/src/Module/Api/Mastodon/Accounts/VerifyCredentialsTest.php
+++ b/tests/src/Module/Api/Mastodon/Accounts/VerifyCredentialsTest.php
@@ -19,11 +19,7 @@ class VerifyCredentialsTest extends ApiTest
 		$verifyCredentials = new VerifyCredentials(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
 		$response          = $verifyCredentials->run();
 
-		$body = (string)$response->getBody();
-
-		self::assertJson($body);
-
-		$json = json_decode($body);
+		$json = $this->toJson($response);
 
 		self::assertEquals(48, $json->id);
 		self::assertIsArray($json->emojis);
diff --git a/tests/src/Module/Api/Twitter/Account/RateLimitStatusTest.php b/tests/src/Module/Api/Twitter/Account/RateLimitStatusTest.php
index 1368990d08..a76b5d87e0 100644
--- a/tests/src/Module/Api/Twitter/Account/RateLimitStatusTest.php
+++ b/tests/src/Module/Api/Twitter/Account/RateLimitStatusTest.php
@@ -15,7 +15,7 @@ class RateLimitStatusTest extends ApiTest
 		$rateLimitStatus = new RateLimitStatus(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => 'json']);
 		$response = $rateLimitStatus->run();
 
-		$result = json_decode($response->getBody());
+		$result = $this->toJson($response);
 
 		self::assertEquals(['Content-type' => ['application/json'], ICanCreateResponses::X_HEADER => ['json']], $response->getHeaders());
 		self::assertEquals(150, $result->remaining_hits);
diff --git a/tests/src/Module/Api/Twitter/Account/UpdateProfileTest.php b/tests/src/Module/Api/Twitter/Account/UpdateProfileTest.php
index 4ce3420d26..e06e8d4848 100644
--- a/tests/src/Module/Api/Twitter/Account/UpdateProfileTest.php
+++ b/tests/src/Module/Api/Twitter/Account/UpdateProfileTest.php
@@ -17,11 +17,7 @@ class UpdateProfileTest extends ApiTest
 		$updateProfile = new UpdateProfile(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST], ['extension' => 'json']);
 		$response      = $updateProfile->run(['name' => 'new_name', 'description' => 'new_description']);
 
-		$body = (string)$response->getBody();
-
-		self::assertJson($body);
-
-		$json = json_decode($body);
+		$json = $this->toJson($response);
 
 		self::assertEquals('new_name', $json->name);
 		self::assertEquals('new_description', $json->description);
diff --git a/tests/src/Module/Api/Twitter/Blocks/ListsTest.php b/tests/src/Module/Api/Twitter/Blocks/ListsTest.php
index 4f63581a70..a37b59f036 100644
--- a/tests/src/Module/Api/Twitter/Blocks/ListsTest.php
+++ b/tests/src/Module/Api/Twitter/Blocks/ListsTest.php
@@ -17,11 +17,7 @@ class ListsTest extends ApiTest
 		$lists    = new Lists(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
 		$response = $lists->run();
 
-		$body = (string)$response->getBody();
-
-		self::assertJson($body);
-
-		$json = json_decode($body);
+		$json = $this->toJson($response);
 
 		self::assertIsArray($json->users);
 	}
diff --git a/tests/src/Module/Api/Twitter/Followers/ListsTest.php b/tests/src/Module/Api/Twitter/Followers/ListsTest.php
index c1e053e5a1..7ea3863eaf 100644
--- a/tests/src/Module/Api/Twitter/Followers/ListsTest.php
+++ b/tests/src/Module/Api/Twitter/Followers/ListsTest.php
@@ -17,11 +17,7 @@ class ListsTest extends ApiTest
 		$lists    = new Lists(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
 		$response = $lists->run();
 
-		$body = (string)$response->getBody();
-
-		self::assertJson($body);
-
-		$json = json_decode($body);
+		$json = $this->toJson($response);
 
 		self::assertIsArray($json->users);
 	}
diff --git a/tests/src/Module/Api/Twitter/Friends/ListsTest.php b/tests/src/Module/Api/Twitter/Friends/ListsTest.php
index 363f8d73c3..7cb5bd10a7 100644
--- a/tests/src/Module/Api/Twitter/Friends/ListsTest.php
+++ b/tests/src/Module/Api/Twitter/Friends/ListsTest.php
@@ -19,11 +19,7 @@ class ListsTest extends ApiTest
 		$lists    = new Lists(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
 		$response = $lists->run();
 
-		$body = (string)$response->getBody();
-
-		self::assertJson($body);
-
-		$json = json_decode($body);
+		$json = $this->toJson($response);
 
 		self::assertIsArray($json->users);
 	}
diff --git a/tests/src/Module/Api/Twitter/Friendships/IncomingTest.php b/tests/src/Module/Api/Twitter/Friendships/IncomingTest.php
index 8c5cb6426b..c1309e1f0a 100644
--- a/tests/src/Module/Api/Twitter/Friendships/IncomingTest.php
+++ b/tests/src/Module/Api/Twitter/Friendships/IncomingTest.php
@@ -19,11 +19,7 @@ class IncomingTest extends ApiTest
 		$lists    = new Incoming(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
 		$response = $lists->run();
 
-		$body = (string)$response->getBody();
-
-		self::assertJson($body);
-
-		$json = json_decode($body);
+		$json = $this->toJson($response);
 
 		self::assertIsArray($json->ids);
 	}
diff --git a/tests/src/Module/Api/Twitter/Lists/StatusesTest.php b/tests/src/Module/Api/Twitter/Lists/StatusesTest.php
index 5d989b71e7..3f47fcaca6 100644
--- a/tests/src/Module/Api/Twitter/Lists/StatusesTest.php
+++ b/tests/src/Module/Api/Twitter/Lists/StatusesTest.php
@@ -31,11 +31,7 @@ class StatusesTest extends ApiTest
 		$lists    = new Statuses(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
 		$response = $lists->run(['list_id' => 1, 'page' => -1, 'max_id' => 10]);
 
-		$body = (string)$response->getBody();
-
-		self::assertJson($body);
-
-		$json = json_decode($body);
+		$json = $this->toJson($response);
 
 		foreach ($json as $status) {
 			self::assertIsString($status->text);
diff --git a/tests/src/Module/Api/Twitter/Media/UploadTest.php b/tests/src/Module/Api/Twitter/Media/UploadTest.php
index abc9d8fdc6..5b0ce1186b 100644
--- a/tests/src/Module/Api/Twitter/Media/UploadTest.php
+++ b/tests/src/Module/Api/Twitter/Media/UploadTest.php
@@ -72,12 +72,13 @@ class UploadTest extends ApiTest
 		];
 
 		$response = (new Upload(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]))->run();
-		$media    = json_decode($response->getBody(), true);
 
-		self::assertEquals('image/png', $media['image']['image_type']);
-		self::assertEquals(1, $media['image']['w']);
-		self::assertEquals(1, $media['image']['h']);
-		self::assertNotEmpty($media['image']['friendica_preview_url']);
+		$media = $this->toJson($response);
+
+		self::assertEquals('image/png', $media->image->image_type);
+		self::assertEquals(1, $media->image->w);
+		self::assertEquals(1, $media->image->h);
+		self::assertNotEmpty($media->image->friendica_preview_url);
 	}
 
 	/**
diff --git a/tests/src/Module/Api/Twitter/SavedSearchesTest.php b/tests/src/Module/Api/Twitter/SavedSearchesTest.php
index 14973b3912..5735f8eef0 100644
--- a/tests/src/Module/Api/Twitter/SavedSearchesTest.php
+++ b/tests/src/Module/Api/Twitter/SavedSearchesTest.php
@@ -14,7 +14,7 @@ class SavedSearchesTest extends ApiTest
 		$savedSearch = new SavedSearches(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']);
 		$response = $savedSearch->run();
 
-		$result = json_decode($response->getBody());
+		$result = $this->toJson($response);
 
 		self::assertEquals(['Content-type' => ['application/json'], ICanCreateResponses::X_HEADER => ['json']], $response->getHeaders());
 		self::assertEquals(1, $result[0]->id);

From 4d330f287631bc0e053cae167414f4d8ed03e2e1 Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 21:03:33 +0100
Subject: [PATCH 02/17] Reenable Twitter/Destroy tests

---
 src/Module/Api/Twitter/Statuses/Destroy.php   |  9 +++++---
 .../Api/Mastodon/Accounts/StatusesTest.php    |  3 ---
 .../Api/Twitter/Statuses/DestroyTest.php      | 23 +++++++++++++++----
 3 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/src/Module/Api/Twitter/Statuses/Destroy.php b/src/Module/Api/Twitter/Statuses/Destroy.php
index a8c4be6f4e..8c2a8bf3eb 100644
--- a/src/Module/Api/Twitter/Statuses/Destroy.php
+++ b/src/Module/Api/Twitter/Statuses/Destroy.php
@@ -26,6 +26,7 @@ use Friendica\Module\BaseApi;
 use Friendica\DI;
 use Friendica\Model\Contact;
 use Friendica\Model\Item;
+use Friendica\Network\HTTPException\BadRequestException;
 
 /**
  * Destroys a specific status.
@@ -39,10 +40,12 @@ class Destroy extends BaseApi
 		BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
 		$uid = BaseApi::getCurrentUserID();
 
-		if (empty($this->parameters['id'])) {
-			$id = intval($request['id'] ?? 0);
-		} else {
+		if (empty($this->parameters['id']) && !empty($request['id'])) {
+			$id = intval($request['id']);
+		} elseif (!empty($this->parameters['id'])) {
 			$id = (int)$this->parameters['id'];
+		} else {
+			throw new BadRequestException('An id is missing.');
 		}
 
 		$this->logger->notice('API: api_statuses_destroy: ' . $id);
diff --git a/tests/src/Module/Api/Mastodon/Accounts/StatusesTest.php b/tests/src/Module/Api/Mastodon/Accounts/StatusesTest.php
index f2a709531c..297c92bae1 100644
--- a/tests/src/Module/Api/Mastodon/Accounts/StatusesTest.php
+++ b/tests/src/Module/Api/Mastodon/Accounts/StatusesTest.php
@@ -2,9 +2,6 @@
 
 namespace Friendica\Test\src\Module\Api\Mastodon\Accounts;
 
-use Friendica\App\Router;
-use Friendica\DI;
-use Friendica\Module\Api\Mastodon\Accounts\Statuses;
 use Friendica\Test\src\Module\Api\ApiTest;
 
 class StatusesTest extends ApiTest
diff --git a/tests/src/Module/Api/Twitter/Statuses/DestroyTest.php b/tests/src/Module/Api/Twitter/Statuses/DestroyTest.php
index 73f32c5d6b..9b2110eb6b 100644
--- a/tests/src/Module/Api/Twitter/Statuses/DestroyTest.php
+++ b/tests/src/Module/Api/Twitter/Statuses/DestroyTest.php
@@ -2,6 +2,10 @@
 
 namespace Friendica\Test\src\Module\Api\Twitter\Statuses;
 
+use Friendica\App\Router;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Statuses\Destroy;
+use Friendica\Network\HTTPException\BadRequestException;
 use Friendica\Test\src\Module\Api\ApiTest;
 
 class DestroyTest extends ApiTest
@@ -13,8 +17,10 @@ class DestroyTest extends ApiTest
 	 */
 	public function testApiStatusesDestroy()
 	{
-		// $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
-		// api_statuses_destroy('json');
+		$this->expectException(BadRequestException::class);
+
+		$destroy = new Destroy(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$destroy->run();
 	}
 
 	/**
@@ -24,6 +30,8 @@ class DestroyTest extends ApiTest
 	 */
 	public function testApiStatusesDestroyWithoutAuthenticatedUser()
 	{
+		self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first');
+
 		// $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
 		// BasicAuth::setCurrentUserID();
 		// $_SESSION['authenticated'] = false;
@@ -37,8 +45,13 @@ class DestroyTest extends ApiTest
 	 */
 	public function testApiStatusesDestroyWithId()
 	{
-		// DI::args()->setArgv(['', '', '', 1]);
-		// $result = api_statuses_destroy('json');
-		// self::assertStatus($result['status']);
+		$destroy = new Destroy(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$response = $destroy->run(['id' => 1]);
+
+		$json = $this->toJson($response);
+
+		self::assertEquals(1, $json->id);
+		self::assertIsObject($json->user);
+		self::assertIsObject($json->friendica_author);
 	}
 }

From 6fb3fa5875af2905a0668cfe0af39724237a5a52 Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 21:07:47 +0100
Subject: [PATCH 03/17] Reenable Twitter/Mentions tests

---
 .../Api/Twitter/Statuses/MentionsTest.php     | 36 +++++++++++++------
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/tests/src/Module/Api/Twitter/Statuses/MentionsTest.php b/tests/src/Module/Api/Twitter/Statuses/MentionsTest.php
index fb9a6b0b29..364af4a569 100644
--- a/tests/src/Module/Api/Twitter/Statuses/MentionsTest.php
+++ b/tests/src/Module/Api/Twitter/Statuses/MentionsTest.php
@@ -2,6 +2,10 @@
 
 namespace Friendica\Test\src\Module\Api\Twitter\Statuses;
 
+use Friendica\App\Router;
+use Friendica\Capabilities\ICanCreateResponses;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Statuses\Mentions;
 use Friendica\Test\src\Module\Api\ApiTest;
 
 class MentionsTest extends ApiTest
@@ -13,13 +17,13 @@ class MentionsTest extends ApiTest
 	 */
 	public function testApiStatusesMentions()
 	{
-		/*
-		$this->app->setLoggedInUserNickname($this->selfUser['nick']);
-		$_REQUEST['max_id'] = 10;
-		$result             = api_statuses_mentions('json');
-		self::assertEmpty($result['status']);
+		$mentions = new Mentions(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$response = $mentions->run(['max_id' => 10]);
+
+		$json = $this->toJson($response);
+
+		self::assertEmpty($json);
 		// We should test with mentions in the database.
-		*/
 	}
 
 	/**
@@ -29,9 +33,13 @@ class MentionsTest extends ApiTest
 	 */
 	public function testApiStatusesMentionsWithNegativePage()
 	{
-		// $_REQUEST['page'] = -2;
-		// $result           = api_statuses_mentions('json');
-		// self::assertEmpty($result['status']);
+		$mentions = new Mentions(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$response = $mentions->run(['page' => -2]);
+
+		$json = $this->toJson($response);
+
+		self::assertEmpty($json);
+		// We should test with mentions in the database.
 	}
 
 	/**
@@ -41,6 +49,8 @@ class MentionsTest extends ApiTest
 	 */
 	public function testApiStatusesMentionsWithUnallowedUser()
 	{
+		self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first');
+
 		// $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
 		// BasicAuth::setCurrentUserID();
 		// api_statuses_mentions('json');
@@ -53,7 +63,11 @@ class MentionsTest extends ApiTest
 	 */
 	public function testApiStatusesMentionsWithRss()
 	{
-		// $result = api_statuses_mentions('rss');
-		// self::assertXml($result, 'statuses');
+		$mentions = new Mentions(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => ICanCreateResponses::TYPE_RSS]);
+		$response = $mentions->run(['page' => -2]);
+
+		self::assertEquals(ICanCreateResponses::TYPE_RSS, $response->getHeaderLine(ICanCreateResponses::X_HEADER));
+
+		self::assertXml((string)$response->getBody(), 'statuses');
 	}
 }

From 7982190a3c012e7f701b091d79549b046f576d06 Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 21:11:40 +0100
Subject: [PATCH 04/17] Reenable Twitter/NetworkPublicTimeline tests

---
 .../Statuses/NetworkPublicTimelineTest.php    | 48 ++++++++++++-------
 1 file changed, 32 insertions(+), 16 deletions(-)

diff --git a/tests/src/Module/Api/Twitter/Statuses/NetworkPublicTimelineTest.php b/tests/src/Module/Api/Twitter/Statuses/NetworkPublicTimelineTest.php
index e340753f42..7d75cdd7d7 100644
--- a/tests/src/Module/Api/Twitter/Statuses/NetworkPublicTimelineTest.php
+++ b/tests/src/Module/Api/Twitter/Statuses/NetworkPublicTimelineTest.php
@@ -2,6 +2,10 @@
 
 namespace Friendica\Test\src\Module\Api\Twitter\Statuses;
 
+use Friendica\App\Router;
+use Friendica\Capabilities\ICanCreateResponses;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Statuses\NetworkPublicTimeline;
 use Friendica\Test\src\Module\Api\ApiTest;
 
 class NetworkPublicTimelineTest extends ApiTest
@@ -13,14 +17,17 @@ class NetworkPublicTimelineTest extends ApiTest
 	 */
 	public function testApiStatusesNetworkpublicTimeline()
 	{
-		/*
-		$_REQUEST['max_id'] = 10;
-		$result             = api_statuses_networkpublic_timeline('json');
-		self::assertNotEmpty($result['status']);
-		foreach ($result['status'] as $status) {
-			self::assertStatus($status);
+		$networkPublicTimeline = new NetworkPublicTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$response = $networkPublicTimeline->run(['max_id' => 10]);
+
+		$json = $this->toJson($response);
+
+		self::assertIsArray($json);
+		self::assertNotEmpty($json);
+		foreach ($json as $status) {
+			self::assertIsString($status->text);
+			self::assertIsInt($status->id);
 		}
-		*/
 	}
 
 	/**
@@ -30,14 +37,17 @@ class NetworkPublicTimelineTest extends ApiTest
 	 */
 	public function testApiStatusesNetworkpublicTimelineWithNegativePage()
 	{
-		/*
-		$_REQUEST['page'] = -2;
-		$result           = api_statuses_networkpublic_timeline('json');
-		self::assertNotEmpty($result['status']);
-		foreach ($result['status'] as $status) {
-			self::assertStatus($status);
+		$networkPublicTimeline = new NetworkPublicTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$response = $networkPublicTimeline->run(['page' => -2]);
+
+		$json = $this->toJson($response);
+
+		self::assertIsArray($json);
+		self::assertNotEmpty($json);
+		foreach ($json as $status) {
+			self::assertIsString($status->text);
+			self::assertIsInt($status->id);
 		}
-		*/
 	}
 
 	/**
@@ -47,6 +57,8 @@ class NetworkPublicTimelineTest extends ApiTest
 	 */
 	public function testApiStatusesNetworkpublicTimelineWithUnallowedUser()
 	{
+		self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first');
+
 		// $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
 		// BasicAuth::setCurrentUserID();
 		// api_statuses_networkpublic_timeline('json');
@@ -59,7 +71,11 @@ class NetworkPublicTimelineTest extends ApiTest
 	 */
 	public function testApiStatusesNetworkpublicTimelineWithRss()
 	{
-		// $result = api_statuses_networkpublic_timeline('rss');
-		// self::assertXml($result, 'statuses');
+		$networkPublicTimeline = new NetworkPublicTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => ICanCreateResponses::TYPE_RSS]);
+		$response = $networkPublicTimeline->run(['page' => -2]);
+
+		self::assertEquals(ICanCreateResponses::TYPE_RSS, $response->getHeaderLine(ICanCreateResponses::X_HEADER));
+
+		self::assertXml((string)$response->getBody(), 'statuses');
 	}
 }

From ccf7e251b5c3ef285a40875ea9390817509845f7 Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 21:17:00 +0100
Subject: [PATCH 05/17] Reenable Twitter/Statuses tests

---
 src/Module/Api/Twitter/Statuses/Show.php      |  8 ++--
 .../Module/Api/Twitter/Statuses/ShowTest.php  | 40 +++++++++++++------
 2 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/src/Module/Api/Twitter/Statuses/Show.php b/src/Module/Api/Twitter/Statuses/Show.php
index 66939bf7ac..905c220f6d 100644
--- a/src/Module/Api/Twitter/Statuses/Show.php
+++ b/src/Module/Api/Twitter/Statuses/Show.php
@@ -42,14 +42,14 @@ class Show extends BaseApi
 		$uid = BaseApi::getCurrentUserID();
 
 		if (empty($this->parameters['id'])) {
-			$id = intval($_REQUEST['id'] ?? 0);
+			$id = intval($request['id'] ?? 0);
 		} else {
 			$id = (int)$this->parameters['id'];
 		}
 
 		Logger::notice('API: api_statuses_show: ' . $id);
 
-		$conversation = !empty($_REQUEST['conversation']);
+		$conversation = !empty($request['conversation']);
 
 		// try to fetch the item for the local user - or the public item, if there is no local one
 		$uri_item = Post::selectFirst(['uri-id'], ['id' => $id]);
@@ -79,7 +79,7 @@ class Show extends BaseApi
 			throw new BadRequestException(sprintf("There is no status or conversation with the id %d.", $id));
 		}
 
-		$include_entities = strtolower(($_REQUEST['include_entities'] ?? 'false') == 'true');
+		$include_entities = strtolower(($request['include_entities'] ?? 'false') == 'true');
 
 		$ret = [];
 		while ($status = DBA::fetch($statuses)) {
@@ -92,7 +92,7 @@ class Show extends BaseApi
 			$this->response->exit('statuses', $data, $this->parameters['extension'] ?? null, Contact::getPublicIdByUserId($uid));
 		} else {
 			$data = ['status' => $ret[0]];
-			$this->response->exit('status', ['status' => $data], $this->parameters['extension'] ?? null, Contact::getPublicIdByUserId($uid));
+			$this->response->exit('status', $data, $this->parameters['extension'] ?? null, Contact::getPublicIdByUserId($uid));
 		}
 	}
 }
diff --git a/tests/src/Module/Api/Twitter/Statuses/ShowTest.php b/tests/src/Module/Api/Twitter/Statuses/ShowTest.php
index 00fcbd5541..c2d87a95f4 100644
--- a/tests/src/Module/Api/Twitter/Statuses/ShowTest.php
+++ b/tests/src/Module/Api/Twitter/Statuses/ShowTest.php
@@ -2,6 +2,10 @@
 
 namespace Friendica\Test\src\Module\Api\Twitter\Statuses;
 
+use Friendica\App\Router;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Statuses\Show;
+use Friendica\Network\HTTPException\BadRequestException;
 use Friendica\Test\src\Module\Api\ApiTest;
 
 class ShowTest extends ApiTest
@@ -13,8 +17,10 @@ class ShowTest extends ApiTest
 	 */
 	public function testApiStatusesShow()
 	{
-		// $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
-		// api_statuses_show('json');
+		$this->expectException(BadRequestException::class);
+
+		$show = new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$show->run();
 	}
 
 	/**
@@ -24,9 +30,13 @@ class ShowTest extends ApiTest
 	 */
 	public function testApiStatusesShowWithId()
 	{
-		// DI::args()->setArgv(['', '', '', 1]);
-		// $result = api_statuses_show('json');
-		// self::assertStatus($result['status']);
+		$show = new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$response = $show->run(['id' => 1]);
+
+		$json = $this->toJson($response);
+
+		self::assertIsInt($json->id);
+		self::assertIsString($json->text);
 	}
 
 	/**
@@ -36,15 +46,17 @@ class ShowTest extends ApiTest
 	 */
 	public function testApiStatusesShowWithConversation()
 	{
-		/*
-		DI::args()->setArgv(['', '', '', 1]);
-		$_REQUEST['conversation'] = 1;
-		$result                   = api_statuses_show('json');
-		self::assertNotEmpty($result['status']);
-		foreach ($result['status'] as $status) {
-			self::assertStatus($status);
+		$show = new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$response = $show->run(['id' => 1, 'conversation' => 1]);
+
+		$json = $this->toJson($response);
+
+		self::assertIsArray($json);
+
+		foreach ($json as $status) {
+			self::assertIsInt($status->id);
+			self::assertIsString($status->text);
 		}
-		*/
 	}
 
 	/**
@@ -54,6 +66,8 @@ class ShowTest extends ApiTest
 	 */
 	public function testApiStatusesShowWithUnallowedUser()
 	{
+		self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first');
+
 		// $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
 		// BasicAuth::setCurrentUserID();
 		// api_statuses_show('json');

From f9c490b29a96b1e5e7443a55b326abb123cb3cf8 Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 21:23:58 +0100
Subject: [PATCH 06/17] Reenable Twitter/UserTimeline tests

---
 .../Api/Twitter/Statuses/UserTimeline.php     | 20 +++---
 .../Api/Twitter/Statuses/UserTimelineTest.php | 63 ++++++++++++-------
 2 files changed, 52 insertions(+), 31 deletions(-)

diff --git a/src/Module/Api/Twitter/Statuses/UserTimeline.php b/src/Module/Api/Twitter/Statuses/UserTimeline.php
index ba713c7651..65f5c35146 100644
--- a/src/Module/Api/Twitter/Statuses/UserTimeline.php
+++ b/src/Module/Api/Twitter/Statuses/UserTimeline.php
@@ -40,17 +40,17 @@ class UserTimeline extends BaseApi
 		BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
 		$uid = BaseApi::getCurrentUserID();
 
-		Logger::info('api_statuses_user_timeline', ['api_user' => $uid, '_REQUEST' => $_REQUEST]);
+		Logger::info('api_statuses_user_timeline', ['api_user' => $uid, '_REQUEST' => $request]);
 
-		$cid             = BaseApi::getContactIDForSearchterm($_REQUEST['screen_name'] ?? '', $_REQUEST['profileurl'] ?? '', $_REQUEST['user_id'] ?? 0, $uid);
-		$since_id        = $_REQUEST['since_id'] ?? 0;
-		$max_id          = $_REQUEST['max_id']   ?? 0;
-		$exclude_replies = !empty($_REQUEST['exclude_replies']);
-		$conversation_id = $_REQUEST['conversation_id'] ?? 0;
+		$cid             = BaseApi::getContactIDForSearchterm($request['screen_name'] ?? '', $request['profileurl'] ?? '', $request['user_id'] ?? 0, $uid);
+		$since_id        = $request['since_id'] ?? 0;
+		$max_id          = $request['max_id']   ?? 0;
+		$exclude_replies = !empty($request['exclude_replies']);
+		$conversation_id = $request['conversation_id'] ?? 0;
 
 		// pagination
-		$count = $_REQUEST['count'] ?? 20;
-		$page  = $_REQUEST['page']  ?? 1;
+		$count = $request['count'] ?? 20;
+		$page  = $request['page']  ?? 1;
 
 		$start = max(0, ($page - 1) * $count);
 
@@ -74,7 +74,7 @@ class UserTimeline extends BaseApi
 		$params   = ['order' => ['id' => true], 'limit' => [$start, $count]];
 		$statuses = Post::selectForUser($uid, [], $condition, $params);
 
-		$include_entities = strtolower(($_REQUEST['include_entities'] ?? 'false') == 'true');
+		$include_entities = strtolower(($request['include_entities'] ?? 'false') == 'true');
 
 		$ret = [];
 		while ($status = DBA::fetch($statuses)) {
@@ -82,6 +82,6 @@ class UserTimeline extends BaseApi
 		}
 		DBA::close($statuses);
 
-		$this->response->exit('user', ['status' => $ret], $this->parameters['extension'] ?? null, Contact::getPublicIdByUserId($uid));
+		$this->response->exit('statuses', ['status' => $ret], $this->parameters['extension'] ?? null, Contact::getPublicIdByUserId($uid));
 	}
 }
diff --git a/tests/src/Module/Api/Twitter/Statuses/UserTimelineTest.php b/tests/src/Module/Api/Twitter/Statuses/UserTimelineTest.php
index 1e4f9cbb7e..fc2565e31c 100644
--- a/tests/src/Module/Api/Twitter/Statuses/UserTimelineTest.php
+++ b/tests/src/Module/Api/Twitter/Statuses/UserTimelineTest.php
@@ -2,6 +2,10 @@
 
 namespace Friendica\Test\src\Module\Api\Twitter\Statuses;
 
+use Friendica\App\Router;
+use Friendica\Capabilities\ICanCreateResponses;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Statuses\UserTimeline;
 use Friendica\Test\src\Module\Api\ApiTest;
 
 class UserTimelineTest extends ApiTest
@@ -13,18 +17,23 @@ class UserTimelineTest extends ApiTest
 	 */
 	public function testApiStatusesUserTimeline()
 	{
-		/*
-			$_REQUEST['user_id']         = 42;
-			$_REQUEST['max_id']          = 10;
-			$_REQUEST['exclude_replies'] = true;
-			$_REQUEST['conversation_id'] = 7;
+		$networkPublicTimeline = new UserTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
 
-			$result = api_statuses_user_timeline('json');
-			self::assertNotEmpty($result['status']);
-			foreach ($result['status'] as $status) {
-				self::assertStatus($status);
-			}
-			*/
+		$response = $networkPublicTimeline->run([
+			'user_id'         => 42,
+			'max_id'          => 10,
+			'exclude_replies' => true,
+			'conversation_id' => 7,
+		]);
+
+		$json = $this->toJson($response);
+
+		self::assertIsArray($json);
+		self::assertNotEmpty($json);
+		foreach ($json as $status) {
+			self::assertIsString($status->text);
+			self::assertIsInt($status->id);
+		}
 	}
 
 	/**
@@ -34,16 +43,21 @@ class UserTimelineTest extends ApiTest
 	 */
 	public function testApiStatusesUserTimelineWithNegativePage()
 	{
-		/*
-		$_REQUEST['user_id'] = 42;
-		$_REQUEST['page']    = -2;
+		$networkPublicTimeline = new UserTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
 
-		$result = api_statuses_user_timeline('json');
-		self::assertNotEmpty($result['status']);
-		foreach ($result['status'] as $status) {
-			self::assertStatus($status);
+		$response = $networkPublicTimeline->run([
+			'user_id' => 42,
+			'page'    => -2,
+		]);
+
+		$json = $this->toJson($response);
+
+		self::assertIsArray($json);
+		self::assertNotEmpty($json);
+		foreach ($json as $status) {
+			self::assertIsString($status->text);
+			self::assertIsInt($status->id);
 		}
-		*/
 	}
 
 	/**
@@ -53,8 +67,13 @@ class UserTimelineTest extends ApiTest
 	 */
 	public function testApiStatusesUserTimelineWithRss()
 	{
-		// $result = api_statuses_user_timeline('rss');
-		// self::assertXml($result, 'statuses');
+		$networkPublicTimeline = new UserTimeline(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => ICanCreateResponses::TYPE_RSS]);
+
+		$response = $networkPublicTimeline->run();
+
+		self::assertEquals(ICanCreateResponses::TYPE_RSS, $response->getHeaderLine(ICanCreateResponses::X_HEADER));
+
+		self::assertXml((string)$response->getBody(), 'statuses');
 	}
 
 	/**
@@ -64,6 +83,8 @@ class UserTimelineTest extends ApiTest
 	 */
 	public function testApiStatusesUserTimelineWithUnallowedUser()
 	{
+		self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first');
+
 		// $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
 		// BasicAuth::setCurrentUserID();
 		// api_statuses_user_timeline('json');

From 616cf012f9beb5efbf210c9f6eb79038a210ef10 Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 21:32:17 +0100
Subject: [PATCH 07/17] Reenable Twitter/Lookup tests & add standard assertions

---
 src/Module/Api/Twitter/Users/Lookup.php       |  4 +-
 tests/legacy/ApiTest.php                      | 49 ------------
 tests/src/Module/Api/ApiTest.php              | 74 +++++++++++++++++++
 .../Module/Api/Twitter/Users/LookupTest.php   | 19 +++--
 4 files changed, 90 insertions(+), 56 deletions(-)

diff --git a/src/Module/Api/Twitter/Users/Lookup.php b/src/Module/Api/Twitter/Users/Lookup.php
index 9d4c460c6e..2633020e84 100644
--- a/src/Module/Api/Twitter/Users/Lookup.php
+++ b/src/Module/Api/Twitter/Users/Lookup.php
@@ -39,8 +39,8 @@ class Lookup extends BaseApi
 
 		$users = [];
 
-		if (!empty($_REQUEST['user_id'])) {
-			foreach (explode(',', $_REQUEST['user_id']) as $cid) {
+		if (!empty($request['user_id'])) {
+			foreach (explode(',', $request['user_id']) as $cid) {
 				if (!empty($cid) && is_numeric($cid)) {
 					$users[] = DI::twitterUser()->createFromContactId((int)$cid, $uid, false)->toArray();
 				}
diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php
index 2067a35362..fea2bd5f1b 100644
--- a/tests/legacy/ApiTest.php
+++ b/tests/legacy/ApiTest.php
@@ -112,55 +112,6 @@ class ApiTest extends FixtureTest
 		BasicAuth::setCurrentUserID($this->selfUser['id']);
 	}
 
-	/**
-	 * Assert that an user array contains expected keys.
-	 *
-	 * @param array $user User array
-	 *
-	 * @return void
-	 */
-	private function assertSelfUser(array $user)
-	{
-		self::assertEquals($this->selfUser['id'], $user['uid']);
-		self::assertEquals($this->selfUser['id'], $user['cid']);
-		self::assertEquals(1, $user['self']);
-		self::assertEquals('DFRN', $user['location']);
-		self::assertEquals($this->selfUser['name'], $user['name']);
-		self::assertEquals($this->selfUser['nick'], $user['screen_name']);
-		self::assertEquals('dfrn', $user['network']);
-		self::assertTrue($user['verified']);
-	}
-
-	/**
-	 * Assert that an user array contains expected keys.
-	 *
-	 * @param array $user User array
-	 *
-	 * @return void
-	 */
-	private function assertOtherUser(array $user = [])
-	{
-		self::assertEquals($this->otherUser['id'], $user['id']);
-		self::assertEquals($this->otherUser['id'], $user['id_str']);
-		self::assertEquals($this->otherUser['name'], $user['name']);
-		self::assertEquals($this->otherUser['nick'], $user['screen_name']);
-		self::assertFalse($user['verified']);
-	}
-
-	/**
-	 * Assert that a status array contains expected keys.
-	 *
-	 * @param array $status Status array
-	 *
-	 * @return void
-	 */
-	private function assertStatus(array $status = [])
-	{
-		self::assertIsString($status['text'] ?? '');
-		self::assertIsInt($status['id'] ?? '');
-		// We could probably do more checks here.
-	}
-
 	/**
 	 * Assert that a list array contains expected keys.
 	 *
diff --git a/tests/src/Module/Api/ApiTest.php b/tests/src/Module/Api/ApiTest.php
index 9d690b1af3..09fbb7bbe9 100644
--- a/tests/src/Module/Api/ApiTest.php
+++ b/tests/src/Module/Api/ApiTest.php
@@ -37,6 +37,31 @@ use Psr\Http\Message\ResponseInterface;
 
 abstract class ApiTest extends FixtureTest
 {
+	// User data that the test database is populated with
+	const SELF_USER = [
+		'id'   => 42,
+		'name' => 'Self contact',
+		'nick' => 'selfcontact',
+		'nurl' => 'http://localhost/profile/selfcontact'
+	];
+
+	const FRIEND_USER = [
+		'id'   => 44,
+		'name' => 'Friend contact',
+		'nick' => 'friendcontact',
+		'nurl' => 'http://localhost/profile/friendcontact'
+	];
+
+	const OTHER_USER = [
+		'id'   => 43,
+		'name' => 'othercontact',
+		'nick' => 'othercontact',
+		'nurl' => 'http://localhost/profile/othercontact'
+	];
+
+	// User ID that we know is not in the database
+	const WRONG_USER_ID = 666;
+
 	/**
 	 * Assert that the string is XML and contain the root element.
 	 *
@@ -52,6 +77,55 @@ abstract class ApiTest extends FixtureTest
 		// We could probably do more checks here.
 	}
 
+	/**
+	 * Assert that an user array contains expected keys.
+	 *
+	 * @param \stdClass $user User
+	 *
+	 * @return void
+	 */
+	protected function assertSelfUser(\stdClass $user)
+	{
+		self::assertEquals(self::SELF_USER['id'], $user->uid);
+		self::assertEquals(self::SELF_USER['id'], $user->cid);
+		self::assertEquals(1, $user->self);
+		self::assertEquals('DFRN', $user->location);
+		self::assertEquals(self::SELF_USER['name'], $user->name);
+		self::assertEquals(self::SELF_USER['nick'], $user->screen_name);
+		self::assertEquals('dfrn', $user->network);
+		self::assertTrue($user->verified);
+	}
+
+	/**
+	 * Assert that an user array contains expected keys.
+	 *
+	 * @param \stdClass $user User
+	 *
+	 * @return void
+	 */
+	protected function assertOtherUser(\stdClass $user)
+	{
+		self::assertEquals(self::OTHER_USER['id'], $user->id);
+		self::assertEquals(self::OTHER_USER['id'], $user->id_str);
+		self::assertEquals(self::OTHER_USER['name'], $user->name);
+		self::assertEquals(self::OTHER_USER['nick'], $user->screen_name);
+		self::assertFalse($user->verified);
+	}
+
+	/**
+	 * Assert that a status array contains expected keys.
+	 *
+	 * @param array $status Status array
+	 *
+	 * @return void
+	 */
+	protected function assertStatus(array $status = [])
+	{
+		self::assertIsString($status['text'] ?? '');
+		self::assertIsInt($status['id'] ?? '');
+		// We could probably do more checks here.
+	}
+
 	/**
 	 * Transforms a response into a JSON class
 	 *
diff --git a/tests/src/Module/Api/Twitter/Users/LookupTest.php b/tests/src/Module/Api/Twitter/Users/LookupTest.php
index ddcedbc763..e54d20dcfb 100644
--- a/tests/src/Module/Api/Twitter/Users/LookupTest.php
+++ b/tests/src/Module/Api/Twitter/Users/LookupTest.php
@@ -2,6 +2,10 @@
 
 namespace Friendica\Test\src\Module\Api\Twitter\Users;
 
+use Friendica\App\Router;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Users\Lookup;
+use Friendica\Network\HTTPException\NotFoundException;
 use Friendica\Test\src\Module\Api\ApiTest;
 
 class LookupTest extends ApiTest
@@ -13,8 +17,10 @@ class LookupTest extends ApiTest
 	 */
 	public function testApiUsersLookup()
 	{
-		// $this->expectException(\Friendica\Network\HTTPException\NotFoundException::class);
-		// api_users_lookup('json');
+		$this->expectException(NotFoundException::class);
+
+		$lookup = new Lookup(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$lookup->run();
 	}
 
 	/**
@@ -24,8 +30,11 @@ class LookupTest extends ApiTest
 	 */
 	public function testApiUsersLookupWithUserId()
 	{
-		// $_REQUEST['user_id'] = $this->otherUser['id'];
-		// $result              = api_users_lookup('json');
-		// self::assertOtherUser($result['users'][0]);
+		$lookup = new Lookup(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$respone = $lookup->run(['user_id' => static::OTHER_USER['id']]);
+
+		$json = $this->toJson($respone);
+
+		self::assertOtherUser($json[0]);
 	}
 }

From e10045f13fe87cc1d2eec1b68265d091b42ec49f Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 21:37:16 +0100
Subject: [PATCH 08/17] Reenable Twitter/Search test

---
 src/Module/Api/Twitter/Users/Search.php       | 14 +++++-----
 .../Module/Api/Twitter/Users/SearchTest.php   | 27 +++++++++++++------
 2 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/src/Module/Api/Twitter/Users/Search.php b/src/Module/Api/Twitter/Users/Search.php
index 9c7be2f515..d53ba1e9b6 100644
--- a/src/Module/Api/Twitter/Users/Search.php
+++ b/src/Module/Api/Twitter/Users/Search.php
@@ -42,15 +42,15 @@ class Search extends BaseApi
 
 		$userlist = [];
 
-		if (!empty($_GET['q'])) {
+		if (!empty($request['q'])) {
 			$contacts = Contact::selectToArray(
 				['id'],
 				[
 					'`uid` = 0 AND (`name` = ? OR `nick` = ? OR `url` = ? OR `addr` = ?)',
-					$_GET['q'],
-					$_GET['q'],
-					$_GET['q'],
-					$_GET['q'],
+					$request['q'],
+					$request['q'],
+					$request['q'],
+					$request['q'],
 				]
 			);
 
@@ -63,12 +63,12 @@ class Search extends BaseApi
 				}
 				$userlist = ['users' => $userlist];
 			} else {
-				throw new NotFoundException('User ' . $_GET['q'] . ' not found.');
+				throw new NotFoundException('User ' . $request['q'] . ' not found.');
 			}
 		} else {
 			throw new BadRequestException('No search term specified.');
 		}
 
-		$this->response->exit('users', ['user' => $userlist], $this->parameters['extension'] ?? null);
+		$this->response->exit('users', $userlist, $this->parameters['extension'] ?? null);
 	}
 }
diff --git a/tests/src/Module/Api/Twitter/Users/SearchTest.php b/tests/src/Module/Api/Twitter/Users/SearchTest.php
index ce088a5412..4fee774dac 100644
--- a/tests/src/Module/Api/Twitter/Users/SearchTest.php
+++ b/tests/src/Module/Api/Twitter/Users/SearchTest.php
@@ -2,6 +2,11 @@
 
 namespace Friendica\Test\src\Module\Api\Twitter\Users;
 
+use Friendica\App\Router;
+use Friendica\Capabilities\ICanCreateResponses;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Users\Search;
+use Friendica\Network\HTTPException\BadRequestException;
 use Friendica\Test\src\Module\Api\ApiTest;
 
 class SearchTest extends ApiTest
@@ -13,9 +18,12 @@ class SearchTest extends ApiTest
 	 */
 	public function testApiUsersSearch()
 	{
-		// $_GET['q'] = 'othercontact';
-		// $result    = api_users_search('json');
-		// self::assertOtherUser($result['users'][0]);
+		$search = new Search(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$respone = $search->run(['q' => static::OTHER_USER['name']]);
+
+		$json = $this->toJson($respone);
+
+		self::assertOtherUser($json[0]);
 	}
 
 	/**
@@ -25,9 +33,10 @@ class SearchTest extends ApiTest
 	 */
 	public function testApiUsersSearchWithXml()
 	{
-		// $_GET['q'] = 'othercontact';
-		// $result    = api_users_search('xml');
-		// self::assertXml($result, 'users');
+		$search = new Search(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => ICanCreateResponses::TYPE_XML]);
+		$respone = $search->run(['q' => static::OTHER_USER['name']]);
+
+		self::assertXml((string)$respone->getBody(), 'users');
 	}
 
 	/**
@@ -37,7 +46,9 @@ class SearchTest extends ApiTest
 	 */
 	public function testApiUsersSearchWithoutQuery()
 	{
-		// $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
-		// api_users_search('json');
+		$this->expectException(BadRequestException::class);
+
+		$search = new Search(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$search->run();
 	}
 }

From 2b57266c88dcc5a8c54dc5de577c5383280b0423 Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 21:43:35 +0100
Subject: [PATCH 09/17] Reenable Twitter/Show test

---
 src/Module/Api/Twitter/Users/Show.php         |  2 +-
 .../src/Module/Api/Twitter/Users/ShowTest.php | 30 ++++++++++++-------
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/src/Module/Api/Twitter/Users/Show.php b/src/Module/Api/Twitter/Users/Show.php
index ce662eb352..77f79166de 100644
--- a/src/Module/Api/Twitter/Users/Show.php
+++ b/src/Module/Api/Twitter/Users/Show.php
@@ -38,7 +38,7 @@ class Show extends BaseApi
 		$uid = BaseApi::getCurrentUserID();
 
 		if (empty($this->parameters['id'])) {
-			$cid = BaseApi::getContactIDForSearchterm($_REQUEST['screen_name'] ?? '', $_REQUEST['profileurl'] ?? '', $_REQUEST['user_id'] ?? 0, $uid);
+			$cid = BaseApi::getContactIDForSearchterm($request['screen_name'] ?? '', $request['profileurl'] ?? '', $request['user_id'] ?? 0, $uid);
 		} else {
 			$cid = (int)$this->parameters['id'];
 		}
diff --git a/tests/src/Module/Api/Twitter/Users/ShowTest.php b/tests/src/Module/Api/Twitter/Users/ShowTest.php
index e34f5c28a3..975bf6d8f1 100644
--- a/tests/src/Module/Api/Twitter/Users/ShowTest.php
+++ b/tests/src/Module/Api/Twitter/Users/ShowTest.php
@@ -2,6 +2,10 @@
 
 namespace Friendica\Test\src\Module\Api\Twitter\Users;
 
+use Friendica\App\Router;
+use Friendica\Capabilities\ICanCreateResponses;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Users\Show;
 use Friendica\Test\src\Module\Api\ApiTest;
 
 class ShowTest extends ApiTest
@@ -13,15 +17,17 @@ class ShowTest extends ApiTest
 	 */
 	public function testApiUsersShow()
 	{
-		/*
-		$result = api_users_show('json');
+		$show = new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$response = $show->run();
+
+		$json = $this->toJson($response);
+
 		// We can't use assertSelfUser() here because the user object is missing some properties.
-		self::assertEquals($this->selfUser['id'], $result['user']['cid']);
-		self::assertEquals('DFRN', $result['user']['location']);
-		self::assertEquals($this->selfUser['name'], $result['user']['name']);
-		self::assertEquals($this->selfUser['nick'], $result['user']['screen_name']);
-		self::assertTrue($result['user']['verified']);
-		*/
+		self::assertEquals(static::SELF_USER['id'], $json->cid);
+		self::assertEquals('DFRN', $json->location);
+		self::assertEquals(static::SELF_USER['name'], $json->name);
+		self::assertEquals(static::SELF_USER['nick'], $json->screen_name);
+		self::assertTrue($json->verified);
 	}
 
 	/**
@@ -31,7 +37,11 @@ class ShowTest extends ApiTest
 	 */
 	public function testApiUsersShowWithXml()
 	{
-		// $result = api_users_show('xml');
-		// self::assertXml($result, 'statuses');
+		$show = new Show(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => ICanCreateResponses::TYPE_XML]);
+		$response = $show->run();
+
+		self::assertEquals(ICanCreateResponses::TYPE_XML, $response->getHeaderLine(ICanCreateResponses::X_HEADER));
+
+		self::assertXml((string)$response->getBody(), 'statuses');
 	}
 }

From 732ef70b8d1b0a8334c1d1444ce1ed376a1760e1 Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 21:47:49 +0100
Subject: [PATCH 10/17] Sadly mark incomplete Twitter/ContactEndpoint tests

---
 tests/src/Module/Api/Twitter/ContactEndpointTest.php | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/tests/src/Module/Api/Twitter/ContactEndpointTest.php b/tests/src/Module/Api/Twitter/ContactEndpointTest.php
index 65d28c4522..01e337cf78 100644
--- a/tests/src/Module/Api/Twitter/ContactEndpointTest.php
+++ b/tests/src/Module/Api/Twitter/ContactEndpointTest.php
@@ -32,6 +32,8 @@ class ContactEndpointTest extends FixtureTest
 {
 	public function testIds()
 	{
+		self::markTestIncomplete('Needs overall refactoring due changed method signature - Calling MrPetovan for help ;-)');
+
 		/*
 		$expectedEmpty = [
 			'ids' => [],
@@ -77,6 +79,8 @@ class ContactEndpointTest extends FixtureTest
 	 */
 	public function testIdsStringify()
 	{
+		self::markTestIncomplete('Needs overall refactoring due changed method signature - Calling MrPetovan for help ;-)');
+
 		/*
 		$result = ContactEndpointMock::ids(Contact::SHARING, 42, -1, ContactEndpoint::DEFAULT_COUNT, true);
 
@@ -88,6 +92,8 @@ class ContactEndpointTest extends FixtureTest
 
 	public function testIdsPagination()
 	{
+		self::markTestIncomplete('Needs overall refactoring due changed method signature - Calling MrPetovan for help ;-)');
+
 		/*
 		$expectedDefaultPageResult = [
 			'ids' => [45],
@@ -172,6 +178,8 @@ class ContactEndpointTest extends FixtureTest
 	 */
 	public function testList()
 	{
+		self::markTestIncomplete('Needs overall refactoring due changed method signature - Calling MrPetovan for help ;-)');
+
 		/*
 		$expectedEmpty = [
 			'users' => [],

From f84c696925467f4091a6ac2e27f97d6a921c1643 Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 21:52:40 +0100
Subject: [PATCH 11/17] Reenable Twitter/Favorites tests

---
 src/Module/Api/Twitter/Favorites.php          | 10 +++---
 tests/src/Module/Api/ApiTest.php              |  8 ++---
 .../src/Module/Api/Twitter/FavoritesTest.php  | 31 +++++++++++++------
 3 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/src/Module/Api/Twitter/Favorites.php b/src/Module/Api/Twitter/Favorites.php
index f806b23eec..8f4643f820 100644
--- a/src/Module/Api/Twitter/Favorites.php
+++ b/src/Module/Api/Twitter/Favorites.php
@@ -45,10 +45,10 @@ class Favorites extends BaseApi
 		Logger::info(BaseApi::LOG_PREFIX . 'for {self}', ['module' => 'api', 'action' => 'favorites']);
 
 		// params
-		$since_id = $_REQUEST['since_id'] ?? 0;
-		$max_id   = $_REQUEST['max_id']   ?? 0;
-		$count    = $_GET['count']        ?? 20;
-		$page     = $_REQUEST['page']     ?? 1;
+		$since_id = $request['since_id'] ?? 0;
+		$max_id   = $request['max_id']   ?? 0;
+		$count    = $request['count']    ?? 20;
+		$page     = $request['page']     ?? 1;
 
 		$start = max(0, ($page - 1) * $count);
 
@@ -64,7 +64,7 @@ class Favorites extends BaseApi
 
 		$statuses = Post::selectForUser($uid, [], $condition, $params);
 
-		$include_entities = strtolower(($_REQUEST['include_entities'] ?? 'false') == 'true');
+		$include_entities = strtolower(($request['include_entities'] ?? 'false') == 'true');
 
 		$ret = [];
 		while ($status = DBA::fetch($statuses)) {
diff --git a/tests/src/Module/Api/ApiTest.php b/tests/src/Module/Api/ApiTest.php
index 09fbb7bbe9..9820061e03 100644
--- a/tests/src/Module/Api/ApiTest.php
+++ b/tests/src/Module/Api/ApiTest.php
@@ -115,14 +115,14 @@ abstract class ApiTest extends FixtureTest
 	/**
 	 * Assert that a status array contains expected keys.
 	 *
-	 * @param array $status Status array
+	 * @param \stdClass $status Status
 	 *
 	 * @return void
 	 */
-	protected function assertStatus(array $status = [])
+	protected function assertStatus(\stdClass $status)
 	{
-		self::assertIsString($status['text'] ?? '');
-		self::assertIsInt($status['id'] ?? '');
+		self::assertIsString($status->text);
+		self::assertIsInt($status->id);
 		// We could probably do more checks here.
 	}
 
diff --git a/tests/src/Module/Api/Twitter/FavoritesTest.php b/tests/src/Module/Api/Twitter/FavoritesTest.php
index 26729144ee..dd95d73f90 100644
--- a/tests/src/Module/Api/Twitter/FavoritesTest.php
+++ b/tests/src/Module/Api/Twitter/FavoritesTest.php
@@ -2,6 +2,10 @@
 
 namespace Friendica\Test\src\Module\Api\Twitter;
 
+use Friendica\App\Router;
+use Friendica\Capabilities\ICanCreateResponses;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Favorites;
 use Friendica\Test\src\Module\Api\ApiTest;
 
 class FavoritesTest extends ApiTest
@@ -13,14 +17,17 @@ class FavoritesTest extends ApiTest
 	 */
 	public function testApiFavorites()
 	{
-		/*
-		$_REQUEST['page']   = -1;
-		$_REQUEST['max_id'] = 10;
-		$result             = api_favorites('json');
-		foreach ($result['status'] as $status) {
-			self::assertStatus($status);
+		$favorites = new Favorites(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET]);
+		$response = $favorites->run([
+			'page' => -1,
+			'max_id' => 10,
+		]);
+
+		$json = $this->toJson($response);
+
+		foreach ($json as $status) {
+			$this->assertStatus($status);
 		}
-		*/
 	}
 
 	/**
@@ -30,8 +37,12 @@ class FavoritesTest extends ApiTest
 	 */
 	public function testApiFavoritesWithRss()
 	{
-		// $result = api_favorites('rss');
-		// self::assertXml($result, 'statuses');
+		$favorites = new Favorites(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::GET], ['extension' => ICanCreateResponses::TYPE_RSS]);
+		$response = $favorites->run();
+
+		self::assertEquals(ICanCreateResponses::TYPE_RSS, $response->getHeaderLine(ICanCreateResponses::X_HEADER));
+
+		self::assertXml((string)$response->getBody(), 'statuses');
 	}
 
 	/**
@@ -41,6 +52,8 @@ class FavoritesTest extends ApiTest
 	 */
 	public function testApiFavoritesWithUnallowedUser()
 	{
+		self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first');
+
 		// $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
 		// BasicAuth::setCurrentUserID();
 		// api_favorites('json');

From 204b8b6e498f856091ef1dae107c91be84f309af Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 22:08:31 +0100
Subject: [PATCH 12/17] Reenable Twitter/Media Post tests

---
 src/Module/Api/Twitter/Statuses/Update.php    |  14 +--
 tests/legacy/ApiTest.php                      |  91 ---------------
 tests/src/Module/Api/ApiTest.php              |  19 +++
 .../Module/Api/Twitter/Media/UploadTest.php   |  19 ---
 .../Api/Twitter/Statuses/UpdateTest.php       | 109 ++++++++++++++++++
 5 files changed, 135 insertions(+), 117 deletions(-)
 create mode 100644 tests/src/Module/Api/Twitter/Statuses/UpdateTest.php

diff --git a/src/Module/Api/Twitter/Statuses/Update.php b/src/Module/Api/Twitter/Statuses/Update.php
index 18cb932f80..381af155f0 100644
--- a/src/Module/Api/Twitter/Statuses/Update.php
+++ b/src/Module/Api/Twitter/Statuses/Update.php
@@ -44,7 +44,7 @@ use HTMLPurifier_Config;
  */
 class Update extends BaseApi
 {
-	public function post(array $request = [], array $post = [])
+	public function post(array $request = [])
 	{
 		self::checkAllowedScope(self::SCOPE_WRITE);
 		$uid = self::getCurrentUserID();
@@ -101,10 +101,10 @@ class Update extends BaseApi
 			$item['coord'] = sprintf("%s %s", $request['lat'], $request['long']);
 		}
 
-		$item['allow_cid'] = $owner['allow_cid'];
-		$item['allow_gid'] = $owner['allow_gid'];
-		$item['deny_cid']  = $owner['deny_cid'];
-		$item['deny_gid']  = $owner['deny_gid'];
+		$item['allow_cid'] = $owner['allow_cid'] ?? '';
+		$item['allow_gid'] = $owner['allow_gid'] ?? '';
+		$item['deny_cid']  = $owner['deny_cid'] ?? '';
+		$item['deny_gid']  = $owner['deny_gid'] ?? '';
 
 		if (!empty($item['allow_cid'] . $item['allow_gid'] . $item['deny_cid'] . $item['deny_gid'])) {
 			$item['private'] = Item::PRIVATE;
@@ -127,8 +127,8 @@ class Update extends BaseApi
 			$item['object-type'] = Activity\ObjectType::NOTE;
 		}
 
-		if (!empty($_REQUEST['media_ids'])) {
-			$ids = explode(',', $_REQUEST['media_ids']);
+		if (!empty($request['media_ids'])) {
+			$ids = explode(',', $request['media_ids']);
 		} elseif (!empty($_FILES['media'])) {
 			// upload the image if we have one
 			$picture = Photo::upload($uid, $_FILES['media']);
diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php
index fea2bd5f1b..c7b2337dd9 100644
--- a/tests/legacy/ApiTest.php
+++ b/tests/legacy/ApiTest.php
@@ -835,97 +835,6 @@ class ApiTest extends FixtureTest
 		// api_statuses_mediap('json');
 	}
 
-	/**
-	 * Test the api_statuses_update() function.
-	 *
-	 * @return void
-	 */
-	public function testApiStatusesUpdate()
-	{
-		/*
-		$_REQUEST['status']                = 'Status content #friendica';
-		$_REQUEST['in_reply_to_status_id'] = -1;
-		$_REQUEST['lat']                   = 48;
-		$_REQUEST['long']                  = 7;
-		$_FILES                            = [
-			'media' => [
-				'id'       => 666,
-				'size'     => 666,
-				'width'    => 666,
-				'height'   => 666,
-				'tmp_name' => $this->getTempImage(),
-				'name'     => 'spacer.png',
-				'type'     => 'image/png'
-			]
-		];
-
-		$result = api_statuses_update('json');
-		self::assertStatus($result['status']);
-		*/
-	}
-
-	/**
-	 * Test the api_statuses_update() function with an HTML status.
-	 *
-	 * @return void
-	 */
-	public function testApiStatusesUpdateWithHtml()
-	{
-		/*
-		$_REQUEST['htmlstatus'] = '<b>Status content</b>';
-
-		$result = api_statuses_update('json');
-		self::assertStatus($result['status']);
-		*/
-	}
-
-	/**
-	 * Test the api_statuses_update() function without an authenticated user.
-	 *
-	 * @return void
-	 */
-	public function testApiStatusesUpdateWithoutAuthenticatedUser()
-	{
-		/*
-		$this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
-		BasicAuth::setCurrentUserID();
-		$_SESSION['authenticated'] = false;
-		api_statuses_update('json');
-		*/
-	}
-
-	/**
-	 * Test the api_statuses_update() function with a parent status.
-	 *
-	 * @return void
-	 */
-	public function testApiStatusesUpdateWithParent()
-	{
-		$this->markTestIncomplete('This triggers an exit() somewhere and kills PHPUnit.');
-	}
-
-	/**
-	 * Test the api_statuses_update() function with a media_ids parameter.
-	 *
-	 * @return void
-	 */
-	public function testApiStatusesUpdateWithMediaIds()
-	{
-		$this->markTestIncomplete();
-	}
-
-	/**
-	 * Test the api_statuses_update() function with the throttle limit reached.
-	 *
-	 * @return void
-	 */
-	public function testApiStatusesUpdateWithDayThrottleReached()
-	{
-		$this->markTestIncomplete();
-	}
-
-
-
 	/**
 	 * Test the api_statuses_repeat() function.
 	 *
diff --git a/tests/src/Module/Api/ApiTest.php b/tests/src/Module/Api/ApiTest.php
index 9820061e03..91c7f21a02 100644
--- a/tests/src/Module/Api/ApiTest.php
+++ b/tests/src/Module/Api/ApiTest.php
@@ -126,6 +126,25 @@ abstract class ApiTest extends FixtureTest
 		// We could probably do more checks here.
 	}
 
+	/**
+	 * Get the path to a temporary empty PNG image.
+	 *
+	 * @return string Path
+	 */
+	protected function getTempImage()
+	{
+		$tmpFile = tempnam(sys_get_temp_dir(), 'tmp_file');
+		file_put_contents(
+			$tmpFile,
+			base64_decode(
+			// Empty 1x1 px PNG image
+				'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg=='
+			)
+		);
+
+		return $tmpFile;
+	}
+
 	/**
 	 * Transforms a response into a JSON class
 	 *
diff --git a/tests/src/Module/Api/Twitter/Media/UploadTest.php b/tests/src/Module/Api/Twitter/Media/UploadTest.php
index 5b0ce1186b..4b0ffada12 100644
--- a/tests/src/Module/Api/Twitter/Media/UploadTest.php
+++ b/tests/src/Module/Api/Twitter/Media/UploadTest.php
@@ -80,23 +80,4 @@ class UploadTest extends ApiTest
 		self::assertEquals(1, $media->image->h);
 		self::assertNotEmpty($media->image->friendica_preview_url);
 	}
-
-	/**
-	 * Get the path to a temporary empty PNG image.
-	 *
-	 * @return string Path
-	 */
-	private function getTempImage()
-	{
-		$tmpFile = tempnam(sys_get_temp_dir(), 'tmp_file');
-		file_put_contents(
-			$tmpFile,
-			base64_decode(
-			// Empty 1x1 px PNG image
-				'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg=='
-			)
-		);
-
-		return $tmpFile;
-	}
 }
diff --git a/tests/src/Module/Api/Twitter/Statuses/UpdateTest.php b/tests/src/Module/Api/Twitter/Statuses/UpdateTest.php
new file mode 100644
index 0000000000..efa6f18066
--- /dev/null
+++ b/tests/src/Module/Api/Twitter/Statuses/UpdateTest.php
@@ -0,0 +1,109 @@
+<?php
+
+namespace Friendica\Test\src\Module\Api\Twitter\Statuses;
+
+use Friendica\App\Router;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Statuses\Update;
+use Friendica\Test\src\Module\Api\ApiTest;
+
+class UpdateTest extends ApiTest
+{
+	/**
+	 * Test the api_statuses_update() function.
+	 *
+	 * @return void
+	 */
+	public function testApiStatusesUpdate()
+	{
+		$_FILES = [
+			'media' => [
+				'id'       => 666,
+				'size'     => 666,
+				'width'    => 666,
+				'height'   => 666,
+				'tmp_name' => $this->getTempImage(),
+				'name'     => 'spacer.png',
+				'type'     => 'image/png'
+			]
+		];
+
+		$show     = new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$response = $show->run([
+			'status'                => 'Status content #friendica',
+			'in_reply_to_status_id' => 0,
+			'lat'                   => 48,
+			'long'                  => 7,
+		]);
+
+		$json = $this->toJson($response);
+
+		self::assertStatus($json);
+		self::assertContains('Status content #friendica', $json->text);
+		self::assertContains('Status content #', $json->statusnet_html);
+	}
+
+	/**
+	 * Test the api_statuses_update() function with an HTML status.
+	 *
+	 * @return void
+	 */
+	public function testApiStatusesUpdateWithHtml()
+	{
+		$show     = new Update(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$response = $show->run([
+			'htmlstatus' => '<b>Status content</b>',
+		]);
+
+		$json = $this->toJson($response);
+
+		self::assertStatus($json);
+	}
+
+	/**
+	 * Test the api_statuses_update() function without an authenticated user.
+	 *
+	 * @return void
+	 */
+	public function testApiStatusesUpdateWithoutAuthenticatedUser()
+	{
+		self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first');
+
+		/*
+		$this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
+		BasicAuth::setCurrentUserID();
+		$_SESSION['authenticated'] = false;
+		api_statuses_update('json');
+		*/
+	}
+
+	/**
+	 * Test the api_statuses_update() function with a parent status.
+	 *
+	 * @return void
+	 */
+	public function testApiStatusesUpdateWithParent()
+	{
+		$this->markTestIncomplete('This triggers an exit() somewhere and kills PHPUnit.');
+	}
+
+	/**
+	 * Test the api_statuses_update() function with a media_ids parameter.
+	 *
+	 * @return void
+	 */
+	public function testApiStatusesUpdateWithMediaIds()
+	{
+		$this->markTestIncomplete();
+	}
+
+	/**
+	 * Test the api_statuses_update() function with the throttle limit reached.
+	 *
+	 * @return void
+	 */
+	public function testApiStatusesUpdateWithDayThrottleReached()
+	{
+		$this->markTestIncomplete();
+	}
+}

From d9949610c5523ac4c55ceeb8120a8bbf21ade944 Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 22:30:35 +0100
Subject: [PATCH 13/17] Reenable Twitter/Create&Destory tests

---
 tests/datasets/api.fixture.php                |  7 +-
 tests/legacy/ApiTest.php                      | 94 -------------------
 .../Api/Twitter/Favorites/CreateTest.php      | 74 +++++++++++++++
 .../Api/Twitter/Favorites/DestroyTest.php     | 58 ++++++++++++
 4 files changed, 137 insertions(+), 96 deletions(-)
 create mode 100644 tests/src/Module/Api/Twitter/Favorites/CreateTest.php
 create mode 100644 tests/src/Module/Api/Twitter/Favorites/DestroyTest.php

diff --git a/tests/datasets/api.fixture.php b/tests/datasets/api.fixture.php
index a8705696f2..fa201f7b0e 100644
--- a/tests/datasets/api.fixture.php
+++ b/tests/datasets/api.fixture.php
@@ -69,7 +69,8 @@ return [
 			'username' => 'Test user',
 			'nickname' => 'selfcontact',
 			'verified' => 1,
-			'password' => '$2y$10$DLRNTRmJgKe1cSrFJ5Jb0edCqvXlA9sh/RHdSnfxjbR.04yZRm4Qm',
+			'prvkey'   => "-----BEGIN RSA PRIVATE KEY-----\nMIICXgIBAAKBgQDVqxF9kIgtgRL0+q+jTi578FA1r1+crEmlYc0pdxcbmmrhjuRc\nrK1gX3r0mnP25fkHzG+6CAjgbDBRFM1/RXBCyp/KHVks7eQ4yr4MxTRlsxo5qf2o\nnbyNzM7Q+LZhFhe/yIoGN/fuEjlqBE98IfPOrUjsQPX240vGNXIkfLiAWwIDAQAB\nAoGBAIwuiPIdggqAtWQ+mD8HCx5LQwSFw6/xpPu5F7ZNqL52aAsGCbL3o2QoIG4c\na1qf9Ot16BNgNBqxQF3hzRTkBMrKYlmNTUkwJXun/zjQJq2JvOlcrSuXlIucUjs4\nXekVN25aYPHrX9m2FEIUwZTb4UYXbR80KbIDI53BkQ6EwSbpAkEA7aO49CR2Hf1Y\n1d2GaUI/Z0wvbj//+t0Kg0bPt16ca8KVjEQQA5ylsDaiw510jDz9NBQxSOk6If23\nUeRixc1RDQJBAOYtN4YnPM1Zfp6IxXlqMCc+xUWRTPEPFt+WpG+v79koNamAeA6o\nZzTl92hl58IqSdbgojeE2zXWQRvlimFMLQcCQQCV6jND0byyLqFcSeQBg0l8YROK\n+dUC7W80YfeoNod3c8nkMwvnO2tLPyxvO2XLEq6prBNra7bAus5rWyj0oBIBAkEA\n1EvUMFm0TLpEfLgtWuTD8Q6GKLnxO0ztjd+FXrXpBGN/ywyArxRHzJRmctW6wmz6\nmcOqGobhIHCysKYv0bnOtQJAc2M5RwlASHH4jGJzXgt3nboyiJfufM0RV9iry3ho\nCXQRWAONKoLqnsfC6qNP8OzY8FMJcwmPWj7Q/6z6yLBFTA==\n-----END RSA PRIVATE KEY-----",
+			'pubkey'   => "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVqxF9kIgtgRL0+q+jTi578FA1\nr1+crEmlYc0pdxcbmmrhjuRcrK1gX3r0mnP25fkHzG+6CAjgbDBRFM1/RXBCyp/K\nHVks7eQ4yr4MxTRlsxo5qf2onbyNzM7Q+LZhFhe/yIoGN/fuEjlqBE98IfPOrUjs\nQPX240vGNXIkfLiAWwIDAQAB\n-----END PUBLIC KEY-----",			'password' => '$2y$10$DLRNTRmJgKe1cSrFJ5Jb0edCqvXlA9sh/RHdSnfxjbR.04yZRm4Qm',
 			'theme'    => 'frio',
 		],
 	],
@@ -137,6 +138,8 @@ return [
 			'nurl'     => 'http://localhost/profile/selfcontact',
 			'url'      => 'http://localhost/profile/selfcontact',
 			'about'    => 'User used in tests',
+			'prvkey'   => "-----BEGIN RSA PRIVATE KEY-----\nMIICXgIBAAKBgQDVqxF9kIgtgRL0+q+jTi578FA1r1+crEmlYc0pdxcbmmrhjuRc\nrK1gX3r0mnP25fkHzG+6CAjgbDBRFM1/RXBCyp/KHVks7eQ4yr4MxTRlsxo5qf2o\nnbyNzM7Q+LZhFhe/yIoGN/fuEjlqBE98IfPOrUjsQPX240vGNXIkfLiAWwIDAQAB\nAoGBAIwuiPIdggqAtWQ+mD8HCx5LQwSFw6/xpPu5F7ZNqL52aAsGCbL3o2QoIG4c\na1qf9Ot16BNgNBqxQF3hzRTkBMrKYlmNTUkwJXun/zjQJq2JvOlcrSuXlIucUjs4\nXekVN25aYPHrX9m2FEIUwZTb4UYXbR80KbIDI53BkQ6EwSbpAkEA7aO49CR2Hf1Y\n1d2GaUI/Z0wvbj//+t0Kg0bPt16ca8KVjEQQA5ylsDaiw510jDz9NBQxSOk6If23\nUeRixc1RDQJBAOYtN4YnPM1Zfp6IxXlqMCc+xUWRTPEPFt+WpG+v79koNamAeA6o\nZzTl92hl58IqSdbgojeE2zXWQRvlimFMLQcCQQCV6jND0byyLqFcSeQBg0l8YROK\n+dUC7W80YfeoNod3c8nkMwvnO2tLPyxvO2XLEq6prBNra7bAus5rWyj0oBIBAkEA\n1EvUMFm0TLpEfLgtWuTD8Q6GKLnxO0ztjd+FXrXpBGN/ywyArxRHzJRmctW6wmz6\nmcOqGobhIHCysKYv0bnOtQJAc2M5RwlASHH4jGJzXgt3nboyiJfufM0RV9iry3ho\nCXQRWAONKoLqnsfC6qNP8OzY8FMJcwmPWj7Q/6z6yLBFTA==\n-----END RSA PRIVATE KEY-----",
+			'pubkey'   => "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVqxF9kIgtgRL0+q+jTi578FA1\nr1+crEmlYc0pdxcbmmrhjuRcrK1gX3r0mnP25fkHzG+6CAjgbDBRFM1/RXBCyp/K\nHVks7eQ4yr4MxTRlsxo5qf2onbyNzM7Q+LZhFhe/yIoGN/fuEjlqBE98IfPOrUjs\nQPX240vGNXIkfLiAWwIDAQAB\n-----END PUBLIC KEY-----",
 			'pending'  => 0,
 			'blocked'  => 0,
 			'rel'      => Contact::FOLLOWER,
@@ -259,7 +262,7 @@ return [
 			"header"           => null,
 			"addr"             => "selfcontact@localhost",
 			"alias"            => null,
-			"pubkey"           => "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzLquDFnFxNYZZFQNbA9f\nkgtUJpC+MPrhxhEsjxme1ivvE4itdPnCueBHifknUkwfmqormyeqr4TdoVbNuKRg\nj2QRBdtaGbUJLQVdbiTKFOmJIYMtV05WIIHEhUW84fwIXmF+6u3kbOw+sIjWY3OW\nwC/2+54HiYS2n8cddfwoZBim6Na8yyQI8pQSKqJ+I4gDfkGuoVex0svNPEv9liLE\nykpQ3PuoeLJV2Wex0Cy6FYPgcfH6xvvUVxh6e8w0w22jC3DJInfDrmbw5H7aUbf+\nMMwV3TVI6/CqTO0cLEOZUjsUwdm6lIV0O0fTsrkjU9G0bc0sLJl7n9i9ICDOKOMf\nCLaK2Pj2sVbpkzXJoufLUDf0oSftdVvN9jR9WYxRdnwsyF8N/xVTw8AsyHhkXawR\n3YDgi6i2uZj5kvG7GPBf7EPZ/MpbGhEZB+/GQuZuyhLdgFDSi/uX8STBmn1jI/zY\nTLZ8JCwMzFKAXAtYaBPklZBbcRyz9O1893MsAXO8d6ODTOkD324gAjRUtuOMscYc\nWV98NZIUSbqQrznmMoJn1fiMNVgx+UXOPkiZuDxnrr1T3vynKnl5LXmadx2YeoAf\nxPeCoDb0eJtCDLcsTZ9qlztaEaohPV+H3HBSpdItea7LgAbccILHPssk9tUgmHVl\na5yV8uFenhKKQ9g93Pt63LsCAwEAAQ==\n-----END PUBLIC KEY-----",
+			"pubkey"           => "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVqxF9kIgtgRL0+q+jTi578FA1\nr1+crEmlYc0pdxcbmmrhjuRcrK1gX3r0mnP25fkHzG+6CAjgbDBRFM1/RXBCyp/K\nHVks7eQ4yr4MxTRlsxo5qf2onbyNzM7Q+LZhFhe/yIoGN/fuEjlqBE98IfPOrUjs\nQPX240vGNXIkfLiAWwIDAQAB\n-----END PUBLIC KEY-----",
 			"subscribe"        => "/follow?url={uri}",
 			"baseurl"          => null,
 			"gsid"             => null,
diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php
index c7b2337dd9..2deca42d6c 100644
--- a/tests/legacy/ApiTest.php
+++ b/tests/legacy/ApiTest.php
@@ -876,100 +876,6 @@ class ApiTest extends FixtureTest
 		// self::assertStatus($result['status']);
 	}
 
-	/**
-	 * Test the api_favorites_create_destroy() function.
-	 *
-	 * @return void
-	 */
-	public function testApiFavoritesCreateDestroy()
-	{
-		// $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
-		// DI::args()->setArgv(['api', '1.1', 'favorites', 'create']);
-		// api_favorites_create_destroy('json');
-	}
-
-	/**
-	 * Test the api_favorites_create_destroy() function with an invalid ID.
-	 *
-	 * @return void
-	 */
-	public function testApiFavoritesCreateDestroyWithInvalidId()
-	{
-		// $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
-		// DI::args()->setArgv(['api', '1.1', 'favorites', 'create', '12.json']);
-		// api_favorites_create_destroy('json');
-	}
-
-	/**
-	 * Test the api_favorites_create_destroy() function with an invalid action.
-	 *
-	 * @return void
-	 */
-	public function testApiFavoritesCreateDestroyWithInvalidAction()
-	{
-		// $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class);
-		// DI::args()->setArgv(['api', '1.1', 'favorites', 'change.json']);
-		// $_REQUEST['id'] = 1;
-		// api_favorites_create_destroy('json');
-	}
-
-	/**
-	 * Test the api_favorites_create_destroy() function with the create action.
-	 *
-	 * @return void
-	 */
-	public function testApiFavoritesCreateDestroyWithCreateAction()
-	{
-		// DI::args()->setArgv(['api', '1.1', 'favorites', 'create.json']);
-		// $_REQUEST['id'] = 3;
-		// $result         = api_favorites_create_destroy('json');
-		// self::assertStatus($result['status']);
-	}
-
-	/**
-	 * Test the api_favorites_create_destroy() function with the create action and an RSS result.
-	 *
-	 * @return void
-	 */
-	public function testApiFavoritesCreateDestroyWithCreateActionAndRss()
-	{
-		// DI::args()->setArgv(['api', '1.1', 'favorites', 'create.rss']);
-		// $_REQUEST['id'] = 3;
-		// $result         = api_favorites_create_destroy('rss');
-		// self::assertXml($result, 'status');
-	}
-
-	/**
-	 * Test the api_favorites_create_destroy() function with the destroy action.
-	 *
-	 * @return void
-	 */
-	public function testApiFavoritesCreateDestroyWithDestroyAction()
-	{
-		// DI::args()->setArgv(['api', '1.1', 'favorites', 'destroy.json']);
-		// $_REQUEST['id'] = 3;
-		// $result         = api_favorites_create_destroy('json');
-		// self::assertStatus($result['status']);
-	}
-
-	/**
-	 * Test the api_favorites_create_destroy() function without an authenticated user.
-	 *
-	 * @return void
-	 */
-	public function testApiFavoritesCreateDestroyWithoutAuthenticatedUser()
-	{
-		/*
-		$this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
-		DI::args()->setArgv(['api', '1.1', 'favorites', 'create.json']);
-		BasicAuth::setCurrentUserID();
-		$_SESSION['authenticated'] = false;
-		api_favorites_create_destroy('json');
-		*/
-	}
-
-
-
 	/**
 	 * Test the api_format_messages() function.
 	 *
diff --git a/tests/src/Module/Api/Twitter/Favorites/CreateTest.php b/tests/src/Module/Api/Twitter/Favorites/CreateTest.php
new file mode 100644
index 0000000000..d4d9b4921f
--- /dev/null
+++ b/tests/src/Module/Api/Twitter/Favorites/CreateTest.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Friendica\Test\src\Module\Api\Twitter\Favorites;
+
+use Friendica\App\Router;
+use Friendica\Capabilities\ICanCreateResponses;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Favorites\Create;
+use Friendica\Network\HTTPException\BadRequestException;
+use Friendica\Test\src\Module\Api\ApiTest;
+
+class CreateTest extends ApiTest
+{
+	/**
+	 * Test the api_favorites_create_destroy() function with an invalid ID.
+	 *
+	 * @return void
+	 */
+	public function testApiFavoritesCreateDestroyWithInvalidId()
+	{
+		$this->expectException(BadRequestException::class);
+
+		$create = new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$create->run();
+	}
+
+	/**
+	 * Test the api_favorites_create_destroy() function with the create action.
+	 *
+	 * @return void
+	 */
+	public function testApiFavoritesCreateDestroyWithCreateAction()
+	{
+		$create = new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$response = $create->run(['id' => 3]);
+
+		$json = $this->toJson($response);
+
+		self::assertStatus($json);
+	}
+
+	/**
+	 * Test the api_favorites_create_destroy() function with the create action and an RSS result.
+	 *
+	 * @return void
+	 */
+	public function testApiFavoritesCreateDestroyWithCreateActionAndRss()
+	{
+		$create = new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST], ['extension' => ICanCreateResponses::TYPE_RSS]);
+		$response = $create->run(['id' => 3]);
+
+		self::assertEquals(ICanCreateResponses::TYPE_RSS, $response->getHeaderLine(ICanCreateResponses::X_HEADER));
+
+		self::assertXml((string)$response->getBody(), 'statuses');
+	}
+
+	/**
+	 * Test the api_favorites_create_destroy() function without an authenticated user.
+	 *
+	 * @return void
+	 */
+	public function testApiFavoritesCreateDestroyWithoutAuthenticatedUser()
+	{
+		self::markTestIncomplete('Needs refactoring of Lists - replace filter_input() with $request parameter checks');
+
+		/*
+		$this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
+		DI::args()->setArgv(['api', '1.1', 'favorites', 'create.json']);
+		BasicAuth::setCurrentUserID();
+		$_SESSION['authenticated'] = false;
+		api_favorites_create_destroy('json');
+		*/
+	}
+}
diff --git a/tests/src/Module/Api/Twitter/Favorites/DestroyTest.php b/tests/src/Module/Api/Twitter/Favorites/DestroyTest.php
new file mode 100644
index 0000000000..3d8ce8a212
--- /dev/null
+++ b/tests/src/Module/Api/Twitter/Favorites/DestroyTest.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace Friendica\Test\src\Module\Api\Twitter\Favorites;
+
+use Friendica\App\Router;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Favorites\Destroy;
+use Friendica\Network\HTTPException\BadRequestException;
+use Friendica\Test\src\Module\Api\ApiTest;
+
+class DestroyTest extends ApiTest
+{
+	/**
+	 * Test the api_favorites_create_destroy() function with an invalid ID.
+	 *
+	 * @return void
+	 */
+	public function testApiFavoritesCreateDestroyWithInvalidId()
+	{
+		$this->expectException(BadRequestException::class);
+
+		$destroy = new Destroy(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$destroy->run();
+	}
+
+	/**
+	 * Test the api_favorites_create_destroy() function with the destroy action.
+	 *
+	 * @return void
+	 */
+	public function testApiFavoritesCreateDestroyWithDestroyAction()
+	{
+		$destroy  = new Destroy(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$response = $destroy->run(['id' => 3]);
+
+		$json = $this->toJson($response);
+
+		self::assertStatus($json);
+	}
+
+	/**
+	 * Test the api_favorites_create_destroy() function without an authenticated user.
+	 *
+	 * @return void
+	 */
+	public function testApiFavoritesCreateDestroyWithoutAuthenticatedUser()
+	{
+		self::markTestIncomplete('Needs refactoring of Lists - replace filter_input() with $request parameter checks');
+
+		/*
+		$this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
+		DI::args()->setArgv(['api', '1.1', 'favorites', 'create.json']);
+		BasicAuth::setCurrentUserID();
+		$_SESSION['authenticated'] = false;
+		api_favorites_create_destroy('json');
+		*/
+	}
+}

From 631b9a84fcd2891e0f987dc5e42d613d314aee81 Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 22:41:19 +0100
Subject: [PATCH 14/17] Reenable Twitter/Retweet tests

---
 src/Module/Api/Twitter/Statuses/Retweet.php   |  2 +-
 tests/legacy/ApiTest.php                      | 41 -----------
 .../Api/Twitter/Statuses/RetweetTest.php      | 70 +++++++++++++++++++
 3 files changed, 71 insertions(+), 42 deletions(-)
 create mode 100644 tests/src/Module/Api/Twitter/Statuses/RetweetTest.php

diff --git a/src/Module/Api/Twitter/Statuses/Retweet.php b/src/Module/Api/Twitter/Statuses/Retweet.php
index 15fc26925f..8319b097d2 100644
--- a/src/Module/Api/Twitter/Statuses/Retweet.php
+++ b/src/Module/Api/Twitter/Statuses/Retweet.php
@@ -70,6 +70,6 @@ class Retweet extends BaseApi
 
 		$status_info = DI::twitterStatus()->createFromItemId($item_id, $uid)->toArray();
 
-		DI::apiResponse()->exit('status', ['status' => $status_info], $this->parameters['extension'] ?? null);
+		DI::apiResponse()->exit('statuses', ['status' => $status_info], $this->parameters['extension'] ?? null);
 	}
 }
diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php
index 2deca42d6c..f469217de4 100644
--- a/tests/legacy/ApiTest.php
+++ b/tests/legacy/ApiTest.php
@@ -835,47 +835,6 @@ class ApiTest extends FixtureTest
 		// api_statuses_mediap('json');
 	}
 
-	/**
-	 * Test the api_statuses_repeat() function.
-	 *
-	 * @return void
-	 */
-	public function testApiStatusesRepeat()
-	{
-		// $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class);
-		// api_statuses_repeat('json');
-	}
-
-	/**
-	 * Test the api_statuses_repeat() function without an authenticated user.
-	 *
-	 * @return void
-	 */
-	public function testApiStatusesRepeatWithoutAuthenticatedUser()
-	{
-		// $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
-		// BasicAuth::setCurrentUserID();
-		// $_SESSION['authenticated'] = false;
-		// api_statuses_repeat('json');
-	}
-
-	/**
-	 * Test the api_statuses_repeat() function with an ID.
-	 *
-	 * @return void
-	 */
-	public function testApiStatusesRepeatWithId()
-	{
-		// DI::args()->setArgv(['', '', '', 1]);
-		// $result = api_statuses_repeat('json');
-		// self::assertStatus($result['status']);
-
-		// Also test with a shared status
-		// DI::args()->setArgv(['', '', '', 5]);
-		// $result = api_statuses_repeat('json');
-		// self::assertStatus($result['status']);
-	}
-
 	/**
 	 * Test the api_format_messages() function.
 	 *
diff --git a/tests/src/Module/Api/Twitter/Statuses/RetweetTest.php b/tests/src/Module/Api/Twitter/Statuses/RetweetTest.php
new file mode 100644
index 0000000000..c8ca339597
--- /dev/null
+++ b/tests/src/Module/Api/Twitter/Statuses/RetweetTest.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace Friendica\Test\src\Module\Api\Twitter\Statuses;
+
+use Friendica\App\Router;
+use Friendica\DI;
+use Friendica\Module\Api\Twitter\Statuses\Retweet;
+use Friendica\Network\HTTPException\BadRequestException;
+use Friendica\Test\src\Module\Api\ApiTest;
+
+class RetweetTest extends ApiTest
+{
+	/**
+	 * Test the api_statuses_repeat() function.
+	 *
+	 * @return void
+	 */
+	public function testApiStatusesRepeat()
+	{
+		$this->expectException(BadRequestException::class);
+
+		$retweet = new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$retweet->run();
+	}
+
+	/**
+	 * Test the api_statuses_repeat() function without an authenticated user.
+	 *
+	 * @return void
+	 */
+	public function testApiStatusesRepeatWithoutAuthenticatedUser()
+	{
+		self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first');
+
+		// $this->expectException(\Friendica\Network\HTTPException\UnauthorizedException::class);
+		// BasicAuth::setCurrentUserID();
+		// $_SESSION['authenticated'] = false;
+		// api_statuses_repeat('json');
+	}
+
+	/**
+	 * Test the api_statuses_repeat() function with an ID.
+	 *
+	 * @return void
+	 */
+	public function testApiStatusesRepeatWithId()
+	{
+		$retweet = new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$response = $retweet->run(['id' => 1]);
+
+		$json = $this->toJson($response);
+
+		self::assertStatus($json);
+	}
+
+	/**
+	 * Test the api_statuses_repeat() function with an shared ID.
+	 *
+	 * @return void
+	 */
+	public function testApiStatusesRepeatWithSharedId()
+	{
+		$retweet = new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$response = $retweet->run(['id' => 5]);
+
+		$json = $this->toJson($response);
+
+		self::assertStatus($json);
+	}
+}

From e9d8af89c24694008c8a0c876c4ce3e7f023745c Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Thu, 9 Dec 2021 22:55:15 +0100
Subject: [PATCH 15/17] Make PHP-CS happy ;-)

---
 tests/datasets/api.fixture.php                        | 10 ++++++++++
 tests/src/Module/Api/Twitter/Favorites/CreateTest.php |  4 ++--
 tests/src/Module/Api/Twitter/Statuses/RetweetTest.php |  4 ++--
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/tests/datasets/api.fixture.php b/tests/datasets/api.fixture.php
index fa201f7b0e..5f87159c49 100644
--- a/tests/datasets/api.fixture.php
+++ b/tests/datasets/api.fixture.php
@@ -836,6 +836,16 @@ return [
 			'gid' => 1,
 			'contact-id' => 42,
 		],
+		[
+			'id' => 2,
+			'gid' => 1,
+			'contact-id' => 42,
+		],
+		[
+			'id' => 3,
+			'gid' => 2,
+			'contact-id' => 43,
+		],
 	],
 	'search' => [
 		[
diff --git a/tests/src/Module/Api/Twitter/Favorites/CreateTest.php b/tests/src/Module/Api/Twitter/Favorites/CreateTest.php
index d4d9b4921f..00a99643bf 100644
--- a/tests/src/Module/Api/Twitter/Favorites/CreateTest.php
+++ b/tests/src/Module/Api/Twitter/Favorites/CreateTest.php
@@ -31,7 +31,7 @@ class CreateTest extends ApiTest
 	 */
 	public function testApiFavoritesCreateDestroyWithCreateAction()
 	{
-		$create = new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$create   = new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
 		$response = $create->run(['id' => 3]);
 
 		$json = $this->toJson($response);
@@ -46,7 +46,7 @@ class CreateTest extends ApiTest
 	 */
 	public function testApiFavoritesCreateDestroyWithCreateActionAndRss()
 	{
-		$create = new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST], ['extension' => ICanCreateResponses::TYPE_RSS]);
+		$create   = new Create(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST], ['extension' => ICanCreateResponses::TYPE_RSS]);
 		$response = $create->run(['id' => 3]);
 
 		self::assertEquals(ICanCreateResponses::TYPE_RSS, $response->getHeaderLine(ICanCreateResponses::X_HEADER));
diff --git a/tests/src/Module/Api/Twitter/Statuses/RetweetTest.php b/tests/src/Module/Api/Twitter/Statuses/RetweetTest.php
index c8ca339597..1b527ccc9f 100644
--- a/tests/src/Module/Api/Twitter/Statuses/RetweetTest.php
+++ b/tests/src/Module/Api/Twitter/Statuses/RetweetTest.php
@@ -45,7 +45,7 @@ class RetweetTest extends ApiTest
 	 */
 	public function testApiStatusesRepeatWithId()
 	{
-		$retweet = new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$retweet  = new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
 		$response = $retweet->run(['id' => 1]);
 
 		$json = $this->toJson($response);
@@ -60,7 +60,7 @@ class RetweetTest extends ApiTest
 	 */
 	public function testApiStatusesRepeatWithSharedId()
 	{
-		$retweet = new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
+		$retweet  = new Retweet(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), ['REQUEST_METHOD' => Router::POST]);
 		$response = $retweet->run(['id' => 5]);
 
 		$json = $this->toJson($response);

From 245d194f87fc13291800c56c557f09c18c52508d Mon Sep 17 00:00:00 2001
From: Philipp <admin+Github@philipp.info>
Date: Fri, 10 Dec 2021 10:14:30 +0100
Subject: [PATCH 16/17] Update src/Module/Api/Twitter/Statuses/Destroy.php

Co-authored-by: Hypolite Petovan <hypolite@mrpetovan.com>
---
 src/Module/Api/Twitter/Statuses/Destroy.php | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/Module/Api/Twitter/Statuses/Destroy.php b/src/Module/Api/Twitter/Statuses/Destroy.php
index 8c2a8bf3eb..4fd95eaaef 100644
--- a/src/Module/Api/Twitter/Statuses/Destroy.php
+++ b/src/Module/Api/Twitter/Statuses/Destroy.php
@@ -40,10 +40,10 @@ class Destroy extends BaseApi
 		BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
 		$uid = BaseApi::getCurrentUserID();
 
-		if (empty($this->parameters['id']) && !empty($request['id'])) {
-			$id = intval($request['id']);
-		} elseif (!empty($this->parameters['id'])) {
+		if (!empty($this->parameters['id'])) {
 			$id = (int)$this->parameters['id'];
+		} elseif (!empty($request['id'])) {
+			$id = (int)$request['id'];
 		} else {
 			throw new BadRequestException('An id is missing.');
 		}

From f6e09204e9a2d0d9f5c8ef7a1e5b5c725a8ad1a4 Mon Sep 17 00:00:00 2001
From: Philipp <admin@philipp.info>
Date: Fri, 10 Dec 2021 17:32:41 +0100
Subject: [PATCH 17/17] Add assertions for NotificationTest

---
 tests/src/Module/Api/Friendica/NotificationTest.php | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/tests/src/Module/Api/Friendica/NotificationTest.php b/tests/src/Module/Api/Friendica/NotificationTest.php
index c9ab001418..f05387bd88 100644
--- a/tests/src/Module/Api/Friendica/NotificationTest.php
+++ b/tests/src/Module/Api/Friendica/NotificationTest.php
@@ -78,7 +78,15 @@ XML;
 		$notification = new Notification(DI::app(), DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], ['extension' => 'json']);
 		$response = $notification->run();
 
-		$this->toJson($response);
+		$json = $this->toJson($response);
+
+		self::assertIsArray($json);
+
+		foreach ($json as $note) {
+			self::assertIsInt($note->id);
+			self::assertIsInt($note->uid);
+			self::assertIsString($note->msg);
+		}
 
 		self::assertEquals(['Content-type' => ['application/json'], ICanCreateResponses::X_HEADER => ['json']], $response->getHeaders());
 	}