mswjs / data

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

Fields with type `Array` cannot be an array of object #165

Closed nvh95 closed 3 years ago

nvh95 commented 3 years ago

I have example code here: https://github.com/nvh95/msw-example/blob/d144e5c98f165c15b8758e1157fa478952307d7f/src/mocks/browser.js#L4-L29 Given I have this schema:

const db = factory({
  user: {
    id: primaryKey(Number),
    email: String,
    additional_data: Array,
  },
});

Basically, I have a field additional_data which is an Array. If I create array of primitive type like string or number, it works fine.

db.user.create({
  ...
  additional_data: [1, 2, 3 ],
});

image

But if additional_data is an array of object, @mswjs/data seems cannot process it and returns an empty array

db.user.create({
  ...
  additional_data: [
    {
      key: "hobby",
      value: "code",
    },
    {
      key: "phone",
      value: "12345",
    },
  ],
});

Screenshot 2021-11-19 at 15 50 10

I have code to reproduce this issue in https://github.com/nvh95/msw-example/blob/msw-example-2021.11.19

git clone git@github.com:nvh95/msw-example.git
git checkout msw-example-2021.11.19
npm i
npm start

@kettanaito Can you take a look? Is this an issue or I misuse additional_data: Array (I refer to #113). (definitely I don't want to use manyOf here). Thank you very much.

VanTanev commented 3 years ago

@kettanaito I want to second this, I consider this a valid use.

The change was introduced in here: https://github.com/mswjs/data/pull/143/files#diff-64401d98a99c109c65a62a9cc791a32f21dddb5d08bce553aaa559b6aa0e382dL67-L74 And: https://github.com/mswjs/data/blob/0970e7ed5a9094d6618ed6563f8bb3a00d5c9ecc/src/utils/isModelValueType.ts#L15

Previously, the check was just that we got an array, and the contents of this array did not matter, but now create() will drop any array that contains non-primitive values and replace it with an empty array.

I think this is a regression.

kettanaito commented 3 years ago

Hey, @nvh95. Thank you for reporting this.

This does look like an issue, as Data should support primitive arrays on model definitions. I'll take a look at the pull request opened by @roertbb (huge thanks πŸ™Œ ) and see if it's indeed a regression.

nvh95 commented 3 years ago

@kettanaito Thank you very much. I'm looking forward to see it fixed. In the mean time, I just want to share my work around:

  1. Change the model:
    const db = factory({
    user: {
    id: primaryKey(Number),
    email: String,
    -    additional_data: Array,
    +    additional_data: () => [
    +      {
    +        key: "hobby",
    +        value: "code",
    +      },
    +      {
    +       key: "phone",
    +        value: "12345",
    +      },
    +    ],
    +  },
    });
  2. Convert file contain the model from .ts to .js. Since TS does not allow me to define the model as above image Well, it looks not very good πŸ™ˆ but at least I feed some data for msw to respond.
VanTanev commented 3 years ago

The above workaround just gives a static value in the factory definition, you cannot create arrays with different values. Here is a workaround that allows you to create different objects:


const db = factory({
  user: {
    id: primaryKey(Number),
    email: String,
    additional_data: Array,
  },
});

const user = {
  email: "example@example.com",
  additional_data: [
    {
      key: "hobby",
      value: "code",
    },
    {
      key: "phone",
      value: "12345",
    },
  ],  
}

// TEMPORARY WORKAROUND FOR #165
Object.defineProperty(user.additional_data, 'every', { value: () => true })

db.user.create(user)