Skip to content

BOGO Select for WooCommerce 2.3.5

Choose a tag to compare

@johnjanney johnjanney released this 02 Aug 03:55
· 36 commits to main since this release

Install: download bogo-select-2.3.5.zip below, then WordPress → Plugins → Add New → Upload Plugin.

[2.3.5] — 2026-08-02

A test written to close a gap, which then found something in it.

Most of this release is CI and tooling, and on its own none of it would have
earned a version — BRIEF.md §8.1 gives the version to the plugin code. The
phone-viewport test changed that by failing: the chooser's buttons were 21 CSS
pixels tall on a phone, which is a real defect a real customer has been tapping
at since 2.2.0. The fix for it is what makes this a PATCH rather than another
entry under Unreleased.

Fixed

  • The build no longer packages node_modules, and the parity check no longer
    says it did not.
    Committing a lockfile in this release means a developer who
    has run npm ci has a node_modules/ directory, and build-zip.sh had no
    reason to exclude one before — so cutting this release produced an archive of
    4.1MB and 180 files instead of 136KB and 23, carrying 197 files of Playwright
    into stores.

    The worse half is that verify-zip.sh passed it. That script exists to
    catch exactly this (CODEX-REVIEW.md M-01, the v1.2.0 archive that shipped a
    superseded class). It compares runtime files on both sides while pruning the
    directories the build excludes, and node_modules was in neither list — so it
    found the same stray .js files in the worktree and in the archive, called
    them matching, and reported "87 runtime files verified": six times the real
    number, in the message whose whole job is to be trusted. Both scripts now
    prune it, and the archive was checked by reading its contents rather than by
    trusting the exclude list.

    CI could not have caught this, because the package job never installs npm
    dependencies and its archive was always clean. Only a developer's own build
    was affected, and only since the lockfile landed — introduced and found inside
    the same unreleased window.

Changed

  • Everything CI reaches for is pinned, and Dependabot watches the pins
    (CODEX-REVIEW.md L-03). Actions are pinned to full commit SHAs with the
    version in a comment beside each — a tag can be moved, a SHA cannot. The
    integration job's browser now comes from npm ci against a committed
    package-lock.json, so it drives the Playwright that file names by integrity
    hash instead of whatever npm install resolved that morning.

    .github/dependabot.yml is the half that makes the rest safe, and is why
    this was not done earlier. Pinning on its own trades a supply-chain risk for
    a staleness risk: pinned actions stop receiving security fixes and nothing
    says so. Weekly updates now cover the actions, the Composer dev tools,
    Playwright, and the integration containers.

    Container images stay pinned by tag rather than digest. They exist for the
    length of one CI job and are never published or deployed, so what matters is
    being told when a newer WordPress or MariaDB appears — the same signal that
    keeps the compatibility matrix honest.

    Nothing here can reach a store: the shipped plugin has no Composer or npm
    runtime dependency, and neither manifest is in the archive.

  • The first five updates Dependabot proposed, all merged.
    actions/checkout 5.1.0 → 7.0.1, actions/setup-node 5.0.0 → 7.0.0,
    actions/upload-artifact 4.6.2 → 7.0.1, Playwright 1.56.0 → 1.62.0, and
    MariaDB 10.11 → 12.3 in the integration containers. The pinning did not cause
    that drift, it revealed it — three of the actions were majors behind before
    anything was pinned.

    The three action majors share one cause: each moved its own runtime to Node 24
    at v6, which needs Actions Runner 2.327.1 or newer, and ubuntu-latest
    satisfies that. actions/checkout v7 also refuses to check out a fork's PR
    head under pull_request_target and workflow_run; this workflow triggers on
    push and pull_request only.

    MariaDB was the jump with the most behind it: order.test.mjs places a real
    order and reads back its line metadata and stock decrements, and all eleven of
    its checks passed on 12.3. The plugin issues no SQL of its own — every query in
    the repository is in a test fixture — so the database is infrastructure for the
    job rather than something the job certifies. The one cost is representativeness,
    since CI now runs a newer database than most stores do. That is acceptable while
    the plugin writes no SQL; if it ever does, the answer is a deliberate pin to an
    LTS or a second lane rather than letting this drift back by accident.

  • The compact chooser is checked at a phone width (CODEX-REVIEW.md L-02).
    The layout added in v2.2.0 applies below 600px and the integration browser
    runs at 1280px, so every browser assertion ever made about the chooser was
    made at a width where the rule does not apply. mobile.test.mjs renders both
    carts at 390×844 and measures the boxes: the thumbnail capped and beside the
    text rather than above it, the button under the name, no card running off the
    side, and buttons meeting the WCAG 2.2 minimum target size.

    Geometry rather than screenshots, because a screenshot proves a layout
    changed and says nothing about whether it changed correctly. It also taps a
    gift, since a card that measures perfectly and cannot be tapped — something
    invisible over it — is the failure worth catching, and Playwright's
    actionability check is exactly that assertion.

    It found a defect on its first run. Every geometry assertion passed — the
    layout is the row it was meant to be — but the buttons measured 21×53 CSS
    pixels, under the 24px WCAG 2.2 asks for and well under what a thumb wants.
    On a phone these are tapped rather than pointed at, so the compact layout now
    gives its controls a 44px minimum target, the size the platform guidelines
    settled on. "Remove gift" is styled as text rather than as a button and is
    tapped just the same, so it gets the same target without gaining a border:
    its background stays transparent, and the extra height is reach rather than
    anything the customer sees. Cards grew from 134px to still well inside the
    bound the test holds them to.

    Overflow is asserted against the chooser and its cards rather than the
    document. A page-level check would fail on the theme's layout or
    WooCommerce's own blocks, neither of which this plugin can fix, and a check
    that fails for someone else's reasons is one that gets switched off. A real
    page-level overflow is still printed to the log.