Skip to content

Tests: Add unit test coverage for deactivate_plugins() - #14605

Open
huzaifaalmesbah wants to merge 2 commits into
WordPress:trunkfrom
huzaifaalmesbah:tests/deactivate-plugins
Open

huzaifaalmesbah wants to merge 2 commits into
WordPress:trunkfrom
huzaifaalmesbah:tests/deactivate-plugins

Conversation

@huzaifaalmesbah

Copy link
Copy Markdown
Member

Description

Adds tests for deactivate_plugins(). The function is mostly used as cleanup in other tests; only multisite/network.php checks it, by counting the deactivated_plugin hook for a network-active plugin. Its handling of several plugins, paths, inactive plugins and the $network_wide argument had no tests.

The tests set the active plugins options directly and record the deactivation hooks. They cover:

  • several plugins being deactivated while the others stay active, with deactivate_plugin, deactivate_{$plugin} and deactivated_plugin firing in order for each;
  • a single plugin passed as a full path with surrounding whitespace;
  • inactive plugins being skipped without hooks or an option update;
  • no hooks in silent mode;
  • on multisite, a network-active plugin being deactivated network-wide and on the site by default, with the hooks receiving true;
  • only the network activation being removed when deactivating network-wide, and a plugin that is only active on the site being kept and not reported as deactivated;
  • the network activation being kept when deactivating on the site only.

Removing or changing each branch of the function makes at least one test fail on single site or multisite. The recovery mode branch is left out.

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_DeactivatePlugins
  2. Run them on multisite:
    npm run test:php -- --filter Tests_Admin_Includes_Plugin_DeactivatePlugins -c tests/phpunit/multisite.xml
  3. Run them in random order:
    npm run test:php -- --filter Tests_Admin_Includes_Plugin_DeactivatePlugins --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/deactivatePlugins.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 04:27
@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 deactivate_plugins(), and CI passes. One suggestion inline.

deactivate_plugins( 'a/a.php', false, true );

$this->assertSame( array( 'a/a.php', 'b/b.php', 'c.php' ), get_option( 'active_plugins' ), 'The site activation should be kept.' );
$this->assertNotContains( 'deactivated_plugin', array_column( $this->calls, 0 ), 'The plugin should not be reported as deactivated.' );

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.

Core has a quirk on this path. With $network_wide = true and a plugin that is active only on the site, deactivate_plugins() still fires deactivate_plugin. It then hits continue before deactivate_{$plugin} and deactivated_plugin, so nothing is deactivated. This test only checks that deactivated_plugin does not fire, so the misleading first hook goes unrecorded.

Could the test assert the full list of calls instead? Then the current behavior is written down, and any change to it shows up in the test:

$this->assertSame(
	array( array( 'deactivate_plugin', array( 'a/a.php', false ) ) ),
	$this->calls,
	'Only deactivate_plugin should fire, although the plugin stays active.'
);

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.

Agreed, thanks! The test now asserts the full list of calls, so the deactivate_plugin call is recorded, in 90231f6.

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