Is the Angular Karma test failing to update the class properties with the method?

I am struggling to comprehend why my test is not passing.

Snapshot of the Class:

export class Viewer implements OnChanges {
    // ...
    selectedTimePeriod: number;
    timePeriods = [20, 30, 40];
    
    constructor( /* ... */) {
        this.selectLastDays(15);
    }
    
    selectLastDays(days: number): void { // triggered on click
        this.selectedTimePeriod = days;
        // ...
    }
}

Snippet of the HTML Code:

// ...
<ul>
    <li *ngFor="let period of timePeriods">
        <a [ngClass]="{'active': selectedTimePeriod === period}" 
           (click)="selectLastDays(period)">{{ period }} days
        </a>
    </li>
</ul>

Brief Overview of the Test:

beforeEach(() => {
    fixture = TestBed.createComponent(HistoryViewerComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
    dh = new DOMHelper(fixture);
});


it('should change selectedTimePeriod value to 20', async () => {
    spyOn(component, 'selectLastDays');

    dh.queryOne('li a').triggerEventHandler('click', null); // button value of 20
    dh.queryOne('li a').nativeElement.click(); // clicked even twice
    await fixture.whenStable();
    fixture.detectChanges();
    expect(component.selectLastDays).toHaveBeenCalledTimes(2); // <- true
    expect(component.selectedTimePeriod).toEqual(20); // <- false
});

it('should change selectedTimePeriod', () => { // this test passes
    expect(component.selectedTimePeriod).toEqual(15);
    component.selectLastDays(20);
    expect(component.selectedTimePeriod).toEqual(20);
});

When the button is clicked, the method selectLastdays receives parameter 20. The application functions smoothly, so why does the test fail?

Answer №1

Your initial test is flawed because you are simply spying on the selectLastDays method without actually making it do anything. By using spyOn, you are creating an empty stub that just makes the function existent but does not execute any code.

If you want to verify that the method is called, you need to make sure the stub actually executes the function. This can be achieved by using .and.callThrough()

it('should update selectedTimePeriod value to 20', async () => {
    spyOn(component, 'selectLastDays').and.callThrough();  // <= Important step

    dh.queryOne('li a').triggerEventHandler('click', null); // button value of 20
    dh.queryOne('li a').nativeElement.click(); // clicked even twice
    await fixture.whenStable();
    fixture.detectChanges();
    expect(component.selectLastDays).toHaveBeenCalledTimes(2); // <- true
    expect(component.selectedTimePeriod).toEqual(20); // <- false
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

button that decreases in size when clicked on

Currently, I am dealing with an element that functions as a button using a combination of Javascript and CSS. To better illustrate the issue, I will simplify the example by removing unnecessary details. The main problem lies in the fact that when this elem ...

The CSS is not displaying correctly on Safari and Chrome browsers in Mac OS

I'm having trouble with CSS not loading properly on Apple devices for a website I made. Despite maintaining all media query statements and style sheets separately, the display is not correct in MAC OS safari and chrome. However, everything looks fine ...

Encountering a npm script error while running on a Windows operating

While using webpack to build my application, I encountered the following error message in the command prompt: [email protected] dev D:\Myprograms\java script\forkify webpack --mode development The error mentioned: Insufficient num ...

What is the best way to retrieve a return string from an external program using XPCOM in Firefox?

Is there a way to execute an external program in XPCOM and retrieve the actual return string from it, instead of just the return code? I have researched nsICommandLine, nsICommandLineHandler, nsICommandLineRunner, and nsIProcess but it seems like none of ...

Using a combination of functions to ensure synchronicity in JavaScript operations

Here is the function I have created: $scope.saveManualResendDraft = function(todo) { if ($scope.editMode) { updateStartJobManual(); byeSendManualInputDirectly(); } else { console.log('bye'); } }; I have defin ...

Is there a maximum size limit for the Fabric.js Path Array?

Has anyone tried plotting a line graph using Fabric.js and encountered issues with the fabric.Path? I've noticed that it stops drawing after 8 segments even though I have attempted different methods like loops and individually coding each segment. co ...

Does Apollo Federation provide support for a code-first development approach?

I have declarations using 'code-first' approach in my project, but now I want to utilize them as microservices. How can I separate my 'typeDefs' and 'resolvers' following Apollo's 'schema-first' methodology? Is ...

What are the steps for importing the merge function from RxJS?

When working on my Angular project using version 10, I have found that I can easily import various RxJS operators such as debounceTime, filter, map, and more from 'rxjs/operators'. However, when it comes to importing the merge operator, things ge ...

Stop zombie.js from loading exclusively third-party resources

During a test, I am using zombie.js to load a page from a local express server. However, the page contains a script element that makes a call to Google Analytics. I want to prevent this external script from loading while allowing other local scripts to run ...

Using CSS properties as false values within React applications

Can you provide guidance on using conditional styles with conditional operators? What would be the ideal code example? Is it possible to use non-CSS values? margin: isOpen ? '10px' : undefined margin: isOpen ? '10px' : 'initial&a ...

Dealing with undefined or null values when using ReactJS with Formik

Issue Resolved: It seems that Formik requires InitialValues to be passed even if they are not necessary. I'm currently working on a formik form in React, but every time I click the submit button, I encounter an error message stating "TypeError: Canno ...

Is there a way to customize the total time out for the v-progress-loader-circular?

After attempting to adjust the time value to 30 seconds and then resetting it, I found that the circular progress would always stop at 100. My goal is for it to count up to 30, with 30 being the maximum count. Even though I did manage to reset it after 30 ...

Discovering the Cookie in Angular 2 after it's Been Created

My setup includes two Components and one Service: Components: 1: LoginComponent 2: HeaderComponent (Shared) Service: 1: authentication.service Within the LoginComponent, I utilize the authentication.service for authentication. Upon successful authent ...

Struggling with the jquery .hover method

Encountering an issue with the jquery .hover function. It seems to only work if I place it inside a generic $(function(){. I have observed it being done without this generic function, so if anyone can point out what I might be doing incorrectly, I would be ...

extracting both the value and ID attributes from a RadioButtonGroup component in React MaterialUI

I am currently working on extracting the selected value and gameID from a dynamic MaterialUI RadioButtonGroup. Although I have been successful in retrieving the gameID, I am encountering difficulty in obtaining the value: <form onSubmit={this.handl ...

Removing a post in Meteor-React using a submission modal is not possible as the post is not defined

After creating an additional submit modal for user confirmation when deleting a post from the collection, I'm facing difficulty in targeting the post. I also have a productivity query - should I include the DeletePost component in each post component ...

Is there a way to recover a deleted element from an array?

I have a list of user cards, and my task is: Clicking the "undo" button: will restore the last card that was deleted (using an array) Question 1: How can I create an array from the displayed cards list? Question 2: How do I restore the last deleted card? ...

Emphasize specific lines within a textarea

I am facing a challenge with a textarea dedicated to validating telephone numbers. My goal is to highlight the lines that contain invalid telephone numbers by adding two asterisks in front of them. However, I'm struggling to figure out how to highlig ...

Having trouble with error handling in Js Node Selenium Try-Catch? Let's troubleshoot

My goal is to simulate the action of clicking on an element that is displayed after a specific iteration of document.readyState = 'complete'. To overcome the readyState issue, I considered using try-catch with the executeScript command to keep re ...

Using the Mongoose $or operator with a nested array in query conditions

Here are the schemas I am using: //ProjectModel const ProjectSchema: Schema = new Schema( owner: { type: Schema.Types.ObjectId, ref: "User" }, users: [{type: Schema.Types.ObjectId, ref: "ProjectUser", unique: true }] ); //Project Use ...