From 6c18c86726fd06252dedaf1609fe37fef29288ae Mon Sep 17 00:00:00 2001 From: kagg-design Date: Sun, 3 Nov 2024 20:17:26 +0200 Subject: [PATCH] Fix Integrations tests. --- .tests/php/unit/Settings/IntegrationsTest.php | 157 ++++++++++++------ src/php/Settings/Integrations.php | 47 ++++-- 2 files changed, 146 insertions(+), 58 deletions(-) diff --git a/.tests/php/unit/Settings/IntegrationsTest.php b/.tests/php/unit/Settings/IntegrationsTest.php index 892bba1f..187ff381 100644 --- a/.tests/php/unit/Settings/IntegrationsTest.php +++ b/.tests/php/unit/Settings/IntegrationsTest.php @@ -110,21 +110,6 @@ public function test_init_hooks(): void { $subject->$method(); } - /** - * Test activated_plugin_action(). - * - * @return void - */ - public function test_activated_plugin_action(): void { - $subject = Mockery::mock( Integrations::class )->makePartial(); - - WP_Mock::userFunction( 'remove_action' ) - ->with( 'activated_plugin', 'Brizy_Admin_GettingStarted::redirectAfterActivation' ) - ->once(); - - $subject->activated_plugin_action(); - } - /** * Test init_form_fields(). * @@ -592,12 +577,12 @@ static function ( $type, $var_name, $filter ) use ( $activate, $entity, $new_the } /** - * Test process_plugins() with activation. + * Test process_plugins() with activation when success. * * @noinspection PhpConditionAlreadyCheckedInspection * @throws ReflectionException ReflectionException. */ - public function test_process_activate_plugins(): void { + public function test_process_activate_plugins_success(): void { $activate = true; $plugins = [ 'acf-extended-pro/acf-extended.php', 'acf-extended/acf-extended.php' ]; $plugin_name = 'ACF Extended'; @@ -609,31 +594,83 @@ public function test_process_activate_plugins(): void { $this->set_protected_property( $subject, 'entity', 'plugin' ); $subject->shouldAllowMockingProtectedMethods(); - $subject->shouldReceive( 'activate_plugins' )->with( $plugins )->once()->andReturn( false ); + $subject->shouldReceive( 'activate_plugins' )->with( $plugins )->once()->andReturn( true ); $subject->shouldReceive( 'plugin_names_from_tree' ) ->with( $plugins_tree )->once()->andReturn( [ $plugin_name ] ); $subject->shouldReceive( 'get_activation_stati' )->with()->andReturn( $activation_stati ); - WP_Mock::userFunction( 'wp_send_json_error' ) + WP_Mock::userFunction( 'wp_send_json_success' ) ->with( [ - 'message' => 'Error activating ACF Extended plugin.', + 'message' => 'ACF Extended plugin is activated.', 'stati' => $activation_stati, ] - )->once(); - WP_Mock::userFunction( 'wp_send_json_success' ) + ) + ->once(); + + $subject->process_plugins( $activate, $plugins, $plugin_name ); + } + + /** + * Test process_plugins() with activation when already activated. + * + * @noinspection PhpConditionAlreadyCheckedInspection + * @throws ReflectionException ReflectionException. + */ + public function test_process_activate_plugins_already_activated(): void { + $activate = true; + $plugins = [ 'acf-extended-pro/acf-extended.php', 'acf-extended/acf-extended.php' ]; + $plugin_name = 'ACF Extended'; + $plugins_tree = [ 'acf-extended-pro/acf-extended.php' => [] ]; + $activation_stati = []; + + $subject = Mockery::mock( Integrations::class )->makePartial(); + $this->set_protected_property( $subject, 'plugins_tree', $plugins_tree ); + $this->set_protected_property( $subject, 'entity', 'plugin' ); + + $subject->shouldAllowMockingProtectedMethods(); + $subject->shouldReceive( 'activate_plugins' )->with( $plugins )->once()->andReturn( true ); + $subject->shouldReceive( 'plugin_names_from_tree' ) + ->with( $plugins_tree )->once()->andReturn( [] ); + $subject->shouldReceive( 'get_activation_stati' )->with()->andReturn( $activation_stati ); + + WP_Mock::userFunction( 'wp_send_json_error' ) ->with( [ - 'message' => 'ACF Extended plugin is activated.', + 'message' => 'Error activating ACF Extended plugin.', 'stati' => $activation_stati, ] ) ->once(); - WP_Mock::userFunction( 'deactivate_plugins' )->with( $plugins )->once(); - WP_Mock::userFunction( 'wp_send_json_success' ) + + $subject->process_plugins( $activate, $plugins, $plugin_name ); + } + + /** + * Test process_plugins() with activation when error. + * + * @noinspection PhpConditionAlreadyCheckedInspection + * @throws ReflectionException ReflectionException. + */ + public function test_process_activate_plugins_error(): void { + $activate = true; + $plugins = [ 'acf-extended-pro/acf-extended.php', 'acf-extended/acf-extended.php' ]; + $plugin_name = 'ACF Extended'; + $plugins_tree = [ 'acf-extended-pro/acf-extended.php' => [] ]; + $activation_stati = []; + + $subject = Mockery::mock( Integrations::class )->makePartial(); + $this->set_protected_property( $subject, 'plugins_tree', $plugins_tree ); + $this->set_protected_property( $subject, 'entity', 'plugin' ); + + $subject->shouldAllowMockingProtectedMethods(); + $subject->shouldReceive( 'activate_plugins' )->with( $plugins )->once()->andReturn( false ); + $subject->shouldReceive( 'get_activation_stati' )->with()->andReturn( $activation_stati ); + + WP_Mock::userFunction( 'wp_send_json_error' ) ->with( [ - 'message' => 'ACF Extended plugin is deactivated.', + 'message' => 'Error activating ACF Extended plugin.', 'stati' => $activation_stati, ] )->once(); @@ -682,8 +719,9 @@ public function test_get_activation_stati(): void { * Test process_plugins() with deactivation. * * @noinspection PhpConditionAlreadyCheckedInspection + * @dataProvider dp_test_process_deactivate_plugins */ - public function test_process_deactivate_plugins(): void { + public function test_process_deactivate_plugins( $is_multisite, $is_network_wide ): void { $activate = false; $plugins = [ 'acf-extended-pro/acf-extended.php', 'acf-extended/acf-extended.php' ]; $plugin_name = 'ACF Extended'; @@ -695,9 +733,13 @@ public function test_process_deactivate_plugins(): void { $subject = Mockery::mock( Integrations::class )->makePartial(); $subject->shouldAllowMockingProtectedMethods(); + $subject->shouldReceive( 'is_network_wide' )->with()->andReturn( $is_network_wide ); $subject->shouldReceive( 'get_activation_stati' )->with()->once()->andReturn( $stati ); - WP_Mock::userFunction( 'deactivate_plugins' )->with( $plugins )->once(); + $network_wide = $is_multisite && $is_network_wide; + + WP_Mock::userFunction( 'is_multisite' )->with()->once()->andReturn( $is_multisite ); + WP_Mock::userFunction( 'deactivate_plugins' )->with( $plugins, true, $network_wide )->once(); WP_Mock::userFunction( 'wp_send_json_success' )->with( [ 'message' => 'ACF Extended plugin is deactivated.', @@ -708,6 +750,20 @@ public function test_process_deactivate_plugins(): void { $subject->process_plugins( $activate, $plugins, $plugin_name ); } + /** + * Data provider for test_process_deactivate_plugins(). + * + * @return array + */ + public function dp_test_process_deactivate_plugins(): array { + return [ + 'not multisite, not network wide' => [ false, false ], + 'multisite, not network wide' => [ true, false ], + 'not multisite, network wide' => [ false, true ], + 'multisite, network wide' => [ true, true ], + ]; + } + /** * Test process_theme(). * @@ -891,20 +947,22 @@ static function ( $thing ) { $wish_result = false === $wish_result ? $wp_error : $wish_result; $woo_result = false === $woo_result ? $wp_error : $woo_result; + $main = Mockery::mock( Main::class )->makePartial(); + + $main->shouldReceive( 'is_plugin_active' )->with( $wish_slug )->andReturn( false ); + $main->shouldReceive( 'is_plugin_active' )->with( $woo_slug )->andReturn( false ); + $subject = Mockery::mock( Integrations::class )->makePartial(); - $method = 'activate_plugins'; $subject->shouldAllowMockingProtectedMethods(); - $subject->shouldReceive( 'build_plugins_tree' ) ->with( $wish_slug )->once()->andReturn( $plugins_tree ); + $subject->shouldReceive( 'activate_plugin' )->with( $wish_slug )->andReturn( $wish_result ); + $subject->shouldReceive( 'activate_plugin' )->with( $woo_slug )->andReturn( $woo_result ); - WP_Mock::userFunction( 'is_plugin_active' )->with( $wish_slug )->andReturn( false ); - WP_Mock::userFunction( 'activate_plugin' )->with( $wish_slug )->andReturn( $wish_result ); - WP_Mock::userFunction( 'is_plugin_active' )->with( $woo_slug )->andReturn( false ); - WP_Mock::userFunction( 'activate_plugin' )->with( $woo_slug )->andReturn( $woo_result ); + WP_Mock::userFunction( 'hcaptcha' )->with()->andReturn( $main ); - self::assertSame( $expected, $subject->$method( [ $wish_slug ] ) ); + self::assertSame( $expected, $subject->activate_plugins( [ $wish_slug ] ) ); } /** @@ -922,41 +980,46 @@ public function dp_test_activate_plugins_with_plugins_tree(): array { } /** - * Test activate_plugin(). + * Test maybe_activate_plugin(). * * @return void */ - public function test_activate_plugin(): void { + public function test_maybe_activate_plugin(): void { $plugin = 'some-plugin/some-plugin.php'; + $main = Mockery::mock( Main::class )->makePartial(); + + $main->shouldReceive( 'is_plugin_active' )->with( $plugin )->once()->andReturn( false ); + $subject = Mockery::mock( Integrations::class )->makePartial(); $subject->shouldAllowMockingProtectedMethods(); + $subject->shouldReceive( 'activate_plugin' )->with( $plugin )->once()->andReturn( null ); - WP_Mock::expectActionAdded( 'activated_plugin', [ $subject, 'activated_plugin_action' ], PHP_INT_MIN ); - WP_Mock::userFunction( 'is_plugin_active' )->with( $plugin )->once()->andReturn( false ); - WP_Mock::userFunction( 'activate_plugin' )->with( $plugin )->once()->andReturn( true ); + WP_Mock::userFunction( 'hcaptcha' )->with()->once()->andReturn( $main ); - self::assertTrue( $subject->activate_plugin( $plugin ) ); + self::assertNull( $subject->maybe_activate_plugin( $plugin ) ); } /** - * Test activate_plugin() when plugin is active. + * Test maybe_activate_plugin() when plugin is active. * * @return void */ - public function test_activate_plugin_when_plugin_is_active(): void { + public function test_maybe_activate_plugin_when_plugin_is_active(): void { $plugin = 'some-plugin/some-plugin.php'; + $main = Mockery::mock( Main::class )->makePartial(); + + $main->shouldReceive( 'is_plugin_active' )->with( $plugin )->once()->andReturn( true ); + $subject = Mockery::mock( Integrations::class )->makePartial(); $subject->shouldAllowMockingProtectedMethods(); - WP_Mock::expectActionNotAdded( 'activated_plugin', [ $subject, 'activated_plugin_action' ] ); - WP_Mock::userFunction( 'is_plugin_active' )->with( $plugin )->once()->andReturn( true ); - WP_Mock::userFunction( 'activate_plugin' )->with( $plugin )->never(); + WP_Mock::userFunction( 'hcaptcha' )->with()->once()->andReturn( $main ); - self::assertTrue( $subject->activate_plugin( $plugin ) ); + self::assertTrue( $subject->maybe_activate_plugin( $plugin ) ); } /** diff --git a/src/php/Settings/Integrations.php b/src/php/Settings/Integrations.php index 15d1d608..101a47a6 100644 --- a/src/php/Settings/Integrations.php +++ b/src/php/Settings/Integrations.php @@ -968,6 +968,8 @@ protected function process_plugins( bool $activate, array $plugins, string $plug ); $this->send_json_success( esc_html( $message ) ); + + return; // For testing purposes. } } @@ -978,11 +980,11 @@ protected function process_plugins( bool $activate, array $plugins, string $plug ); $this->send_json_error( esc_html( $message ) ); - } - $network_wide = is_multisite() && $this->is_network_wide(); + return; // For testing purposes. + } - deactivate_plugins( $plugins, true, $network_wide ); + $this->deactivate_plugins( $plugins ); $message = sprintf( /* translators: 1: Plugin name. */ @@ -993,6 +995,19 @@ protected function process_plugins( bool $activate, array $plugins, string $plug $this->send_json_success( esc_html( $message ) ); } + /** + * Deactivate plugins. + * + * @param array $plugins Plugins to deactivate. + * + * @return void + */ + protected function deactivate_plugins( array $plugins ): void { + $network_wide = is_multisite() && $this->is_network_wide(); + + deactivate_plugins( $plugins, true, $network_wide ); + } + /** * Activate a theme. * @@ -1094,19 +1109,19 @@ protected function activate_plugin_tree( array &$node ) { unset( $child ); } - $node['result'] = $this->activate_plugin( $node['plugin'] ); + $node['result'] = $this->maybe_activate_plugin( $node['plugin'] ); return $node['result']; } /** - * Activate plugin. + * Maybe activate plugin. * * @param string $plugin Path to the plugin file relative to the plugins' directory. * * @return null|true|WP_Error Null on success, WP_Error on failure. True if the plugin is already active. */ - protected function activate_plugin( string $plugin ) { + protected function maybe_activate_plugin( string $plugin ) { if ( hcaptcha()->is_plugin_active( $plugin ) ) { return true; @@ -1114,17 +1129,27 @@ protected function activate_plugin( string $plugin ) { ob_start(); - $network_wide = is_multisite() && $this->is_network_wide(); - - // Activate plugins silently to avoid redirects. - // Result is null on success, WP_Error on failure. - $result = activate_plugin( $plugin, '', $network_wide, true ); + $result = $this->activate_plugin( $plugin ); ob_end_clean(); return $result; } + /** + * Activate plugin. + * + * @param string $plugin Path to the plugin file relative to the plugins' directory. + * + * @return null|WP_Error Null on success, WP_Error on failure. + */ + protected function activate_plugin( string $plugin ): ?WP_Error { + $network_wide = is_multisite() && $this->is_network_wide(); + + // Activate plugins silently to avoid redirects. + return activate_plugin( $plugin, '', $network_wide, true ); + } + /** * Get plugins' tree. *