Skip to content

Tests: Add unit test coverage for activate_plugin() - #14601

Open
huzaifaalmesbah wants to merge 3 commits into
WordPress:trunkfrom
huzaifaalmesbah:tests/activate-plugin
Open

huzaifaalmesbah wants to merge 3 commits into
WordPress:trunkfrom
huzaifaalmesbah:tests/activate-plugin

Conversation

@huzaifaalmesbah

Copy link
Copy Markdown
Member

Description

Adds tests for activate_plugin(). The existing tests only call it through activate_plugins() for a single plugin; its validation, hooks, redirect, output check and network activation had no direct tests.

The tests create a temporary plugin for each test (a plugin file is only loaded once per process), stop the redirect through the wp_redirect filter, and restore $_GET. They cover:

  • plugin_not_found for a plugin that is not installed, and plugin_php_incompatible for unmet requirements, without changing the active plugins;
  • the plugin being added to the sorted active plugins, and activate_plugin, activate_{$plugin} and activated_plugin firing in order with their arguments;
  • a full path with surrounding whitespace being reduced to the plugin basename;
  • no hooks in silent mode;
  • nothing happening for a plugin that is already active, including no redirect;
  • unexpected_output with the output as error data when loading the plugin prints something, while the plugin stays activated;
  • the redirect to the error URL with an _error_nonce;
  • on multisite, network-wide activation (with $_GET['networkwide']), a network-only plugin always being activated network-wide, and a network-active plugin keeping its activation time.

Removing or changing each branch of the function makes at least one test fail on single site or multisite.

One case is left out on multisite: activate_plugin() calls is_network_only_plugin() before validate_plugin(), so a plugin that is not installed raises a file_get_contents() warning before the plugin_not_found error is returned. That can be handled in its own ticket.

This is a test-only change; no production code is modified.

Testing Instructions

  1. Run the tests on single site:
    npm run test:php -- --filter Tests_Admin_Includes_Plugin_ActivatePlugin
  2. Run them on multisite:
    npm run test:php -- --filter Tests_Admin_Includes_Plugin_ActivatePlugin -c tests/phpunit/multisite.xml
  3. Run them in random order:
    npm run test:php -- --filter Tests_Admin_Includes_Plugin_ActivatePlugin --order-by=random
  4. Run the plugins group:
    npm run test:php -- --group plugins
  5. Run PHPCS on the test file:
    node ./tools/local-env/scripts/docker.js run --rm php ./vendor/bin/phpcs tests/phpunit/tests/admin/includes/plugin/activatePlugin.php

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

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: Brainstorming edge-case scenarios and drafting test boilerplate; test architecture, assertions, and local PHPUnit verification were written and validated by me.

@huzaifaalmesbah
huzaifaalmesbah marked this pull request as ready for review October 21, 2026 03:29
@github-actions

github-actions Bot commented Oct 21, 2026 •

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 huzaifaalmesbah, mukesh27.

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

@mukeshpanchal27 mukeshpanchal27 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The assertions match the source, and CI passes. One note about fixture cleanup inline.

private function create_plugin( $headers = '', $code = '' ) {
$dir = WP_PLUGIN_DIR . '/' . $this->slug;

$this->assertTrue( mkdir( $dir ), 'The test plugin directory should be created.' );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In core tests, WP_PLUGIN_DIR is tests/phpunit/data/plugins, which is a tracked directory. If a run stops partway, such as on a fatal error or Ctrl+C, tear_down() never runs and this fixture folder stays there. The slug comes from a counter that starts at 1 again on the next run, so mkdir() fails on the same folder name. So every test in the class fails here until someone deletes the folder by hand. The leftover also shows up in git status.

Could this helper, or set_up(), remove a leftover folder first? #14600 already does this: its remove_plugin() helper runs in both set_up() and tear_down().

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, thanks! Added a remove_plugin() helper that clears a leftover folder before mkdir() and in tear_down(), in b888f06. I checked it with a leftover folder in place: the old code failed and the new code passes.

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