@stream-io/feeds-client 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index-react-bindings.browser.cjs +365 -207
  3. package/dist/index-react-bindings.browser.cjs.map +1 -1
  4. package/dist/index-react-bindings.browser.js +365 -207
  5. package/dist/index-react-bindings.browser.js.map +1 -1
  6. package/dist/index-react-bindings.node.cjs +365 -207
  7. package/dist/index-react-bindings.node.cjs.map +1 -1
  8. package/dist/index-react-bindings.node.js +365 -207
  9. package/dist/index-react-bindings.node.js.map +1 -1
  10. package/dist/index.browser.cjs +366 -207
  11. package/dist/index.browser.cjs.map +1 -1
  12. package/dist/index.browser.js +366 -208
  13. package/dist/index.browser.js.map +1 -1
  14. package/dist/index.node.cjs +366 -207
  15. package/dist/index.node.cjs.map +1 -1
  16. package/dist/index.node.js +366 -208
  17. package/dist/index.node.js.map +1 -1
  18. package/dist/src/feed/event-handlers/activity/handle-activity-deleted.d.ts +12 -3
  19. package/dist/src/feed/event-handlers/activity/handle-activity-pinned.d.ts +3 -0
  20. package/dist/src/feed/event-handlers/activity/handle-activity-reaction-added.d.ts +10 -6
  21. package/dist/src/feed/event-handlers/activity/handle-activity-reaction-deleted.d.ts +10 -6
  22. package/dist/src/feed/event-handlers/activity/handle-activity-unpinned.d.ts +3 -0
  23. package/dist/src/feed/event-handlers/activity/handle-activity-updated.d.ts +7 -3
  24. package/dist/src/feed/event-handlers/bookmark/handle-bookmark-added.d.ts +10 -6
  25. package/dist/src/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts +10 -6
  26. package/dist/src/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts +10 -6
  27. package/dist/src/gen/models/index.d.ts +36 -1
  28. package/dist/src/test-utils/response-generators.d.ts +46 -1
  29. package/dist/src/utils/index.d.ts +1 -0
  30. package/dist/src/utils/update-entity-in-array.d.ts +27 -0
  31. package/dist/tsconfig.tsbuildinfo +1 -1
  32. package/package.json +1 -1
  33. package/src/feed/event-handlers/activity/activity-reaction-utils.test.ts +108 -96
  34. package/src/feed/event-handlers/activity/activity-utils.test.ts +84 -122
  35. package/src/feed/event-handlers/activity/handle-activity-deleted.ts +43 -10
  36. package/src/feed/event-handlers/activity/handle-activity-pinned.test.ts +60 -0
  37. package/src/feed/event-handlers/activity/handle-activity-pinned.ts +30 -0
  38. package/src/feed/event-handlers/activity/handle-activity-reaction-added.test.ts +157 -0
  39. package/src/feed/event-handlers/activity/handle-activity-reaction-added.ts +82 -40
  40. package/src/feed/event-handlers/activity/handle-activity-reaction-deleted.test.ts +200 -0
  41. package/src/feed/event-handlers/activity/handle-activity-reaction-deleted.ts +89 -51
  42. package/src/feed/event-handlers/activity/handle-activity-unpinned.test.ts +94 -0
  43. package/src/feed/event-handlers/activity/handle-activity-unpinned.ts +30 -0
  44. package/src/feed/event-handlers/activity/handle-activity-updated.test.ts +115 -0
  45. package/src/feed/event-handlers/activity/handle-activity-updated.ts +73 -35
  46. package/src/feed/event-handlers/bookmark/bookmark-utils.test.ts +121 -109
  47. package/src/feed/event-handlers/bookmark/handle-bookmark-added.test.ts +178 -0
  48. package/src/feed/event-handlers/bookmark/handle-bookmark-added.ts +82 -39
  49. package/src/feed/event-handlers/bookmark/handle-bookmark-deleted.test.ts +188 -0
  50. package/src/feed/event-handlers/bookmark/handle-bookmark-deleted.ts +86 -48
  51. package/src/feed/event-handlers/bookmark/handle-bookmark-updated.test.ts +196 -0
  52. package/src/feed/event-handlers/bookmark/handle-bookmark-updated.ts +83 -44
  53. package/src/gen/model-decoders/decoders.ts +13 -0
  54. package/src/gen/models/index.ts +73 -2
  55. package/src/gen/moderation/ModerationApi.ts +1 -0
  56. package/src/test-utils/response-generators.ts +260 -0
  57. package/src/utils/index.ts +1 -0
  58. package/src/utils/update-entity-in-array.ts +51 -0
@@ -0,0 +1,60 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+
3
+ import { Feed } from '../../../feed';
4
+ import { FeedsClient } from '../../../feeds-client';
5
+ import { handleActivityPinned } from './handle-activity-pinned';
6
+ import {
7
+ generateActivityPinnedEvent,
8
+ generateActivityPinResponse,
9
+ generateFeedResponse,
10
+ } from '../../../test-utils/response-generators';
11
+ import { ActivityPinResponse } from '../../../gen/models';
12
+
13
+ describe(handleActivityPinned.name, () => {
14
+ let feed: Feed;
15
+ let client: FeedsClient;
16
+ let pinnedActivity: ActivityPinResponse;
17
+ let otherPinnedActivity: ActivityPinResponse;
18
+
19
+ beforeEach(() => {
20
+ client = new FeedsClient('mock-api-key');
21
+ const feedResponse = generateFeedResponse({ id: 'main', group_id: 'user' });
22
+ feed = new Feed(
23
+ client,
24
+ feedResponse.group_id,
25
+ feedResponse.id,
26
+ feedResponse,
27
+ );
28
+ pinnedActivity = generateActivityPinResponse();
29
+ otherPinnedActivity = generateActivityPinResponse();
30
+ feed.state.next((currentState) => ({
31
+ ...currentState,
32
+ pinned_activities: [otherPinnedActivity],
33
+ }));
34
+ });
35
+
36
+ it('adds a new activity to pinned_activities', () => {
37
+ const event = generateActivityPinnedEvent({
38
+ pinned_activity: pinnedActivity,
39
+ });
40
+ handleActivityPinned.call(feed, event);
41
+ const { pinned_activities } = feed.currentState;
42
+ expect(pinned_activities).toHaveLength(2);
43
+ expect(pinned_activities![0].activity.id).toBe(pinnedActivity.activity.id);
44
+ expect(pinned_activities![1]).toBe(otherPinnedActivity);
45
+ });
46
+
47
+ it('creates pinned_activities if it was undefined', () => {
48
+ feed.state.next((currentState) => ({
49
+ ...currentState,
50
+ pinned_activities: undefined,
51
+ }));
52
+ const event = generateActivityPinnedEvent({
53
+ pinned_activity: pinnedActivity,
54
+ });
55
+ handleActivityPinned.call(feed, event);
56
+ const { pinned_activities } = feed.currentState;
57
+ expect(pinned_activities).toHaveLength(1);
58
+ expect(pinned_activities![0].activity.id).toBe(pinnedActivity.activity.id);
59
+ });
60
+ });
@@ -0,0 +1,30 @@
1
+ import { ActivityPinResponse } from '../../../gen/models';
2
+ import { EventPayload } from '../../../types-internal';
3
+ import { Feed } from '../../feed';
4
+
5
+ export function handleActivityPinned(
6
+ this: Feed,
7
+ event: EventPayload<'feeds.activity.pinned'>,
8
+ ) {
9
+ this.state.next((currentState) => {
10
+ const newState = {
11
+ ...currentState,
12
+ };
13
+
14
+ // FIXME: type mismatch PinActivityResponse vs ActivityPinResponse (almost identical but not quite)
15
+
16
+ // re-map the event value to match the ActivityPinResponse type
17
+ const pinnedActivity: ActivityPinResponse = {
18
+ ...event.pinned_activity,
19
+ user: event.user!,
20
+ feed: event.fid,
21
+ updated_at: new Date(),
22
+ };
23
+
24
+ newState.pinned_activities = currentState.pinned_activities
25
+ ? [pinnedActivity, ...currentState.pinned_activities]
26
+ : [pinnedActivity];
27
+
28
+ return newState;
29
+ });
30
+ }
@@ -0,0 +1,157 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { Feed } from '../../../feed';
3
+ import { FeedsClient } from '../../../feeds-client';
4
+ import { handleActivityReactionAdded } from './handle-activity-reaction-added';
5
+ import {
6
+ generateActivityPinResponse,
7
+ generateActivityResponse,
8
+ generateFeedResponse,
9
+ generateOwnUser,
10
+ generateActivityReactionAddedEvent,
11
+ getHumanId,
12
+ } from '../../../test-utils/response-generators';
13
+
14
+ describe(handleActivityReactionAdded.name, () => {
15
+ let feed: Feed;
16
+ let client: FeedsClient;
17
+ let currentUserId: string;
18
+
19
+ beforeEach(() => {
20
+ client = new FeedsClient('mock-api-key');
21
+ currentUserId = getHumanId();
22
+ client.state.partialNext({
23
+ connected_user: generateOwnUser({ id: currentUserId }),
24
+ });
25
+ const feedResponse = generateFeedResponse({
26
+ id: 'main',
27
+ group_id: 'user',
28
+ created_by: { id: currentUserId },
29
+ });
30
+ feed = new Feed(
31
+ client,
32
+ feedResponse.group_id,
33
+ feedResponse.id,
34
+ feedResponse,
35
+ );
36
+ });
37
+
38
+ it('adds a reaction to the correct activity for current user & updates activities with event.activity', () => {
39
+ const event = generateActivityReactionAddedEvent({
40
+ reaction: {
41
+ user: { id: currentUserId },
42
+ },
43
+ activity: {
44
+ reaction_count: 1,
45
+ },
46
+ });
47
+ const activity = generateActivityResponse({
48
+ id: event.activity.id,
49
+ reaction_count: 0,
50
+ });
51
+ const activityPin = generateActivityPinResponse({
52
+ activity: { ...activity },
53
+ });
54
+ feed.state.partialNext({
55
+ activities: [activity],
56
+ pinned_activities: [activityPin],
57
+ });
58
+
59
+ const stateBefore = feed.currentState;
60
+
61
+ expect(stateBefore.activities![0].reaction_count).toEqual(0);
62
+ expect(stateBefore.pinned_activities![0].activity.reaction_count).toEqual(
63
+ 0,
64
+ );
65
+
66
+ handleActivityReactionAdded.call(feed, event);
67
+
68
+ const stateAfter = feed.currentState;
69
+
70
+ expect(stateAfter.activities![0].own_reactions).toContain(event.reaction);
71
+ expect(stateAfter.pinned_activities![0].activity.own_reactions).toContain(
72
+ event.reaction,
73
+ );
74
+ expect(stateAfter.activities![0].own_bookmarks).toEqual(
75
+ stateBefore.activities![0].own_bookmarks,
76
+ );
77
+ expect(stateAfter.pinned_activities![0].activity.own_bookmarks).toEqual(
78
+ stateBefore.pinned_activities![0].activity.own_bookmarks,
79
+ );
80
+ expect(stateAfter.activities![0].reaction_count).toEqual(1);
81
+ expect(stateAfter.pinned_activities![0].activity.reaction_count).toEqual(1);
82
+ });
83
+
84
+ it('does not add to own_reactions if reaction is from another user but still updates activity', () => {
85
+ const event = generateActivityReactionAddedEvent({
86
+ reaction: { user: { id: 'other-user-id' } },
87
+ activity: {
88
+ reaction_count: 1,
89
+ },
90
+ });
91
+ const activity = generateActivityResponse({
92
+ id: event.activity.id,
93
+ reaction_count: 0,
94
+ });
95
+ const activityPin = generateActivityPinResponse({
96
+ activity: { ...activity },
97
+ });
98
+ feed.state.partialNext({
99
+ activities: [activity],
100
+ pinned_activities: [activityPin],
101
+ });
102
+
103
+ const stateBefore = feed.currentState;
104
+
105
+ expect(stateBefore.activities![0].reaction_count).toEqual(0);
106
+ expect(stateBefore.pinned_activities![0].activity.reaction_count).toEqual(
107
+ 0,
108
+ );
109
+
110
+ handleActivityReactionAdded.call(feed, event);
111
+
112
+ const stateAfter = feed.currentState;
113
+
114
+ expect(stateAfter.activities![0].own_reactions).toHaveLength(0);
115
+ expect(
116
+ stateAfter.pinned_activities![0].activity.own_reactions,
117
+ ).toHaveLength(0);
118
+ expect(stateAfter.activities![0].reaction_count).toEqual(1);
119
+ expect(stateAfter.pinned_activities![0].activity.reaction_count).toEqual(1);
120
+ expect(stateAfter.activities![0].own_bookmarks).toEqual(
121
+ stateBefore.activities![0].own_bookmarks,
122
+ );
123
+ expect(stateAfter.pinned_activities![0].activity.own_bookmarks).toEqual(
124
+ stateBefore.pinned_activities![0].activity.own_bookmarks,
125
+ );
126
+ expect(stateAfter.activities![0].own_reactions).toEqual(
127
+ stateBefore.activities![0].own_reactions,
128
+ );
129
+ expect(stateAfter.pinned_activities![0].activity.own_reactions).toEqual(
130
+ stateBefore.pinned_activities![0].activity.own_reactions,
131
+ );
132
+ });
133
+
134
+ it('does nothing if activity is not found', () => {
135
+ const event = generateActivityReactionAddedEvent({
136
+ reaction: { user: { id: currentUserId } },
137
+ });
138
+ const activity = generateActivityResponse({
139
+ id: 'unrelated',
140
+ });
141
+ const activityPin = generateActivityPinResponse({
142
+ activity: { ...activity },
143
+ });
144
+ feed.state.partialNext({
145
+ activities: [activity],
146
+ pinned_activities: [activityPin],
147
+ });
148
+
149
+ const stateBefore = feed.currentState;
150
+
151
+ handleActivityReactionAdded.call(feed, event);
152
+
153
+ const stateAfter = feed.currentState;
154
+
155
+ expect(stateAfter).toEqual(stateBefore);
156
+ });
157
+ });
@@ -1,67 +1,109 @@
1
1
  import type { Feed } from '../../../feed';
2
2
  import type {
3
+ ActivityPinResponse,
3
4
  ActivityReactionAddedEvent,
4
5
  ActivityResponse,
5
6
  } from '../../../gen/models';
6
- import type { EventPayload, UpdateStateResult } from '../../../types-internal';
7
+ import type { EventPayload } from '../../../types-internal';
8
+ import { updateEntityInArray } from '../../../utils';
7
9
 
8
- import { updateActivityInState } from './handle-activity-updated';
10
+ // shared function to update the activity with the new reaction
11
+ const sharedUpdateActivity = ({
12
+ currentActivity,
13
+ event,
14
+ eventBelongsToCurrentUser,
15
+ }: {
16
+ currentActivity: ActivityResponse;
17
+ event: ActivityReactionAddedEvent;
18
+ eventBelongsToCurrentUser: boolean;
19
+ }) => {
20
+ let newOwnReactions = currentActivity.own_reactions;
9
21
 
10
- export const addReactionToActivity = (
11
- event: ActivityReactionAddedEvent,
12
- activity: ActivityResponse,
13
- isCurrentUser: boolean,
14
- ): UpdateStateResult<ActivityResponse> => {
15
- // Update own_reactions if the reaction is from the current user
16
- const ownReactions = [...(activity.own_reactions || [])];
17
- if (isCurrentUser) {
18
- ownReactions.push(event.reaction);
22
+ if (eventBelongsToCurrentUser) {
23
+ newOwnReactions = [...currentActivity.own_reactions, event.reaction];
19
24
  }
20
25
 
21
26
  return {
22
- ...activity,
23
- own_reactions: ownReactions,
24
- latest_reactions: event.activity.latest_reactions,
25
- reaction_groups: event.activity.reaction_groups,
26
- changed: true,
27
+ ...event.activity,
28
+ own_reactions: newOwnReactions,
29
+ own_bookmarks: currentActivity.own_bookmarks,
27
30
  };
28
31
  };
29
32
 
30
33
  export const addReactionToActivities = (
31
34
  event: ActivityReactionAddedEvent,
32
35
  activities: ActivityResponse[] | undefined,
33
- isCurrentUser: boolean,
34
- ): UpdateStateResult<{ activities: ActivityResponse[] }> => {
35
- if (!activities) {
36
- return { changed: false, activities: [] };
37
- }
36
+ eventBelongsToCurrentUser: boolean,
37
+ ) =>
38
+ updateEntityInArray({
39
+ entities: activities,
40
+ matcher: (activity) => activity.id === event.activity.id,
41
+ updater: (matchedActivity) =>
42
+ sharedUpdateActivity({
43
+ currentActivity: matchedActivity,
44
+ event,
45
+ eventBelongsToCurrentUser,
46
+ }),
47
+ });
38
48
 
39
- const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
40
- if (activityIndex === -1) {
41
- return { changed: false, activities };
42
- }
49
+ export const addReactionToPinnedActivities = (
50
+ event: ActivityReactionAddedEvent,
51
+ pinnedActivities: ActivityPinResponse[] | undefined,
52
+ eventBelongsToCurrentUser: boolean,
53
+ ) =>
54
+ updateEntityInArray({
55
+ entities: pinnedActivities,
56
+ matcher: (pinnedActivity) =>
57
+ pinnedActivity.activity.id === event.activity.id,
58
+ updater: (matchedPinnedActivity) => {
59
+ const newActivity = sharedUpdateActivity({
60
+ currentActivity: matchedPinnedActivity.activity,
61
+ event,
62
+ eventBelongsToCurrentUser,
63
+ });
43
64
 
44
- const activity = activities[activityIndex];
45
- const updatedActivity = addReactionToActivity(event, activity, isCurrentUser);
46
- return updateActivityInState(updatedActivity, activities, true);
47
- };
65
+ // this should never happen, but just in case
66
+ if (newActivity === matchedPinnedActivity.activity) {
67
+ return matchedPinnedActivity;
68
+ }
69
+
70
+ return {
71
+ ...matchedPinnedActivity,
72
+ activity: newActivity,
73
+ };
74
+ },
75
+ });
48
76
 
49
77
  export function handleActivityReactionAdded(
50
78
  this: Feed,
51
79
  event: EventPayload<'feeds.activity.reaction.added'>,
52
80
  ) {
53
- const currentActivities = this.currentState.activities;
81
+ const {
82
+ activities: currentActivities,
83
+ pinned_activities: currentPinnedActivities,
84
+ } = this.currentState;
54
85
  const connectedUser = this.client.state.getLatestValue().connected_user;
55
- const isCurrentUser = Boolean(
56
- connectedUser && event.reaction.user.id === connectedUser.id,
57
- );
86
+ const eventBelongsToCurrentUser =
87
+ typeof connectedUser !== 'undefined' &&
88
+ event.reaction.user.id === connectedUser.id;
89
+
90
+ const [result1, result2] = [
91
+ addReactionToActivities(
92
+ event,
93
+ currentActivities,
94
+ eventBelongsToCurrentUser,
95
+ ),
96
+ addReactionToPinnedActivities(
97
+ event,
98
+ currentPinnedActivities,
99
+ eventBelongsToCurrentUser,
100
+ ),
101
+ ];
58
102
 
59
- const result = addReactionToActivities(
60
- event,
61
- currentActivities,
62
- isCurrentUser,
63
- );
64
- if (result.changed) {
65
- this.state.partialNext({ activities: result.activities });
103
+ if (result1.changed || result2.changed) {
104
+ this.state.partialNext({
105
+ activities: result1.entities,
106
+ pinned_activities: result2.entities,
107
+ });
66
108
  }
67
109
  }
@@ -0,0 +1,200 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { Feed } from '../../../feed';
3
+ import { FeedsClient } from '../../../feeds-client';
4
+ import { handleActivityReactionDeleted } from './handle-activity-reaction-deleted';
5
+ import {
6
+ generateActivityPinResponse,
7
+ generateActivityResponse,
8
+ generateFeedReactionResponse,
9
+ generateFeedResponse,
10
+ generateOwnUser,
11
+ getHumanId,
12
+ generateActivityReactionDeletedEvent,
13
+ } from '../../../test-utils/response-generators';
14
+
15
+ describe(handleActivityReactionDeleted.name, () => {
16
+ let feed: Feed;
17
+ let client: FeedsClient;
18
+ let currentUserId: string;
19
+
20
+ beforeEach(() => {
21
+ client = new FeedsClient('mock-api-key');
22
+ currentUserId = getHumanId();
23
+ client.state.partialNext({
24
+ connected_user: generateOwnUser({ id: currentUserId }),
25
+ });
26
+ const feedResponse = generateFeedResponse({
27
+ id: 'main',
28
+ group_id: 'user',
29
+ created_by: { id: currentUserId },
30
+ });
31
+ feed = new Feed(
32
+ client,
33
+ feedResponse.group_id,
34
+ feedResponse.id,
35
+ feedResponse,
36
+ );
37
+ });
38
+
39
+ it('removes a reaction from the correct activity for current user & updates activities with event.activity', () => {
40
+ const event = generateActivityReactionDeletedEvent({
41
+ activity: {
42
+ reaction_count: 0,
43
+ },
44
+ reaction: {
45
+ type: 'like',
46
+ user: { id: currentUserId },
47
+ },
48
+ user: { id: currentUserId },
49
+ });
50
+
51
+ const activity = generateActivityResponse({
52
+ reaction_count: 1,
53
+ own_reactions: [
54
+ generateFeedReactionResponse({
55
+ type: 'like',
56
+ user: { id: currentUserId },
57
+ activity_id: event.activity.id,
58
+ }),
59
+ ],
60
+ id: event.activity.id,
61
+ });
62
+ const activityPin = generateActivityPinResponse({
63
+ activity: { ...activity },
64
+ });
65
+ feed.state.partialNext({
66
+ activities: [activity],
67
+ pinned_activities: [activityPin],
68
+ });
69
+
70
+ const stateBefore = feed.currentState;
71
+ expect(stateBefore.activities![0].own_reactions).toHaveLength(1);
72
+ expect(
73
+ stateBefore.pinned_activities![0].activity.own_reactions,
74
+ ).toHaveLength(1);
75
+ expect(stateBefore.activities![0].reaction_count).toEqual(1);
76
+ expect(stateBefore.pinned_activities![0].activity.reaction_count).toEqual(
77
+ 1,
78
+ );
79
+
80
+ handleActivityReactionDeleted.call(feed, event);
81
+
82
+ const stateAfter = feed.currentState;
83
+ expect(stateAfter.activities![0].own_reactions).toHaveLength(0);
84
+ expect(
85
+ stateAfter.pinned_activities![0].activity.own_reactions,
86
+ ).toHaveLength(0);
87
+ expect(stateAfter.activities![0].reaction_count).toEqual(0);
88
+ expect(stateAfter.pinned_activities![0].activity.reaction_count).toEqual(0);
89
+ expect(stateAfter.activities![0].own_bookmarks).toEqual(
90
+ stateBefore.activities![0].own_bookmarks,
91
+ );
92
+ expect(stateAfter.pinned_activities![0].activity.own_bookmarks).toEqual(
93
+ stateBefore.pinned_activities![0].activity.own_bookmarks,
94
+ );
95
+ });
96
+
97
+ it('does not remove from own_reactions if reaction is from another user but still updates activity', () => {
98
+ const event = generateActivityReactionDeletedEvent({
99
+ activity: {
100
+ reaction_count: 0,
101
+ },
102
+ reaction: {
103
+ type: 'like',
104
+ user: { id: 'other-user-id' },
105
+ },
106
+ user: { id: 'other-user-id' },
107
+ });
108
+
109
+ const activity = generateActivityResponse({
110
+ reaction_count: 1,
111
+ own_reactions: [
112
+ generateFeedReactionResponse({
113
+ type: 'like',
114
+ user: { id: currentUserId },
115
+ activity_id: event.activity.id,
116
+ }),
117
+ ],
118
+ id: event.activity.id,
119
+ });
120
+ const activityPin = generateActivityPinResponse({
121
+ activity: { ...activity },
122
+ });
123
+ feed.state.partialNext({
124
+ activities: [activity],
125
+ pinned_activities: [activityPin],
126
+ });
127
+
128
+ const stateBefore = feed.currentState;
129
+ expect(stateBefore.activities![0].own_reactions).toHaveLength(1);
130
+ expect(
131
+ stateBefore.pinned_activities![0].activity.own_reactions,
132
+ ).toHaveLength(1);
133
+ expect(stateBefore.activities![0].reaction_count).toEqual(1);
134
+ expect(stateBefore.pinned_activities![0].activity.reaction_count).toEqual(
135
+ 1,
136
+ );
137
+
138
+ handleActivityReactionDeleted.call(feed, event);
139
+
140
+ const stateAfter = feed.currentState;
141
+ expect(stateAfter.activities![0].own_reactions).toHaveLength(1);
142
+ expect(stateAfter.activities![0].own_reactions).toEqual(
143
+ stateBefore.activities![0].own_reactions,
144
+ );
145
+ expect(stateAfter.pinned_activities![0].activity.own_reactions).toEqual(
146
+ stateBefore.pinned_activities![0].activity.own_reactions,
147
+ );
148
+ expect(stateAfter.activities![0].own_bookmarks).toEqual(
149
+ stateBefore.activities![0].own_bookmarks,
150
+ );
151
+ expect(stateAfter.pinned_activities![0].activity.own_bookmarks).toEqual(
152
+ stateBefore.pinned_activities![0].activity.own_bookmarks,
153
+ );
154
+ expect(
155
+ stateAfter.pinned_activities![0].activity.own_reactions,
156
+ ).toHaveLength(1);
157
+ expect(stateAfter.activities![0].reaction_count).toEqual(0);
158
+ expect(stateAfter.pinned_activities![0].activity.reaction_count).toEqual(0);
159
+ });
160
+
161
+ it('does nothing if activity is not found', () => {
162
+ const event = generateActivityReactionDeletedEvent({
163
+ activity: {
164
+ reaction_count: 0,
165
+ },
166
+ reaction: {
167
+ type: 'like',
168
+ user: { id: currentUserId },
169
+ },
170
+ user: { id: currentUserId },
171
+ });
172
+
173
+ const activity = generateActivityResponse({
174
+ reaction_count: 1,
175
+ own_reactions: [
176
+ generateFeedReactionResponse({
177
+ type: 'like',
178
+ user: { id: currentUserId },
179
+ activity_id: 'activity1',
180
+ }),
181
+ ],
182
+ id: 'activity1',
183
+ });
184
+ const activityPin = generateActivityPinResponse({
185
+ activity: { ...activity },
186
+ });
187
+ feed.state.partialNext({
188
+ activities: [activity],
189
+ pinned_activities: [activityPin],
190
+ });
191
+
192
+ const stateBefore = feed.currentState;
193
+
194
+ handleActivityReactionDeleted.call(feed, event);
195
+
196
+ const stateAfter = feed.currentState;
197
+
198
+ expect(stateAfter).toBe(stateBefore);
199
+ });
200
+ });