Reputation: 581
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
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
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