refactor(core): add links to top runtime errors (#40326)
add links to 5 runtime error messages navigate user to AIO new /errors pages for debugging PR Close #40326
This commit is contained in:
		
							parent
							
								
									0568c7387f
								
							
						
					
					
						commit
						bfdca0b87f
					
				| @ -63,9 +63,11 @@ describe('Ivy NgModule', () => { | ||||
|       } | ||||
| 
 | ||||
|       const errorCode = ivyEnabled ? 'NG0200: ' : ''; | ||||
|       const errorLink = ivyEnabled ? '. Find more at https://angular.io/errors/NG0200' : ''; | ||||
|       expect(() => createInjector(AModule)) | ||||
|           .toThrowError(`${ | ||||
|               errorCode}Circular dependency in DI detected for AModule. Dependency path: AModule > BModule > AModule`);
 | ||||
|               errorCode}Circular dependency in DI detected for AModule. Dependency path: AModule > BModule > AModule${ | ||||
|               errorLink}`);
 | ||||
|     }); | ||||
| 
 | ||||
|     it('merges imports and exports', () => { | ||||
|  | ||||
| @ -6,6 +6,11 @@ | ||||
|  * found in the LICENSE file at https://angular.io/license
 | ||||
|  */ | ||||
| 
 | ||||
| // Base URL for the error details page.
 | ||||
| // Keep this value in sync with a similar const in
 | ||||
| // `packages/compiler-cli/src/ngtsc/diagnostics/src/error_code.ts`.
 | ||||
| const ERROR_DETAILS_PAGE_BASE_URL = 'https://angular.io/errors'; | ||||
| 
 | ||||
| export const enum RuntimeErrorCode { | ||||
|   // Internal Errors
 | ||||
| 
 | ||||
| @ -38,8 +43,32 @@ export class RuntimeError extends Error { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // Contains a set of error messages that have details guides at angular.io.
 | ||||
| // Full list of available error guides can be found at https://angular.io/errors
 | ||||
| /* tslint:disable:no-toplevel-property-access */ | ||||
| export const RUNTIME_ERRORS_WITH_GUIDES = new Set([ | ||||
|   RuntimeErrorCode.EXPRESSION_CHANGED_AFTER_CHECKED, | ||||
|   RuntimeErrorCode.CYCLIC_DI_DEPENDENCY, | ||||
|   RuntimeErrorCode.PROVIDER_NOT_FOUND, | ||||
|   RuntimeErrorCode.MULTIPLE_COMPONENTS_MATCH, | ||||
|   RuntimeErrorCode.EXPORT_NOT_FOUND, | ||||
| ]); | ||||
| /* tslint:enable:no-toplevel-property-access */ | ||||
| 
 | ||||
| /** Called to format a runtime error */ | ||||
| export function formatRuntimeError(code: RuntimeErrorCode, message: string): string { | ||||
|   const fullCode = code ? `NG0${code}: ` : ''; | ||||
|   return `${fullCode}${message}`; | ||||
| 
 | ||||
|   let errorMessage = `${fullCode}${message}`; | ||||
| 
 | ||||
|   // Some runtime errors are still thrown without `ngDevMode` (for example
 | ||||
|   // `throwProviderNotFoundError`), so we add `ngDevMode` check here to avoid pulling
 | ||||
|   // `RUNTIME_ERRORS_WITH_GUIDES` symbol into prod bundles.
 | ||||
|   // TODO: revisit all instances where `RuntimeError` is thrown and see if `ngDevMode` can be added
 | ||||
|   // there instead to tree-shake more devmode-only code (and eventually remove `ngDevMode` check
 | ||||
|   // from this code).
 | ||||
|   if (ngDevMode && RUNTIME_ERRORS_WITH_GUIDES.has(code)) { | ||||
|     errorMessage = `${errorMessage}. Find more at ${ERROR_DETAILS_PAGE_BASE_URL}/NG0${code}`; | ||||
|   } | ||||
|   return errorMessage; | ||||
| } | ||||
|  | ||||
| @ -617,7 +617,8 @@ describe('di', () => { | ||||
| 
 | ||||
|           TestBed.configureTestingModule({declarations: [DirectiveA, DirectiveB, MyComp]}); | ||||
|           expect(() => TestBed.createComponent(MyComp)) | ||||
|               .toThrowError('NG0200: Circular dependency in DI detected for DirectiveA'); | ||||
|               .toThrowError( | ||||
|                   'NG0200: Circular dependency in DI detected for DirectiveA. Find more at https://angular.io/errors/NG0200'); | ||||
|         }); | ||||
| 
 | ||||
|     onlyInIvy('Ivy has different error message for circular dependency') | ||||
| @ -633,7 +634,8 @@ describe('di', () => { | ||||
| 
 | ||||
|           TestBed.configureTestingModule({declarations: [DirectiveA, DirectiveB, MyComp]}); | ||||
|           expect(() => TestBed.createComponent(MyComp)) | ||||
|               .toThrowError('NG0200: Circular dependency in DI detected for DirectiveA'); | ||||
|               .toThrowError( | ||||
|                   'NG0200: Circular dependency in DI detected for DirectiveA. Find more at https://angular.io/errors/NG0200'); | ||||
|         }); | ||||
| 
 | ||||
|     describe('flags', () => { | ||||
| @ -1779,7 +1781,8 @@ describe('di', () => { | ||||
| 
 | ||||
|               TestBed.configureTestingModule({declarations: [DirectiveString, MyComp, MyApp]}); | ||||
|               expect(() => TestBed.createComponent(MyApp)) | ||||
|                   .toThrowError('NG0201: No provider for String found in NodeInjector'); | ||||
|                   .toThrowError( | ||||
|                       'NG0201: No provider for String found in NodeInjector. Find more at https://angular.io/errors/NG0201'); | ||||
|             }); | ||||
| 
 | ||||
|         onlyInIvy('Ivy has different error message when dependency is not found') | ||||
| @ -1859,7 +1862,8 @@ describe('di', () => { | ||||
| 
 | ||||
|               TestBed.configureTestingModule({declarations: [DirectiveComp, MyComp, MyApp]}); | ||||
|               expect(() => TestBed.createComponent(MyApp)) | ||||
|                   .toThrowError('NG0201: No provider for MyApp found in NodeInjector'); | ||||
|                   .toThrowError( | ||||
|                       'NG0201: No provider for MyApp found in NodeInjector. Find more at https://angular.io/errors/NG0201'); | ||||
|             }); | ||||
| 
 | ||||
|         describe('regression', () => { | ||||
|  | ||||
| @ -628,7 +628,8 @@ describe('View injector', () => { | ||||
|         .it('should not instantiate a directive with cyclic dependencies', () => { | ||||
|           TestBed.configureTestingModule({declarations: [CycleDirective]}); | ||||
|           expect(() => createComponent('<div cycleDirective></div>')) | ||||
|               .toThrowError('NG0200: Circular dependency in DI detected for CycleDirective'); | ||||
|               .toThrowError( | ||||
|                   'NG0200: Circular dependency in DI detected for CycleDirective. Find more at https://angular.io/errors/NG0200'); | ||||
|         }); | ||||
| 
 | ||||
|     obsoleteInIvy('This error is no longer generated by the compiler') | ||||
| @ -661,7 +662,8 @@ describe('View injector', () => { | ||||
|                   SimpleComponent, {set: {template: '<div needsServiceFromHost><div>'}}); | ||||
| 
 | ||||
|               expect(() => createComponent('<div simpleComponent></div>')) | ||||
|                   .toThrowError('NG0201: No provider for service found in NodeInjector'); | ||||
|                   .toThrowError( | ||||
|                       'NG0201: No provider for service found in NodeInjector. Find more at https://angular.io/errors/NG0201'); | ||||
|             }); | ||||
| 
 | ||||
|     obsoleteInIvy('This error is no longer generated by the compiler') | ||||
| @ -694,7 +696,8 @@ describe('View injector', () => { | ||||
|                   SimpleComponent, {set: {template: '<div needsServiceFromHost><div>'}}); | ||||
| 
 | ||||
|               expect(() => createComponent('<div simpleComponent someOtherDirective></div>')) | ||||
|                   .toThrowError('NG0201: No provider for service found in NodeInjector'); | ||||
|                   .toThrowError( | ||||
|                       'NG0201: No provider for service found in NodeInjector. Find more at https://angular.io/errors/NG0201'); | ||||
|             }); | ||||
| 
 | ||||
|     obsoleteInIvy('This error is no longer generated by the compiler') | ||||
| @ -717,7 +720,8 @@ describe('View injector', () => { | ||||
|               expect( | ||||
|                   () => createComponent( | ||||
|                       '<div simpleDirective><div needsDirectiveFromSelf></div></div>')) | ||||
|                   .toThrowError('NG0201: No provider for SimpleDirective found in NodeInjector'); | ||||
|                   .toThrowError( | ||||
|                       'NG0201: No provider for SimpleDirective found in NodeInjector. Find more at https://angular.io/errors/NG0201'); | ||||
|             }); | ||||
| 
 | ||||
|     it('should instantiate directives that depend on other directives', fakeAsync(() => { | ||||
| @ -779,7 +783,8 @@ describe('View injector', () => { | ||||
|               TestBed.overrideComponent( | ||||
|                   SimpleComponent, {set: {template: '<div needsDirectiveFromHost></div>'}}); | ||||
|               expect(() => createComponent('<div simpleComponent simpleDirective></div>')) | ||||
|                   .toThrowError('NG0201: No provider for SimpleDirective found in NodeInjector'); | ||||
|                   .toThrowError( | ||||
|                       'NG0201: No provider for SimpleDirective found in NodeInjector. Find more at https://angular.io/errors/NG0201'); | ||||
|             }); | ||||
| 
 | ||||
|     it('should allow to use the NgModule injector from a root ViewContainerRef.parentInjector', | ||||
|  | ||||
| @ -107,7 +107,9 @@ describe('di', () => { | ||||
|           (DirA as any)['__NG_ELEMENT_ID__'] = 1; | ||||
|           (DirC as any)['__NG_ELEMENT_ID__'] = 257; | ||||
|           new ComponentFixture(App); | ||||
|         }).toThrowError('NG0201: No provider for DirB found in NodeInjector'); | ||||
|         }) | ||||
|             .toThrowError( | ||||
|                 'NG0201: No provider for DirB found in NodeInjector. Find more at https://angular.io/errors/NG0201'); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user