Opened 6 days ago
Last modified 5 days ago
#66491 new enhancement
Toolbar: Improve unit test coverage for admin-bar.php
| Reported by: | hmbashar | Owned by: | |
|---|---|---|---|
| Priority: | normal | Milestone: | Awaiting Review |
| Component: | Toolbar | Version: | |
| Severity: | normal | Keywords: | has-patch has-unit-tests |
| Cc: | Focuses: |
Description
src/wp-includes/admin-bar.php contains most of the functions that build and render the Toolbar (Admin Bar), but only a small part of it is covered by the PHPUnit suite today. The existing tests live in tests/phpunit/tests/adminbar.php.
A search of tests/phpunit/tests shows that the following functions are currently covered:
_wp_admin_bar_init()wp_admin_bar_wp_menu()wp_admin_bar_customize_menu()wp_admin_bar_new_content_menu()show_admin_bar()is_admin_bar_showing()
The following functions have no direct test references:
wp_admin_bar_render()wp_admin_bar_sidebar_toggle()wp_admin_bar_my_account_item()wp_admin_bar_my_account_menu()wp_admin_bar_site_menu()wp_admin_bar_edit_site_menu()wp_admin_bar_my_sites_menu()wp_admin_bar_shortlink_menu()wp_admin_bar_edit_menu()wp_admin_bar_comments_menu()wp_admin_bar_appearance_menu()wp_admin_bar_updates_menu()wp_admin_bar_search_menu()wp_admin_bar_recovery_mode_menu()wp_admin_bar_add_secondary_groups()wp_enqueue_admin_bar_header_styles()wp_enqueue_admin_bar_bump_styles()_get_admin_bar_pref()
Adding tests for these functions will make future changes to the Toolbar safer to review, and will help catch regressions around capability checks, multisite behavior, and the output/escaping of menu items.
Proposed scope
Add tests (new methods in tests/phpunit/tests/adminbar.php, or a new test class where it makes more sense) that verify, for example:
- Nodes added by each
wp_admin_bar_*_menu()callback: the expected node IDs, parent, title, and href. - Capability handling: the nodes shown (or not shown) for different roles such as administrator, editor, subscriber and logged-out users.
- Context handling: the front end vs. the admin screens (e.g. the edit/view links in
wp_admin_bar_edit_menu(),wp_admin_bar_appearance_menu(),wp_admin_bar_customize_menu()). - Multisite:
wp_admin_bar_my_sites_menu()andwp_admin_bar_site_menu()for users with one site, several sites, and super admins. wp_admin_bar_updates_menu()andwp_admin_bar_comments_menu(): the counts and the resulting title/label.wp_admin_bar_search_menu(): the form output and its escaping.wp_admin_bar_recovery_mode_menu(): shown only while recovery mode is active.wp_admin_bar_render(): thewp_before_admin_bar_render/wp_after_admin_bar_renderactions and the HTML output.wp_enqueue_admin_bar_header_styles()andwp_enqueue_admin_bar_bump_styles(): the inline styles that are added._get_admin_bar_pref(): the user option, default value andget_user_option_*filter handling.
This ticket is only about test coverage. No change in behavior is expected, and if a test uncovers a bug, it should be reported in a separate ticket.
The work can be split across several patches/PRs, each covering a group of related functions, so it is easy to review. Contributors are welcome to pick one group and mention it in a comment, to avoid overlapping work.
Change History (7)
This ticket was mentioned in PR #15521 on WordPress/wordpress-develop by @hmbashar.
6 days ago
#1
- Keywords has-patch has-unit-tests added
This ticket was mentioned in PR #15522 on WordPress/wordpress-develop by @hmbashar.
6 days ago
#2
Adds unit tests for the Toolbar (Admin Bar) edit, Edit Site and appearance menus in tests/phpunit/tests/adminbar.php. This is the second group of the test coverage work proposed in the ticket, and is independent from the first group in #15521. No behavior is changed.
Functions covered:
wp_admin_bar_edit_menu()- Front end: the "Edit" link for the queried post, page, term and user, including the title, URL and icon.
- Front end: no link without the edit capability, for post types hidden from the Toolbar, or when nothing is queried.
- Admin: "View Post" for a published post, "Preview" for a draft, nothing on the screen for adding a post, and "View Post" on the Comments screen for a single post.
- Admin: "View Category" for a publicly viewable term and nothing for a term that is not, and "View User" on the user edit screen.
wp_admin_bar_edit_site_menu()- "Edit Site" link and its URL for block themes.
- Not added for classic themes, for users who cannot edit theme options, or in the admin.
wp_admin_bar_appearance_menu()- The group is always added, with no items for users without theme capabilities.
- Themes link for users who can switch themes.
- Widgets, Menus, Background and Header links depending on the theme features.
Testing:
vendor/bin/phpunit --filter Tests_AdminBarvendor/bin/phpunit -c tests/phpunit/multisite.xml --filter Tests_AdminBarvendor/bin/phpcs tests/phpunit/tests/adminbar.php
I also temporarily broke the related lines in src/wp-includes/admin-bar.php (draft preview branch, edit_theme_options guard, Edit Site admin guard, publicly viewable term check, user view link) 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.
This ticket was mentioned in PR #15523 on WordPress/wordpress-develop by @hmbashar.
6 days ago
#3
Adds unit tests for the Toolbar (Admin Bar) comments, updates, search and recovery mode items in tests/phpunit/tests/adminbar.php. This is the third group of the test coverage work proposed in the ticket, and is independent from the other groups. No behavior is changed.
Functions covered:
wp_admin_bar_comments_menu()- Not added for users who cannot edit posts.
- Link, icon and the label for 0, 1 and several comments in moderation.
wp_admin_bar_updates_menu()- Not added when there are no updates, or for users who cannot update anything.
- Link, icon, total and singular/plural label.
- The total includes plugin updates for users who can update plugins.
wp_admin_bar_search_menu()- Form markup and node settings on the front end.
- Also added for users without capabilities.
- The form action is escaped.
- Not added in the admin.
wp_admin_bar_recovery_mode_menu()- Not added when recovery mode is inactive.
- "Exit Recovery Mode" link with the nonce when it is active.
Testing:
vendor/bin/phpunit --filter Tests_AdminBarvendor/bin/phpunit -c tests/phpunit/multisite.xml --filter Tests_AdminBarvendor/bin/phpcs tests/phpunit/tests/adminbar.php
I also temporarily broke the related lines in src/wp-includes/admin-bar.php (comments capability guard, no updates guard, updates URL, search admin guard, search action escaping, recovery mode guard) 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.
This ticket was mentioned in PR #15524 on WordPress/wordpress-develop by @hmbashar.
6 days ago
#4
Adds unit tests for how the Toolbar (Admin Bar) is rendered, styled and shown. This is the fourth group of the test coverage work proposed in the ticket, and is independent from the other groups. No behavior is changed.
Functions covered, in tests/phpunit/tests/adminbar.php:
wp_admin_bar_add_secondary_groups()- The
top-secondaryandwp-logo-externalgroups, their parent and CSS classes, both when called directly and in the standard Toolbar.
- The
wp_enqueue_admin_bar_header_styles()- The print style that hides the Toolbar, on the front end and in the admin, and the removal of the legacy
wp_admin_bar_headeraction. - Nothing is added when the legacy action was unhooked.
- The print style that hides the Toolbar, on the front end and in the admin, and the removal of the legacy
wp_enqueue_admin_bar_bump_styles()- The inline styles that make room for the Toolbar, and the removal of the legacy callback.
- Nothing is added when the legacy callback was unhooked, or when the theme provides its own callback.
_get_admin_bar_pref()- Defaults to showing the Toolbar when no preference is stored.
- Stored
trueandfalsevalues, the preference of a given user, and the preference of each context.
And in a new file, tests/phpunit/tests/general/wpAdminBarRender.php:
wp_admin_bar_render()- Nothing is rendered, and no action fires, when the Toolbar is hidden or there is no Toolbar object.
- The Toolbar is rendered once, between
admin_bar_menu,wp_before_admin_bar_renderandwp_after_admin_bar_render.
The wp_admin_bar_render() function remembers that it already rendered the Toolbar in a static variable, so these tests run in a separate process. They are in their own file because a separate process also runs the fixtures clean up of its class, which would remove the users shared by the other tests in adminbar.php.
The tests that add inline styles use a fresh WP_Styles instance, which is restored afterwards, so styles added by one test are not visible to the next.
Testing:
vendor/bin/phpunit --filter 'Tests_AdminBar|Tests_General_WpAdminBarRender'vendor/bin/phpunit -c tests/phpunit/multisite.xml --filter 'Tests_AdminBar|Tests_General_WpAdminBarRender'vendor/bin/phpcs tests/phpunit/tests/adminbar.php tests/phpunit/tests/general/wpAdminBarRender.php
I also temporarily broke the related lines in src/wp-includes/admin-bar.php (render guards and rendered flag, print style, custom callback check, preference default and user argument, secondary group ID) 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.
This ticket was mentioned in PR #15525 on WordPress/wordpress-develop by @hmbashar.
6 days ago
#5
Adds unit tests for the Toolbar (Admin Bar) icon helper, sidebar toggle and command palette button in tests/phpunit/tests/adminbar.php. This is the last group of the test coverage work proposed in the ticket, and is independent from the other groups. No behavior is changed.
Functions covered:
_wp_admin_bar_icon()- Wraps the SVG of a registered icon in the
ab-icon svg-iconelement. - Returns an empty string for an icon that is not registered.
- Wraps the SVG of a registered icon in the
wp_admin_bar_sidebar_toggle()- Added in the admin, with its icon, URL and hidden label.
- Not added on the front end.
wp_admin_bar_command_palette_menu()- Added in the admin when the
wp-core-commandsscript is enqueued: icon, URL,onclick, class, label and inline script. - The
Ctrl+Klabel by default and the⌘Klabel for an Apple user agent. - Not added when the script is not enqueued, or on the front end.
- Added in the admin when the
The tests that depend on the enqueued scripts use a fresh WP_Scripts instance, which is restored afterwards, and the user agent is restored too.
Testing:
vendor/bin/phpunit --filter Tests_AdminBarvendor/bin/phpunit -c tests/phpunit/multisite.xml --filter Tests_AdminBarvendor/bin/phpcs tests/phpunit/tests/adminbar.php
I also temporarily broke the related lines in src/wp-includes/admin-bar.php (sidebar toggle admin guard, command palette script and admin guards, Apple user agent detection, icon empty check and wrapper class) 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.
This ticket was mentioned in PR #15526 on WordPress/wordpress-develop by @hmbashar.
6 days ago
#6
Adds unit tests for the Toolbar (Admin Bar) New and Customize menus, and for when the Toolbar is showing, in tests/phpunit/tests/adminbar.php. These functions only had a little coverage. This is an additional group for the test coverage work in the ticket, and is independent from the other PRs. No behavior is changed.
Functions covered:
wp_admin_bar_new_content_menu()- The New menu node, and the items an editor, a contributor and a subscriber can create.
- The menu links to the first item.
- Custom post types: shown in the Toolbar, hidden from the Toolbar, without the create capability, and the post type named
content, which would clash with the parent node. - The Site item on multisite for super admins only, and no Site item on single site.
wp_admin_bar_customize_menu()- The link for the current URL, its icon and class, and the Customizer support script.
- Not added without the
customizecapability or in the admin. - Block themes: only added when a plugin uses the Customizer.
is_admin_bar_showing()andshow_admin_bar()- Logged-out visitors, the default for logged-in users, and the user preference.
- Always showing in the admin, but not on the login screen, for JSON requests or in embeds.
- The
show_admin_barfilter and theshow_admin_bar()function, which overrides the user preference.
_wp_admin_bar_init()- Not set up when the Toolbar is not showing.
- Sets up the Toolbar and its default menus.
- The
wp_admin_bar_classfilter, including a class that does not exist.
Testing:
vendor/bin/phpunit --filter Tests_AdminBarvendor/bin/phpunit -c tests/phpunit/multisite.xml --filter Tests_AdminBarvendor/bin/phpcs tests/phpunit/tests/adminbar.php
I also temporarily broke the related lines in src/wp-includes/admin-bar.php (the capability, custom post type, content clash and empty menu checks, the Site item check, the Customize guards, each of the is_admin_bar_showing() guards, the boolean cast, and the _wp_admin_bar_init() checks) 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.
#7
@
5 days ago
Thanks for the PRs! Having 6 separate PRs for the same test file makes this harder to review. Having said that, I asked Claude to review the 6 PRs attached to this ticket. Below are the findings:
Review: #66491 — Toolbar: improve unit test coverage for admin-bar.php
Reviewed 2026-11-06. The six PRs on this ticket are PR #15521, PR #15522, PR #15523, PR #15524, PR #15525 and PR #15526. Together they add about 2,550 lines, almost all to tests/phpunit/tests/adminbar.php. PR #15524 also adds tests/phpunit/tests/general/wpAdminBarRender.php.
How this was verified
- Each PR applies cleanly to current trunk. All six PRs are based on the same blob of
adminbar.php(22c3328582616). - All six also stack on top of each other with no conflicts and no duplicate method names, in order 15521 → 15526 using
git apply --3way. - Results with all six applied together:
- Single site:
npm run test:php -- --filter 'Tests_AdminBar|Tests_General_WpAdminBarRender'gave OK (150 tests, 590 assertions). - Multisite:
-c tests/phpunit/multisite.xmlgave OK (181 tests, 767 assertions). --order-by=random: 2 single-site runs and 1 multisite run all passed, so no order dependence was found.
- Single site:
- I also wrote scratch tests to check specific claims below. They're marked "verified" where they appear. The working tree was restored afterwards.
Cross-cutting notes (apply to all six)
1. One ticket, six PRs. All six change the same file for the same ticket. A committer will have to merge them into one commit anyway, and reviewers have to switch between six PRs to get a picture of the file. I recommend asking for a single combined PR, or at least one branch that stacks all six, before committing. The six-way split also means the PRs restore global state in different ways (next point).
2. Global state is restored in different ways.
- PR #15523 uses
try/finally(recovery mode). - PR #15524 uses a
tear_down()hook ($wp_styles). - PR #15522, PR #15525 and PR #15526 restore state inline, after building the toolbar but before the assertions (
$_wp_theme_features,$wp_scripts,$_SERVER['HTTP_USER_AGENT'],switch_theme()).
The inline style is fine when assertions fail, because the restore has already run. If get_standard_admin_bar() throws, though, the state leaks into the rest of the class. $_wp_theme_features is a particular risk because WP_UnitTestCase_Base::tear_down() does not reset it. Pick one pattern (save in the test, restore in tear_down()) and use it everywhere.
3. Some cleanup duplicates what the test framework already does.
WP_UnitTestCase_Base::set_up()already callsreset_post_types()andreset_taxonomies(). That makes theunregister_post_type()andunregister_taxonomy()calls unnecessary.tear_down()already sets$GLOBALS['post']to null, so theunset( $GLOBALS['post'] )calls are unnecessary too.
It's harmless, but it adds noise. Not all of the cleanup is redundant: $tag, $user_id, $pagenow, HTTP_USER_AGENT and HTTP_ACCEPT are not reset by the framework (tests_reset__SERVER() only resets the HOST, REQUEST_* and SERVER_* keys), so restoring those is correct.
4. Some expected values are computed the same way the code under test computes them. Several assertions build the expected value with the same calls the implementation makes, so the test can't catch a change in what those calls produce. Examples: esc_url( home_url( '/' ) ) in the search test, the wp_nonce_url( add_query_arg( ... ) ) chain in the recovery-mode test, and wp_get_icon( $name ) in the icon test. Specific fixes are listed under each PR.
5. Overlap with existing tests. Three new tests largely repeat existing ones. They're called out under PR #15521, PR #15522 and PR #15526.
6. Out of scope, but found while reviewing (verified): a core bug. With add_theme_support( 'admin-bar' ) and no arguments, get_theme_support( 'admin-bar' ) returns true. Then $admin_bar_args[0]['callback'] raises "Trying to access array offset on value of type bool". This happens in two places:
src/wp-includes/admin-bar.php:1428(wp_enqueue_admin_bar_bump_styles())src/wp-includes/class-wp-admin-bar.php:63(WP_Admin_Bar::initialize())
I confirmed it with a scratch test. It's worth searching Trac for an existing ticket and opening one if none exists. None of these PRs exercise this path.
PR #15521 — My Account and My Sites menus
Verdict: Good. No blocking issues; the suggestions are optional.
Where (PR's adminbar.php) | Finding | Suggestion |
|---|---|---|
L1337 test_my_sites_menu_network_admin_items_have_expected_urls() | Mostly repeats the existing test_my_sites_network_menu_for_super_admin() (trunk L757), which already checks that each network-admin-* node exists, using data_my_sites_network_menu_items(). The only new checks are the hrefs, the parents, and the ab-sub-secondary class. | Add an expected-URL column to data_my_sites_network_menu_items() and assert the href in the existing test. Keep only the ab-sub-secondary class assertion as a new test.
|
L1173 test_my_sites_menu_is_not_added_for_user_without_sites() | Covers only one half of the guard count( $wp_admin_bar->user->blogs ) < 1 && ! current_user_can( 'manage_network' ) (admin-bar.php:621). The fallback $my_sites_url = admin_url( 'my-sites.php' ) when active_blog is empty (admin-bar.php:625-629) is not covered at all. | Add a test where a super admin who belongs to no sites still gets the my-sites node, with href === admin_url( 'my-sites.php' ).
|
L1380, L1404 (create_upload_object()) | Upload files are left in the uploads directory after each test. The existing site-icon tests do the same (trunk L837, L855), so this follows the file's convention. | Optional: call wp_delete_attachment( $attachment_id, true ) at the end, or $this->remove_added_uploads() in tear_down().
|
PR #15522 — Edit, Edit Site and Appearance menus
Verdict: Good coverage of wp_admin_bar_edit_menu(). The state handling needs tidying.
| Where | Finding | Suggestion |
|---|---|---|
L1265, L1295, L1321, L1347, L1382 ($_wp_theme_features tests) | The tests save $_wp_theme_features and restore it inline (L1278, L1308, L1333, L1360, L1393). The framework doesn't reset this global, so an exception from get_standard_admin_bar() would leak theme features into every later test in the class. | Save it in each test and restore it in tear_down(), or wrap the code in try/finally as PR #15523 does. Bypassing remove_theme_support() is correct here: _remove_theme_support() touches the custom-header/custom-background globals, which was the bug fixed in commit 69f9b3be.
|
L1122, L1160, L1181, L1202 (switch_theme()) | Same pattern for the theme: switch, build the toolbar, switch back, then assert. | Same fix. switch_theme( 'default' ) at L1162 can also go, because the test environment's theme is already default (WP_DEFAULT_THEME).
|
L1382 test_appearance_menu_excludes_background_and_header_when_theme_does_not_support_them() | $has_nodes combines two null !== checks with a logical OR (L1391), followed by assertFalse( $has_nodes ). On failure this only reports "false is not true", not which node exists. | Use two assertNull() calls, as the sibling tests do.
|
L745 test_edit_menu_on_front_end_links_to_edit_screen_for_queried_post() | Covers more than the existing test_admin_bar_has_edit_link_for_existing_posts() (trunk L350), which only checks that the node is not null. | Fine to keep. Consider deleting the older test or adding a reference to it in the docblock. |
| L762, L787, L819, and the term/user variants | Set $GLOBALS['wp_the_query']->queried_object directly. The existing tests do the same, so this is consistent. | Optional: $this->go_to( get_permalink( $post_id ) ), go_to( get_term_link( $term ) ) and go_to( get_author_posts_url( $id ) ) would run the real query path.
|
| L824, L1087, L952, L984, L1010 | Redundant cleanup, as described in cross-cutting note 3. | Remove unregister_post_type(), unregister_taxonomy() and unset( $GLOBALS['post'] ). Keep the unset() calls for $tag and $user_id.
|
L1122 test_edit_site_menu_links_to_site_editor_for_block_theme() | The case where $_wp_current_template_id is unset isn't covered. add_query_arg() drops the null postId. | Optional: add an assertion that the URL has no postId when the global is unset.
|
PR #15523 — Comments, Updates, Search and Recovery Mode
Verdict: Solid. A few assertions compute their expected value the same way the code does and could be made stronger.
| Where | Finding | Suggestion |
|---|---|---|
L741 wp_cache_delete( 'comments-0', 'counts' ) in test_comments_menu_shows_number_of_comments_in_moderation() | Unneeded (verified). I removed the line and its comment and all three data sets still pass. Inserting a comment calls wp_update_comment_count_now(), which already deletes this key (src/wp-includes/comment.php:3235). clean_up_global_scope() also flushes the cache before every test. The comment "counted per request" is wrong. | Remove both lines. |
| L729 same test | Creates real comments, which is slow, and can't practically cover large counts. The label uses number_format_i18n() while the class uses the raw integer (admin-bar.php:1187), and nothing checks that difference. | Short-circuit with the wp_count_comments filter (return (object) array( 'moderated' => 1234, ... )). Then add a data set asserting count-1234 in the class and 1,234 in the label.
|
L822 data_updates_menu_totals() | number_format_i18n() in the label and screen-reader text (admin-bar.php:1299-1302) is never tested with a number that gets formatted. | Add 'thousands' => array( 1234, '1,234 updates available' ), and change the label assertion at L813 to use number_format_i18n( $total ).
|
L875 test_updates_menu_is_not_added_for_users_who_cannot_update() | Exercises the capability checks inside wp_get_update_data(). wp_admin_bar_updates_menu() itself has only the ! total guard (admin-bar.php:1292), which L773 already covers. | Keep it as an integration test, but add @covers ::wp_get_update_data, or drop it.
|
L959 test_search_menu_escapes_form_action() | The second assertion computes its expected value with esc_url( home_url( '/' ) ), the same function the code under test uses. | Assert the literal instead: action="http://example.org/?foo=bar&baz=script". I confirmed this is the exact output of esc_url() for this input.
|
L1015 test_recovery_mode_menu_links_to_exit_action_when_recovery_mode_is_active() | The expected URL (L1034-1035) repeats the implementation's add_query_arg() + wp_nonce_url() chain exactly. The test also depends on the private property WP_Recovery_Mode::$is_active through reflection (L1018). There's no public way to set it, so this is acceptable given the finally. | Check behaviour instead of rebuilding the string. html_entity_decode() the href first (the real value is ...wp-login.php?action=exit_recovery_mode&_wpnonce=..., verified). Then use wp_parse_url() and wp_parse_str(), and assert the path ends with wp-login.php, action === WP_Recovery_Mode::EXIT_ACTION, and wp_verify_nonce( $nonce, WP_Recovery_Mode::EXIT_ACTION ).
|
| L999 / L1004 | assertFalse( wp_is_recovery_mode() ) is a precondition, but it runs after the toolbar is built. | Move it above get_standard_admin_bar().
|
PR #15524 — Rendering, header/bump styles and _get_admin_bar_pref()
Verdict: Useful coverage. The new file is in the wrong place, and the styles restore helper is more complicated than it needs to be.
| Where | Finding | Suggestion |
|---|---|---|
tests/phpunit/tests/general/wpAdminBarRender.php (new file), @group general | tests/general/ holds tests for general-template.php. wp_admin_bar_render() is in admin-bar.php. | Move it to tests/phpunit/tests/adminbar/wpAdminBarRender.php (class Tests_AdminBar_WpAdminBarRender) and drop @group general.
|
wpAdminBarRender.php, three @runInSeparateProcess tests | Process isolation is justified: the static $rendered flag in wp_admin_bar_render() (admin-bar.php:75) would otherwise make the two negative tests pass for the wrong reason if an earlier test had rendered the toolbar. It does cost three PHP bootstraps. | No change needed. A docblock sentence explaining why the negative tests also need isolation would help. |
wpAdminBarRender.php L60, L87, L128, L148 | ob_start() / ob_get_clean() | Use the get_echo( 'wp_admin_bar_render' ) helper.
|
adminbar.php L22 $saved_styles, L37 tear_down(), L51 use_fresh_styles() | The property wraps the value in an array so that "saved null" and "not saved" look different. It's documented as @var array but holds WP_Styles|null. PR #15525 needs the same thing for $wp_scripts and does it inline instead. | Use two plain properties, e.g. private $original_wp_styles; private $wp_styles_replaced = false;. Better still, add one use_fresh_scripts()/use_fresh_styles() pair that both PRs share, restored in tear_down().
|
L991 test_enqueue_admin_bar_bump_styles_does_nothing_when_theme_uses_custom_callback() | global $_wp_theme_features; comes after $this->use_fresh_styles();, and $_wp_theme_features is restored inline (L1002). | Put the global first and restore in tear_down() (cross-cutting note 2).
|
wp_enqueue_admin_bar_bump_styles() coverage | Two paths are missing: theme support with an explicit 'callback' => '_admin_bar_bump_cb' (passes through admin-bar.php:1426-1435), and argument-less add_theme_support( 'admin-bar' ), which hits the PHP warning in cross-cutting note 6. | Add the explicit-callback case now. The argument-less case belongs with the bug fix. |
L863 assertEmpty( $node_secondary->parent ) | parent is false, not just empty. | assertFalse(). The same applies to PR #15526 L825.
|
L1038 data_get_admin_bar_pref_stored_values() | Only 'true' and 'false' are tested. The strict 'true' === $pref check (admin-bar.php:1540) isn't pinned down. | Add 'unexpected value' => array( '1', false ).
|
PR #15525 — _wp_admin_bar_icon(), sidebar toggle and command palette
Verdict: Fine, but there's repeated setup to pull out and one test that does more than it needs to.
| Where | Finding | Suggestion |
|---|---|---|
L433, L475, L529 wp_register_script( 'wp-core-commands', false ) | Does nothing. wp-core-commands is a default package script (src/wp-includes/assets/script-loader-packages.php:245). Once $wp_scripts is set to null, wp_scripts() creates a new instance and the default scripts register it again, so wp_register_script() returns false. Only the wp_enqueue_script() call matters. | Remove the wp_register_script() lines.
|
| L427-466, L469-500, L502-523, L525-546 | The same save/null/restore code for $GLOBALS['wp_scripts'] (and for $_SERVER['HTTP_USER_AGENT']) appears four times. | Pull it into a shared helper and restore in tear_down(), shared with PR #15524's styles helper. Restoring HTTP_USER_AGENT is needed, because tests_reset__SERVER() doesn't reset it.
|
L354 test_admin_bar_icon_wraps_registered_icon() | Registers a made-up icon in the core-admin/ namespace through WP_Icons_Registry::register() and unregisters it afterwards. That's unnecessary and ties the test to the registry's API. The expected value also calls wp_get_icon( $name ), the same function the code under test calls. | Use a core icon, as the existing test_icon_is_kept_when_node_is_updated() does: assertSame( '<span class="ab-icon svg-icon" aria-hidden="true">' . wp_get_icon( 'core-admin/plus' ) . '</span>', _wp_admin_bar_icon( 'core-admin/plus' ) ).
|
L469 test_command_palette_menu_shows_apple_shortcut_for_apple_user_agent() | Only one user agent is tested. The pattern Macintosh|Mac OS X|Mac_PowerPC is case-insensitive, and there's a fallback $_SERVER['HTTP_USER_AGENT'] ?? '' (admin-bar.php:1026-1027). | Turn it into a data provider: Macintosh, Mac OS X, Mac_PowerPC, lower-case macintosh (expects ⌘K), Windows (expects Ctrl+K), and HTTP_USER_AGENT unset (expects Ctrl+K with no warning).
|
| L427 inline script assertions | Only <script and sourceURL= are checked. | Optional: also assert that the JSON-encoded Apple pattern and label are passed to the script. |
PR #15526 — New and Customize menus, is_admin_bar_showing(), show_admin_bar() and _wp_admin_bar_init()
Verdict: The largest PR. It has the most overlap with existing tests and leaves out the most branches.
| Where | Finding | Suggestion |
|---|---|---|
L807 test_new_content_menu_avoids_clash_for_custom_post_type_named_content() | Duplicates the existing test_content_post_type() (trunk L42, ticket #21117), which already checks the new-content parent and the add-new-content node. The only new check is the href. | Drop it and add the href assertion to test_content_post_type().
|
L649 / L659 test_new_content_menu_lists_items_the_user_can_create() | The assertion labelled "The menu should link to the first item" can't tell admin_url( array_key_first( $actions ) ) (admin-bar.php:1135) apart from a hard-coded 'post-new.php', because Post is always first for an editor. | Add a case where Post isn't first. For example, a user who can only upload_files, by denying create_posts through a map_meta_cap filter, should get href === admin_url( 'media-new.php' ).
|
wp_admin_bar_new_content_menu() coverage | The new-link branch (admin-bar.php:1096-1098) is untested. manage_links maps to do_not_allow unless link_manager_enabled is set (capabilities.php:691-697). | Add a test with update_option( 'link_manager_enabled', 1 ) and an administrator, expecting the new-link node with admin_url( 'link-add.php' ).
|
wp_admin_bar_customize_menu() coverage | The one non-trivial branch is still untested: a user who can customize but can't edit the customize_changeset post being previewed (admin-bar.php:577-581). The existing test_customize_link() (trunk L706) only covers the success case. | Add a test that builds a changeset owned by another user, removes edit_post for the current user, and asserts there's no customize node.
|
L1483, L1514, L1533, L1553, L1572, L1595 $GLOBALS['wp_customize'] = null | Repeated six times because the existing test_customize_link() leaves a WP_Customize_Manager in the global. | Reset $wp_customize once in tear_down(), or make test_customize_link() clean up after itself, and remove the six lines.
|
L1485, L1516, L1535, L1555 switch_theme( 'default' ) | Does nothing useful, since the test environment already runs default. It still writes options and fires the switch_theme hooks. Nothing switches back, unlike the block-theme tests. | Remove. |
L1501 strtok( $node_customize->href, '?' ) | $parsed_url is already computed two lines earlier. | assertStringStartsWith( wp_customize_url() . '?', $node_customize->href ), or compare the $parsed_url parts.
|
L738, L767, L795, L822 unregister_post_type() | Redundant, as described in cross-cutting note 3. | Remove. |
L1847 get_class( new class() extends WP_Admin_Bar {} ) | Works (it passes), but anonymous class names contain a NUL byte and the line is hard to read. | Optional: a small named test class, e.g. class Tests_AdminBar_Custom_Class extends WP_Admin_Bar {} in tests/phpunit/includes/, or at the bottom of the file.
|
L825 assertEmpty( $node_new_content->parent ) | Same as PR #15524 L863. | assertFalse().
|
is_admin_bar_showing() tests (L1617-L1791) | Good coverage of the guards that can be tested without separate processes. XMLRPC_REQUEST, DOING_AJAX and IFRAME_REQUEST are constants and reasonably left out. One behaviour isn't documented: the result is cached in the $show_admin_bar global, which is why set_up() unsets it. | Optional: add a test showing that changing the user preference after the first call has no effect until the global is cleared. |
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
Adds unit tests for the Toolbar (Admin Bar) My Account and My Sites menus in
tests/phpunit/tests/adminbar.php. This is the first group of the test coverage work proposed in the ticket. No behavior is changed.Functions covered:
wp_admin_bar_my_account_item()andwp_admin_bar_my_account_menu()my-account,user-actions,user-infoandlogout.tabindex, with and without a profile link.show_avatars.wp_admin_bar_my_sites_menu()readcapability: links to the front end and only offers "Visit Site".www.) when the name is empty.wp_admin_bar_show_site_iconsfilter.Testing:
vendor/bin/phpunit --filter Tests_AdminBarvendor/bin/phpunit -c tests/phpunit/multisite.xml --filter Tests_AdminBarvendor/bin/phpcs tests/phpunit/tests/adminbar.phpI also temporarily broke the related lines in
src/wp-includes/admin-bar.php(avatar class, logged-out guard, no-sites guard,readcapability branch, site name fallback, site icon filter, secondary class) 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: Drafting the tests and running them. The tests and this description should be reviewed and edited by the author before the PR is marked ready for review.