Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / docs-core / lib / AuthenticatedDocController / AuthenticatedDocController.spec.ts
blob6c03fb16c373fb956ba5c5163a1b23a1fc3eced5
1 import type { DocumentMetaInterface, InternalEventBusInterface } from '@proton/docs-shared'
2 import { DocumentRole } from '@proton/docs-shared'
3 import type { DecryptedNode, DriveCompat } from '@proton/drive-store'
4 import type { LoggerInterface } from '@proton/utils/logs'
5 import { Result } from '@proton/docs-shared'
6 import type { DocumentEntitlements } from '../Types/DocumentEntitlements'
7 import type { CreateNewDocument } from '../UseCase/CreateNewDocument'
8 import type { DuplicateDocument } from '../UseCase/DuplicateDocument'
9 import type { SeedInitialCommit } from '../UseCase/SeedInitialCommit'
10 import type { SquashDocument } from '../UseCase/SquashDocument'
11 import { AuthenticatedDocController } from './AuthenticatedDocController'
12 import { DocumentMeta } from '../Models/DocumentMeta'
13 import type { GetNode } from '../UseCase/GetNode'
14 import type { DocumentStateValues } from '../State/DocumentState'
15 import { DocumentState } from '../State/DocumentState'
17 describe('AuthenticatedDocController', () => {
18   let controller: AuthenticatedDocController
19   let driveCompat = {
20     getNode: jest.fn(),
21     trashDocument: jest.fn(),
22     restoreDocument: jest.fn(),
23     getShareId: jest.fn(),
24   }
25   let documentState: DocumentState
27   beforeEach(async () => {
28     documentState = new DocumentState({
29       ...DocumentState.defaults,
30       documentMeta: {
31         latestCommitId: () => '123',
32       } as unknown as DocumentMetaInterface,
33       entitlements: { keys: {}, role: new DocumentRole('Editor') } as unknown as DocumentEntitlements,
34       decryptedNode: {} as DecryptedNode,
35     } as DocumentStateValues)
37     controller = new AuthenticatedDocController(
38       documentState,
39       driveCompat as unknown as jest.Mocked<DriveCompat>,
40       {} as jest.Mocked<SquashDocument>,
41       {} as jest.Mocked<SeedInitialCommit>,
42       {} as jest.Mocked<DuplicateDocument>,
43       {} as jest.Mocked<CreateNewDocument>,
44       {
45         execute: jest.fn().mockReturnValue(Result.ok({})),
46       } as unknown as jest.Mocked<GetNode>,
47       {
48         addEventHandler: jest.fn(),
49         publish: jest.fn(),
50       } as unknown as jest.Mocked<InternalEventBusInterface>,
51       {
52         debug: jest.fn(),
53         info: jest.fn(),
54         warn: jest.fn(),
55         error: console.error,
56       } as unknown as jest.Mocked<LoggerInterface>,
57     )
58   })
60   describe('handleEditorProvidingInitialConversionContent', () => {
61     beforeEach(() => {
62       controller.createInitialCommit = jest.fn().mockReturnValue(Result.ok({ commitId: '123' }))
63     })
65     it('should create initial commit', async () => {
66       await controller.handleEditorProvidingInitialConversionContent(new Uint8Array())
68       expect(controller.createInitialCommit).toHaveBeenCalled()
69     })
70   })
72   describe('trashDocument', () => {
73     beforeEach(() => {
74       documentState.setProperty('documentMeta', new DocumentMeta('volume-id-def', ['ghi'], 123, 456, 'jkl'))
76       documentState.setProperty('decryptedNode', { parentNodeId: '123', trashed: true } as unknown as DecryptedNode)
78       documentState.setProperty('documentTrashState', 'not_trashed')
79     })
81     it('trashState should be trashing initially', () => {
82       const promise = controller.trashDocument()
83       expect(documentState.getProperty('documentTrashState')).toBe('trashing')
84       return promise
85     })
87     it('trashState should be trashed when complete', async () => {
88       await controller.trashDocument()
89       expect(documentState.getProperty('documentTrashState')).toBe('trashed')
90     })
92     it('should refreshNodeAndDocMeta', async () => {
93       const refreshNodeAndDocMeta = jest.spyOn(controller, 'refreshNodeAndDocMeta')
95       await controller.trashDocument()
96       expect(refreshNodeAndDocMeta).toHaveBeenCalled()
97     })
99     it('should set didTrashDocInCurrentSession to true', async () => {
100       expect(controller.didTrashDocInCurrentSession).toBe(false)
102       await controller.trashDocument()
104       expect(controller.didTrashDocInCurrentSession).toBe(true)
105     })
106   })
108   describe('restoreDocument', () => {
109     beforeEach(() => {
110       documentState.setProperty('documentMeta', new DocumentMeta('volume-id-def', ['ghi'], 123, 456, 'jkl'))
112       documentState.setProperty('decryptedNode', { parentNodeId: '123', trashed: true } as unknown as DecryptedNode)
114       documentState.setProperty('documentTrashState', 'trashed')
115     })
117     it('trashState should be restoring initially', () => {
118       const promise = controller.restoreDocument()
119       expect(documentState.getProperty('documentTrashState')).toBe('restoring')
120       return promise
121     })
123     it('trashState should be restored when complete', async () => {
124       controller._getNode.execute = jest
125         .fn()
126         .mockResolvedValue(Result.ok({ node: { parentNodeId: '123', trashed: false } }))
127       await controller.restoreDocument()
128       expect(documentState.getProperty('documentTrashState')).toBe('not_trashed')
129     })
131     it('should refreshNodeAndDocMeta', async () => {
132       const refreshNodeAndDocMeta = jest.spyOn(controller, 'refreshNodeAndDocMeta')
134       await controller.restoreDocument()
135       expect(refreshNodeAndDocMeta).toHaveBeenCalled()
136     })
137   })
139   describe('refreshNodeAndDocMeta', () => {
140     it('trashed state will be not_trashed if DecryptedNode trashed property is null', async () => {
141       documentState.setProperty('documentMeta', new DocumentMeta('volume-id-def', ['ghi'], 123, 456, 'jkl'))
143       controller._getNode.execute = jest
144         .fn()
145         .mockResolvedValueOnce(Result.ok({ node: { parentNodeId: 123, trashed: null } }))
147       await controller.refreshNodeAndDocMeta({ imposeTrashState: undefined })
148       expect(documentState.getProperty('documentTrashState')).toBe('not_trashed')
149     })
151     it('trashed state will be not_trashed if DecryptedNode trashed property is omitted', async () => {
152       documentState.setProperty('documentMeta', new DocumentMeta('volume-id-def', ['ghi'], 123, 456, 'jkl'))
154       controller._getNode.execute = jest.fn().mockResolvedValueOnce(Result.ok({ node: { parentNodeId: 123 } }))
156       await controller.refreshNodeAndDocMeta({ imposeTrashState: undefined })
157       expect(documentState.getProperty('documentTrashState')).toBe('not_trashed')
158     })
160     it('trashed state will be trashed if DecryptedNode trashed property is populated', async () => {
161       documentState.setProperty('documentMeta', new DocumentMeta('volume-id-def', ['ghi'], 123, 456, 'jkl'))
163       controller._getNode.execute = jest
164         .fn()
165         .mockResolvedValueOnce(Result.ok({ node: { parentNodeId: 123, trashed: 123 } }))
167       await controller.refreshNodeAndDocMeta({ imposeTrashState: undefined })
168       expect(documentState.getProperty('documentTrashState')).toBe('trashed')
169     })
170   })