diff --git a/lib/Controller/ChatController.php b/lib/Controller/ChatController.php index cf931467cd7..3b9c61cec6d 100644 --- a/lib/Controller/ChatController.php +++ b/lib/Controller/ChatController.php @@ -880,7 +880,6 @@ public function getObjectsSharedInRoomOverview(int $limit = 7): DataResponse { Attachment::TYPE_VOICE, ]; - $messages = []; $messageIdsByType = []; // Get all attachments foreach ($objectTypes as $objectType) { diff --git a/lib/Controller/ReactionController.php b/lib/Controller/ReactionController.php index 5d9bbe5317d..466c66b7376 100644 --- a/lib/Controller/ReactionController.php +++ b/lib/Controller/ReactionController.php @@ -74,7 +74,7 @@ public function react(int $messageId, string $reaction): DataResponse { return new DataResponse([], Http::STATUS_BAD_REQUEST); } $reactions = $this->reactionManager->retrieveReactionMessages($this->getRoom(), $this->getParticipant(), $messageId); - return new DataResponse($reactions, $status); + return new DataResponse($this->formatReactions($reactions), $status); } #[PublicPage] @@ -98,7 +98,7 @@ public function delete(int $messageId, string $reaction): DataResponse { return new DataResponse([], Http::STATUS_BAD_REQUEST); } - return new DataResponse($reactions, Http::STATUS_OK); + return new DataResponse($this->formatReactions($reactions), Http::STATUS_OK); } #[PublicPage] @@ -114,6 +114,21 @@ public function getReactions(int $messageId, ?string $reaction): DataResponse { $reactions = $this->reactionManager->retrieveReactionMessages($this->getRoom(), $this->getParticipant(), $messageId, $reaction); - return new DataResponse($reactions, Http::STATUS_OK); + return new DataResponse($this->formatReactions($reactions), Http::STATUS_OK); + } + + + /** + * @param array $reactions + * @return array|\stdClass + */ + public function formatReactions(array $reactions): array|\stdClass { + if ($this->getResponseFormat() === 'json' && empty($reactions)) { + // Cheating here to make sure the reactions array is always a + // JSON object on the API, even when there is no reaction at all. + return new \stdClass(); + } + + return $reactions; } } diff --git a/tests/integration/features/bootstrap/FeatureContext.php b/tests/integration/features/bootstrap/FeatureContext.php index 751390999b3..4d6e4c938ad 100644 --- a/tests/integration/features/bootstrap/FeatureContext.php +++ b/tests/integration/features/bootstrap/FeatureContext.php @@ -2262,12 +2262,17 @@ public function userSeesTheFollowingSharedOverviewMediaInRoom($user, $identifier $this->sendRequest('GET', '/apps/spreed/api/' . $apiVersion . '/chat/' . self::$identifierToToken[$identifier] . '/share/overview'); $this->assertStatusCode($this->response, $statusCode); - $overview = $this->getDataFromResponse($this->response); - $expected = $formData->getRowsHash(); - $summarized = array_map(function ($type) { - return (string) count($type); - }, $overview); - Assert::assertEquals($expected, $summarized); + $contents = $this->response->getBody()->getContents(); + $this->assertEmptyArrayIsNotAListButADictionary($formData, $contents); + $overview = $this->getDataFromResponseBody($contents); + + if ($formData instanceof TableNode) { + $expected = $formData->getRowsHash(); + $summarized = array_map(function ($type) { + return (string) count($type); + }, $overview); + Assert::assertEquals($expected, $summarized); + } } /** @@ -2856,7 +2861,16 @@ public function userCheckCapability($user, $capability, $value) { * @return array */ protected function getDataFromResponse(ResponseInterface $response) { - $jsonBody = json_decode($response->getBody()->getContents(), true); + return $this->getDataFromResponseBody($response->getBody()->getContents()); + } + + /** + * Parses the JSON answer to get the array of users returned. + * @param string $response + * @return array + */ + protected function getDataFromResponseBody(string $response) { + $jsonBody = json_decode($response, true); return $jsonBody['ocs']['data']; } @@ -3322,7 +3336,9 @@ public function userReactWithOnMessageToRoomWith(string $user, string $action, s 'reaction' => $reaction ]); $this->assertStatusCode($this->response, $statusCode); - $this->assertReactionList($formData); + if ($statusCode === 200 || $statusCode === 201) { + $this->assertReactionList($formData); + } } /** @@ -3340,10 +3356,15 @@ public function userRetrieveReactionsOfMessageInRoomWith(string $user, string $r } private function assertReactionList(?TableNode $formData): void { + $contents = $this->response->getBody()->getContents(); + $this->assertEmptyArrayIsNotAListButADictionary($formData, $contents); + $reactions = $this->getDataFromResponseBody($contents); + $expected = []; if (!$formData instanceof TableNode) { return; } + foreach ($formData->getHash() as $row) { $reaction = $row['reaction']; unset($row['reaction']); @@ -3358,8 +3379,7 @@ private function assertReactionList(?TableNode $formData): void { $expected[$reaction][] = $row; } - $result = $this->getDataFromResponse($this->response); - $result = array_map(static function ($reaction, $list) use ($expected): array { + $actual = array_map(static function ($reaction, $list) use ($expected): array { $list = array_map(function ($reaction) { unset($reaction['timestamp']); $reaction['actorId'] = ($reaction['actorType'] === 'guests') ? self::$sessionIdToUser[$reaction['actorId']] : (string) $reaction['actorId']; @@ -3372,8 +3392,8 @@ private function assertReactionList(?TableNode $formData): void { usort($list, [self::class, 'sortAttendees']); Assert::assertEquals($expected[$reaction], $list, 'Reaction list by type does not match'); return $list; - }, array_keys($result), array_values($result)); - Assert::assertCount(count($expected), $result, 'Reaction count does not match'); + }, array_keys($reactions), array_values($reactions)); + Assert::assertCount(count($expected), $actual, 'Reaction count does not match'); } /** @@ -3791,6 +3811,13 @@ public function setUserStatus(string $user, string $status, int $statusCode, str $this->assertStatusCode($this->response, $statusCode); } + protected function assertEmptyArrayIsNotAListButADictionary(?TableNode $formData, string $content) { + if (!$formData instanceof TableNode || empty($formData->getHash())) { + $data = json_decode($content); + Assert::assertIsNotArray($data->ocs->data, 'Response ocs.data should be an "object" to represent a JSON dictionary, not a list-array'); + } + } + /** * @Then the response error matches with :error */ diff --git a/tests/integration/features/chat-2/rich-object-share.feature b/tests/integration/features/chat-2/rich-object-share.feature index e8dcab5ff1f..7158b019e43 100644 --- a/tests/integration/features/chat-2/rich-object-share.feature +++ b/tests/integration/features/chat-2/rich-object-share.feature @@ -64,6 +64,7 @@ Feature: chat-2/rich-object-share Given user "participant1" creates room "public room" (v4) | roomType | 3 | | roomName | room | + Then user "participant1" sees the following shared summarized overview in room "public room" with 200 When user "participant1" shares rich-object "call" "R4nd0mT0k3n" '{"name":"Another room","call-type":"group"}' to room "public room" with 201 (v1) Then user "participant1" sees the following shared other in room "public room" with 200 | room | actorType | actorId | actorDisplayName | message | messageParameters |