Opened 6 days ago
Last modified 6 days ago
#66495 new enhancement
Tests: Add unit coverage for the post functions in post.php
| Reported by: | hmbashar | Owned by: | |
|---|---|---|---|
| Priority: | normal | Milestone: | Awaiting Review |
| Component: | Posts, Post Types | Version: | |
| Severity: | normal | Keywords: | has-patch has-unit-tests |
| Cc: | Focuses: | tests |
Description
src/wp-includes/post.php has several functions that sanitize post data, detect changes of posts and keep related data in sync, but they have no direct PHPUnit coverage. A search of tests/phpunit/tests finds no references to:
sanitize_post_field(),wp_get_recent_posts()andget_private_posts_cap_sql().wp_check_for_changed_slugs(),wp_check_for_changed_dates(),wp_transition_post_status()andis_local_attachment().wp_trash_post_comments(),wp_untrash_post_comments(),delete_post_thumbnail(),update_post_caches(),update_postmeta_cache(),clean_attachment_cache()andupdate_attached_file().
Some of these are only exercised indirectly through wp_insert_post() and wp_update_post(), so a change in their behavior is hard to spot and to attribute. Direct tests describe the current behavior of each function.
Proposed scope
This ticket is meant to be handled with several small patches, one for each group of related functions, so each one is easy to review. The tests go in tests/phpunit/tests/post/, one class per function, with data providers where it helps.
- Sanitizing and queries.
sanitize_post_field()for each context (raw,edit,db,display,attributeandjs), the integer fields and the filters.wp_get_recent_posts()for the defaults, the arguments and the output types.get_private_posts_cap_sql()for the users who can read private posts. - Changes of a post.
wp_check_for_changed_slugs()andwp_check_for_changed_dates().wp_transition_post_status()for the actions that fire with and without a change, including the post type.is_local_attachment(). - Comments, thumbnails and caches.
wp_trash_post_comments()andwp_untrash_post_comments().delete_post_thumbnail().update_post_caches(),update_postmeta_cache()andclean_attachment_cache().update_attached_file().
Out of scope
This ticket only adds tests and does not change behavior. The following are left out on purpose because other tickets are working on them:
get_post_statuses()andget_page_statuses(), see #24722 and #58617.get_post_custom(),get_post_custom_keys()andget_post_custom_values(), see #65044, #45505 and #20853.wp_match_mime_types(), see #60003.wp_check_post_hierarchy_for_loops(), which goes with the tests ofwp_find_hierarchy_loop()in #59901.
Change History (3)
This ticket was mentioned in PR #15532 on WordPress/wordpress-develop by @hmbashar.
6 days ago
#1
- Keywords has-patch has-unit-tests added; needs-patch removed
This ticket was mentioned in PR #15533 on WordPress/wordpress-develop by @hmbashar.
6 days ago
#2
Adds unit tests for the functions that track the changes of a post in src/wp-includes/post.php, which had no direct test coverage. This is the second group of the work described in the ticket, and is independent from the other groups. No behavior is changed.
Functions covered, each in its own test class in tests/phpunit/tests/post/:
wp_check_for_changed_slugs()- The old slug of a published post, or of an attachment with the status
inherit, is stored. - Nothing is stored when the slug does not change, for posts that are not published, or for hierarchical post types.
- An empty slug is not stored, an old slug is not stored twice, and a new slug that was used before is removed from the old slugs.
- It is hooked to
post_updatedandattachment_updated, and stores the old slug when a post is updated.
- The old slug of a published post, or of an attachment with the status
wp_check_for_changed_dates()- The same rules for the old date, which is stored as a date without the time. A change of the time only is not stored.
wp_transition_post_status()- The
transition_post_status,{old}_to_{new}and{new}_{post_type}actions fire in order with their arguments, also when the status does not change. - The status
newis allowed as the old status. - Only the first action fires for a new status that is not registered, the transition action does not fire for an old status that is not registered, and the last action does not fire for a post type that is not registered.
- It is used when a post is published.
- The
is_local_attachment()- A URL of the form
?attachment_id=of this site, and the permalink of an attachment, are attachments. - The URL of a post, a URL that matches nothing, and a URL of another site, are not.
- A URL of the form
Removing the check for the host from is_local_attachment() cannot be detected by a test, because url_to_postid() already ignores the URLs of other sites. The test with a URL of another site that names a real attachment is kept for the behavior.
Testing:
vendor/bin/phpunit --filter 'Tests_Post_(WpCheckForChangedSlugs|WpCheckForChangedDates|WpTransitionPostStatus|IsLocalAttachment)'vendor/bin/phpunit -c tests/phpunit/multisite.xml --filter 'Tests_Post_(WpCheckForChangedSlugs|WpCheckForChangedDates|WpTransitionPostStatus|IsLocalAttachment)'vendor/bin/phpunit --group postvendor/bin/phpcs tests/phpunit/tests/post/
I also temporarily broke the related lines in src/wp-includes/post.php (the change check, the status and hierarchical checks, the attachment case, the empty and duplicate old values, the removal of a new value that was used before, each of the conditions and arguments of the actions, and the checks of is_local_attachment()) and confirmed that a new test fails for each one, except the host check described above.
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Sonnet 5.5
Used for: Written with AI and manually reviewed by me.
This ticket was mentioned in PR #15534 on WordPress/wordpress-develop by @hmbashar.
6 days ago
#3
Adds unit tests for the functions of src/wp-includes/post.php that handle the comments, the thumbnail, the caches and the attached file of a post, which had no direct test coverage. This is the third and last group of the work described in the ticket, and is independent from the other groups. No behavior is changed.
Functions covered, each in its own test class in tests/phpunit/tests/post/:
wp_trash_post_comments()andwp_untrash_post_comments()- Nothing is done for a post that does not exist, and the
trashed_post_commentsaction does not fire for a post without comments. - The comments are marked as
post-trashed, only the comments of that post are changed, and the status of each comment is stored. - Untrashing restores the status of each comment, deletes the stored statuses, and a comment that was stored as
post-trashedbecomes unapproved. - The four actions and their arguments, and that both functions are used when a post is trashed and restored.
- Nothing is done for a post that does not exist, and the
delete_post_thumbnail()- The thumbnail is removed and the attachment is kept,
falseis returned for a post without a thumbnail or one that does not exist, and the other custom fields are kept.
- The thumbnail is removed and the attachment is kept,
update_post_caches()andupdate_postmeta_cache()- The posts, their custom fields and their terms are cached by default, each of the last two can be turned off, and the post type argument decides which terms are cached.
update_postmeta_cache()caches the custom fields, returns the cache of each post, and returnsfalsewithout IDs.
clean_attachment_cache()- The cache of the attachment and of its custom fields is emptied, the ID is cast to an integer, the terms are cleaned only when asked, and nothing is done while the invalidation of the cache is suspended.
update_attached_file()- The path is stored relative to the uploads directory, a relative path or a path outside the directory is stored as it is, an empty path deletes the stored file, and the
update_attached_filefilter is used.
- The path is stored relative to the uploads directory, a relative path or a path outside the directory is stored as it is, an empty path deletes the stored file, and the
The check for an empty list of posts in update_post_caches() is not tested, because the function does nothing for an empty list with or without it.
Testing:
vendor/bin/phpunit --filter 'Tests_Post_(WpTrashPostComments|WpUntrashPostComments|DeletePostThumbnail|UpdatePostCaches|UpdatePostmetaCache|CleanAttachmentCache|UpdateAttachedFile)'vendor/bin/phpunit -c tests/phpunit/multisite.xml --filter 'Tests_Post_(WpTrashPostComments|WpUntrashPostComments|DeletePostThumbnail|UpdatePostCaches|UpdatePostmetaCache|CleanAttachmentCache|UpdateAttachedFile)'vendor/bin/phpunit --group postvendor/bin/phpcs tests/phpunit/tests/post/
I also temporarily broke the related lines in src/wp-includes/post.php (the checks, the actions, the stored and restored statuses, the return values, the flags and post type handling of the caches, the cache deletions, the ID cast, the suspension check, and each step of update_attached_file()) and confirmed that a new test fails for each one, except the check described above.
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Sonnet 5.5
Used for: Written with AI and manually reviewed by me.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
Adds unit tests for
sanitize_post_field(),wp_get_recent_posts()andget_private_posts_cap_sql()insrc/wp-includes/post.php, which had no direct test coverage. This is the first group of the work described in the ticket, and each of the groups is a separate PR. No behavior is changed.Functions covered, each in its own test class in
tests/phpunit/tests/post/:sanitize_post_field()ID,post_parent,menu_order) are cast to integers in every context, also after escaping.ancestorsis returned as a list of positive integers.post_prefix, the text of the title, excerpt and password formatted for a text area, and the other fields escaped as attributes.wp_get_recent_posts()OBJECToutput, and the empty results (array()orfalse).include,exclude, the category, the custom field, the post type and the post status.get_private_posts_cap_sql()get_posts_by_author_sql()without the full query.Testing:
vendor/bin/phpunit --filter 'Tests_Post_(SanitizePostField|WpGetRecentPosts|GetPrivatePostsCapSql)'vendor/bin/phpunit -c tests/phpunit/multisite.xml --filter 'Tests_Post_(SanitizePostField|WpGetRecentPosts|GetPrivatePostsCapSql)'vendor/bin/phpunit --group postvendor/bin/phpcs tests/phpunit/tests/post/I also temporarily broke the related lines in
src/wp-includes/post.php(the integer casts,absintof the ancestors, the raw early return, each of the edit, db and display filters, the formatting and escaping of the fields, and the defaults, output and deprecated argument ofwp_get_recent_posts()) and confirmed that a new test fails for each one.Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Sonnet 5.5
Used for: Written with AI and manually reviewed by me.