// envía -> error, segundo envío -> error, reenvía dos en el primer intervalo
// fallan todos los reenvíos y se descartan

import CfNetworkQueue from "./CfNetworkQueue"

describe('Network queue', () => {
    afterEach(() => {
        jest.clearAllMocks();
    });

    it('Should send an event without error',  () => {
        const mockBsNetwork = {
            send: jest.fn(() => new Promise(r => r([]))),
            get: jest.fn()
        }

        const notificationSpy = jest.spyOn(mockBsNetwork, 'send')

        const networkQueue = new CfNetworkQueue(
            mockBsNetwork,
        )

        networkQueue.send('url', { value: 111})

        expect(notificationSpy).toBeCalled()
    })


    it('Should send an event after a network error', async () => {
        const mockBsNetwork = {
            send: jest.fn()
                .mockRejectedValueOnce(new Error('Async error'))
                .mockResolvedValueOnce('first call')
                .mockResolvedValueOnce('first call'),
            get: jest.fn()
        }

        const notificationSpy = jest.spyOn(mockBsNetwork, 'send')

        const networkQueue = new CfNetworkQueue(
            mockBsNetwork,
            {
                flushInterval: 100
            }
        )

        networkQueue.send('url1', { value: 111 })

        await new Promise((r) => setTimeout(r, 300));

        expect(notificationSpy).toBeCalledTimes(2)
    })

    it('Should send several events with a network error in the first one', async () => {
        const mockBsNetwork = {
            send: jest.fn()
                .mockRejectedValueOnce(new Error('Async error'))
                .mockResolvedValue('first call'),
            get: jest.fn()
        }

        const notificationSpy = jest.spyOn(mockBsNetwork, 'send')

        const networkQueue = new CfNetworkQueue(
            mockBsNetwork,
            {
                flushInterval: 100
            }
        )

        networkQueue.send('url1', { value: 111 })
        networkQueue.send('url1', { value: 222 })

        await new Promise((r) => setTimeout(r, 300));

        expect(notificationSpy).toBeCalledTimes(3)
        expect(notificationSpy).lastCalledWith('url1', { value: 111 })
    })

    it('Should discard events after reaching the maximum number or retries', async () => {
        const mockBsNetwork = {
            send: jest.fn()
                .mockRejectedValue(new Error('Async error')),
            get: jest.fn()
        }

        const notificationSpy = jest.spyOn(mockBsNetwork, 'send')

        const networkQueue = new CfNetworkQueue(
            mockBsNetwork,
            {
                flushInterval: 100,
                maxRetries: 1
            }
        )

        networkQueue.send('url1', { value: 111 })

        await new Promise((r) => setTimeout(r, 300));

        expect(notificationSpy).toBeCalledTimes(3)
    })


})
