What is the process for implementing a type hint for a custom Chai assertion?

As part of my typescript project, I decided to create a custom assertion for the chai assertion library. Here is how I implemented it:

// ./tests/assertions/assertTimestamp.ts
import moment = require("moment");
import {Moment} from "moment";

const {Assertion} = require("chai");

const parseDateWithTime = (dateWithTime: string, format = "YYYY-MM-DD hh:mm:ss"): Moment => {
    return moment.utc(dateWithTime, format);
};

const formatTimestamp = (timestampInMs: number): string => {
    return moment.utc(timestampInMs).toISOString();
};

Assertion.addMethod("timestampOf", function (humanReadableDate: string, format = "YYYY-MM-DD hh:mm:ss") {
        const expectedValue = parseDateWithTime(humanReadableDate, format);
        const formatted = formatTimestamp(this._obj);

        new Assertion(this._obj)
            .to.eq(
            expectedValue.valueOf(),
            `\nEXPECTED: "${expectedValue.toISOString()}"\nGOT:      "${formatted}"\n`,
        );
    },
);

This custom assertion can be used like this:

require("../assertions/assertTimestamp");
import {expect} from "chai";


describe("Testing timestamps", () => {
   it("should validate timestamp conversion", () => {
     expect(1610841600000).to.be.timestampOf("2021-01-16");
   });
});

However, I encountered a typescript error:

TS2339:Property 'timestampOf' does not exist on type 'Assertion'.

To work around this issue, I found a temporary solution:

(expect(1610841600000).to.be as any).timestampOf("2021-01-16");

But my goal is to properly register this custom method within typescript so that I can benefit from auto-completion in my IDE.

Answer №1

In your assertTimestamp.ts file, you have the ability to include the following:

declare global {
    export namespace Chai {
        interface Assertion {
            timestampOf(date: string, format?: string): void;
        }
    }
}

This will introduce a custom function while retaining the current functionality.

Upon running your test, it is expected to fail with the following error message:

AssertionError: 
EXPECTED: "2021-01-16T00:00:00.000Z"
GOT:      "2021-01-17T00:00:00.000Z"
: expected 1610841600000 to equal 1610755200000
Expected :1610755200000
Actual   :1610841600000

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

How can I access keys and values from an Observable within an Angular template?

Attempting to display all keys and values from an Observable obtained through Angular Firebase Firestore Collection. This is how I establish a connection to the collection and retrieve an Observable. The function is called subsequently. verOrden : any; ...

Can you explain the variance between Next.js and Create React App?

I've been curious about understanding the distinctions between Next.js and Create React App (CRA). Both aim to simplify our lives when developing front-end applications with React. While researching online, I came across a key difference: Next.js o ...

Having trouble launching React application on local machine due to missing node modules

I am completely new to React. I recently forked a project on Github and am attempting to run it on my own machine. However, I've noticed that the folder structure is missing the node modules. Does this mean I need to install create-react-app globally ...

Is it possible to use TypeScript or Angular to disable or remove arrow key navigation from a PrimeNG Table programmatically?

Is there a way to programmatically prevent left and right arrow key navigation in a PrimeNG Table with cell editing, without the need to modify the Table component source code? You can check out an example here: Angular Primeng Tableedit Demo code. I mana ...

Guide to Dynamically Including an Element in an Array using Typescript

Encountering a type error within the <RenderFormFields formFields={formFieldsData} /> component:- Types of property 'type' are not compatible. Type 'string' cannot be assigned to type '"select"'.ts(2322) Rende ...

Utilizing Database values in .css files with Vue.js and TypeScript

I am currently working on extracting a color value from the database and applying it to my external .css files. I have searched extensively online but haven't found a satisfactory solution yet. Here is the JavaScript code snippet: createBackgroundHead ...

Steps for constructing an object literal with a property designated as the `keyof` type

Struggling to articulate my question, here is a simplified code snippet outlining what I aim to accomplish. class Example<T, TId extends keyof T> { public create(id: T[TId]): T { return { [TId]: id, // Encounter an error at this point. Ob ...

Creating a file logging system with log4js to capture Console logs

Is there a way to automatically log all console logs, including failed expectations and exceptions, to a file without using try and catch in JavaScript? In Java's LOG4j, the rootlogger feature does this by default. Is there a similar functionality ava ...

Unexpected outcome when returning a map

Encountered a puzzling issue that requires immediate clarification. When I input the following code into my project: this.metadata = json.metadata.map((x) => {return new Metadatum(x);}); console.log(this.metadata[0].value); The output consistently sho ...

Do you need to redeclare the type when using an interface with useState in React?

Take a look at this snippet: IAppStateProps.ts: import {INoteProps} from "./INoteProps"; export interface IAppStateProps { notesData: INoteProps[]; } and then implement it here: useAppState.ts: import {INoteProps} from "./interfaces/INo ...

Having an issue with forkJoin where the code seems to get stuck and does not continue execution after

The following script is retrieving two values from the database. I am using forkJoin for this purpose, which is a new approach for me. The reason behind utilizing this method is that there is a specific function that requires both values to be fetched bef ...

Mastering the integration of NestJS with Redis for microservices

Currently, I am diving into the world of nestjs microservices. I am curious, what commands are available for me to use? const pattern = { cmd: 'get' }; this.client.send<any>(pattern, data) Additionally, how do I go about retrieving data ...

Typescript's default string types offer a versatile approach to defining string values

Here is an example code snippet to consider: type PredefinedStrings = 'test' | 'otherTest'; interface MyObject { type: string | PredefinedStrings; } The interface MyObject has a single property called type, which can be one of the ...

No slides will be displayed in Ionic 2 once the workout is completed

Here is the result of the JSONOBJ: In my home.html file, I have ion-card containing a method called navigate(), which is structured as follows: navigate(event, exercise, exercise2, exercise3, exercise4){ this.navCtrl.push(exerciseSlides, { ...

The softAssert method is not available when trying to implement soft assertions within a TypeScript-based Protractor framework

Uncaught TypeError: assertion.softAssert is not a function I recently included a package called soft-assert using npm in my project. To install this package, I executed the following command: npm i soft-assert -g --save-dev Incorporated the following co ...

What is the best way to create a TypeScript interface or type definition for my constant variable?

I'm facing challenges in defining an interface or type for my dataset, and encountering some errors. Here is the incorrect interfaces and code that I'm using: interface IVehicle { [key: number]: { model: string, year: number }; } interface IV ...

Managing Angular routing: selectively updating named outlets without reloading submodules

My routing configuration currently reloads Module2 ListComponent on every routing event. However, I want to prevent the list from reloading when a user clicks on a list item within ListComponent. Specifically, when navigating from module2/route1 to module ...

Get ready for 10 AM with the RxJS timer function

I am trying to figure out how to schedule a method in my code using rxjs/timer. Specifically, I want the method to run at precisely 10 AM after an initial delay of 1 minute. However, my current implementation is running every 2 minutes after a 1-minute d ...

Can someone share with me the best practices for implementing @HostListener within a method in my Angular 16 project?

Currently, I've been involved in developing a Single Page Application using Angular 16, TypeScript, and The Movie Database (TMDB). My task at hand is to implement the "infinite scroll" functionality on a particular component. To achieve this, I have ...

Tips for including a clickable button in an Angular textarea

I am looking for a solution to float a button to the top right corner of a text area in an Angular application. Below is my current code setup, but unfortunately, it does not achieve the desired result: <textarea matInput matInput rows="15" cols="40" ...