Sudharsan Venkatraj
Sudharsan Venkatraj

Reputation: 581

Unit Test case for pre hook in mongoose using jest

i AM trying to write a unit test case for pre-hook. I was facing the issue in condition to check this.isNew when I pass the document in the console it prints as undefined. Can anyone tell me what's wrong in this code?

schema

// hooks callback
    export async function arrayCount(this: any, next: NextFunction) {
      if (this.isNew) {
        const parentArray = (this as any).parentArray();
        const maxSequence = parentArray.reduce((maximum: number, review: ReviewRatingType) => {
          if (review.review_rating_no) {
            const sequenceString = review.review_rating_no.match(/\d+/g);
            if (!sequenceString) {
              throw new Error('Invalid sequence in array.');
            }
            const sequenceNumber = parseInt(sequenceString.toString());
            if (sequenceNumber > maximum) {
              maximum = sequenceNumber;
            }
          }
          return maximum;
        }, 0);
        const sequence = 'RAT' + (maxSequence + 1 + '').padStart(3, '0');
        this.set({ review_rating_no: sequence });
      }
      next();
    }
    /**
     * Product Review Schema.
     */
    @singleton()
    export class ReviewRatingSchema extends AbstractSchema {
      isSubDocument = true;
      entityName = 'review_rating';
      schemaDefinition = {
        review_rating_user_id: {
          type: ObjectId,
          required: [true, 'review_rating_user_id is required'],
          ref: 'UserModel',
          unique: true,
        },
        review_rating_user_full_name: {
          type: String,
          trim: true,
          minlength: 3,
          maxlength: 20,
          validate: {
            validator: function (value: string) {
              return RegexConstants.betaRegex.test(value);
            },
            message: 'review_rating_user_full_name is invalid.',
          },
          required: [true, 'review_rating_user_full_name is required'],
        },
        review_rating_user_rating: {
          type: String,
          minlength: 1,
          maxlength: 1,
          validate: {
            validator: function (value: string) {
              return RegexConstants.rating.test(value);
            },
            message: 'review_rating_user_rating is invalid.',
          },
          required: [true, 'review_rating_user_rating is required'],
        },
        review_rating_description: {
          type: String,
          trim: true,
          minlength: 10,
          maxlength: 500,
          validate: {
            validator: function (value: string) {
              return RegexConstants.alphaRegex.test(value);
            },
            message: 'review_rating_description is invalid.',
          },
          required: [true, 'review_rating_description is required'],
        },
      };

      indexes = ['review_rating_user_id'];

      hooks = () => {
        // sequence for review rating
        this.schema?.pre('save', arrayCount);
      };
    }

Test Case

  describe('save hook', () => {
    it('should encrypt user password.', async () => {
      // Preparing
      const context = [
        {
          review_rating_status_is_active: false,
          review_rating_user_id: '5d5e6329a85f1a0ba718ceb3',
          review_rating_user_full_name: 'susdhassr',
          review_rating_modified_date: ' 2020-05-20T06:31:37.728Z',
        },
        {
          review_rating_status_is_active: false,
          review_rating_user_id: '5d5e6329a85f1a0ba718ceb5',
          review_rating_user_full_name: 'susdhassr',
          review_rating_modified_date: ' 2020-05-20T06:31:37.728Z',
        }
      ];
      for (let i in context){
        // console.log(context[i])
        await arrayCount.call(context[i], next);
      }
      // Verifying
      expect(next).toBeCalledTimes(2);
    });
  });

Upvotes: 0

Views: 492

Answers (2)

Sudharsan Venkatraj
Sudharsan Venkatraj

Reputation: 581

   it('should call next when valid document is passed.', async () => {
      // Preparing
      const ProductReview = [
        {
          review_rating_status_is_active: false,
          review_rating_user_id: '5d5e6329a85f1a0ba718ceb3',
          review_rating_user_full_name: 'susdhassr',
          review_rating_user_rating: '2',
          review_rating_description: 'W Ds as always, solid build, worthy product',
          review_rating_created_date: '2020-05-20T06:31:37.728Z',
          review_rating_modified_date: ' 2020-05-20T06:31:37.728Z',
        },
      ];
      const context = {
        isNew: jest.fn().mockReturnValue(ProductReview)
      };
      await arrayCount.call(context, next);
      // Verifying
      expect(next).toBeCalledTimes(1);
    });

Upvotes: 1

AJcodez
AJcodez

Reputation: 34166

It looks like you are calling the pre hook on a plain object instead of a mongoose document object. Plain objects will not have all of the mongoose document properties like isNew. Try this:

await arrayCount.call(new ReviewRating(context[i]), next);

If you want parentArray() then it probably needs to be referenced from a parent document object.

const review = new Review({ ratings: [ /* your objects */ ] });
await arrayCount.call(review.ratings[i], next);

Upvotes: 0

Related Questions