Exploring the functionality of the Angular snackbar feature

I have created a simple snackbar with the following code:

app.component.ts:

  ngOnInit(){
    this.dataService.valueChanges.pipe(
        filter((data) => data === true),
        switchMap(() => {
          const snackBarRef = this.matSnackBar.open(
            'A new value updated',
            'OK',
            {
              duration: 3000
            }
          );

          return snackBarRef.onAction();
        })
      )
      .subscribe(() => {
        this.window.location.reload();
      });
  }

app.component.spec.ts (Including mock data for service)

describe('AppComponent', () => { 
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;
  let matSnackBarSpy: jasmine.SpyObj<MatSnackBar>;

  let a = "";
  let b = "";
  let c = "";

  const mockDataService = {
    valueChanges: of(true)
  };

  beforeEach(async(() => {
    TestBed.configureTestingModule({

    a = "Test";
    b = "X";
    c = "suc";
    matSnackBarSpy = TestBed.get<MatSnackBar>(MatSnackBar);

 })
}))

  describe('#ngOnInit()', () => {

    it('should call MatSnackBar.open()', async(done: DoneFn) => {
      const error = new HttpErrorResponse({ error: 'Some error' });

      component.ngOnInit();

      expect(mockDataService.valueChanges).toBeTruthy();
      expect(matSnackBarSpy.open(a,b,c)).toBeTruthy();

      done();
    });
  });

})

data.service.ts

import { Observable } from 'rxjs';

export class DataService {
  valueChanges: Observable<boolean>;
}

Explanation:

  • I have a service with a property valueChanges of type Observable<boolean>.

  • In the component.ts, I receive boolean value true after the value change and the snackbar opens successfully.

  • Currently, I am working on implementing test cases in component.spec.ts,

      expect(mockDataService.valueChanges).toBeTruthy();
      expect(matSnackBarSpy.open(a,b,c)).toBeTruthy();
    

Although the tests are passing, I consistently see a warning in Chrome as depicted below.

https://i.sstatic.net/6SXJo.png

  • Despite referencing Mocking MatSnackBar in Angular 8 & Jasmine, I am unable to resolve the issue.

Requirement: I aim to cover all the tests that currently show warnings indicating they are not covered, as displayed in the image above.

Even though the test cases pass, the test coverage report still shows function not covered and statement not covered warnings when accessing index.html of the component.

Answer №1

When testing, it's important to check if the matSnackBar methods are being called correctly. It's worth noting that testing the behavior of matSnackBar does not fall under unit testing.

To do this, you can create a MatSnackBarStub class:

class MatSnackBarStub{
  open(){
    return {
      onAction: () => of({})
    };
  }
}

You can then use this in your component.spec file:

beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [SomeComponent],
    providers: [{provide: MatSnackBar , useClass: MatSnackBarStub}]
  }).compileComponents();
}));

it('should create', () => {
  spyOn(component.matSnackBar,"open").and.callThrough();
  component.ngOnInit();
  expect(component.matSnackBar.open).toHaveBeenCalled();
  // you can also use ".toHaveBeenCalledWith" with necessary params
});

If you're looking for more resources on unit testing using jasmine and karma, I recommend checking out this collection of articles. There is a guide on how to use stubs and spies which might be helpful for you.

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

What is the best way to verify the presence of a value in an SQL column?

I need to check if a value exists in a column. If the value already exists, I do not want to insert it into the table. However, if it does not exist, then I want to add new data. Unfortunately, my attempted solution hasn't been successful. You can fi ...

Using Typescript to pass an interface as an argument to a function that requires a JSON type

Here is an extension related to the topic of Typescript: interface that extends a JSON type Consider the following JSON type: type JSONValue = | string | number | boolean | null | JSONValue[] | {[key: string]: JSONValue} The goal is to inform type ...

What is the procedure for transferring the inputted data from an HTML file to its corresponding TS file and subsequently to a different component file?

I have created two components, a login and a home-page. I am attempting to capture user input from the login template, pass it to the login component, and then display it on the home-page template using the home-page component. What is the best approach to ...

Angular 2 Material - Troubleshooting: Why does my input lose focus?

I've encountered a strange issue. Using Angular CLI, I integrated Material 2. Created inputs with ngfor and linked them to ngmodel. Everything was functioning correctly... Except, as I type in the input field, it deselects itself. This is the snipp ...

Apply a CSS class when the tab key is pressed by the user

Currently in my Angular 14 project, I am working on a feature where I need to apply "display: block" to an element once the user reaches it using the tab key. However, I am struggling with removing the "display: block" when the user tabs out of the element ...

pull information from mongodb into angular

I am attempting to retrieve data from MongoDB, but I keep seeing [object] [object]. How can I transfer array data from MongoDB to Angular? Here is the code snippet: import { Component, OnInit } from '@angular/core'; import {HttpClient} from &quo ...

Error: the attempt to execute the mongoose connection function has failed due to it not being recognized as a valid function

Hey there, I'm encountering the error TypeError: mongoose__WEBPACK_IMPORTED_MODULE_15___default.a.connect is not a function import mongoose from "mongoose"; const dbURI = 'myurlstuffhere'; mongoose.connect(dbURI , {useNewUrlParser: ...

The Angular 2 application successfully loads the JSON file and the HTML structure, however, there seems

I successfully connected an external json file and used ngFor to loop through nested objects on the website. However, I am facing an issue where no data is being displayed. I have attempted to structure the data using an interface but still encounter the p ...

Are there any ways to run newman collections directly from jasmine test suites?

I have experience writing API tests using Jasmine in the Node platform. We also have existing API test cases in Postman collections. Now, we are considering executing both sets of test cases simultaneously... We've successfully executed the Postman c ...

Determining the presence of generic K within generic M in Typescript Generics and Redux

Hello there I am currently working on minimizing repetitive code in my react application by utilizing Redux state. After choosing the Redux structure to use (refer to Context), I now aim to make it more concise. To achieve this, I have developed a generic ...

Can we trust the accuracy of the official type definition for JSON.stringify?

Upon reviewing the official type definition for JSON.stringify, it appears that it states JSON.stringify always returns a string, even when passed undefined. interface JSON { stringify(value: any, /*...*/): undefined; } However, executing JSON.stringif ...

Combining Different Types of Errors

Can TypeScript's type system be exploited to provide additional information from a repository to a service in case of errors? I have a service that needs a port for a repository (Interface that the Repository must implement), but since the service mu ...

Template literal types in TypeScript and Visual Studio Code: An unbeatable duo

I'm encountering an issue while attempting to utilize literal types in Visual Studio Code. When following the example from the documentation, https://i.stack.imgur.com/V6njl.png eslint is flagging an error in the code (Parsing error: Type expected.e ...

Using Typescript to extract/calculate types with limitations without the need to explicitly extend or broaden them

I have a function called build that constructs a User object using the provided parameters. I want to define the function in such a way that it recognizes which parameters are being passed and incorporates them into the return value. Initially, I thought ...

Exploring Angular 2 - examining how @input is implemented within the ngOnInit lifecycle hook for testing a component

Presently, I am facing a challenge while attempting to test a child component that is designed to receive input from the host component and utilizes the ngOnInit lifecycle hook as depicted in the following code snippet. @Component({ selector: 'my ...

Using ES6 and Typescript, when a button is clicked, apply a class to all TD elements within the button except for the first one. No need for jQuery

A sample table structure is shown below: <table> <tr> <td>1</td> <td>joe</td> <td>brown</td> <td><button onclick="addClasses()">Add Class to add TD's in t ...

Typescript Error: TS2339: The property 'faillogout' is not found within the type '{ failed(): void; onSubmit(): void; }'

I encountered an issue with my Vue.js app using TypeScript. The error message I'm getting is: Property 'faillogout' does not exist on type '{ failed(): void; onSubmit(): void; }'. 101 | failed () { This snippet shows the s ...

Switching the focus of detection from a child to a parent

I am currently working on enhancing the functionality of my UI to display selections dynamically as they are selected or de-selected. import { Wizard } from './report-common'; import { Router } from '@angular/router'; import { DataServ ...

Issue with radio button validation not being triggered upon form submission

I am encountering an issue with validating a radio button in a form. Despite my efforts, I am able to proceed to the next page without selecting a radio button option. However, the validation for the email address field is working correctly. Below is the r ...

Best practices for working with child components in Vue.js using TypeScript: Steer clear of directly mutating props

I feel like I'm stuck in a loop here. Currently, I have a Vue.js 2 app set up and running with TypeScript. However, I'm encountering an issue when trying to pass data to a child component that originates from the store. <template> < ...