From d562a25c78afb75db7442e8ef50f4fc27626dcdf Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 20 May 2020 11:46:49 -0500 Subject: [PATCH] Add emojiReact utils with tests --- .../components/status_interaction_bar.js | 41 +------ .../utils/__tests__/emoji_reacts-test.js | 110 ++++++++++++++++++ app/gabsocial/utils/emoji_reacts.js | 40 +++++++ 3 files changed, 156 insertions(+), 35 deletions(-) create mode 100644 app/gabsocial/utils/__tests__/emoji_reacts-test.js create mode 100644 app/gabsocial/utils/emoji_reacts.js diff --git a/app/gabsocial/features/status/components/status_interaction_bar.js b/app/gabsocial/features/status/components/status_interaction_bar.js index 6859601e4..bb276dd84 100644 --- a/app/gabsocial/features/status/components/status_interaction_bar.js +++ b/app/gabsocial/features/status/components/status_interaction_bar.js @@ -1,16 +1,7 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import emojify from 'gabsocial/features/emoji/emoji'; - -// https://emojipedia.org/facebook/ -const ALLOWED_EMOJI = [ - '👍', - '❤️', - '😂', - '😯', - '😢', - '😡', -]; +import { reduceEmoji } from 'gabsocial/utils/emoji_reacts'; export class StatusInteractionBar extends React.Component { @@ -18,35 +9,15 @@ export class StatusInteractionBar extends React.Component { status: ImmutablePropTypes.map, } - sortEmoji = emojiReacts => ( - emojiReacts // TODO: Sort by count - ); - - mergeEmoji = emojiReacts => ( - emojiReacts // TODO: Merge similar emoji - ); - - filterEmoji = emojiReacts => ( - emojiReacts.filter(emojiReact => ( - ALLOWED_EMOJI.includes(emojiReact.get('name')) - ))) - render() { const { status } = this.props; const emojiReacts = status.getIn(['pleroma', 'emoji_reactions']); - const likeCount = status.get('favourites_count'); + const favouritesCount = status.get('favourites_count'); return ( - <> - {likeCount > 0 && - - {likeCount} - } - {this.filterEmoji(emojiReacts).map(e => ( - +
+ {reduceEmoji(emojiReacts, favouritesCount).map((e, i) => ( + {e.get('count')} ))} - +
); } diff --git a/app/gabsocial/utils/__tests__/emoji_reacts-test.js b/app/gabsocial/utils/__tests__/emoji_reacts-test.js new file mode 100644 index 000000000..f0577c582 --- /dev/null +++ b/app/gabsocial/utils/__tests__/emoji_reacts-test.js @@ -0,0 +1,110 @@ +import { + sortEmoji, + mergeEmojiFavourites, + filterEmoji, + reduceEmoji, +} from '../emoji_reacts'; +import { fromJS } from 'immutable'; + +describe('filterEmoji', () => { + describe('with a mix of allowed and disallowed emoji', () => { + const emojiReacts = fromJS([ + { 'count': 1, 'me': true, 'name': '🌵' }, + { 'count': 1, 'me': true, 'name': '😂' }, + { 'count': 1, 'me': true, 'name': '👀' }, + { 'count': 1, 'me': true, 'name': '🍩' }, + { 'count': 1, 'me': true, 'name': '😡' }, + { 'count': 1, 'me': true, 'name': '🔪' }, + { 'count': 1, 'me': true, 'name': '😠' }, + ]); + it('filters only allowed emoji', () => { + expect(filterEmoji(emojiReacts)).toEqual(fromJS([ + { 'count': 1, 'me': true, 'name': '😂' }, + { 'count': 1, 'me': true, 'name': '😡' }, + ])); + }); + }); +}); + +describe('sortEmoji', () => { + describe('with an unsorted list of emoji', () => { + const emojiReacts = fromJS([ + { 'count': 7, 'me': true, 'name': '😯' }, + { 'count': 3, 'me': true, 'name': '😢' }, + { 'count': 1, 'me': true, 'name': '😡' }, + { 'count': 20, 'me': true, 'name': '👍' }, + { 'count': 7, 'me': true, 'name': '😂' }, + { 'count': 15, 'me': true, 'name': '❤️' }, + ]); + it('sorts the emoji by count', () => { + expect(sortEmoji(emojiReacts)).toEqual(fromJS([ + { 'count': 20, 'me': true, 'name': '👍' }, + { 'count': 15, 'me': true, 'name': '❤️' }, + { 'count': 7, 'me': true, 'name': '😯' }, + { 'count': 7, 'me': true, 'name': '😂' }, + { 'count': 3, 'me': true, 'name': '😢' }, + { 'count': 1, 'me': true, 'name': '😡' }, + ])); + }); + }); +}); + +describe('mergeEmojiFavourites', () => { + const favouritesCount = 12; + + describe('with existing 👍 reacts', () => { + const emojiReacts = fromJS([ + { 'count': 20, 'me': true, 'name': '👍' }, + { 'count': 15, 'me': true, 'name': '❤️' }, + { 'count': 7, 'me': true, 'name': '😯' }, + ]); + it('combines 👍 reacts with favourites', () => { + expect(mergeEmojiFavourites(emojiReacts, favouritesCount)).toEqual(fromJS([ + { 'count': 32, 'me': true, 'name': '👍' }, + { 'count': 15, 'me': true, 'name': '❤️' }, + { 'count': 7, 'me': true, 'name': '😯' }, + ])); + }); + }); + + describe('without existing 👍 reacts', () => { + const emojiReacts = fromJS([ + { 'count': 15, 'me': true, 'name': '❤️' }, + { 'count': 7, 'me': true, 'name': '😯' }, + ]); + it('adds 👍 reacts to the map equaling favourite count', () => { + expect(mergeEmojiFavourites(emojiReacts, favouritesCount)).toEqual(fromJS([ + { 'count': 15, 'me': true, 'name': '❤️' }, + { 'count': 7, 'me': true, 'name': '😯' }, + { 'count': 12, 'me': false, 'name': '👍' }, + ])); + }); + }); +}); + +describe('reduceEmoji', () => { + describe('with a clusterfuck of emoji', () => { + const emojiReacts = fromJS([ + { 'count': 1, 'me': false, 'name': '😡' }, + { 'count': 1, 'me': true, 'name': '🔪' }, + { 'count': 7, 'me': true, 'name': '😯' }, + { 'count': 3, 'me': false, 'name': '😢' }, + { 'count': 1, 'me': true, 'name': '🌵' }, + { 'count': 20, 'me': true, 'name': '👍' }, + { 'count': 7, 'me': false, 'name': '😂' }, + { 'count': 15, 'me': true, 'name': '❤️' }, + { 'count': 1, 'me': false, 'name': '👀' }, + { 'count': 1, 'me': false, 'name': '🍩' }, + ]); + it('sorts, filters, and combines emoji and favourites', () => { + expect(reduceEmoji(emojiReacts, 7)).toEqual(fromJS([ + { 'count': 27, 'me': true, 'name': '👍' }, + { 'count': 15, 'me': true, 'name': '❤️' }, + { 'count': 7, 'me': true, 'name': '😯' }, + { 'count': 7, 'me': false, 'name': '😂' }, + { 'count': 3, 'me': false, 'name': '😢' }, + { 'count': 1, 'me': false, 'name': '😡' }, + ])); + }); + }); +}); diff --git a/app/gabsocial/utils/emoji_reacts.js b/app/gabsocial/utils/emoji_reacts.js new file mode 100644 index 000000000..b2426b9a2 --- /dev/null +++ b/app/gabsocial/utils/emoji_reacts.js @@ -0,0 +1,40 @@ +import { Map as ImmutableMap } from 'immutable'; + +// https://emojipedia.org/facebook/ +export const ALLOWED_EMOJI = [ + '👍', + '❤️', + '😂', + '😯', + '😢', + '😡', +]; + +export const sortEmoji = emojiReacts => ( + emojiReacts.sortBy(emojiReact => -emojiReact.get('count')) +); + +export const mergeEmoji = emojiReacts => ( + emojiReacts // TODO: Merge similar emoji +); + +export const mergeEmojiFavourites = (emojiReacts, favouritesCount) => { + const likeIndex = emojiReacts.findIndex(emojiReact => + emojiReact.get('name') === '👍'); + if (likeIndex > -1) { + const likeCount = emojiReacts.getIn([likeIndex, 'count']); + return emojiReacts.setIn([likeIndex, 'count'], likeCount + favouritesCount); + } else { + return emojiReacts.push(ImmutableMap({ count: favouritesCount, me: false, name: '👍' })); + } +}; + +export const filterEmoji = emojiReacts => ( + emojiReacts.filter(emojiReact => ( + ALLOWED_EMOJI.includes(emojiReact.get('name')) + ))); + +export const reduceEmoji = (emojiReacts, favouritesCount) => ( + sortEmoji(filterEmoji(mergeEmoji(mergeEmojiFavourites( + emojiReacts, favouritesCount + )))));