Skip to content

Commit

Permalink
fix(document): fire pre validate hooks on 5 level deep single nested …
Browse files Browse the repository at this point in the history
…subdoc when modifying after save()

Fix #14591
  • Loading branch information
vkarpov15 committed May 17, 2024
1 parent e661f5e commit 65c40b5
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 1 deletion.
4 changes: 4 additions & 0 deletions lib/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -1716,6 +1716,9 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
} else {
obj._doc[parts[i]] = val;
}
if (shouldModify) {
obj.markModified(parts[i]);
}
} else {
obj[parts[i]] = val;
}
Expand Down Expand Up @@ -2698,6 +2701,7 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip) {
!doc.isDirectModified(fullPathToSubdoc) &&
!doc.$isDefault(fullPathToSubdoc)) {
paths.add(fullPathToSubdoc);

if (doc.$__.pathsToScopes == null) {
doc.$__.pathsToScopes = {};
}
Expand Down
2 changes: 1 addition & 1 deletion lib/types/subdocument.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ Subdocument.prototype.$__fullPath = function(path) {

/**
* Given a path relative to this document, return the path relative
* to the top-level document.
* to the parent document.
* @param {String} p
* @returns {String}
* @method $__pathRelativeToParent
Expand Down
35 changes: 35 additions & 0 deletions test/document.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12627,6 +12627,41 @@ describe('document', function() {
doc.set('branding.logo.attachment', { name: 'coolLogo' });
await doc.save();
assert.strictEqual(attachmentSchemaPreValidateCalls, 1);

instance.set('branding.logo.attachment', { name: 'coolOtherLogo' });
await instance.save();
assert.strictEqual(attachmentSchemaPreValidateCalls, 2);
});

it('fires pre validate hooks on 5 level deep single nested subdoc when modifying after save() (gh-14591)', async function() {
let preValidate = [];

const createSchema = (path, subSchema) => {
const schema = new Schema({ [path]: subSchema });
schema.pre('validate', function() {
preValidate.push(path);
});
return schema;
};

const e = createSchema('e', { type: String });
const d = createSchema('d', { type: e });
const c = createSchema('c', { type: d });
const b = createSchema('b', { type: c });
const a = createSchema('a', { type: b });
b.add({ otherProp: String });
const NestedModelHooksTestModel = db.model('Test', a);

const newData = { a: { b: { c: { d: { e: new Date().toString() } } } } };
newData.a.otherProp = 'test';
const doc = await new NestedModelHooksTestModel(newData).save();
preValidate = [];
doc.set({ 'a.b.c.d.e': 'updated nested value' });
await doc.save();
assert.deepStrictEqual(preValidate, ['a', 'b', 'c', 'd', 'e']);

const fromDb = await NestedModelHooksTestModel.findById(doc._id);
assert.strictEqual(fromDb.a.otherProp, 'test');
});

it('returns constructor if using $model() with no args (gh-13878)', async function() {
Expand Down

0 comments on commit 65c40b5

Please sign in to comment.