I am running Angular unit test with Jasmine/Karma. Currently getting the below error:
TypeError: Cannot read property 'name' of undefined
at ReplicateListComponent_Template (ng:///ReplicateListComponent.js:221:64)
at executeTemplate (http://localhost:9876/_karma_webpack_/vendor.js:49857:9)
at refreshView (http://localhost:9876/_karma_webpack_/vendor.js:49723:13)
at refreshComponent (http://localhost:9876/_karma_webpack_/vendor.js:50894:13)
at refreshChildComponents (http://localhost:9876/_karma_webpack_/vendor.js:49520:9)
Line 221 of ReplicateListComponent.js:
jit___property_12('title',jit___pipeBind1_9(13,28,'upload_replicate_tooltip'))('routerLink',
jit___pureFunction1_10(32,_c1,ctx.managementConfig.name));
jit___advance_6(3);
ctx.managementConfig.name - ctx does not have a variable named managementConfig - see screenshot.
Unit test code:
let component: ReplicateViewComponent;
let fixture: ComponentFixture<ReplicateViewComponent>;
let params: Subject<Params>;
let queryParams: Subject<Params>;
let mockManagementService: jasmine.SpyObj<ManagementConfigService>;
let getManagementConfig: Subject<IManagementConfig>;
let environmentSwitched: Subject<string>;
beforeEach(async () => {
params = new Subject<Params>();
queryParams = new Subject<Params>();
mockManagementService = jasmine.createSpyObj<ManagementConfigService>([ 'getManagementConfig', 'getCurrentManagementConfig', 'findManagementConfig', 'environmentSwitched' ]);
getManagementConfig = new Subject<IManagementConfig>();
environmentSwitched = new Subject<string>();
...
await TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
ToastrModule.forRoot({}),
RouterTestingModule.withRoutes([
{ path: ':env/replicates', component: DummyComponent },
]),
...
],
declarations: [
ReplicateViewComponent,
...
ReplicateListComponent,
...
],
providers: [
{ provide: ManagementConfigService, useValue: mockManagementService },
{ provide: ActivatedRoute, useValue: ACTIVATED_ROUTE },
{ provide: RuntimeConfig, useValue: RUNTIME_CONFIG },
...
],
})
.compileComponents();
mockManagementService.getManagementConfig.and.returnValue(getManagementConfig);
mockManagementService.getCurrentManagementConfig.and.returnValue(RUNTIME_CONFIG.environments[0]);
mockManagementService.findManagementConfig.and.returnValue(RUNTIME_CONFIG.environments[0]);
mockManagementService.environmentSwitched.and.returnValue(environmentSwitched);
});
beforeEach(() => {
fixture = TestBed.createComponent(ReplicateViewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
component.list.managementConfig = RUNTIME_CONFIG.environments[0];
component.list.replicates = REPLICATIONS;
component.details.replicate = REPLICATIONS[0];
const router = TestBed.inject(Router);
router.initialNavigation();
getManagementConfig.next(RUNTIME_CONFIG.environments[0]);
environmentSwitched.next(RUNTIME_CONFIG.environments[0].name);
params.next({ id: '11111111-1111-1111-1111-111111111111' });
});
it('should create', () => {
expect(component).toBeTruthy();
expect(component.list).toBeTruthy();
expect(component.details).toBeTruthy();
});
Reason why am I expecting there to be a variable named managementConfig :
export class ReplicateListComponent extends BaseContainerComponent implements OnInit {
managementConfig: IManagementConfig;
...
ngOnInit(): void {
this.subs.add(
this.route.params.subscribe(
(params: Params) => {
this.managementConfig = this.managementService.findManagementConfig(params.env);
Offending section of ReplicateListComponent's HTML - see the routerLink
<div class="my-auto ml-auto">
<a data-cy="batchReplicateLink" [title]="'upload_replicate_tooltip' | translate" [routerLink]="[ '/', managementConfig.name, 'replicates', 'batch']" queryParamsHandling="preserve">
<i class="icons8-sm icons8-Copy"></i>{{ 'replicate_batch_link' | translate }}
</a>
</div>
ReplicateListComponent.js is very similar to AssetListComponent.js which does not have the error. As you can see from the screenshot there is a managementConfig within the context of AssetListComponent:
The routerLink HTML of AssetListComponent is essentially the same:
<a
data-cy="uploadLink"
[title]="'upload_asset_tooltip' | translate"
[routerLink]="[ '/', managementConfig.name, 'assets', 'upload']"
[queryParamsHandling]="'preserve'"
*ngIf="managementConfig?.upload"
>
<i class="icons8-sm icons8-Upload"></i>{{ 'asset_list_upload_link' | translate }}
</a>
Backend code of AssetListComponent:
export class AssetListComponent extends BaseContainerComponent implements OnInit {
managementConfig: IManagementConfig;
...
ngOnInit(): void {
this.subs.add(
this.route.params.subscribe(
(params: Params) => {
this.managementConfig = this.managementService.findManagementConfig(params.env);
- What caused the error?
- What is the fix?
- Why is the error in ReplicateListComponent but not AssetListComponent?
Thanks.

