diff --git a/lib/dao.js b/lib/dao.js index 887711df..4db12e8d 100644 --- a/lib/dao.js +++ b/lib/dao.js @@ -2609,6 +2609,11 @@ DataAccessObject.replaceById = function(id, data, options, cb) { err.statusCode = 400; process.nextTick(function() { cb(err); }); return cb.promise; + } else { + // Ensure any type conversion applied by the instance constructor + // on `data.id` is applied on the `id` value too. + // Typically, MongoDB converts PK value from a string to an ObjectID. + id = inst[pkName]; } let context = { diff --git a/test/manipulation.test.js b/test/manipulation.test.js index b49e186b..c6015b19 100644 --- a/test/manipulation.test.js +++ b/test/manipulation.test.js @@ -1576,6 +1576,33 @@ describe('manipulation', function() { done(); }); }); + + it('correctly coerces the PK value', async () => { + const created = await Post.create({ + title: 'a title', + content: 'a content', + }); + + // Emulate what happens when model instance is received by REST API clients + const data = JSON.parse(JSON.stringify(created)); + + // Modify some of the data + data.title = 'Draft'; + + // Call replaceById to modify the database record + await Post.replaceById(data.id, data); + + // Verify what has been stored + const found = await Post.findById(data.id); + found.toObject().should.eql({ + id: created.id, + title: 'Draft', + content: 'a content', + }); + + // Verify that no warnings were triggered + Object.keys(Post._warned).should.be.empty(); + }); }); describe('findOrCreate', function() {