store: cover cart.ts with tests, drop unused Tailwind, fix stale copy #49

Closed
opened 2026-08-27 06:35:53 +00:00 by yuris · 0 comments
Owner

Three unrelated small things, batched because each is a few lines and none deserves its own issue.

1. lib/cart.ts has no test

It is the only module in apps/store/lib without one, and it is the riskiest: it owns money-adjacent state, treats localStorage as a trust boundary via isLine(), keeps a module-level store with a listener Set, and syncs across tabs on StorageEvent. #41 and #47 both change the cart line shape, so the coverage should exist before they land, not after.

Worth asserting: a malformed stored value yields an empty cart rather than throwing; add of an existing slug increments instead of duplicating; setQty(0) removes the line; total excludes null-price lines and hasUnpricedLine reports them; listeners fire on mutation. The hook needs no DOM — export the store functions and test those, keeping useCart as the thin wrapper.

2. Tailwind is installed but never used

tailwindcss v4 and @tailwindcss/postcss are in apps/store devDependencies and wired in postcss.config.mjs, but globals.css has no @import "tailwindcss" and no component uses a utility class. All styling is the plain-CSS token system from #33. Delete both dependencies and the postcss wiring — it is install weight and a misleading signal to the next reader about how this app is styled. (apps/management genuinely uses Tailwind; leave it alone.)

3. Pre-cart copy on the products page

app/products/page.tsx metadata and lead still say "tanya stok dan harga lewat WhatsApp". Prices and a cart shipped in #39 — the copy predates them and now undersells the page. Reword to match the shipped behaviour.

Acceptance

pnpm --filter garage-store test covers the cart cases above and passes. pnpm install no longer pulls Tailwind for the store, and pnpm --filter garage-store build produces a visually identical site (the postcss pipeline was a no-op). No page still tells visitors to ask for prices they can see.

Three unrelated small things, batched because each is a few lines and none deserves its own issue. ### 1. `lib/cart.ts` has no test It is the only module in `apps/store/lib` without one, and it is the riskiest: it owns money-adjacent state, treats `localStorage` as a trust boundary via `isLine()`, keeps a module-level store with a listener `Set`, and syncs across tabs on `StorageEvent`. #41 and #47 both change the cart line shape, so the coverage should exist before they land, not after. Worth asserting: a malformed stored value yields an empty cart rather than throwing; `add` of an existing slug increments instead of duplicating; `setQty(0)` removes the line; `total` excludes null-price lines and `hasUnpricedLine` reports them; listeners fire on mutation. The hook needs no DOM — export the store functions and test those, keeping `useCart` as the thin wrapper. ### 2. Tailwind is installed but never used `tailwindcss` v4 and `@tailwindcss/postcss` are in `apps/store` devDependencies and wired in `postcss.config.mjs`, but `globals.css` has no `@import "tailwindcss"` and no component uses a utility class. All styling is the plain-CSS token system from #33. Delete both dependencies and the postcss wiring — it is install weight and a misleading signal to the next reader about how this app is styled. (`apps/management` genuinely uses Tailwind; leave it alone.) ### 3. Pre-cart copy on the products page `app/products/page.tsx` metadata and lead still say *"tanya stok dan harga lewat WhatsApp"*. Prices and a cart shipped in #39 — the copy predates them and now undersells the page. Reword to match the shipped behaviour. ### Acceptance `pnpm --filter garage-store test` covers the cart cases above and passes. `pnpm install` no longer pulls Tailwind for the store, and `pnpm --filter garage-store build` produces a visually identical site (the postcss pipeline was a no-op). No page still tells visitors to ask for prices they can see.
yuris closed this issue 2026-08-27 09:01:18 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
yuris/garage#49
No description provided.