diff --git a/src/deep-linking.spec.ts b/src/deep-linking.spec.ts index ebb32230..bd06764b 100644 --- a/src/deep-linking.spec.ts +++ b/src/deep-linking.spec.ts @@ -9,6 +9,11 @@ import * as helpers from './util/helpers'; describe('Deep Linking task', () => { describe('deepLinkingWorkerImpl', () => { + + beforeEach(() => { + deepLinking.reset(); + }); + it('should not update app ngmodule when it has an existing deeplink config', () => { const appNgModulePath = join('some', 'fake', 'path', 'myApp', 'src', 'app', 'app.module.ts'); const context = { @@ -26,6 +31,7 @@ describe('Deep Linking task', () => { const promise = deepLinking.deepLinkingWorkerImpl(context, null); return promise.then(() => { + expect(deepLinking.cachedUnmodifiedAppNgModuleFileContent).toEqual(knownFileContent); expect(deeplinkUtils.convertDeepLinkConfigEntriesToString).not.toHaveBeenCalled(); expect(deeplinkUtils.updateAppNgModuleAndFactoryWithDeepLinkConfig).not.toHaveBeenCalled(); }); @@ -73,6 +79,7 @@ describe('Deep Linking task', () => { const promise = deepLinking.deepLinkingWorkerImpl(context, changedFiles); return promise.then(() => { + expect(deepLinking.cachedDeepLinkString).toEqual(knownDeepLinkString); expect(helpers.getStringPropertyValue).toBeCalledWith(Constants.ENV_APP_NG_MODULE_PATH); expect(deeplinkUtils.getDeepLinkData).toHaveBeenCalledWith(appNgModulePath, context.fileCache, context.runAot); expect(deeplinkUtils.hasExistingDeepLinkConfig).toHaveBeenCalledWith(appNgModulePath, knownFileContent); @@ -80,5 +87,110 @@ describe('Deep Linking task', () => { expect(deeplinkUtils.updateAppNgModuleAndFactoryWithDeepLinkConfig).toHaveBeenCalledWith(context, knownDeepLinkString, changedFiles, context.runAot); }); }); + + it('should update deeplink config on subsequent updates when the deeplink string is different', () => { + const appNgModulePath = join('some', 'fake', 'path', 'myApp', 'src', 'app', 'app.module.ts'); + const context = { + fileCache: new FileCache(), + runAot: true + }; + const knownFileContent = 'someFileContent'; + const knownDeepLinkString = 'someDeepLinkString'; + const knownDeepLinkString2 = 'someDeepLinkString2'; + const knownMockDeepLinkArray = [1]; + const changedFiles: ChangedFile[] = null; + context.fileCache.set(appNgModulePath, { path: appNgModulePath, content: knownFileContent}); + + spyOn(helpers, helpers.getStringPropertyValue.name).and.returnValue(appNgModulePath); + spyOn(deeplinkUtils, deeplinkUtils.getDeepLinkData.name).and.returnValue(knownMockDeepLinkArray); + spyOn(deeplinkUtils, deeplinkUtils.hasExistingDeepLinkConfig.name).and.returnValue(false); + + let hasConvertDeepLinkConfigToStringBeenCalled = false; + spyOn(deeplinkUtils, deeplinkUtils.convertDeepLinkConfigEntriesToString.name).and.callFake(() => { + if (!hasConvertDeepLinkConfigToStringBeenCalled) { + hasConvertDeepLinkConfigToStringBeenCalled = true; + return knownDeepLinkString; + } + return knownDeepLinkString2; + }); + + const spy = spyOn(deeplinkUtils, deeplinkUtils.updateAppNgModuleAndFactoryWithDeepLinkConfig.name); + + const promise = deepLinking.deepLinkingWorkerImpl(context, changedFiles); + + return promise.then(() => { + expect(deepLinking.cachedDeepLinkString).toEqual(knownDeepLinkString); + expect(helpers.getStringPropertyValue).toBeCalledWith(Constants.ENV_APP_NG_MODULE_PATH); + expect(deeplinkUtils.getDeepLinkData).toHaveBeenCalledWith(appNgModulePath, context.fileCache, context.runAot); + expect(deeplinkUtils.hasExistingDeepLinkConfig).toHaveBeenCalledWith(appNgModulePath, knownFileContent); + expect(deeplinkUtils.convertDeepLinkConfigEntriesToString).toHaveBeenCalledWith(knownMockDeepLinkArray); + expect(spy.calls.first().args[0]).toEqual(context); + expect(spy.calls.first().args[1]).toEqual(knownDeepLinkString); + expect(spy.calls.first().args[2]).toEqual(changedFiles); + expect(spy.calls.first().args[3]).toEqual(context.runAot); + + return deepLinking.deepLinkingWorkerImpl(context, changedFiles); + }).then((result) => { + expect(deepLinking.cachedDeepLinkString).toEqual(knownDeepLinkString2); + expect(deeplinkUtils.getDeepLinkData).toHaveBeenCalledTimes(2); + expect(deeplinkUtils.getDeepLinkData).toHaveBeenCalledWith(appNgModulePath, context.fileCache, context.runAot); + expect(deeplinkUtils.hasExistingDeepLinkConfig).toHaveBeenCalledTimes(2); + expect(deeplinkUtils.hasExistingDeepLinkConfig).toHaveBeenCalledWith(appNgModulePath, knownFileContent); + expect(deeplinkUtils.convertDeepLinkConfigEntriesToString).toHaveBeenCalledWith(knownMockDeepLinkArray); + expect(deeplinkUtils.convertDeepLinkConfigEntriesToString).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledTimes(2); + expect(spy.calls.mostRecent().args[0]).toEqual(context); + expect(spy.calls.mostRecent().args[1]).toEqual(knownDeepLinkString2); + expect(spy.calls.mostRecent().args[2]).toEqual(changedFiles); + expect(spy.calls.mostRecent().args[3]).toEqual(context.runAot); + }); + }); + + it('should not update deeplink config on subsequent updates when the deeplink string is the same', () => { + const appNgModulePath = join('some', 'fake', 'path', 'myApp', 'src', 'app', 'app.module.ts'); + const context = { + fileCache: new FileCache(), + runAot: true + }; + const knownFileContent = 'someFileContent'; + const knownDeepLinkString = 'someDeepLinkString'; + const knownMockDeepLinkArray = [1]; + const changedFiles: ChangedFile[] = null; + context.fileCache.set(appNgModulePath, { path: appNgModulePath, content: knownFileContent}); + + spyOn(helpers, helpers.getStringPropertyValue.name).and.returnValue(appNgModulePath); + spyOn(deeplinkUtils, deeplinkUtils.getDeepLinkData.name).and.returnValue(knownMockDeepLinkArray); + spyOn(deeplinkUtils, deeplinkUtils.hasExistingDeepLinkConfig.name).and.returnValue(false); + + spyOn(deeplinkUtils, deeplinkUtils.convertDeepLinkConfigEntriesToString.name).and.returnValue(knownDeepLinkString); + + const spy = spyOn(deeplinkUtils, deeplinkUtils.updateAppNgModuleAndFactoryWithDeepLinkConfig.name); + + const promise = deepLinking.deepLinkingWorkerImpl(context, changedFiles); + + return promise.then(() => { + expect(deepLinking.cachedDeepLinkString).toEqual(knownDeepLinkString); + expect(helpers.getStringPropertyValue).toBeCalledWith(Constants.ENV_APP_NG_MODULE_PATH); + expect(deeplinkUtils.getDeepLinkData).toHaveBeenCalledWith(appNgModulePath, context.fileCache, context.runAot); + expect(deeplinkUtils.hasExistingDeepLinkConfig).toHaveBeenCalledWith(appNgModulePath, knownFileContent); + expect(deeplinkUtils.convertDeepLinkConfigEntriesToString).toHaveBeenCalledWith(knownMockDeepLinkArray); + expect(spy.calls.first().args[0]).toEqual(context); + expect(spy.calls.first().args[1]).toEqual(knownDeepLinkString); + expect(spy.calls.first().args[2]).toEqual(changedFiles); + expect(spy.calls.first().args[3]).toEqual(context.runAot); + + return deepLinking.deepLinkingWorkerImpl(context, changedFiles); + }).then((result) => { + expect(result).toEqual(knownMockDeepLinkArray); + expect(deepLinking.cachedDeepLinkString).toEqual(knownDeepLinkString); + expect(deeplinkUtils.getDeepLinkData).toHaveBeenCalledTimes(2); + expect(deeplinkUtils.getDeepLinkData).toHaveBeenCalledWith(appNgModulePath, context.fileCache, context.runAot); + expect(deeplinkUtils.hasExistingDeepLinkConfig).toHaveBeenCalledTimes(2); + expect(deeplinkUtils.hasExistingDeepLinkConfig).toHaveBeenCalledWith(appNgModulePath, knownFileContent); + expect(deeplinkUtils.convertDeepLinkConfigEntriesToString).toHaveBeenCalledWith(knownMockDeepLinkArray); + expect(deeplinkUtils.convertDeepLinkConfigEntriesToString).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledTimes(1); + }); + }); }); }); diff --git a/src/deep-linking.ts b/src/deep-linking.ts index f8ab95db..3831ecce 100644 --- a/src/deep-linking.ts +++ b/src/deep-linking.ts @@ -15,7 +15,8 @@ import { convertDeepLinkConfigEntriesToString, getDeepLinkData, hasExistingDeepL * as the cached version of the App's main NgModule content will basically always * have a generated deep likn config in it. */ -let cachedUnmodifiedAppNgModuleFileContent: string = null; +export let cachedUnmodifiedAppNgModuleFileContent: string = null; +export let cachedDeepLinkString: string = null; export function deepLinking(context: BuildContext) { const logger = new Logger(`deeplinks`); @@ -42,12 +43,26 @@ export function deepLinkingWorkerImpl(context: BuildContext, changedFiles: Chang if (!cachedUnmodifiedAppNgModuleFileContent) { cachedUnmodifiedAppNgModuleFileContent = appNgModuleFile.content; } - const deepLinkConfigEntries = getDeepLinkData(appNgModulePath, context.fileCache, context.runAot); + + // is there is an existing (legacy) deep link config, just move on and don't look for decorators const hasExisting = hasExistingDeepLinkConfig(appNgModulePath, cachedUnmodifiedAppNgModuleFileContent); - if (!hasExisting && deepLinkConfigEntries && deepLinkConfigEntries.length) { - // only update the app's main ngModule if there isn't an existing config - const deepLinkString = convertDeepLinkConfigEntriesToString(deepLinkConfigEntries); - updateAppNgModuleAndFactoryWithDeepLinkConfig(context, deepLinkString, changedFiles, context.runAot); + if (hasExisting) { + return []; + } + + const deepLinkConfigEntries = getDeepLinkData(appNgModulePath, context.fileCache, context.runAot) || []; + if (deepLinkConfigEntries.length) { + const newDeepLinkString = convertDeepLinkConfigEntriesToString(deepLinkConfigEntries); + if (!cachedDeepLinkString) { + // this is the first time running this, so update the build either way + cachedDeepLinkString = newDeepLinkString; + updateAppNgModuleAndFactoryWithDeepLinkConfig(context, newDeepLinkString, changedFiles, context.runAot); + } else if (newDeepLinkString !== cachedDeepLinkString) { + // we have an existing deep link string, and we have a new one, and they're different + // so go ahead and update the config + cachedDeepLinkString = newDeepLinkString; + updateAppNgModuleAndFactoryWithDeepLinkConfig(context, newDeepLinkString, changedFiles, context.runAot); + } } return deepLinkConfigEntries; }); @@ -89,3 +104,9 @@ export function deepLinkingWorkerFullUpdate(context: BuildContext) { throw logger.fail(error); }); } + +// this is purely for testing +export function reset() { + cachedUnmodifiedAppNgModuleFileContent = null; + cachedDeepLinkString = null; +} \ No newline at end of file