experimenting with a TypeScript annotation

I have created a simple decorator that can trigger either stopPropagation() or preventDefault() based on certain conditions. I have thoroughly tested this decorator in my application and am confident that it works correctly. However, I encountered an issue when trying to test whether the specified methods are actually being triggered.

During the testing process, I encountered the following error:

Error: Expected spy stopPropagation to have been called.

core.decorators.ts

export function eventModifier( stopPropagation = false, preventDefault?: boolean ) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
      const originalMethod = descriptor.value;
      descriptor.value = function() {
        const context = this;
        const mouseEvent: MouseEvent = Array.from( arguments ).find( event => event instanceof MouseEvent );
    
        if ( stopPropagation ) {
          mouseEvent.stopPropagation();
        }
    
        if ( preventDefault ) {
          mouseEvent.preventDefault();
        }
    
        originalMethod.apply( context, arguments );
      };
    
      return descriptor;
    };
  }
  

core.decorators.spec.ts

import { eventModifier } from './core.decorators';
  
  describe('eventModifier decorator', () => {
  
    class TestClass {
  
      @eventModifier( true )
      public click( event: MouseEvent ): void {
      }
  
    }
  
    it('should define the decorator', function() {
      expect( eventModifier ).toBeDefined();
    });
  
    it('stopPropagation() should be called', function() {
      const testClass = new TestClass();
      const ev = new MouseEvent('click')
  
      spyOn( testClass, 'click' );
      spyOn( ev, 'stopPropagation' );
  
      testClass.click( <MouseEvent> ev );
  
      expect( testClass.click ).toHaveBeenCalledWith( ev );
      expect( ev.stopPropagation ).toHaveBeenCalled();
    });
  
  });
  

Answer №1

It took a few days of trial and error, but I finally figured it out. It seems that I had forgotten something when setting up the spy on the testClass.click method.

Below is the successful unit test:

 import { eventModifier } from './core.decorators';

describe('eventModifier decorator', () => {

  class TestClass {

    @eventModifier( true )
    public click( event: MouseEvent ): void {
    }

  }

  it('decorator is defined', function() {
    expect( eventModifier ).toBeDefined();
  });

  it('stopPropagation() should be called', function() {
    const testClass = new TestClass();
    const ev = new MouseEvent('click')

    spyOn( testClass, 'click' ).and.callThrough();
    spyOn( ev, 'stopPropagation' );

    testClass.click( <MouseEvent> ev );

    expect( testClass.click ).toHaveBeenCalledWith( ev );
    expect( ev.stopPropagation ).toHaveBeenCalled();
  });

});

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

Adjusting the Material UI Select handleChange function

const handleObjectChange = (event: React.ChangeEvent<{ value: unknown }>) => { const { options } = event.target as HTMLSelectElement; const selectedValues: object[] = []; for (let i = 0, l = options.length; i < l; i += 1) { if ...

Route protection is ineffective when dealing with two observables simultaneously

After writing the route guard as shown below, I encountered an issue with the else statement that was not returning a result, even though it should have. Surprisingly, there were no errors either. this.hotelSettingsService.get().pipe(map(res => { ...

If the option is 'Gel', use an if statement to console log

I'm trying to console.log the option from the data() function that is equal to 'Gel'. I attempted to use an if statement, but it doesn't seem to be working. Anyone have any ideas on how to make this work? data(){ return { ...

Merging angular-file-upload with multer

I am facing a challenge in integrating the angular file upload plugin with multer to create a fully Single Page Application (SPA). I am currently stuck on uploading multiple files through multer. Below is how my multer options are set up in my node route. ...

Invoking a function within a functional component from a React element

Let's imagine a scenario where we have a Child component that is a functional component and contains a function called a(): export default function child({ ... }) { ... function a() { ... } ... } Now, let's introduce a parent ...

Organizing JSON keys based on their values using Typescript

In the context of a main JSON structure represented below, I am interested in creating two separate JSONs based on the ID and Hobby values. x = [ {id: "1", hobby: "videogames"}, {id: "1", hobby: "chess"}, {id: "2", hobby: "chess ...

NextJS struggles to load EditorJS plugins

I am currently working on integrating EditorJS into my NextJS project. The editor is loading properly without any plugins, with only paragraph as a block option. However, I'm facing an issue when trying to add plugins using the tools prop which result ...

Implementing handleRequest as an asynchronous function within the passportjs guard

@Injectable() export class RefreshAuthGuard extends JwtAuthGuard { constructor( private readonly jwtService: JwtService, ) { super(); } public handleRequest(err: any, user: any, info: Error, ctx: any): any { if (err ...

Is there a way to utilize JavaScript or jQuery to modify the background color of the `Save` and `Cancel` buttons within a SharePoint 2013 edit form?

Is there a way to modify the background color of the Save and Cancel buttons on a SharePoint 2013 edit form using JavaScript or jQuery? ...

Tips on streamlining two similar TypeScript interfaces with distinct key names

Presented here are two different formats for the same interface: a JSON format with keys separated by low dash, and a JavaScript camelCase format: JSON format: interface MyJsonInterface { key_one: string; key_two: number; } interface MyInterface { ...

Why does the text in a div display in Safari 8.2 and Chrome 39, but not in Firefox 34?

In my HTML document, I have a div tag located within the body like so: <div id="content_text"></div>​ Using javascript, I later set the contents of the div like this: var content_text = document.getElementById("content_text") c ...

Update the URL and parse the data in a Backbone collection

For the purpose of development, I am looking to replace the collection with fake JSON results either from a JSON variable or a JSON file. However, I encountered an error when attempting to do so using url http://jsfiddle.net/qhoc/uZhM8/ GET http://fiddle ...

Preventing an event from bubbling up to its parent in a jQuery Ajax call: A step-by-step guide

I am working on a page that showcases a tree list using unordered lists. Each li element with children triggers an ajax call to fetch those children and display them as another ul/li combination, which is functioning correctly. However, the problem arise ...

How come the hook keeps triggering endlessly in a loop when I try to pass the updated props?

I've encountered an issue with a custom hook I created for making HTTP requests. The problem is that the request seems to be firing in an endless loop, and I'm unsure of what's causing this behavior. My intention is for the request to only t ...

When integrating AngularJS with CKEditor, an error regarding module dependency injection may occur, causing the following message to be displayed:

Just starting out with Angularjs and attempting to integrate Ckeditor into my webapp. Currently encountering the following error: Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.5.8/$injector/modulerr?p0=editor&p1=Error%3A%…Flo ...

Utilizing Jquery selectors for elements that change dynamically

While this question may be common, I have yet to find a satisfactory answer that meets my needs. On one of the pages on my website, labeled A, there is a script being loaded: jQuery.getScript('js/jquery.tablesorter.min.js', function (data, statu ...

Response from Socket.io: What is the best way for the server to respond to all clients after receiving input from multiple clients?

Currently diving into the realm of node.js, express, and socket.io Thrilled to report that my server is up and running, successfully connecting to the browser via localhost:3000 Communication between client and server is seamless both ways. Now, onto th ...

Encountering difficulty in removing a record from the database utilizing Prisma with Next.js API routes

Currently, I am in the process of developing a Todo manager using Next.js 13, Prisma, and MySQL. In order to include a feature that allows users to delete a todo item, I have implemented the use of a Link tag for the delete button within my code: ... <L ...

Time for the browser to evaluate javascript code has arrived

We are looking to enhance the speed at which our Javascript files load in the browser. Although our own Javascript files are simple and small, larger libraries like jQuery and KendoUI take a considerable amount of time to evaluate. We are interested in fin ...

Struggling to get JavaScript to successfully load a .txt file in order to load various links

I created a cool feature that takes users to a random link, but I currently have a large list of links and wanted to find a way for JavaScript to read them from a text file. The code I have tried so far is not working, and I have experimented with other s ...