fix(devtools): update the prod mode detection to also consider VE apps

Fix rangle/angular-devtools#798
This commit is contained in:
mgechev 2021-05-23 10:48:21 -07:00 committed by Minko Gechev
parent d60bdfc207
commit e6bec2430a
2 changed files with 117 additions and 4 deletions

View file

@ -0,0 +1,109 @@
import {
appIsAngularInDevMode,
appIsAngularIvy,
appIsAngular,
appIsSupportedAngularVersion,
getAngularVersion,
} from './angular-check';
const setNgVersion = (version = '12.0.0') => document.documentElement.setAttribute('ng-version', version);
const removeNgVersion = () => document.documentElement.removeAttribute('ng-version');
describe('angular-check', () => {
afterEach(() => removeNgVersion());
describe('getAngularVersion', () => {
it('should return the angular version', () => {
setNgVersion('11.1.1');
expect(getAngularVersion()).toBe('11.1.1');
});
});
describe('appIsSupportedAngularVersion', () => {
it('should work with g3', () => {
setNgVersion('0.0.0-placeholder');
expect(appIsSupportedAngularVersion()).toBeTrue();
});
it('should work with new versions', () => {
setNgVersion('9.0.0');
expect(appIsSupportedAngularVersion()).toBeTrue();
});
it('should return false for older version', () => {
setNgVersion('8.0.0');
expect(appIsSupportedAngularVersion()).toBeFalse();
});
it('should return false for no version', () => {
expect(appIsSupportedAngularVersion()).toBeFalse();
});
});
describe('appIsAngular', () => {
it('should return true for older version', () => {
setNgVersion('8.0.0');
expect(appIsAngular()).toBeTrue();
});
it('should return false for no version', () => {
expect(appIsAngular()).toBeFalse();
});
});
describe('appIsAngularIvy', () => {
it('should not recognize VE apps', () => {
(window as any).ng = {
probe() {},
};
setNgVersion();
expect(appIsAngularIvy()).toBeFalse();
});
it('should not recognize no Angular apps', () => {
expect(appIsAngularIvy()).toBeFalse();
});
it('should recognize Ivy apps', () => {
(window as any).getAllAngularRootElements = () => {
const el = document.createElement('div');
(el as any).__ngContext__ = 0;
return [el];
};
expect(appIsAngularIvy()).toBeTrue();
delete (window as any).getAllAngularRootElements;
});
});
describe('appIsAngularInDevMode', () => {
afterEach(() => {
delete (window as any).ng;
});
it('should detect VE apps', () => {
(window as any).ng = {
probe() {},
};
setNgVersion();
expect(appIsAngularInDevMode()).toBeTrue();
});
it('should detect Ivy apps', () => {
(window as any).ng = {
getComponent() {},
};
setNgVersion();
expect(appIsAngularInDevMode()).toBeTrue();
});
it('should not detect apps if `ng` is not an object with the right shape', () => {
setNgVersion();
(window as any).ng = {};
expect(appIsAngularInDevMode()).toBeFalse();
(window as any).ng = () => {};
expect(appIsAngularInDevMode()).toBeFalse();
});
});
});

View file

@ -23,14 +23,18 @@ export const appIsSupportedAngularVersion = (): boolean => {
/**
* We check if the global `window.ng` is an object and if this object
* has the `getComponent` method attached to it. In some g3 apps processed
* with Closure, `ng` is a function, which means that `typeof ng !== 'undefined'`
* is not a sufficient check.
* has the `getComponent` or `probe` methods attached to it.
*
* `ng.probe` is a view engine method, but to ensure that we correctly
* detect development mode we need to consider older rendering engines.
*
* In some g3 apps processed with Closure, `ng` is a function,
* which means that `typeof ng !== 'undefined'` is not a sufficient check.
*
* @returns if the app has global ng debug object
*/
const appHasGlobalNgDebugObject = (): boolean => {
return typeof ng === 'object' && typeof ng.getComponent === 'function';
return typeof ng === 'object' && (typeof ng.getComponent === 'function' || typeof ng.probe === 'function');
};
export const getAngularVersion = (): string | null => {