Browse Source
Merge pull request #6730 from nextcloud/feature/1920/api-reactions-to-message
Merge pull request #6730 from nextcloud/feature/1920/api-reactions-to-message
Api reactions to messagepull/6912/head
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 933 additions and 16 deletions
-
130.drone.yml
-
1appinfo/routes.php
-
41appinfo/routes/routesReactionController.php
-
1docs/capabilities.md
-
2docs/chat.md
-
1docs/index.md
-
66docs/reaction.md
-
9lib/Capabilities.php
-
44lib/Chat/Notifier.php
-
12lib/Chat/Parser/Listener.php
-
52lib/Chat/Parser/ReactionParser.php
-
153lib/Chat/ReactionManager.php
-
130lib/Controller/ReactionController.php
-
29lib/Exceptions/ReactionAlreadyExistsException.php
-
29lib/Exceptions/ReactionNotSupportedException.php
-
29lib/Exceptions/ReactionOutOfContextException.php
-
2lib/Manager.php
-
2lib/Model/Message.php
-
23lib/Notification/Notifier.php
-
1mkdocs.yml
-
63tests/integration/features/bootstrap/FeatureContext.php
-
68tests/integration/features/reaction/react.feature
-
11tests/php/CapabilitiesTest.php
-
50tests/php/Chat/NotifierTest.php
@ -0,0 +1,41 @@ |
|||
<?php |
|||
|
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2021 Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @author Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
return [ |
|||
'ocs' => [ |
|||
['name' => 'Reaction#react', 'url' => '/api/{apiVersion}/reaction/{token}/{messageId}', 'verb' => 'POST', 'requirements' => [ |
|||
'apiVersion' => 'v1', |
|||
'token' => '^[a-z0-9]{4,30}$', |
|||
]], |
|||
['name' => 'Reaction#delete', 'url' => '/api/{apiVersion}/reaction/{token}/{messageId}', 'verb' => 'DELETE', 'requirements' => [ |
|||
'apiVersion' => 'v1', |
|||
'token' => '^[a-z0-9]{4,30}$', |
|||
]], |
|||
['name' => 'Reaction#getReactions', 'url' => '/api/{apiVersion}/reaction/{token}/{messageId}', 'verb' => 'GET', 'requirements' => [ |
|||
'apiVersion' => 'v1', |
|||
'token' => '^[a-z0-9]{4,30}$', |
|||
]], |
|||
], |
|||
]; |
|||
@ -0,0 +1,66 @@ |
|||
# Reaction API |
|||
|
|||
Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1` |
|||
|
|||
## React to a message |
|||
|
|||
* Required capability: `reactions` |
|||
* Method: `POST` |
|||
* Endpoint: `/reaction/{token}/{messageId}` |
|||
* Data: |
|||
|
|||
field | type | Description |
|||
---|---|--- |
|||
`reaction` | string | the reaction emoji |
|||
|
|||
* Response: |
|||
- Status code: |
|||
+ `200 OK` Reaction already exists |
|||
+ `201 Created` |
|||
+ `400 Bad Request` In case of no reaction support, message out of reactions context or any other error |
|||
+ `404 Not Found` When the conversation or message to react could not be found for the participant |
|||
+ `409 Conflict` User already did this reaction to this message |
|||
|
|||
## Delete a reaction |
|||
|
|||
* Required capability: `reactions` |
|||
* Method: `DELETE` |
|||
* Endpoint: `/reaction/{token}/{messageId}` |
|||
* Data: |
|||
|
|||
field | type | Description |
|||
---|---|--- |
|||
`reaction` | string | the reaction emoji |
|||
|
|||
* Response: |
|||
- Status code: |
|||
+ `201 Created` |
|||
+ `400 Bad Request` In case of no reaction support, message out of reactions context or any other error |
|||
+ `404 Not Found` When the conversation or message to react or reaction could not be found for the participant |
|||
|
|||
## Retrieve reactions of a message by type |
|||
|
|||
* Required capability: `reactions` |
|||
* Method: `GET` |
|||
* Endpoint: `/reaction/{token}/{messageId}` |
|||
* Data: |
|||
|
|||
field | type | Description |
|||
---|---|--- |
|||
`reaction` | string | **Optional:** the reaction emoji |
|||
|
|||
* Response: |
|||
- Status code: |
|||
+ `200 OK` |
|||
+ `400 Bad Request` In case of no reaction support, message out of reactions context or any other error |
|||
+ `404 Not Found` When the conversation or message to react could not be found for the participant |
|||
|
|||
- Data: |
|||
Array with data of reactions: |
|||
|
|||
field | type | Description |
|||
---|---|--- |
|||
`actorType` | string | `guests` or `users` |
|||
`actorId` | string | Actor id of the reacting participant |
|||
`actorDisplayName` | string | Display name of the reaction author |
|||
`timestamp` | int | Timestamp in seconds and UTC time zone |
|||
@ -0,0 +1,52 @@ |
|||
<?php |
|||
|
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2021 Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @author Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Talk\Chat\Parser; |
|||
|
|||
use OCA\Talk\Model\Message; |
|||
use OCP\IL10N; |
|||
|
|||
class ReactionParser { |
|||
/** @var IL10N|null */ |
|||
private $l; |
|||
/** |
|||
* @param Message $message |
|||
* @throws \OutOfBoundsException |
|||
*/ |
|||
public function parseMessage(Message $message): void { |
|||
$comment = $message->getComment(); |
|||
if (!in_array($comment->getVerb(), ['reaction', 'reaction_deleted'])) { |
|||
throw new \OutOfBoundsException('Not a reaction'); |
|||
} |
|||
$this->l = $message->getL10n(); |
|||
$message->setMessageType('system'); |
|||
if ($comment->getVerb() === 'reaction_deleted') { |
|||
// This message is necessary to make compatible with old clients
|
|||
$message->setMessage($this->l->t('Message deleted by author'), [], $comment->getVerb()); |
|||
} else { |
|||
$message->setMessage($message->getMessage(), [], $comment->getVerb()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,153 @@ |
|||
<?php |
|||
|
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2021 Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @author Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Talk\Chat; |
|||
|
|||
use OCA\Talk\Exceptions\ReactionAlreadyExistsException; |
|||
use OCA\Talk\Exceptions\ReactionNotSupportedException; |
|||
use OCA\Talk\Exceptions\ReactionOutOfContextException; |
|||
use OCA\Talk\Participant; |
|||
use OCA\Talk\Room; |
|||
use OCP\AppFramework\Utility\ITimeFactory; |
|||
use OCP\Comments\IComment; |
|||
use OCP\Comments\ICommentsManager; |
|||
use OCP\Comments\NotFoundException; |
|||
use OCP\IL10N; |
|||
|
|||
class ReactionManager { |
|||
/** @var ICommentsManager|CommentsManager */ |
|||
private $commentsManager; |
|||
/** @var IL10N */ |
|||
private $l; |
|||
/** @var MessageParser */ |
|||
private $messageParser; |
|||
/** @var Notifier */ |
|||
private $notifier; |
|||
/** @var ITimeFactory */ |
|||
protected $timeFactory; |
|||
|
|||
public function __construct(CommentsManager $commentsManager, |
|||
IL10N $l, |
|||
MessageParser $messageParser, |
|||
Notifier $notifier, |
|||
ITimeFactory $timeFactory) { |
|||
$this->commentsManager = $commentsManager; |
|||
$this->l = $l; |
|||
$this->messageParser = $messageParser; |
|||
$this->notifier = $notifier; |
|||
$this->timeFactory = $timeFactory; |
|||
} |
|||
|
|||
public function addReactionMessage(Room $chat, Participant $participant, IComment $parentMessage, string $reaction): IComment { |
|||
try { |
|||
// Check if the user already reacted with the same reaction
|
|||
$comment = $this->commentsManager->getReactionComment( |
|||
(int) $parentMessage->getId(), |
|||
$participant->getAttendee()->getActorType(), |
|||
$participant->getAttendee()->getActorId(), |
|||
$reaction |
|||
); |
|||
throw new ReactionAlreadyExistsException(); |
|||
} catch (NotFoundException $e) { |
|||
} |
|||
|
|||
$comment = $this->commentsManager->create( |
|||
$participant->getAttendee()->getActorType(), |
|||
$participant->getAttendee()->getActorId(), |
|||
'chat', |
|||
(string) $chat->getId() |
|||
); |
|||
$comment->setParentId((string) $parentMessage->getId()); |
|||
$comment->setMessage($reaction); |
|||
$comment->setVerb('reaction'); |
|||
$this->commentsManager->save($comment); |
|||
|
|||
$this->notifier->notifyReacted($chat, $parentMessage, $comment); |
|||
return $comment; |
|||
} |
|||
|
|||
public function deleteReactionMessage(Participant $participant, int $messageId, string $reaction): IComment { |
|||
$comment = $this->commentsManager->getReactionComment( |
|||
$messageId, |
|||
$participant->getAttendee()->getActorType(), |
|||
$participant->getAttendee()->getActorId(), |
|||
$reaction |
|||
); |
|||
$comment->setMessage( |
|||
json_encode([ |
|||
'deleted_by_type' => $participant->getAttendee()->getActorType(), |
|||
'deleted_by_id' => $participant->getAttendee()->getActorId(), |
|||
'deleted_on' => $this->timeFactory->getDateTime()->getTimestamp(), |
|||
]) |
|||
); |
|||
$comment->setVerb('reaction_deleted'); |
|||
$this->commentsManager->save($comment); |
|||
return $comment; |
|||
} |
|||
|
|||
public function retrieveReactionMessages(Room $chat, Participant $participant, int $messageId, ?string $reaction): array { |
|||
if ($reaction) { |
|||
$comments = $this->commentsManager->retrieveAllReactionsWithSpecificReaction($messageId, $reaction); |
|||
} else { |
|||
$comments = $this->commentsManager->retrieveAllReactions($messageId); |
|||
} |
|||
|
|||
foreach ($comments as $comment) { |
|||
$message = $this->messageParser->createMessage($chat, $participant, $comment, $this->l); |
|||
$this->messageParser->parseMessage($message); |
|||
|
|||
$reactions[$comment->getMessage()][] = [ |
|||
'actorType' => $comment->getActorType(), |
|||
'actorId' => $comment->getActorId(), |
|||
'actorDisplayName' => $message->getActorDisplayName(), |
|||
'timestamp' => $comment->getCreationDateTime()->getTimestamp(), |
|||
]; |
|||
} |
|||
return $reactions; |
|||
} |
|||
|
|||
/** |
|||
* @param Room $chat |
|||
* @param string $messageId |
|||
* @return IComment |
|||
* @throws NotFoundException |
|||
* @throws ReactionNotSupportedException |
|||
* @throws ReactionOutOfContextException |
|||
*/ |
|||
public function getCommentToReact(Room $chat, string $messageId): IComment { |
|||
if (!$this->commentsManager->supportReactions()) { |
|||
throw new ReactionNotSupportedException(); |
|||
} |
|||
$comment = $this->commentsManager->get($messageId); |
|||
|
|||
if ($comment->getObjectType() !== 'chat' |
|||
|| $comment->getObjectId() !== (string) $chat->getId() |
|||
|| $comment->getVerb() !== 'comment') { |
|||
throw new ReactionOutOfContextException(); |
|||
} |
|||
|
|||
return $comment; |
|||
} |
|||
} |
|||
@ -0,0 +1,130 @@ |
|||
<?php |
|||
|
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2021 Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @author Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Talk\Controller; |
|||
|
|||
use OCA\Talk\Chat\ReactionManager; |
|||
use OCA\Talk\Exceptions\ReactionAlreadyExistsException; |
|||
use OCA\Talk\Exceptions\ReactionNotSupportedException; |
|||
use OCA\Talk\Exceptions\ReactionOutOfContextException; |
|||
use OCP\AppFramework\Http; |
|||
use OCP\AppFramework\Http\DataResponse; |
|||
use OCP\Comments\NotFoundException; |
|||
use OCP\IRequest; |
|||
|
|||
class ReactionController extends AEnvironmentAwareController { |
|||
/** @var ReactionManager */ |
|||
private $reactionManager; |
|||
|
|||
public function __construct(string $appName, |
|||
IRequest $request, |
|||
ReactionManager $reactionManager) { |
|||
parent::__construct($appName, $request); |
|||
$this->reactionManager = $reactionManager; |
|||
} |
|||
|
|||
/** |
|||
* @NoAdminRequired |
|||
* @RequireParticipant |
|||
* @RequireReadWriteConversation |
|||
* @RequireModeratorOrNoLobby |
|||
* |
|||
* @param int $messageId for reaction |
|||
* @param string $reaction the reaction emoji |
|||
* @return DataResponse |
|||
*/ |
|||
public function react(int $messageId, string $reaction): DataResponse { |
|||
try { |
|||
$chat = $this->getRoom(); |
|||
$participant = $this->getParticipant(); |
|||
$parentMessage = $this->reactionManager->getCommentToReact($chat, (string) $messageId); |
|||
$this->reactionManager->addReactionMessage($chat, $participant, $parentMessage, $reaction); |
|||
} catch (NotFoundException $e) { |
|||
return new DataResponse([], Http::STATUS_NOT_FOUND); |
|||
} catch (ReactionAlreadyExistsException $e) { |
|||
return new DataResponse([], Http::STATUS_OK); |
|||
} catch (ReactionNotSupportedException | ReactionOutOfContextException | \Exception $e) { |
|||
return new DataResponse([], Http::STATUS_BAD_REQUEST); |
|||
} |
|||
return new DataResponse([], Http::STATUS_CREATED); |
|||
} |
|||
|
|||
/** |
|||
* @NoAdminRequired |
|||
* @RequireParticipant |
|||
* @RequireReadWriteConversation |
|||
* @RequireModeratorOrNoLobby |
|||
* |
|||
* @param int $messageId for reaction |
|||
* @param string $reaction the reaction emoji |
|||
* @return DataResponse |
|||
*/ |
|||
public function delete(int $messageId, string $reaction): DataResponse { |
|||
$participant = $this->getParticipant(); |
|||
try { |
|||
// Verify that messageId is part of the room
|
|||
$this->reactionManager->getCommentToReact($this->getRoom(), (string) $messageId); |
|||
} catch (ReactionNotSupportedException | ReactionOutOfContextException | NotFoundException $e) { |
|||
return new DataResponse([], Http::STATUS_NOT_FOUND); |
|||
} |
|||
|
|||
try { |
|||
$this->reactionManager->deleteReactionMessage( |
|||
$participant, |
|||
$messageId, |
|||
$reaction |
|||
); |
|||
} catch (NotFoundException $e) { |
|||
return new DataResponse([], Http::STATUS_NOT_FOUND); |
|||
} catch (\Exception $e) { |
|||
return new DataResponse([], Http::STATUS_BAD_REQUEST); |
|||
} |
|||
|
|||
return new DataResponse([], Http::STATUS_OK); |
|||
} |
|||
|
|||
/** |
|||
* @NoAdminRequired |
|||
* @RequireParticipant |
|||
* @RequireReadWriteConversation |
|||
* @RequireModeratorOrNoLobby |
|||
* |
|||
* @param int $messageId for reaction |
|||
* @param string|null $reaction the reaction emoji |
|||
* @return DataResponse |
|||
*/ |
|||
public function getReactions(int $messageId, ?string $reaction): DataResponse { |
|||
try { |
|||
// Verify that messageId is part of the room
|
|||
$this->reactionManager->getCommentToReact($this->getRoom(), (string) $messageId); |
|||
} catch (ReactionNotSupportedException | ReactionOutOfContextException | NotFoundException $e) { |
|||
return new DataResponse([], Http::STATUS_NOT_FOUND); |
|||
} |
|||
|
|||
$reactions = $this->reactionManager->retrieveReactionMessages($this->getRoom(), $this->getParticipant(), $messageId, $reaction); |
|||
|
|||
return new DataResponse($reactions, Http::STATUS_OK); |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
<?php |
|||
|
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2021 Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @author Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Talk\Exceptions; |
|||
|
|||
class ReactionAlreadyExistsException extends \OutOfBoundsException { |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
<?php |
|||
|
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2022, Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @author Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Talk\Exceptions; |
|||
|
|||
class ReactionNotSupportedException extends \Exception { |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
<?php |
|||
|
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2022, Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @author Vitor Mattos <vitor@php.rio> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Talk\Exceptions; |
|||
|
|||
class ReactionOutOfContextException extends \Exception { |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
Feature: reaction/react |
|||
Background: |
|||
Given user "participant1" exists |
|||
Given user "participant2" exists |
|||
|
|||
Scenario: React to message with success |
|||
Given user "participant1" creates room "room" (v4) |
|||
| roomType | 3 | |
|||
| roomName | room | |
|||
And user "participant1" adds user "participant2" to room "room" with 200 (v4) |
|||
And user "participant1" sends message "Message 1" to room "room" with 201 |
|||
And user "participant2" react with "👍" on message "Message 1" to room "room" with 201 |
|||
Then user "participant1" sees the following messages in room "room" with 200 |
|||
| room | actorType | actorId | actorDisplayName | message | messageParameters | reactions | |
|||
| room | users | participant1 | participant1-displayname | Message 1 | [] | {"👍":1} | |
|||
And user "participant1" react with "👍" on message "Message 1" to room "room" with 201 |
|||
Then user "participant1" sees the following messages in room "room" with 200 |
|||
| room | actorType | actorId | actorDisplayName | message | messageParameters | reactions | |
|||
| room | users | participant1 | participant1-displayname | Message 1 | [] | {"👍":2} | |
|||
|
|||
Scenario: React two times to same message with the same reaction |
|||
Given user "participant1" creates room "room" (v4) |
|||
| roomType | 3 | |
|||
| roomName | room | |
|||
And user "participant1" adds user "participant2" to room "room" with 200 (v4) |
|||
And user "participant1" sends message "Message 1" to room "room" with 201 |
|||
And user "participant2" react with "👍" on message "Message 1" to room "room" with 201 |
|||
And user "participant2" react with "👍" on message "Message 1" to room "room" with 200 |
|||
Then user "participant1" sees the following messages in room "room" with 200 |
|||
| room | actorType | actorId | actorDisplayName | message | messageParameters | reactions | |
|||
| room | users | participant1 | participant1-displayname | Message 1 | [] | {"👍":1} | |
|||
|
|||
Scenario: Delete reaction to message with success |
|||
Given user "participant1" creates room "room" (v4) |
|||
| roomType | 3 | |
|||
| roomName | room | |
|||
And user "participant1" adds user "participant2" to room "room" with 200 (v4) |
|||
And user "participant1" sends message "Message 1" to room "room" with 201 |
|||
And user "participant2" react with "👍" on message "Message 1" to room "room" with 201 |
|||
Then user "participant1" sees the following messages in room "room" with 200 |
|||
| room | actorType | actorId | actorDisplayName | message | messageParameters | reactions | |
|||
| room | users | participant1 | participant1-displayname | Message 1 | [] | {"👍":1} | |
|||
And user "participant2" delete react with "👍" on message "Message 1" to room "room" with 200 |
|||
Then user "participant1" sees the following messages in room "room" with 200 |
|||
| room | actorType | actorId | actorDisplayName | message | messageParameters | reactions | |
|||
| room | users | participant1 | participant1-displayname | Message 1 | [] | [] | |
|||
|
|||
Scenario: Retrieve reactions of a message |
|||
Given user "participant1" creates room "room" (v4) |
|||
| roomType | 3 | |
|||
| roomName | room | |
|||
And user "participant1" adds user "participant2" to room "room" with 200 (v4) |
|||
And user "participant1" sends message "Message 1" to room "room" with 201 |
|||
And user "participant1" react with "👍" on message "Message 1" to room "room" with 201 |
|||
And user "participant2" react with "👍" on message "Message 1" to room "room" with 201 |
|||
Then user "participant1" retrieve reactions "👍" of message "Message 1" in room "room" with 200 |
|||
| actorType | actorId | actorDisplayName | reaction | |
|||
| users | participant1 | participant1-displayname | 👍 | |
|||
| users | participant2 | participant2-displayname | 👍 | |
|||
And user "participant2" react with "👎" on message "Message 1" to room "room" with 201 |
|||
And user "participant1" retrieve reactions "👎" of message "Message 1" in room "room" with 200 |
|||
| actorType | actorId | actorDisplayName | reaction | |
|||
| users | participant2 | participant2-displayname | 👎 | |
|||
And user "participant1" retrieve reactions "all" of message "Message 1" in room "room" with 200 |
|||
| actorType | actorId | actorDisplayName | reaction | |
|||
| users | participant1 | participant1-displayname | 👍 | |
|||
| users | participant2 | participant2-displayname | 👎 | |
|||
| users | participant2 | participant2-displayname | 👍 | |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue