Skip to content

Commit b5b2180

Browse files
authored
fix: allow to post twice a like on an item (#1864)
* fix: allow to post twice a like on an item * fix: make requested changes
1 parent 71cf0ab commit b5b2180

4 files changed

Lines changed: 60 additions & 3 deletions

File tree

src/services/item/plugins/itemLike/itemLike.controller.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { isAfter } from 'date-fns';
12
import { eq } from 'drizzle-orm';
23
import { StatusCodes } from 'http-status-codes';
34

@@ -325,6 +326,40 @@ describe('Item Like', () => {
325326
expect(savedLikes[1].creatorId).toEqual(actor.id);
326327
});
327328

329+
it('Allows to override like if already exist', async () => {
330+
const {
331+
actor,
332+
items: [item],
333+
} = await seedFromJson({
334+
items: [
335+
{
336+
likes: ['actor'],
337+
memberships: [{ account: 'actor', permission: PermissionLevel.Read }],
338+
},
339+
],
340+
});
341+
assertIsDefined(actor);
342+
assertIsMember(actor);
343+
mockAuthenticate(actor);
344+
const [initialLike] = await getItemLikesByItem(item.id);
345+
346+
const res = await app.inject({
347+
method: HttpMethod.Post,
348+
url: `/items/${item.id}/like`,
349+
});
350+
expect(res.statusCode).toBe(StatusCodes.OK);
351+
// the creatorId should be the same
352+
const result = await res.json();
353+
expect(result.creatorId).toEqual(actor.id);
354+
355+
// check received item like
356+
// since we don't have full item, deduce from saved value
357+
const savedLikes = await getItemLikesByItem(item.id);
358+
expect(savedLikes).toHaveLength(1);
359+
expect(savedLikes[0].creatorId).toEqual(actor.id);
360+
expect(isAfter(savedLikes[0].createdAt, initialLike.createdAt)).toBeTruthy();
361+
});
362+
328363
it('Cannot like item if does not have rights', async () => {
329364
const {
330365
actor,

src/services/item/plugins/itemLike/itemLike.controller.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
5454
} = request;
5555
const member = asDefined(user?.account);
5656
assertIsMember(member);
57-
await db.transaction(async (tx) => {
58-
await itemLikeService.post(tx, member, itemId);
57+
return await db.transaction(async (tx) => {
58+
const itemLike = await itemLikeService.post(tx, member, itemId);
5959
// action like item
6060
const item = await authorizedItemService.getItemById(tx, { actor: member, itemId });
6161
const action = {
@@ -66,6 +66,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
6666
},
6767
};
6868
await actionService.postMany(tx, member, request, [action]);
69+
return itemLike;
6970
});
7071
},
7172
);

src/services/item/plugins/itemLike/itemLike.repository.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { sql } from 'drizzle-orm';
12
import { and, eq } from 'drizzle-orm/sql';
23
import { singleton } from 'tsyringe';
34

@@ -36,6 +37,10 @@ export class ItemLikeRepository {
3637
const result = await dbConnection
3738
.insert(itemLikesTable)
3839
.values({ itemId, creatorId })
40+
.onConflictDoUpdate({
41+
target: [itemLikesTable.itemId, itemLikesTable.creatorId],
42+
set: { createdAt: sql.raw('DEFAULT') },
43+
})
3944
.returning();
4045
if (result.length != 1) {
4146
throw new Error('Expected to receive, created item, but did not get it.');

src/services/item/plugins/itemLike/itemLike.schemas.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,22 @@ export const getLikesForItem = {
6060
},
6161
};
6262

63+
const rawItemLikeSchemaRef = registerSchemaAsRef(
64+
'rawItemLike',
65+
'Raw Item Like',
66+
customType.StrictObject(
67+
{
68+
id: customType.UUID(),
69+
itemId: customType.UUID(),
70+
creatorId: customType.UUID(),
71+
createdAt: customType.DateTime(),
72+
},
73+
{
74+
description: 'Raw Like entry created when a member likes an item.',
75+
},
76+
),
77+
);
78+
6379
export const create = {
6480
operationId: 'createItemLike',
6581
tags: ['like'],
@@ -70,7 +86,7 @@ export const create = {
7086
itemId: customType.UUID(),
7187
}),
7288
response: {
73-
[StatusCodes.OK]: itemLikeSchemaRef,
89+
[StatusCodes.OK]: rawItemLikeSchemaRef,
7490
'4xx': errorSchemaRef,
7591
},
7692
};

0 commit comments

Comments
 (0)