@angular/core/testing#discardPeriodicTasks TypeScript Examples

The following examples show how to use @angular/core/testing#discardPeriodicTasks. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: home.component.spec.ts    From Angular-Cookbook with MIT License 6 votes vote down vote up
describe('HomeComponent', () => {
  let component: HomeComponent;
  let fixture: ComponentFixture<HomeComponent>;

  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        declarations: [HomeComponent],
        imports: [HttpClientModule],
      }).compileComponents();
    })
  );

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

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

  it('should not send an http request before the debounceTime of 300ms', fakeAsync(async () => {
    spyOn(component, 'searchUsers');
    component.searchForm.get('username').setValue('iri');
    tick(component.searchDebounceTime - 10); // less than desired debounce time
    expect(component.searchUsers).not.toHaveBeenCalled();
    discardPeriodicTasks();
  }));

  it('should send an http request after the debounceTime of 300ms', fakeAsync(async () => {
    spyOn(component, 'searchUsers');
    component.searchForm.get('username').setValue('iri');
    tick(component.searchDebounceTime + 10); // more than desired debounce time
    expect(component.searchUsers).toHaveBeenCalled();
    discardPeriodicTasks();
  }));
});
Example #2
Source File: angular-context.ts    From s-libs with MIT License 5 votes vote down vote up
/**
   * Performs any cleanup needed at the end of each test. This base implementation calls {@linkcode https://angular.io/api/core/testing/discardPeriodicTasks|discardPeriodicTasks} and [flush]{https://angular.io/api/core/testing/flush|flush} to avoid an error from the `fakeAsync` zone.
   */
  protected cleanUp(): void {
    discardPeriodicTasks();
    flush();
    AngularContext.#current = undefined;
  }
Example #3
Source File: log-timers.spec.ts    From s-libs with MIT License 5 votes vote down vote up
describe('logTimers()', () => {
  it('prints each timeout call to `console.log`', fakeAsync(() => {
    const logSpy = spyOn(console, 'log');
    const stopLogging = logTimers();

    setTimeout(myFunction);
    expectSingleCallAndReset(logSpy, 'setTimeout(', myFunction, ')');

    setTimeout(myDelayedFunction, 1000);
    expectSingleCallAndReset(
      logSpy,
      'setTimeout(',
      myDelayedFunction,
      1000,
      ')',
    );

    tick(1000);
    stopLogging();

    // eslint-disable-next-line @typescript-eslint/no-empty-function
    function myFunction(): void {}

    // eslint-disable-next-line @typescript-eslint/no-empty-function
    function myDelayedFunction(): void {}
  }));

  it('prints each interval call to `console.log`', fakeAsync(() => {
    const logSpy = spyOn(console, 'log');
    const stopLogging = logTimers();

    setInterval(myFunction);
    expectSingleCallAndReset(logSpy, 'setInterval(', myFunction, ')');

    setInterval(myDelayedFunction, 1000);
    expectSingleCallAndReset(
      logSpy,
      'setInterval(',
      myDelayedFunction,
      1000,
      ')',
    );

    discardPeriodicTasks();
    stopLogging();

    // eslint-disable-next-line @typescript-eslint/no-empty-function
    function myFunction(): void {}

    // eslint-disable-next-line @typescript-eslint/no-empty-function
    function myDelayedFunction(): void {}
  }));

  it('returns a function to stop the logging', () => {
    const logSpy = spyOn(console, 'log');

    const stopLogging = logTimers();
    stopLogging();

    setTimeout(noop);
    setInterval(noop);
    expect(logSpy).not.toHaveBeenCalled();
  });
});
Example #4
Source File: carousel.component.spec.ts    From canopy with Apache License 2.0 4 votes vote down vote up
describe('LgCarouselComponent', () => {
  let component: LgCarouselComponent;
  let fixture: ComponentFixture<TestWrapperComponent>;
  let subscription: Subscription;

  const timerSelectionCheck = () => {
    component.ngAfterContentInit();

    expect(component.selectedItemIndex).toBe(0);
    component['pause'].next(true);
    tick(100);
    fixture.detectChanges();

    expect(component.selectedItemIndex).toBe(0);
    tick(100);
    fixture.detectChanges();

    expect(component.selectedItemIndex).toBe(0);
  };

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [
        TestWrapperComponent,
        TestWrapperComponent,
        TestCarouselComponent,
        LgCarouselItemComponent,
        LgCarouselComponent,
        MockComponents(LgHeadingComponent, LgIconComponent),
      ],
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(TestWrapperComponent);
    component = fixture.debugElement.children[0].children[0].componentInstance;
    fixture.detectChanges();
  });

  afterEach(() => {
    subscription?.unsubscribe();
  });

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

  it('should set the pause to true when pauseCarousel is invoked', fakeAsync(() => {
    component.pauseCarousel();
    fixture.detectChanges();

    component.pause.subscribe(pause => {
      expect(pause).toBeDefined();
      expect(pause).toBeTruthy();
    });
  }));

  it('should set the pause to false when playCarousel is invoked', fakeAsync(() => {
    component.playCarousel();
    fixture.detectChanges();

    component.pause.subscribe(pause => {
      expect(pause).toBeDefined();
      expect(pause).toBeFalsy();
    });
  }));

  it('should detect the amount of carousel item components are nested in order to build the navigation and apply styles to the carousel wrapper', () => {
    const wrapperElement = fixture.debugElement.query(By.css('.lg-carousel__wrapper'));

    expect(component.carouselItemCount).toBe(3);

    expect(wrapperElement.attributes['style']).toBe(
      'width: 300%; left: 0%; transition: left 0.5s ease 0s;',
    );
  });

  describe('navigation', () => {
    let prevButton: DebugElement;
    let bullet1: DebugElement;
    let bullet2: DebugElement;
    let bullet3: DebugElement;
    let nextButton: DebugElement;
    let bullet1Icon: DebugElement;
    let bullet2Icon: DebugElement;
    let bullet3Icon: DebugElement;

    beforeEach(() => {
      const buttons = fixture.debugElement.queryAll(By.css('.lg-carousel__button'));

      prevButton = buttons[0];
      bullet1 = buttons[1];
      bullet2 = buttons[2];
      bullet3 = buttons[3];
      nextButton = buttons[4];

      bullet1Icon = bullet1.query(By.css('.lg-carousel__bullet'));
      bullet2Icon = bullet2.query(By.css('.lg-carousel__bullet'));
      bullet3Icon = bullet3.query(By.css('.lg-carousel__bullet'));
    });

    it('should select the chosen carousel item as expected', () => {
      subscription = component.selectedItemIndexSet$.subscribe(selectedItem => {
        expect(component.selectedItemIndex).toBe(selectedItem);
        bullet2.nativeElement.click();

        expect(component.selectedItemIndex).toBe(1);
      });

      fixture.detectChanges();

      expect(
        bullet2Icon.nativeElement.classList.contains('lg-carousel__bullet--active'),
      ).toBe(true);
    });

    it('should navigate to the previous slide as expected', () => {
      subscription = component.selectedItemIndexSet$.subscribe(selectedItem => {
        expect(component.selectedItemIndex).toBe(selectedItem);
      });

      expect(component.selectedItemIndex).toBe(0);
      bullet2.nativeElement.click();
      fixture.detectChanges();

      expect(component.selectedItemIndex).toBe(1);
      prevButton.nativeElement.click();

      expect(component.selectedItemIndex).toBe(0);

      fixture.detectChanges();

      expect(
        bullet1Icon.nativeElement.classList.contains('lg-carousel__bullet--active'),
      ).toBe(true);
    });

    it('should navigate to the next slide as expected', () => {
      subscription = component.selectedItemIndexSet$.subscribe(selectedItem => {
        expect(component.selectedItemIndex).toBe(selectedItem);
      });

      expect(component.selectedItemIndex).toBe(0);
      nextButton.nativeElement.click();

      expect(component.selectedItemIndex).toBe(1);
      fixture.detectChanges();

      nextButton.nativeElement.click();

      expect(component.selectedItemIndex).toBe(2);

      fixture.detectChanges();

      expect(
        bullet3Icon.nativeElement.classList.contains('lg-carousel__bullet--active'),
      ).toBe(true);
    });

    it('should toggle the disabled attribute for the previous button when loopMode is true - disabled when the first slide is active', () => {
      expect(prevButton.attributes['disabled']).toBe('');
      bullet3.nativeElement.click();
      fixture.detectChanges();

      expect(prevButton.attributes['disabled']).toBeUndefined();
    });

    it('should toggle the disabled attribute for the next button when loopMode is true - disabled when the last slide is active', () => {
      expect(nextButton.attributes['disabled']).toBeUndefined();
      bullet3.nativeElement.click();
      fixture.detectChanges();

      expect(nextButton.attributes['disabled']).toBe('');
    });

    describe('accessibility', () => {
      it('should populate the aria-live region with selected item text', () => {
        const ariaLiveRegion = fixture.debugElement.query(
          By.css('.lg-carousel__active-content'),
        );

        expect(ariaLiveRegion.nativeNode.innerText).toBe(
          'Carousel item 1\n\nLorem ipsum dolor sit amet',
        );

        bullet2.nativeElement.click();
        fixture.detectChanges();

        expect(ariaLiveRegion.nativeNode.innerText).toBe(
          'Carousel item 2\n\nLorem ipsum dolor sit amet',
        );

        bullet3.nativeElement.click();
        fixture.detectChanges();

        expect(ariaLiveRegion.nativeNode.innerText).toBe(
          'Carousel item 3\n\nLorem ipsum dolor sit amet',
        );
      });
    });

    describe('loop mode enabled', () => {
      beforeEach(() => {
        component.loopMode = true;
        fixture.detectChanges();
      });

      it('should navigate to the last slide when previousCarouselItem is invoked and the first slide is active', () => {
        expect(component.selectedItemIndex).toBe(0);
        component.previousCarouselItem();

        expect(component.selectedItemIndex).toBe(2);
      });

      it('should navigate to the first slide when nextCarouselItem is invoked and the last slide is active', () => {
        expect(component.selectedItemIndex).toBe(0);
        bullet3.nativeElement.click();

        expect(component.selectedItemIndex).toBe(2);
        nextButton.nativeElement.click();

        expect(component.selectedItemIndex).toBe(0);
      });
    });

    describe('auto play', () => {
      beforeEach(() => {
        component.autoPlay = true;
        component.autoPlayDelay = 100;
        fixture.detectChanges();
      });

      it('should set the timer correctly', fakeAsync(() => {
        const checkSelectedItemIndex = () => {
          expect(component.selectedItemIndex).toBe(0);
          tick(100);
          fixture.detectChanges();

          expect(component.selectedItemIndex).toBe(1);
          tick(100);
          fixture.detectChanges();

          expect(component.selectedItemIndex).toBe(2);
        };

        component.ngAfterContentInit();

        checkSelectedItemIndex();
        tick(100);
        fixture.detectChanges();
        checkSelectedItemIndex();
        discardPeriodicTasks();
      }));

      it('should pause the timer', fakeAsync(() => {
        timerSelectionCheck();
        discardPeriodicTasks();
      }));

      it('should restart a paused timer', fakeAsync(() => {
        timerSelectionCheck();
        component['pause'].next(false);
        tick(100);
        fixture.detectChanges();

        expect(component.selectedItemIndex).toBe(1);
        tick(100);
        fixture.detectChanges();

        expect(component.selectedItemIndex).toBe(2);
        discardPeriodicTasks();
      }));
    });
  });
});
Example #5
Source File: spinner.component.spec.ts    From canopy with Apache License 2.0 4 votes vote down vote up
describe('LgSpinnerComponent', () => {
  let component: LgSpinnerComponent;
  let fixture: ComponentFixture<LgSpinnerComponent>;
  let cdrMock: ChangeDetectorRef;

  beforeEach(
    waitForAsync(() => {
      cdrMock = mock(ChangeDetectorRef);

      TestBed.configureTestingModule({
        declarations: [ LgSpinnerComponent ],
        providers: [ { provide: ChangeDetectorRef, useValue: instance(cdrMock) } ],
      }).compileComponents();
    }),
  );

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

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

  it('adds the variant class to the spinner ring', () => {
    let link = fixture.debugElement.query(By.css('.lg-spinner__ring--color'));

    expect(link).toBeFalsy();
    component.variant = 'color';
    fixture.detectChanges();
    link = fixture.debugElement.query(By.css('.lg-spinner__ring--color'));

    expect(link).toBeTruthy();
  });

  it('adds the small size variant to the component', () => {
    fixture.detectChanges();

    expect(fixture.debugElement.nativeElement.getAttribute('class')).not.toContain(
      'lg-spinner--sm',
    );

    component.size = 'sm';
    fixture.detectChanges();

    expect(fixture.debugElement.nativeElement.getAttribute('class')).toContain(
      'lg-spinner--sm',
    );
  });

  describe('text input', () => {
    describe('when not specified', () => {
      it('should add a visually hidden element with default text', () => {
        fixture.detectChanges();
        const hiddenEl = fixture.nativeElement.querySelector('.lg-visually-hidden');
        const textEl = fixture.nativeElement.querySelector('.lg-spinner__content');

        expect(textEl).toBeNull();
        expect(hiddenEl).toBeDefined();
        expect(hiddenEl.innerText).toEqual('Loading...');
      });
    });

    describe('when specified', () => {
      it('should add an element with the specified text', () => {
        component.text = 'Test text';
        fixture.detectChanges();

        const hiddenEl = fixture.nativeElement.querySelector('.lg-visually-hidden');
        const textEl = fixture.nativeElement.querySelector(
          '.lg-spinner__content > span[aria-hidden="true"]',
        );

        expect(hiddenEl.innerText).not.toEqual('Loading...');
        expect(textEl).toBeDefined();
        expect(textEl.innerText).toBe('Test text');
      });
    });
  });

  describe('readScreenReaderAlert', () => {
    beforeEach(() => {
      jasmine.clock().uninstall();
      jasmine.clock().install();
    });

    it('should be toggled every few seconds', fakeAsync(() => {
      component.ngOnInit();

      expect(component.readScreenReaderAlert).toBe(true);

      tick(1000);

      expect(component.readScreenReaderAlert).toBe(true);
      tick(1500);

      expect(component.readScreenReaderAlert).toBe(false);
      discardPeriodicTasks();
    }));

    describe('when set to false', () => {
      it('should remove the role and aria-live attributes', fakeAsync(() => {
        component.ngOnInit();
        tick(2500);
        fixture.detectChanges();

        expect(component.readScreenReaderAlert).toBe(false);
        expect(fixture.nativeElement.getAttribute('role')).toBeNull();
        expect(fixture.nativeElement.getAttribute('aria-live')).toBeNull();
        discardPeriodicTasks();
      }));
    });

    describe('when set to true', () => {
      it('should add the role and aria-live attributes', fakeAsync(() => {
        tick(1000);
        fixture.detectChanges();

        expect(component.readScreenReaderAlert).toBe(true);
        expect(fixture.nativeElement.getAttribute('role')).toBe('alert');
        expect(fixture.nativeElement.getAttribute('aria-live')).toBe('assertive');
        discardPeriodicTasks();
      }));
    });
  });
});
Example #6
Source File: data-view-map.component.spec.ts    From geonetwork-ui with GNU General Public License v2.0 4 votes vote down vote up
describe('DataViewMapComponent', () => {
  let component: DataViewMapComponent
  let fixture: ComponentFixture<DataViewMapComponent>
  let mdViewFacade

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [
        DataViewMapComponent,
        MockMapContextComponent,
        MockDropdownSelectorComponent,
        MockExternalViewerButtonComponent,
        MockLoadingMaskComponent,
        MockPopupAlertComponent,
      ],
      schemas: [NO_ERRORS_SCHEMA],
      providers: [
        {
          provide: MdViewFacade,
          useClass: MdViewFacadeMock,
        },
        {
          provide: MapUtilsService,
          useClass: MapUtilsServiceMock,
        },
        {
          provide: DataService,
          useClass: DataServiceMock,
        },
        {
          provide: MapStyleService,
          useValue: mapStyleServiceMock,
        },
        {
          provide: MapManagerService,
          useValue: mapManagerMock,
        },
        {
          provide: FeatureInfoService,
          useValue: featureInfoServiceMock,
        },
      ],
      imports: [TranslateModule.forRoot()],
    }).compileComponents()
    mdViewFacade = TestBed.inject(MdViewFacade)
  })

  beforeEach(() => {
    fixture = TestBed.createComponent(DataViewMapComponent)
    component = fixture.componentInstance
    fixture.detectChanges()
  })

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

  describe('map layers', () => {
    let mapComponent: MockMapContextComponent
    let dropdownComponent: DropdownSelectorComponent
    let externalViewerButtonComponent: MockExternalViewerButtonComponent

    beforeEach(() => {
      mapComponent = fixture.debugElement.query(
        By.directive(MockMapContextComponent)
      ).componentInstance
      dropdownComponent = fixture.debugElement.query(
        By.directive(MockDropdownSelectorComponent)
      ).componentInstance
      externalViewerButtonComponent = fixture.debugElement.query(
        By.directive(MockExternalViewerButtonComponent)
      ).componentInstance
    })

    describe('with no link compatible with MAP_API or GEODATA usage', () => {
      beforeEach(() => {
        mdViewFacade.mapApiLinks$.next([])
        mdViewFacade.geoDataLinks$.next([])
        fixture.detectChanges()
      })
      it('emits a map context with no layer', () => {
        expect(mapComponent.context).toEqual({
          layers: [],
          view: expect.any(Object),
        })
      })
      it('emits map config to map component', () => {
        expect(mapComponent.mapConfig).toEqual(mapConfigMock)
      })
      it('emits map config to external viewer component', () => {
        expect(externalViewerButtonComponent.mapConfig).toEqual(mapConfigMock)
      })
      it('emits no link to external viewer component', () => {
        expect(externalViewerButtonComponent.link).toEqual(undefined)
      })
      it('provides a placeholder value to the dropdown', () => {
        expect(dropdownComponent.choices).toEqual([
          {
            value: 0,
            label: expect.any(String),
          },
        ])
      })
    })

    describe('with several links compatible with MAP_API usage', () => {
      beforeEach(() => {
        mdViewFacade.mapApiLinks$.next([
          {
            url: 'http://abcd.com/',
            name: 'layer1',
            label: 'layer1',
            protocol: 'OGC:WMS--1-3-0',
          },
          {
            url: 'http://abcd.com/',
            name: 'layer2',
            label: 'layer2',
            protocol: 'OGC:WMS--1-1-0',
          },
        ])
        mdViewFacade.geoDataLinks$.next([])
        fixture.detectChanges()
      })
      it('emits a map context with the first compatible link', () => {
        expect(mapComponent.context).toEqual({
          layers: [
            {
              url: 'http://abcd.com/',
              name: 'layer1',
              type: 'wms',
            },
          ],
          view: expect.any(Object),
        })
      })
      it('provides a list of links to the dropdown', () => {
        expect(dropdownComponent.choices).toEqual([
          {
            value: 0,
            label: 'layer1 (WMS)',
          },
          {
            value: 1,
            label: 'layer2 (WMS)',
          },
        ])
      })
      it('provides first (selected) link to the external viewer component', () => {
        expect(externalViewerButtonComponent.link).toEqual({
          url: 'http://abcd.com/',
          label: 'layer1',
          name: 'layer1',
          protocol: 'OGC:WMS--1-3-0',
        })
      })
    })

    describe('with links compatible with MAP_API and GEODATA usage', () => {
      beforeEach(() => {
        mdViewFacade.mapApiLinks$.next([
          {
            url: 'http://abcd.com/',
            name: 'layer1',
            label: 'layer1',
            protocol: 'OGC:WMS',
          },
        ])
        mdViewFacade.geoDataLinks$.next([
          {
            url: 'http://abcd.com/wfs',
            name: 'featuretype',
            label: 'featuretype',
            protocol: 'OGC:WFS--2-0-0',
          },
          {
            url: 'http://abcd.com/data.geojson',
            name: 'data.geojson',
            label: 'data.geojson',
            protocol: 'WWW:DOWNLOAD',
            format: 'geojson',
          },
        ])
        fixture.detectChanges()
      })
      it('provides a list of links to the dropdown', () => {
        expect(dropdownComponent.choices).toEqual([
          {
            value: 0,
            label: 'layer1 (WMS)',
          },
          {
            value: 1,
            label: 'featuretype (WFS)',
          },
          {
            value: 2,
            label: 'data.geojson (geojson)',
          },
        ])
      })
      it('provides first (selected) link to the external viewer component', () => {
        expect(externalViewerButtonComponent.link).toEqual({
          url: 'http://abcd.com/',
          name: 'layer1',
          label: 'layer1',
          protocol: 'OGC:WMS',
        })
      })
    })

    describe('with a link using WFS protocol', () => {
      beforeEach(fakeAsync(() => {
        mdViewFacade.mapApiLinks$.next([])
        mdViewFacade.geoDataLinks$.next([
          {
            url: 'http://abcd.com/wfs',
            name: 'featuretype',
            protocol: 'OGC:WFS',
          },
        ])
        tick(200)
        fixture.detectChanges()
      }))
      it('emits a map context with the downloaded data from WFS', () => {
        expect(mapComponent.context).toEqual({
          layers: [
            {
              type: 'geojson',
              data: SAMPLE_GEOJSON,
            },
          ],
          view: expect.any(Object),
        })
      })
    })

    describe('with a link using ESRI:REST protocol', () => {
      beforeEach(fakeAsync(() => {
        mdViewFacade.mapApiLinks$.next([])
        mdViewFacade.geoDataLinks$.next([
          {
            protocol: 'ESRI:REST',
            name: 'mes_hdf',
            url: 'https://services8.arcgis.com/rxZzohbySMKHTNcy/arcgis/rest/services/mes_hdf/WFSServer/0',
          },
        ])
        tick(200)
        fixture.detectChanges()
      }))
      it('emits a map context with the the downloaded data from WFS', () => {
        expect(mapComponent.context).toEqual({
          layers: [
            {
              type: 'geojson',
              data: SAMPLE_GEOJSON,
            },
          ],
          view: expect.any(Object),
        })
      })
    })

    describe('with a link using WFS which returns an error', () => {
      beforeEach(() => {
        mdViewFacade.mapApiLinks$.next([])
        mdViewFacade.geoDataLinks$.next([
          {
            url: 'http://abcd.com/wfs/error',
            name: 'featuretype',
            protocol: 'OGC:WFS',
          },
        ])
      })
      it('shows an error', () => {
        expect(component.error).toEqual('data loading error')
      })
    })

    describe('with a link using DOWNLOAD protocol', () => {
      describe('during download', () => {
        beforeEach(fakeAsync(() => {
          mdViewFacade.mapApiLinks$.next([])
          mdViewFacade.geoDataLinks$.next([
            {
              url: 'http://abcd.com/data.geojson',
              name: 'data.geojson',
              protocol: 'WWW:DOWNLOAD--https',
              format: 'geojson',
            },
          ])
          fixture.detectChanges()
          tick(50)
          discardPeriodicTasks()
        }))
        it('does not emit immediately a map context', () => {
          expect(mapComponent.context).toBe(null)
        })
        it('shows a loading indicator', () => {
          expect(
            fixture.debugElement.query(By.directive(MockLoadingMaskComponent))
          ).toBeTruthy()
        })
      })
      describe('after download', () => {
        beforeEach(fakeAsync(() => {
          mdViewFacade.mapApiLinks$.next([])
          mdViewFacade.geoDataLinks$.next([
            {
              url: 'http://abcd.com/data.geojson',
              name: 'data.geojson',
              protocol: 'WWW:DOWNLOAD--https',
              format: 'geojson',
            },
          ])
          fixture.detectChanges()
          tick(200)
        }))
        it('emits a map context after loading with the downloaded data', () => {
          fixture.detectChanges()
          expect(mapComponent.context).toEqual({
            layers: [
              {
                type: 'geojson',
                data: SAMPLE_GEOJSON,
              },
            ],
            view: expect.any(Object),
          })
        })
        it('does not show a loading indicator', () => {
          fixture.detectChanges()
          expect(
            fixture.debugElement.query(By.directive(MockLoadingMaskComponent))
          ).toBeFalsy()
        })
      })
    })

    describe('when receiving several metadata records', () => {
      beforeEach(() => {
        mdViewFacade.mapApiLinks$.next([])
        mdViewFacade.geoDataLinks$.next([
          {
            url: 'http://abcd.com/data.geojson',
            name: 'data.geojson',
            label: 'data.geojson',
            protocol: 'WWW:DOWNLOAD',
            format: 'geojson',
          },
        ])
        mdViewFacade.mapApiLinks$.next([
          {
            url: 'http://abcd.com/',
            name: 'layer',
            label: 'layer',
            protocol: 'OGC:WMS',
          },
        ])
        mdViewFacade.geoDataLinks$.next([])
        fixture.detectChanges()
      })
      it('emits a map context with the link from the last record', () => {
        expect(mapComponent.context).toEqual({
          layers: [
            {
              url: 'http://abcd.com/',
              name: 'layer',
              type: 'wms',
            },
          ],
          view: expect.any(Object),
        })
      })
      it('provides a list of links to the dropdown', () => {
        expect(dropdownComponent.choices).toEqual([
          {
            value: 0,
            label: 'layer (WMS)',
          },
        ])
      })
      it('provides first (selected) link to the external viewer component', () => {
        expect(externalViewerButtonComponent.link).toEqual({
          url: 'http://abcd.com/',
          name: 'layer',
          label: 'layer',
          protocol: 'OGC:WMS',
        })
      })
    })

    describe('when selecting a layer', () => {
      beforeEach(inject([MapUtilsService], (mapUtils) => {
        mapUtils._returnImmediately = false
        mdViewFacade.mapApiLinks$.next([
          {
            url: 'http://abcd.com/',
            name: 'layer1',
            protocol: 'OGC:WMS',
          },
          {
            url: 'http://abcd.com/',
            name: 'layer2',
            protocol: 'OGC:WMS',
          },
        ])
        mdViewFacade.geoDataLinks$.next([])
        dropdownComponent.selectValue.emit(1)
        fixture.detectChanges()
      }))
      describe('while extent is not ready', () => {
        it('does not emit a map context', () => {
          expect(mapComponent.context).toBeFalsy()
        })
      })
      describe('when extent is received', () => {
        beforeEach(inject([MapUtilsService], (mapUtils) => {
          mapUtils._observer.next([-100, -200, 100, 200])
          fixture.detectChanges()
        }))
        it('emits a new map context with the selected layer and the computed extent', () => {
          expect(mapComponent.context).toEqual({
            layers: [
              {
                url: 'http://abcd.com/',
                name: 'layer2',
                type: 'wms',
              },
            ],
            view: {
              extent: [-100, -200, 100, 200],
            },
          })
        })
        it('provides selected link to the external viewer component', () => {
          expect(externalViewerButtonComponent.link).toEqual({
            url: 'http://abcd.com/',
            name: 'layer2',
            protocol: 'OGC:WMS',
          })
        })
      })
      describe('when extent computation fails', () => {
        beforeEach(inject([MapUtilsService], (mapUtils) => {
          mapUtils._observer.error('extent computation failed')
          fixture.detectChanges()
        }))
        it('emits a new map context with the selected layer and a default view', () => {
          expect(mapComponent.context).toEqual({
            layers: [
              {
                url: 'http://abcd.com/',
                name: 'layer2',
                type: 'wms',
              },
            ],
            view: expect.any(Object),
          })
        })
        it('provides selected link to the external viewer component', () => {
          expect(externalViewerButtonComponent.link).toEqual({
            url: 'http://abcd.com/',
            name: 'layer2',
            protocol: 'OGC:WMS',
          })
        })
      })
      describe('selecting another layer, while extent is not ready', () => {
        beforeEach(inject([MapUtilsService], (mapUtils) => {
          mapUtils._observer.next([-10, -20, 10, 20])
          dropdownComponent.selectValue.emit(0)
          fixture.detectChanges()
        }))
        it('does not emit another map context', () => {
          expect(mapComponent.context.layers).toEqual([
            {
              url: 'http://abcd.com/',
              name: 'layer2',
              type: 'wms',
            },
          ])
        })
      })
    })
  })

  const vectorLayer = new VectorLayer({
    source: new VectorSource({
      features: new GeoJSON().readFeatures(
        FEATURE_COLLECTION_POINT_FIXTURE_4326,
        {
          featureProjection: 'EPSG:3857',
          dataProjection: 'EPSG:4326',
        }
      ),
    }),
  })
  const selectionFeatures = [
    vectorLayer
      .getSource()
      .getFeatures()
      .find((feature) => feature.getId() === 2),
  ]

  describe('feature info', () => {
    it('creates selection style', () => {
      expect(component['selectionStyle']).toBeTruthy()
    })
    describe('#onMapFeatureSelect', () => {
      beforeEach(() => {
        const changeDetectorRef =
          fixture.debugElement.injector.get(ChangeDetectorRef)
        jest.spyOn(changeDetectorRef.constructor.prototype, 'detectChanges')
        jest.spyOn(component, 'resetSelection')
        featureInfoServiceMock.features$.next(selectionFeatures)
      })
      it('reset the selection first', () => {
        expect(component.resetSelection).toHaveBeenCalled()
      })
      it('set the selection', () => {
        expect(component.selection).toBe(selectionFeatures[0])
      })
      it('change detection applied', () => {
        expect(component['changeRef'].detectChanges).toHaveBeenCalled()
      })
      it('set feature style', () => {
        expect(component.selection.getStyle()).toBe(component['selectionStyle'])
      })
    })
    describe('#resetSelection', () => {
      beforeEach(() => {
        component.selection = selectionFeatures[0]
        component.resetSelection()
      })
      it('reset the style of the feature', () => {
        expect(selectionFeatures[0].getStyle()).toBeNull()
      })
      it('remove the selection', () => {
        expect(component.selection).toBeFalsy()
      })
    })
    describe('changing the map context', () => {
      beforeEach(() => {
        jest.spyOn(component, 'resetSelection')
        mdViewFacade.geoDataLinks$.next([])
        mdViewFacade.mapApiLinks$.next([])
      })
      it('resets selection', () => {
        expect(component.resetSelection).toHaveBeenCalled()
      })
    })
  })
})
Example #7
Source File: data-view-table.component.spec.ts    From geonetwork-ui with GNU General Public License v2.0 4 votes vote down vote up
describe('DataViewTableComponent', () => {
  let component: DataViewTableComponent
  let fixture: ComponentFixture<DataViewTableComponent>
  let facade
  let dataService: DataService

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [
        DataViewTableComponent,
        MockTableComponent,
        MockDropdownSelectorComponent,
        MockLoadingMaskComponent,
        MockPopupAlertComponent,
      ],
      providers: [
        {
          provide: MdViewFacade,
          useClass: MdViewFacadeMock,
        },
        {
          provide: DataService,
          useClass: DataServiceMock,
        },
      ],
      imports: [TranslateModule.forRoot()],
    }).compileComponents()
    facade = TestBed.inject(MdViewFacade)
    dataService = TestBed.inject(DataService)
  })

  beforeEach(() => {
    fixture = TestBed.createComponent(DataViewTableComponent)
    component = fixture.componentInstance
    fixture.detectChanges()
  })

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

  describe('initial state', () => {
    let dropDownComponent: MockDropdownSelectorComponent
    let tableComponent: MockTableComponent

    beforeEach(() => {
      dropDownComponent = fixture.debugElement.query(
        By.directive(MockDropdownSelectorComponent)
      ).componentInstance
    })

    describe('when component is rendered', () => {
      beforeEach(() => {
        facade.dataLinks$.next(DATALINKS_FIXTURE)
        facade.geoDataLinks$.next(GEODATALINKS_FIXTURE)
        fixture.detectChanges()
      })

      it('shows the dropdown with the same number of entries', () => {
        expect(dropDownComponent.choices).toEqual([
          {
            label: 'CSV file (csv)',
            value: 0,
          },
          {
            label: 'Geojson file (geojson)',
            value: 1,
          },
          {
            label: 'Service WFS (WFS)',
            value: 2,
          },
        ])
      })

      it('loads the data from the first available link', () => {
        expect(dataService.readDataset).toHaveBeenCalledWith(
          'https://test.org/some_file_name.csv',
          'csv'
        )
      })
    })

    describe('during data loading', () => {
      beforeEach(fakeAsync(() => {
        facade.dataLinks$.next(DATALINKS_FIXTURE)
        facade.geoDataLinks$.next([])
        fixture.detectChanges()
        tick(50)
        discardPeriodicTasks()
      }))
      it('shows a loading indicator', () => {
        expect(
          fixture.debugElement.query(By.directive(MockLoadingMaskComponent))
        ).toBeTruthy()
      })
    })
    describe('when data is loaded', () => {
      beforeEach(fakeAsync(() => {
        facade.dataLinks$.next(DATALINKS_FIXTURE)
        facade.geoDataLinks$.next(GEODATALINKS_FIXTURE)
        tick(200)
        fixture.detectChanges()

        tableComponent = fixture.debugElement.query(
          By.directive(MockTableComponent)
        ).componentInstance
      }))
      it('displays mocked data in the table', () => {
        expect(tableComponent.data).toEqual([
          {
            id: SAMPLE_GEOJSON.features[0].id,
            ...SAMPLE_GEOJSON.features[0].properties,
          },
        ])
      })

      describe('when switching data link', () => {
        beforeEach(() => {
          dropDownComponent.selectValue.emit(1)
        })
        it('loads data from selected link', () => {
          expect(dataService.readDataset).toHaveBeenCalledWith(
            'https://test.org/some_file_name.geojson',
            'geojson'
          )
        })
        it('displays mocked data in the table', () => {
          expect(tableComponent.data).toEqual([
            {
              id: SAMPLE_GEOJSON.features[0].id,
              ...SAMPLE_GEOJSON.features[0].properties,
            },
          ])
        })
      })
    })
  })
  describe('error when loading data', () => {
    beforeEach(() => {
      facade.dataLinks$.next([])
      facade.geoDataLinks$.next([
        {
          url: 'http://abcd.com/wfs/error',
          name: 'featuretype',
          protocol: 'OGC:WFS',
        },
      ])
    })
    it('shows an error warning', () => {
      expect(component.error).toEqual('data loading error')
    })
  })
})