import commonModule from '../..';

describe('wsCurrency directive', () => {
  let $compile;
  let outerScope;
  let element;
  let elementWrapper;

  beforeEach(angular.mock.module(commonModule));
  beforeEach(angular.mock.inject((_$compile_, $rootScope) => {
    $compile = _$compile_;
    outerScope = $rootScope.$new();
  }));

  function injectElement(elementHtml, scopeValues = {}) {
    element = angular.element(elementHtml);

    $compile(element)(Object.assign(outerScope, scopeValues));

    outerScope.$digest();
    elementWrapper = element.parent();
  }

  it('outputs the model as a float', () => {
    injectElement('<input ws-currency ng-model="value">', { value: 0 });
    element.val('123.45');
    element[0].dispatchEvent(new Event('input'));

    expect(element.scope().value).toEqual(123.45);
  });

  it('defaults to $ with no symbol set', () => {
    injectElement('<input ws-currency >');
    expect(elementWrapper.html()).toContain('$');
  });

  it('uses the provided symbol when set', () => {
    injectElement('<input ws-currency="{symbol: \'💩\'}" ng-model="value">', { value: 0 });

    expect(elementWrapper.html()).toContain('💩');
    expect(element.val()).toContain('0.00');
  });

  it('trims trailing decimals with fractional cents value', () => {
    injectElement('<input ws-currency ng-model="value">', { value: '123.4567' });

    expect(elementWrapper.html()).toContain('$');
    expect(element.val()).toEqual('123.45');
  });

  it('defaults to zero when given non-numeric value', () => {
    injectElement('<input ws-currency ng-model="value">', { value: 'foo' });

    expect(elementWrapper.html()).toContain('$');
    expect(element.val()).toEqual('0.00');
  });

  it('defaults to zero when given empty string', () => {
    injectElement('<input ws-currency value="">');

    expect(elementWrapper.html()).toContain('$');
    expect(element.val()).toEqual('0.00');
  });

  it('defaults to zero when no value is given', () => {
    injectElement('<input ws-currency>');

    expect(element.val()).toContain('0.00');
  });

  it('trims leading zeros', () => {
    injectElement('<input ws-currency ng-model="value">', { value: '000123' });

    expect(elementWrapper.html()).toContain('$');
    expect(element.val()).toEqual('123.00');
  });

  describe('custom validation', () => {
    it('should apply parent validation to nested input and report back to parent', () => {
      injectElement('<form name="form"><input ws-currency="{integer:true}" name="currency" ng-model="value" maxlength="4"/></form>', { value: 123 });

      expect(outerScope.form.$valid).toBeTruthy();

      const input = element.find('input');
      input.val('12345');
      input[0].dispatchEvent(new Event('input'));
      outerScope.$apply();

      expect(outerScope.form.$invalid).toBeTruthy();
    });
  });

  describe('with clearOnInitialFocus attribute set', () => {
    beforeEach(() => {
      injectElement('<input ws-currency="{clearOnInitialFocus: true}" ng-model="value">', { value: '123.45' });
    });

    it('should contain the initial value while pristine', () => {
      expect(element.val()).toEqual('123.45');
    });

    it('resets the value once focused', () => {
      element.triggerHandler('focus');
      expect(element.val()).toEqual('');
    });

    it('does not reset the value on subsequent focuses', () => {
      element.triggerHandler('focus');
      element.val('543.21');
      element.triggerHandler('focus');

      expect(element.val()).toEqual('543.21');
    });
  });

  describe('with autogrow attribute set', () => {
    beforeEach(() => {
      injectElement('<input ws-currency="{autogrow: true, integer: true}" ng-model="value">', { value: 122 });
    });

    it('should contain the initial value', () => {
      expect(element.val()).toEqual('122');
    });

    it('should update the model when the input value is changed', () => {
      element.val('12345');
      element[0].dispatchEvent(new Event('input'));
      outerScope.$apply();
      expect(outerScope.value).toEqual(12345);
    });
  });

  describe('with min and max attributes set', () => {
    it('should contain the maximum when the value was set to be higher', () => {
      injectElement('<input ws-currency="{min: 1, max: 10}" ng-model="value">', { value: 122 });
      expect(element.val()).toEqual('10.00');
    });

    it('should contain the minimum when the value was set to be lower', () => {
      injectElement('<input ws-currency="{min: 1, max: 10}" ng-model="value">', { value: 0 });
      expect(element.val()).toEqual('1.00');
    });

    it('doesn\'t break when a joker uses non-numeric values', () => {
      injectElement('<input ws-currency="{min: \'1\', max: \'true\'}" ng-model="value">', { value: 6 });
      expect(element.val()).toEqual('6.00');
    });
  });
});
