mswjs / data

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

Cannot update relation if not initially defined #137

Closed tinleym closed 3 years ago

tinleym commented 3 years ago

Using 0.6.0, I've encountered some unexpected behavior when updating a relation.

Using the following factory...

const db = factory({
  user: {
    id: primaryKey(String),
    registeredUser: oneOf("registeredUser"),
  },
  registeredUser: {
    id: primaryKey(String),
  },
});

If I initialize and then update a relation...

const user = db.user.create({
  id: "a",
  registeredUser: db.registeredUser.create({ id: "b" }),
});

db.user.update({
  where: { id: { equals: "a" } },
  data: {
    registeredUser: db.registeredUser.create({
      id: "c",
    }),
  },
});

The update goes through as expected.

However, if I try to update a relation that hasn't been initialized...

const user = db.user.create({
  id: "a",
});

db.user.update({
  where: { id: { equals: "a" } },
  data: {
    registeredUser: db.registeredUser.create({
      id: "c",
    }),
  },
});

I get

TypeError: Cannot read property 'modelName' of null

      71 |             if (propertyDefinition instanceof Relation_1.Relation) {
      72 |                 log('property "%s" is a "%s" relation to "%s"!', propertyName, propertyDefinition.kind, propertyDefinition.target.modelName);
    > 73 |                 outvariant_1.invariant(isObject_1.isObject(value) || Array.isArray(value), 'Failed to update relational property "%s" on "%s": the next value must be an entity or a list of entities.', propertyName, propertyDefinition.source.modelName);
         |                                                                                                                                                                                                                                                  ^
      74 |                 log('updating the relation to resolve with:', value);
      75 |                 // Re-define the relational property to now point at the next value.
      76 |                 propertyDefinition.resolveWith(nextEntity, value);

      at lib/model/updateEntity.js:73:242
          at Array.reduce (<anonymous>)
      at updateRecursively (lib/model/updateEntity.js:51:43)
      at Object.updateEntity (lib/model/updateEntity.js:92:18)
      at Object.update (lib/factory.js:110:45)
      at Object.<anonymous> (test/relations/one-to-one.test.ts:343:37)

That traces to @mswjs/data/lib/model/updateEntity.js:71:242

kettanaito commented 3 years ago

Hey, @tinleym. Thank you for reporting this!

I've fixed the root cause and updated the tests to catch any regressions on this. See #138.

tinleym commented 3 years ago

Thank you!!