mercredi 31 août 2016

Angular 2 Jasmine test failed - sync emitter used

I have angular 2 component - list, that contains items. It is filterable and supports 2 events: filtering - before the filter process happens; filtered - after the filter process happens. Here is the implementation:

 @Output() filtering = new EventEmitter(false); // synchronous event emitter
 @Output() filtered = new EventEmitter(); // async event emitter

filter() {
            filteringArgs = { cancel: false };

            this.filtering.emit(filteringArgs);
            
            // Because the emitter is synchronous, the filtering handler will be executed now
            // and then the execution of filter function will continue from here
            
            if(filteringArgs.cancel) { 
                return; 
            }            

            // Filtering is happens here

            var result = { /* result of filtering */ };

            filteredArgs = { result: result }
            this.filtered.emit(filteredArgs);             
    }

When I use the following handler:

filteringHandler(args) { args.cancel = true; }

in its parent component to cancel the filtering process - it works as it is expected: no filter happens. So I want to test it and wrote the following test:

it('should cancel emitted filter events',
    async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
      var template = '<list (filtering)="filteringHandler($event)"><list-item>Item 1</list-item><list-item>Item 2</list-item><list-item>Item 3</list-item></list>';
                return tcb.overrideTemplate(ListTestComponent, template)
                .createAsync(ListTestComponent)
                .then((fixture) => {
                      var items, visibleItems,
                          list = fixture.componentInstance.viewChild;

                      spyOn(list.filtering, 'emit');
                      spyOn(list.filtered, 'emit');

                      fixture.detectChanges();
                      items = list.items;                      
                      visibleItems = items.filter((listItem) => { return !listItem.hidden; });
                      expect(list.items.length).toBe(3);
                      expect(visibleItems.length).toBe(3);
                      
                      list.searchInputElement = document.createElement('input');                      
                      list.searchInputElement.value = "3"; // filtering down only to item 3
                      fixture.componentInstance.filteringHandler = (args: any) => { args.cancel = true; }; // it should prevent form filtering
                      fixture.detectChanges(); 
                      list.filter(); // filter should not happen because of canceling
                      fixture.detectChanges();        

                      visibleItems = items.filter((listItem) => { return !listItem.hidden; }); 
                      expect(visibleItems.length).toBe(3);
                      expect(list.filtering.emit).toHaveBeenCalledWith({ cancel: false });
                      expect(list.filtered.emit).not.toHaveBeenCalledWith({ result: [visibleItems[0]] });
                }).catch (reason => {
                    console.log(reason);
                    return Promise.reject(reason);
                });
         })));

However, despite the fact that I expect from test to cancel the filtering, it does not and filter happens. Which leads to unexpected result for the test and it fails. What is wrong with testing of sync emitter using karma/jasmine?

Aucun commentaire:

Enregistrer un commentaire