Skip to content

Enqueued Assets audit: treat zero-size and no-store responses as errors#2481

Open
Gilmoursa wants to merge 3 commits into
WordPress:trunkfrom
Gilmoursa:fix/2417-enqueued-assets-zero-size-no-store
Open

Enqueued Assets audit: treat zero-size and no-store responses as errors#2481
Gilmoursa wants to merge 3 commits into
WordPress:trunkfrom
Gilmoursa:fix/2417-enqueued-assets-zero-size-no-store

Conversation

@Gilmoursa
Copy link
Copy Markdown

Summary

Fixes #2417.

perflab_aea_get_asset_size() had two TODOs in the code for cases that silently passed the audit when they should be flagged as errors:

  1. Zero-size response body — a 200 response with an empty body means the asset is effectively broken. The audit was reporting it as OK with a size of 0 bytes.
  2. Cache-Control: no-store — an asset that browsers are forbidden from caching is a performance problem and should surface in the audit. The audit was reporting these as OK as long as the status was 200.

Behaviour change

Zero-size: Returns WP_Error('zero_size') instead of 0.

Non-cacheable: Returns WP_Error('not_cacheable') when the response has a Cache-Control: no-store directive.

Cache-Control: no-cache (revalidate) is intentionally left as passing — the asset can still be served from cache after revalidation, so it is not a hard performance problem in the same way as no-store.

Both WP_Error results feed into the existing error display path in the audit table (red row, error message shown, recommended status), so no additional UI changes are needed.

Changes

  • plugins/performance-lab/includes/site-health/audit-enqueued-assets/helper.php: implement the two checks, remove the TODO comments
  • plugins/performance-lab/tests/includes/site-health/audit-enqueued-assets/test-audit-enqueued-assets-helper.php: update the zero-size assertion to expect WP_Error; add test_perflab_aea_get_asset_size_not_cacheable() covering no-store, no-store with extra directives, no-cache (should pass), and a normal cacheable response
  • plugins/performance-lab/tests/data/class-audit-assets-mock-assets.php: pass headers from mocked responses through the pre_http_request filter so header-dependent tests work end-to-end

Test plan

  • Run composer test:integration -- --filter test_perflab_aea_get_asset_size
  • Run composer test:integration -- --filter test_perflab_aea_get_asset_size_not_cacheable
  • Confirm an asset returning a zero-byte body shows as an error row in the Site Health blocking assets table
  • Confirm an asset served with Cache-Control: no-store shows as an error row in the table
  • Confirm an asset served with Cache-Control: no-cache still passes the audit
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 15, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: Gilmoursa <gilmoursa@git.wordpress.org>
Co-authored-by: westonruter <westonruter@git.wordpress.org>
Co-authored-by: tejas0306 <suhan2411@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

In perflab_aea_get_asset_size(), two cases that should have been
treated as errors were silently passing the audit:

- A 200 response with an empty body now returns WP_Error('zero_size').
  An asset that returns nothing is effectively broken, regardless of the
  status code.

- A 200 response with Cache-Control: no-store now returns
  WP_Error('not_cacheable'). An asset that browsers are forbidden from
  caching is a clear performance problem and should surface in the audit.

  Cache-Control: no-cache (revalidate) is intentionally left as passing
  since the asset can still be served from cache after revalidation.

Both cases were already noted as TODOs in the original code. Removes
those TODO comments and adds tests covering zero-size, no-store,
no-cache (should pass), and normal cacheable responses. Also updates
the mock class to pass response headers through so header-dependent
tests can work end-to-end.

Fixes WordPress#2417.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Gilmoursa Gilmoursa force-pushed the fix/2417-enqueued-assets-zero-size-no-store branch from 7168784 to 4bcfe31 Compare May 15, 2026 14:58
@codecov
Copy link
Copy Markdown

codecov Bot commented May 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.39%. Comparing base (347597f) to head (48748c9).
⚠️ Report is 5 commits behind head on trunk.

Additional details and impacted files
@@            Coverage Diff             @@
##            trunk    #2481      +/-   ##
==========================================
+ Coverage   69.33%   69.39%   +0.05%     
==========================================
  Files          90       90              
  Lines        7749     7763      +14     
==========================================
+ Hits         5373     5387      +14     
  Misses       2376     2376              
Flag Coverage Δ
multisite 69.39% <100.00%> (+0.05%) ⬆️
single 35.66% <0.00%> (-0.07%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
wp_remote_retrieve_header() returns string|array (array when the same
header appears multiple times in the response). Joining array values
with implode() before passing to strtolower() resolves the PHPStan
error and also correctly handles multi-value Cache-Control headers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@westonruter westonruter added the [Type] Enhancement A suggestion for improvement of an existing feature label May 15, 2026
@westonruter westonruter added this to the performance-lab n.e.x.t milestone May 15, 2026
@westonruter westonruter requested a review from Copilot May 15, 2026 15:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Enqueued Assets Site Health audit so empty asset responses and Cache-Control: no-store responses are surfaced as asset errors instead of passing as successful zero-byte/cacheable assets.

Changes:

  • Returns WP_Error for zero-size asset bodies and Cache-Control: no-store.
  • Adds tests for zero-size and cache-control handling.
  • Updates the audit asset test mock to pass response headers through.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
plugins/performance-lab/includes/site-health/audit-enqueued-assets/helper.php Adds empty-body and no-store error handling in asset size retrieval.
plugins/performance-lab/tests/includes/site-health/audit-enqueued-assets/test-audit-enqueued-assets-helper.php Updates and expands coverage for the new asset-size error behavior.
plugins/performance-lab/tests/data/class-audit-assets-mock-assets.php Includes mocked headers in HTTP responses for header-dependent tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@westonruter westonruter added the [Plugin] Performance Lab Issue relates to work in the Performance Lab Plugin only label May 15, 2026
…ze check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Plugin] Performance Lab Issue relates to work in the Performance Lab Plugin only [Type] Enhancement A suggestion for improvement of an existing feature

3 participants