0
votes

I'm new to angular 2 and unit testing with jasmine, I'm trying to test that my async service is called by my ng-on-init and that the value is set in my componenent

here is my component :

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

  @Input()
  fragmentOverlay:FragmentOverlay;

  @Input()
  index: Number;

  fragmentDefinition:FragmentDefinition;


  constructor(private fragmentService:FragmentService) {
  }

  ngOnInit():void {
    let fragmentId = this.fragmentOverlay.fragmentId;

    this.fragmentService.getFragmentDefinitionByConfigurationId(fragmentId).subscribe(function (fragmentDefinition:FragmentDefinition) {
      this.fragmentDefinition = fragmentDefinition;
      console.log("blablabla "+fragmentDefinition);
    });
  }

  ngOnChanges(changes) {
    if (changes.hasOwnProperty("index") && !changes.index.firstChange ){
      console.log(this.fragmentOverlay.fragmentId +"previous "+ changes.index.previousValue +"after "+changes.index.currentValue);
    }
  }
}

here is my test :

describe('Fragment overlay ', () => {

  let comp:    FragmentOverlayComponent;
  let fixture: ComponentFixture<FragmentOverlayComponent>;
  let de:      DebugElement;
  let el:      HTMLElement;
  let spy ;


  class FragmentServiceMock {
    private fragmentDefinitionTest = new FragmentDefinition("id", "label", false, true, [], "location");

    getFragmentDefinitionByConfigurationId(id:string):Observable<FragmentDefinition> { return Observable.of(this.fragmentDefinitionTest) }
  }


  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpModule],
      declarations: [FragmentOverlayComponent],// declare the test component
      providers: [FragmentService, { provide: XHRBackend, useClass: MockBackend },]
    })
      .compileComponents();  // compile template and css
    fixture = TestBed.createComponent(FragmentOverlayComponent);



    comp = fixture.componentInstance;

    let fragService = fixture.debugElement.injector.get(FragmentService);

    let fragmentDefinitionTest = new FragmentDefinition("id", "label", false, true, [], "location");

    spy = spyOn(fragService, 'getFragmentDefinitionByConfigurationId')
      .and.returnValue(Observable.of(fragmentDefinitionTest));

    comp.fragmentOverlay = new FragmentOverlay();
    comp.fragmentOverlay.fragmentId = "idFragment";


    // query for the title <h1> by CSS element selector
    de = fixture.debugElement.query(By.css('.fragment-overlay'));
    el = de.nativeElement;

  });



  it('should get a definition avec init async call resolved', async(() => {
    fixture.detectChanges();
    fixture.whenStable().then(() => { // wait for async getFragmentDefinitionByConfigurationId
      fixture.detectChanges();        // update view with quote
      expect(fixture.componentInstance.fragmentDefinition).toBeDefined();

    });
  }));


  it('should show quote after getQuote promise (fakeAsync)', fakeAsync(() => {
    fixture.detectChanges();
    tick();                  // wait for async getQuote
    fixture.detectChanges(); // update view with quote

  }));


});

expect(fixture.componentInstance.fragmentDefinition).toBeDefined(); --> fail

I've been stuck for a couple of hours, any help would be welcome

1

1 Answers

2
votes

You lose context within subscribe callback

this.fragmentService.getFragmentDefinitionByConfigurationId(fragmentId)
  .subscribe(function (fragmentDefinition:FragmentDefinition) { // don't use FE here
    this.fragmentDefinition = fragmentDefinition;
    console.log("blablabla "+fragmentDefinition);
  });

Use arrow to retain this:

.subscribe((fragmentDefinition:FragmentDefinition) => { 
  ...