jeudi 17 décembre 2020

Angular & Jest: Why is the subscribe block running inside ngOnInit?

I'm trying to run a simple test in jest: that the setUsername() method gets called on the joinGameService. But when I run the test, I get the following error:

Image showing the error

game.component.ts:

import { Component, OnInit } from '@angular/core';
import { GameService } from './shared/services/game.service';
import { JoinGameService } from './shared/services/join-game.service';
import { MatDialog } from '@angular/material/dialog';
import { QuitGameDialogComponent } from './shared/components/quit-game-dialog/quit-game-dialog.component';

@Component({
  selector: 'app-game',
  templateUrl: './game.component.html',
  styleUrls: ['./game.component.css']
})
export class GameComponent implements OnInit {

  public playersInLobby: Array<any>;

  constructor(
    public gameService: GameService,
    public dialog: MatDialog,
    private joinGameService: JoinGameService,
  ) { }

  ngOnInit() {
    this.joinGameService.onSetUsername()
      .subscribe((data: any) => {
        const { users } = data.room;
        this.playersInLobby = users;
      });
  }

  public enterRoom(userAndRoomId: any): void {
    const { username, roomId } = userAndRoomId;
    this.clientUsername = username;
    this.roomIsJoined = true;
    this.roomId = roomId;
    this.joinGameService.setUsername(roomId, username);
  }
}

relevant methods inside join-game.service.ts:

  public setUsername(roomId: string, username: string): void {
    this.socket.emit('set-username', {
      roomId,
      username
    });
  }

  public onSetUsername(): Observable<any> {
    return this.socket.fromEvent('set-username');
  }

game.component.spec.ts:

import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { GameComponent } from './game.component';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { JoinGameService } from './shared/services/join-game.service';
import { GameService } from './shared/services/game.service';
import { of } from 'rxjs';
import { MatDialogModule } from '@angular/material/dialog';

describe('GameComponent', () => {
  let component: GameComponent;
  let fixture: ComponentFixture<GameComponent>;
  let MOCK_USERNAME_AND_ID;

  const mockJoinGameService = {
    setUsername: jest.fn(),
    onSetUsername: jest.fn().mockReturnValue(of({data: 'test'})),
    isHost: jest.fn().mockReturnValue(of({data: 'test'})),
  };
  const mockGameService = {
    onStartGame: jest.fn().mockReturnValue(of({data: 'test'})),
  };

  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      imports: [
        MatDialogModule,
      ],
      declarations: [
        GameComponent
      ],
      providers: [
        { provide: GameService, useValue: mockGameService },
        { provide: JoinGameService, useValue: mockJoinGameService },
        { provide: ToastrService, useValue: mockToastrService }
      ],
      schemas: [ NO_ERRORS_SCHEMA ]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(GameComponent);
    component = fixture.componentInstance;
  });

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

  describe('enterRoom', () => {
    beforeEach(() => {
      MOCK_USERNAME_AND_ID = {
        username: 'James',
        roomId: 'a1b2c3d4'
      };
      fixture.detectChanges();
    });

    test('should call the setUsername method in joinGameService', () => {
      component.enterRoom(MOCK_USERNAME_AND_ID);
      expect(mockJoinGameService.setUsername).toHaveBeenCalled();
    });
  });
});

Why does the subscribe block run on onSetUsername which isn't even relevant in this test?

Aucun commentaire:

Enregistrer un commentaire