var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
import React from 'react';
import { render, screen, within, fireEvent } from '@testing-library/react';
import { VariableSizeList } from 'react-window';
import * as useScrollToFocusItemImport from './useScrollToFocusItem';
import { flattenGroupedItemsData } from './helpers';
import { VirtualGroupedList } from './VirtualGroupedList';
describe('VirtualGroupedList tests', function () {
    var getItems = function (type) {
        var simpleItems = [
            { item: { label: 'Label 1', id: 'some_id1' } },
            { item: { label: 'Label 2', id: 'some_id2' } },
            { item: { label: 'Label 3', id: 'some_id3' } }
        ];
        var newSimpleItems = [{ item: { label: 'Label 1', id: 'some_id1' } }, { item: { label: 'Label 2', id: 'some_id2' } }];
        var groupedItems = [
            {
                item: { label: 'Label 1', id: 'some_id1' },
                items: [
                    { item: { label: 'Label 1.1', id: 'some_id1.1' } },
                    { item: { label: 'Label 1.2', id: 'some_id1.2' } },
                    { item: { label: 'Label 1.3', id: 'some_id1.3' } }
                ]
            },
            {
                item: { label: 'Label 2', id: 'some_id2' },
                items: [
                    { item: { label: 'Label 2.1', id: 'some_id2.1' } },
                    { item: { label: 'Label 2.2', id: 'some_id2.2' }, moveTo: false }
                ]
            }
        ];
        switch (type) {
            case 'grouped':
                return flattenGroupedItemsData(groupedItems);
            case 'groupedWithMove': {
                groupedItems[1].items[1].moveTo = true;
                return flattenGroupedItemsData(groupedItems);
            }
            case 'newSimpleItems': {
                return flattenGroupedItemsData(newSimpleItems);
            }
            case 'simple':
            default:
                return flattenGroupedItemsData(simpleItems);
        }
    };
    var renderItem = function (style, _a) {
        var item = _a.item;
        return (React.createElement("div", { style: style, "data-reltio-id": "grouped-list-item" }, item.label));
    };
    var defaultProps = {
        getItemSize: function () { return 50; },
        renderItem: renderItem,
        renderGroupTitle: renderItem,
        items: getItems('simple'),
        height: 500
    };
    var setUp = function (props) {
        if (props === void 0) { props = {}; }
        return render(React.createElement(VirtualGroupedList, __assign({}, defaultProps, props)));
    };
    afterEach(function () {
        jest.restoreAllMocks();
    });
    it('should correct render simple items', function () {
        setUp({ items: getItems('simple') });
        expect(screen.getByText('Label 1')).toBeInTheDocument();
        expect(screen.getByText('Label 2')).toBeInTheDocument();
        expect(screen.getByText('Label 3')).toBeInTheDocument();
    });
    it('should correct render grouped items', function () {
        setUp({ items: getItems('grouped') });
        var stickyTitles = screen.getByTestId('grouped-list-sticky-titles');
        expect(stickyTitles.childNodes).toHaveLength(2);
        expect(within(stickyTitles).getByText('Label 1')).toHaveStyle('visibility: visible');
        expect(within(stickyTitles).getByText('Label 2')).toHaveStyle('visibility: hidden');
        var items = screen.getAllByTestId('grouped-list-item');
        expect(items).toHaveLength(9);
        expect(items.map(function (item) { return item.textContent; })).toEqual([
            'Label 1',
            'Label 2',
            'Label 1',
            'Label 1.1',
            'Label 1.2',
            'Label 1.3',
            'Label 2',
            'Label 2.1',
            'Label 2.2'
        ]);
    });
    it('should set sticky titles width if items width changed', function () {
        var _a = setUp({ items: getItems('grouped') }), container = _a.container, rerender = _a.rerender;
        var stickyTitles = screen.getByTestId('grouped-list-sticky-titles');
        Object.defineProperties(container.childNodes[1].firstChild, {
            offsetWidth: {
                get: function () {
                    return 200;
                }
            }
        });
        rerender(React.createElement(VirtualGroupedList, __assign({}, defaultProps, { items: getItems('grouped'), height: 100 })));
        expect(stickyTitles).toHaveStyle('width: 200px');
    });
    it('should not render fixed group title when fixedTitle is false', function () {
        setUp({ items: getItems('grouped'), fixedTitle: false });
        var stickyTitles = screen.getByTestId('grouped-list-sticky-titles');
        expect(stickyTitles.childNodes).toHaveLength(0);
    });
    it('should clear index when items is updated', function () {
        var useScrollToFocusItemSpy = jest.spyOn(useScrollToFocusItemImport, 'useScrollToFocusItem');
        var rerender = setUp({ items: getItems('simple') }).rerender;
        var listRef = useScrollToFocusItemSpy.mock.calls[0][0].listRef;
        var resetAfterIndexSpy = jest.spyOn(listRef.current, 'resetAfterIndex');
        rerender(React.createElement(VirtualGroupedList, __assign({}, defaultProps, { items: getItems('simple') })));
        expect(resetAfterIndexSpy).toHaveBeenCalledWith(0);
    });
    describe('Scroll behavior', function () {
        var setHeightForNode = function (node, height, scrollHeight) {
            Object.defineProperties(node, {
                clientHeight: {
                    get: function () { return height; },
                    configurable: true
                },
                scrollHeight: {
                    get: function () { return scrollHeight; },
                    configurable: true
                }
            });
        };
        /*
            Some scroll offsets for grouped items(getItems('grouped')):
            First title offset: 0
            First title will be showing in offset range: 0-199
            Second title offset: 200
            Second title will be showing in offset range: 200+
            Offset range when titles is touching each other: 150-200
        */
        it('should scroll to moveTo item', function () {
            var requestAnimationFrameMock = jest
                .spyOn(window, 'requestAnimationFrame')
                .mockImplementation(function (callback) {
                callback(0);
                return 0;
            });
            var scrollToSpy = jest.spyOn(VariableSizeList.prototype, 'scrollTo').mockImplementation(function () { return null; });
            var rerender = setUp({ items: getItems('grouped'), height: 150 }).rerender;
            rerender(React.createElement(VirtualGroupedList, __assign({}, defaultProps, { items: getItems('groupedWithMove'), height: 150 })));
            expect(scrollToSpy).toHaveBeenCalledTimes(2);
            expect(scrollToSpy).toHaveBeenCalledWith(200);
            requestAnimationFrameMock.mockRestore();
        });
        it('should scroll to top of item', function () {
            var scrollToSpy = jest.spyOn(VariableSizeList.prototype, 'scrollTo').mockImplementation(function () { return null; });
            var rerender = setUp({ items: getItems('grouped'), height: 150 }).rerender;
            var requestAnimationFrameMock = jest
                .spyOn(window, 'requestAnimationFrame')
                .mockImplementation(function (callback) {
                callback(0);
                return 0;
            });
            rerender(React.createElement(VirtualGroupedList, __assign({}, defaultProps, { items: getItems('newSimpleItems'), height: 150 })));
            expect(scrollToSpy).toHaveBeenCalledTimes(1);
            expect(scrollToSpy).toHaveBeenCalledWith(0);
            requestAnimationFrameMock.mockRestore();
        });
        it('should change fixed title on forward scroll', function () {
            var container = setUp({ items: getItems('grouped'), height: 150 }).container;
            var titlesContainer = screen.getByTestId('grouped-list-sticky-titles');
            var titles = within(titlesContainer).getAllByTestId('grouped-list-item');
            setHeightForNode(container.childNodes[1], 150, 400);
            fireEvent.scroll(container.childNodes[1], { target: { scrollTop: 210 } });
            expect(titles).toHaveLength(2);
            expect(titlesContainer).toHaveStyle('top: 0px');
            expect(titles[0]).toHaveStyle('visibility: hidden');
            expect(titles[1]).toHaveStyle('visibility: visible');
        });
        it('should move current fixed title on forward scroll when next title start touching the current title', function () {
            var container = setUp({ items: getItems('grouped'), height: 150 }).container;
            var titlesContainer = screen.getByTestId('grouped-list-sticky-titles');
            var titles = within(titlesContainer).getAllByTestId('grouped-list-item');
            setHeightForNode(container.childNodes[1], 150, 400);
            fireEvent.scroll(container.childNodes[1], { target: { scrollTop: 151 } });
            expect(titles).toHaveLength(2);
            expect(titlesContainer).toHaveStyle('top: -1px');
            expect(titles[0]).toHaveStyle('visibility: visible');
            expect(titles[1]).toHaveStyle('visibility: hidden');
        });
        it('should change fixed title on backward scroll', function () {
            var container = setUp({ items: getItems('grouped'), height: 150 }).container;
            var titlesContainer = screen.getByTestId('grouped-list-sticky-titles');
            var titles = within(titlesContainer).getAllByTestId('grouped-list-item');
            setHeightForNode(container.childNodes[1], 150, 400);
            fireEvent.scroll(container.childNodes[1], { target: { scrollTop: 210 } });
            fireEvent.scroll(container.childNodes[1], { target: { scrollTop: 140 } });
            expect(titles).toHaveLength(2);
            expect(titlesContainer).toHaveStyle('top: 0px');
            expect(titles[0]).toHaveStyle('visibility: visible');
            expect(titles[1]).toHaveStyle('visibility: hidden');
        });
        it('should move current fixed title on backward scroll when previous title start touching the current title', function () {
            var container = setUp({ items: getItems('grouped'), height: 150 }).container;
            var titlesContainer = screen.getByTestId('grouped-list-sticky-titles');
            var titles = within(titlesContainer).getAllByTestId('grouped-list-item');
            setHeightForNode(container.childNodes[1], 150, 400);
            fireEvent.scroll(container.childNodes[1], { target: { scrollTop: 210 } });
            fireEvent.scroll(container.childNodes[1], { target: { scrollTop: 199 } });
            expect(titles).toHaveLength(2);
            expect(titlesContainer).toHaveStyle('top: -49px');
            expect(titles[0]).toHaveStyle('visibility: visible');
            expect(titles[1]).toHaveStyle('visibility: hidden');
        });
    });
});
