2.1.0 — campaign scheduling
Campaign scheduling, a chooser defect found by review, and the integration
coverage that closes out CODEX-REVIEW.md M-03.
Fixed
- Two variations of one product, each listed individually, are no longer both
shown as chosen (CODEX-REVIEW.mdM-01). Such cards share a parent, and the
selected-state comparison looked only at the parent — so picking one marked
both, and because a chosen card shows only "Selected" and "Remove", the
customer was left with no control anywhere on the page for switching to the
other. Which card owns the selection is now decided once, where the whole list
is visible, with a variation listed in its own right taking precedence over the
parent card that could also offer it.
Changed
- A page of variable rewards costs far fewer product loads
(CODEX-REVIEW.mdM-02). Rendering asked for the same variation through four
separate paths: judging the parent a card, enumerating its selector, pricing
each option, and quoting the card. On a page of 24 variable products with 20
variations each that was 2,016 product loads against 504 distinct products;
it is now 552. A test holds the ratio so it cannot drift back.
Added
-
The offer can be given a start date and an end date (
OPEN-QUESTIONS.md
Q-005,DECISION.mdD-019). Both are optional and both are inclusive whole
days in the store's timezone: an offer running "1–7 August" is live on both of
those days and stops on the 8th. Leaving a field empty leaves that side
unbounded, and an offer with neither behaves exactly as it did before — every
existing install is unscheduled, with no migration.The settings screen refuses a window that ends before it begins, and says so
when an enabled offer has already ended or has not started yet, since in both
cases the storefront looks identical to the offer being switched off. -
Two tests fix how the Buy quantity counts (
OPEN-QUESTIONS.mdQ-002,
confirmingDECISION.mdD-003). Quantities are summed across everything on the
Buy list, so one each of two listed products satisfies a Buy 2 offer. A store
wanting "two of the same product" gives the offer a Buy list of one product,
which needs no new setting — a recipe now inINSTRUCTIONS.md§4 and held by a
test, since untested advice rots. -
Shipping behaviour is covered, answering
OPEN-QUESTIONS.mdQ-004. That
question had stated from the beginning that a free reward adds weight to the
parcel but nothing to order value, and nothing had ever checked it — every
other fixture uses virtual products so that shipping stays out of the way.
Measured now, in both modes: a free reward leaves the order value untouched and
cannot carry a customer over a free-shipping threshold, a discounted one adds
its own reduced price and can, and either joins the parcel. -
A real order is now placed in CI, and its metadata and stock asserted
(CODEX-REVIEW.mdM-03). The plugin writes reward metadata on
woocommerce_checkout_create_order_line_item, a hook nothing in CI had ever
fired —BRIEF.md§8.6 listed order placement, order metadata, and stock
reduction as verified by hand. A new lane builds a qualifying cart over the
Store API, checks out through it, and then inspects what landed: the reward
line and its quantity, the discounted line total, both meta keys, the visible
label, and stock down by the awarded quantity rather than by one. -
The classic cart and checkout are covered in a real browser. Every browser
assertion until now ran against the Cart and Checkout blocks, because that is
what WooCommerce provisions on a fresh install — but the shortcode path is
different code on both sides, reaching the page through template hooks rather
than therender_blockfilter and choosing over admin-ajax rather than the
Store API. The reward is chosen by clicking the button, so the JavaScript and
the reload that classic mode performs are covered too, along with the badge,
the discounted price, the locked quantity, and the checkout slot being marked
so it never reloads a part-filled form. -
Tax on a discounted reward is covered, in both display modes. The plugin
sets the line's price before totals run, so tax should follow the discounted
figure rather than the price it was discounted from — the difference a store
would feel, and never checked until now. A store whose prices exclude tax
charges 10.00 plus tax on a 20.00 reward at half price; one whose prices
include tax charges exactly 10.00, tax included. Both are asserted, along with
the rate being applied to the discounted line rather than the original. -
Coupon behaviour alongside a reward is now tested rather than reasoned.
The 1.3.0 notes said eligible coupons stack on the strength of where the
pricing hook sits, since the unit stubs have no coupon support. Both halves are
now covered against a real store: an eligible 20% coupon over a 50% reward
leaves the customer paying 40% of list, and a coupon excluding the reward
leaves it untouched while still discounting the rest of the cart. -
tests/README.mddescribes what is actually run. It had gone stale in the
opposite direction, still saying there was no database, HTTP, WordPress
install, JavaScript runner, or real block rendering — all of which the
integration job has done since 1.2.1. It now covers both suites and is
explicit about what neither reaches.