Skip to content
This repository was archived by the owner on Feb 12, 2025. It is now read-only.

Commit 3b40b5d

Browse files
authored
fix: deduplicate item ids on add favorites (#256)
1 parent 4edf294 commit 3b40b5d

File tree

2 files changed

+56
-6
lines changed

2 files changed

+56
-6
lines changed

src/mutations/member.test.ts

+43
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,49 @@ describe('Member Mutations', () => {
357357
expect(newData).toEqualImmutable(response);
358358
});
359359

360+
it(`Adding duplicated favorite item should dedupe`, async () => {
361+
const response = MEMBER_RESPONSE.set(
362+
'extra',
363+
convertJs({ favoriteItems: ['item-id'] }),
364+
);
365+
// set random data in cache
366+
queryClient.setQueryData(CURRENT_MEMBER_KEY, response);
367+
const endpoints = [
368+
{
369+
response,
370+
method: HttpMethod.PATCH,
371+
route,
372+
},
373+
];
374+
const mockedMutation = await mockMutation({
375+
mutation,
376+
wrapper,
377+
endpoints,
378+
});
379+
380+
await act(async () => {
381+
await mockedMutation.mutate({
382+
memberId: id,
383+
itemId,
384+
extra: { favoriteItems: ['item-id'] },
385+
});
386+
await waitForMutation();
387+
});
388+
389+
expect(
390+
queryClient.getQueryState(CURRENT_MEMBER_KEY)?.isInvalidated,
391+
).toBeTruthy();
392+
expect(mockedNotifier).toHaveBeenCalledWith({
393+
type: addFavoriteItemRoutine.SUCCESS,
394+
});
395+
396+
// verify cache keys
397+
const newData = queryClient.getQueryData(
398+
CURRENT_MEMBER_KEY,
399+
) as MemberRecord;
400+
expect(newData).toEqualImmutable(response);
401+
});
402+
360403
it(`Unauthorized`, async () => {
361404
// set random data in cache
362405
queryClient.setQueryData(CURRENT_MEMBER_KEY, MEMBER_RESPONSE);

src/mutations/member.ts

+13-6
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,18 @@ export default (queryClient: QueryClient, queryConfig: QueryClientConfig) => {
143143
// mutation to update favorite items of given member
144144
queryClient.setMutationDefaults(ADD_FAVORITE_ITEM, {
145145
mutationFn: ({ memberId, itemId, extra: prevExtra }) => {
146-
const newFavoriteItems = prevExtra.favoriteItems
147-
? prevExtra.favoriteItems.concat([itemId])
146+
const favoriteItems = prevExtra.favoriteItems
147+
? prevExtra.favoriteItems.concat(
148+
prevExtra.favoriteItems.includes(itemId) ? [] : [itemId],
149+
)
148150
: [itemId];
149151
return Api.editMember(
150152
{
151153
id: memberId,
152-
extra: { ...prevExtra, favoriteItems: newFavoriteItems },
154+
extra: {
155+
...prevExtra,
156+
favoriteItems,
157+
},
153158
},
154159
queryConfig,
155160
).then((member) => convertJs(member));
@@ -164,12 +169,14 @@ export default (queryClient: QueryClient, queryConfig: QueryClientConfig) => {
164169

165170
// Optimistically update to the new value
166171
const { itemId, extra } = payload;
167-
const newFavoriteItems = extra.favoriteItems
168-
? extra.favoriteItems.concat([itemId])
172+
const favoriteItems = extra.favoriteItems
173+
? extra.favoriteItems.concat(
174+
extra.favoriteItems.includes(itemId) ? [] : [itemId],
175+
)
169176
: [itemId];
170177

171178
const member = convertJs({
172-
extra: { ...extra, favoriteItems: newFavoriteItems },
179+
extra: { ...extra, favoriteItems },
173180
});
174181

175182
queryClient.setQueryData(

0 commit comments

Comments
 (0)