diff --git a/frontend/package.json b/frontend/package.json index 164243531..d25828e83 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -31,7 +31,7 @@ "font-awesome": "4.7.0", "luxon": "1.0.0", "rxjs": "5.5.8", - "zone.js": "0.8.20" + "zone.js": "0.8.25" }, "devDependencies": { "@angular/cli": "1.7.3", diff --git a/frontend/src/app/cities-upload/cities-upload.component.spec.ts b/frontend/src/app/cities-upload/cities-upload.component.spec.ts index 9981b6cd1..8d59aa09e 100644 --- a/frontend/src/app/cities-upload/cities-upload.component.spec.ts +++ b/frontend/src/app/cities-upload/cities-upload.component.spec.ts @@ -1,170 +1,159 @@ -import { async, fakeAsync, TestBed, tick } from '@angular/core/testing'; +import { TestBed } from '@angular/core/testing'; import { CitiesUploadComponent } from './cities-upload.component'; import { SearchCityService } from '../search-city.service'; import { Subject } from 'rxjs/Subject'; import { HttpClientModule, HttpEventType, HttpResponse } from '@angular/common/http'; -import { DateTime } from 'luxon'; import { GlobeNgbModule } from '../globe-ngb/globe-ngb.module'; -class FakeNow { - private now = DateTime.local(); +// TODO: those three lines of code can be removed after new version of angular is released. +declare let Zone: any; +const { fakeAsync, tick } = Zone['__zone_symbol__fakeAsyncTest']; +const async = Zone['__zone_symbol__asyncTest']; - constructor() { - jasmine.clock().mockDate(this.now.toJSDate()); - } - - tickSeconds(seconds: number) { - this.now = this.now.plus({ seconds }); - jasmine.clock().mockDate(this.now.toJSDate()); - tick(seconds * 1000); - } +function tickSeconds(seconds: number) { + tick(seconds * 1000); } describe('CitiesUploadComponent', () => { - - beforeEach(async(() => { - TestBed.configureTestingModule({ - imports: [GlobeNgbModule.forRoot(), HttpClientModule], - declarations: [CitiesUploadComponent], - providers: [SearchCityService] - }); - })); - - afterEach(() => jasmine.clock().uninstall()); + beforeEach( + async(() => { + TestBed.configureTestingModule({ + imports: [GlobeNgbModule.forRoot(), HttpClientModule], + declarations: [CitiesUploadComponent], + providers: [SearchCityService] + }); + }) + ); it('should upload', fakeAsync(() => { - const cityService = TestBed.get(SearchCityService); - const component = new CitiesUploadComponent(cityService); - - expect(component.status).toBe('pending'); + const cityService = TestBed.get(SearchCityService); + const component = new CitiesUploadComponent(cityService); - const fileChangeEvent = { - target: { - files: ['fakeFile'] - } - } as any; + expect(component.status).toBe('pending'); - const fileReader = new FileReader(); - spyOn(fileReader, 'readAsText'); + const fileChangeEvent = { + target: { + files: ['fakeFile'] + } + } as any; - spyOn(component, '_createFileReader').and.returnValue(fileReader); + const fileReader = new FileReader(); + spyOn(fileReader, 'readAsText'); - const fakeNow = new FakeNow(); + spyOn(component, '_createFileReader').and.returnValue(fileReader); - component.upload(fileChangeEvent); - expect(fileReader.onload).toBeDefined(); - expect(fileReader.readAsText).toHaveBeenCalledWith('fakeFile', 'UTF8'); + component.upload(fileChangeEvent); + expect(fileReader.onload).toBeDefined(); + expect(fileReader.readAsText).toHaveBeenCalledWith('fakeFile', 'UTF8'); - const fileLoadedEvent: any = { - target: { - result: 'fakeFileContent' - } - }; + const fileLoadedEvent: any = { + target: { + result: 'fakeFileContent' + } + }; - const fakeEvents = new Subject(); - spyOn(cityService, 'uploadCities').and.returnValue(fakeEvents); + const fakeEvents = new Subject(); + spyOn(cityService, 'uploadCities').and.returnValue(fakeEvents); - fileReader.onload(fileLoadedEvent); - expect(component.status).toBe('uploading'); + fileReader.onload(fileLoadedEvent); + expect(component.status).toBe('uploading'); - // emit first progress event after 5 seconds - fakeNow.tickSeconds(5); - fakeEvents.next({ - type: HttpEventType.UploadProgress, - loaded: 5, - total: 10 - }); + tickSeconds(5); + fakeEvents.next({ + type: HttpEventType.UploadProgress, + loaded: 5, + total: 10 + }); - // upload is halfway and has taken 5 seconds. Estimated processing time is 20 seconds - // so total time is 30 seconds and we're thus at 5 / 30 - expect(component.progress).toBe(5 / 30); + // upload is halfway and has taken 5 seconds. Estimated processing time is 20 seconds + // so total time is 30 seconds and we're thus at 5 / 30 + expect(component.progress).toBe(5 / 30); - // emit last progress events - fakeNow.tickSeconds(5); - fakeEvents.next({ - type: HttpEventType.UploadProgress, - loaded: 10, - total: 10 - }); + tickSeconds(5); + fakeEvents.next({ + type: HttpEventType.UploadProgress, + loaded: 10, + total: 10 + }); - expect(component.progress).toBe(10 / 30); - expect(component.status).toBe('processing'); + expect(component.progress).toBe(10 / 30); + expect(component.status).toBe('processing'); - fakeNow.tickSeconds(10); - expect(component.progress).toBe(20 / 30); + tickSeconds(10); + expect(component.progress).toBe(20 / 30); - fakeNow.tickSeconds(5); - expect(component.progress).toBe(25 / 30); + tickSeconds(5); + expect(component.progress).toBe(25 / 30); - fakeNow.tickSeconds(6); - expect(component.progress).toBeLessThan(1); - expect(component.status).toBe('processing'); + tickSeconds(6); + expect(component.progress).toBeLessThan(1); + expect(component.status).toBe('processing'); - // emit response and complete - fakeEvents.next(new HttpResponse()); - fakeEvents.complete(); - expect(component.progress).toBe(1); - expect(component.status).toBe('done'); - })); + // emit response and complete + fakeEvents.next(new HttpResponse()); + fakeEvents.complete(); + expect(component.progress).toBe(1); + expect(component.status).toBe('done'); + }) + ); it('should finish if response comes back early', fakeAsync(() => { - const cityService = TestBed.get(SearchCityService); - const component = new CitiesUploadComponent(cityService); - - expect(component.status).toBe('pending'); - - const fileChangeEvent = { - target: { - files: ['fakeFile'] - } - } as any; - - const fileReader = new FileReader(); - spyOn(fileReader, 'readAsText'); - spyOn(component, '_createFileReader').and.returnValue(fileReader); - - const fakeNow = new FakeNow(); - - component.upload(fileChangeEvent); - expect(fileReader.onload).toBeDefined(); - expect(fileReader.readAsText).toHaveBeenCalledWith('fakeFile', 'UTF8'); - - const fileLoadedEvent: any = { - target: { - result: 'fakeFileContent' - } - }; - - const fakeEvents = new Subject(); - spyOn(cityService, 'uploadCities').and.returnValue(fakeEvents); - - fileReader.onload(fileLoadedEvent); - expect(component.status).toBe('uploading'); - - // emit last progress events - fakeNow.tickSeconds(10); - fakeEvents.next({ - type: HttpEventType.UploadProgress, - loaded: 10, - total: 10 - }); - - expect(component.progress).toBe(10 / 30); - expect(component.status).toBe('processing'); - - fakeNow.tickSeconds(15); - expect(component.progress).toBe(25 / 30); - - // emit response and complete - fakeEvents.next(new HttpResponse()); - fakeEvents.complete(); - expect(component.progress).toBe(1); - expect(component.status).toBe('done'); - - // let the fake event observable a chance to realize that the processing is done - fakeNow.tickSeconds(1); - })); + const cityService = TestBed.get(SearchCityService); + const component = new CitiesUploadComponent(cityService); + + expect(component.status).toBe('pending'); + + const fileChangeEvent = { + target: { + files: ['fakeFile'] + } + } as any; + + const fileReader = new FileReader(); + spyOn(fileReader, 'readAsText'); + spyOn(component, '_createFileReader').and.returnValue(fileReader); + + component.upload(fileChangeEvent); + expect(fileReader.onload).toBeDefined(); + expect(fileReader.readAsText).toHaveBeenCalledWith('fakeFile', 'UTF8'); + + const fileLoadedEvent: any = { + target: { + result: 'fakeFileContent' + } + }; + + const fakeEvents = new Subject(); + spyOn(cityService, 'uploadCities').and.returnValue(fakeEvents); + + fileReader.onload(fileLoadedEvent); + expect(component.status).toBe('uploading'); + + // emit last progress events + tickSeconds(10); + fakeEvents.next({ + type: HttpEventType.UploadProgress, + loaded: 10, + total: 10 + }); + + expect(component.progress).toBe(10 / 30); + expect(component.status).toBe('processing'); + + tickSeconds(15); + expect(component.progress).toBe(25 / 30); + + // emit response and complete + fakeEvents.next(new HttpResponse()); + fakeEvents.complete(); + expect(component.progress).toBe(1); + expect(component.status).toBe('done'); + + // let the fake event observable a chance to realize that the processing is done + tickSeconds(1); + }) + ); it('should display an info message and a file upload control, and no progress', () => { const fixture = TestBed.createComponent(CitiesUploadComponent); diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 322210248..7a4b59c26 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -7341,6 +7341,6 @@ yn@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" -zone.js@0.8.20: - version "0.8.20" - resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.20.tgz#a218c48db09464b19ff6fc8f0d4bb5b1046e185d" +zone.js@0.8.25: + version "0.8.25" + resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.25.tgz#e20e5e85b881e2e66352612b5f238e8309e5badd"