import { newSpecPage } from "@stencil/core/testing";
import { MaskedInputService } from "../../services/masked-input.service";
import { BpSdkMaskedInput } from "./bp-sdk-masked-input";
jest.mock('inputmask');
const setupPage = async () => {
    return await newSpecPage({
        html: '<bp-sdk-masked-input></bp-sdk-masked-input>',
        components: [BpSdkMaskedInput],
    });
};
const setupInstance = (page) => {
    return page.rootInstance;
};
const createMockInputElement = (value) => {
    const el = document.createElement('input');
    el.value = value;
    return el;
};
const createMockInputMask = () => {
    return {
        mask: jest.fn(() => { }),
        unmaskedvalue: jest.fn(() => 'value'),
    };
};
const createMockInputEvent = (value) => {
    return {
        target: {
            inputmask: {
                unmaskedvalue: () => value,
            },
            value,
        },
    };
};
class LabelTestCase {
}
class MaskOptionsTestCase {
}
class InputMaskTestCase {
}
class DidRenderTestCase {
}
describe('bp-sdk-masked-input', () => {
    describe('renders', () => {
        let page;
        let instance;
        beforeEach(async () => {
            page = await setupPage();
            instance = setupInstance(page);
        });
        it('vanilla', async () => {
            instance._placeholder = 'placeholder';
            instance.labelledBy = 'labelledBy';
            instance.labelId = 'labelId';
            await page.waitForChanges();
            const input = page.root.querySelector('.bp-sdk-masked__input');
            expect(input.placeholder).toBe(instance._placeholder);
            expect(input.getAttribute('aria-labelledby')).toEqual('labelId labelledBy');
        });
        it('renders read only mode', async () => {
            instance.value = 'value';
            instance.isReadOnly = true;
            await page.waitForChanges();
            const element = page.root.querySelector('.read-only-value');
            expect(element.textContent).toBe(instance.value);
        });
        it('renders errors', async () => {
            instance.isCompleted = false;
            instance.errors = ['errors'];
            instance.pristine = false;
            instance.touched = true;
            instance._touched = true;
            await page.waitForChanges();
            expect(page.root.querySelectorAll('bp-sdk-errors-container').length).toBe(1);
        });
        it('does not render error text if is completed', async () => {
            instance.isCompleted = true;
            instance.errors = undefined;
            instance.errorText = 'some error';
            instance.pristine = false;
            instance.touched = true;
            instance._touched = true;
            await page.waitForChanges();
            expect(page.root.querySelectorAll('bp-sdk-errors-container').length).toBe(0);
        });
        it('renders error text', async () => {
            instance.isCompleted = false;
            instance.errors = null;
            instance.errorText = 'errors';
            instance.pristine = false;
            instance.touched = true;
            instance._touched = true;
            await page.waitForChanges();
            expect(page.root.querySelectorAll('bp-sdk-errors-container').length).toBe(1);
        });
        it('hides error text if is completed', async () => {
            instance.isCompleted = false;
            instance.errors = null;
            instance.errorText = 'errors';
            instance.pristine = false;
            instance.touched = true;
            instance.isCompleted = true;
            await page.waitForChanges();
            expect(page.root.querySelectorAll('bp-sdk-errors-container').length).toBe(0);
        });
        it('handles null errors', async () => {
            instance.isCompleted = false;
            instance.errors = null;
            instance.errorText = null;
            instance.pristine = false;
            instance.touched = true;
            await page.waitForChanges();
            expect(page.root.querySelectorAll('bp-sdk-errors-container').length).toBe(0);
        });
        it('can render external', async () => {
            const whenDefinedMock = jest.spyOn(customElements, 'whenDefined').mockResolvedValueOnce({});
            const page = await setupPage();
            await page.waitForChanges();
            expect(page.root.querySelector('.bp-sdk-masked__input')).toBeFalsy();
            whenDefinedMock.mockRestore();
        });
    });
    // Lifecycle events
    describe('connectedCallback()', () => {
        let instance;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.touched = true;
            instance.connectedCallback();
        });
        it('should reset the touched state', () => {
            expect(instance._touched).toEqual(false);
        });
        it('should create an service instance', () => {
            expect(instance.service).toBeDefined();
        });
    });
    describe('componentWillUpdate()', () => {
        let instance;
        const placeholder = 'placeholder';
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.service = new MaskedInputService();
        });
        describe('when an external component is used', () => {
            beforeEach(() => {
                instance.useExternal = true;
                instance.shouldUpdatePlaceholder = true;
                instance._placeholder = null;
                instance.componentWillUpdate();
            });
            it('should not update the placeholder', () => {
                expect(instance._placeholder).toEqual(null);
            });
            it('should unset the update placeholder flag', () => {
                expect(instance.shouldUpdatePlaceholder).toEqual(false);
            });
        });
        describe('when the placeholder should not be updated', () => {
            beforeEach(() => {
                instance.useExternal = false;
                instance.shouldUpdatePlaceholder = false;
                instance._placeholder = null;
                instance.placeholder = placeholder;
                instance.componentWillUpdate();
            });
            it('should not update the placeholder', () => {
                expect(instance._placeholder).toEqual(null);
            });
            it('should unset the update placeholder flag', () => {
                expect(instance.shouldUpdatePlaceholder).toEqual(false);
            });
        });
        describe('when the component is read only', () => {
            beforeEach(() => {
                instance.useExternal = false;
                instance.isReadOnly = true;
                instance.shouldUpdatePlaceholder = true;
                instance._placeholder = null;
                instance.placeholder = placeholder;
                instance.componentWillUpdate();
            });
            it('should not update the placeholder', () => {
                expect(instance._placeholder).toEqual(null);
            });
            it('should unset the update placeholder flag', () => {
                expect(instance.shouldUpdatePlaceholder).toEqual(false);
            });
        });
        describe('when the placeholder should be updated', () => {
            beforeEach(() => {
                instance.useExternal = false;
                instance.isReadOnly = false;
                instance.shouldUpdatePlaceholder = true;
                instance._placeholder = null;
                instance.placeholder = placeholder;
                instance.componentWillUpdate();
            });
            it('should update the placeholder', () => {
                expect(instance._placeholder).toEqual(placeholder);
            });
            it('should unset the update placeholder flag', () => {
                expect(instance.shouldUpdatePlaceholder).toEqual(false);
            });
        });
    });
    describe('componentWillLoad()', () => {
        let instance;
        const placeholder = 'placeholder';
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.service = new MaskedInputService();
        });
        describe('when an external component is used', () => {
            let whenDefinedMock;
            beforeEach(() => {
                whenDefinedMock = jest.spyOn(customElements, 'whenDefined').mockResolvedValueOnce({});
                jest.spyOn(customElements, 'get').mockReturnValueOnce({});
                instance.shouldUpdatePlaceholder = true;
                instance._placeholder = null;
                instance.componentWillLoad();
            });
            afterEach(() => {
                whenDefinedMock.mockRestore();
            });
            it('should not update the placeholder', () => {
                expect(instance._placeholder).toEqual(null);
            });
            it('should unset the update placeholder flag', () => {
                expect(instance.shouldUpdatePlaceholder).toEqual(false);
            });
        });
        describe.each([
            [true, null],
            [false, placeholder],
        ])('when an external component is not used and read only is %s', (isReadOnly, expectedPlaceholder) => {
            beforeEach(() => {
                instance.useExternal = false;
                instance.isReadOnly = isReadOnly;
                instance.shouldUpdatePlaceholder = true;
                instance._placeholder = null;
                instance.placeholder = placeholder;
                instance.componentWillLoad();
            });
            it('should update the placeholder to the correct value', () => {
                expect(instance._placeholder).toEqual(expectedPlaceholder);
            });
            it('should unset the update placeholder flag', () => {
                expect(instance.shouldUpdatePlaceholder).toEqual(false);
            });
        });
    });
    describe('componentDidRender()', () => {
        let instance;
        let elementQuerySpy;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.service = {};
        });
        describe('when an external component is used', () => {
            beforeEach(() => {
                instance.useExternal = true;
                elementQuerySpy = jest.spyOn(instance.el, 'querySelector').mockImplementation(() => createMockInputElement('value'));
                instance.componentDidRender();
            });
            it('should not attempt to mask an element', () => {
                expect(elementQuerySpy).not.toHaveBeenCalled();
            });
        });
        describe('when component is read only', () => {
            beforeEach(() => {
                instance.isReadOnly = true;
                elementQuerySpy = jest.spyOn(instance.el, 'querySelector').mockImplementation(() => createMockInputElement('value'));
                instance.componentDidRender();
            });
            it('should not attempt to mask an element', () => {
                expect(elementQuerySpy).not.toHaveBeenCalled();
            });
        });
        describe('when the mask is not flagged for an update', () => {
            beforeEach(() => {
                instance.useExternal = false;
                instance.shouldUpdateMask = false;
                elementQuerySpy = jest.spyOn(instance.el, 'querySelector').mockImplementation(() => createMockInputElement('value'));
                instance.componentDidRender();
            });
            it('should not attempt to mask an element', () => {
                expect(elementQuerySpy).not.toHaveBeenCalled();
            });
        });
    });
    describe('componentDidRender() - input masking scenarios', () => {
        let instance;
        let mockService;
        let mockInputMask;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            mockInputMask = createMockInputMask();
            mockService = {
                buildPlaceholderFromMaskConfig: jest.fn(() => ''),
                createDefaultMaskInstance: jest.fn(() => mockInputMask),
                createPasswordMaskInstance: jest.fn(() => mockInputMask),
                createTextMaskInstance: jest.fn(() => mockInputMask),
                applyMaskToElement: jest.fn(() => { }),
                removeMaskFromElement: jest.fn(() => { }),
                isElementMaskSame: jest.fn(() => true),
            };
            instance.service = mockService;
            instance.useExternal = false;
            instance.shouldUpdateMask = true;
        });
        describe('custom mask should not be applied', () => {
            describe('when the target element is not found', () => {
                beforeEach(() => {
                    jest.spyOn(instance.el, 'querySelector').mockImplementation(() => null);
                    instance.componentDidRender();
                });
                it('should not attempt to mask the element', () => {
                    expect(mockService.applyMaskToElement).not.toHaveBeenCalled();
                });
                it('should unset the mask update flag', () => {
                    expect(instance.shouldUpdateMask).toEqual(false);
                });
            });
            describe.each([
                [
                    'when an external component is used',
                    {
                        isExternal: true,
                        isReadOnly: false,
                    },
                ],
                [
                    'when the component is read only',
                    {
                        isExternal: false,
                        isReadOnly: true,
                    },
                ],
            ])('when the target element is not found', (_description, testCase) => {
                beforeEach(() => {
                    instance.useExternal = testCase.isExternal;
                    instance.isReadOnly = testCase.isReadOnly;
                    instance.componentDidRender();
                });
                it('should not attempt to mask the element', () => {
                    expect(mockService.applyMaskToElement).not.toHaveBeenCalled();
                });
                it('should unset the mask update flag', () => {
                    expect(instance.shouldUpdateMask).toEqual(false);
                });
            });
            describe('when complex mask logic is not set and the element is already masked', () => {
                beforeEach(() => {
                    const element = createMockInputElement('value');
                    element.inputmask = {};
                    jest.spyOn(instance.el, 'querySelector').mockImplementation(() => element);
                    instance.componentDidRender();
                });
                it('should not attempt to mask the element', () => {
                    expect(mockService.applyMaskToElement).not.toHaveBeenCalled();
                });
                it('should unset the mask update flag', () => {
                    expect(instance.shouldUpdateMask).toEqual(false);
                });
            });
            describe('config:(complex, not focus, complete)', () => {
                beforeEach(() => {
                    const element = createMockInputElement('value');
                    jest.spyOn(instance.el, 'querySelector').mockImplementation(() => element);
                    instance.useComplexMaskLogic = true;
                    instance.hasFocus = false;
                    instance.isCompleted = true;
                    instance.completedValue = 'value';
                    instance.componentDidRender();
                });
                it('should not use a custom mask', () => {
                    expect(mockService.createTextMaskInstance).not.toHaveBeenCalled();
                    expect(mockService.createPasswordMaskInstance).not.toHaveBeenCalled();
                    // The default mask is used in the is scenario, so a mask will still be applied
                    expect(mockService.applyMaskToElement).toHaveBeenCalled();
                });
                it('should unset the mask update flag', () => {
                    expect(instance.shouldUpdateMask).toEqual(false);
                });
            });
        });
        describe.each([
            [
                'not complex',
                {
                    useComplexMaskLogic: false,
                    hasFocus: true,
                    isCompleted: false,
                },
            ],
            [
                'complex, focus, not complete',
                {
                    useComplexMaskLogic: true,
                    hasFocus: true,
                    isCompleted: false,
                },
            ],
            [
                'complex, not focus, not complete',
                {
                    useComplexMaskLogic: true,
                    hasFocus: false,
                    isCompleted: false,
                },
            ],
        ])('mask should be applied config:(%s)', (_description, testCase) => {
            beforeEach(() => {
                var _a, _b;
                const element = createMockInputElement((_a = testCase.elementValue) !== null && _a !== void 0 ? _a : '');
                jest.spyOn(instance.el, 'querySelector').mockImplementation(() => element);
                instance.isHidden = false;
                instance.useComplexMaskLogic = testCase.useComplexMaskLogic;
                instance.hasFocus = testCase.hasFocus;
                instance.isCompleted = testCase.isCompleted;
                instance.completedValue = (_b = testCase.completedValue) !== null && _b !== void 0 ? _b : '';
                instance.componentDidRender();
            });
            it('should apply a text mask to the element', () => {
                expect(mockService.removeMaskFromElement).toHaveBeenCalled();
                expect(mockService.applyMaskToElement).toHaveBeenCalled();
                expect(mockService.createTextMaskInstance).toHaveBeenCalled();
            });
            it('should unset the mask update flag', () => {
                expect(instance.shouldUpdateMask).toEqual(false);
            });
        });
        describe('DOM reuse of input element when inputmask is not same', () => {
            beforeEach(() => {
                const element = createMockInputElement('');
                element.inputmask = {};
                jest.spyOn(instance.el, 'querySelector').mockImplementation(() => element);
                mockService.isElementMaskSame.mockReturnValue(false);
                instance.isHidden = false;
                instance.useComplexMaskLogic = false;
                instance.hasFocus = true;
                instance.isCompleted = false;
                instance.completedValue = '';
                instance.componentDidRender();
            });
            it('should apply a text mask to the element', () => {
                expect(mockService.removeMaskFromElement).toHaveBeenCalled();
                expect(mockService.applyMaskToElement).toHaveBeenCalled();
                expect(mockService.createTextMaskInstance).toHaveBeenCalled();
            });
            it('should unset the mask update flag', () => {
                expect(instance.shouldUpdateMask).toEqual(false);
            });
        });
        describe('DOM reuse of input element when inputmask is the same', () => {
            beforeEach(() => {
                const element = createMockInputElement('');
                element.inputmask = {};
                jest.spyOn(instance.el, 'querySelector').mockImplementation(() => element);
                mockService.isElementMaskSame.mockReturnValue(true);
                instance.isHidden = false;
                instance.useComplexMaskLogic = false;
                instance.hasFocus = true;
                instance.isCompleted = false;
                instance.completedValue = '';
                instance.componentDidRender();
            });
            it('should not apply a text mask to the element', () => {
                expect(mockService.removeMaskFromElement).not.toHaveBeenCalled();
                expect(mockService.applyMaskToElement).not.toHaveBeenCalled();
                expect(mockService.createTextMaskInstance).not.toHaveBeenCalled();
            });
            it('should unset the mask update flag', () => {
                expect(instance.shouldUpdateMask).toEqual(false);
            });
        });
    });
    describe('disconnectedCallback()', () => {
        let instance;
        let mockService;
        let mockInputMask;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            mockInputMask = createMockInputMask();
            mockService = {
                buildPlaceholderFromMaskConfig: jest.fn(() => ''),
                createDefaultMaskInstance: jest.fn(() => mockInputMask),
                createPasswordMaskInstance: jest.fn(() => mockInputMask),
                createTextMaskInstance: jest.fn(() => mockInputMask),
                applyMaskToElement: jest.fn(() => { }),
                removeMaskFromElement: jest.fn(() => { }),
                isElementMaskSame: jest.fn(() => true),
            };
            instance.service = mockService;
            instance.disconnectedCallback();
        });
        it('should remove mask from input', () => {
            expect(instance.service.removeMaskFromElement).toHaveBeenCalled();
        });
    });
    // Props
    describe('when the value prop changes', () => {
        let instance;
        const value = 'llama';
        describe('when the question is completed', () => {
            beforeEach(() => {
                instance = new BpSdkMaskedInput();
                instance.isCompleted = true;
                instance.shouldUpdateMask = false;
                instance.completedValue = '';
                instance.inputValue = '';
                instance.onValueChange(value);
            });
            it('should set the mask update flag', () => {
                expect(instance.shouldUpdateMask).toEqual(true);
            });
            it('should set the completed value', () => {
                expect(instance.completedValue).toEqual(value);
            });
            it('should set the input value', () => {
                expect(instance.inputValue).toEqual(value);
            });
        });
        describe('when the question is not completed', () => {
            beforeEach(() => {
                instance = new BpSdkMaskedInput();
                instance.isCompleted = false;
                instance.shouldUpdateMask = false;
                instance.completedValue = '';
                instance.inputValue = '';
                instance.onValueChange(value);
            });
            it('should set the mask update flag', () => {
                expect(instance.shouldUpdateMask).toEqual(true);
            });
            it('should not change the completed value', () => {
                expect(instance.completedValue).toEqual('');
            });
            it('should not change the input value', () => {
                expect(instance.inputValue).toEqual('');
            });
        });
    });
    describe('when the answer ID prop changes', () => {
        let instance;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.completedValue = 'llama';
            instance.inputValue = 'llama';
            instance.onAnswerIdChange();
        });
        it('should reset the completed value', () => {
            expect(instance.completedValue).toEqual('');
        });
        it('should reset the input value', () => {
            expect(instance.inputValue).toEqual('');
        });
    });
    describe('when the touched prop changes', () => {
        let instance;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.touched = true;
            instance._touched = false;
            instance.onTouchedChange();
        });
        it('should update the touched internal value', () => {
            expect(instance._touched).toEqual(true);
        });
    });
    describe('when the completed prop changes', () => {
        let instance;
        describe('when complex mask logic is set', () => {
            beforeEach(() => {
                instance = new BpSdkMaskedInput();
                instance.useComplexMaskLogic = true;
                instance.shouldUpdateMask = false;
                instance.onIsCompletedChange();
            });
            it('should set the mask update flag', () => {
                expect(instance.shouldUpdateMask).toEqual(true);
            });
        });
        describe('when complex mask logic is not set', () => {
            beforeEach(() => {
                instance = new BpSdkMaskedInput();
                instance.useComplexMaskLogic = false;
                instance.shouldUpdateMask = false;
                instance.onIsCompletedChange();
            });
            it('should not set the mask update flag', () => {
                expect(instance.shouldUpdateMask).toEqual(false);
            });
        });
    });
    describe('when the can hide prop changes', () => {
        let instance;
        const canHide = true;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.isHidden = false;
            instance.shouldUpdateMask = false;
            instance.onCanHideChange(canHide);
        });
        it('should set the mask update flag', () => {
            expect(instance.shouldUpdateMask).toEqual(true);
        });
        it('should set the hidden flag to the prop value', () => {
            expect(instance.isHidden).toEqual(canHide);
        });
    });
    describe('when the placeholder prop changes', () => {
        let instance;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.shouldUpdatePlaceholder = false;
            instance.onPlaceholderChange();
        });
        it('should set the placeholder update flag', () => {
            expect(instance.shouldUpdatePlaceholder).toEqual(true);
        });
    });
    describe('when the mask prop changes', () => {
        let instance;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.shouldUpdateMask = false;
            instance.shouldUpdatePlaceholder = false;
            instance.onMaskChange();
        });
        it('should set the mask update flag', () => {
            expect(instance.shouldUpdateMask).toEqual(true);
        });
        it('should set the placeholder update flag', () => {
            expect(instance.shouldUpdatePlaceholder).toEqual(true);
        });
    });
    describe('when the mask options prop changes', () => {
        let instance;
        const option1 = { prefix: '$' };
        const option2 = { prefix: '&' };
        describe.each([
            [
                'if the options are different',
                {
                    previous: option1,
                    next: option2,
                    shouldUpdateMask: true,
                    shouldUpdatePlaceholder: true,
                },
            ],
            [
                'if the options are the same',
                {
                    previous: option1,
                    next: option1,
                    shouldUpdateMask: false,
                    shouldUpdatePlaceholder: false,
                },
            ],
        ])('%s', (_description, testCase) => {
            beforeEach(() => {
                instance = new BpSdkMaskedInput();
                instance.shouldUpdateMask = false;
                instance.shouldUpdatePlaceholder = false;
                instance.onOptionsChange(testCase.next, testCase.previous);
            });
            it('should set the mask update flag', () => {
                expect(instance.shouldUpdateMask).toEqual(testCase.shouldUpdateMask);
            });
            it('should set the placeholder update flag', () => {
                expect(instance.shouldUpdatePlaceholder).toEqual(testCase.shouldUpdatePlaceholder);
            });
        });
    });
    describe('when the complex mask logic prop changes', () => {
        let instance;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.shouldUpdateMask = false;
            instance.onUseComplexMaskLogicChange();
        });
        it('should set the mask update flag', () => {
            expect(instance.shouldUpdateMask).toEqual(true);
        });
    });
    describe('when label props change', () => {
        let instance;
        const label = 'llama';
        const id = '123';
        const blankInput = '';
        const testCases = [
            [
                'if the label and id are defined',
                {
                    label: label,
                    id: id,
                    expected: `${id} ${label}`,
                },
            ],
            [
                'if the label is not defined',
                {
                    label: blankInput,
                    id: id,
                    expected: id,
                },
            ],
            [
                'if the id is not defined',
                {
                    label: label,
                    id: blankInput,
                    expected: label,
                },
            ],
            [
                'if neither the label nor the id is defined',
                {
                    label: blankInput,
                    id: blankInput,
                    expected: undefined,
                },
            ],
        ];
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
        });
        describe.each(testCases)('when the label id prop changes, %s', (_description, testCase) => {
            beforeEach(() => {
                instance.labelledBy = testCase.label;
                instance.onLabelIdChange(testCase.id);
            });
            it('should set the labelled by to the correct value', () => {
                expect(instance._labelledBy).toEqual(testCase.expected);
            });
        });
        describe.each(testCases)('when the labelled by prop changes, %s', (_description, testCase) => {
            beforeEach(() => {
                instance.labelId = testCase.id;
                instance.onLabelledByChange(testCase.label);
            });
            it('should set the labelled by to the correct value', () => {
                expect(instance._labelledBy).toEqual(testCase.expected);
            });
        });
    });
    // Events
    describe('when the visibility button is clicked', () => {
        let instance;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.isHidden = true;
            instance.shouldUpdateMask = false;
            instance.onToggleVisibilityButton();
        });
        it('should toggle the hidden flag', () => {
            expect(instance.isHidden).toEqual(false);
        });
        it('should set the mask update flag', () => {
            expect(instance.shouldUpdateMask).toEqual(true);
        });
    });
    describe('when the component receives focus', () => {
        let instance;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.shouldUpdateMask = false;
            instance.hasFocus = false;
            instance.onFocus();
        });
        it('should set the focus flag', () => {
            expect(instance.hasFocus).toEqual(true);
        });
        it('should set the mask update flag', () => {
            expect(instance.shouldUpdateMask).toEqual(true);
        });
    });
    describe('when the component loses focus', () => {
        let instance;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.shouldUpdateMask = false;
            instance.hasFocus = true;
            instance.onBlur();
        });
        it('should unset the focus flag', () => {
            expect(instance.hasFocus).toEqual(false);
        });
        it('should set the mask update flag', () => {
            expect(instance.shouldUpdateMask).toEqual(true);
        });
        it('should set the touched flag if the component is not pristine', () => {
            instance.pristine = false;
            instance._touched = false;
            instance.onBlur();
            expect(instance._touched).toEqual(true);
        });
    });
    describe('when autocomplete input is detected', () => {
        let instance;
        let spy;
        const value = 'llama';
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            instance.inputValue = '4321';
            spy = jest.spyOn(instance.valueUpdate, 'emit').mockImplementation();
            const event = createMockInputEvent(value);
            instance.onAutocompleteInput(event);
        });
        it('should emit an event', () => {
            expect(spy).toHaveBeenCalledWith(value);
        });
        it('should update the input value', () => {
            expect(instance.inputValue).toEqual(value);
        });
    });
    describe('when input changes', () => {
        let spy;
        let instance;
        beforeEach(() => {
            instance = new BpSdkMaskedInput();
            spy = jest.spyOn(instance.valueUpdate, 'emit').mockImplementation();
        });
        describe('if the value is a valid date', () => {
            const value = '11/27/1972';
            beforeEach(() => {
                instance.fieldType = 'date';
                const event = createMockInputEvent(value);
                instance.onInput(event);
            });
            it('should emit an event', () => {
                expect(spy).toHaveBeenCalledWith(new Date(value).toISOString());
            });
            it('should update the input value', () => {
                expect(instance.inputValue).toEqual(value);
            });
        });
        describe.each(['**/**/****', undefined])('if the value is an invalid date (%s)', (date) => {
            beforeEach(() => {
                instance.fieldType = 'date';
                const event = createMockInputEvent(date);
                instance.onInput(event);
            });
            it('should not emit an event', () => {
                expect(spy).not.toHaveBeenCalled();
            });
            it('should set the input value to empty string', () => {
                expect(instance.inputValue).toEqual('');
            });
        });
        describe('if the new and current values are undefined', () => {
            const value = undefined;
            beforeEach(() => {
                instance.value = undefined;
                const event = createMockInputEvent(value);
                instance.onInput(event);
            });
            it('should not emit an event', () => {
                expect(spy).not.toHaveBeenCalled();
            });
            it('should not change the input value', () => {
                expect(instance.inputValue).toEqual('');
            });
        });
        describe('if the new value is undefined, but the current saved value has value', () => {
            const value = '';
            beforeEach(() => {
                instance.inputValue = 'llama!';
                instance.value = 'llama!';
                const event = createMockInputEvent(value);
                instance.onInput(event);
            });
            it('should emit an event', () => {
                expect(spy).toHaveBeenCalled();
            });
            it('should change the input value', () => {
                expect(instance.inputValue).toEqual('');
            });
        });
        describe('if the value is unchanged from the current value', () => {
            const value = '1234';
            beforeEach(() => {
                instance.inputValue = value;
                const event = createMockInputEvent(value);
                instance.onInput(event);
            });
            it('should not emit an event', () => {
                expect(spy).not.toHaveBeenCalled();
            });
        });
        describe('if the value is different from the current value', () => {
            const value = '1234';
            beforeEach(() => {
                instance.inputValue = '4321';
                const event = createMockInputEvent(value);
                instance.onInput(event);
            });
            it('should emit an event', () => {
                expect(spy).toHaveBeenCalledWith(value);
            });
            it('should update the input value', () => {
                expect(instance.inputValue).toEqual(value);
            });
        });
        describe('if the value is 0', () => {
            const value = '0';
            beforeEach(() => {
                instance.inputValue = '1234';
                const event = createMockInputEvent(value);
                instance.onInput(event);
            });
            it('should emit an event', () => {
                expect(spy).toHaveBeenCalledWith(value);
            });
            it('should update the input value', () => {
                expect(instance.inputValue).toEqual(value);
            });
        });
    });
});
