• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

worktile / ngx-planet / da0907b1-b713-4b19-ac07-e0f1788da14c

13 Mar 2024 07:15AM UTC coverage: 93.578% (+0.5%) from 93.088%
da0907b1-b713-4b19-ac07-e0f1788da14c

push

circleci

why520crazy
test: add ngZone for fix test error

249 of 278 branches covered (89.57%)

Branch coverage included in aggregate %.

669 of 703 relevant lines covered (95.16%)

19.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.55
/packages/planet/src/application/ng-planet-application-ref.ts
1
import { ApplicationRef, NgModuleRef, NgZone, EnvironmentInjector } from '@angular/core';
2
import { Router, NavigationEnd } from '@angular/router';
3
import { take } from 'rxjs/operators';
4
import { Observable, from } from 'rxjs';
5
import { PlanetPortalApplication } from './portal-application';
6
import { PlantComponentConfig } from '../component/plant-component.config';
7
import { PlanetComponentRef } from '../component/planet-component-ref';
8
import { getTagNameByTemplate } from '../helpers';
9
import { getSandboxInstance, Sandbox } from '../sandbox/';
10
import { PlanetApplicationRef } from './planet-application-ref';
11

12
export type NgBootstrapAppModule = (
13
    portalApp: PlanetPortalApplication
14
) => Promise<NgModuleRef<any> | void | ApplicationRef | undefined | null>;
15

16
export interface NgBootstrapOptions {
17
    template: string;
18
    bootstrap: NgBootstrapAppModule;
19
}
20

21
/**
22
 * @deprecated please use NgBootstrapAppModule
23
 */
24
export type BootstrapAppModule = NgBootstrapAppModule;
25
/**
26
 * @deprecated please use NgBootstrapOptions
27
 */
28
export interface BootstrapOptions extends NgBootstrapOptions {}
29

30
export type PlantComponentFactory = <TData, TComp>(componentName: string, config: PlantComponentConfig<TData>) => PlanetComponentRef<TComp>;
31

32
export class NgPlanetApplicationRef implements PlanetApplicationRef {
33
    private injector?: EnvironmentInjector;
34
    private appRef?: ApplicationRef;
35
    public appModuleRef?: NgModuleRef<any>;
36
    public template?: string;
37
    private innerSelector?: string;
38
    private name: string;
39
    private portalApp!: PlanetPortalApplication;
40
    private appModuleBootstrap?: NgBootstrapAppModule;
41
    private componentFactory?: PlantComponentFactory;
42

43
    public get selector() {
44
        return this.innerSelector;
29✔
45
    }
46

47
    public get ngZone(): NgZone | undefined {
48
        return (this.injector || this.appModuleRef?.injector)?.get(NgZone);
2!
49
    }
50

51
    public get sandbox(): Sandbox {
52
        return getSandboxInstance();
3✔
53
    }
54

55
    public get bootstrapped(): boolean {
56
        return !!(this.appModuleRef || this.appRef);
27✔
57
    }
58

59
    constructor(name: string, options?: BootstrapOptions) {
60
        this.name = name;
58✔
61
        if (options) {
58✔
62
            this.template = options.template;
31✔
63
            this.innerSelector = this.template ? getTagNameByTemplate(this.template) : '';
31✔
64
            this.appModuleBootstrap = options.bootstrap;
31✔
65
        }
66
        // This is a hack, since NgZone doesn't allow you to configure the property that identifies your zone.
67
        // See https://github.com/PlaceMe-SAS/single-spa-angular-cli/issues/33,
68
        // NgZone.isInAngularZone = () => {
69
        //     // @ts-ignore
70
        //     return window.Zone.current._properties[`ngx-planet-${name}`] === true;
71
        // };
72
    }
73

74
    // 子应用路由变化后同步修改 portal 的 Route
75
    private syncPortalRouteWhenNavigationEnd() {
76
        const router = (this.injector || this.appModuleRef?.injector)?.get(Router);
24!
77
        if (router) {
24✔
78
            router.events.subscribe(event => {
24✔
79
                if (event instanceof NavigationEnd) {
10✔
80
                    this.ngZone?.onStable
1✔
81
                        .asObservable()
82
                        .pipe(take(1))
83
                        .subscribe(() => {
84
                            this.portalApp.ngZone.run(() => {
1✔
85
                                this.portalApp.router!.navigateByUrl(event.url);
1✔
86
                            });
87
                        });
88
                }
89
            });
90
        }
91
    }
92

93
    bootstrap(app: PlanetPortalApplication): Observable<this> {
94
        if (!this.appModuleBootstrap) {
25✔
95
            throw new Error(`app(${this.name}) is not defined`);
1✔
96
        }
97
        this.portalApp = app;
24✔
98
        return from(
24✔
99
            this.appModuleBootstrap(app).then(appModuleRef => {
100
                if (appModuleRef['instance']) {
24✔
101
                    this.appModuleRef = appModuleRef as NgModuleRef<any>;
22✔
102
                    this.appModuleRef.instance.appName = this.name;
22✔
103
                    this.injector = this.appModuleRef.injector;
22✔
104
                } else {
105
                    this.appRef = appModuleRef as unknown as ApplicationRef;
2✔
106
                    this.injector = this.appRef.injector;
2✔
107
                    const moduleRef = this.appRef.injector.get(NgModuleRef);
2✔
108
                    (moduleRef as any).instance = { appName: this.name };
2✔
109
                }
110
                this.syncPortalRouteWhenNavigationEnd();
24✔
111
                return this;
24✔
112
            })
113
        );
114
    }
115

116
    getRouter() {
117
        return (this.injector || this.appModuleRef?.injector)?.get(Router);
4!
118
    }
119

120
    getCurrentRouterStateUrl() {
121
        return this.getRouter()?.routerState.snapshot.url;
1✔
122
    }
123

124
    navigateByUrl(url: string): void {
125
        const router = this.getRouter();
1✔
126
        this.ngZone?.run(() => {
1✔
127
            router?.navigateByUrl(url);
1✔
128
        });
129
    }
130

131
    getComponentFactory() {
132
        return this.componentFactory;
21✔
133
    }
134

135
    registerComponentFactory(componentFactory: PlantComponentFactory) {
136
        this.componentFactory = componentFactory;
9✔
137
    }
138

139
    destroy(): void {
140
        if (this.appModuleRef || this.appRef) {
3✔
141
            const router = (this.injector || this.appModuleRef?.injector)?.get(Router);
3!
142
            if (router) {
3✔
143
                router.dispose();
3✔
144
            }
145
            if (this.sandbox) {
3!
146
                this.sandbox.destroy();
×
147
            }
148
            this.appModuleRef?.destroy();
3✔
149
            this.appModuleRef = undefined;
3✔
150
            this.appRef?.destroy();
3✔
151
            this.appRef = undefined;
3✔
152
            this.injector = undefined;
3✔
153
        }
154
    }
155
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc