Guide to writing a unit test for a parameter decorator in NestJs

I want to implement a unit test for a basic custom decorator that I created, but I'm facing some challenges. This decorator was developed based on the solution provided here. I have Keycloak authentication set up and using this solution in my controllers allows me to retrieve the user object associated with the token.

Here's how I use the decorator:

import {
  Body,
  Controller,
  Post,
  UseGuards,
  UsePipes,
  ValidationPipe,
} from '@nestjs/common'
import { LogbooksService } from './logbooks.service'
import { User } from 'src/typeorm/user.entity'
import { AuthUser } from 'src/users/users.decorator'
import { UsersGuard } from 'src/users/users.guard'
import { CreateLogbookDto } from './dto/CreateLogbook.dto'

@Controller('logbooks')
export class LogbooksController {
  constructor(private readonly logbookService: LogbooksService) {}

  @Post()
  @UseGuards(UsersGuard)
  @UsePipes(ValidationPipe)
  async createLogbook(
    @Body() createLogbookDto: CreateLogbookDto,
    @AuthUser('user') user: User,
  ) {
    const newLogbook = await this.logbookService.createLogbook(
      createLogbookDto,
      user,
    )
    return newLogbook
  }
}

Below is the simple decorator code:

import { createParamDecorator } from '@nestjs/common'

export const AuthUser = createParamDecorator((data: string, req) => {
  return req.args[0].principal
})

The version of Nest being used is 10.2.1

Any advice on how to successfully do this would be greatly appreciated. Thank you!

Answer №1

  1. The old decorator is no longer compatible with Nest v10 and the req parameter was positioned as the second argument in Nest v7, if my memory serves me right. The updated custom decorator should look like this:
export const AuthUser = createParamDecorator((data: string, ctx: ExecutionContext) => {
  const req = ctx.switchToHttp().getRequest()
  return req[data].principle
})

This will retrieve req.user.principle as intended.

  1. Unit testing something of this nature isn't straightforward, aside from isolating the callback within createParamDecorator, which remains an option. However, it's more effective to test this through integration or end-to-end tests that actually send requests to the server.

Answer №2

I have come across a solution:

function createParamDecoratorFactory(decorator: unknown) {
    class TestParamDecorator {
      public test(@AuthUser() value) {
        console.log(value)
        console.log(decorator)
      }
    }

    const arguments = Reflect.getMetadata(ROUTE_ARGS_METADATA, TestParamDecorator, 'test')
    return arguments[Object.keys(arguments)[0]].factory
  }
...Setting up Test Module

describe('decorator', () => {
    it('Testing Decorator Functionality', () => {
      const request = httpMock.createRequest()
      const response = httpMock.createResponse()
      request.user = { principle: {} }
      const context = new ExecutionContextHost(
        [request, response],
        LogbooksController,
        logbookController.createLogbook,
      )
      const factory = createParamDecoratorFactory(AuthUser)
      user = factory('user', context)
    })
  })

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

Retrieving Data from Outside Source using AngularJS

Is there a way to retrieve JSON-Text-Stream data from a specific URL (e.g. SOMEURL/ean.php?id=4001513007704)? The returned result typically appears as follows: { "product": { "ean_id": "4001513007704", "title": "Gerolsteiner Mineralw ...

Using AngularJS to create interactive popups within leaflet maps

My map uses leafletjs to create markers such as ev124, ev125, and so on. In addition, there are links with a key attribute like <a ng-click="popup(evsi)" key="124">link</a> Using angular, I extract the key value this way: $scope.popup= funct ...

Using the `ssh2` module in Node.js without specifying a specific object

When you use require('ssh2') in Node.js without a specific object (e.g. require('ssh2').Client), what does it imply? I'm in the process of understanding some code and still new to learning Node.js. Here's how it is being used: ...

Unlocking the AngularJS variable within the template script

My controller code: $scope.totals = totals; In the template, I am able to successfully inject HTML using this code: {{totals}} However, my goal is to access the totals variable in a script within the template. Here's what I attempted: <script& ...

Develop fresh JavaScript code using JavaScript

Is it possible to dynamically create a new row in an HTML table by clicking on a button? Each row contains multiple input fields. <script type="text/javascript> row = 2; specific_row_id = new Array(); $(document).ready(function() { $(".change_1 ...

What is the method for exporting all functions from a TypeScript file with a default export included?

An example of the export type mentioned is React. To use it, we can include the following code: import React, {Component} from "react". This allows us to access both React.Component and Component. What steps are necessary to make this possible? ...

Troubleshooting: Resolving the error message 'Unable to assign to Partial<this>' within a subclass method

If I call the base class's update method using a subclass instance, it functions as expected. However, I encounter an error when attempting to do so within a subclass method: Argument of type '{ prop: number; }' is not compatible with par ...

I used npm to install AngularJS and then included AngularJS in my application

My goal is to set up AngularJS v1.5.x using npm and integrate it into my application for seamless utilization. Most tutorials opt for downloading the Angular Version from angularjs.org and manually adding it to the index.html within a <script></sc ...

Iterating through a JSON object to verify the presence of a specific value

I have a JSON Object and I am looking for a way in Angular 6 to search for the value "Tennis" in the key "name". Can you provide guidance on how to achieve this? { "id":2, "name":"Sports", "url":"/sports" "children":[ { "id":1, ...

Discover the seamless transformation of a class definition into a Vue 3 component definition utilizing the dazzling 'tc39' decorators

The proposed API in the tc39/proposal-decorators repository is significantly different from the previous decorators API. Although TypeScript 5 doesn't fully support the new API yet, it's only a matter of time before the old API becomes deprecated ...

Are there any alternative methods to define a constructor function in TypeScript that do not involve utilizing classes? Upon researching on this subject, it appears that all sources suggest using classes

Is it possible to transform this class declaration into a constructor function without losing TypeScript compatibility? class Animal { constructor(public name: string, public energy: string) {} } ...

Removing a single object from an array of objects using MongooseJS

Hello to all the MongooseJS experts out there! I'm a newcomer to MongooseJS, and I've been trying to solve this problem for the past two days but haven't found a solution yet. Thank you in advance for any help! The Issue with My Delete me ...

Using Vuex: Bypassing Action and triggering Mutation directly within Component

When working with a vue.js app and utilizing vuex as the state management store, one may need to update a property's value in vuex. This can be achieved through two methods: One can dispatch an action method, which will then commit a mutation to a ...

The presence of React Router in Office JS Excel results in a blank screen

My current project involves developing add-ins for Excel using TypeScript and React. However, I have encountered numerous challenges along the way. Unlike a typical CRA React boilerplate web application, the Office add-in behaves differently. To illustrate ...

Updating the contents of one specific div without affecting all other divs with the same class

Below is the HTML code snippet in question: <a class="btn test-btn test-btn-1"> <span>Content 1</span> </a> This particular code block appears multiple times on the page. The number at the end of test-btn- is dynamically generat ...

Step-by-step guide on how to effectively send a NodeJS request and stream it into a separate response

Currently, I am in the process of developing an API to interact with a specific map service that requires the use of an API key. It is crucial for me to keep this API key private. To achieve this, I plan to make internal calls within my server's own A ...

Steps for retrieving multiple documents from Firestore within a cloud function

In my cloud function, I have set up a trigger that activates on document write. This function is designed to check multiple documents based on the trigger and execute if/else statements accordingly. I have developed a method that retrieves all documents u ...

Encountering a 404 error in an AngularJS app within Cordova on Android

Currently, I am working on an android application using Cordova and AngularJS (front-end framework OnsenUI). Below is the code snippet for my GET request to retrieve data from the server: $http.get(url+"getlotterylist").then(function(msg){ $scope. ...

Learn how to subscribe to Azure Event Grid using Angular without the need for a backend service layer

I am currently working on an Angular project and I am looking to set up Azure Event Grid subscription directly from the client-side without the need for a backend service. After exploring different options, I have not yet found a straightforward solution. ...

Jump to Anchor when Page Reloads

Hey there! I'm currently developing a gallery script and I'm trying to figure out how to automatically position the page to the top of a specific anchor when it is loaded. I attempted to use the following code: <script>location.href = "#tr ...