feat(checkout): lock shipment options the cart already decided on - #480
feat(checkout): lock shipment options the cart already decided on#480FreekVR wants to merge 3 commits into
Conversation
✅ Deploy Preview for myparcel-delivery-options ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Bundle ReportChanges will increase total bundle size by 4.13kB (1.41%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: @myparcel-dev/delivery-options-MyParcelDeliveryOptionsLib-esmAssets Changed:
Files in
view changes for bundle: @myparcel-dev/delivery-options-MyParcelDeliveryOptionsLib-umdAssets Changed:
Files in
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #480 +/- ##
==========================================
- Coverage 70.25% 70.16% -0.09%
==========================================
Files 262 263 +1
Lines 2938 2970 +32
Branches 437 445 +8
==========================================
+ Hits 2064 2084 +20
Misses 539 539
- Partials 335 347 +12 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR extends the delivery-options widget input to accept cart-calculated shipment options (per carrier) and uses that data to enforce capability requires/excludes so that cart-decided options are reflected as checked/unchecked and locked in the UI. It centralizes shipment option rendering/locking/defaulting logic into a single composable to ensure consistent state across the selector and option list.
Changes:
- Add
cartShipmentOptionsto the configuration types and configuration pipeline, including sanitization/normalization and a dedicated store. - Introduce
useShipmentOptionsState(with a pureresolveShipmentOptionsState) as the single source of truth for shipment option visibility, defaults, and forced on/off state; removeuseShipmentOptionRules. - Expand shared capability→shipment-option mapping utilities to support plugin cart option name translation (camelCase) back to capability keys, and adjust tests/mocks accordingly.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| libs/shared/src/utils/capabilitiesMapping.ts | Adds a single source-of-truth shipment-option map and introduces mapCartShipmentOptionToCapability() for plugin cart option name translation. |
| libs/shared/src/types/config.types.ts | Introduces CartShipmentOptions type and wires optional cartShipmentOptions into config input/output types. |
| libs/shared/src/data/config.ts | Adds KEY_CART_SHIPMENT_OPTIONS for consistent configuration key access. |
| libs/shared/src/tests/mocks/mockCapabilitiesResponse.ts | Exports DEFAULT_OPTION and extends mock capabilities with age-check rules for new behavior coverage. |
| apps/delivery-options/src/views/MyParcelDeliveryOptions/Delivery/ShipmentOptionsSelector/ShipmentOptionsSelector.vue | Switches enforcement/defaulting logic to useShipmentOptionsState. |
| apps/delivery-options/src/stores/useCartShipmentOptionsStore.ts | New store to hold per-carrier cart shipment options while preserving reactive identity across updates. |
| apps/delivery-options/src/stores/index.ts | Exposes the new cart shipment options store from the stores barrel. |
| apps/delivery-options/src/config/validateConfiguration.ts | Sanitizes cartShipmentOptions input (type-safety, carrier normalization, boolean filtering, __proto__ hardening). |
| apps/delivery-options/src/config/validateConfiguration.spec.ts | Adds unit tests for cartShipmentOptions validation/sanitization behavior. |
| apps/delivery-options/src/config/setConfiguration.ts | Applies validated cartShipmentOptions into the new store on configuration set. |
| apps/delivery-options/src/composables/useShipmentOptionsState.ts | New single-owner module implementing forced/default/rendering state resolution, including cart-derived forcing. |
| apps/delivery-options/src/composables/useShipmentOptionsState.spec.ts | Adds tests for cart-driven forcing plus existing requires/excludes/default behaviors. |
| apps/delivery-options/src/composables/useShipmentOptionsOptions.ts | Refactors option list building to consume optionStates from useShipmentOptionsState and only add label/price. |
| apps/delivery-options/src/composables/useShipmentOptionsOptions.spec.ts | Adds test ensuring disallowed options never render even when forced by cart rules. |
| apps/delivery-options/src/composables/useShipmentOptionRules.ts | Removes the old rules composable now superseded by useShipmentOptionsState. |
| apps/delivery-options/src/composables/index.ts | Updates exports to remove useShipmentOptionRules and export useShipmentOptionsState. |
| apps/delivery-options/src/tests/utils/mockDeliveryOptionsConfig.ts | Ensures cart shipment options store is updated/reset during test config mocking. |
| apps/delivery-options/src/snapshots/index.spec.ts.snap | Updates public export snapshot to include new exports and remove deleted composable. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
5897d82 to
da6b3f5
Compare
fd414d7 to
ea5fb50
Compare
The plugin can now pass the cart's calculated shipment options to the widget through a new optional top-level `cartShipmentOptions` key (per carrier, camelCase option name → boolean), next to `initial` and `address`. When an option the consumer cannot choose (like age check) is active on the cart, the widget looks up its capability rules and shows every option it requires as checked and locked, and every option it excludes as unchecked and locked. One module (`useShipmentOptionsState`) now decides all shipment option state — what renders, what is forced on or off, defaults and prices; the option list and the selector only read from it. Rules are evaluated on the capabilities key-space, so options without a consumer UI (like age check) can force the ones that do have one. The shop's allow* settings keep deciding what the consumer sees: an option that is not allowed never renders, forced or not; the plugin still enforces it at export. Without `cartShipmentOptions` the widget behaves exactly as before. Resolves INT-1596 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…place
Cart shipment options arrive under the plugin's names ('ageCheck') while the
widget works with its own ('age_check'), which meant a second lookup table and
a third vocabulary inside the option rules. The names are now translated where
the rest of the configuration is cleaned up, so everything past that point
speaks one language, and the one reverse lookup covers every shipment option
instead of only the ones a consumer can select.
Resolves INT-1596
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… inputs Which options are forced, which start out checked, which are shown and which count as selected are now four separate calculations, each over only the data it needs. The selection follows from them instead of being written into the consumer's choices, so an option the chosen carrier no longer offers disappears by itself and options that were only checked because a rule forced them do not linger after switching carriers. This also fixes unchecking two options in a row: because everything was calculated together, the starting state looked new on every click, and emptying the selection made the widget apply it again — putting both options back. The cart's calculated value now decides the starting state of options the consumer can pick: on means checked to begin with, off means unchecked, either way still theirs to change. Options that cannot be selected in the widget keep working purely through the capability rules, so they can force an option they require without ever being shown or sent themselves. Resolves INT-1596 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ea5fb50 to
d79a56f
Compare
Lets the plugin pass the cart's calculated shipment options into the widget, so options the shop already decided on show as checked and locked.
The plugin can pass a new optional top-level cartShipmentOptions key (per carrier, camelCase option name → boolean), next to initial and address. When an option the consumer cannot choose (like age check) is active on the cart, the widget looks up its capability rules and shows every option it requires as checked and locked, and every option it excludes as unchecked and locked. One module (useShipmentOptionsState) decides all shipment option state; the option list and the selector only read from it.
The shop's allow* settings keep deciding what the consumer sees: an option that is not allowed never renders, forced or not; the plugin still enforces it at export. Forced options keep their configured surcharge (like priceSignature) — being forced doesn't make an option free. Without cartShipmentOptions the widget behaves exactly as before, so older plugin versions keep working.
Merge order for INT-1596:
Fixes INT-1596
Subtask: INT-1733
🤖 Generated with Claude Code