/**
 * Copyright (C) 2022 Robert Bosch GmbH Copyright (C) 2022 Robert Bosch Manufacturing Solutions GmbH, Germany. All rights reserved.
 */
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatIconModule } from '@angular/material/icon';
import { RouterTestingModule } from '@angular/router/testing';

import { BciSelectComponent } from './bci-select.component';

describe('BciSelectComponent', () => {
  let component: BciSelectComponent;
  let fixture: ComponentFixture<BciSelectComponent>;
  let el: HTMLElement;

  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule, MatIconModule, MatCheckboxModule],
      declarations: [BciSelectComponent],
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(BciSelectComponent);
    component = fixture.componentInstance;
    el = fixture.nativeElement as HTMLElement;
    fixture.detectChanges();
  });

  it('should create the component', () => {
    expect(component).toBeTruthy();
  });

  describe('input variable', () => {
    it('width should be 192px per default', () => {
      expect(component.width).toEqual('192px');
    });
    it('shouldScrollOptions should be false per default', () => {
      expect(component.shouldScrollOptions).toEqual(false);
    });
    it('shouldScrollValue should be false per default', () => {
      expect(component.shouldScrollValue).toEqual(false);
    });
    it('disabled should be false per default', () => {
      expect(component.disabled).toEqual(false);
    });
    it('required should be false per default', () => {
      expect(component.required).toEqual(false);
    });
    it('multiple should be false per default', () => {
      expect(component.multiple).toEqual(false);
    });
    it('placeholder should be Placeholder per default', () => {
      expect(component.required).toEqual(false);
    });
    it('label should be Label per default', () => {
      expect(component.multiple).toEqual(false);
    });
  });

  describe('input variable', () => {
    beforeEach(() => {
      component.placeholder = 'MyFancyPlaceholder';
      component.label = 'MyFancyLabel';
      fixture.detectChanges();
    });

    it('placeholder should be set correct', () => {
      expect(component.placeholder).toEqual('MyFancyPlaceholder');
    });
    it('label should be set correct', () => {
      expect(component.label).toEqual('MyFancyLabel');
    });
  });

  describe('opens correctly', () => {
    // Might rather be done with e2e-Tests
    it('should open when clicking the select trigger', () => {
      const event = new Event('click');
      expect(component.panel).toBeFalsy();
      expect(component.panelOpen).toBe(false);
      el.querySelector('.bci-select-trigger').dispatchEvent(event);
      expect(component.panel).toBeTruthy();
      expect(component.panelOpen).toBe(true);
    });
  });

  it('should display a "*" in the label when required', () => {
    component.required = true;
    fixture.detectChanges();
    expect(el.querySelector('.bci-select-trigger-label').classList).toContain('withRequiredMark');
  });

  describe('toggle', () => {
    it('should call open if its closed', () => {
      component._panelOpen = false;
      fixture.detectChanges();
      const spy = jest.spyOn(component, 'open');
      component.toggle();
      expect(spy).toHaveBeenCalled();
    });
    it('should call close if its opened', () => {
      component._panelOpen = true;
      fixture.detectChanges();
      const spy = jest.spyOn(component, 'close');
      component.toggle();
      expect(spy).toHaveBeenCalled();
    });
  });
  
  describe('open', () => {
    /* These two tests would work if _findOverflowingOptions was a public function */
    // it('should find overflowing options when opening the panel', () => {
    //   component.shouldScrollOptions = true;
    //   fixture.detectChanges();
    //   const spy = jest.spyOn(component, '_findOverflowingOptions');
    //   component.toggle();
    //   expect(spy).toHaveBeenCalled();
    // });
    // it('should not find overflowing options when opening the panel', () => {
    //   const spy = jest.spyOn(component, '_findOverflowingOptions');
    //   component.toggle();
    //   expect(spy).toBeCalledTimes(0);
    // });

    it('should initialize the keyboard selected option when opening the panel', () => {
      const spy = jest.spyOn(component, 'initActiveOption');
      component.toggle();
      expect(spy).toHaveBeenCalled();
    });
  });

  describe('close', () => {
    it('should focus the trigger element after closing the panel', () => {
      component._panelOpen = true;
      fixture.detectChanges();
      component.close();
      expect(document.activeElement).toBe(component.trigger.nativeElement)
    });
  });
});
