import { newSpecPage } from "@stencil/core/testing";
import { BpSdkQuestionSetNavigation } from "./bp-sdk-question-set-navigation";
describe('bp-sdk-question-set-navigation', () => {
    describe('rendering', () => {
        it('empty', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            await page.waitForChanges();
            expect(page.root.querySelector('ul').className).toEqual('bp-sdk-question-set-navigation__list');
        });
        it('renders active question sets', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            instance.questionSets = [
                {
                    question_set_id: '1',
                    is_active: true,
                    is_completed: true,
                    question_set: {
                        name: 'Bill',
                    },
                    answers: [{}],
                },
                {
                    question_set_id: '2',
                    is_active: true,
                    is_completed: false,
                    question_set: {
                        name: 'Ted',
                    },
                    answers: [{}],
                },
            ];
            instance.activeId = '1';
            await page.waitForChanges();
            expect(page.root.querySelector('ul').className).toEqual('bp-sdk-question-set-navigation__list');
            expect(page.root.querySelectorAll('.bp-sdk-question-set-navigation__list-item').length).toEqual(2);
            expect(page.root.querySelectorAll('.bp-sdk-question-set-navigation__list-item--completed').length).toEqual(1);
            const activeElement = page.root.querySelector('.bp-sdk-question-set-navigation__list-item--active');
            expect(activeElement.textContent).toEqual('Bill');
        });
        it('can render external', async () => {
            const whenDefinedMock = jest.spyOn(customElements, 'whenDefined').mockResolvedValueOnce({});
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            page.waitForChanges();
            expect(page.root.querySelector('ul')).toBeFalsy();
            whenDefinedMock.mockRestore();
        });
    });
    describe('updateQuestionSetId', () => {
        it('should make expected calls', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            const id = 'some id';
            jest.spyOn(instance.activeIdUpdate, 'emit').mockImplementation(() => ({}));
            const curriedFunction = instance.updateQuestionSetId(id);
            curriedFunction();
            expect(instance.activeId).toEqual(id);
            expect(instance.activeIdUpdate.emit).toHaveBeenCalledWith(id);
            expect(instance.activeIdUpdate.emit).toHaveBeenCalledTimes(1);
        });
        it('should not make calls when navigation is disabled', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            const id = 'new id';
            instance.isNavigationEnabled = false;
            jest.spyOn(instance.activeIdUpdate, 'emit').mockImplementation(() => ({}));
            instance.updateQuestionSetId(id)();
            expect(instance.activeIdUpdate.emit).not.toHaveBeenCalled();
        });
    });
    describe('onKeyUp', () => {
        it('prevent default on ArrowUp', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            const event = new KeyboardEvent('keyUp', {
                key: 'ArrowUp',
            });
            jest.spyOn(event, 'preventDefault').mockImplementation(() => { });
            instance.onKeyDown(event);
            expect(event.preventDefault).toHaveBeenCalledTimes(1);
        });
        it('prevent default on ArrowDown', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            const event = new KeyboardEvent('keyDown', {
                key: 'ArrowDown',
            });
            jest.spyOn(event, 'preventDefault').mockImplementation(() => { });
            instance.onKeyDown(event);
            expect(event.preventDefault).toHaveBeenCalledTimes(1);
        });
        it('nothing otherwise', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            const event = new KeyboardEvent('keyDown', {
                key: 'some key',
            });
            jest.spyOn(event, 'preventDefault').mockImplementation(() => { });
            instance.onKeyDown(event);
            expect(event.preventDefault).toHaveBeenCalledTimes(0);
        });
    });
    describe('onKeyUp', () => {
        it('should be able navigate up', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            instance.questionSets = [
                {
                    question_set_id: '1',
                    question_set: {
                        name: 'Bill',
                    },
                },
                {
                    question_set_id: '2',
                    question_set: {
                        name: 'Ted',
                    },
                },
                {
                    question_set_id: '3',
                    question_set: {
                        name: 'Adventure',
                    },
                },
            ];
            const focus = {
                parentElement: {
                    getAttribute: jest.fn(() => 2),
                },
            };
            const button = {
                focus: jest.fn(),
            };
            jest.spyOn(instance.el, 'querySelector').mockImplementation((query) => (query === ':focus' ? focus : button));
            const up = new KeyboardEvent('keyUp', {
                key: 'ArrowUp',
            });
            instance.onKeyUp(up);
            expect(button.focus).toHaveBeenCalledTimes(1);
        });
        it('should be able navigate up with fallback', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            instance.questionSets = [
                {
                    question_set_id: '1',
                    question_set: {
                        name: 'Bill',
                    },
                },
                {
                    question_set_id: '2',
                    question_set: {
                        name: 'Ted',
                    },
                },
                {
                    question_set_id: '3',
                    question_set: {
                        name: 'Adventure',
                    },
                },
            ];
            const focus = {
                parentElement: {
                    getAttribute: jest.fn(),
                },
            };
            const button = {
                focus: jest.fn(),
            };
            jest.spyOn(instance.el, 'querySelector').mockImplementation((query) => (query === ':focus' ? focus : button));
            const up = new KeyboardEvent('keyUp', {
                key: 'ArrowUp',
            });
            instance.onKeyUp(up);
            expect(button.focus).toHaveBeenCalledTimes(1);
        });
        it('should be able navigate down', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            instance.questionSets = [
                {
                    question_set_id: '1',
                    question_set: {
                        name: 'Bill',
                    },
                },
                {
                    question_set_id: '2',
                    question_set: {
                        name: 'Ted',
                    },
                },
                {
                    question_set_id: '3',
                    question_set: {
                        name: 'Adventure',
                    },
                },
            ];
            const focus = {
                parentElement: {
                    getAttribute: jest.fn(),
                },
            };
            const button = {
                focus: jest.fn(),
            };
            jest.spyOn(instance.el, 'querySelector').mockImplementation((query) => (query === ':focus' ? focus : button));
            const down = new KeyboardEvent('keyUp', {
                key: 'ArrowDown',
            });
            instance.onKeyUp(down);
            expect(button.focus).toHaveBeenCalledTimes(1);
        });
        it('should be able navigate down with fallback', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            instance.questionSets = [
                {
                    question_set_id: '1',
                    question_set: {
                        name: 'Bill',
                    },
                },
                {
                    question_set_id: '2',
                    question_set: {
                        name: 'Ted',
                    },
                },
                {
                    question_set_id: '3',
                    question_set: {
                        name: 'Adventure',
                    },
                },
            ];
            const focus = {
                parentElement: {
                    getAttribute: jest.fn(() => 3),
                },
            };
            const button = {
                focus: jest.fn(),
            };
            jest.spyOn(instance.el, 'querySelector').mockImplementation((query) => (query === ':focus' ? focus : button));
            const down = new KeyboardEvent('keyUp', {
                key: 'ArrowDown',
            });
            instance.onKeyUp(down);
            expect(button.focus).toHaveBeenCalledTimes(1);
        });
        it('fail gracefully', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            instance.questionSets = [
                {
                    question_set_id: '1',
                    question_set: {
                        name: 'Bill',
                    },
                },
                {
                    question_set_id: '2',
                    question_set: {
                        name: 'Ted',
                    },
                },
                {
                    question_set_id: '3',
                    question_set: {
                        name: 'Adventure',
                    },
                },
            ];
            const focus = {
                parentElement: {
                    getAttribute: jest.fn(() => 3),
                },
            };
            const button = {
                focus: jest.fn(),
            };
            jest.spyOn(instance, 'getPosition').mockReturnValue(undefined);
            jest.spyOn(instance.el, 'querySelector').mockImplementation((query) => (query === ':focus' ? focus : button));
            const down = new KeyboardEvent('keyUp', {
                key: 'ArrowDown',
            });
            instance.onKeyUp(down);
            expect(button.focus).toHaveBeenCalledTimes(0);
        });
        it('ignore other keys', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            instance.questionSets = [
                {
                    question_set_id: '1',
                    question_set: {
                        name: 'Bill',
                    },
                },
                {
                    question_set_id: '2',
                    question_set: {
                        name: 'Ted',
                    },
                },
                {
                    question_set_id: '3',
                    question_set: {
                        name: 'Adventure',
                    },
                },
            ];
            const focus = {
                parentElement: {
                    getAttribute: jest.fn(() => 3),
                },
            };
            const button = {
                focus: jest.fn(),
            };
            jest.spyOn(instance.el, 'querySelector').mockImplementation((query) => (query === ':focus' ? focus : button));
            const down = new KeyboardEvent('keyUp', {
                key: 'some key',
            });
            instance.onKeyUp(down);
            expect(button.focus).toHaveBeenCalledTimes(0);
        });
    });
    describe('getPosition', () => {
        it('should return expected results', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-question-set-navigation></bp-sdk-question-set-navigation>',
                components: [BpSdkQuestionSetNavigation],
            });
            const instance = page.rootInstance;
            instance.questionSets = [1, 2, 3];
            expect(instance.getPosition(-1, 'ArrowUp')).toEqual(3);
            expect(instance.getPosition(0, 'ArrowUp')).toEqual(3);
            expect(instance.getPosition(1, 'ArrowUp')).toEqual(3);
            expect(instance.getPosition(2, 'ArrowUp')).toEqual(1);
            expect(instance.getPosition(3, 'ArrowUp')).toEqual(2);
            expect(instance.getPosition(4, 'ArrowUp')).toEqual(3);
            expect(instance.getPosition(-1, 'ArrowDown')).toEqual(1);
            expect(instance.getPosition(0, 'ArrowDown')).toEqual(1);
            expect(instance.getPosition(1, 'ArrowDown')).toEqual(2);
            expect(instance.getPosition(2, 'ArrowDown')).toEqual(3);
            expect(instance.getPosition(3, 'ArrowDown')).toEqual(1);
            expect(instance.getPosition(4, 'ArrowDown')).toEqual(1);
            expect(instance.getPosition(2, 'some key')).toBeUndefined();
        });
    });
});
