Angular 带测试的角谷歌符号

Angular 带测试的角谷歌符号,angular,jasmine,karma-runner,google-authentication,Angular,Jasmine,Karma Runner,Google Authentication,我在模拟gauth的attachClickHandler函数时遇到问题。下面是我的代码。我无法在成功和失败回调时模拟attachClickHander。因此,无法测试prepareLoginButton方法 export class GoogleSignInButtonComponent implements OnInit { auth2: any; constructor( private socialSignInController: SocialSignInContro

我在模拟gauth的attachClickHandler函数时遇到问题。下面是我的代码。我无法在成功和失败回调时模拟attachClickHander。因此,无法测试prepareLoginButton方法

export class GoogleSignInButtonComponent implements OnInit {

  auth2: any;

  constructor(
    private socialSignInController: SocialSignInControllerService,
    private ngZone: NgZone,
    private toastr: ToastrService,
    private authenticationService: AuthenticationService) { }

  ngOnInit(): void {
    this.googleSDK();
  }
  googleSDK() {

    window['googleSDKLoaded'] = () => {
      window['gapi'].load('auth2', () => {
        this.auth2 = window['gapi'].auth2.init({
          client_id: environment.social.google.clientId,
          cookiepolicy: 'single_host_origin',
          scope: 'profile email'
        });
        this.prepareLoginButton();
      });
    }

    (function (d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) { return; }
      js = d.createElement(s); js.id = id;
      js.src = "https://apis.google.com/js/platform.js?onload=googleSDKLoaded";
      fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'google-jssdk'));

  }

   prepareLoginButton() {
    this.auth2.attachClickHandler(document.getElementById('googleBtn'), {},
      (googleUser) => {
        this.ngZone.run(() => {
          const token = googleUser.getAuthResponse().id_token;
          this.socialSignInController.googleTokenSignIn(token).subscribe(res => {
            this.authenticationService.onSocialLoginSuccess(res.token);
            window.location.href = '/dashboard'
          });
        }, (error) => {
          this.toastr.error('An error occurred. Please try again', 'Could not sign you in')
          console.log(error);
        });
      })

  }

}

目标是实现谷歌登录。代码需要100%的测试。因为模仿auth2 attachClickHandler成功函数很困难,所以我删除了它并使用了一个库angularx社交登录

我创建了一个CustomHRefService,因为router.navigate在promise then函数中不起作用。我后来发现,将承诺包装成可观察性解决了这一问题

代码和测试如下所示:

按钮html

<a #googlebtn (click)="signInWithGoogle()" class="social_bt google" id="googleBtn">Login with google</a>
按钮测试

import { async, ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing';

import { GoogleBtnComponent } from './google-btn.component';
import { provideConfig } from '../authentication.module';
import { AuthenticationServiceImpl } from 'src/app/services/authentication.service';
import { AuthService, AuthServiceConfig, SocialUser } from 'angularx-social-login';
import { of } from 'rxjs';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { ToastrModule } from 'ngx-toastr';
import { CustomHrefService } from 'src/app/services/custom-href.service';
import { WindowToken } from 'src/app/injector/window';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';

const MockWindow = {
  location: {
    _href: '',
    set href(url: string) { this._href = url },
    get href() { return this._href }
  }
};

describe('GoogleBtnComponent', () => {
  let component: GoogleBtnComponent;
  let fixture: ComponentFixture<GoogleBtnComponent>;
  let authService: AuthService;
  let socialSignInService: SocialSignInControllerService;
  let socialSignInSpy: jasmine.Spy;
  let authSpy: jasmine.Spy;
  let service: CustomHrefService;
  let setHrefSpy: jasmine.Spy;

  beforeEach(async(() => {

    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule,
        RouterTestingModule.withRoutes([{ path: 'dashboard', component: DummyComponent }]),
        ToastrModule.forRoot(),
        TranslateModule.forRoot({
          loader: {
            provide: TranslateLoader,
            useValue: new FakeLoader()
          }
        }),
      ],

      declarations: [GoogleBtnComponent],
      providers: [{
        provide: AuthenticationService,
        useClass: AuthenticationServiceImpl,
      }, AuthService, { provide: AuthServiceConfig, useFactory: provideConfig },
      { provide: CustomHrefService, useClass: CustomHrefService, deps: [WindowToken]},
      { provide: WindowToken, useValue: MockWindow }]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    //mock response
    socialSignInService = TestBed.get(SocialSignInControllerService);
    service = TestBed.get(CustomHrefService);
    authService = TestBed.get(AuthService);
    socialSignInSpy = spyOn(socialSignInService, "googleTokenSignIn").and.returnValue(of({ token: '2323' } as any))
    setHrefSpy = spyOnProperty(MockWindow.location, 'href', 'set');
    const googleUser: SocialUser = {
      name: 'godwin', firstName: 'ish',
      lastName: 'dako', idToken: '1009',
      provider: 'google',
      id: '2', email: 'noone@gmail.com',
      photoUrl: 'null',
      authToken: '2323', authorizationCode: '232'
    };
    authSpy = spyOn(authService, 'signIn').and.returnValue(Promise.resolve(googleUser));
    fixture = TestBed.createComponent(GoogleBtnComponent);
    authService = TestBed.get(AuthService);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

  it('should sign with google', fakeAsync(() => {
    component.signInWithGoogle();
    fixture.detectChanges();
    tick(3);
    expect(setHrefSpy).toHaveBeenCalledWith('/dashboard');
  }))


});
import { TestBed } from '@angular/core/testing';

import { CustomHrefService } from './custom-href.service';
import { Injector } from '@angular/core';
import { WindowToken } from '../injector/window';
import { AuthenticationModule } from '../modules/authentication/authentication.module';

const MockWindow = {
  location: {
    _href: '',
    set href(url: string) { this._href = url },
    get href() { return this._href }
  }
};

describe('CustomHrefService', () => {
  let service: CustomHrefService;
  let setHrefSpy: jasmine.Spy;


  beforeEach(() => {
    setHrefSpy = spyOnProperty(MockWindow.location, 'href', 'set');
    const injector = Injector.create({
      providers: [
        { provide: CustomHrefService, useClass: CustomHrefService, deps: [WindowToken]},
        { provide: WindowToken, useValue: MockWindow}
      ]
    });
    service = injector.get(CustomHrefService);
  });

  it('should be registered on the AppModule', () => {
    service = TestBed.configureTestingModule({ imports: [AuthenticationModule] }).get(CustomHrefService);
    expect(service).toEqual(jasmine.any(CustomHrefService));
  });

  describe('#jumpTo', () => {
    it('should modify window.location.href', () => {
      const url = 'http://localhost:8080';
      service.jumpTo(url);
      expect(setHrefSpy).toHaveBeenCalledWith(url);
    });
  });
});
WindowToken

import { InjectionToken } from '@angular/core';

export const WindowToken = new InjectionToken('Window');
export function windowProvider() { return window; }
@NgModule({
  declarations: [
    //components],
  imports: [
    //other modules
  ],
  providers: [{
    { provide: WindowToken, useFactory: windowProvider }
  ]
})
export class AuthenticationModule { }
使用InjectionToken

import { InjectionToken } from '@angular/core';

export const WindowToken = new InjectionToken('Window');
export function windowProvider() { return window; }
@NgModule({
  declarations: [
    //components],
  imports: [
    //other modules
  ],
  providers: [{
    { provide: WindowToken, useFactory: windowProvider }
  ]
})
export class AuthenticationModule { }
客户HREF服务测试

import { async, ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing';

import { GoogleBtnComponent } from './google-btn.component';
import { provideConfig } from '../authentication.module';
import { AuthenticationServiceImpl } from 'src/app/services/authentication.service';
import { AuthService, AuthServiceConfig, SocialUser } from 'angularx-social-login';
import { of } from 'rxjs';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { ToastrModule } from 'ngx-toastr';
import { CustomHrefService } from 'src/app/services/custom-href.service';
import { WindowToken } from 'src/app/injector/window';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';

const MockWindow = {
  location: {
    _href: '',
    set href(url: string) { this._href = url },
    get href() { return this._href }
  }
};

describe('GoogleBtnComponent', () => {
  let component: GoogleBtnComponent;
  let fixture: ComponentFixture<GoogleBtnComponent>;
  let authService: AuthService;
  let socialSignInService: SocialSignInControllerService;
  let socialSignInSpy: jasmine.Spy;
  let authSpy: jasmine.Spy;
  let service: CustomHrefService;
  let setHrefSpy: jasmine.Spy;

  beforeEach(async(() => {

    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule,
        RouterTestingModule.withRoutes([{ path: 'dashboard', component: DummyComponent }]),
        ToastrModule.forRoot(),
        TranslateModule.forRoot({
          loader: {
            provide: TranslateLoader,
            useValue: new FakeLoader()
          }
        }),
      ],

      declarations: [GoogleBtnComponent],
      providers: [{
        provide: AuthenticationService,
        useClass: AuthenticationServiceImpl,
      }, AuthService, { provide: AuthServiceConfig, useFactory: provideConfig },
      { provide: CustomHrefService, useClass: CustomHrefService, deps: [WindowToken]},
      { provide: WindowToken, useValue: MockWindow }]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    //mock response
    socialSignInService = TestBed.get(SocialSignInControllerService);
    service = TestBed.get(CustomHrefService);
    authService = TestBed.get(AuthService);
    socialSignInSpy = spyOn(socialSignInService, "googleTokenSignIn").and.returnValue(of({ token: '2323' } as any))
    setHrefSpy = spyOnProperty(MockWindow.location, 'href', 'set');
    const googleUser: SocialUser = {
      name: 'godwin', firstName: 'ish',
      lastName: 'dako', idToken: '1009',
      provider: 'google',
      id: '2', email: 'noone@gmail.com',
      photoUrl: 'null',
      authToken: '2323', authorizationCode: '232'
    };
    authSpy = spyOn(authService, 'signIn').and.returnValue(Promise.resolve(googleUser));
    fixture = TestBed.createComponent(GoogleBtnComponent);
    authService = TestBed.get(AuthService);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

  it('should sign with google', fakeAsync(() => {
    component.signInWithGoogle();
    fixture.detectChanges();
    tick(3);
    expect(setHrefSpy).toHaveBeenCalledWith('/dashboard');
  }))


});
import { TestBed } from '@angular/core/testing';

import { CustomHrefService } from './custom-href.service';
import { Injector } from '@angular/core';
import { WindowToken } from '../injector/window';
import { AuthenticationModule } from '../modules/authentication/authentication.module';

const MockWindow = {
  location: {
    _href: '',
    set href(url: string) { this._href = url },
    get href() { return this._href }
  }
};

describe('CustomHrefService', () => {
  let service: CustomHrefService;
  let setHrefSpy: jasmine.Spy;


  beforeEach(() => {
    setHrefSpy = spyOnProperty(MockWindow.location, 'href', 'set');
    const injector = Injector.create({
      providers: [
        { provide: CustomHrefService, useClass: CustomHrefService, deps: [WindowToken]},
        { provide: WindowToken, useValue: MockWindow}
      ]
    });
    service = injector.get(CustomHrefService);
  });

  it('should be registered on the AppModule', () => {
    service = TestBed.configureTestingModule({ imports: [AuthenticationModule] }).get(CustomHrefService);
    expect(service).toEqual(jasmine.any(CustomHrefService));
  });

  describe('#jumpTo', () => {
    it('should modify window.location.href', () => {
      const url = 'http://localhost:8080';
      service.jumpTo(url);
      expect(setHrefSpy).toHaveBeenCalledWith(url);
    });
  });
});