0

When running unit tests I am getting the error:

TypeError: Cannot read property 'value' of undefined

enter image description here

In the component.ts file I have tried intializing all values:

    @Input() beneficiary: string = '';
    
        pageInfo: { startingPayment: number; endingPayment: number; total: number };
    
        history = new BehaviorSubject<[]>([]);
        history$: Observable<[]> = null;
    
        pageNumber = 1;
        maxPages: number = 0;
        maxPerPage: number = 0;
        totalPayments: number = 0;
        prevBtnDisabled = true;
        nextBtnDisabled = true;
        errorMessage: string = '';
        handleId: string = '';
        apiCalled = true;
    
        paginator: MatPaginator = null;
    
        constructor(private thirdPartyAccountsStoreService: ThirdPartyAccountsStoreService) {
            this.history$ = this.history.asObservable();
        }

    ngOnInit(): void {
        this.getPaymentInitHistory();
    }

    getPaymentInitHistory() {
        if (this.beneficiary) {
            this.apiCalled = true;
            this.resetProperties();
            this.thirdPartyAccountsStoreService.getPaymentInitHistory(this.beneficiary).subscribe(
                (result: any) => {
                    this.handleId = result.input.value;
                    this.setUpPagesProperties(result.model[0]);
                    this.handleResponse(result);
                },
                (error) => this.handleError(error)
            );
        }
    }

In the html I added ngIf to check history$ before running the ngFor:

<div *ngIf="history$">
    <div class="grid" *ngFor="let row of history$ | async">
    <div class="grid-row">
        <div class="text-size">{{ row.valuedate | appFormatDate | async }}</div>
        <div class="secondary-text">{{ row.narrative }}</div>
    </div>
    <div class="grid-row-end">
        <div class="text-size">
            <app-amount [value]="row.credit" [currency]="row.currency"></app-amount>
        </div>
        <div class="secondary-text">{{ row.contranarrative }}</div>
    </div>

I am not sure what is causing this error. The only place value is used is in the html page [value]="row.credit" and I have tried using [value]="row?.credit" but that hasn't worked either. And in the ts file in the file this.handleId = result.input.value; but I added a check if (this.beneficiary) so if that field is blank it shouldn't run the code in the function

user123456789
  • 1,914
  • 7
  • 44
  • 100

2 Answers2

0

This might be because of history$, while you are using it with async in view.

You are initializing it with null. So async will start to evaluate value of history$ immediately after view initialization, Hence you are getting the error.

Try to initialize the history$ like below

history$: Observable<[]> = new Observable();

Edit:

You can try by Initializing in two ways:

history$ = Observable.of<any>([]);

By doing this Object will be initialized as Observable immediately. (what is the difference between "new Observable()" and "of()" in RxJs)

*ngIf="(history$ | async).length"

We can also check it before evaluation..

Happy Coding.. :)

Ganesh
  • 5,808
  • 2
  • 21
  • 41
  • Still getting the error.. Does adding `
    ` not work then? If `history$` is null then it shouldn't run ngFor. That's what I was trying to do to stop this error. Or is there a different way to check history$?
    – user123456789 Mar 25 '21 at 09:59
0

Unfortunately you cropped the most important part of the stacktrace but I'll take a wild guess:

getPaymentInitHistory() {
    if (this.beneficiary) {
        this.apiCalled = true;
        this.resetProperties();
        this.thirdPartyAccountsStoreService.getPaymentInitHistory(this.beneficiary).subscribe(
            (result: any) => { 
                // I guess here's the problem
                this.handleId = result.input.value;
                this.setUpPagesProperties(result.model[0]);
                this.handleResponse(result);
            },
            (error) => this.handleError(error)
        );
    }
}

result might not have the property input. Therefore result.input gets resolved to undefined. And undefined.value results in the error message: Cannot read property 'value' of undefined.

Therefore use this.handleId = result.input?.value ?? '-1'; and handleId becomes '-1' whenever the property input is missing.

For reference: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#optional-chaining and https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing

acincognito
  • 1,595
  • 1
  • 13
  • 24