import { newSpecPage } from "@stencil/core/testing";
import { BpSdkDateInput } from "./bp-sdk-date-input";
describe('bp-sdk-date-input', () => {
    describe('renders', () => {
        it('vanilla', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-date-input placeholder="Date"></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            const instance = page.rootInstance;
            instance.labelId = 'aria';
            instance.labelledBy = 'label';
            await page.waitForChanges();
            const input = page.root.querySelector('input');
            expect(input.tagName).toEqual('INPUT');
            expect(input.type).toEqual('date');
            expect(input.getAttribute('aria-labelledby')).toEqual('label aria');
        });
        it('renders external component if defined', async () => {
            const whenDefinedMock = jest.spyOn(customElements, 'whenDefined').mockResolvedValueOnce({});
            const page = await newSpecPage({
                html: '<bp-sdk-date-input></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            await page.waitForChanges();
            const element = page.root.querySelector('div');
            expect(element).toBeFalsy();
            whenDefinedMock.mockRestore();
        });
        it('calendar can be themed', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-date-input placeholder="Date"></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            const instance = page.rootInstance;
            const themeSpy = jest.fn();
            jest.spyOn(instance.el, 'querySelector').mockImplementation(() => ({
                _setTheme: themeSpy,
            }));
            await page.waitForChanges();
            instance.componentDidLoad();
            expect(instance.el.querySelector).toHaveBeenCalledTimes(1);
            expect(themeSpy).toHaveBeenCalledWith('calendar');
            expect(themeSpy).toHaveBeenCalledTimes(1);
        });
        it('displays errors', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-date-input></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            const instance = page.rootInstance;
            instance.errors = ['Error message'];
            instance.touched = true;
            instance.pristine = false;
            await page.waitForChanges();
            expect(page.root.querySelectorAll('bp-sdk-errors-container').length).toBe(1);
        });
        it('displays errors if completed', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-date-input></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            const instance = page.rootInstance;
            instance.errors = ['Error message'];
            instance.touched = true;
            instance.pristine = false;
            instance.isCompleted = true;
            await page.waitForChanges();
            expect(page.root.querySelectorAll('bp-sdk-errors-container').length).toBe(1);
        });
        it('displays error text', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-date-input></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            const instance = page.rootInstance;
            instance.errorText = 'Error message';
            instance.touched = true;
            instance.pristine = false;
            await page.waitForChanges();
            expect(page.root.querySelectorAll('bp-sdk-errors-container').length).toBe(1);
        });
        it('hides error text if completed', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-date-input></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            const instance = page.rootInstance;
            instance.errorText = 'Error message';
            instance.touched = true;
            instance.pristine = false;
            instance.isCompleted = true;
            await page.waitForChanges();
            expect(page.root.querySelectorAll('bp-sdk-errors-container').length).toBe(0);
        });
        it("doesn't error out of element is missing", async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-date-input placeholder="Date"></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            const instance = page.rootInstance;
            jest.spyOn(instance.el, 'querySelector').mockImplementation(() => null);
            await page.waitForChanges();
            instance.componentDidLoad();
            expect(instance.el.querySelector).toHaveBeenCalledTimes(1);
        });
        it('handles null errors', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-date-input></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            const instance = page.rootInstance;
            instance.errors = null;
            instance.touched = true;
            instance.pristine = false;
            await page.waitForChanges();
            expect(page.root.querySelectorAll('bp-sdk-errors-container').length).toBe(0);
        });
    });
    it('should update state value if prop _value changes', async () => {
        const page = await newSpecPage({
            html: '<bp-sdk-date-input placeholder="Date"></bp-sdk-date-input>',
            components: [BpSdkDateInput],
        });
        const instance = page.rootInstance;
        const value = '2010-10-10';
        instance.value = value;
        await page.waitForChanges();
        expect(instance._value).toEqual(value);
        instance.onValueChange(value);
        expect(instance._value).toEqual(value);
        const newValue = '2010-01-01';
        instance.onValueChange(newValue);
        expect(instance._value).toEqual(newValue);
    });
    describe('when the component is marked as read only', () => {
        const value = '2010-10-10';
        let page;
        let instance;
        beforeEach(async () => {
            page = await newSpecPage({
                html: '<bp-sdk-date-input placeholder="Date"></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            instance = page.rootInstance;
            instance.isReadOnly = true;
            instance.value = 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);
        });
    });
    describe('onChange', () => {
        it('can change date', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-date-input placeholder="Date"></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            await page.waitForChanges();
            const instance = page.rootInstance;
            const value = '2010-10-10';
            const event = new Event('change');
            event.target = {
                value,
            };
            expect(instance._value).toBeUndefined();
            instance.onChange(event);
            expect(instance._value).toEqual(value);
        });
        it('disables on useExternal', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-date-input placeholder="Date"></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            await page.waitForChanges();
            const instance = page.rootInstance;
            instance.useExternal = true;
            const value = '2010-10-10';
            const event = new Event('change');
            event.target = {
                value,
            };
            expect(instance._value).toBeUndefined();
            instance.onChange(event);
            expect(instance._value).toBeUndefined();
        });
        it('emits expected event', async () => {
            const page = await newSpecPage({
                html: '<bp-sdk-date-input placeholder="Date"></bp-sdk-date-input>',
                components: [BpSdkDateInput],
            });
            const instance = page.rootInstance;
            const value = '2010-10-10';
            const oldValue = '2010-01-01';
            jest.spyOn(instance.valueUpdate, 'emit');
            await page.waitForChanges();
            instance.value = oldValue;
            const event = new Event('change');
            event.target = {
                value,
            };
            instance.onChange(event);
            expect(instance.valueUpdate.emit).toHaveBeenCalledWith(new Date(value).toISOString());
            expect(instance.valueUpdate.emit).toHaveBeenCalledTimes(1);
            instance.value = value;
            // only does if values are mismatch
            instance.onChange(event);
            expect(instance.valueUpdate.emit).toHaveBeenCalledWith(new Date(value).toISOString());
            expect(instance.valueUpdate.emit).toHaveBeenCalledTimes(1);
        });
    });
});
