Jest unit tests in Angular using Typescript are not detecting failures when it comes to console errors or unrecognized elements

In my Angular Typescript project, I am facing an issue with my Jest unit test. The test does not fail even if a component (e.g., mat-paginator without importing MatPaginatorModule in configureTestingModule) or template bindings (e.g., [mask] directive from ngx-mask without importing NgxMaskDirective) are missing. This situation would normally cause a build failure, but the Jest unit test somehow passes successfully.

Is there a specific configuration that needs to be set up to ensure that these tests fail when they should?

Below is an excerpt from my test-setup.ts file:

import 'jest-preset-angular/setup-jest';

import { getTestBed } from '@angular/core/testing';
import {
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';

getTestBed().resetTestEnvironment();
getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting(),
  { teardown: { destroyAfterEach: false } }
);

Answer №1

Alright, let's break this down. First things first, I was missing certain configurations for the initTestEnvironment that were introduced in the middle of 2022.

import 'jest-preset-angular/setup-jest';

import { getTestBed } from '@angular/core/testing';
import {
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';

getTestBed().resetTestEnvironment();
getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting(),
  {
    teardown: { destroyAfterEach: false },
    errorOnUnknownElements: true, // <---
    errorOnUnknownProperties: true, // <---
  }

This configuration ensures that any unknown components or template errors will trigger test failures as they would during a build process. However, there are still other types of errors that may cause runtime or build failures not covered by these properties. To address those, I implemented a custom override for console.error to throw an error instead of just logging it. You can add this to your test-setup.ts file:

// test-setup.ts
import { failTestOnConsoleError } from './testing-utils'

...
getTestBed().resetTestEnvironment();
getTestBed().initTestEnvironment(
  ...
);

beforeEach(() => {
  failTestOnConsoleError();
});

// testing-utils.ts
const defaultConsoleError = window.console.error;

/**
 * Forces a Jest test to fail when a console.error is detected.
 *
 * To allow the test to pass, execute {@link permitTestWithConsoleError} in your test.
 */
export function failTestOnConsoleError(): void {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  window.console.error = (...args: any[]) => {
    defaultConsoleError.apply(this, args);
    throw new Error(
      'Test was forced to fail due to a console.error that was triggered. If this console.error should be permitted, execute permitTestWithConsoleError() in your test.'
    );
  };
}

/**
 * Allows a Jest test to pass even if a console.error is detected.
 *
 * This is the default behavior and undos the logic in {@link failTestOnConsoleError}
 */
export function permitTestWithConsoleError(): void {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  window.console.error = (...args: any[]) => {
    defaultConsoleError.apply(this, args);
    console.warn('Test permitted to pass despite throwing a console.error.');
  };
}

By calling failTestOnConsoleError() in the beforeEach of your test-setup, any test sending a console.error will result in a failed test. On the other hand, using permitTestWithConsoleError() will allow tests to throw console.errors and still pass, reverting back to default behavior.

// some-random.spec.ts
describe('my tests', () => {
  it('will pass', () => {
    ... // Expecting no errors, so fail the test if any occur
  });
  it('will have error', () => {
    permitTestWithConsoleError(); // Testing specifically for an error, so the test shouldn't fail upon detection
    myMockedService.myMethod.mockImplementationOnce(() =>
      throwError(() => new Error('oh no I failed'))
    );
    ...
  });
});

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

Encountering "Angular Reactive forms - FormArray - Unable to locate control with specified path" error upon initial loading

Encountering some Cannot find control with path errors while attempting to utilize a basic Reactive Form and FormArray. Component.ts ngOnInit() { this.newForm = this.fb.group({ currencyExchangex: this.fb.array( [this.fb.group({ rateNumeri ...

In Next.js, the switch button remains in the same state even after the page is refreshed

Is there a solution for this issue? I am currently developing a switch button for a configuration page. The problem arises when I toggle the switch from active to maintenance mode, save it successfully, but upon refreshing the page, the switch reverts back ...

Angular 2's ng-required directive is used to specify that

I have created a model-driven form in Angular 2, and I need one of the input fields to only show up if a specific checkbox is unchecked. I was able to achieve this using *ngIf directive. Now, my question is how can I make that input field required only whe ...

Reacting to Appwrite events in a React Native environment

My React Native application encounters an error when subscribing to realtime events. The error message reads as follows: ERROR Error: URLSearchParams.set is not implemented, js engine: hermes. appwriteClient .subscribe( `databases.${APPWRITE_DATAB ...

Obtain document via Angular 2

Is it possible to use TypeScript to download an image that is already loaded? <div *ngIf="DisplayAttachmentImage" class="fixed-window-wrapper_dark"> <button class="btn btn-close-window" (wslClick)="HideAttachmentImage()"> & ...

Warning message in ReactJS Material UI Typescript when using withStyles

I am facing an issue even though I have applied styling as per my requirements: Warning: Failed prop type validation- Invalid prop classes with type function passed to WithStyles(App), expected type object. This warning is originating from Wi ...

Using Node-Forge for importing in an Angular 2 service

I've been attempting to incorporate Forge (https://github.com/digitalbazaar/forge) into my Angular 2 project. After executing the command :npm install node-forge, the node-forge directory was created within my application (in the node-modules directo ...

Angular 7: Unable to connect with 'messages' because it is not recognized as a valid attribute of 'message-list'

Currently, I am embarking on an Angular journey to develop a hobby chat project using Angular 7 for educational purposes. My main hurdle lies in comprehending modules and components, which has led me to encounter a certain issue. The Challenge In the tut ...

Adding custom TypeScript classes to an Electron project is a straightforward process that allows developers to enhance their

Currently working on a hello world project in Electron and stumbled across the possibility of using Typescript for the Main process, . The provided instructions suggest changing the file extension from index.js to index.ts and updating the package.json fi ...

What method can be used to fetch generic type parameter in typescript?

I am having trouble finding the type of E within the code provided below. class A<E> { getParameterType() { // I need to determine the type of E } } class B { } ** Example ** new A<number>().getParameterType() // number new A<B&g ...

The function signature '(_event: React.SyntheticEvent, value: number) => void' cannot be assigned to the type 'FormEventHandler<HTMLUListElement>'

I am facing an issue with my component "PageFooter" being duplicated in three other components. I am trying to refactor it as a UI component. " I am getting the error message: 'Type '(_event: React.SyntheticEvent, value: number) = ...

Troubleshooting dynamic route issues in Angular 6 when making changes in *ngFor

`<div *ngFor="let data of projects"> <a [routerLink]="'/projects/'+data.project_id"> {{data.project_name}}</a> </div>` When I click on the link, the URL changes from http://localhost:4200/projects/1 to http://localhost ...

Encountering an error when attempting to access undefined property while using a method as a callback

Exploring OOP and angular is new to me. I am currently trying to implement a reusable table with pagination that triggers an API request when the page changes (pagination within the table component). The issue arises when I attempt to access my method usi ...

Ways to detect button click in a separate component

I am working with an Angular app that consists of two components: a navbar component and a display component. The navbar component has a search button that, when clicked, searches for the entered name and displays the details in the display component. I ne ...

When using react-admin with TypeScript, it is not possible to treat a namespace as a type

Encountering issues while adding files from the react-admin example demo, facing some errors: 'Cannot use namespace 'FilterProps' as a type.' Snippet of code: https://github.com/marmelab/react-admin/blob/master/examples/demo/src/orde ...

Ways to navigate to a routerlink in Angular 2 without passing any parameters

Struggling with accessing a routerlink in Angular 2 without its parameters. The goal is to use the routerlinks to determine whether or not to display a specific element in the navigation. For normal routerlinks without parameters, I do it like this: *ngIf ...

I keep seeing "Uncaught TypeError: Unable to retrieve property 'get' from undefined" error message popping up

Currently, I am attempting to retrieve a JSON from a separate microservice (local) utilizing a different port. There is uncertainty as to whether the issue lies within my configuration or the microservice itself. Despite successfully displaying the JSON on ...

Expand the size of the imported gltf model within Three.js

After successfully loading a 3d model with a gltf extension using the GLTFLoader in Three.js, I encountered a new challenge. I needed to adjust the dimensions of the model dynamically when the window is resized, based on the values of window.innerWidth and ...

Types are not appearing in @types/node

I have added @types/node to my project. In the index.ts file, the default node modules are being treated as type any. const fs = require('fs'); The type of fs is currently set to any. { "ts-node": { "cwd": "/User ...

Simulating Cordova plugin functionality during unit testing

I have a code snippet that I need to test in my controller: $scope.fbLogin = function() { console.log('Start FB login'); facebookConnectPlugin.login(["public_profile", "email", "user_friends"], FacebookServices.fbLoginSuccess, FacebookServic ...