import { newSpecPage } from "@stencil/core/testing";
import { BpSdkAutocompleteInput } from "./bp-sdk-autocomplete-input";
describe('bp-sdk-autocomplete-input', () => {
    it('renders external component if defined', async () => {
        const whenDefinedMock = jest.spyOn(customElements, 'whenDefined').mockResolvedValueOnce({});
        const page = await newSpecPage({
            html: '<bp-sdk-autocomplete-input></bp-sdk-autocomplete-input>',
            components: [BpSdkAutocompleteInput],
        });
        await page.waitForChanges();
        const element = page.root.querySelector('div');
        expect(element).toBeFalsy();
        whenDefinedMock.mockRestore();
    });
    it('should have an input', async () => {
        const page = await newSpecPage({
            html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
            components: [BpSdkAutocompleteInput],
        });
        const instance = page.rootInstance;
        instance.questionId = '1';
        instance.placeholder = 'auto';
        instance.labelledBy = 'label';
        instance.labelId = 'aria';
        await page.waitForChanges();
        const input = page.body.querySelector('.bp-sdk-autocomplete__input');
        expect(input.placeholder).toEqual('auto');
        expect(input.getAttribute('aria-labelledby')).toEqual('label aria');
    });
    it('should display options', async () => {
        const page = await newSpecPage({
            html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
            components: [BpSdkAutocompleteInput],
        });
        page.rootInstance.questionId = '1';
        page.rootInstance._showChoices = true;
        page.rootInstance._choices = [
            { id: '1', value: '1' },
            { id: '2', value: '2' },
        ];
        await page.waitForChanges();
        const nodes = page.body.querySelectorAll('.bp-sdk-autocomplete__list-item');
        expect(nodes[0].textContent).toEqual('1');
        expect(nodes[1].textContent).toEqual('2');
    });
    it('can disable display of options', async () => {
        const page = await newSpecPage({
            html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
            components: [BpSdkAutocompleteInput],
        });
        page.rootInstance.questionId = '1';
        page.rootInstance._showChoices = true;
        page.rootInstance._choices = [
            { id: '1', value: '1' },
            { id: '2', value: '2' },
        ];
        page.rootInstance.disableDropdown = true;
        await page.waitForChanges();
        const nodes = page.body.querySelectorAll('.bp-sdk-autocomplete__list-item');
        expect(nodes.length).toEqual(0);
    });
    it('should handle null options', async () => {
        const page = await newSpecPage({
            html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
            components: [BpSdkAutocompleteInput],
        });
        page.rootInstance.questionId = '1';
        page.rootInstance._showChoices = true;
        page.rootInstance._choices = null;
        await page.waitForChanges();
        const nodes = page.body.querySelectorAll('.bp-sdk-autocomplete__list-item');
        expect(nodes.length).toEqual(0);
    });
    it('should be able to display no choices fallback', async () => {
        const page = await newSpecPage({
            html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
            components: [BpSdkAutocompleteInput],
        });
        page.rootInstance.questionId = '1';
        page.rootInstance._showChoices = true;
        page.rootInstance._choices = [];
        page.rootInstance.showNoChoicesFallback = true;
        await page.waitForChanges();
        const nodes = page.body.querySelectorAll('.bp-sdk-autocomplete__list-item');
        expect(nodes.length).toEqual(0);
        expect(page.body.querySelector('.bp-sdk-no-results')).toBeTruthy();
    });
    it('should be able to hide no choices fallback', async () => {
        const page = await newSpecPage({
            html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
            components: [BpSdkAutocompleteInput],
        });
        page.rootInstance.questionId = '1';
        page.rootInstance._showChoices = true;
        page.rootInstance._choices = [];
        page.rootInstance.showNoChoicesFallback = false;
        await page.waitForChanges();
        const nodes = page.body.querySelectorAll('.bp-sdk-autocomplete__list-item');
        expect(nodes.length).toEqual(0);
        expect(page.body.querySelector('.bp-sdk-no-results')).toBeFalsy();
    });
    it('should display errors', async () => {
        const page = await newSpecPage({
            html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
            components: [BpSdkAutocompleteInput],
        });
        const instance = page.rootInstance;
        instance.questionId = '1';
        instance.showChoices = true;
        instance.choices = [
            { id: '1', value: '1' },
            { id: '2', value: '2' },
        ];
        instance.errors = ['some errors'];
        instance.touched = true;
        instance.pristine = false;
        await page.waitForChanges();
        expect(page.body.querySelectorAll('bp-sdk-errors-container').length).toBe(1);
    });
    it('should display error text', async () => {
        const page = await newSpecPage({
            html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
            components: [BpSdkAutocompleteInput],
        });
        const instance = page.rootInstance;
        instance.questionId = '1';
        instance.showChoices = true;
        instance.choices = [
            { id: '1', value: '1' },
            { id: '2', value: '2' },
        ];
        instance.errorText = 'some errors';
        instance.touched = true;
        instance.pristine = false;
        await page.waitForChanges();
        expect(page.body.querySelectorAll('bp-sdk-errors-container').length).toBe(1);
    });
    it('should handle null errors', async () => {
        const page = await newSpecPage({
            html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
            components: [BpSdkAutocompleteInput],
        });
        const instance = page.rootInstance;
        instance.questionId = '1';
        instance.showChoices = true;
        instance.choices = [
            { id: '1', value: '1' },
            { id: '2', value: '2' },
        ];
        instance.errors = null;
        instance.touched = true;
        instance.pristine = false;
        await page.waitForChanges();
        expect(page.body.querySelectorAll('bp-sdk-errors-container').length).toBe(0);
    });
    describe('when the component is marked as read only', () => {
        const value = 'llama';
        let page;
        let instance;
        beforeEach(async () => {
            page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            instance = page.rootInstance;
            instance.isReadOnly = true;
            instance.text = value;
            await page.waitForChanges();
        });
        it('should render a read only value', () => {
            const element = page.body.querySelector('.read-only-value');
            expect(element.textContent).toEqual(value);
        });
        it('should not render an input', () => {
            expect(page.body.querySelectorAll('input').length).toEqual(0);
        });
    });
    it('can click options', async () => {
        const page = await newSpecPage({
            html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
            components: [BpSdkAutocompleteInput],
        });
        const instance = page.rootInstance;
        instance.questionId = '1';
        instance.showChoices = true;
        instance.choices = [
            { id: '1', value: '1' },
            { id: '2', value: '2' },
        ];
        const focusSpy = jest.fn();
        instance.el.querySelector = jest.fn(() => ({
            focus: focusSpy,
        }));
        expect(instance.value).toBeUndefined();
        expect(instance.choice).toBeUndefined();
        await page.waitForChanges();
        const nodes = page.body.querySelectorAll('.bp-sdk-autocomplete__list-item');
        expect(nodes[0].textContent).toEqual('1');
        nodes[0].click();
        await page.waitForChanges();
        const selected = page.body.querySelector('[aria-selected="true"]');
        expect(selected.textContent).toEqual('1');
        expect(instance._showChoices).toBeFalsy();
        expect(instance.value).toEqual('1');
        expect(instance.choice).toEqual(instance.choices[0]);
        expect(focusSpy).toHaveBeenCalledTimes(1);
    });
    describe('displayChoice', () => {
        it('returns expected values', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            expect(instance.displayChoice({})).toBeUndefined();
            expect(instance.displayChoice(undefined)).toBeUndefined();
            expect(instance.displayChoice(null)).toBeUndefined();
            expect(instance.displayChoice({ value: 'value' })).toBe('value');
        });
    });
    describe('choiceSelected', () => {
        it('should make expected calls', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const focus = jest.fn();
            jest.spyOn(instance.el, 'querySelector').mockReturnValue({
                focus,
            });
            const choice = {
                id: 'an id',
            };
            instance.choiceSelected(choice);
            expect(instance.value).toEqual(choice.id);
            expect(instance.choice).toEqual(choice);
            expect(focus).toHaveBeenCalledTimes(1);
        });
        it('should make expected calls if fallback', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.allowFallthrough = true;
            instance.filterText = 'oh my';
            const focus = jest.fn();
            jest.spyOn(instance.el, 'querySelector').mockReturnValue({
                focus,
            });
            expect(instance.value).not.toEqual(instance.filterText);
            instance.choiceSelected(undefined);
            expect(instance.value).toEqual(instance.filterText);
            expect(focus).toHaveBeenCalledTimes(1);
        });
        it('handle query failing', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const focus = jest.fn();
            jest.spyOn(instance.el, 'querySelector').mockReturnValue(null);
            const choice = {
                id: 'an id',
            };
            instance.choiceSelected(choice);
            expect(instance.value).toEqual(choice.id);
            expect(instance.choice).toEqual(choice);
            expect(focus).toHaveBeenCalledTimes(0);
        });
        it('handle no choice', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const focus = jest.fn();
            jest.spyOn(instance.el, 'querySelector').mockReturnValue({
                focus,
            });
            instance.choiceSelected(undefined);
            expect(focus).toHaveBeenCalledTimes(1);
        });
    });
    describe('onChoiceIdChange', () => {
        it('should make expected changes', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            instance.onChoiceIdChange('1');
            expect(instance.choice).toEqual(instance.choices[0]);
            instance.onChoiceIdChange('0');
            expect(instance.choice).toBeUndefined();
        });
    });
    describe('onChoicesUpdate', () => {
        it('should update choices state and make expected calls', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            await page.waitForChanges();
            instance.choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            instance.choiceId = 'someId';
            jest.spyOn(instance, 'onChoiceIdChange').mockImplementation(() => { });
            await page.waitForChanges();
            instance.onChoicesChange(instance.choices);
            expect(instance._choices).toBe(instance.choices);
            expect(instance.onChoiceIdChange).toBeCalledTimes(1);
            expect(instance.onChoiceIdChange).toBeCalledWith(instance.choiceId);
        });
        it('should not reset text if choice has not changed', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            await page.waitForChanges();
            const text = '100';
            instance.choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            instance.choiceId = '1';
            expect(instance.choiceText).toEqual(instance.choices[0].value);
            expect(instance.text).toEqual(instance.choices[0].value);
            instance.text = text;
            instance.choices = [
                { id: '1', value: '1' },
                { id: '3', value: '3' },
                { id: '2', value: '2' },
            ];
            await page.waitForChanges();
            expect(instance.text).toEqual(text);
            expect(instance.choiceText).toEqual(instance.choices[0].value);
        });
        it("shouldn't update choices state haven't changed", async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            instance._choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            instance.choiceId = 'some id';
            jest.spyOn(instance, 'onChoiceIdChange').mockImplementation(() => { });
            await page.waitForChanges();
            instance.onChoicesChange(instance.choices);
            expect(instance._choices).toEqual(instance.choices);
            expect(instance._choices).not.toBe(instance.choices);
            expect(instance.onChoiceIdChange).toBeCalledTimes(1);
            expect(instance.onChoiceIdChange).toBeCalledWith(instance.choiceId);
        });
    });
    describe('onBlur', () => {
        it('should make expected changes', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            await page.waitForChanges();
            const el = {
                value: 'some value',
            };
            jest.spyOn(instance.el, 'querySelector').mockReturnValue(el);
            instance.isFocused = true;
            instance.onBlur();
            expect(instance.isFocused).toBeFalsy();
            expect(el.value).toEqual(instance.getText(instance.choice));
        });
        it('skips updating value if disabled drop down', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.disableDropdown = true;
            instance.choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            await page.waitForChanges();
            const value = 'some value';
            const el = {
                value,
            };
            jest.spyOn(instance.el, 'querySelector').mockReturnValue(el);
            instance.isFocused = true;
            instance.onBlur();
            expect(instance.isFocused).toBeFalsy();
            expect(el.value).toEqual(value);
        });
    });
    describe('onFilterChange', () => {
        it('should emit expected value', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const result = {
                id: '20',
                value: 'newValue',
            };
            instance.questionId = result.id;
            instance.answerId = 'answer id';
            instance.filterUpdate.emit = jest.fn();
            instance.updateActiveAnswer.emit = jest.fn();
            await page.waitForChanges();
            // NaN !== NaN
            instance.onFilterChange(result.value);
            expect(instance.filterUpdate.emit).toHaveBeenCalledTimes(1);
            expect(instance.filterUpdate.emit).toHaveBeenLastCalledWith(result);
            expect(instance.updateActiveAnswer.emit).toHaveBeenCalledTimes(1);
            expect(instance.updateActiveAnswer.emit).toHaveBeenLastCalledWith(instance.answerId);
        });
    });
    describe('checkForSelectedChoice', () => {
        it('should update value and choice if match found', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            instance.choiceId = '1';
            instance.checkForSelectedChoice();
            expect(instance.choice).toBe(instance._choices[0]);
            expect(instance.value).toBe(instance._choices[0].id);
        });
        it('should do nothing if not match', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            instance.choiceId = null;
            instance.checkForSelectedChoice();
            expect(instance.choice).toBe(undefined);
            expect(instance.value).toBe(undefined);
        });
    });
    describe('onShowChoicesChange', () => {
        it('makes expected changes', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            instance._showChoices = true;
            instance.isFocused = false;
            instance.onShowChoicesChange(true);
            expect(instance._showChoices).toBeFalsy();
            instance._showChoices = true;
            instance.onShowChoicesChange(false);
            expect(instance._showChoices).toBeFalsy();
            instance._showChoices = true;
            instance.isFocused = true;
            instance.onShowChoicesChange(true);
            expect(instance._showChoices).toBeTruthy();
            instance._showChoices = true;
            instance.onShowChoicesChange(false);
            expect(instance._showChoices).toBeFalsy();
        });
    });
    describe('focusOption', () => {
        it('should make expected choice', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            instance._showChoices = false;
            instance.isFocused = true;
            expect(instance.focusedIndex).toEqual(0);
            expect(instance._showChoices).toBeFalsy();
            instance.focusOption(1);
            expect(instance.focusedIndex).toEqual(1);
            expect(instance._showChoices).toBeTruthy();
        });
    });
    describe('filterChoices', () => {
        it('should update filter text after 300ms', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            await page.waitForChanges();
            instance.filterText = 'fake';
            instance._showChoices = false;
            instance.isFocused = true;
            jest.spyOn(instance.el, 'querySelector').mockReturnValue({
                value: 'new number',
            });
            expect(instance._showChoices).toBeFalsy();
            instance.filterChoices();
            expect(instance.filterText).toEqual('new number');
            expect(instance._showChoices).toBeTruthy();
        });
        it('should not show choices if not focused', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            await page.waitForChanges();
            instance.filterText = 'fake';
            instance._showChoices = true;
            instance.isFocused = false;
            jest.spyOn(instance.el, 'querySelector').mockReturnValue({
                value: 'new number',
            });
            expect(instance._showChoices).toBeTruthy();
            instance.filterChoices();
            expect(instance.filterText).toEqual('new number');
            expect(instance._showChoices).toBeFalsy();
        });
        it('should not show list if no text', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            await page.waitForChanges();
            instance.filterText = 'fake';
            instance._showChoices = false;
            jest.spyOn(instance.el, 'querySelector').mockReturnValue({
                value: '',
            });
            expect(instance._showChoices).toBeFalsy();
            instance.filterChoices();
            expect(instance.filterText).toEqual('');
            expect(instance._showChoices).toBeFalsy();
        });
    });
    describe('OnKeyDown', () => {
        let page;
        let instance;
        beforeEach(async () => {
            page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            instance = page.rootInstance;
            instance.handleKeyEvent = jest.fn();
            instance.debounceFilterChoices = jest.fn();
        });
        it('ArrowUp', () => {
            const keyboardEvent = new KeyboardEvent('keydown', {
                key: 'ArrowUp',
            });
            keyboardEvent.preventDefault = jest.fn();
            instance.onKeydown(keyboardEvent);
            expect(instance.handleKeyEvent).toHaveBeenCalledWith(keyboardEvent.key);
            expect(instance.handleKeyEvent).toHaveBeenCalledTimes(1);
            expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(1);
            expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(0);
        });
        it('ArrowDown', () => {
            const keyboardEvent = new KeyboardEvent('keydown', {
                key: 'ArrowDown',
            });
            keyboardEvent.preventDefault = jest.fn();
            instance.onKeydown(keyboardEvent);
            expect(instance.handleKeyEvent).toHaveBeenCalledWith(keyboardEvent.key);
            expect(instance.handleKeyEvent).toHaveBeenCalledTimes(1);
            expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(1);
            expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(0);
        });
        it('Enter', () => {
            const keyboardEvent = new KeyboardEvent('keydown', {
                key: 'Enter',
            });
            keyboardEvent.preventDefault = jest.fn();
            instance.onKeydown(keyboardEvent);
            expect(instance.handleKeyEvent).toHaveBeenCalledWith(keyboardEvent.key);
            expect(instance.handleKeyEvent).toHaveBeenCalledTimes(1);
            expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(1);
            expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(0);
        });
        it('Escape', () => {
            const keyboardEvent = new KeyboardEvent('keydown', {
                key: 'Escape',
            });
            keyboardEvent.preventDefault = jest.fn();
            instance._showChoices = true;
            instance.onKeydown(keyboardEvent);
            expect(instance._showChoices).toBeFalsy();
            expect(instance.handleKeyEvent).toHaveBeenCalledTimes(0);
            expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(0);
            expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(0);
        });
        it('Tab', () => {
            const keyboardEvent = new KeyboardEvent('keydown', {
                key: 'Tab',
            });
            keyboardEvent.preventDefault = jest.fn();
            instance._showChoices = true;
            instance.onKeydown(keyboardEvent);
            expect(instance._showChoices).toBeFalsy();
            expect(instance.handleKeyEvent).toHaveBeenCalledTimes(0);
            expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(0);
            expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(0);
        });
        it('Meta without flag', () => {
            const keyboardEvent = new KeyboardEvent('keydown', {
                key: 'Meta',
            });
            keyboardEvent.preventDefault = jest.fn();
            instance._showChoices = true;
            instance.onKeydown(keyboardEvent);
            expect(instance._showChoices).toBeTruthy();
            expect(instance.handleKeyEvent).toHaveBeenCalledTimes(0);
            expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(0);
            expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(0);
        });
        it('Meta', () => {
            const keyboardEvent = new KeyboardEvent('keydown', {
                key: 'Meta',
                metaKey: true,
            });
            keyboardEvent.preventDefault = jest.fn();
            instance._showChoices = true;
            instance.onKeydown(keyboardEvent);
            expect(instance._showChoices).toBeTruthy();
            expect(instance.handleKeyEvent).toHaveBeenCalledTimes(0);
            expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(0);
            expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(0);
        });
        it('Alt', () => {
            const keyboardEvent = new KeyboardEvent('keydown', {
                key: 'Alt',
                altKey: true,
            });
            keyboardEvent.preventDefault = jest.fn();
            instance._showChoices = true;
            instance.onKeydown(keyboardEvent);
            expect(instance._showChoices).toBeTruthy();
            expect(instance.handleKeyEvent).toHaveBeenCalledTimes(0);
            expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(0);
            expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(0);
        });
        it('Alt without flag', () => {
            const keyboardEvent = new KeyboardEvent('keydown', {
                key: 'Alt',
            });
            keyboardEvent.preventDefault = jest.fn();
            instance._showChoices = true;
            instance.onKeydown(keyboardEvent);
            expect(instance._showChoices).toBeTruthy();
            expect(instance.handleKeyEvent).toHaveBeenCalledTimes(0);
            expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(0);
            expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(0);
        });
        it('Control', () => {
            const keyboardEvent = new KeyboardEvent('keydown', {
                key: 'Control',
            });
            keyboardEvent.preventDefault = jest.fn();
            instance._showChoices = true;
            instance.onKeydown(keyboardEvent);
            expect(instance._showChoices).toBeTruthy();
            expect(instance.handleKeyEvent).toHaveBeenCalledTimes(0);
            expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(0);
            expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(0);
        });
        describe('Backspace', () => {
            it('has filter text', () => {
                const keyboardEvent = new KeyboardEvent('keydown', {
                    key: 'Backspace',
                });
                keyboardEvent.preventDefault = jest.fn();
                const value = "Bob's Burgers";
                instance.filterText = value;
                jest.spyOn(instance.el, 'querySelector').mockReturnValue({
                    value: value.slice(0, value.length - 1),
                });
                instance.onKeydown(keyboardEvent);
                expect(instance.handleKeyEvent).toHaveBeenCalledTimes(0);
                expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(0);
                expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(1);
            });
            it('no filter text', () => {
                const keyboardEvent = new KeyboardEvent('keydown', {
                    key: 'Backspace',
                });
                keyboardEvent.preventDefault = jest.fn();
                instance.filterText = '';
                instance.onKeydown(keyboardEvent);
                expect(instance.handleKeyEvent).toHaveBeenCalledTimes(0);
                expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(0);
                expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(1);
            });
        });
        it('Other key', () => {
            const keyboardEvent = new KeyboardEvent('keydown', {
                key: 'A',
            });
            keyboardEvent.preventDefault = jest.fn();
            jest.spyOn(instance.el, 'querySelector').mockReturnValue({
                value: 'A',
            });
            instance.filterText = '';
            instance.onKeydown(keyboardEvent);
            expect(instance.handleKeyEvent).toHaveBeenCalledTimes(0);
            expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(0);
            expect(instance.debounceFilterChoices).toHaveBeenCalledTimes(1);
        });
    });
    describe('handleKeyEvent', () => {
        it('should make expected calls', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const keyOptions = {
                isOpenOrSelectKey: false,
                shouldMoveIndex: true,
                goToPrevious: true,
                goToNext: false,
            };
            instance.getKeyEventOptions = jest.fn(() => keyOptions);
            instance.getIndexToSelect = jest.fn(() => 3);
            instance.mapKeyEventToAction = jest.fn();
            instance.handleKeyEvent('some key');
            expect(instance.getKeyEventOptions).toHaveBeenCalledTimes(1);
            expect(instance.getKeyEventOptions).toHaveBeenCalledWith('some key');
            expect(instance.getIndexToSelect).toHaveBeenCalledTimes(1);
            expect(instance.getIndexToSelect).toHaveBeenCalledWith('some key', keyOptions);
            expect(instance.mapKeyEventToAction).toHaveBeenCalledTimes(1);
            expect(instance.mapKeyEventToAction).toHaveBeenCalledWith(3, keyOptions);
        });
    });
    describe('getKeyEventOptions', () => {
        describe('ArrowUp', () => {
            it('should return expected result', async () => {
                const page = await newSpecPage({
                    html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                    components: [BpSdkAutocompleteInput],
                });
                const instance = page.rootInstance;
                const options = {
                    isOpenOrSelectKey: false,
                    shouldMoveIndex: false,
                    goToPrevious: true,
                    goToNext: false,
                };
                expect(instance.getKeyEventOptions('ArrowUp')).toEqual(options);
                instance._showChoices = true;
                expect(instance.getKeyEventOptions('ArrowUp')).toEqual(Object.assign(Object.assign({}, options), { shouldMoveIndex: true }));
            });
        });
        describe('ArrowDown', () => {
            it('should return expected result', async () => {
                const page = await newSpecPage({
                    html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                    components: [BpSdkAutocompleteInput],
                });
                const instance = page.rootInstance;
                const options = {
                    isOpenOrSelectKey: false,
                    shouldMoveIndex: false,
                    goToNext: true,
                    goToPrevious: false,
                };
                expect(instance.getKeyEventOptions('ArrowDown')).toEqual(options);
                instance._showChoices = true;
                expect(instance.getKeyEventOptions('ArrowDown')).toEqual(Object.assign(Object.assign({}, options), { shouldMoveIndex: true }));
            });
        });
        describe('Enter', () => {
            it('should return expected result', async () => {
                const page = await newSpecPage({
                    html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                    components: [BpSdkAutocompleteInput],
                });
                const instance = page.rootInstance;
                const options = {
                    isOpenOrSelectKey: true,
                    shouldMoveIndex: false,
                    goToPrevious: false,
                    goToNext: false,
                };
                expect(instance.getKeyEventOptions('Enter')).toEqual(options);
            });
        });
        it('Other keys should return expected result', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const options = {
                isOpenOrSelectKey: false,
                shouldMoveIndex: false,
                goToPrevious: false,
                goToNext: false,
            };
            expect(instance.getKeyEventOptions('A')).toEqual(options);
        });
    });
    describe('getIndexToSelect', () => {
        it('should open select list', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const options = {
                isOpenOrSelectKey: true,
                shouldMoveIndex: true,
                goToPrevious: true,
            };
            instance._showChoices = true;
            instance.focusedIndex = 10;
            expect(instance.getIndexToSelect('Escape', options)).toEqual(instance.focusedIndex);
        });
        it('should skip open or select key option if choices are hidden', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const options = {
                isOpenOrSelectKey: true,
                shouldMoveIndex: true,
                goToPrevious: true,
            };
            instance._showChoices = false;
            instance.focusedIndex = 10;
            expect(instance.getIndexToSelect('Escape', options)).toBeUndefined();
            expect(instance._showChoices).toBeFalsy();
        });
        it('should close list if escape key pressed', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const options = {
                isOpenOrSelectKey: false,
                shouldMoveIndex: true,
                goToPrevious: true,
            };
            instance._showChoices = true;
            instance.focusedIndex = 10;
            expect(instance.getIndexToSelect('Escape', options)).toBeUndefined();
            expect(instance._showChoices).toBeFalsy();
        });
        it('should not return selected index if choices are shown', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const options = {
                isOpenOrSelectKey: false,
                shouldMoveIndex: true,
                goToPrevious: true,
            };
            instance._showChoices = true;
            instance.focusedIndex = 10;
            expect(instance.getIndexToSelect('Any Other Key', options)).toBeUndefined();
            expect(instance._showChoices).toBeTruthy();
        });
        it('should return previous index if go to previous', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const options = {
                isOpenOrSelectKey: false,
                shouldMoveIndex: true,
                goToPrevious: true,
            };
            instance._showChoices = false;
            instance.focusedIndex = 10;
            expect(instance.getIndexToSelect('Any Other Key', options)).toBe(instance.focusedIndex - 1);
            expect(instance._showChoices).toBeFalsy();
        });
        it('should return next index if not go previous', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const options = {
                isOpenOrSelectKey: false,
                shouldMoveIndex: true,
                goToPrevious: false,
            };
            instance._showChoices = false;
            instance.focusedIndex = 10;
            expect(instance.getIndexToSelect('Any Other Key', options)).toBe(instance.focusedIndex + 1);
            expect(instance._showChoices).toBeFalsy();
        });
        it('should return 0 if no focused index', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const options = {
                isOpenOrSelectKey: false,
                shouldMoveIndex: true,
                goToPrevious: false,
            };
            instance._showChoices = false;
            instance.focusedIndex = null;
            expect(instance.getIndexToSelect('Any Other Key', options)).toBe(0);
            expect(instance._showChoices).toBeFalsy();
        });
        it('otherwise returns undefined and does nothing', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const options = {
                isOpenOrSelectKey: false,
                shouldMoveIndex: false,
                goToPrevious: true,
            };
            instance._showChoices = false;
            instance.focusedIndex = 10;
            expect(instance.getIndexToSelect('Any Other Key', options)).toBeUndefined();
            expect(instance._showChoices).toBeFalsy();
        });
    });
    describe('mapKeyEventToAction', () => {
        it('should select from index if index is provided', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.focusOption = jest.fn();
            instance.selectOptionByIndex = jest.fn();
            const options = {
                shouldMoveIndex: true,
                goToPrevious: true,
            };
            expect(instance.focusedIndex).toEqual(0);
            instance.mapKeyEventToAction(1, options);
            expect(instance.selectOptionByIndex).toHaveBeenCalledWith(1);
            expect(instance.focusOption).toHaveBeenCalledTimes(0);
            expect(instance.selectOptionByIndex).toHaveBeenCalledTimes(1);
        });
        it('should move back if should move and not opening list or selecting index', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.focusOption = jest.fn();
            instance.selectOptionByIndex = jest.fn();
            instance._showChoices = true;
            const options = {
                shouldMoveIndex: true,
                goToPrevious: true,
            };
            expect(instance.focusedIndex).toEqual(0);
            instance.mapKeyEventToAction(null, options);
            expect(instance.focusOption).toHaveBeenCalledWith(-1);
            expect(instance.focusOption).toHaveBeenCalledTimes(1);
            expect(instance.selectOptionByIndex).toHaveBeenCalledTimes(0);
        });
        it('should move forward if not going back if should move and not opening list or selecting index', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.focusOption = jest.fn();
            instance.selectOptionByIndex = jest.fn();
            instance._showChoices = true;
            const options = {
                shouldMoveIndex: true,
                goToPrevious: false,
            };
            instance.focusedIndex = 1;
            instance.mapKeyEventToAction(null, options);
            expect(instance.focusOption).toHaveBeenCalledWith(2);
            expect(instance.focusOption).toHaveBeenCalledTimes(1);
            expect(instance.selectOptionByIndex).toHaveBeenCalledTimes(0);
        });
        it('should set to top item if  move down and no list shown', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.focusOption = jest.fn();
            instance.selectOptionByIndex = jest.fn();
            instance._showChoices = true;
            const id = 'some id';
            jest.spyOn(instance, 'displayChoice').mockReturnValue(id);
            const options = {
                shouldMoveIndex: false,
                goToPrevious: true,
            };
            instance.mapKeyEventToAction(null, options);
            expect(instance.focusOption).toHaveBeenCalledTimes(1);
            expect(instance.focusOption).toHaveBeenCalledWith(0);
            expect(instance.filterText).toEqual(id);
            expect(instance.selectOptionByIndex).toHaveBeenCalledTimes(0);
        });
        it('should set to top item if move up and no list shown', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.focusOption = jest.fn();
            instance.selectOptionByIndex = jest.fn();
            instance._showChoices = true;
            const id = 'some id';
            jest.spyOn(instance, 'displayChoice').mockReturnValue(id);
            const options = {
                shouldMoveIndex: false,
                goToNext: true,
            };
            instance.mapKeyEventToAction(null, options);
            expect(instance.focusOption).toHaveBeenCalledTimes(1);
            expect(instance.focusOption).toHaveBeenCalledWith(0);
            expect(instance.filterText).toEqual(id);
            expect(instance.selectOptionByIndex).toHaveBeenCalledTimes(0);
        });
        it('should do nothing otherwise', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.focusOption = jest.fn();
            instance.selectOptionByIndex = jest.fn();
            instance._showChoices = true;
            const options = {
                shouldMoveIndex: false,
            };
            instance.mapKeyEventToAction(null, options);
            expect(instance.focusOption).toHaveBeenCalledTimes(0);
            expect(instance.selectOptionByIndex).toHaveBeenCalledTimes(0);
        });
        it("should do nothing if 'showChoices' is false", async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.focusOption = jest.fn();
            instance.selectOptionByIndex = jest.fn();
            instance._showChoices = false;
            const options = {
                shouldMoveIndex: true,
            };
            instance.mapKeyEventToAction(null, options);
            expect(instance.focusOption).toHaveBeenCalledTimes(0);
            expect(instance.selectOptionByIndex).toHaveBeenCalledTimes(0);
        });
    });
    describe('selectOptionByIndex', () => {
        it('should make expected choice', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const focusSpy = jest.fn();
            const instance = page.rootInstance;
            instance.el.querySelector = jest.fn(() => ({
                focus: focusSpy,
            }));
            instance.choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            expect(instance.focusedIndex).toEqual(0);
            instance.selectOptionByIndex(1);
            expect(instance.focusedIndex).toEqual(1);
            expect(instance.choice).toEqual(instance._choices[1]);
            expect(focusSpy).toHaveBeenCalledTimes(1);
        });
    });
    describe('getSelectableIndex', () => {
        it('should bound check index', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.choices = [
                { id: '1', value: '1' },
                { id: '2', value: '2' },
            ];
            expect(instance.getSelectableIndex(-1)).toBe(0);
            expect(instance.getSelectableIndex(0)).toBe(0);
            expect(instance.getSelectableIndex(1)).toBe(1);
            expect(instance.getSelectableIndex(2)).toBe(1);
        });
    });
    describe('handleOutsideClick', () => {
        it('should make expected changes', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance._showChoices = true;
            instance.handleOutsideClick();
            expect(instance._showChoices).toBeFalsy();
        });
    });
    describe('onFocus', () => {
        it('should make expected changes', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.isFocused = false;
            instance.onFocus();
            expect(instance.isFocused).toBeTruthy();
        });
    });
    describe('handleClick', () => {
        it('should make expected changes', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            const event = {
                stopPropagation: jest.fn(),
            };
            instance.handleClick(event);
            expect(event.stopPropagation).toHaveBeenCalledTimes(1);
        });
        it('disable if external', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-autocomplete-input></<bp-sdk-autocomplete-input>',
                components: [BpSdkAutocompleteInput],
            });
            const instance = page.rootInstance;
            instance.useExternal = true;
            const event = {
                stopPropagation: jest.fn(),
            };
            instance.handleClick(event);
            expect(event.stopPropagation).toHaveBeenCalledTimes(0);
        });
    });
});
