From 544d1c41b48bb7db8eb2688d9c5c06defdbb6193 Mon Sep 17 00:00:00 2001 From: hasezoey Date: Wed, 17 May 2023 12:34:20 +0200 Subject: [PATCH 1/3] fix(getModelMapForPopulate): mention model name in error fixes #13406 --- .../populate/getModelsMapForPopulate.js | 2 +- test/helpers/getModelsMapForPopulate.test.js | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 test/helpers/getModelsMapForPopulate.test.js diff --git a/lib/helpers/populate/getModelsMapForPopulate.js b/lib/helpers/populate/getModelsMapForPopulate.js index 41b92097419..024bb90af95 100644 --- a/lib/helpers/populate/getModelsMapForPopulate.js +++ b/lib/helpers/populate/getModelsMapForPopulate.js @@ -390,7 +390,7 @@ function _virtualPopulate(model, docs, options, _virtualRes) { if (!localField || !foreignField) { return new MongooseError('If you are populating a virtual, you must set the ' + - 'localField and foreignField options'); + 'localField and foreignField options' + ` (Model: ${model.modelName})`); } if (typeof localField === 'function') { diff --git a/test/helpers/getModelsMapForPopulate.test.js b/test/helpers/getModelsMapForPopulate.test.js new file mode 100644 index 00000000000..df1c00b1d31 --- /dev/null +++ b/test/helpers/getModelsMapForPopulate.test.js @@ -0,0 +1,41 @@ +'use strict'; + +const assert = require('assert'); +const start = require('../common'); +const util = require('../util'); + +const mongoose = start.mongoose; +const Schema = mongoose.Schema; + +describe('getModelsMapForPopulate', function() { + let db; + + beforeEach(() => db.deleteModel(/.*/)); + + before(function() { + db = start(); + }); + + after(async function() { + await db.close(); + }); + + afterEach(() => util.clearTestData(db)); + afterEach(() => util.stopRemainingOps(db)); + + it('should error on missing options on populate', async function() { + const sch = new Schema({ + test: mongoose.Schema.Types.ObjectId + }, { + virtuals: { + someVirtual: {} + } + }); + + const model = db.model('Test', sch); + + const doc = await model.create({ test: new mongoose.Types.ObjectId() }); + + await assert.rejects(() => model.findById(doc._id).populate('someVirtual').exec(), /If you are populating a virtual, you must set the localField and foreignField options \(Model: Test\)/); + }); +}); From bc01db8fefa07bef04bf2fb97e46b0db3f4d5e22 Mon Sep 17 00:00:00 2001 From: hasezoey Date: Wed, 17 May 2023 16:14:16 +0200 Subject: [PATCH 2/3] style(getModelsMapForPopulate): combine string statement Co-authored-by: Uzlopak --- lib/helpers/populate/getModelsMapForPopulate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/helpers/populate/getModelsMapForPopulate.js b/lib/helpers/populate/getModelsMapForPopulate.js index 024bb90af95..68bd3dea82c 100644 --- a/lib/helpers/populate/getModelsMapForPopulate.js +++ b/lib/helpers/populate/getModelsMapForPopulate.js @@ -390,7 +390,7 @@ function _virtualPopulate(model, docs, options, _virtualRes) { if (!localField || !foreignField) { return new MongooseError('If you are populating a virtual, you must set the ' + - 'localField and foreignField options' + ` (Model: ${model.modelName})`); + `localField and foreignField options (Model: ${model.modelName})`); } if (typeof localField === 'function') { From 66c553042def63af1d96c45b9ac5e183b8f6d1e2 Mon Sep 17 00:00:00 2001 From: hasezoey Date: Thu, 18 May 2023 10:39:27 +0200 Subject: [PATCH 3/3] style(getModelsMapForPopulate): change error to also include the virtual path --- lib/helpers/populate/getModelsMapForPopulate.js | 3 +-- test/helpers/getModelsMapForPopulate.test.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/helpers/populate/getModelsMapForPopulate.js b/lib/helpers/populate/getModelsMapForPopulate.js index 68bd3dea82c..dbe3707766a 100644 --- a/lib/helpers/populate/getModelsMapForPopulate.js +++ b/lib/helpers/populate/getModelsMapForPopulate.js @@ -389,8 +389,7 @@ function _virtualPopulate(model, docs, options, _virtualRes) { let foreignField = virtual.options.foreignField; if (!localField || !foreignField) { - return new MongooseError('If you are populating a virtual, you must set the ' + - `localField and foreignField options (Model: ${model.modelName})`); + return new MongooseError(`Cannot populate virtual \`${options.path}\` on model \`${model.modelName}\`, because options \`localField\` and / or \`foreignField\` are missing`); } if (typeof localField === 'function') { diff --git a/test/helpers/getModelsMapForPopulate.test.js b/test/helpers/getModelsMapForPopulate.test.js index df1c00b1d31..5b2d6632f68 100644 --- a/test/helpers/getModelsMapForPopulate.test.js +++ b/test/helpers/getModelsMapForPopulate.test.js @@ -36,6 +36,6 @@ describe('getModelsMapForPopulate', function() { const doc = await model.create({ test: new mongoose.Types.ObjectId() }); - await assert.rejects(() => model.findById(doc._id).populate('someVirtual').exec(), /If you are populating a virtual, you must set the localField and foreignField options \(Model: Test\)/); + await assert.rejects(() => model.findById(doc._id).populate('someVirtual').exec(), /Cannot populate virtual `someVirtual` on model `Test`, because options `localField` and \/ or `foreignField` are missing/); }); });