# Feature B — Shopping Cart ## Your goal Implement `ShoppingCart` using strict TDD. **Do not write any production code before you have a failing test.** ## Domain rules to implement (in order) | Step | Feature | Notes | |------|---------|-------| | 1 | Empty cart has subtotal 0 and count 0 | The baseline | | 2 | Add items — subtotal = price × quantity | Multiple items accumulate | | 3 | Remove item by name | Removing unknown name does nothing | | 4 | Apply % discount to subtotal | 10% off $50 → $45 | | 5 | CartItem rejects zero/negative price & quantity | Value Object validation | | 6 | Bonus: duplicate name / float precision | Design decision — your call | ## The rhythm — repeat for every rule ``` 1. Uncomment the next test → run → watch it FAIL (Red) 2. Write the minimum code to make it pass → run → GREEN 3. Refactor if needed → run → still GREEN 4. Move to the next test ``` ## Running the tests ```bash dart pub get dart test ``` ## Files - `lib/shopping_cart.dart` — your implementation goes here - `test/shopping_cart_test.dart` — uncomment tests one at a time ## Design hints (don't peek until you're stuck!)
Hint for Step 3 — Remove by name When you need to remove by name, a `List` forces you to search by name. A `Map` makes lookup O(1) and removal trivial. Let the test drive you toward the right data structure.
Hint for Step 5 — Value Object Validation belongs in `CartItem`'s constructor, not in `ShoppingCart.addItem()`. If the item can't be created, the cart never sees it. This is the Value Object pattern: invalid state is unrepresentable.
Hint for the float precision bonus test Use `closeTo(expected, delta)` instead of `equals()` for floating point comparisons. Example: `expect(result, closeTo(0.30, 0.001))`