1 import type { LoggerInterface } from '@proton/utils/logs'
2 import { AckLedger } from './AckLedger'
3 import type { ClientMessageWithDocumentUpdates, ServerMessageWithMessageAcks } from '@proton/docs-proto'
4 import metrics from '@proton/metrics'
6 const mockMetric = jest.mocked(metrics.docs_document_updates_ack_error_total.increment)
8 describe('AckLedger', () => {
11 const createService = (callback: () => void) =>
15 } as unknown as LoggerInterface,
20 ledger = createService(() => {})
25 mockMetric.mockClear()
28 describe('messagePosted', () => {
29 it('should add to unconfirmed messages', () => {
32 documentUpdates: [{ uuid: '1' }, { uuid: '2' }],
34 } as ClientMessageWithDocumentUpdates
36 ledger.messagePosted(message)
38 expect(ledger.unconfirmedMessages.size).toBe(2)
42 describe('getUnacknowledgedUpdates', () => {
43 it('should return unconfirmed messages', () => {
46 documentUpdates: [{ uuid: '1' }, { uuid: '2' }],
48 } as ClientMessageWithDocumentUpdates
50 ledger.messagePosted(message)
52 expect(ledger.getUnacknowledgedUpdates().length).toBe(2)
56 describe('messageAcknowledgementReceived', () => {
57 it('should remove from unconfirmed messages', () => {
60 documentUpdates: [{ uuid: '1' }, { uuid: '2' }],
62 } as ClientMessageWithDocumentUpdates
64 ledger.messagePosted(message)
67 acks: [{ uuid: '1' }],
68 } as ServerMessageWithMessageAcks
69 ledger.messageAcknowledgementReceived(ackMessage)
71 expect(ledger.unconfirmedMessages.size).toBe(1)
74 it('should remove from concerning messages', () => {
77 documentUpdates: [{ uuid: '1' }, { uuid: '2' }],
79 } as ClientMessageWithDocumentUpdates
81 ledger.messagePosted(message)
82 ledger.concerningMessages.add('1')
85 acks: [{ uuid: '1' }],
86 } as ServerMessageWithMessageAcks
87 ledger.messageAcknowledgementReceived(ackMessage)
89 expect(ledger.concerningMessages.size).toBe(0)
92 it('should remove from errored messages', () => {
95 documentUpdates: [{ uuid: '1' }, { uuid: '2' }],
97 } as ClientMessageWithDocumentUpdates
99 ledger.messagePosted(message)
100 ledger.erroredMessages.add('1')
103 acks: [{ uuid: '1' }],
104 } as ServerMessageWithMessageAcks
105 ledger.messageAcknowledgementReceived(ackMessage)
107 expect(ledger.erroredMessages.size).toBe(0)
111 describe('checkForUnackedMessages', () => {
112 it('should add to concerning messages if concern threshold is passed', () => {
117 documentUpdates: [{ uuid: '1' }],
119 } as ClientMessageWithDocumentUpdates
121 ledger.messagePosted(message)
123 ledger.thresholdForConcern = () => 10
125 jest.advanceTimersByTime(11)
127 ledger.checkForUnackedMessages()
129 expect(ledger.concerningMessages.size).toBe(1)
130 expect(mockMetric).toHaveBeenCalledTimes(1)
131 expect(mockMetric).toHaveBeenCalledWith(
133 type: 'concern_threshold',
139 it('should add to erorred messages if error threshold is passed', () => {
144 documentUpdates: [{ uuid: '1' }],
146 } as ClientMessageWithDocumentUpdates
148 ledger.messagePosted(message)
150 ledger.thresholdForError = () => 10
152 jest.advanceTimersByTime(11)
154 ledger.checkForUnackedMessages()
156 expect(ledger.erroredMessages.size).toBe(1)
157 expect(ledger.concerningMessages.size).toBe(0)
158 expect(mockMetric).toHaveBeenCalledTimes(1)
159 expect(mockMetric).toHaveBeenCalledWith(
161 type: 'error_threshold',
167 it('should notify of status change if messages are added', () => {
170 const mock = (ledger.notifyOfStatusChange = jest.fn())
174 documentUpdates: [{ uuid: '1' }],
176 } as ClientMessageWithDocumentUpdates
178 ledger.messagePosted(message)
180 ledger.thresholdForConcern = () => 10
182 jest.advanceTimersByTime(11)
184 ledger.checkForUnackedMessages()
186 expect(mock).toHaveBeenCalled()