-
-
Notifications
You must be signed in to change notification settings - Fork 351
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: enhance overrideResponse assignment #1199
Conversation
@melloware Oops sorry. I didn't expect the Pull request to close when I renamed the branch on Github. |
bce4536
to
6535b03
Compare
6535b03
to
928a9c6
Compare
@DevSDK |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reviewed this PR. This PR includes several issues and feature additions that we would like to address.
I want to deeply understand how each problem occurs and how it can be improved.
Please consider creating an issue as it will help us proceed smoothly.
For example, there are some functions that can no longer be overridden, such as Below are the previous functions: export const getListPetsMock = (overrideResponse: any = {}): Pets => (Array.from({ length: faker.number.int({ min: 1, max: 10 }) }, (_, i) => i + 1).map(() => (faker.helpers.arrayElement([{breed: faker.helpers.arrayElement(['Labradoodle'] as const), cuteness: faker.number.int({min: undefined, max: undefined}), ...overrideResponse,barksPerMinute: faker.helpers.arrayElement([faker.number.int({min: undefined, max: undefined}), undefined]), type: faker.helpers.arrayElement(['dog'] as const), ...overrideResponse},{breed: faker.helpers.arrayElement(['Dachshund'] as const), length: faker.number.int({min: undefined, max: undefined}), ...overrideResponse,barksPerMinute: faker.helpers.arrayElement([faker.number.int({min: undefined, max: undefined}), undefined]), type: faker.helpers.arrayElement(['dog'] as const), ...overrideResponse,'@id': faker.helpers.arrayElement([faker.word.sample(), undefined]), callingCode: faker.helpers.arrayElement([faker.helpers.arrayElement(['+33','+420','+33'] as const), undefined]), country: faker.helpers.arrayElement([faker.helpers.arrayElement(['People\'s Republic of China','Uruguay'] as const), undefined]), email: faker.helpers.arrayElement([faker.internet.email(), undefined]), id: faker.number.int({min: undefined, max: undefined}), name: faker.word.sample(), tag: faker.helpers.arrayElement([faker.word.sample(), undefined]), ...overrideResponse},{petsRequested: faker.helpers.arrayElement([faker.number.int({min: undefined, max: undefined}), undefined]), type: faker.helpers.arrayElement(['cat'] as const), ...overrideResponse,'@id': faker.helpers.arrayElement([faker.word.sample(), undefined]), callingCode: faker.helpers.arrayElement([faker.helpers.arrayElement(['+33','+420','+33'] as const), undefined]), country: faker.helpers.arrayElement([faker.helpers.arrayElement(['People\'s Republic of China','Uruguay'] as const), undefined]), email: faker.helpers.arrayElement([faker.internet.email(), undefined]), id: faker.number.int({min: undefined, max: undefined}), name: faker.word.sample(), tag: faker.helpers.arrayElement([faker.word.sample(), undefined]), ...overrideResponse}]))))
export const getCreatePetsMock = (overrideResponse: any = {}): Pet => (faker.helpers.arrayElement([{breed: faker.helpers.arrayElement(['Labradoodle'] as const), cuteness: faker.number.int({min: undefined, max: undefined}), ...overrideResponse,barksPerMinute: faker.helpers.arrayElement([faker.number.int({min: undefined, max: undefined}), undefined]), type: faker.helpers.arrayElement(['dog'] as const), ...overrideResponse},{breed: faker.helpers.arrayElement(['Dachshund'] as const), length: faker.number.int({min: undefined, max: undefined}), ...overrideResponse,barksPerMinute: faker.helpers.arrayElement([faker.number.int({min: undefined, max: undefined}), undefined]), type: faker.helpers.arrayElement(['dog'] as const), ...overrideResponse,'@id': faker.helpers.arrayElement([faker.word.sample(), undefined]), callingCode: faker.helpers.arrayElement([faker.helpers.arrayElement(['+33','+420','+33'] as const), undefined]), country: faker.helpers.arrayElement([faker.helpers.arrayElement(['People\'s Republic of China','Uruguay'] as const), undefined]), email: faker.helpers.arrayElement([faker.internet.email(), undefined]), id: faker.number.int({min: undefined, max: undefined}), name: faker.word.sample(), tag: faker.helpers.arrayElement([faker.word.sample(), undefined]), ...overrideResponse},{petsRequested: faker.helpers.arrayElement([faker.number.int({min: undefined, max: undefined}), undefined]), type: faker.helpers.arrayElement(['cat'] as const), ...overrideResponse,'@id': faker.helpers.arrayElement([faker.word.sample(), undefined]), callingCode: faker.helpers.arrayElement([faker.helpers.arrayElement(['+33','+420','+33'] as const), undefined]), country: faker.helpers.arrayElement([faker.helpers.arrayElement(['People\'s Republic of China','Uruguay'] as const), undefined]), email: faker.helpers.arrayElement([faker.internet.email(), undefined]), id: faker.number.int({min: undefined, max: undefined}), name: faker.word.sample(), tag: faker.helpers.arrayElement([faker.word.sample(), undefined]), ...overrideResponse}]))
export const getShowPetByIdMock = (overrideResponse: any = {}): Pet => (faker.helpers.arrayElement([{breed: faker.helpers.arrayElement(['Labradoodle'] as const), cuteness: faker.number.int({min: undefined, max: undefined}), ...overrideResponse,barksPerMinute: faker.helpers.arrayElement([faker.number.int({min: undefined, max: undefined}), undefined]), type: faker.helpers.arrayElement(['dog'] as const), ...overrideResponse},{breed: faker.helpers.arrayElement(['Dachshund'] as const), length: faker.number.int({min: undefined, max: undefined}), ...overrideResponse,barksPerMinute: faker.helpers.arrayElement([faker.number.int({min: undefined, max: undefined}), undefined]), type: faker.helpers.arrayElement(['dog'] as const), ...overrideResponse,'@id': faker.helpers.arrayElement([faker.word.sample(), undefined]), callingCode: faker.helpers.arrayElement([faker.helpers.arrayElement(['+33','+420','+33'] as const), undefined]), country: faker.helpers.arrayElement([faker.helpers.arrayElement(['People\'s Republic of China','Uruguay'] as const), undefined]), email: faker.helpers.arrayElement([faker.internet.email(), undefined]), id: faker.number.int({min: undefined, max: undefined}), name: faker.word.sample(), tag: faker.helpers.arrayElement([faker.word.sample(), undefined]), ...overrideResponse},{petsRequested: faker.helpers.arrayElement([faker.number.int({min: undefined, max: undefined}), undefined]), type: faker.helpers.arrayElement(['cat'] as const), ...overrideResponse,'@id': faker.helpers.arrayElement([faker.word.sample(), undefined]), callingCode: faker.helpers.arrayElement([faker.helpers.arrayElement(['+33','+420','+33'] as const), undefined]), country: faker.helpers.arrayElement([faker.helpers.arrayElement(['People\'s Republic of China','Uruguay'] as const), undefined]), email: faker.helpers.arrayElement([faker.internet.email(), undefined]), id: faker.number.int({min: undefined, max: undefined}), name: faker.word.sample(), tag: faker.helpers.arrayElement([faker.word.sample(), undefined]), ...overrideResponse}])) |
I am not sure that it’s a good idea to force the user to install lodash merge no? |
I agree I am not a fan of forced dependencies. |
I don't want to increase the number of dependent libraries if possible. It is convenient because there are no dependent libraries, and |
Make sense. I respect that. We can choose the alternative ways: Implement recursive assignments like lodash.merge, and then
Which way would you like prefer to approach? Let me know prefer way and it would be great to advise me on some consideration points of each way if you don't mind. |
Related: #1199 (comment) Yes. It has become unable to override. Thanks for letting me know :). Because it will be decided by whether the 'overrideResponse' string exists or not in value. It happened by removing '...overrideResponse' string from the value string by removing the push statement in the object.js. The simplest way to resolve this is adding I assume a bit complex way will be to return overridable information from How about a simplest way? Or can you suggest fixing this case? |
@DevSDK |
Regarding the override variable being lost, if it was implemented correctly without adding comments, the current string match judgment would work fine. And, alternative implementations of |
The overridable information is only checked by string match. I understand that there are some blocking tasks related to separate issues that need to be addressed first. I'm happy to wait until those are completed before diving into this further. And sure, the alternative way requires the maintainer's review :). |
Looks like merge conflicts? |
I don't think merging arrays is an obvious, easy to grasp option array should be overwritten with new array |
@soartec-lab oh wow. That change is huge. Sorry for the late response. I was unwell though by cold... For now, I haven't caught the context yet so please understand if I say weird below. (If it is, please ignore blow :)) We should handle nested. use case of our product was (a bit overstated)
If only the root is overridable with Partial, we should make whole Object A and B. In our company, we created a fixture creator to resolve the same problem with that nested interface. function createAwesomeThingFixtures(props: DeepPartial<Type>) {
...
}
const fixture = createAwesomeThingFixtures(
[
{
id: '1',
type,
roleReference: {
name: "Seokho"
// There are more than 20 properties in here!
// but I want to test only "name"
}
// and here, also have more properties
},
{
id: '2',
type,
roleReference: {
name: "Ph"
// There are more than 20 properties in here!
// but I want to test only "name"
}
},
]
) What if we write the whole 20 properties in there, I think there can be significant developer experience damage and it will be hard to change I'll check and participate in it but now I'm a bit busy.. So... I may slow. |
@DevSDK Do you have an opinion on that? |
Yeah. I think #1338 will cause a breaking change because the exposed function argument type changed: But after that, So.. I agree that we can move on gradually. I'll pull that change and make supporting |
Thank you for confirming. |
Hey @DevSDK , it's been a while since this PR was opened. Mocks are still being improved, so conflicts still occur. If there is an issue, it would be a good idea to open the PR again, and once the policy is organized in an issue, I think someone else can continue to deal with it. and if you would like to come back to development, I would always welcome you back. |
Yep. If you prefer so. Actually, I resolved the conflict on the local repo. (It was not as much as I thought) So we can decide to push the merge commit with resolving the conflicts and continue gradually or simply close this PR and reopen when I'm ready. However, I might be slow due to the other things to do... So If we decide to close this PR, yeah, I'll do it again someday ;) |
Thank you for contacting me. I have determined that the issue and approach have changed from the original purpose of creating this PR, so if it is possible to continue, could you please open the PR again? |
@soartec-lab Yep :) I'll do it soon. Feel free to close this |
Status
READY
Description
1. Apply loadsh/merge
According to the ECMAScript specification [1], The spread syntax does not guarantee deep assignment.
Because the properties will overwrite per each key by CreateDataProperty.
(Also Object.assign [2] - [[Set]] in this case operation.)
For example:
The
result
will be:The user expectation that presents given properties is only valid on 1depth of the result.
Therefore, apply
loadsh/merge
[3] to assign property recursively.2. Deterministic array length by overrideResponse
The overrideResponse can contain an array property. Currently, the override target generates a random length of it.
The length of the generated array can be shorter than the length in overrideResponse.
That possibly leads to unexpected overriding behavior.
For example:
Hence, get length information from the array of the given overrideResponse to ensure the length of the generated array is greater than the given parameter.
The result will be looks like:
[1] https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-runtime-semantics-propertydefinitionevaluation
[2] https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-object.assign
FYR: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#spread_in_object_literals
[3] https://lodash.com/docs/4.17.15#merge
Related PRs
List related PRs against other branches:
Todos
Steps to Test or Reproduce
Outline the steps to test or reproduce the PR here.