Skip to content

Make the checkout pickup-point chooser testable and extensible#109

Merged
loevgaard merged 6 commits into
2.xfrom
feat/extensible-pickup-point-chooser-js
Jun 8, 2026
Merged

Make the checkout pickup-point chooser testable and extensible#109
loevgaard merged 6 commits into
2.xfrom
feat/extensible-pickup-point-chooser-js

Conversation

@loevgaard

Copy link
Copy Markdown
Member

Refactors the shop checkout pickup-point chooser (public/js/setono-pickup-point.js) from a closed IIFE that built all its markup in JavaScript into a class-based native ES module — testable, and extensible by plugin users without forking. No bundler / build step is introduced; it's still a single hand-served file, now loaded with <script type="module">.

What changed

  • Markup lives in Twig. The chooser is built by cloning server-rendered <template>s from the new templates/shop/checkout/_pickup_point_templates.html.twig partial and filling [data-slot]/[data-role]/[data-action] hooks. All markup, translations and styling are in Twig — overriding that one partial restyles the chooser with no JavaScript. A missing template renders nothing rather than fabricating markup. The field partial drops its eight data-*-text attributes accordingly.
  • Four extension levels (see docs/customizing-the-chooser.md): override the Twig templates → window.setonoSyliusPickupPointConfig → bubbling setono:pickup-point(s):* CustomEvents (the selected one is cancelable) → subclass PickupPointChooser via window.SetonoSyliusPickupPointChooser.
  • JS unit tests. Vitest + jsdom specs (25 tests) for the exported helpers and the render/list/state/event/boot behaviour, plus a javascript-tests CI job.

Behaviour preserved

Two-state summary/list widget, auto-select-nearest, identity-based "Selected" badge on reload (now matching the server's provider+id identity), loading/empty/error states, multi-shipment support, and a single shared /pickup-points fetch per visit.

Verification

  • vitest 25/25, PHPStan, ECS, lint:twig, lint:container all green locally.
  • Playwright live check on the test app: module boots, nearest GLS point auto-selected, Change → list (badge + highlight) → pick another updates the token, selected/loaded events fire.

Base: 2.x.

loevgaard added 6 commits June 8, 2026 13:25
…ble templates

The shop pickup-point chooser was a closed IIFE that built all its markup in
JavaScript, so none of it was unit-testable and a consumer could only customize
it by forking the whole file.

Rewrite public/js/setono-pickup-point.js as a native ES module (loaded with
<script type="module">, still no bundler) exporting the pure helpers and a
PickupPointChooser class. The class builds the UI by cloning server-rendered
<template>s from the new templates/shop/checkout/_pickup_point_templates.html.twig
partial and filling their [data-slot]/[data-role]/[data-action] hooks, so all
markup, translations and styling live in Twig — overriding that one partial
restyles the chooser with no JavaScript. A missing template renders nothing
rather than fabricating markup.

Consumers can also subclass PickupPointChooser (registered on
window.SetonoSyliusPickupPointChooser), listen for the bubbling
setono:pickup-point(s):* CustomEvents, or set window.setonoSyliusPickupPointConfig.
The field partial drops its eight data-*-text attributes (the strings moved into
the templates), and the templates partial is emitted once per checkout page via
the sylius_shop.checkout#javascripts hook.
Cover the now-exported helpers (decodeToken/identity/addressLine) and the
PickupPointChooser render/list/state/event/boot behaviour with Vitest + jsdom,
added to tests/Application (the repo's Node tooling home). A javascript-tests
workflow job runs them; because tests/Application/package.json has file: deps on
the installed Sylius/Symfony assets, the job sets up PHP + composer (to populate
vendor/) before yarn + vitest, mirroring the functional-tests setup.

The Vitest config is a .mjs file so tests/Application/package.json need not become
"type": "module" (which would break Encore's CommonJS webpack.config.js).
Add docs/customizing-the-chooser.md describing the four extension levels (override
the Twig templates, config object, DOM events, subclass) and update README,
CLAUDE.md and UPGRADE.md to note the chooser is now an ES module that clones
overridable templates.
ramsey/composer-install already falls back to highest when there is no
composer.lock, so stating it explicitly added nothing.
Each <template> now sits in its own {% block setono_sylius_pickup_point_* %} so a
consumer can override a single template via Twig inheritance instead of copying the
whole partial. The rendered output (and the <template> ids the JS clones) is unchanged.
@loevgaard loevgaard merged commit f7ec873 into 2.x Jun 8, 2026
88 checks passed
@loevgaard loevgaard deleted the feat/extensible-pickup-point-chooser-js branch June 8, 2026 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant