Skip to content

Commit 7dbdcd1

Browse files
authored
fix: trigger onItemUpdate (#39)
* fix: trigger onItemUPdate when item updated * test: add more test coverage * chore: set default array for items arg
1 parent 0392b39 commit 7dbdcd1

File tree

3 files changed

+170
-8
lines changed

3 files changed

+170
-8
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"scripts": {
2222
"build": "rollup -c",
2323
"start": "rollup -c -w",
24-
"test": "jest"
24+
"test": "jest",
25+
"test:watch": "jest --watch"
2526
},
2627
"devDependencies": {
2728
"@babel/core": "7.10.2",

src/index.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,12 @@ function reducer(state, action) {
5757
}
5858
}
5959

60-
const generateCartState = (state, items) => {
60+
const generateCartState = (state = initialState, items = []) => {
6161
const totalUniqueItems = calculateUniqueItems(items);
6262
const isEmpty = totalUniqueItems === 0;
6363

6464
return {
65+
...initialState,
6566
...state,
6667
items: calculateItemTotals(items),
6768
totalItems: calculateTotalItems(items),
@@ -71,19 +72,19 @@ const generateCartState = (state, items) => {
7172
};
7273
};
7374

74-
const calculateItemTotals = (items) =>
75+
const calculateItemTotals = (items = []) =>
7576
items.map((item) => ({
7677
itemTotal: item.price * item.quantity,
7778
...item,
7879
}));
7980

80-
const calculateCartTotal = (items) =>
81+
const calculateCartTotal = (items = []) =>
8182
items.reduce((total, item) => total + item.quantity * item.price, 0);
8283

83-
const calculateTotalItems = (items) =>
84+
const calculateTotalItems = (items = []) =>
8485
items.reduce((sum, item) => sum + item.quantity, 0);
8586

86-
const calculateUniqueItems = (items) => items.length;
87+
const calculateUniqueItems = (items = []) => items.length;
8788

8889
export function CartProvider({
8990
children,
@@ -116,7 +117,7 @@ export function CartProvider({
116117
const setItems = (items) => {
117118
dispatch({
118119
type: SET_ITEMS,
119-
payload,
120+
payload: items,
120121
});
121122

122123
onSetItems && onSetItems(items);
@@ -148,8 +149,10 @@ export function CartProvider({
148149
onItemUpdate && onItemUpdate(payload);
149150
};
150151

151-
const updateItem = (id, payload) =>
152+
const updateItem = (id, payload) => {
152153
dispatch({ type: UPDATE_ITEM, id, payload });
154+
onItemUpdate && onItemUpdate(payload);
155+
};
153156

154157
const updateItemQuantity = (id, quantity) => {
155158
if (quantity <= 0) {

src/index.test.js

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { renderHook, act } from "@testing-library/react-hooks";
33

44
import { CartProvider, useCart, initialState } from "./";
55

6+
afterEach(() => window.localStorage.clear());
7+
68
describe("CartProvider", () => {
79
test("initial cart meta state is set", () => {
810
const wrapper = ({ children }) => (
@@ -43,6 +45,54 @@ describe("addItem", () => {
4345
expect(result.current.totalUniqueItems).toBe(1);
4446
expect(result.current.isEmpty).toBe(false);
4547
});
48+
49+
test("triggers onItemAdd when cart empty", () => {
50+
let called = false;
51+
52+
const wrapper = ({ children }) => (
53+
<CartProvider id="test" onItemAdd={() => (called = true)}>
54+
{children}
55+
</CartProvider>
56+
);
57+
58+
const { result } = renderHook(() => useCart(), {
59+
wrapper,
60+
});
61+
62+
const item = { id: "test", price: 1000 };
63+
64+
act(() => {
65+
result.current.addItem(item);
66+
});
67+
68+
expect(called).toBe(true);
69+
});
70+
71+
test("triggers onItemUpdate when cart has existing item", () => {
72+
let called = false;
73+
74+
const item = { id: "test", price: 1000 };
75+
76+
const wrapper = ({ children }) => (
77+
<CartProvider
78+
id="test"
79+
defaultItems={[item]}
80+
onItemUpdate={() => (called = true)}
81+
>
82+
{children}
83+
</CartProvider>
84+
);
85+
86+
const { result } = renderHook(() => useCart(), {
87+
wrapper,
88+
});
89+
90+
act(() => {
91+
result.current.updateItem(item);
92+
});
93+
94+
expect(called).toBe(true);
95+
});
4696
});
4797

4898
describe("updateItem", () => {
@@ -69,6 +119,33 @@ describe("updateItem", () => {
69119
expect(result.current.items).toHaveLength(1);
70120
expect(result.current.totalItems).toBe(2);
71121
expect(result.current.totalUniqueItems).toBe(1);
122+
expect(result.current.isEmpty).toBe(false);
123+
});
124+
125+
test("triggers onItemUpdate when updating existing item", () => {
126+
let called = false;
127+
128+
const item = { id: "test", price: 1000 };
129+
130+
const wrapper = ({ children }) => (
131+
<CartProvider
132+
id="test"
133+
defaultItems={[item]}
134+
onItemUpdate={() => (called = true)}
135+
>
136+
{children}
137+
</CartProvider>
138+
);
139+
140+
const { result } = renderHook(() => useCart(), {
141+
wrapper,
142+
});
143+
144+
act(() => {
145+
result.current.addItem(item);
146+
});
147+
148+
expect(called).toBe(true);
72149
});
73150
});
74151

@@ -94,6 +171,59 @@ describe("updateItemQuantity", () => {
94171
expect(result.current.items).toHaveLength(1);
95172
expect(result.current.totalItems).toBe(3);
96173
expect(result.current.totalUniqueItems).toBe(1);
174+
expect(result.current.isEmpty).toBe(false);
175+
});
176+
177+
test("triggers onItemUpdate when setting quantity above 0", () => {
178+
let called = false;
179+
180+
const item = { id: "test", price: 1000 };
181+
182+
const wrapper = ({ children }) => (
183+
<CartProvider
184+
id="test"
185+
defaultItems={[item]}
186+
onItemUpdate={() => (called = true)}
187+
>
188+
{children}
189+
</CartProvider>
190+
);
191+
192+
const { result } = renderHook(() => useCart(), {
193+
wrapper,
194+
});
195+
196+
act(() => {
197+
result.current.updateItemQuantity(item.id, 2);
198+
});
199+
200+
expect(called).toBe(true);
201+
});
202+
203+
test("triggers onItemRemove when setting quantity to 0", () => {
204+
let called = false;
205+
206+
const item = { id: "test", price: 1000 };
207+
208+
const wrapper = ({ children }) => (
209+
<CartProvider
210+
id="test"
211+
defaultItems={[item]}
212+
onItemRemove={() => (called = true)}
213+
>
214+
{children}
215+
</CartProvider>
216+
);
217+
218+
const { result } = renderHook(() => useCart(), {
219+
wrapper,
220+
});
221+
222+
act(() => {
223+
result.current.updateItemQuantity(item.id, 0);
224+
});
225+
226+
expect(called).toBe(true);
97227
});
98228
});
99229

@@ -119,6 +249,33 @@ describe("removeItem", () => {
119249
expect(result.current.items).toEqual([]);
120250
expect(result.current.totalItems).toBe(0);
121251
expect(result.current.totalUniqueItems).toBe(0);
252+
expect(result.current.isEmpty).toBe(true);
253+
});
254+
255+
test("triggers onItemRemove when removing item", () => {
256+
let called = false;
257+
258+
const item = { id: "test", price: 1000 };
259+
260+
const wrapper = ({ children }) => (
261+
<CartProvider
262+
id="test"
263+
defaultItems={[item]}
264+
onItemRemove={() => (called = true)}
265+
>
266+
{children}
267+
</CartProvider>
268+
);
269+
270+
const { result } = renderHook(() => useCart(), {
271+
wrapper,
272+
});
273+
274+
act(() => {
275+
result.current.updateItemQuantity(item.id, 0);
276+
});
277+
278+
expect(called).toBe(true);
122279
});
123280
});
124281

@@ -143,5 +300,6 @@ describe("emptyCart", () => {
143300
expect(result.current.items).toEqual([]);
144301
expect(result.current.totalItems).toBe(0);
145302
expect(result.current.totalUniqueItems).toBe(0);
303+
expect(result.current.isEmpty).toBe(true);
146304
});
147305
});

0 commit comments

Comments
 (0)