From bd754e4f12dd9b5254917a371bedc3938d4c0c5f Mon Sep 17 00:00:00 2001 From: why520crazy Date: Fri, 11 Oct 2019 10:21:59 +0800 Subject: [PATCH] fix(app-loader): backwards compatibility get current url, add test cases --- .../planet-application-loader.spec.ts | 36 +------- .../application/planet-application-loader.ts | 7 +- .../planet-application-ref.spec.ts | 17 ---- .../planet-application.service.spec.ts | 82 ++++++++++--------- .../application/planet-application.service.ts | 9 +- .../application/portal-application.spec.ts | 52 ++++++++++++ packages/planet/src/test/applications.ts | 57 +++++++++++++ 7 files changed, 164 insertions(+), 96 deletions(-) create mode 100644 packages/planet/src/application/portal-application.spec.ts create mode 100644 packages/planet/src/test/applications.ts diff --git a/packages/planet/src/application/planet-application-loader.spec.ts b/packages/planet/src/application/planet-application-loader.spec.ts index 2a40e58..6851018 100644 --- a/packages/planet/src/application/planet-application-loader.spec.ts +++ b/packages/planet/src/application/planet-application-loader.spec.ts @@ -9,41 +9,7 @@ import { SwitchModes, PlanetApplication } from '../planet.class'; import { PlanetApplicationService } from './planet-application.service'; import { NgZone } from '@angular/core'; import { PlanetApplicationRef } from './planet-application-ref'; - -const app1 = { - name: 'app1', - hostParent: '.host-selector', - selector: 'app1-root-container', - routerPathPrefix: '/app1', - hostClass: 'app1-host', - preload: false, - switchMode: SwitchModes.default, - resourcePathPrefix: '/static/app1/', - styles: ['styles/main.css'], - scripts: ['vendor.js', 'main.js'], - loadSerial: false, - manifest: '', - extra: { - appName: '应用1' - } -}; - -const app2 = { - name: 'app2', - hostParent: '.host-selector', - selector: 'app2-root-container', - routerPathPrefix: '/app2', - hostClass: 'app2-host', - preload: false, - switchMode: SwitchModes.coexist, - resourcePathPrefix: '/static/app2', - styles: ['styles/main.css'], - scripts: ['vendor.js', 'main.js'], - loadSerial: false, - extra: { - appName: '应用2' - } -}; +import { app1, app2 } from '../test/applications'; class PlanetApplicationRefFaker { planetAppRef: PlanetApplicationRef; diff --git a/packages/planet/src/application/planet-application-loader.ts b/packages/planet/src/application/planet-application-loader.ts index e10b65d..ebe8303 100644 --- a/packages/planet/src/application/planet-application-loader.ts +++ b/packages/planet/src/application/planet-application-loader.ts @@ -193,7 +193,10 @@ export class PlanetApplicationLoader { of(app).pipe( tap(() => { const appRef = getPlanetApplicationRef(app.name); - const currentUrl = appRef.getCurrentRouterStateUrl(); + // Backwards compatibility sub app use old version which has not getCurrentRouterStateUrl + const currentUrl = appRef.getCurrentRouterStateUrl + ? appRef.getCurrentRouterStateUrl() + : ''; if (currentUrl !== event.url) { appRef.navigateByUrl(event.url); } @@ -309,7 +312,7 @@ export class PlanetApplicationLoader { } } let result = appRef.bootstrap(this.portalApp); - // Forward compatibility promise for bootstrap + // Backwards compatibility promise for bootstrap if (result['then']) { result = from(result) as Observable; } diff --git a/packages/planet/src/application/planet-application-ref.spec.ts b/packages/planet/src/application/planet-application-ref.spec.ts index b18a517..ea34c62 100644 --- a/packages/planet/src/application/planet-application-ref.spec.ts +++ b/packages/planet/src/application/planet-application-ref.spec.ts @@ -25,23 +25,6 @@ class EmptyComponent {} }) class AppModule {} -const app1 = { - name: 'app1', - hostParent: '.host-selector', - selector: 'app1-root-container', - routerPathPrefix: '/app1', - hostClass: 'app1-host', - preload: false, - resourcePathPrefix: '/static/app1/', - styles: ['styles/main.css'], - scripts: ['vendor.js', 'main.js'], - loadSerial: false, - manifest: '', - extra: { - appName: '应用1' - } -}; - describe('PlanetApplicationRef', () => { afterEach(() => { // delete all apps diff --git a/packages/planet/src/application/planet-application.service.spec.ts b/packages/planet/src/application/planet-application.service.spec.ts index cb76be3..bc9f17d 100644 --- a/packages/planet/src/application/planet-application.service.spec.ts +++ b/packages/planet/src/application/planet-application.service.spec.ts @@ -1,7 +1,9 @@ import { TestBed } from '@angular/core/testing'; -import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { PlanetApplicationService } from './planet-application.service'; import { SwitchModes } from '../planet.class'; +import { HttpClient } from '@angular/common/http'; +import { app1, app2, app2WithPreload } from '../test/applications'; describe('PlanetApplicationService', () => { let planetApplicationService: PlanetApplicationService; @@ -13,42 +15,6 @@ describe('PlanetApplicationService', () => { planetApplicationService = TestBed.get(PlanetApplicationService); }); - const app1 = { - name: 'app1', - hostParent: '.host-selector', - selector: 'app1-root-container', - routerPathPrefix: '/app1', - hostClass: 'app1-host', - preload: false, - switchMode: SwitchModes.coexist, - resourcePathPrefix: '/static/app1/', - styles: ['styles/main.css'], - scripts: ['vendor.js', 'main.js'], - loadSerial: false, - manifest: '/static/app/manifest.json', - extra: { - appName: '应用1' - } - }; - - const app2 = { - name: 'app2', - hostParent: '.host-selector', - selector: 'app2-root-container', - routerPathPrefix: '/app2', - hostClass: 'app2-host', - preload: true, - switchMode: SwitchModes.coexist, - resourcePathPrefix: '/static/app2', - styles: ['styles/main.css'], - scripts: ['vendor.js', 'main.js'], - loadSerial: false, - manifest: '/static/app/manifest.json', - extra: { - appName: '应用2' - } - }; - describe('register', () => { it('should register signal app1 success', () => { planetApplicationService.register(app1); @@ -66,6 +32,42 @@ describe('PlanetApplicationService', () => { planetApplicationService.register([app1, app2]); expect(planetApplicationService.getApps()).toEqual([app1, app2]); }); + + describe('registerByUrl', () => { + let httpClient: HttpClient; + let httpTestingController: HttpTestingController; + beforeEach(() => { + httpClient = TestBed.get(HttpClient); + httpTestingController = TestBed.get(HttpTestingController); + }); + + afterEach(() => { + // After every test, assert that there are no more pending requests. + httpTestingController.verify(); + }); + + it('should register multiple apps by url', () => { + planetApplicationService.registerByUrl('/static/apps.json'); + const req = httpTestingController.expectOne('/static/apps.json'); + + // Assert that the request is a GET. + expect(req.request.method).toEqual('GET'); + + // Respond with mock data, causing Observable to resolve. + // Subscribe callback asserts that correct data was returned. + req.flush([app1, app2]); + + expect(planetApplicationService.getApps()).toEqual([app1, app2]); + }); + + it('should register one app by url', () => { + planetApplicationService.registerByUrl('/static/apps.json'); + const req = httpTestingController.expectOne('/static/apps.json'); + expect(req.request.method).toEqual('GET'); + req.flush(app1); + expect(planetApplicationService.getApps()).toEqual([app1]); + }); + }); }); describe('unregister', () => { @@ -110,14 +112,14 @@ describe('PlanetApplicationService', () => { describe('getAppsToPreload', () => { it('should get correct preload apps', () => { planetApplicationService.register(app1); - planetApplicationService.register(app2); + planetApplicationService.register(app2WithPreload); const appsToPreload = planetApplicationService.getAppsToPreload(); - expect(appsToPreload).toEqual([app2]); + expect(appsToPreload).toEqual([app2WithPreload]); }); it('should get correct preload apps exclude app names', () => { planetApplicationService.register(app1); - planetApplicationService.register(app2); + planetApplicationService.register(app2WithPreload); const appsToPreload = planetApplicationService.getAppsToPreload(['app2']); expect(appsToPreload).toEqual([]); }); diff --git a/packages/planet/src/application/planet-application.service.ts b/packages/planet/src/application/planet-application.service.ts index aaa1663..fa6b329 100644 --- a/packages/planet/src/application/planet-application.service.ts +++ b/packages/planet/src/application/planet-application.service.ts @@ -28,13 +28,18 @@ export class PlanetApplicationService { } registerByUrl(url: string): Observable { - return this.http.get(`${url}`).pipe( + const result = this.http.get(`${url}`).pipe( map(apps => { if (apps && Array.isArray(apps)) { this.register(apps); + } else { + this.register(apps as PlanetApplication); } - }) + }), + shareReplay() ); + result.subscribe(); + return result; } unregister(name: string) { diff --git a/packages/planet/src/application/portal-application.spec.ts b/packages/planet/src/application/portal-application.spec.ts new file mode 100644 index 0000000..f63abd7 --- /dev/null +++ b/packages/planet/src/application/portal-application.spec.ts @@ -0,0 +1,52 @@ +import { TestBed } from '@angular/core/testing'; +import { RouterModule, Router } from '@angular/router'; +import { PlanetPortalApplication } from './portal-application'; +import { NgZone, ApplicationRef } from '@angular/core'; + +describe('PlanetPortalApplication', () => { + let router: Router; + let planetPortalApplication: PlanetPortalApplication; + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [RouterModule.forRoot([])] + }); + router = TestBed.get(Router); + planetPortalApplication = new PlanetPortalApplication(); + planetPortalApplication.ngZone = TestBed.get(NgZone); + planetPortalApplication.applicationRef = TestBed.get(ApplicationRef); + planetPortalApplication.router = TestBed.get(Router); + }); + + it(`should create PlanetPortalApplication`, () => { + expect(planetPortalApplication).toBeTruthy(); + }); + + it(`should run function`, () => { + const spy = jasmine.createSpy('spy'); + expect(spy).not.toHaveBeenCalled(); + planetPortalApplication.run(spy); + expect(spy).toHaveBeenCalled(); + }); + + it(`should run function in ngZone`, () => { + const ngZoneRunSpy = spyOn(planetPortalApplication.ngZone, 'run'); + expect(ngZoneRunSpy).not.toHaveBeenCalled(); + planetPortalApplication.run(() => {}); + expect(ngZoneRunSpy).toHaveBeenCalled(); + }); + + it(`should run tick`, () => { + const tickSpy = spyOn(planetPortalApplication.applicationRef, 'tick'); + expect(tickSpy).not.toHaveBeenCalled(); + planetPortalApplication.tick(); + expect(tickSpy).toHaveBeenCalled(); + }); + + it(`should run navigateByUrl`, () => { + const navigateByUrlSpy = spyOn(planetPortalApplication.router, 'navigateByUrl'); + expect(navigateByUrlSpy).not.toHaveBeenCalled(); + planetPortalApplication.navigateByUrl('/app1/dashboard', { skipLocationChange: true }); + expect(navigateByUrlSpy).toHaveBeenCalled(); + expect(navigateByUrlSpy).toHaveBeenCalledWith('/app1/dashboard', { skipLocationChange: true }); + }); +}); diff --git a/packages/planet/src/test/applications.ts b/packages/planet/src/test/applications.ts new file mode 100644 index 0000000..db55f66 --- /dev/null +++ b/packages/planet/src/test/applications.ts @@ -0,0 +1,57 @@ +import { SwitchModes } from '../planet.class'; +const app1 = { + name: 'app1', + hostParent: '.host-selector', + selector: 'app1-root-container', + routerPathPrefix: '/app1', + hostClass: 'app1-host', + preload: false, + switchMode: SwitchModes.default, + resourcePathPrefix: '/static/app1/', + styles: ['styles/main.css'], + scripts: ['vendor.js', 'main.js'], + loadSerial: false, + manifest: '', + extra: { + appName: '应用1' + } +}; + +const app1WithManifest = { + ...app1, + manifest: '/static/app/manifest.json' +}; + +const app1WithPreload = { + ...app1, + preload: true +}; + +const app2 = { + name: 'app2', + hostParent: '.host-selector', + selector: 'app2-root-container', + routerPathPrefix: '/app2', + hostClass: 'app2-host', + preload: false, + switchMode: SwitchModes.coexist, + resourcePathPrefix: '/static/app2', + styles: ['styles/main.css'], + scripts: ['vendor.js', 'main.js'], + loadSerial: false, + extra: { + appName: '应用2' + } +}; + +const app2WithManifest = { + ...app2, + manifest: '/static/app/manifest.json' +}; + +const app2WithPreload = { + ...app2, + preload: true +}; + +export { app1, app1WithManifest, app1WithPreload, app2, app2WithManifest, app2WithPreload };