1 import { Result } from '../Domain/Result/Result'
2 import type { DocumentKeys, NodeMeta } from '@proton/drive-store'
3 import { Comment } from '../Models'
4 import { GenerateUUID } from '../Util/GenerateUuid'
5 import type { EncryptComment } from './EncryptComment'
6 import type { LocalCommentsState } from '../Services/Comments/LocalCommentsState'
7 import { CreateComment } from './CreateComment'
8 import type { DocsApi } from '../Api/DocsApi'
10 jest.mock('../Util/GenerateUuid', () => ({
11 GenerateUUID: jest.fn(),
14 const mockEncryptComment = {
16 } as unknown as jest.Mocked<EncryptComment>
18 const mockCommentsApi = {
19 addCommentToThread: jest.fn(),
20 } as unknown as jest.Mocked<DocsApi>
22 const mockCommentsState = {
23 findThreadById: jest.fn(),
24 addComment: jest.fn(),
25 deleteComment: jest.fn(),
26 replacePlaceholderComment: jest.fn(),
27 } as unknown as jest.Mocked<LocalCommentsState>
29 describe('CreateComment', () => {
30 let createComment: CreateComment
34 threadID: 'thread-id',
35 lookup: { volumeId: 'volume-id', linkId: 'link-id' } as NodeMeta,
36 userDisplayName: 'User',
38 userOwnAddress: 'foo@bar.com',
40 commentsState: mockCommentsState,
44 createComment = new CreateComment(
45 mockCommentsApi as unknown as DocsApi,
46 mockEncryptComment as unknown as EncryptComment,
48 ;(GenerateUUID as jest.Mock).mockReturnValue('uuid')
51 it('should call encryptComment, api.addCommentToThread, and decryptComment in order', async () => {
52 mockCommentsState.findThreadById.mockReturnValue({ markID: 'mark-id' } as never)
53 mockEncryptComment.execute.mockResolvedValue(Result.ok('encrypted-comment'))
54 mockCommentsApi.addCommentToThread.mockResolvedValue(
55 Result.ok({ Comment: { text: 'encrypted-response-comment', AuthorEmail: 'foo@bar.com' } as never, Code: 1000 }),
58 await createComment.execute(dto)
60 expect(mockCommentsState.findThreadById).toHaveBeenCalledWith('thread-id')
61 expect(mockCommentsState.addComment).toHaveBeenCalledWith(expect.any(Comment), 'thread-id')
62 expect(mockEncryptComment.execute).toHaveBeenCalledWith('Test comment', 'mark-id', {
63 userOwnAddress: 'foo@bar.com',
65 expect(mockCommentsApi.addCommentToThread).toHaveBeenCalledWith({
66 volumeId: 'volume-id',
68 threadId: 'thread-id',
69 encryptedContent: 'encrypted-comment',
70 parentCommentId: null,
71 authorEmail: 'foo@bar.com',
73 expect(mockCommentsState.replacePlaceholderComment).toHaveBeenCalled()
76 it('should delete comment if encryption fails', async () => {
77 mockCommentsState.findThreadById.mockReturnValue({ markID: 'mark-id' } as never)
78 mockEncryptComment.execute.mockResolvedValue(Result.fail('encryption error'))
80 const result = await createComment.execute(dto)
82 expect(result.isFailed()).toBe(true)
83 expect(mockCommentsState.deleteComment).toHaveBeenCalledWith({ commentID: 'uuid', threadID: 'thread-id' })
86 it('should delete comment if api call fails', async () => {
87 mockCommentsState.findThreadById.mockReturnValue({ markID: 'mark-id' } as never)
88 mockEncryptComment.execute.mockResolvedValue(Result.ok('encrypted-comment'))
89 mockCommentsApi.addCommentToThread.mockResolvedValue(Result.fail('api error'))
91 const result = await createComment.execute(dto)
93 expect(result.isFailed()).toBe(true)
94 expect(mockCommentsState.deleteComment).toHaveBeenCalledWith({ commentID: 'uuid', threadID: 'thread-id' })