fix(core): prevent timestamp stripping in Model.build (#7284)#18173
fix(core): prevent timestamp stripping in Model.build (#7284)#18173abdelrahmanSheref101 wants to merge 3 commits intosequelize:mainsequelize/sequelize:mainfrom abdelrahmanSheref101:fix/core-7284-build-timestampsabdelrahmanSheref101/sequelize:fix/core-7284-build-timestampsCopy head branch name to clipboard
Conversation
- Fixes issue where Model.build(instance.toJSON()) stripped timestamps. - Ensure timestamps are assigned in _initValues when isNewRecord is false. - Added unit test in build.test.js for round-trip consistency.
📝 WalkthroughWalkthroughThe changes fix an issue where Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/core/test/unit/instance/build.test.js (1)
99-132: Test doesn't exercise the fix in_initValues.This test uses
timestamps: falsewith manually defined timestamp fields. With this configuration,createdAt/updatedAtare not inreadOnlyAttributeNames, so the new code at lines 268-280 inmodel.jsisn't triggered.The fix addresses the case where:
- Timestamps are enabled (the default) — so
createdAt/updatedAtare inreadOnlyAttributeNamesisNewRecord: falseis passed tobuild()— triggering the new code pathConsider adding a test that verifies the actual fix:
💡 Suggested additional test
+ it('should retain timestamps when rebuilding with isNewRecord: false', () => { + const User = current.define('User', { + username: DataTypes.STRING, + }); // timestamps: true by default + + const now = new Date(); + now.setMilliseconds(0); + + const instance = User.build( + { + username: 'user-name', + createdAt: now, + updatedAt: now, + }, + { isNewRecord: false }, + ); + + const json = instance.toJSON(); + const rebuiltInstance = User.build(json, { isNewRecord: false }); + + expect(rebuiltInstance.get('createdAt')).to.be.an.instanceof(Date); + expect(rebuiltInstance.get('updatedAt')).to.be.an.instanceof(Date); + expect(rebuiltInstance.get('createdAt').getTime()).to.equal(now.getTime()); + expect(rebuiltInstance.get('updatedAt').getTime()).to.equal(now.getTime()); + });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/test/unit/instance/build.test.js` around lines 99 - 132, Add a new unit test in build.test.js that exercises the _initValues code path by using a model with default timestamps (do not set timestamps:false), defining createdAt and updatedAt attributes, building an instance with isNewRecord: false and providing createdAt/updatedAt values (use a Date with milliseconds zeroed), then assert the rebuilt instance preserves those dates (instances of Date, equal getTime()) and that dataValues contains createdAt/updatedAt; this ensures the branch that checks readOnlyAttributeNames (the new logic in _initValues) is actually tested when timestamps are enabled and build() is called with isNewRecord:false.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/core/test/unit/instance/build.test.js`:
- Around line 99-132: Add a new unit test in build.test.js that exercises the
_initValues code path by using a model with default timestamps (do not set
timestamps:false), defining createdAt and updatedAt attributes, building an
instance with isNewRecord: false and providing createdAt/updatedAt values (use a
Date with milliseconds zeroed), then assert the rebuilt instance preserves those
dates (instances of Date, equal getTime()) and that dataValues contains
createdAt/updatedAt; this ensures the branch that checks readOnlyAttributeNames
(the new logic in _initValues) is actually tested when timestamps are enabled
and build() is called with isNewRecord:false.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: b903e261-36fa-496a-b757-639ff7f68290
📒 Files selected for processing (2)
packages/core/src/model.jspackages/core/test/unit/instance/build.test.js
Pull Request Checklist
Description of Changes
This PR resolves an issue where
Model.build()would stripcreatedAtandupdatedAtvalues when an instance was rebuilt from a JSON object (e.g.,Model.build(instance.toJSON()))._initValuesto ensure timestamps are assigned whenisNewRecordis false. This allows the model to correctly hydrate existing data that includes manual timestamp values.test/unit/instance/build.test.jsto verify that timestamps are retained during a round-trip build.List of Breaking Changes
None. This fix aligns the behavior of
Model.buildwith standard attribute hydration for existing records.Summary by CodeRabbit