mswjs / data

Data modeling and relation library for testing JavaScript applications.
https://npm.im/@mswjs/data
MIT License
823 stars 52 forks source link

Relational property's getter is lost when updating the parent entity #170

Closed kettanaito closed 3 years ago

kettanaito commented 3 years ago

Steps to reproduce

const db = factory({
  segment: {
    id: primaryKey(String),
    title: String,
    revision: oneOf('revision'),
  },
  revision: {
    id: primaryKey(String),
    title: String,
  },
})

db.segment.create({
  id: 'segment-1',
  revision: db.revision.create({
    id: 'revision-1',
    title: 'Initial',
  }),
})

// Update the parent entity "segment".
const segment = db.segment.update({
  where: { id: { equals: 'segment-1' } },
  data: { title: 'Updated segment' },
})!

expect(Object.getOwnPropertyDescriptor(segment, 'revision')).toHaveProperty(
  'get',
)

segment.revision is no longer a getter to resolve the referenced entity. Instead, it's the actual value of the referenced entity at the moment of the "segment" update.

Root cause

The issue is caused by spreading the updated entityChunk when performing update:

https://github.com/mswjs/data/blob/0970e7ed5a9094d6618ed6563f8bb3a00d5c9ecc/src/model/updateEntity.ts#L120

When the object is spread its getters are resolved. Instead, we should clone the entityChunk while preserving its getters (any property descriptors, really).