import React, { RefObject } from 'react';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import { MAIN_CONTENT_CLASSNAME } from 'src/constants';
import StickyHeader, { CLASSNAME, CLASSNAME_ACTIVE } from '../stickyHeader';

describe('<StickyHeader>', () => {
    const CONTENT = 'content';

    const renderComponent = (top: number) => {
        const target = {
            current: {
                getBoundingClientRect: () => ({ top }),
            },
        } as RefObject<HTMLElement>;

        return renderInAppContext(
            <div className={MAIN_CONTENT_CLASSNAME}>
                <StickyHeader target={target}>
                    <div>{CONTENT}</div>
                </StickyHeader>
            </div>
        );
    };

    const parentHasClass = (element: HTMLElement, className: string) =>
        !!element?.parentElement?.parentElement?.classList.contains(className);

    describe('beneath scroll threshold', () => {
        test('does not set the active class', async () => {
            const { container } = renderComponent(100);

            const elem = container
                .getElementsByClassName(MAIN_CONTENT_CLASSNAME)
                .item(0);
            if (!elem) throw new Error('Element not found');

            fireEvent.scroll(elem);
            const content = await screen.findByText(CONTENT);

            expect(parentHasClass(content, CLASSNAME)).toBe(true);
            expect(parentHasClass(content, CLASSNAME_ACTIVE)).toBe(false);
        });
    });

    describe('above scroll threshold', () => {
        test('sets the active class', async () => {
            const { container } = renderComponent(-100);

            const elem = container
                .getElementsByClassName(MAIN_CONTENT_CLASSNAME)
                .item(0);
            if (!elem) throw new Error('Element not found');

            fireEvent.scroll(elem);
            const content = await screen.findByText(CONTENT);

            expect(parentHasClass(content, CLASSNAME)).toBe(true);
            await waitFor(() => {
                expect(parentHasClass(content, CLASSNAME_ACTIVE)).toBe(true);
            });
        });
    });
});
