diff --git a/src/CONST.js b/src/CONST.js
index 88282c4b68e4..7ebdd6bad406 100755
--- a/src/CONST.js
+++ b/src/CONST.js
@@ -174,6 +174,7 @@ const CONST = {
},
DATE: {
MOMENT_FORMAT_STRING: 'YYYY-MM-DD',
+ SQL_DATE_TIME: 'YYYY-MM-DD HH:mm:ss',
UNIX_EPOCH: '1970-01-01 00:00:00.000',
MAX_DATE: '9999-12-31',
MIN_DATE: '0001-01-01',
diff --git a/src/components/AttachmentCarousel/index.js b/src/components/AttachmentCarousel/index.js
index 85f3abcc90aa..2c72321f490b 100644
--- a/src/components/AttachmentCarousel/index.js
+++ b/src/components/AttachmentCarousel/index.js
@@ -270,7 +270,11 @@ class AttachmentCarousel extends React.Component {
/**
* Defines how a single attachment should be rendered
- * @param {{ isAuthTokenRequired: Boolean, source: String, file: { name: String } }} item
+ * @param {Object} item
+ * @param {Boolean} item.isAuthTokenRequired
+ * @param {String} item.source
+ * @param {Object} item.file
+ * @param {String} item.file.name
* @returns {JSX.Element}
*/
renderItem({item}) {
diff --git a/src/components/AttachmentPicker/index.native.js b/src/components/AttachmentPicker/index.native.js
index b0b1222316f0..b4b7d0b04c4e 100644
--- a/src/components/AttachmentPicker/index.native.js
+++ b/src/components/AttachmentPicker/index.native.js
@@ -315,7 +315,8 @@ class AttachmentPicker extends Component {
/**
* Setup native attachment selection to start after this popover closes
*
- * @param {{pickAttachment: function}} item - an item from this.menuItemData
+ * @param {Object} item - an item from this.menuItemData
+ * @param {Function} item.pickAttachment
*/
selectItem(item) {
/* setTimeout delays execution to the frame after the modal closes
diff --git a/src/components/Reactions/EmojiReactionsPropTypes.js b/src/components/Reactions/EmojiReactionsPropTypes.js
new file mode 100644
index 000000000000..ace88abefcd9
--- /dev/null
+++ b/src/components/Reactions/EmojiReactionsPropTypes.js
@@ -0,0 +1,31 @@
+import PropTypes from 'prop-types';
+
+/** All the emoji reactions for the report action. An object that looks like this:
+ "emojiReactions": {
+ "+1": { // The emoji added to the action
+ "createdAt": "2021-01-01 00:00:00",
+ "users": {
+ 2352342: { // The accountID of the user who added this emoji
+ "skinTones": {
+ "1": "2021-01-01 00:00:00",
+ "2": "2021-01-01 00:00:00",
+ },
+ },
+ },
+ },
+ },
+*/
+export default PropTypes.objectOf(
+ PropTypes.shape({
+ /** The time the emoji was added */
+ createdAt: PropTypes.string,
+
+ /** All the users who have added this emoji */
+ users: PropTypes.objectOf(
+ PropTypes.shape({
+ /** The skin tone which was used and also the timestamp of when it was added */
+ skinTones: PropTypes.objectOf(PropTypes.string),
+ }),
+ ),
+ }),
+);
diff --git a/src/components/Reactions/MiniQuickEmojiReactions.js b/src/components/Reactions/MiniQuickEmojiReactions.js
index 9973c5fae083..4d918f5e7f58 100644
--- a/src/components/Reactions/MiniQuickEmojiReactions.js
+++ b/src/components/Reactions/MiniQuickEmojiReactions.js
@@ -12,7 +12,7 @@ import Icon from '../Icon';
import * as Expensicons from '../Icon/Expensicons';
import getButtonState from '../../libs/getButtonState';
import * as EmojiPickerAction from '../../libs/actions/EmojiPickerAction';
-import {baseQuickEmojiReactionsPropTypes} from './QuickEmojiReactions/BaseQuickEmojiReactions';
+import {baseQuickEmojiReactionsPropTypes, baseQuickEmojiReactionsDefaultProps} from './QuickEmojiReactions/BaseQuickEmojiReactions';
import withLocalize, {withLocalizePropTypes} from '../withLocalize';
import compose from '../../libs/compose';
import ONYXKEYS from '../../ONYXKEYS';
@@ -40,6 +40,7 @@ const propTypes = {
};
const defaultProps = {
+ ...baseQuickEmojiReactionsDefaultProps,
onEmojiPickerClosed: () => {},
preferredSkinTone: CONST.EMOJI_DEFAULT_SKIN_TONE,
reportAction: {},
@@ -61,7 +62,7 @@ function MiniQuickEmojiReactions(props) {
EmojiPickerAction.showEmojiPicker(
props.onEmojiPickerClosed,
(emojiCode, emojiObject) => {
- props.onEmojiSelected(emojiObject);
+ props.onEmojiSelected(emojiObject, props.emojiReactions);
},
ref.current,
undefined,
@@ -77,7 +78,7 @@ function MiniQuickEmojiReactions(props) {
key={emoji.name}
isDelayButtonStateComplete={false}
tooltipText={`:${EmojiUtils.getLocalizedEmojiName(emoji.name, props.preferredLocale)}:`}
- onPress={Session.checkIfActionIsAllowed(() => props.onEmojiSelected(emoji))}
+ onPress={Session.checkIfActionIsAllowed(() => props.onEmojiSelected(emoji, props.emojiReactions))}
>
{EmojiUtils.getPreferredEmojiCode(emoji, props.preferredSkinTone)}
@@ -105,9 +106,15 @@ MiniQuickEmojiReactions.propTypes = propTypes;
MiniQuickEmojiReactions.defaultProps = defaultProps;
export default compose(
withLocalize,
+ // ESLint throws an error because it can't see that emojiReactions is defined in props. It is defined in props, but
+ // because of a couple spread operators, I think that's why ESLint struggles to see it
+ // eslint-disable-next-line rulesdir/onyx-props-must-have-default
withOnyx({
preferredSkinTone: {
key: ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE,
},
+ emojiReactions: {
+ key: ({reportActionID}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`,
+ },
}),
)(MiniQuickEmojiReactions);
diff --git a/src/components/Reactions/QuickEmojiReactions/BaseQuickEmojiReactions.js b/src/components/Reactions/QuickEmojiReactions/BaseQuickEmojiReactions.js
index 7040f579863e..69ff37338c2d 100644
--- a/src/components/Reactions/QuickEmojiReactions/BaseQuickEmojiReactions.js
+++ b/src/components/Reactions/QuickEmojiReactions/BaseQuickEmojiReactions.js
@@ -10,9 +10,12 @@ import styles from '../../../styles/styles';
import ONYXKEYS from '../../../ONYXKEYS';
import Tooltip from '../../Tooltip';
import * as EmojiUtils from '../../../libs/EmojiUtils';
+import EmojiReactionsPropTypes from '../EmojiReactionsPropTypes';
import * as Session from '../../../libs/actions/Session';
const baseQuickEmojiReactionsPropTypes = {
+ emojiReactions: EmojiReactionsPropTypes,
+
/**
* Callback to fire when an emoji is selected.
*/
@@ -39,6 +42,7 @@ const baseQuickEmojiReactionsPropTypes = {
};
const baseQuickEmojiReactionsDefaultProps = {
+ emojiReactions: {},
onWillShowPicker: () => {},
onPressOpenPicker: () => {},
reportAction: {},
@@ -67,7 +71,7 @@ function BaseQuickEmojiReactions(props) {
props.onEmojiSelected(emoji))}
+ onPress={Session.checkIfActionIsAllowed(() => props.onEmojiSelected(emoji, props.emojiReactions))}
/>
@@ -90,9 +94,12 @@ export default withOnyx({
preferredSkinTone: {
key: ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE,
},
+ emojiReactions: {
+ key: ({reportActionID}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`,
+ },
preferredLocale: {
key: ONYXKEYS.NVP_PREFERRED_LOCALE,
},
})(BaseQuickEmojiReactions);
-export {baseQuickEmojiReactionsPropTypes};
+export {baseQuickEmojiReactionsPropTypes, baseQuickEmojiReactionsDefaultProps};
diff --git a/src/components/Reactions/ReportActionItemReactions.js b/src/components/Reactions/ReportActionItemEmojiReactions.js
similarity index 52%
rename from src/components/Reactions/ReportActionItemReactions.js
rename to src/components/Reactions/ReportActionItemEmojiReactions.js
index 823fa065b0c6..bb21f034c11c 100644
--- a/src/components/Reactions/ReportActionItemReactions.js
+++ b/src/components/Reactions/ReportActionItemEmojiReactions.js
@@ -9,26 +9,14 @@ import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultPro
import withLocalize from '../withLocalize';
import compose from '../../libs/compose';
import * as Report from '../../libs/actions/Report';
+import EmojiReactionsPropTypes from './EmojiReactionsPropTypes';
import Tooltip from '../Tooltip';
import ReactionTooltipContent from './ReactionTooltipContent';
import * as EmojiUtils from '../../libs/EmojiUtils';
import ReportScreenContext from '../../pages/home/ReportScreenContext';
const propTypes = {
- /**
- * An array of objects containing the reaction data.
- * The shape of a reaction looks like this:
- *
- * "reactionName": {
- * emoji: string,
- * users: {
- * accountID: string,
- * skinTone: number,
- * }[]
- * }
- */
- // eslint-disable-next-line react/forbid-prop-types
- reactions: PropTypes.arrayOf(PropTypes.object).isRequired,
+ emojiReactions: EmojiReactionsPropTypes,
/** The ID of the reportAction. It is the string representation of the a 64-bit integer. */
reportActionID: PropTypes.string.isRequired,
@@ -45,27 +33,66 @@ const propTypes = {
const defaultProps = {
...withCurrentUserPersonalDetailsDefaultProps,
+ emojiReactions: {},
};
-function ReportActionItemReactions(props) {
+function ReportActionItemEmojiReactions(props) {
const {reactionListRef} = useContext(ReportScreenContext);
const popoverReactionListAnchor = useRef(null);
- const reactionsWithCount = _.filter(props.reactions, (reaction) => reaction.users.length > 0);
+ let totalReactionCount = 0;
+
+ // Each emoji is sorted by the oldest timestamp of user reactions so that they will always appear in the same order for everyone
+ const sortedReactions = _.sortBy(props.emojiReactions, (emojiReaction, emojiName) => {
+ // Since the emojiName is only stored as the object key, when _.sortBy() runs, the object is converted to an array and the
+ // keys are lost. To keep from losing the emojiName, it's copied to the emojiReaction object.
+ // eslint-disable-next-line no-param-reassign
+ emojiReaction.emojiName = emojiName;
+ const oldestUserReactionTimestamp = _.chain(emojiReaction.users)
+ .reduce((allTimestampsArray, userData) => {
+ if (!userData) {
+ return allTimestampsArray;
+ }
+ _.each(userData.skinTones, (createdAt) => {
+ allTimestampsArray.push(createdAt);
+ });
+ return allTimestampsArray;
+ }, [])
+ .sort()
+ .first()
+ .value();
+
+ // Just in case two emojis have the same timestamp, also combine the timestamp with the
+ // emojiName so that the order will always be the same. Without this, the order can be pretty random
+ // and shift around a little bit.
+ return (oldestUserReactionTimestamp || emojiReaction.createdAt) + emojiName;
+ });
return (
- {_.map(reactionsWithCount, (reaction) => {
- const reactionCount = reaction.users.length;
- const reactionUsers = _.map(reaction.users, (sender) => sender.accountID);
- const emoji = EmojiUtils.findEmojiByName(reaction.emoji);
- const emojiCodes = EmojiUtils.getUniqueEmojiCodes(emoji, reaction.users);
- const hasUserReacted = Report.hasAccountIDReacted(props.currentUserPersonalDetails.accountID, reactionUsers);
+ {_.map(sortedReactions, (reaction) => {
+ const reactionEmojiName = reaction.emojiName;
+ const usersWithReactions = _.pick(reaction.users, _.identity);
+ let reactionCount = 0;
+
+ // Loop through the users who have reacted and see how many skintones they reacted with so that we get the total count
+ _.forEach(usersWithReactions, (user) => {
+ reactionCount += _.size(user.skinTones);
+ });
+ if (!reactionCount) {
+ return null;
+ }
+ totalReactionCount += reactionCount;
+ const emojiAsset = EmojiUtils.findEmojiByName(reactionEmojiName);
+ const emojiCodes = EmojiUtils.getUniqueEmojiCodes(emojiAsset, reaction.users);
+ const hasUserReacted = Report.hasAccountIDEmojiReacted(props.currentUserPersonalDetails.accountID, reaction.users);
+ const reactionUsers = _.keys(usersWithReactions);
+ const reactionUserAccountIDs = _.map(reactionUsers, Number);
const onPress = () => {
- props.toggleReaction(emoji);
+ props.toggleReaction(emojiAsset);
};
const onReactionListOpen = (event) => {
@@ -76,14 +103,14 @@ function ReportActionItemReactions(props) {
(
)}
renderTooltipContentKey={[..._.map(reactionUsers, (user) => user.toString()), ...emojiCodes]}
- key={reaction.emoji}
+ key={reactionEmojiName}
>
);
})}
- {reactionsWithCount.length > 0 && (
+ {totalReactionCount > 0 && (
{
* Given an emoji object and a list of senders it will return an
* array of emoji codes, that represents all used variations of the
* emoji.
- * @param {{ name: string, code: string, types: string[] }} emoji
+ * @param {Object} emojiAsset
+ * @param {String} emojiAsset.name
+ * @param {String} emojiAsset.code
+ * @param {String[]} [emojiAsset.types]
* @param {Array} users
* @return {string[]}
* */
-const getUniqueEmojiCodes = (emoji, users) => {
- const emojiCodes = [];
- _.forEach(users, (user) => {
- const emojiCode = getPreferredEmojiCode(emoji, user.skinTone);
-
- if (emojiCode && !emojiCodes.includes(emojiCode)) {
- emojiCodes.push(emojiCode);
- }
+const getUniqueEmojiCodes = (emojiAsset, users) => {
+ const uniqueEmojiCodes = [];
+ _.each(users, (userSkinTones) => {
+ _.each(lodashGet(userSkinTones, 'skinTones'), (createdAt, skinTone) => {
+ const emojiCode = getPreferredEmojiCode(emojiAsset, skinTone);
+ if (emojiCode && !uniqueEmojiCodes.includes(emojiCode)) {
+ uniqueEmojiCodes.push(emojiCode);
+ }
+ });
});
- return emojiCodes;
+ return uniqueEmojiCodes;
};
export {
diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js
index 3c2a7be271cd..7a6cbd1d9d45 100644
--- a/src/libs/actions/Report.js
+++ b/src/libs/actions/Report.js
@@ -4,6 +4,7 @@ import lodashGet from 'lodash/get';
import ExpensiMark from 'expensify-common/lib/ExpensiMark';
import Onyx from 'react-native-onyx';
import Str from 'expensify-common/lib/str';
+import moment from 'moment';
import ONYXKEYS from '../../ONYXKEYS';
import * as Pusher from '../Pusher/pusher';
import LocalNotification from '../Notification/LocalNotification';
@@ -1554,179 +1555,134 @@ function clearIOUError(reportID) {
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {errorFields: {iou: null}});
}
-/**
- * Internal function to help with updating the onyx state of a message of a report action.
- * @param {Object} originalReportAction
- * @param {Object} message
- * @param {String} reportID
- * @return {Object[]}
- */
-function getOptimisticDataForReportActionUpdate(originalReportAction, message, reportID) {
- const reportActionID = originalReportAction.reportActionID;
-
- return [
- {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
- value: {
- [reportActionID]: {
- message: [message],
- },
- },
- },
- ];
-}
-
/**
* Returns true if the accountID has reacted to the report action (with the given skin tone).
- * @param {Number} accountID
- * @param {Array
)}
- {hasReactions && (
-
- {
- if (Session.isAnonymousUser()) {
- hideContextMenu(false);
-
- InteractionManager.runAfterInteractions(() => {
- Session.signOutAndRedirectToSignIn();
- });
- } else {
- toggleReaction(emoji);
- }
- }}
- />
-
- )}
+
+ {
+ if (Session.isAnonymousUser()) {
+ hideContextMenu(false);
+
+ InteractionManager.runAfterInteractions(() => {
+ Session.signOutAndRedirectToSignIn();
+ });
+ } else {
+ toggleReaction(emoji);
+ }
+ }}
+ />
+
+
{shouldDisplayThreadReplies && (
`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${action.reportActionID}`,
+ },
}),
)(
memo(
@@ -561,6 +563,7 @@ export default compose(
prevProps.isMostRecentIOUReportAction === nextProps.isMostRecentIOUReportAction &&
prevProps.hasOutstandingIOU === nextProps.hasOutstandingIOU &&
prevProps.shouldDisplayNewMarker === nextProps.shouldDisplayNewMarker &&
+ _.isEqual(prevProps.emojiReactions, nextProps.emojiReactions) &&
_.isEqual(prevProps.action, nextProps.action) &&
lodashGet(prevProps.report, 'statusNum') === lodashGet(nextProps.report, 'statusNum') &&
lodashGet(prevProps.report, 'stateNum') === lodashGet(nextProps.report, 'stateNum') &&
diff --git a/tests/actions/ReportTest.js b/tests/actions/ReportTest.js
index e896f7aca487..c50e8b250104 100644
--- a/tests/actions/ReportTest.js
+++ b/tests/actions/ReportTest.js
@@ -521,14 +521,23 @@ describe('actions/Report', () => {
const EMOJI = {
code: EMOJI_CODE,
name: EMOJI_NAME,
+ types: ['👍🏿', '👍🏾', '👍🏽', '👍🏼', '👍🏻'],
};
let reportActions;
-
Onyx.connect({
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${REPORT_ID}`,
callback: (val) => (reportActions = val),
});
+ const reportActionsReactions = {};
+ Onyx.connect({
+ key: ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS,
+ callback: (val, key) => {
+ reportActionsReactions[key] = val;
+ },
+ });
+ let reportAction;
+ let reportActionID;
// Set up Onyx with some test user data
return TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN)
@@ -544,76 +553,70 @@ describe('actions/Report', () => {
return waitForPromisesToResolve();
})
.then(() => {
- const resultAction = _.first(_.values(reportActions));
+ reportAction = _.first(_.values(reportActions));
+ reportActionID = reportAction.reportActionID;
// Add a reaction to the comment
- Report.addEmojiReaction(REPORT_ID, resultAction, EMOJI);
+ Report.toggleEmojiReaction(REPORT_ID, reportActionID, EMOJI);
return waitForPromisesToResolve();
})
.then(() => {
- const resultAction = _.first(_.values(reportActions));
+ // Expect the reaction to exist in the reportActionsReactions collection
+ expect(reportActionsReactions).toHaveProperty(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`);
- // Expect to have the reaction on the message
- expect(resultAction.message[0].reactions).toEqual(
- expect.arrayContaining([
- expect.objectContaining({
- emoji: EMOJI_NAME,
- users: expect.arrayContaining([expect.objectContaining({accountID: TEST_USER_ACCOUNT_ID})]),
- }),
- ]),
- );
+ // Expect the reaction to have the emoji on it
+ const reportActionReaction = reportActionsReactions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`];
+ expect(reportActionReaction).toHaveProperty(EMOJI.name);
+
+ // Expect the emoji to have the user accountID
+ const reportActionReactionEmoji = reportActionReaction[EMOJI.name];
+ expect(reportActionReactionEmoji.users).toHaveProperty(`${TEST_USER_ACCOUNT_ID}`);
// Now we remove the reaction
- Report.removeEmojiReaction(REPORT_ID, resultAction, EMOJI);
+ Report.toggleEmojiReaction(REPORT_ID, reportActionID, EMOJI, reportActionReaction);
return waitForPromisesToResolve();
})
.then(() => {
- // Expect that the reaction is removed
- const resultAction = _.first(_.values(reportActions));
-
- expect(resultAction.message[0].reactions).toHaveLength(0);
+ // Expect the reaction to have null where the users reaction used to be
+ expect(reportActionsReactions).toHaveProperty(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`);
+ const reportActionReaction = reportActionsReactions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`];
+ expect(reportActionReaction[EMOJI.name].users[TEST_USER_ACCOUNT_ID]).toBeNull();
})
.then(() => {
- const resultAction = _.first(_.values(reportActions));
-
- // Add the reaction to the comment, but two times with different variations
- Report.addEmojiReaction(REPORT_ID, resultAction, EMOJI);
+ // Add the same reaction to the same report action with a different skintone
+ Report.toggleEmojiReaction(REPORT_ID, reportActionID, EMOJI);
return waitForPromisesToResolve()
.then(() => {
- const updatedResultAction = _.first(_.values(reportActions));
- Report.addEmojiReaction(REPORT_ID, updatedResultAction, EMOJI, 2);
+ const reportActionReaction = reportActionsReactions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`];
+ Report.toggleEmojiReaction(REPORT_ID, reportActionID, EMOJI, reportActionReaction, EMOJI_SKIN_TONE);
return waitForPromisesToResolve();
})
.then(() => {
- const updatedResultAction = _.first(_.values(reportActions));
-
- // Expect to have the reaction on the message
- expect(updatedResultAction.message[0].reactions).toEqual(
- expect.arrayContaining([
- expect.objectContaining({
- emoji: EMOJI_NAME,
- users: expect.arrayContaining([
- expect.objectContaining({
- accountID: TEST_USER_ACCOUNT_ID,
- }),
- expect.objectContaining({
- accountID: TEST_USER_ACCOUNT_ID,
- skinTone: EMOJI_SKIN_TONE,
- }),
- ]),
- }),
- ]),
- );
+ // Expect the reaction to exist in the reportActionsReactions collection
+ expect(reportActionsReactions).toHaveProperty(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`);
+
+ // Expect the reaction to have the emoji on it
+ const reportActionReaction = reportActionsReactions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`];
+ expect(reportActionReaction).toHaveProperty(EMOJI.name);
+
+ // Expect the emoji to have the user accountID
+ const reportActionReactionEmoji = reportActionReaction[EMOJI.name];
+ expect(reportActionReactionEmoji.users).toHaveProperty(`${TEST_USER_ACCOUNT_ID}`);
+
+ // Expect two different skintone reactions
+ const reportActionReactionEmojiUserSkinTones = reportActionReactionEmoji.users[TEST_USER_ACCOUNT_ID].skinTones;
+ expect(reportActionReactionEmojiUserSkinTones).toHaveProperty('-1');
+ expect(reportActionReactionEmojiUserSkinTones).toHaveProperty('2');
// Now we remove the reaction, and expect that both variations are removed
- Report.removeEmojiReaction(REPORT_ID, updatedResultAction, EMOJI);
+ Report.toggleEmojiReaction(REPORT_ID, reportActionID, EMOJI, reportActionReaction);
return waitForPromisesToResolve();
})
.then(() => {
- // Expect that the reaction is removed
- const updatedResultAction = _.first(_.values(reportActions));
-
- expect(updatedResultAction.message[0].reactions).toHaveLength(0);
+ // Expect the reaction to have null where the users reaction used to be
+ expect(reportActionsReactions).toHaveProperty(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`);
+ const reportActionReaction = reportActionsReactions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`];
+ expect(reportActionReaction[EMOJI.name].users[TEST_USER_ACCOUNT_ID]).toBeNull();
});
});
});
@@ -632,11 +635,19 @@ describe('actions/Report', () => {
};
let reportActions;
-
Onyx.connect({
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${REPORT_ID}`,
callback: (val) => (reportActions = val),
});
+ const reportActionsReactions = {};
+ Onyx.connect({
+ key: ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS,
+ callback: (val, key) => {
+ reportActionsReactions[key] = val;
+ },
+ });
+
+ let resultAction;
// Set up Onyx with some test user data
return TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN)
@@ -652,26 +663,25 @@ describe('actions/Report', () => {
return waitForPromisesToResolve();
})
.then(() => {
- const resultAction = _.first(_.values(reportActions));
+ resultAction = _.first(_.values(reportActions));
// Add a reaction to the comment
- Report.toggleEmojiReaction(REPORT_ID, resultAction.reportActionID, EMOJI);
+ Report.toggleEmojiReaction(REPORT_ID, resultAction.reportActionID, EMOJI, {});
return waitForPromisesToResolve();
})
.then(() => {
- const resultAction = _.first(_.values(reportActions));
-
// Now we toggle the reaction while the skin tone has changed.
// As the emoji doesn't support skin tones, the emoji
// should get removed instead of added again.
- Report.toggleEmojiReaction(REPORT_ID, resultAction.reportActionID, EMOJI, 2);
+ const reportActionReaction = reportActionsReactions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${resultAction.reportActionID}`];
+ Report.toggleEmojiReaction(REPORT_ID, resultAction.reportActionID, EMOJI, reportActionReaction, 2);
return waitForPromisesToResolve();
})
.then(() => {
- const resultAction = _.first(_.values(reportActions));
-
- // Expect to have the reaction on the message
- expect(resultAction.message[0].reactions).toHaveLength(0);
+ // Expect the reaction to have null where the users reaction used to be
+ expect(reportActionsReactions).toHaveProperty(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${resultAction.reportActionID}`);
+ const reportActionReaction = reportActionsReactions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${resultAction.reportActionID}`];
+ expect(reportActionReaction[EMOJI.name].users[TEST_USER_ACCOUNT_ID]).toBeNull();
});
});
});