What is the best way to test TypeScript optional parameter in Jasmine?

I am currently revising a TypeScript function to include an optional parameter with a default value. This function is a crucial operation, and it is utilized by several high-level operations. Existing calls to the function do not include the new parameter (thus utilizing the default value), while new and revised methods provide a value for the new parameter. An example of the simplified version is as follows:

export class Scratch {
  coreOperation(mainArg: string, option: boolean = false) {
    // ...
  }

  private midLevelOperation(mainArg: string) {
    this.coreOperation(mainArg + '1');
  }

  highLevelOperation1(mainArg: string) {
    this.midLevelOperation(mainArg);
    this.coreOperation(mainArg + '2', true);
  }
}

I am also updating the Jasmine tests for the higher-level operations. I aim to confirm that these operations trigger the core operation with specific parameters. The tests would resemble the following:

describe('Scratch', () => {
  let objectUnderTest: Scratch;

  beforeEach(() => {
    objectUnderTest = new Scratch();
    spyOn(objectUnderTest, 'coreOperation');
  });

  describe('highLevelOperation1', () => {
    it('should call core operation', () => {
      objectUnderTest.highLevelOperation1('main');
      expect(objectUnderTest.coreOperation).toHaveBeenCalledWith('main1', false);
      expect(objectUnderTest.coreOperation).toHaveBeenCalledWith('main2', true);
    });
  });
});

The issue arises when using Jasmine's toHaveBeenCalledWith because it does not recognize that the second argument has a default value. The error message for the provided code is as follows:

  - Expected spy coreOperation to have been called with:
    [ 'main1', false ]
  but actual calls were:
    [ 'main1' ],
    [ 'main2', true ].

To resolve this, one could remove the false argument from the test in order to pass. However, it is preferable for the tests not to be aware of whether call sites use one or two arguments, particularly in cases involving private library functions like the one shown here.

Is there a feasible approach to create a Jasmine matcher that functions effectively regardless of whether an optional parameter is excluded or if the default value is supplied?

Answer â„–1

Regrettably, there is no known method to monitor default or optional parameters within Jasmine.

This limitation exists for several reasons:

  1. Default parameters are recorded in the arguments array variable specific to the invoked method's scope, rather than as actual values passed into parameters.
  2. The toHaveBeenCalledWith function solely verifies the arguments the method was called with, not the values used to default any missing parameters.

To navigate around this issue, one can encapsulate the target method within another function containing a default parameter such as option: boolean = false. This way, it becomes possible to observe what coreOperation was called with:

coreOperation(mainArg: string, option: boolean) {
  // ...
}

private coreOperationDefaultWrapper(mainArg: string, option: boolean = false) {
  this.coreOperationmainArg(mainArg, option);
}

Remember, the most effective tests evaluate the application’s functionality rather than its code structure. Therefore, it is advisable to focus on testing the behavior resulting from default arguments, rather than inspecting their exact values. While this may not always be feasible, I trust that the aforementioned example can provide some assistance! :)

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

Discover the Category of Union based on Discriminator

Imagine a scenario where there is a concept of a union type called Thing, which combines types Foo, Bar, and Baz, each identified by the property tag. interface Foo { tag: 'Foo' foo: string } interface Bar { tag: 'Bar' bar: nu ...

What is the best way to transfer information between two components when working with an edit form?

Presently, I am utilizing a modal material dialog window that prompts the user to input a number and then press search. Upon searching, it retrieves data from an API call and receives a response object. My goal is to utilize this response object to populat ...

Angular Appreciation Meter

Looking to create a rating system using Angular. The square should turn green if there are more likes than dislikes, and red vice versa (check out the stackblitz link for reference). Check it out here: View demo I've tried debugging my code with con ...

The issue of ngModel not binding to the value of ion-select in Angular Ionic

Having an ion select outside of a form with an ngModel attribute bound to "selectedValue", I encounter an issue where my selections are not being properly populated in the selectedValue variable even though they appear in the ionChange method. The main pur ...

There is no module.hot in Webpack for TypeScript

I am trying to implement Webpack HMR in a NodeJS project that is built using TypeScript. However, I am encountering an issue where module.hot is not available: @types/webpack-env defines: declare var module: __WebpackModuleApi.Module This conflict ...

A generic type in TypeScript that allows for partial types to be specified

My goal is to create a type that combines explicit properties with a generic type, where the explicit properties have priority in case of matching keys. I've tried implementing this but encountered an error on a specific line - can anyone clarify why ...

Encountering problem with '@datadog/browser-rum' compilation related to the 'allowedTracingOrigins' attribute

I'm facing a typing problem with the @datadog/browser-rum library: Error: node_modules/@datadog/browser-rum-core/src/domain/configuration.ts:100:3 error TS2322: Type '{ applicationId: string; version: string; actionNameAttribute: string; premium ...

Next.js useDarkMode Hook Fails to Maintain Dark Mode State Between Page Reloads

I'm currently developing a theme toggle feature within a Next.js application using the use-dark-mode hook and @nextui-org/react components. Although the dark mode toggle functions correctly, I encounter an issue where the theme resets to light mode up ...

A guide to effectively utilizing a TypeScript cast in JSX/TSX components

When trying to cast TypeScript in a .tsx file, the compiler automatically interprets it as JSX. For example: (<HtmlInputElement> event.target).value You will receive an error message stating that: JSX element type 'HtmlInputElement' is ...

What's causing the subscription feature to malfunction in a fresh browser tab?

I am facing an issue with camera entries on an angular website. Whenever I click on an entry, a new window opens to display the camera livestream. However, I am having trouble with the subscribe functionality. Important note: Once the window is open, subs ...

Populating datasets with relative indexing

I am working on a code where I need to fill the datasets with the property isProjected set to 1. There are 3 datasets - lower estimate, projected, and upper estimate. The goal is to fill the Lower Estimate and Upper Estimate with a background color of rgba ...

Tip Sheet: Combining Elements from an Array of Objects into a Single Array

When I invoke the function getAllUsers() { return this.http.get(this.url); } using: this.UserService.getAllUsers().subscribe(res => { console.log(res); }) The result is: [{id:1, name:'anna'}, {id:2, name:'john'}, {id:3, name ...

TypeScript fails to detect errors in setting state with incorrect interface properties in React components

Even though I clearly defined an interface with specific props and assigned that interface to be used in useState, no error is triggered when the state value is set to an array of objects with incompatible props: This is how ResultProps is defined: interf ...

Using Typescript: ForOf Iteration with Unknown Value Types

My journey began with a quick peek at this particular inquiry. However, the approach discussed there utilized custom typing. I am currently iterating over object entries using a for-of loop. Here's a snippet of the values I'm dealing with below. ...

Customizing exception handling in Ionic2 app

I have been working on an Ionic v2 App and trying to incorporate the ExceptionHandler from angular2. With Ionic2 not requiring the developer to explicitly call bootstrap, it appears challenging to implement this feature at the moment. Has anyone successfu ...

ReactJS Provider not passing props to Consumer resulting in undefined value upon access

Hey there! I've been facing an issue with passing context from a Provider to a consumer in my application. Everything was working fine until suddenly it stopped. Let me walk you through a sample of my code. First off, I have a file named AppContext.t ...

Tips for crafting a test scenario for input alterations within Angular

Hello there, currently I am working on an application using Angular and TypeScript. Here is a snippet of my template code: <input type="text" placeholder="Search Results" (input)="searchInput($event)"> And here is the TypeScript code for the searc ...

Yep, identifying InferType optional attributes

Here's an example of a Yup schema I created to fetch entities known as Parcels: export const FindParcelsParamsSchema = Yup.object({ cursor: Yup.number().optional(), pageSize: Yup.number().positive().integer().optional(), }); All fields are option ...

In React-Redux, attempting to assign a value to an empty string is not permitted

When using the useDispatch hook, I am facing an issue where I cannot set the string to an empty value. Instead, it always sets the value to the last character in the string. App.tsx const dispatch = useDispatch(); dispatch(updateLocation('')); ...

Enhance user information by adding necessary fields

I often encounter situations where I need to select a specific entry from a set of data in a component, whether through a select box or as part of a table. However, the way I intend to utilize this data typically requires additional fields like the "label ...