A guide to simulating Custom Dialog in Angular for Unit Testing with Jest

Currently, I am in the process of creating test cases for unit tests and ensuring code coverage for a method that triggers a dialog component when isEdit = 'true' which is retrieved from localStorage.

The issue arises with the first test case where I am setting isEdit = true and invoking the method showMessagesList(). The lines within the if statement are covered in code coverage but the test case fails with an exception stating

Cannot read property 'openModalDialog' of undefined
. However, the second test case does not fail because it is being Spied On. I need assistance in mocking the Dialog component in Jest to resolve this error.

Error Message SideBarDrawerComponent › should call show Message Items when true

    TypeError: Cannot read property 'openModalDialog' of undefined

      49 |     this.isEdit = localStorage.getItem('isEditMode').toString()
      50 |     if (this.isEdit === 'true') {
    > 51 |       this.modalDialog.openModalDialog()
         |                                ^
      52 |     } else {
      53 |       this.toggleComponent.emit(componentTypes.LIST)
      54 |     }

Method in Component

showMessagesList() {
    // Check if the compose componenet is in edit mode;
    this.isEdit = localStorage.getItem('isEdit').toString()
    if (this.isEdit === 'true') {
      this.modalDialog.openModalDialog() // exception when isEdit is set to 'true' in the test case
    } else {
      this.toggleComponent.emit("true")
    }
  }

Spect.ts file

import { ComponentFixture, TestBed } from '@angular/core/testing'
import { By } from '@angular/platform-browser'
import {
  ModalDialogComponent,
  ModalDialogModule,
} from 'modal-dialog'

import { ContentModel } from '../../model/content.model'
import * as componentTypes from '../componentTypes'
import { ComposeComponent } from '../compose-message/compose.component'
import { MessageItemsComponent } from '../message-list/message-item.component'
import { SideBarDrawerComponent } from './side-bar-drawer.component'
import spyOn = jest.spyOn


window.ResizeObserver =
  window.ResizeObserver ||
  jest.fn().mockImplementation(() => ({
    disconnect: jest.fn(),
    observe: jest.fn(),
    unobserve: jest.fn(),
  }))

describe('SideBarDrawerComponent ', () => {
  let component: SideBarDrawerComponent 
  let fixture: ComponentFixture<SideBarDrawerComponent>

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [ModalDialogModule],
      declarations: [
        SideBarDrawerComponent,
        MessageItemsComponent ,
        ComposeComponent,
        ModalDialogComponent, // <-- Dialog Component
      ],
      providers: [
        { provide: Window, useValue: window },
        { provide: ModalDialogComponent, useValue: {} },
      ],
    })
      .compileComponents()
      .then(() => {
        fixture = TestBed.createComponent(SideBarDrawerComponent)
        component = fixture.componentInstance
      })
  })

  beforeEach(() => {
    component.content = mockContent
  })

  it('should call show Message Items when true', () => {
    localStorage.setItem('isEditMode', 'true')
    component.showMessagesList()
    component.isEdit = localStorage.getItem('isEditMode') ?? ''
    fixture.detectChanges()
    expect(component.isEdit).toBe('true')
  })

  it('should check open dialog', () => {
    const isEdit = 'true'
    component.isEdit = isEdit.toString()
    expect(component.isEdit).toBe('true')
    jest.spyOn(component, 'showMessagesList').mockImplementationOnce(() => {
      if (isEdit === 'true') {
        expect(component.modalDialog.openModalDialog).toBeCalled()
      }
    })
  })
})

Answer №1

There seems to be a potential typo issue, as I have identified an error in this code snippet:

this.exampleModalDialog4.openModalDialog()
// --------------------^-----4 added here.

To address this issue, you can consider providing some mock method implementations for the Modal dialog component:

{ 
  provide: ModalDialogComponent, 
  useValue: {
     openModalDialog: () => {},
     // other implementations
  } 
},

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

Scroll to the top on every Angular 5 route change

Currently, I am utilizing Angular 5 for my project. Within the dashboard interface, there are various sections with varying amounts of content. Some sections contain only a small amount of information, while others have large amounts of content. However, w ...

Populate choices in the mat-select dropdown

I am encountering an issue with two-way binding in the mat-select component from Angular Material. In my TypeScript file, I have an option list and a variable for binding called valueFromDB. When I choose a value in the mat-select component, it automatical ...

The latest version, Angular 13, introduced numerous enhancements to caching in Angular applications

I recently made the switch to Angular 13 and noticed an abundance of cache files in a folder called .angular\cache\13.3.10 Within this folder, I found two sub directories: - angular-webpack - babel-webpack After manually upgrading from versio ...

Issue with method assignment in extending Array class in Typescript

Currently, I am utilizing Typescript and Vue in my workflow, although the specific framework is not a major concern for me. I have been attempting to expand Array functionality in the following manner: class AudioArray extends Array<[number, number]&g ...

Tips for binding a dynamically generated array in ngModel while using ngFor for looping

I am facing an issue with binding an array dynamically in my component using ngModel. While one-way binding works fine, the model does not update when I make changes or add new elements to the array. Here is the HTML section: <div class="form-group ro ...

Implementing data binding for arrays of inputs in Angular

Can anyone provide assistance with this code snippet and explain why it is not functioning as expected? I am trying to generate input fields from a string array and bind each input value to its corresponding element in the array. It seems like a common tas ...

What is the reason behind the return type of 'MyType | undefined' for Array<MyType>.find(...) method?

Currently, I am in the process of developing an Angular application using TypeScript. As part of this project, I have defined several classes along with corresponding interfaces that align perfectly with their respective properties: Map: export class Map ...

Combining two streams in RxJS and terminating the merged stream when a particular input is triggered

I am currently developing an Angular application and working on implementing a system where an NGRX effect will make requests to a service. This service will essentially perform two tasks: Firstly, it will check the local cache (sqlite) for the requested ...

What is the best approach to implement a recursive intersection while keeping refactoring in consideration?

I'm currently in the process of refactoring this code snippet to allow for the reuse of the same middleware logic on multiple pages in a type-safe manner. However, I am encountering difficulties when trying to write a typesafe recursive type that can ...

What is the best way to showcase two different arrays' data in a single Angular view?

I have 2 different arrays retrieved from an API with no common FK or any other identifier. Even though my TypeScript code produces the expected results, the view remains blank. The debugging results are provided as comments in the code snippet below: ngO ...

Long wait times for Angular 2 applications to load

My Angular 2 app is experiencing slow loading times, almost 8 seconds. Upon investigation, I discovered that the longest load time is attributed to rxjs. The app makes numerous requests to rxjs/observable, rxjs/add and rxjs/operator. How can I enhance the ...

Angular form retains the previous value when saving

I encountered an issue with my form component where it displays previous values instead of updated ones during a save operation. The strange part is that if I close the form and reopen it, the new values are then shown correctly. It seems like the problem ...

What is the most effective way to condense these if statements?

I've been working on a project that includes some if statements in the code. I was advised to make it more concise and efficient by doing it all in one line. While my current method is functional, I need to refactor it for approval. Can you assist me ...

Why the CoreModule in Angular is a must-have for practical development

Though I have gained ample experience in developing Angular-UIs, there is one concept that continues to elude me - the true value of incorporating a CoreModule. To clarify, I understand the purpose of a SharedModule; it houses reusable components (such as ...

Using a function from one class within another class by passing it as a prop

Below are the methods found in my Search.tsx class. renderSuggestion(suggestion) { <div className="buttons"> <button className="button">View Location</button> <button className="button whitebutton" onClick={this.h ...

We are encountering an issue with a missing module: Error: Unable to locate '@angular/flex-layout' in the 'app' directory

Out of nowhere I encountered the following error: Module not found: Error: Can't resolve '@angular/flex-layout' in '\src\app' This issue popped up right after I installed @angular/cdk. To address this error, I reinstal ...

What is the functionality of observable in Angular? The 'includes' property is not present in the 'Observable' type

I am currently diving into the world of Angular5 and I have been using Firebase to fetch data for my page display. While researching how to retrieve data from Firebase using AngularFire, I found that many examples were outdated. Eventually, I learned that ...

Navigating with Angular: Transmitting dynamic URL parameters to components

I currently have the following routes defined: const routes: Routes = [ { path: ':product/new', children: [{ path: 'std/:country', component: SignUpComponent, data: { ...

When attempting to execute my script, I encountered an error message stating that "TypeError: puppeteer.use(...) is not

Here is the current code that I've been working on. After switching it to a new folder, I encountered an error that wasn't present before. I made sure to reinstall all the necessary modules in the package.json file, but the issue persists. Is the ...

Navigating with query parameters in Angular 5

Currently, I am developing my angular 5+ application and utilizing the AuthGuardService. My scenario involves redirecting from another php application that sends form data through a query string. http://localhost:44200/#/users/save?first_name=John&las ...