Skip to content

Premium Analytics: converge both date pickers onto one range-bounds helper - #52064

Merged
chihsuan merged 5 commits into
trunkfrom
change/wooa7s-2079-range-patch
Sep 9, 2026
Merged

Premium Analytics: converge both date pickers onto one range-bounds helper#52064
chihsuan merged 5 commits into
trunkfrom
change/wooa7s-2079-range-patch

Conversation

@chihsuan

@chihsuan chihsuan commented Sep 8, 2026

Copy link
Copy Markdown
Member

Fixes WOOA7S-2079 (item 1 of 8; the rest follow in a separate PR)

Proposed changes

  • Export one encodeRangeToSearchParams helper that owns where a staged date range's to bound lands, and have both date pickers call it.
  • buildRangePatch (the URL picker) keeps a preset or already-normalized range verbatim and moves only a calendar edit's midnight to to the site's end of day. stageDateRange (a widget's own date field) applied that move unconditionally, while its comment pointed at build-range-patch as though it followed the same rule.
  • Add tests for the shared helper, and one at the field level asserting a preset's to survives staging.

The divergence is currently unreachable. reportParamsAttributeField has one production consumer, wordads-chart-tabs, whose grain offers only last-7-days, last-30-days and last-12-months, and presetIds filters the period menu as well as the pills. Every one of those ends at end of day, so the extra move was a no-op. last-24-hours (to: endOfHour( now )) is the only selectable preset it would change, and nothing offers it through this field today. What this removes is a trap in a documented extension point, not a live bug.

The shared helper also skips the move for the year surface (all-time and year-YYYY), which buildRangePatch did not. That is behavior-neutral: every year-surface range already ends at the site's end of day, so the move was a no-op there too. A test in date-range.test.ts pins it.

Worth knowing for the review: the unconditional endOfDayTZ came from #51419, where the concern was that a bare endOfDay used the visitor's timezone rather than the site's. That fix is preserved. A calendar edit still goes through endOfDayTZ( ..., reportingTimeZone() ); only presets stop being extended.

Related product discussion/links

Does this pull request change what data or activity we track or use?

No.

Testing instructions

The bug this closes cannot be reached from any shipping surface, so these steps check that the one live consumer did not regress.

  • Open a dashboard section that renders the WordAds metric tabs widget, and open the widget's own date control.
  • Pick each of Last 7 days, Last 30 days and Last 12 months. Each should apply as before, with the chart and the bucket menu reshaping to the range.
  • Pick Custom range, set a range by hand, Apply. The stored to should still be the site's end of day, not the visitor's.
  • Turn on a comparison and re-pick a period. The comparison window should stay the same length as the primary window.

To see the behavior the change actually fixes, drive the field's API directly rather than the UI: staging last-24-hours through stageDateRange previously stored to at end of day, and the comparison derived from it kept that stretch even after normalizeReportParams recomputed the primary window from the preset. packages/fields/src/report-params-field/__tests__/report-params-field.test.tsx pins the clock and asserts both halves.

Testing

Tested on a local site with its timezone set to Europe/Amsterdam (+02:00), serving this branch. The discriminator is last-24-hours at 09:59 site time: it is the only selectable preset whose to is not end of day, so a regression in the shared bounds helper would show to at 23:59:59.999+02:00 and a ~38h primary window instead of 24h.

Checked What happened Status
Last 30 days through the header picker from 2026-08-10T00:00:00.000+02:00, to 2026-09-08T23:59:59.999+02:00, primary window 720h
Previous period comparison on that range Comparison window 720h, equal to the primary, both ending at the site's end of day
Last 24 hours with comparison on (the discriminator) to 2026-09-08T09:59:59.999+02:00, not stretched. Primary 24.000h, comparison 24.000h, interval coerced to hour
Custom range Sep 1 to Sep 8, applied by hand to 2026-09-08T23:59:59.999+02:00, extended to the site's end of day rather than the browser's. Primary 192h, comparison 192h
Browser console across the pass, including a reload No errors or exceptions

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack or WordPress.com Site Helper), and enable the change/wooa7s-2079-range-patch branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack change/wooa7s-2079-range-patch
bin/jetpack-downloader test jetpack-mu-wpcom-plugin change/wooa7s-2079-range-patch

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

@jp-launch-control

jp-launch-control Bot commented Sep 8, 2026

Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 3 files.

File Coverage Δ% Δ Uncovered
projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/build-range-patch.ts 15/15 (100.00%) 0.00% 0 💚
projects/packages/premium-analytics/packages/routing/src/search/date-range/date-range.ts 6/6 (100.00%) 0.00% 0 💚
projects/packages/premium-analytics/packages/fields/src/report-params-field/report-params-field.tsx 57/57 (100.00%) 8.62% -5 💚

Full summary · PHP report · JS report

@chihsuan chihsuan changed the title WOOA7S-2079: Premium Analytics: converge both date pickers onto one range-bounds helper Premium Analytics: converge both date pickers onto one range-bounds helper Sep 8, 2026
@chihsuan
chihsuan marked this pull request as ready for review September 8, 2026 09:52
@chihsuan
chihsuan requested a review from a team as a code owner September 8, 2026 09:52
@chihsuan chihsuan added [Status] Needs Review This PR is ready for review. and removed [Status] In Progress labels Sep 8, 2026
layoutd
layoutd previously approved these changes Sep 8, 2026

@layoutd layoutd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Manually tested and verified following the testing instructions, with the site on UTC-10 (since my browser is on UTC+2) so a browser-zone leak would be clear.

Header picker: all scenarios land to where expected in the site zone, and the comparison window matches the primary. Widget-level date field on the WordAds chart tabs: the three presets and a custom range save as before.

Claude-assisted code review identified one thing worth a line in the description, inline below. Not blocking.

* verbatim; a calendar edit stages midnight, moved to the *site's* end of
* day because date-fns' bare `endOfDay` would use the visitor's.
*/
to: dateToISOStringWithLocalTZ(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is a bit wider than the rule it replaces: year-surface presets now skip the end-of-day move too. Looks behavior-neutral since those ranges already end at the site's end of day, but it isn't mentioned in the description. Might be worth a sentence?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch, that's intentional but undocumented. I checked all five year-surface presets and each already ends at the site's end of day, so it's a no-op. Added a sentence and a test.


expect( span( params.compare_from, params.compare_to ) ).toBe( span( params.from, params.to ) );

jest.useRealTimers();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If any expect throws, execution will stop before real timers are reinstated, leaving fake timers installed and leaking into following tests. An afterEach would cover it, or a try/finally

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

You're right, thanks. I forced a failure and the four tests after it timed out too. Switched to an afterEach.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VubBCJBkJSDBEGD7F42Tbt
@chihsuan
chihsuan merged commit 148881f into trunk Sep 9, 2026
82 checks passed
@chihsuan
chihsuan deleted the change/wooa7s-2079-range-patch branch September 9, 2026 03:14
@github-actions github-actions Bot removed [Status] In Progress [Status] Needs Review This PR is ready for review. labels Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants