Skip to content

Commit e0329f8

Browse files
authored
fix: setItems type fixed in CartProviderState (#84)
* chore: package.lock is updated * code: added setItems type to CartProviderState * Added test for setItems * test: removed .only from setItems tests to run all tests * fix: updated setItems by the doc requirements * test: updated setItems test for mock items to not have quantity * test: added expectation to ensure quantity is implicitly added * test: added test to ensure setItems does not ignore quantity input * test: added test to ensure onSetItems is triggered * test: Updated description for onSetItems trigger test * test: ensure that setItems replaces the current items * docs: setItems implicit quantity * test: fixed false positive for replacing current items with new items * refactor: setItems, mapping items
1 parent 70ae607 commit e0329f8

File tree

4 files changed

+84
-7
lines changed

4 files changed

+84
-7
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,14 +166,14 @@ ReactDOM.render(
166166
| `onItemRemove` | _No_ | Triggered on items removed from your cart. |
167167
| `storage` | _No_ | Must return `[getter, setter]`. |
168168
| `metadata` | _No_ | Custom global state on the cart. Stored inside of `metadata`. |
169-
170169
## `useCart`
171170

172171
The `useCart` hook exposes all the getter/setters for your cart state.
173172

174173
### `setItems(items)`
175174

176-
The `setItems` method should be used to set all items in the cart. This will overwrite any existing cart items.
175+
The `setItems` method should be used to set all items in the cart. This will overwrite any existing cart items. A `quantity` default of 1 will be set for an item implicitly if no `quantity` is specified.
176+
177177

178178
#### Args
179179

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ interface CartProviderState extends InitialState {
2828
addItem: (item: Item, quantity?: number) => void;
2929
removeItem: (id: Item["id"]) => void;
3030
updateItem: (id: Item["id"], payload: object) => void;
31+
setItems: (items: Item[]) => void;
3132
updateItemQuantity: (id: Item["id"], quantity: number) => void;
3233
emptyCart: () => void;
3334
getItem: (id: Item["id"]) => any | undefined;
@@ -191,7 +192,10 @@ export const CartProvider: React.FC<{
191192
const setItems = (items: Item[]) => {
192193
dispatch({
193194
type: "SET_ITEMS",
194-
payload: items,
195+
payload: items.map(item => ({
196+
...item,
197+
quantity: item.quantity || 1
198+
})),
195199
});
196200

197201
onSetItems && onSetItems(items);

test/index.test.tsx

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,3 +450,76 @@ describe("updateCartMetadata", () => {
450450
});
451451
});
452452
});
453+
describe("setItems", () => {
454+
test("set cart items state", () => {
455+
const items = [{ id: "test", price: 1000 }, { id: "test2", price: 2000 }];
456+
457+
const wrapper: FC<Props> = ({ children }) => (
458+
<CartProvider defaultItems={[]}>{children}</CartProvider>
459+
);
460+
const { result } = renderHook(() => useCart(), {
461+
wrapper,
462+
});
463+
464+
act(() =>
465+
result.current.setItems(items)
466+
);
467+
expect(result.current.items).toHaveLength(2);
468+
expect(result.current.totalItems).toBe(2);
469+
expect(result.current.totalUniqueItems).toBe(2);
470+
expect(result.current.isEmpty).toBe(false);
471+
expect(result.current.items).toContainEqual(
472+
expect.objectContaining({ id: "test2", price: 2000, quantity: 1 })
473+
);
474+
})
475+
test("add custom quantities with setItems", () => {
476+
const items = [{ id: "test", price: 1000, quantity: 2 }, { id: "test2", price: 2000, quantity: 1 }];
477+
const wrapper: FC<Props> = ({ children }) => (
478+
<CartProvider defaultItems={[]}>{children}</CartProvider>
479+
);
480+
const { result } = renderHook(() => useCart(), {
481+
wrapper,
482+
});
483+
484+
act(() =>
485+
result.current.setItems(items)
486+
);
487+
expect(result.current.items).toHaveLength(2);
488+
expect(result.current.totalItems).toBe(3);
489+
expect(result.current.totalUniqueItems).toBe(2);
490+
})
491+
test("current items is replaced when setItems has been called with a new set of items", () => {
492+
const itemToBeReplaced = { id: "test", price: 1000 };
493+
const wrapper: FC<Props> = ({ children }) => (
494+
<CartProvider defaultItems={[itemToBeReplaced]}>{children}</CartProvider>
495+
);
496+
const { result } = renderHook(() => useCart(), {
497+
wrapper,
498+
});
499+
const items = [{ id: "test2", price: 2000}, { id: "test3", price: 3000}];
500+
act(() =>
501+
result.current.setItems(items)
502+
);
503+
expect(result.current.items).toHaveLength(2);
504+
expect(result.current.items).not.toContainEqual(
505+
expect.objectContaining(itemToBeReplaced)
506+
);
507+
})
508+
test("trigger onSetItems when setItems is called", () => {
509+
let called = false;
510+
511+
const wrapper: FC<Props> = ({ children }) => (
512+
<CartProvider onSetItems={() => (called = true)}>{children}</CartProvider>
513+
);
514+
515+
const { result } = renderHook(() => useCart(), {
516+
wrapper,
517+
});
518+
519+
const items = [{ id: "test", price: 1000 }];
520+
521+
act(() => result.current.setItems(items));
522+
523+
expect(called).toBe(true);
524+
})
525+
})

0 commit comments

Comments
 (0)