jest.mock('@ngx-translate/core');

import { ComponentFixture, TestBed, waitForAsync, inject, tick, fakeAsync } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { FormBuilder } from '@angular/forms';
import { of, throwError } from 'rxjs';
import { TranslateService } from '@ngx-translate/core';

import { EMAIL_ALREADY_USED_TYPE, LOGIN_ALREADY_USED_TYPE } from 'app/config/error.constants';

import { RegisterService } from 'app/account/register/register.service';
import { UsuarioExtraUpdateComponent } from './usuario-extra-update.component';

describe('Component Tests', () => {
  describe('RegisterComponent', () => {
    let fixture: ComponentFixture<UsuarioExtraUpdateComponent>;
    let comp: UsuarioExtraUpdateComponent;

    beforeEach(
      waitForAsync(() => {
        TestBed.configureTestingModule({
          imports: [HttpClientTestingModule],
          declarations: [UsuarioExtraUpdateComponent],
          providers: [FormBuilder, TranslateService],
        })
          .overrideTemplate(UsuarioExtraUpdateComponent, '')
          .compileComponents();
      })
    );

    beforeEach(() => {
      fixture = TestBed.createComponent(UsuarioExtraUpdateComponent);
      comp = fixture.componentInstance;
    });

    it('should ensure the two passwords entered match', () => {
      comp.registerForm.patchValue({
        password: 'password',
        confirmPassword: 'non-matching',
      });

      comp.register();

      expect(comp.doNotMatch).toBe(true);
    });

    it('should update success to true after creating an account', inject(
      [RegisterService, TranslateService],
      fakeAsync((service: RegisterService, mockLanguageService: TranslateService) => {
        jest.spyOn(service, 'save').mockReturnValue(of({}));
        mockLanguageService.currentLang = 'es';
        comp.registerForm.patchValue({
          password: 'password',
          confirmPassword: 'password',
        });

        comp.register();
        tick();

        expect(service.save).toHaveBeenCalledWith({
          email: '',
          password: 'password',
          login: '',
          langKey: 'es',
          name: '',
          firstName: 'userNormal',
          profileIcon: 1,
          isAdmin: 1,
          isGoogle: 0,
        });
        expect(comp.success).toBe(true);
        expect(comp.errorUserExists).toBe(false);
        expect(comp.errorEmailExists).toBe(false);
        expect(comp.error).toBe(false);
      })
    ));

    it('should notify of user existence upon 400/login already in use', inject(
      [RegisterService],
      fakeAsync((service: RegisterService) => {
        jest.spyOn(service, 'save').mockReturnValue(
          throwError({
            status: 400,
            error: { type: LOGIN_ALREADY_USED_TYPE },
          })
        );
        comp.registerForm.patchValue({
          password: 'password',
          confirmPassword: 'password',
        });

        comp.register();
        tick();

        expect(comp.errorUserExists).toBe(true);
        expect(comp.errorEmailExists).toBe(false);
        expect(comp.error).toBe(false);
      })
    ));

    it('should notify of email existence upon 400/email address already in use', inject(
      [RegisterService],
      fakeAsync((service: RegisterService) => {
        jest.spyOn(service, 'save').mockReturnValue(
          throwError({
            status: 400,
            error: { type: EMAIL_ALREADY_USED_TYPE },
          })
        );
        comp.registerForm.patchValue({
          password: 'password',
          confirmPassword: 'password',
        });

        comp.register();
        tick();

        expect(comp.errorEmailExists).toBe(true);
        expect(comp.errorUserExists).toBe(false);
        expect(comp.error).toBe(false);
      })
    ));

    it('should notify of generic error', inject(
      [RegisterService],
      fakeAsync((service: RegisterService) => {
        jest.spyOn(service, 'save').mockReturnValue(
          throwError({
            status: 503,
          })
        );
        comp.registerForm.patchValue({
          password: 'password',
          confirmPassword: 'password',
        });

        comp.register();
        tick();

        expect(comp.errorUserExists).toBe(false);
        expect(comp.errorEmailExists).toBe(false);
        expect(comp.error).toBe(true);
      })
    ));
  });
});
