Skip to content

Build/Test Tools: Use strict assertions in the REST API tests. - #13683

Closed
haritpanchal wants to merge 1 commit into
WordPress:trunkfrom
haritpanchal:tests/rest-api-strict-assertions
Closed

haritpanchal wants to merge 1 commit into
WordPress:trunkfrom
haritpanchal:tests/rest-api-strict-assertions

Conversation

@haritpanchal

Copy link
Copy Markdown

What

Reviewed the 12 files claimed on the ticket under tests/phpunit/tests/rest-api/
(excluding 5 files still covered by the open PR #11707: rest-attachments-controller.php,
rest-global-styles-controller.php, wpRestAbilitiesV1CategoriesController.php,
wpRestAbilitiesV1ListController.php, wpRestAbilitiesV1RunController.php).

44 of 50 loose assertions convert; 6 stay loose as legitimate object-value comparisons.

Converted

rest-posts-controller.php (15/15) — $data['author'], $data['id'], and the
date/date_gmt/modified/modified_gmt fields are all real int/string types per
class-wp-rest-posts-controller.php ((int) $post->post_author, $post->ID sanitized
to int, mysql_to_rfc3339() returning string|null), so these convert directly to
assertNotSame(). Two calls needed a cast: get_post_meta( $post_id, 'my_custom_int', true )
always returns the raw DB string '123', not int 123 — assertEquals( 123, ... ) was
passing on loose coercion. Confirmed by mutation: reverting the cast to 123 fails with
Failed asserting that '123' is identical to 123.

rest-comments-controller.php (11/11) — same 123/'123' meta pattern as posts.
check_comment_data()'s four property comparisons (comment_ID, comment_post_ID,
comment_parent, user_id) compare WP_Comment's raw numeric-string properties against
the REST response's (int)-cast fields, so each needs (int) on the expected side.
Confirmed by mutation: removing one cast fails with
Failed asserting that 2 is identical to '2'. One (comment_approved) is a plain string
cast ('1'), and one line was simply inconsistent with its own file — the sibling
assertion on the line above already used the same (string) cast with assertSame().

rest-users-controller.php (5/9) — post_author reassignment checks follow the same
WP_Post::$post_author string contract established earlier on this ticket (props
haritpanchal, changeset 63632), plus the same 123/'123' meta pattern. Left unconverted:
two comparisons against new stdClass() and two comparisons of (object) $user->allcaps /
(object) $user->caps against the controller's own independently-cast copy — both sides are
always different object instances by construction, so assertSame() would fail on identity
alone regardless of matching properties.

rest-autosaves-controller.php (3/3), rest-revisions-controller.php (1/1) — the
shared check_get_autosave_response() / check_get_revision_response() helpers compare
$autosave->post_author / $revision->post_author (string) against the REST response's
(int)-cast author field; both need the same (int) cast, confirmed by mutation
(Failed asserting that 2 is identical to '2'.).

rest-post-meta-fields.php (3/3), rest-term-meta-fields.php (3/3) — identical setup
in both files: test_custom_schema is registered with show_in_rest.schema.type => 'number',
so the REST-exposed value is sanitized to (float) — same finding as PR #12613's REST schema
sanitization work. assertSame( 3.0, ... ) is required, not 3; confirmed by mutation
(Failed asserting that 3.0 is identical to 3.). The two raw get_post_meta()/get_term_meta()
reads in the same tests stay string-cast ('3', '2'), since those bypass the REST schema
entirely.

rest-server.php (1/1) — test_default_param_is_overridden() sets
'foo' => 123 (a real int, not a query string) directly via set_query_params(), and no
'type' is declared for the foo arg, so no sanitization runs. The original
assertEquals( '123', $request['foo'] ) was passing only because of loose int/string
coercion — the expected literal was simply wrong. Confirmed by first converting straight to
assertSame( '123', ... ), which failed with
Failed asserting that 123 is identical to '123'.; fixed to assertSame( 123, ... ) to
match the actual (and intended) behavior — the test is about default-value override, not
type coercion.

rest-themes-controller.php (1/1) — wp_list_pluck( $data, 'stylesheet' ) always
returns an array of plain strings; direct conversion.

rest-request.php (1/1, not a direct swap) — test_alternate_json_content_type()'s
has_json_params assertion is a trap: when the JSON body is parsed, get_param() returns
real bool true; when it isn't, get_param() returns null (a missing key), never false.
A direct assertSame( $accept_json, ... ) swap looks correct but actually breaks the two
false data sets, since null !== false. Confirmed by mutation: swapping to a plain
assertSame() fails 2 of 6 data sets with Failed asserting that null is identical to false.
Fixed with an explicit branch — assertTrue() when JSON is expected, assertNull()
otherwise — so each branch asserts the value it actually gets, the same fix shape as the
assertTrue() change requested on PR #13659.

Left as assertEquals(), no changes

  • rest-users-controller.php (4) — $data['capabilities']/$data['extra_capabilities']
    vs new stdClass(), and vs (object) $user->allcaps / (object) $user->caps: always
    distinct object instances, compared by value only.
  • rest-block-renderer-controller.php (1) — two independent json_decode() calls (without
    the true arg) produce distinct stdClass trees each time; compared by value only.
  • wpRestTemplatesController.php (1) — compares against new stdClass(); same identity
    issue as above.

Testing

npm run test:php -- --group restapi
Tests: 3566, Assertions: 16298, Errors: 1 (pre-existing, unrelated — see below), Skipped: 6

node ./tools/local-env/scripts/docker.js run --rm php ./vendor/bin/phpunit -c tests/phpunit/multisite.xml --group restapi
Tests: 3601, Assertions: 16428, Errors: 1 (same pre-existing error), Skipped: 6

npm run test:php -- --group restapi-autosave / restapi-themes (single-site and multisite)
All OK, no failures

The one error (Test_oEmbed_Controller::test_proxy_with_classic_embed_provider, Attempt to read property "queue" on null) is in tests/oembed/controller.php, a file untouched by
this PR. Confirmed pre-existing by stashing this branch's changes and re-running the same
test directly against trunk — it fails identically there.

Every risky conversion above (the four 123/'123' meta findings, the four (int)-cast
post_author/comment-property findings, the 3.0 schema-float finding, the rest-server.php
literal-mismatch finding, and the rest-request.php null-vs-false trap) was proven by
mutation: reverting the fix and confirming the test fails for the expected reason, then
restoring it.

PHPCS clean on all 10 changed files. Test-only change; no production code touched.

Trac ticket: https://core.trac.wordpress.org/ticket/64895

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5
Used for: Digging through this directory turned up a few things worth flagging beyond the mechanical conversion — get_param() returning null instead of false when a param is simply absent (which a naive strict-assertion swap would have broken outright), get_post_meta()/get_term_meta() silently returning strings for values stored as ints, and a schema declared type => 'number' quietly coercing to float on the way out. One assertion (rest-server.php) turned out to be checking the wrong literal type entirely, just masked by loose comparison the whole time. Each of these was confirmed by mutation before I trusted it. I take responsibility for the result.

@github-actions

Copy link
Copy Markdown

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.

Core Committers: Use this line as a base for the props when committing in SVN:

Props haritpanchal.

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

@lancewillett

Copy link
Copy Markdown
Member

wporg-sync pushed a commit that referenced this pull request Sep 23, 2026
Use type-strict assertions for REST response values and metadata. Match expected types to raw database values and REST schema sanitization, and explicitly check for null when JSON parameters are absent.

Developed in: #13683

Props haritpanchal.
See #64895.


git-svn-id: https://develop.svn.wordpress.org/trunk@63896 602fd350-edb4-49c9-b593-d223f7449a82
wporg-sync pushed a commit to WordPress/WordPress that referenced this pull request Sep 23, 2026
Use type-strict assertions for REST response values and metadata. Match expected types to raw database values and REST schema sanitization, and explicitly check for null when JSON parameters are absent.

Developed in: WordPress/wordpress-develop#13683

Props haritpanchal.
See #64895.

Built from https://develop.svn.wordpress.org/trunk@63896


git-svn-id: http://core.svn.wordpress.org/trunk@63065 1a063a9b-81f0-0310-95a4-ce76da25c4cd
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