Object properties are merged instead overriden
Opened this issue · 3 comments
Description
Object properties are merged instead overriden.
To Reproduce
https://codesandbox.io/s/fishery-test-forked-h29nq6?file=/src/index.test.ts
Thank you for sharing this issue. I'm going to share the code from your sandbox inline below to keep the discussion in one place:
import { Factory } from "fishery";
test("Sample test", () => {
type User = {
names: Record<string, string>;
};
const userFactory = Factory.define<User>(() => ({
names: { last: "Susan" }
}));
expect(
userFactory.build({ names: { first: "Maria" } })
).toEqual({ names: { first: "Maria" } }); // error, names also includes `last: "Susan"`
});
When you call build
, the params supplied are deeply merged with the result provided from your factory function. The deep merge behavior is very useful for some common scenarios, but there are some times when it is undesired. For these cases, you can rely on associations
(readme) or transientParams
(readme).
Here is a Code Sandbox with passing tests for both approaches. In this case, I'd recommend associations
, since this is what that feature was built to address.
Just trying to use this library for the first time, and this is one area of annoyance for me as well. I expected that a factory will return the final object, but the fact that any extra params passed in, will also be in the object, is causing somewhat of a pain. I'm not sure what the intended use-cases are for this behavior, but it would be nice to at least have an option allowing me to opt-out of this behavior, and assume that my factory function knows how to create a complete object.
Maybe this could be solved with sub types. Something like this:
const userFactory = Factory.define<User>(({preventMerging}) => ({
names: preventMerging({ last: "Susan" })
}));
function mergeObjects(a, b) {
if (b instanceof PreventMerging) {
return b.attributes
}
if (a instanceof PreventMerging) {
return b === undefined ? a.attributes : b
}
// original code to merge objects
}
(This is a proposal, not something that is implemented!)