-
Notifications
You must be signed in to change notification settings - Fork 98
Create AJAX_Runner #79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| <?php | ||
| /** | ||
| * Class WordPress\Plugin_Check\Checker\AJAX_Runner | ||
| * | ||
| * @package plugin-check | ||
| */ | ||
|
|
||
| namespace WordPress\Plugin_Check\Checker; | ||
|
|
||
| use Exception; | ||
| use WordPress\Plugin_Check\Utilities\Plugin_Request_Utility; | ||
|
|
||
| /** | ||
| * AJAX Runner class. | ||
| * | ||
| * @since n.e.x.t | ||
| */ | ||
| class AJAX_Runner extends Abstract_Check_Runner { | ||
|
|
||
| /** | ||
| * An instance of the Checks class. | ||
| * | ||
| * @since n.e.x.t | ||
| * @var Checks | ||
| */ | ||
| protected $checks; | ||
|
|
||
| /** | ||
| * Checks if the current request is an AJAX request for the Plugin Checker. | ||
| * | ||
| * @since n.e.x.t | ||
| * | ||
| * @return bool Returns true if is an AJAX request for the plugin check else false. | ||
| */ | ||
| public function is_plugin_check() { | ||
| if ( ! wp_doing_ajax() ) { | ||
| return false; | ||
| } | ||
|
|
||
| if ( ! isset( $_REQUEST['action'] ) || 'plugin_check_run_checks' !== $_REQUEST['action'] ) { | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * Creates and returns an instance of the Checks class based on the request. | ||
| * | ||
| * @since n.e.x.t | ||
| * | ||
| * @return Checks An instance of the Checks class. | ||
| * | ||
| * @throws Exception Thrown if the plugin main file cannot be found based on the AJAX input. | ||
| */ | ||
| protected function get_checks_instance() { | ||
| if ( ! isset( $this->checks ) ) { | ||
| if ( ! isset( $_REQUEST['plugin'] ) ) { | ||
| throw new Exception( 'Invalid plugin slug: Plugin slug must not be empty.' ); | ||
| } | ||
|
|
||
| // Get the plugin name from the AJAX request. | ||
| $plugin_file = Plugin_Request_Utility::get_plugin_basename_from_input( $_REQUEST['plugin'] ); | ||
|
|
||
| $this->checks = new Checks( WP_PLUGIN_DIR . '/' . $plugin_file ); | ||
| } | ||
|
|
||
| return $this->checks; | ||
| } | ||
|
|
||
| /** | ||
| * Returns an array of Check slugs to run based on the request. | ||
| * | ||
| * @since n.e.x.t | ||
| * | ||
| * @return array An array of Check slugs to run. | ||
|
felixarntz marked this conversation as resolved.
|
||
| */ | ||
| protected function get_check_slugs_to_run() { | ||
| $checks = array(); | ||
|
|
||
| if ( isset( $_REQUEST['checks'] ) ) { | ||
| // Checks are passed as a comma separated string. | ||
| $checks = wp_parse_list( $_REQUEST['checks'] ); | ||
| } | ||
|
|
||
| return $checks; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| <?php | ||
| /** | ||
| * Tests for the Checks class. | ||
| * | ||
| * @package plugin-check | ||
| */ | ||
|
|
||
| use WordPress\Plugin_Check\Checker\AJAX_Runner; | ||
| use WordPress\Plugin_Check\Checker\Check_Result; | ||
|
|
||
| class AJAX_Runner_Tests extends WP_UnitTestCase { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just an observation, but since all of these are filtering the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @joemcgill I've added an additional test to check behaviour when |
||
|
|
||
| public function test_is_plugin_check_returns_true() { | ||
| // Mock the AJAX request. | ||
| add_filter( 'wp_doing_ajax', '__return_true' ); | ||
| $_REQUEST['action'] = 'plugin_check_run_checks'; | ||
|
|
||
| $runner = new AJAX_Runner(); | ||
|
|
||
| $this->assertTrue( $runner->is_plugin_check() ); | ||
| } | ||
|
|
||
| public function test_is_plugin_check_returns_false() { | ||
| // Mock the AJAX request. | ||
| add_filter( 'wp_doing_ajax', '__return_true' ); | ||
| $_REQUEST['action'] = 'a_different_ajax_request'; | ||
|
|
||
| $runner = new AJAX_Runner(); | ||
|
|
||
| $this->assertFalse( $runner->is_plugin_check() ); | ||
| } | ||
|
|
||
| public function test_is_plugin_check_returns_false_not_ajax() { | ||
| // Mock the AJAX request. | ||
| add_filter( 'wp_doing_ajax', '__return_false' ); | ||
|
|
||
| $runner = new AJAX_Runner(); | ||
|
|
||
| $this->assertFalse( $runner->is_plugin_check() ); | ||
| } | ||
|
|
||
| public function test_prepare_with_runtime_check() { | ||
| add_filter( 'wp_doing_ajax', '__return_true' ); | ||
| $_REQUEST['action'] = 'plugin_check_run_checks'; | ||
| $_REQUEST['plugin'] = 'plugin-check'; | ||
| $_REQUEST['checks'] = 'runtime_check'; | ||
|
|
||
| add_filter( | ||
| 'wp_plugin_check_checks', | ||
| function( $checks ) { | ||
| return array( | ||
| 'runtime_check' => new WordPress\Plugin_Check\Test_Data\Runtime_Check(), | ||
| ); | ||
| } | ||
| ); | ||
|
|
||
| $runner = new AJAX_Runner(); | ||
| $cleanup = $runner->prepare(); | ||
|
|
||
| $this->assertIsCallable( $cleanup ); | ||
|
|
||
| // Assert the Universal_Runtume_Preparation was run. | ||
| $this->assertTrue( has_filter( 'option_active_plugins' ) ); | ||
| $this->assertTrue( has_filter( 'default_option_active_plugins' ) ); | ||
| $this->assertTrue( has_filter( 'stylesheet' ) ); | ||
| $this->assertTrue( has_filter( 'template' ) ); | ||
| $this->assertTrue( has_filter( 'pre_option_template' ) ); | ||
| $this->assertTrue( has_filter( 'pre_option_stylesheet' ) ); | ||
| $this->assertTrue( has_filter( 'pre_option_current_theme' ) ); | ||
| $this->assertTrue( has_filter( 'pre_option_template_root' ) ); | ||
| $this->assertTrue( has_filter( 'pre_option_stylesheet_root' ) ); | ||
| } | ||
|
|
||
| public function test_prepare_with_static_check() { | ||
| add_filter( 'wp_doing_ajax', '__return_true' ); | ||
| $_REQUEST['action'] = 'plugin_check_run_checks'; | ||
| $_REQUEST['plugin'] = 'plugin-check'; | ||
| $_REQUEST['checks'] = 'empty_check'; | ||
|
|
||
| add_filter( | ||
| 'wp_plugin_check_checks', | ||
| function( $checks ) { | ||
| return array( | ||
| 'empty_check' => new WordPress\Plugin_Check\Test_Data\Empty_Check(), | ||
| ); | ||
| } | ||
| ); | ||
|
|
||
| $runner = new AJAX_Runner(); | ||
| $cleanup = $runner->prepare(); | ||
|
|
||
| $this->assertIsCallable( $cleanup ); | ||
|
|
||
| // Assert the Universal_Runtume_Preparation was not run. | ||
| $this->assertFalse( has_filter( 'option_active_plugins' ) ); | ||
| $this->assertFalse( has_filter( 'default_option_active_plugins' ) ); | ||
| $this->assertFalse( has_filter( 'stylesheet' ) ); | ||
| $this->assertFalse( has_filter( 'template' ) ); | ||
| $this->assertFalse( has_filter( 'pre_option_template' ) ); | ||
| $this->assertFalse( has_filter( 'pre_option_stylesheet' ) ); | ||
| $this->assertFalse( has_filter( 'pre_option_current_theme' ) ); | ||
| $this->assertFalse( has_filter( 'pre_option_template_root' ) ); | ||
| $this->assertFalse( has_filter( 'pre_option_stylesheet_root' ) ); | ||
| } | ||
|
|
||
| public function test_run() { | ||
| add_filter( 'wp_doing_ajax', '__return_true' ); | ||
| $_REQUEST['action'] = 'plugin_check_run_checks'; | ||
| $_REQUEST['plugin'] = 'plugin-check'; | ||
| $_REQUEST['checks'] = 'empty_check'; | ||
|
|
||
| add_filter( | ||
| 'wp_plugin_check_checks', | ||
| function( $checks ) { | ||
| return array( | ||
| 'empty_check' => new WordPress\Plugin_Check\Test_Data\Empty_Check(), | ||
| ); | ||
| } | ||
| ); | ||
|
|
||
| $runner = new AJAX_Runner(); | ||
| $runner->prepare(); | ||
| $results = $runner->run(); | ||
|
|
||
| $this->assertInstanceOf( Check_Result::class, $results ); | ||
| $this->assertEmpty( $results->get_warnings() ); | ||
| $this->assertEmpty( $results->get_errors() ); | ||
| } | ||
|
|
||
| public function test_run_with_errors() { | ||
| add_filter( 'wp_doing_ajax', '__return_true' ); | ||
| $_REQUEST['action'] = 'plugin_check_run_checks'; | ||
| $_REQUEST['plugin'] = 'plugin-check'; | ||
| $_REQUEST['checks'] = 'error_check'; | ||
|
|
||
| add_filter( | ||
| 'wp_plugin_check_checks', | ||
| function( $checks ) { | ||
| return array( | ||
| 'error_check' => new WordPress\Plugin_Check\Test_Data\Error_Check(), | ||
| ); | ||
| } | ||
| ); | ||
|
|
||
| $runner = new AJAX_Runner(); | ||
| $runner->prepare(); | ||
| $results = $runner->run(); | ||
|
|
||
| $this->assertInstanceOf( Check_Result::class, $results ); | ||
| $this->assertEmpty( $results->get_warnings() ); | ||
| $this->assertNotEmpty( $results->get_errors() ); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assumes that the plugin is always being loaded from inside the plugins directory rather than as an mu-plugin or required via code, as is often the case during unit testing setups, or some platform configurations. Is that an intentional limitation at this point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @joemcgill thats a great point and something we should probably look into in the future. For this initial milestone I believe the intention is to only check plugins found within the main plugin directory.