@@ -13,6 +13,7 @@ import {
1313 Component ,
1414 DestroyRef ,
1515 ElementRef ,
16+ EnvironmentInjector ,
1617 OnDestroy ,
1718 ViewChild ,
1819 inject ,
@@ -21,10 +22,9 @@ import {
2122import { takeUntilDestroyed } from '@angular/core/rxjs-interop' ;
2223import { MatTabGroup , MatTabsModule } from '@angular/material/tabs' ;
2324import { Title } from '@angular/platform-browser' ;
24- import { debounceTime , map } from 'rxjs' ;
25+ import { debounceTime , from , map , switchMap } from 'rxjs' ;
2526
2627import { TerminalType } from '../terminal/terminal-handler.service' ;
27- import { EmbeddedTutorialManager } from '../embedded-tutorial-manager.service' ;
2828
2929import { CodeMirrorEditor } from './code-mirror-editor.service' ;
3030import { DiagnosticWithLocation , DiagnosticsState } from './services/diagnostics-state.service' ;
@@ -34,6 +34,7 @@ import {ClickOutside, IconComponent} from '@angular/docs';
3434import { CdkMenu , CdkMenuItem , CdkMenuTrigger } from '@angular/cdk/menu' ;
3535import { IDXLauncher } from '../idx-launcher.service' ;
3636import { MatTooltip } from '@angular/material/tooltip' ;
37+ import { injectEmbeddedTutorialManager } from '../inject-embedded-tutorial-manager' ;
3738
3839export const REQUIRED_FILES = new Set ( [
3940 'src/main.ts' ,
@@ -91,7 +92,7 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
9192 private readonly idxLauncher = inject ( IDXLauncher ) ;
9293 private readonly title = inject ( Title ) ;
9394 private readonly location = inject ( Location ) ;
94- private readonly embeddedTutorialManager = inject ( EmbeddedTutorialManager ) ;
95+ private readonly environmentInjector = inject ( EnvironmentInjector ) ;
9596
9697 private readonly errors$ = this . diagnosticsState . diagnostics$ . pipe (
9798 // Display errors one second after code update
@@ -142,7 +143,8 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
142143 }
143144
144145 async downloadCurrentCodeEditorState ( ) : Promise < void > {
145- const name = this . embeddedTutorialManager . tutorialId ( ) ;
146+ const embeddedTutorialManager = await injectEmbeddedTutorialManager ( this . environmentInjector ) ;
147+ const name = embeddedTutorialManager . tutorialId ( ) ;
146148 await this . downloadManager . downloadCurrentStateOfTheSolution ( name ) ;
147149 }
148150
@@ -236,8 +238,14 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
236238 }
237239
238240 private setSelectedTabOnTutorialChange ( ) {
239- this . embeddedTutorialManager . tutorialChanged$
240- . pipe ( takeUntilDestroyed ( this . destroyRef ) )
241+ // Using `from` to prevent injecting the embedded tutorial manager once the
242+ // injector is destroyed (this may happen in unit tests when the test ends
243+ // before `injectAsync` runs, causing an error).
244+ from ( injectEmbeddedTutorialManager ( this . environmentInjector ) )
245+ . pipe (
246+ switchMap ( ( embeddedTutorialManager ) => embeddedTutorialManager . tutorialChanged$ ) ,
247+ takeUntilDestroyed ( this . destroyRef ) ,
248+ )
241249 . subscribe ( ( ) => {
242250 // selected file on project change is always the first
243251 this . matTabGroup . selectedIndex = 0 ;
0 commit comments