Experimenting with retrieving input from other components while implementing setTimeout

In continuation of the previous question (linked here), I am still working on tutorials for Angular testing using the same files. The current issue revolves around the setTimeout function.

Within both ngOnInit and ngAfterViewInit, I have included a setTimeout function (as future tests will also utilize this). The function sets a variable value that is then passed to a child component through the HTML file, and I need to check if the child component's variable has the expected value.

Despite trying to use tick(value) and fixture.detectChanges() to trigger the contents of the setTimeout function, the value remains undefined. Below are code snippets demonstrating the setup:

random.test.component.ts

public dataThatGetsDelayed: any;

constructor() {

}

ngOnInit() {
    setTimeout(() => {
        this.dataThatGetsDelayed = "OnInit";
    }, 100);
}

ngAfterViewInit() {
    setTimeout(() => {
        this.dataThatGetsDelayed = "AfterView";
    }, 100);
}

random.test.component.html

[variableThatStoresDelayedData]="dataThatGetsDelayed"

random.test.component.child.ts

@Input() variableThatStoresDelayedData: any;

random.test.file.spec.ts

it('Testing if receiving input works properly with a time delay in ngOnInit', fakeAsync(() => {
    const componentInThePage: TestComponentChild = fixture.debugElement.query(By.directive(TestComponentChild)).componentInstance;
    expect(componentInThePage).toBeTruthy();

    tick(100);
    fixture.detectChanges();

    fixture.whenStable().then(() => {
        expect(componentInThePage.variableThatStoresDelayedData).toEqual("OnInit");
    });
}));

it('Testing if receiving input works properly with a time delay in ngAfterViewInit', fakeAsync(() => {
    const componentInThePage: TestComponentChild = fixture.debugElement.query(By.directive(TestComponentChild)).componentInstance;
    expect(componentInThePage).toBeTruthy();

    //tick(100);
    //component.ngAfterViewInit();

    fixture.whenStable().then(() => {
        expect(componentInThePage.variableThatStoresDelayedData).toEqual("AfterView");
    });
}));

I have attempted to use whenStable at the end as recommended, but it seems to be disregarded. Without it, I receive the error "Expected undefined to equal 'OnInit'/'AfterView'". I have avoided the second tick as it results in the error "1 timer(s) still in the queue".

How can I instruct the program to wait until the setTimeout function sets the variable value?

Answer №1

After some investigation and trial and error, I have discovered the solution. The code comments provide a detailed explanation:

random.test.component.ts

public dataThatGetsDelayed: any = "Initial value"; //Illustrates how the value changes.

constructor(private detectorReference: ChangeDetectorRef) {
    //The detectorReference is utilized in ngAfterViewInit
}

ngOnInit() {
    setTimeout(() => {
        this.dataThatGetsDelayed = "OnInit";
    }, 100);
}

ngAfterViewInit() {
    setTimeout(() => {
        this.dataThatGetsDelayed = "AfterView";
        this.detectorReference.detectChanges(); //Necessary to prevent error regarding value change
    }, 200);
}

(Special thanks to this source for assistance!)

random.test.file.spec.ts

//Test for the ngOnInit function
it('Testing if receiving input works properly with a time delay in ngOnInit', fakeAsync(() => {
    const componentInThePage: TestComponentChild = fixture.debugElement.query(By.directive(TestComponentChild)).componentInstance;
    expect(componentInThePage).toBeTruthy();

    expect(componentInThePage.variableThatStoresDelayedData).toEqual("Initial value");

    component.ngOnInit();
    //tick(99); - setTimeout doesn't fully execute from ngOnInit.
    tick(100); //This completes the setTimeout.
    fixture.detectChanges();

    expect(componentInThePage.variableThatStoresDelayedData).toEqual("OnInit");
}));

//Test for the ngAfterViewInit function. Note that the value isn't initialized in ngOnInit first;
//only the explicit method call triggers the intended action.
it('Testing if receiving input works properly with a time delay in ngAfterViewInit', fakeAsync(() => {
    const componentInThePage: TestComponentChild = fixture.debugElement.query(By.directive(TestComponentChild)).componentInstance;
    expect(componentInThePage).toBeTruthy();

    expect(componentInThePage.variableThatStoresDelayedData).toEqual("Initial value");

    component.ngAfterViewInit();
    //tick(199); - setTimeout not fully executed.
    tick(200); //But this completes it.
    fixture.detectChanges();

    expect(componentInThePage.variableThatStoresDelayedData).toEqual("AfterView");
}));

Hopefully, this will assist someone in the future!

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

Uploading videos on Mobile Safari causes the website to refresh automatically

Setting up a photo uploading server on a raspberry pi using Angular with Node.Js and multer has been an exciting project for me. I opted to host it on an unsecured ad-hoc network created by the pi itself so I can easily take it on road trips and store phot ...

Removing a directory from GitHub with the help of octokit/rest

I am attempting to utilize octokit/rest in order to programmatically remove a directory. Below is the code I am using: import {Octokit as Github} from '@octokit/rest'; const githubToken = "read from vault"; // Functions for retrieving current c ...

Verify the type of email domain (personal or corporate)

Here's an example: isPersonalEmail("<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c0aea1ada580a7ada1a9aceea3afad">[email protected]</a>") // true isPersonalEmail("<a href="/cdn-cgi/l/email- ...

Exploring the concept of TypeScript interface declaration

I have a function A that will return function B. The parameter of function B is object C, which has a property named D with a type of T. T's value is determined when function B is fetched; this means T can be set when calling function A or using alte ...

Obtaining the host name in server-side rendering (

In the process of developing an app that consists of a client and an API hosted on different domains, the setup resembles the following: [Local] localhost:5000 (client) localhost:5001 (API) [Web] app.domain.com (client) api.domain.com (API) When mak ...

Angular is putting the page on ice - all clicks are officially off limits

When making an HTTP request to the backend in my project, I need the ability to sort of "freeze" the screen until the request is complete. Specifically, I want to prevent users from being able to interact with certain elements on the page, such as a butt ...

The function type '() => JSX.Element' cannot be assigned to the type 'ReactNode'

I am encountering an issue while trying to display a component using an object. The code is throwing an error: const Login = () => <>login</> const publicRoutes = [ { path: '/login', component: Login } ] function AppR ...

Executing ng test on every application within the project

Angular CLI version 6.0.0 New setup completed with CLI Utilized ng generate library to create multiple projects Created 2 new projects in addition to the main app Issue: When running ng test, each project, including the main app, is tested separately ...

What is the process of creating a callback in Angular using TypeScript?

Despite finding numerous resources, I am still struggling to fully grasp the concept at hand. The issue revolves around two functions in particular: roulette_animation(){ do animation (may take 5 sec) } alertResult(){ alert('You win') } My obje ...

The absence of transpiled Typescript code "*.js" in imports

Here is an example of the code I am working with: User.ts ... import { UserFavoriteRoom } from "./UserFavoriteRoom.js"; import { Room } from "./Room.js"; import { Reservation } from "./Reservation.js"; import { Message } from ...

Encountering an error in Angular 8 with the plugin: Unhandled ReferenceError for SystemJS

I recently followed a tutorial on integrating plugins into my Angular application at this link. I'm trying to create a component in my Angular app that can execute and display an external component. However, I encountered the following error: Uncaugh ...

What's the best way to group rows in an angular mat-table?

I am working on a detailed mat-table with expanded rows and trying to group the rows based on Execution Date. While looking at this Stackblitz example where the data is grouped alphabetically, I am struggling to understand where to place the group header c ...

Is it advisable to verify the attributes of a view in unit tests?

What is the best way to conduct unit testing for a Django view like the one below? class UserListView(LoginRequiredMixin, ListView): model = get_user_model() template_name = 'users/user_list.html' ordering = 'last_name' ...

Retrieving information from the Dog API using axios and storing the results in a fresh array

Currently, I am working on a NextJS app using Typescript. My issue lies in the functionality aspect of the application. I am utilizing the Dog API to retrieve all the breeds names and store them in a new array of arrays. Each sub-array contains the breed a ...

How can we simultaneously execute multiple HTTP requests in Angular 6 by leveraging the power of forkJoin and ngrx?

Current Situation In the realm of my angular6 application, I find myself juggling three distinct categories: catA, catB, and catC. Each of these categories requires data retrieval from 3 separate APIs. Upon selecting any category, the CategoryDetailsCompo ...

What is the best way to verify a field against a set of string values using Typescript in a NestJS application

I currently have an Enum containing various timezones listed below export enum Timezones { 'Europe/Andorra', 'Asia/Dubai', 'Asia/Kabul', 'America/Antigua' } In the DTO file, I am attempting to valid ...

Another option to avoid using complicated else if chains

I'm facing a challenge with a function that returns a value known as user_id. It involves multiple conditions that need to be checked. First condition: Verify the service variable Second condition: If not found, retrieve user_id from local storage ...

Testing with mount in React Enzyme, the setState method does not function correctly

I've been experimenting with testing this code block in my React App using Jest and Enzyme: openDeleteUserModal = ({ row }: { row: IUser | null }): any => ( event: React.SyntheticEvent ): void => { if (event) event.preventDefault(); ...

Displaying a random element from the state array in React Native

I'm attempting to display a random item from the state array, with the possibility of it changing each time the page reloads. Here's what I have tried so far, any suggestions or ideas are welcome! This is my current state: state = { randomIt ...

Transferring information between two components in separate Angular 4 modules

Within my application, I have defined two modules named AppModule and UserModule. I am currently encountering an issue with data sharing between the AppComponent and the LoginComponent (which belongs to the UserModule). Below is a snippet of app.componen ...