import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
import { createWrapper, axios } from 'app/test/vitest/helper';
import VnPaginate from 'src/components/ui/VnPaginate.vue';

describe('VnPaginate', () => {
    const expectedUrl = '/api/customers';

    let vm;
    beforeAll(() => {
        const options = {
            attrs: {
                url: expectedUrl,
                dataKey: 'CustomerList',
                order: 'id DESC',
                limit: 3,
            },
        };
        vm = createWrapper(VnPaginate, options).vm;
    });

    afterEach(() => {
        vm.store.data = [];
        vm.store.skip = 0;
        vm.pagination.page = 1;
        vm.hasMoreData = true;
    });

    describe('paginate()', () => {
        it('should call to the paginate() method and set the data on the rows property', async () => {
            vi.spyOn(vm.arrayData, 'loadMore');
            vm.store.data = [
                { id: 1, name: 'Tony Stark' },
                { id: 2, name: 'Jessica Jones' },
                { id: 3, name: 'Bruce Wayne' },
            ];

            await vm.paginate();

            expect(vm.arrayData.loadMore).toHaveBeenCalledWith();
            expect(vm.store.data.length).toEqual(3);
        });

        it('should call to the paginate() method and then call it again to paginate', async () => {
            vi.spyOn(axios, 'get').mockResolvedValue({
                data: [
                    { id: 1, name: 'Tony Stark' },
                    { id: 2, name: 'Jessica Jones' },
                    { id: 3, name: 'Bruce Wayne' },
                ],
            });
            vm.store.hasMoreData = true;
            await vm.$nextTick();

            vm.store.data = [
                { id: 1, name: 'Tony Stark' },
                { id: 2, name: 'Jessica Jones' },
                { id: 3, name: 'Bruce Wayne' },
            ];

            await vm.paginate();

            expect(vm.store.skip).toEqual(3);
            expect(vm.store.data.length).toEqual(6);

            await vm.paginate();

            expect(vm.store.skip).toEqual(6);
            expect(vm.store.data.length).toEqual(9);
        });
    });

    describe('onLoad()', () => {
        it('should call to the done() callback and not increment the pagination', async () => {
            const index = 1;
            const done = vi.fn();

            await vm.onLoad(index, done);

            expect(vm.pagination.page).toEqual(1);
            expect(done).toHaveBeenCalledWith(false);
        });

        it('should increment the pagination and then call to the done() callback', async () => {
            expect(vm.pagination.page).toEqual(1);

            const index = 1;
            const done = vi.fn();
            vm.store.data = [
                { id: 1, name: 'Tony Stark' },
                { id: 2, name: 'Jessica Jones' },
                { id: 3, name: 'Bruce Wayne' },
            ];

            await vm.onLoad(index, done);

            expect(vm.pagination.page).toEqual(2);
            expect(done).toHaveBeenCalledWith(false);
        });

        it('should call to the done() callback with true as argument to finish pagination', async () => {
            vi.spyOn(axios, 'get').mockResolvedValue({
                data: [
                    { id: 1, name: 'Tony Stark' },
                    { id: 2, name: 'Jessica Jones' },
                ],
            });

            vm.store.data = [
                { id: 1, name: 'Tony Stark' },
                { id: 2, name: 'Jessica Jones' },
                { id: 3, name: 'Bruce Wayne' },
            ];

            expect(vm.pagination.page).toEqual(1);

            const index = 1;
            const done = vi.fn();

            vm.hasMoreData = false;

            await vm.onLoad(index, done);

            expect(vm.pagination.page).toEqual(2);
            expect(done).toHaveBeenCalledWith(false);
        });
    });
});
