Skip to content

Commit 95e404e

Browse files
authored
fix: add thumbnail URL access to bookmarks (#2143)
* Add thumbnail URL support in BookmarkService and tests * fix: BookmarkService test to look for undefined URLs
1 parent 4e9f07d commit 95e404e

2 files changed

Lines changed: 111 additions & 1 deletion

File tree

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { v4 } from 'uuid';
2+
import { describe, expect, it, vi } from 'vitest';
3+
4+
import { ItemFactory } from '../../../../../test/factories/item.factory';
5+
import { MemberFactory } from '../../../../../test/factories/member.factory';
6+
import type { DBConnection } from '../../../../drizzle/db';
7+
import { AuthorizedItemService } from '../../../authorizedItem.service';
8+
import { ItemMembershipRepository } from '../../../itemMembership/membership.repository';
9+
import { ItemVisibilityRepository } from '../itemVisibility/itemVisibility.repository';
10+
import { ItemThumbnailService } from '../thumbnail/itemThumbnail.service';
11+
import { ItemBookmarkRepository } from './itemBookmark.repository';
12+
import { BookmarkService } from './itemBookmark.service';
13+
14+
const dbConnection = {} as DBConnection;
15+
16+
describe('BookmarkService', () => {
17+
describe('getOwn', () => {
18+
it('returns packed bookmarked items with thumbnail URLs', async () => {
19+
const member = MemberFactory();
20+
const itemWithThumbnail = ItemFactory({ settings: { hasThumbnail: true } });
21+
const itemWithoutThumbnail = ItemFactory({ settings: { hasThumbnail: false } });
22+
const thumbnailUrls = {
23+
[itemWithThumbnail.id]: {
24+
small: 'https://example.com/small-thumbnail',
25+
medium: 'https://example.com/medium-thumbnail',
26+
},
27+
};
28+
const bookmarks = [
29+
{
30+
id: v4(),
31+
itemId: itemWithThumbnail.id,
32+
memberId: member.id,
33+
createdAt: new Date().toISOString(),
34+
item: itemWithThumbnail,
35+
},
36+
{
37+
id: v4(),
38+
itemId: itemWithoutThumbnail.id,
39+
memberId: member.id,
40+
createdAt: new Date().toISOString(),
41+
item: itemWithoutThumbnail,
42+
},
43+
];
44+
45+
const itemBookmarkRepository = {
46+
getBookmarksForMember: vi.fn().mockResolvedValue(bookmarks),
47+
} as unknown as ItemBookmarkRepository;
48+
const itemMembershipRepository = {
49+
getForManyItems: vi.fn().mockResolvedValue({
50+
data: {
51+
[itemWithThumbnail.id]: [{ permission: 'read' }],
52+
[itemWithoutThumbnail.id]: [{ permission: 'read' }],
53+
},
54+
errors: [],
55+
}),
56+
} as unknown as ItemMembershipRepository;
57+
const itemVisibilityRepository = {
58+
getManyForMany: vi.fn().mockResolvedValue({
59+
data: {
60+
[itemWithThumbnail.id]: [],
61+
[itemWithoutThumbnail.id]: [],
62+
},
63+
errors: [],
64+
}),
65+
} as unknown as ItemVisibilityRepository;
66+
const itemThumbnailService = {
67+
getUrlsByItems: vi.fn().mockResolvedValue(thumbnailUrls),
68+
} as unknown as ItemThumbnailService;
69+
70+
const service = new BookmarkService(
71+
{} as AuthorizedItemService,
72+
itemBookmarkRepository,
73+
itemMembershipRepository,
74+
itemVisibilityRepository,
75+
itemThumbnailService,
76+
);
77+
78+
const result = await service.getOwn(dbConnection, member);
79+
80+
expect(itemThumbnailService.getUrlsByItems).toHaveBeenCalledWith([
81+
itemWithThumbnail,
82+
itemWithoutThumbnail,
83+
]);
84+
expect(result).toHaveLength(2);
85+
expect(result[0]).toMatchObject({
86+
id: bookmarks[0].id,
87+
createdAt: bookmarks[0].createdAt,
88+
item: {
89+
id: itemWithThumbnail.id,
90+
thumbnails: thumbnailUrls[itemWithThumbnail.id],
91+
},
92+
});
93+
expect(result[1]).toMatchObject({
94+
id: bookmarks[1].id,
95+
createdAt: bookmarks[1].createdAt,
96+
item: {
97+
id: itemWithoutThumbnail.id,
98+
},
99+
});
100+
expect(result[1].item.thumbnails).toBeUndefined();
101+
});
102+
});
103+
});

src/services/item/plugins/itemBookmark/itemBookmark.service.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { AuthorizedItemService } from '../../../authorizedItem.service';
88
import { ItemMembershipRepository } from '../../../itemMembership/membership.repository';
99
import type { PackedItem } from '../../packedItem.dto';
1010
import { ItemVisibilityRepository } from '../itemVisibility/itemVisibility.repository';
11+
import { ItemThumbnailService } from '../thumbnail/itemThumbnail.service';
1112
import { ItemBookmarkRepository } from './itemBookmark.repository';
1213

1314
type PackedBookmarkedItem = ItemBookmarkRaw & { item: PackedItem };
@@ -18,24 +19,29 @@ export class BookmarkService {
1819
private readonly itemBookmarkRepository: ItemBookmarkRepository;
1920
private readonly itemMembershipRepository: ItemMembershipRepository;
2021
private readonly itemVisibilityRepository: ItemVisibilityRepository;
22+
private readonly itemThumbnailService: ItemThumbnailService;
2123

2224
constructor(
2325
authorizedItemService: AuthorizedItemService,
2426
itemBookmarkRepository: ItemBookmarkRepository,
2527
itemMembershipRepository: ItemMembershipRepository,
2628
itemVisibilityRepository: ItemVisibilityRepository,
29+
itemThumbnailService: ItemThumbnailService,
2730
) {
2831
this.authorizedItemService = authorizedItemService;
2932
this.itemBookmarkRepository = itemBookmarkRepository;
3033
this.itemMembershipRepository = itemMembershipRepository;
3134
this.itemVisibilityRepository = itemVisibilityRepository;
35+
this.itemThumbnailService = itemThumbnailService;
3236
}
3337

3438
async getOwn(dbConnection: DBConnection, member: MinimalMember): Promise<PackedBookmarkedItem[]> {
3539
const bookmarks = await this.itemBookmarkRepository.getBookmarksForMember(
3640
dbConnection,
3741
member.id,
3842
);
43+
const bookmarkedItems = bookmarks.map(({ item }) => item);
44+
const thumbnails = await this.itemThumbnailService.getUrlsByItems(bookmarkedItems);
3945

4046
// filter out items user might not have access to
4147
// and packed item
@@ -46,7 +52,8 @@ export class BookmarkService {
4652
itemMembershipRepository: this.itemMembershipRepository,
4753
itemVisibilityRepository: this.itemVisibilityRepository,
4854
},
49-
bookmarks.map(({ item }) => item),
55+
bookmarkedItems,
56+
thumbnails,
5057
);
5158

5259
// insert back packed item inside bookmark entities

0 commit comments

Comments
 (0)