|
6 | 6 | * found in the LICENSE file at https://angular.dev/license |
7 | 7 | */ |
8 | 8 |
|
| 9 | +import ts from 'typescript'; |
9 | 10 | import type { AngularHostOptions } from '../angular-host'; |
10 | 11 | import { |
11 | 12 | AngularCompilation, |
12 | 13 | AngularCompilationResult, |
| 14 | + DiagnosticModes, |
13 | 15 | NoopCompilation, |
| 16 | + TypeScriptCompilation, |
14 | 17 | createAngularCompilation, |
15 | 18 | } from './index'; |
16 | 19 |
|
@@ -68,15 +71,90 @@ describe('AngularCompilation', () => { |
68 | 71 | expect(result.compilerOptions['customOption']).toBe(true); |
69 | 72 | }); |
70 | 73 |
|
71 | | - it('throws when calling collectDiagnostics or emitAffectedFiles', () => { |
| 74 | + it('throws when calling emitAffectedFiles', () => { |
72 | 75 | const compilation = new NoopCompilation(); |
73 | | - expect(() => |
74 | | - (compilation as unknown as { collectDiagnostics(): unknown }).collectDiagnostics(), |
75 | | - ).toThrowError('Not available when using noop compilation.'); |
76 | 76 | expect(() => compilation.emitAffectedFiles()).toThrowError( |
77 | 77 | 'Not available when using noop compilation.', |
78 | 78 | ); |
79 | 79 | }); |
| 80 | + |
| 81 | + it('returns empty diagnostics from diagnoseFiles', async () => { |
| 82 | + const compilation = new NoopCompilation(); |
| 83 | + const diagnostics = await compilation.diagnoseFiles(); |
| 84 | + expect(diagnostics).toEqual({}); |
| 85 | + }); |
| 86 | + }); |
| 87 | + |
| 88 | + describe('TypeScriptCompilation', () => { |
| 89 | + class MockTypeScriptCompilation extends TypeScriptCompilation { |
| 90 | + async initialize(): Promise<AngularCompilationResult> { |
| 91 | + return { compilerOptions: {}, referencedFiles: [] }; |
| 92 | + } |
| 93 | + |
| 94 | + protected override *collectDiagnostics(modes: DiagnosticModes): Iterable<ts.Diagnostic> { |
| 95 | + if (modes & DiagnosticModes.Option) { |
| 96 | + yield { |
| 97 | + category: ts.DiagnosticCategory.Error, |
| 98 | + code: 1234, |
| 99 | + messageText: 'Mock option error', |
| 100 | + file: undefined, |
| 101 | + start: undefined, |
| 102 | + length: undefined, |
| 103 | + }; |
| 104 | + } |
| 105 | + if (modes & DiagnosticModes.Semantic) { |
| 106 | + yield { |
| 107 | + category: ts.DiagnosticCategory.Warning, |
| 108 | + code: 5678, |
| 109 | + messageText: 'Mock semantic warning', |
| 110 | + file: undefined, |
| 111 | + start: undefined, |
| 112 | + length: undefined, |
| 113 | + }; |
| 114 | + } |
| 115 | + } |
| 116 | + |
| 117 | + public getCachedSourceFiles(): Map<string, ts.SourceFile> { |
| 118 | + return this.sourceFiles; |
| 119 | + } |
| 120 | + } |
| 121 | + |
| 122 | + it('collects and converts diagnostics categorized by error and warning', async () => { |
| 123 | + const compilation = new MockTypeScriptCompilation(); |
| 124 | + const diagnostics = await compilation.diagnoseFiles(DiagnosticModes.All); |
| 125 | + |
| 126 | + expect(diagnostics.errors?.length).toBe(1); |
| 127 | + expect(diagnostics.errors?.[0].text).toContain('Mock option error'); |
| 128 | + expect(diagnostics.warnings?.length).toBe(1); |
| 129 | + expect(diagnostics.warnings?.[0].text).toContain('Mock semantic warning'); |
| 130 | + }); |
| 131 | + |
| 132 | + it('filters diagnostics according to requested DiagnosticModes', async () => { |
| 133 | + const compilation = new MockTypeScriptCompilation(); |
| 134 | + const diagnostics = await compilation.diagnoseFiles(DiagnosticModes.Option); |
| 135 | + |
| 136 | + expect(diagnostics.errors?.length).toBe(1); |
| 137 | + expect(diagnostics.errors?.[0].text).toContain('Mock option error'); |
| 138 | + expect(diagnostics.warnings).toBeUndefined(); |
| 139 | + }); |
| 140 | + |
| 141 | + it('returns empty diagnostics immediately when mode is DiagnosticModes.None', async () => { |
| 142 | + const compilation = new MockTypeScriptCompilation(); |
| 143 | + const diagnostics = await compilation.diagnoseFiles(DiagnosticModes.None); |
| 144 | + |
| 145 | + expect(diagnostics).toEqual({}); |
| 146 | + }); |
| 147 | + |
| 148 | + it('evicts files from AST cache on update and invalidateFiles', async () => { |
| 149 | + const compilation = new MockTypeScriptCompilation(); |
| 150 | + const mockSourceFile = ts.createSourceFile('test.ts', '', ts.ScriptTarget.Latest); |
| 151 | + compilation.getCachedSourceFiles().set('/src/test.ts', mockSourceFile); |
| 152 | + |
| 153 | + expect(compilation.getCachedSourceFiles().has('/src/test.ts')).toBeTrue(); |
| 154 | + |
| 155 | + await compilation.update?.(new Set(['/src/test.ts'])); |
| 156 | + expect(compilation.getCachedSourceFiles().has('/src/test.ts')).toBeFalse(); |
| 157 | + }); |
80 | 158 | }); |
81 | 159 |
|
82 | 160 | describe('createAngularCompilation', () => { |
|
0 commit comments