Skip to content
This repository was archived by the owner on May 1, 2020. It is now read-only.

Commit 759bb4f

Browse files
committed
fix(deep-linking): fix bug with null deep link config when modifying the main NgModule file (app.module.ts)
1 parent b1b9422 commit 759bb4f

File tree

2 files changed

+164
-11
lines changed

2 files changed

+164
-11
lines changed

src/deep-linking.spec.ts

Lines changed: 144 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe('Deep Linking task', () => {
1414
deepLinking.reset();
1515
});
1616

17-
it('should not update app ngmodule when it has an existing deeplink config', () => {
17+
it('should not update app ngmodule when it has an existing deeplink config', () => {
1818
const appNgModulePath = join('some', 'fake', 'path', 'myApp', 'src', 'app', 'app.module.ts');
1919
const context = {
2020
fileCache: new FileCache()
@@ -192,5 +192,148 @@ describe('Deep Linking task', () => {
192192
expect(spy).toHaveBeenCalledTimes(1);
193193
});
194194
});
195+
196+
it('should update the deeplink config and cached deeplink string no matter what when the app.module.ts is changed', () => {
197+
const appNgModulePath = join('some', 'fake', 'path', 'myApp', 'src', 'app', 'app.module.ts');
198+
const context = {
199+
fileCache: new FileCache(),
200+
runAot: true
201+
};
202+
const knownFileContent = `
203+
import { BrowserModule } from '@angular/platform-browser';
204+
import { HttpModule } from '@angular/http';
205+
import { NgModule, ErrorHandler } from '@angular/core';
206+
207+
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
208+
209+
import { InAppBrowser } from '@ionic-native/in-app-browser';
210+
import { SplashScreen } from '@ionic-native/splash-screen';
211+
212+
import { IonicStorageModule } from '@ionic/storage';
213+
214+
import { ConferenceApp } from './app.component';
215+
216+
import { ConferenceData } from '../providers/conference-data';
217+
import { UserData } from '../providers/user-data';
218+
219+
@NgModule({
220+
declarations: [
221+
ConferenceApp
222+
],
223+
imports: [
224+
BrowserModule,
225+
HttpModule,
226+
IonicModule.forRoot(ConferenceApp, {
227+
preloadModules: true
228+
}),
229+
IonicStorageModule.forRoot()
230+
],
231+
bootstrap: [IonicApp],
232+
entryComponents: [
233+
ConferenceApp
234+
],
235+
providers: [
236+
{ provide: ErrorHandler, useClass: IonicErrorHandler },
237+
ConferenceData,
238+
UserData,
239+
InAppBrowser,
240+
SplashScreen
241+
]
242+
})
243+
export class AppModule { }
244+
`;
245+
246+
const knownFileContent2 = `
247+
import { BrowserModule } from '@angular/platform-browser';
248+
import { HttpModule } from '@angular/http';
249+
import { NgModule, ErrorHandler } from '@angular/core';
250+
251+
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
252+
253+
import { InAppBrowser } from '@ionic-native/in-app-browser';
254+
import { SplashScreen } from '@ionic-native/splash-screen';
255+
256+
import { IonicStorageModule } from '@ionic/storage';
257+
258+
import { ConferenceApp } from './app.component';
259+
260+
import { ConferenceData } from '../providers/conference-data';
261+
import { UserData } from '../providers/user-data';
262+
263+
@NgModule({
264+
declarations: [
265+
ConferenceApp,
266+
SomeNewComponent
267+
],
268+
imports: [
269+
BrowserModule,
270+
HttpModule,
271+
IonicModule.forRoot(ConferenceApp, {
272+
preloadModules: true
273+
}),
274+
IonicStorageModule.forRoot()
275+
],
276+
bootstrap: [IonicApp],
277+
entryComponents: [
278+
ConferenceApp
279+
],
280+
providers: [
281+
{ provide: ErrorHandler, useClass: IonicErrorHandler },
282+
ConferenceData,
283+
UserData,
284+
InAppBrowser,
285+
SplashScreen
286+
]
287+
})
288+
export class AppModule { }
289+
`;
290+
const knownDeepLinkString = 'someDeepLinkString';
291+
const knownMockDeepLinkArray = [1];
292+
const changedFiles: ChangedFile[] = [];
293+
context.fileCache.set(appNgModulePath, { path: appNgModulePath, content: knownFileContent});
294+
295+
spyOn(helpers, helpers.getStringPropertyValue.name).and.returnValue(appNgModulePath);
296+
spyOn(deeplinkUtils, deeplinkUtils.getDeepLinkData.name).and.returnValue(knownMockDeepLinkArray);
297+
spyOn(deeplinkUtils, deeplinkUtils.hasExistingDeepLinkConfig.name).and.returnValue(false);
298+
299+
spyOn(deeplinkUtils, deeplinkUtils.convertDeepLinkConfigEntriesToString.name).and.returnValue(knownDeepLinkString);
300+
301+
const spy = spyOn(deeplinkUtils, deeplinkUtils.updateAppNgModuleAndFactoryWithDeepLinkConfig.name);
302+
303+
const promise = deepLinking.deepLinkingWorkerImpl(context, changedFiles);
304+
305+
return promise.then(() => {
306+
expect(deepLinking.cachedUnmodifiedAppNgModuleFileContent).toEqual(knownFileContent);
307+
expect(deepLinking.cachedDeepLinkString).toEqual(knownDeepLinkString);
308+
expect(helpers.getStringPropertyValue).toBeCalledWith(Constants.ENV_APP_NG_MODULE_PATH);
309+
expect(deeplinkUtils.getDeepLinkData).toHaveBeenCalledWith(appNgModulePath, context.fileCache, context.runAot);
310+
expect(deeplinkUtils.hasExistingDeepLinkConfig).toHaveBeenCalledWith(appNgModulePath, knownFileContent);
311+
expect(deeplinkUtils.convertDeepLinkConfigEntriesToString).toHaveBeenCalledWith(knownMockDeepLinkArray);
312+
expect(spy.calls.first().args[0]).toEqual(context);
313+
expect(spy.calls.first().args[1]).toEqual(knownDeepLinkString);
314+
expect(spy.calls.first().args[2]).toEqual(changedFiles);
315+
expect(spy.calls.first().args[3]).toEqual(context.runAot);
316+
317+
// add a changed file to the fray
318+
changedFiles.push({
319+
event: 'change',
320+
ext: '.ts',
321+
filePath: appNgModulePath
322+
});
323+
context.fileCache.set(appNgModulePath, { path: appNgModulePath, content: knownFileContent2});
324+
return deepLinking.deepLinkingWorkerImpl(context, changedFiles);
325+
}).then((result) => {
326+
expect(result).toEqual(knownMockDeepLinkArray);
327+
expect(deepLinking.cachedDeepLinkString).toEqual(knownDeepLinkString);
328+
expect(deepLinking.cachedUnmodifiedAppNgModuleFileContent).toEqual(knownFileContent2);
329+
expect(deeplinkUtils.getDeepLinkData).toHaveBeenCalledTimes(2);
330+
expect(deeplinkUtils.getDeepLinkData).toHaveBeenCalledWith(appNgModulePath, context.fileCache, context.runAot);
331+
expect(deeplinkUtils.hasExistingDeepLinkConfig).toHaveBeenCalledTimes(2);
332+
expect(deeplinkUtils.hasExistingDeepLinkConfig).toHaveBeenCalledWith(appNgModulePath, knownFileContent);
333+
expect(deeplinkUtils.convertDeepLinkConfigEntriesToString).toHaveBeenCalledWith(knownMockDeepLinkArray);
334+
expect(deeplinkUtils.convertDeepLinkConfigEntriesToString).toHaveBeenCalledTimes(2);
335+
expect(spy).toHaveBeenCalledTimes(2);
336+
});
337+
});
195338
});
196339
});

src/deep-linking.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ export function deepLinking(context: BuildContext) {
3333

3434

3535
function deepLinkingWorker(context: BuildContext) {
36-
return deepLinkingWorkerImpl(context, null);
36+
return deepLinkingWorkerImpl(context, []);
3737
}
3838

3939
export function deepLinkingWorkerImpl(context: BuildContext, changedFiles: ChangedFile[]) {
4040
return Promise.resolve().then(() => {
4141
const appNgModulePath = getStringPropertyValue(Constants.ENV_APP_NG_MODULE_PATH);
4242
const appNgModuleFile = context.fileCache.get(appNgModulePath);
43-
if (!cachedUnmodifiedAppNgModuleFileContent) {
43+
if (!cachedUnmodifiedAppNgModuleFileContent || hasAppModuleChanged(changedFiles, appNgModulePath)) {
4444
cachedUnmodifiedAppNgModuleFileContent = appNgModuleFile.content;
4545
}
4646

@@ -53,13 +53,11 @@ export function deepLinkingWorkerImpl(context: BuildContext, changedFiles: Chang
5353
const deepLinkConfigEntries = getDeepLinkData(appNgModulePath, context.fileCache, context.runAot) || [];
5454
if (deepLinkConfigEntries.length) {
5555
const newDeepLinkString = convertDeepLinkConfigEntriesToString(deepLinkConfigEntries);
56-
if (!cachedDeepLinkString) {
57-
// this is the first time running this, so update the build either way
58-
cachedDeepLinkString = newDeepLinkString;
59-
updateAppNgModuleAndFactoryWithDeepLinkConfig(context, newDeepLinkString, changedFiles, context.runAot);
60-
} else if (newDeepLinkString !== cachedDeepLinkString) {
61-
// we have an existing deep link string, and we have a new one, and they're different
62-
// so go ahead and update the config
56+
57+
// 1. this is the first time running this, so update the build either way
58+
// 2. we have an existing deep link string, and we have a new one, and they're different - so go ahead and update the config
59+
// 3. the app's main ngmodule has changed, so we need to rewrite the config
60+
if (!cachedDeepLinkString || newDeepLinkString !== cachedDeepLinkString || hasAppModuleChanged(changedFiles, appNgModulePath)) {
6361
cachedDeepLinkString = newDeepLinkString;
6462
updateAppNgModuleAndFactoryWithDeepLinkConfig(context, newDeepLinkString, changedFiles, context.runAot);
6563
}
@@ -68,6 +66,18 @@ export function deepLinkingWorkerImpl(context: BuildContext, changedFiles: Chang
6866
});
6967
}
7068

69+
export function hasAppModuleChanged(changedFiles: ChangedFile[], appNgModulePath: string) {
70+
if (!changedFiles) {
71+
changedFiles = [];
72+
}
73+
for (const changedFile of changedFiles) {
74+
if (changedFile.filePath === appNgModulePath) {
75+
return true;
76+
}
77+
}
78+
return false;
79+
}
80+
7181
export function deepLinkingUpdate(changedFiles: ChangedFile[], context: BuildContext) {
7282
if (context.deepLinkState === BuildState.RequiresBuild) {
7383
return deepLinkingWorkerFullUpdate(context);
@@ -109,4 +119,4 @@ export function deepLinkingWorkerFullUpdate(context: BuildContext) {
109119
export function reset() {
110120
cachedUnmodifiedAppNgModuleFileContent = null;
111121
cachedDeepLinkString = null;
112-
}
122+
}

0 commit comments

Comments
 (0)