Skip to content

Commit 34fea9e

Browse files
authored
Merge pull request #13912 from Automattic/vkarpov15/gh-13876
fix(document): call pre('validate') hooks when modifying a path underneath triply nested subdoc
2 parents d219306 + 6447b97 commit 34fea9e

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

lib/document.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -1694,6 +1694,13 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
16941694
if (last) {
16951695
if (obj instanceof Map) {
16961696
obj.set(parts[i], val);
1697+
} else if (obj.$isSingleNested) {
1698+
if (!(parts[i] in obj)) {
1699+
obj[parts[i]] = val;
1700+
obj._doc[parts[i]] = val;
1701+
} else {
1702+
obj._doc[parts[i]] = val;
1703+
}
16971704
} else {
16981705
obj[parts[i]] = val;
16991706
}
@@ -1705,7 +1712,7 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
17051712
} else if (value && value instanceof Embedded) {
17061713
obj = value;
17071714
} else if (value && !Array.isArray(value) && value.$isSingleNested) {
1708-
obj = value._doc;
1715+
obj = value;
17091716
} else if (value && Array.isArray(value)) {
17101717
obj = value;
17111718
} else if (value == null) {
@@ -2650,7 +2657,7 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip) {
26502657
const modifiedPaths = doc.modifiedPaths();
26512658
for (const subdoc of subdocs) {
26522659
if (subdoc.$basePath) {
2653-
const fullPathToSubdoc = subdoc.$__fullPathWithIndexes();
2660+
const fullPathToSubdoc = subdoc.$isSingleNested ? subdoc.$__pathRelativeToParent() : subdoc.$__fullPathWithIndexes();
26542661

26552662
// Remove child paths for now, because we'll be validating the whole
26562663
// subdoc.

test/document.test.js

+21
Original file line numberDiff line numberDiff line change
@@ -12212,6 +12212,8 @@ describe('document', function() {
1221212212

1221312213
const x = new Test();
1221412214
x.set('d.x.y', 1);
12215+
assert.strictEqual(x.d.x.y, 1);
12216+
assert.deepStrictEqual(x.get('d.x'), { y: 1 });
1221512217
assert.strictEqual(x.get('d.x.y'), 1);
1221612218
await x.save();
1221712219

@@ -12527,6 +12529,25 @@ describe('document', function() {
1252712529
assert.strictEqual(parent.get('child.concreteProp'), 123);
1252812530
assert.strictEqual(parent.toObject().child.concreteProp, 123);
1252912531
});
12532+
12533+
it('fires pre validate hooks on 4 level single nested subdocs (gh-13876)', async function() {
12534+
let attachmentSchemaPreValidateCalls = 0;
12535+
const attachmentSchema = new Schema({ name: String });
12536+
attachmentSchema.pre('validate', () => { ++attachmentSchemaPreValidateCalls; });
12537+
12538+
const richImageSchema = new Schema({ attachment: { type: attachmentSchema, required: false } });
12539+
const brandingSchema = new Schema({ logo: richImageSchema });
12540+
const instanceSchema = new Schema({ branding: brandingSchema });
12541+
const TestModel = db.model('Test', instanceSchema);
12542+
12543+
const instance = await TestModel.create({ branding: { logo: {} } });
12544+
assert.strictEqual(attachmentSchemaPreValidateCalls, 0);
12545+
const doc = await TestModel.findById(instance._id);
12546+
12547+
doc.set('branding.logo.attachment', { name: 'coolLogo' });
12548+
await doc.save();
12549+
assert.strictEqual(attachmentSchemaPreValidateCalls, 1);
12550+
});
1253012551
});
1253112552

1253212553
describe('Check if instance function that is supplied in schema option is availabe', function() {

test/query.middleware.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ describe('query middleware', function() {
359359
assert.equal(postCount, 1);
360360
});
361361

362-
it('error handlers XYZ (gh-2284)', async function() {
362+
it('error handlers (gh-2284)', async function() {
363363
const testSchema = new Schema({ title: { type: String, unique: true } });
364364

365365
testSchema.post('updateOne', function(error, res, next) {

0 commit comments

Comments
 (0)