import { IUiInput, UiInput } from './ui-input';
import { UiInputOptions } from './ui-input-options';

describe('UiInput', () => {
  const testData: IUiInput = {
    key: 'qs',
    placeholder: 'ISBN/EAN, Titel, Kundenname',
    type: 1,
    constraint: '^.{2,100}$',
    options: { values: [], max: 1 },
    target: 'target',
    label: 'label',
    description: 'description',
    maxValue: '4',
    minValue: '2',
    selected: false,
  };

  let uiInput: UiInput;

  beforeEach(() => {
    spyOn(UiInputOptions, 'create');
    uiInput = UiInput.create(testData);
  });

  describe('setValue(value: string, { emitEvent } = { emitEvent: true })', () => {
    it('should set the property value and calls changes.next with the value', () => {
      spyOn(uiInput.changes, 'next');
      uiInput.setValue('value test');
      expect(uiInput.value).toEqual('value test');
      expect(uiInput.changes.next).toHaveBeenCalledWith({ keys: ['value'], target: uiInput });
    });

    it('should set the property value and calls changes.next with the value when emitEvent is true', () => {
      spyOn(uiInput.changes, 'next');
      uiInput.setValue('value test', { emitEvent: true });
      expect(uiInput.value).toEqual('value test');
      expect(uiInput.changes.next).toHaveBeenCalledWith({ keys: ['value'], target: uiInput });
    });

    it('should set the property value and not calls changes.next with the value when emitEvent is false', () => {
      spyOn(uiInput.changes, 'next');
      uiInput.setValue('value test', { emitEvent: false });
      expect(uiInput.value).toEqual('value test');
      expect(uiInput.changes.next).not.toHaveBeenCalled();
    });

    it('should not call changes.next if the value is equal', () => {
      uiInput.setValue('value test');
      spyOn(uiInput.changes, 'next');
      uiInput.setValue('value test', { emitEvent: true });
      expect(uiInput.value).toEqual('value test');
      expect(uiInput.changes.next).not.toHaveBeenCalled();
    });
  });

  describe('setSelected(value: boolean, { emitEvent } = { emitEvent: true })', () => {
    it('should set selected to true and calls changes.next when no option is provided', () => {
      spyOn(uiInput.changes, 'next');
      uiInput.setSelected(true);
      expect(uiInput.selected).toBe(true);
      expect(uiInput.changes.next).toHaveBeenCalledWith({ keys: ['selected'], target: uiInput });
    });

    it('should not call changes.next if value is the same', () => {
      uiInput.setSelected(true);
      spyOn(uiInput.changes, 'next');
      uiInput.setSelected(true);
      expect(uiInput.changes.next).not.toHaveBeenCalledWith({ keys: ['selected'], target: uiInput });
    });

    it('should call changes.next if option emitEvent is true', () => {
      spyOn(uiInput.changes, 'next');
      uiInput.setSelected(true, { emitEvent: true });
      expect(uiInput.changes.next).toHaveBeenCalledWith({ keys: ['selected'], target: uiInput });
    });

    it('should not call changes.next if option emitEvent is false', () => {
      spyOn(uiInput.changes, 'next');
      uiInput.setSelected(true, { emitEvent: false });
      expect(uiInput.changes.next).not.toHaveBeenCalledWith({ keys: ['selected'], target: uiInput });
    });
  });

  describe('static create(inputOptions: IUiInputDTO)', () => {
    it('should return an instance of UiInputDTO', () => {
      expect(uiInput instanceof UiInput).toBe(true);
      expect(uiInput.constraint).toBe(testData.constraint);
      expect(uiInput.description).toBe(testData.description);
      expect(uiInput.key).toBe(testData.key);
      expect(uiInput.label).toBe(testData.label);
      expect(uiInput.maxValue).toBe(testData.maxValue);
      expect(uiInput.minValue).toBe(testData.minValue);
      expect(UiInputOptions.create).toHaveBeenCalledWith(testData.options, uiInput);
      expect(uiInput.placeholder).toBe(testData.placeholder);
      expect(uiInput.target).toBe(testData.target);
      expect(uiInput.type).toBe(testData.type);
      expect(uiInput.value).toBe(testData.value);
      expect(uiInput.selected).toBe(testData.selected);
    });
  });
});
