Skip to content

WOOTAX-25 - Add regression test for zero-amount tax calculations - #2966

Merged
Abdalsalaam merged 2 commits into
trunkfrom
fix/WOOTAX-25
Jun 20, 2026
Merged

WOOTAX-25 - Add regression test for zero-amount tax calculations#2966
Abdalsalaam merged 2 commits into
trunkfrom
fix/WOOTAX-25

Conversation

@Abdalsalaam

@Abdalsalaam Abdalsalaam commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Description

When a subscription is switched, or when a free-trial subscription's initial cart total is $0, TaxJar returns a response whose top-level rate (and amount_to_collect) is 0 because taxable_amount is 0 — while the real per-jurisdiction rates are still present inside breakdown.line_items. Historically the rate builder wrote the zeroed top-level rate into the shared WooCommerce tax-rate row, which set an existing rate to 0.0000% (WOOTAX-18) and left subscription renewals with no tax (WOOTAX-25).

The current get_itemized_tax_rates() already persists the real per-jurisdiction rates from breakdown.line_items and never writes the zeroed top-level rate (fixed by the itemized-tax-rate refactor). This PR is a test-only change that locks that behaviour in with a regression test, so the zeroing-out cannot silently come back.

The test feeds the exact zero-amount response captured in WOOTAX-18 into get_itemized_tax_rates() and asserts the real per-jurisdiction rates (city 1.5%, county 1.25%, state 4.225%) are persisted and the combined rate is 6.975%, never 0. It was verified to fail if the builder is reverted to writing the top-level rate.

Related issue(s)

Linear: WOOTAX-25 (same root cause as WOOTAX-18 / #2826).

Steps to reproduce & screenshots/GIFs

Original bug (no longer reproducible on trunk):

  1. Enable automated tax rates (WooCommerce Tax).
  2. Create a subscription product with a free trial and no sign-up fee.
  3. Add it to the cart; observe the "recurring total" tax line shows $0.00 because the $0 initial calculation zeroed the shared tax rate.

Verifying the guard:

  1. Run the suite: ./vendor/bin/phpunit --filter test_zero_amount_response_persists_real_itemized_rates — passes on trunk.
  2. Temporarily change the line-item rate in get_itemized_tax_rates() to write the top-level rate — the test fails, confirming it catches the regression.

N/A - test-only change, no visual changes.

Checklist

  • unit tests
  • changelog.txt entry added — N/A: test-only change, no user-facing impact.
  • readme.txt entry added — N/A: test-only change, no user-facing impact.

@Abdalsalaam Abdalsalaam self-assigned this Jun 18, 2026
A subscription switch, or a free-trial subscription whose initial cart total is
$0, produces a TaxJar response with a zeroed top-level rate while the real
per-jurisdiction rates remain in breakdown.line_items. The itemized rate builder
(get_itemized_tax_rates) already persists those real rates and never writes the
zeroed top-level rate, so the historical "tax rate set to 0.0000%" / "no tax on
renewal" behaviour no longer occurs.

This locks that in: the test feeds the exact zero-amount response captured in
WOOTAX-18 into get_itemized_tax_rates and asserts the real per-jurisdiction rates
(city 1.5%, county 1.25%, state 4.225%) are persisted and the combined rate is
6.975%, not 0. Verified the test fails if the builder is reverted to writing the
top-level rate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Abdalsalaam
Abdalsalaam requested a review from bartech June 18, 2026 10:53
@Abdalsalaam
Abdalsalaam marked this pull request as ready for review June 18, 2026 10:53

@bartech bartech left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — approving.

The regression test correctly locks in the zero-amount tax fix (WOOTAX-25): I traced the path and it genuinely fails if production regresses to writing the top-level shared tax_rate = 0, and CI is green across the PHP/WP/WC matrix.

A couple of optional, non-blocking hardening ideas:

  • Consider also asserting $result['tax_rate'] is 0.0 — that's the field actually carrying the zeroed shared rate, and it's currently unasserted (the other half of the contract).
  • A one-line comment on why assertCount( 4, … ) is load-bearing would help future readers.

Nice, well-scoped test.

@Abdalsalaam
Abdalsalaam merged commit 51e98b2 into trunk Jun 20, 2026
9 checks passed
@Abdalsalaam
Abdalsalaam deleted the fix/WOOTAX-25 branch June 20, 2026 14:00
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.

2 participants