Skip to content

Instantly share code, notes, and snippets.

@jmporchet
Last active April 4, 2019 13:50
Show Gist options
  • Save jmporchet/e77ca1d84eba9f39f479b8645b5d4b1d to your computer and use it in GitHub Desktop.
Save jmporchet/e77ca1d84eba9f39f479b8645b5d4b1d to your computer and use it in GitHub Desktop.
Spread operator vs lodash's cloneDeep()
// This is an illustration of when NOT to use the spread operator to copy variables.
// Check https://codesandbox.io/s/6w749171mz for a working copy of the code
import { cloneDeep } from "lodash";
import {
getDrinkNutrientsFromResult,
mapRecipesToNutrients
} from "../nutrition";
describe("helper methods", () => {
const recipes = [
{
id: 1,
state: "ready",
createdAt: "2019-03-19T01:01:01.000Z",
nutrients: [
{ key: "chromium", value: 1116.47 },
{ key: "biotin", value: 0.01 }
]
},
{
id: 2,
state: "in_progress",
createdAt: "2019-03-19T01:01:01.000Z",
nutrients: [
{ key: "chromium", value: 1116.47 },
{ key: "biotin", value: 0.01 }
]
}
];
const expectedData = [
{ key: "biotin", unit: "mg", value: 0.01 },
{ key: "chromium", unit: "mg", value: 1116.47 }
// ...
];
const nutrientNames = [
"biotin",
"chromium"
// ...
];
let recipesList, expected;
beforeEach(() => {
// cloneDeep will copy all the elements by value recursively, instead of passing them by reference
//
recipesList = cloneDeep(recipes);
expected = cloneDeep(expectedData);
// The tests would break, because even though recipesList is a new variable
// teh rest operator will copy all the elements by REFERENCE
//
// recipesList = [...recipes];
});
it("should get the nutrients from a recipe", () => {
// mutates the element
recipesList.find(recipe => recipe.state === "in_progress").createdAt =
"2019-03-20T22:13:13.889Z";
expect(getDrinkNutrientsFromResult(recipesList)).toEqual(expected);
});
it("should behave gracefully when an expected element is not in the recipe", () => {
// mutates the elements
recipesList.find(r => r.id === 1).nutrients[0] = null;
expected.find(n => n.key === "chromium").value = 0;
expect(getDrinkNutrientsFromResult(recipesList)).toEqual(expected);
});
// putting this test last will make it fail if using the spread operator
// because chromium's value has been modified to 0 from line 67.
// cloneDeep() clones the elements too, this way the problem doesn't happen anymore
//
it("should map recipes to nutrients correctly", () => {
expect(mapRecipesToNutrients(recipesList, nutrientNames)).toEqual(expected);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment