Skip to content

Mock HTTP requests #210

@BrianHenryIE

Description

@BrianHenryIE

Feature Request

Describe your use case and the problem you are facing

When writing my own CLI commands, they sometimes perform HTTP requests. E.g. I'm currently working with a software licence server, I want a CLI command to activate the licence, but I don't want to use a real licence server which would decrement the available licence activations and return different responses when the test is re-run.

Maybe WP CLI already has this utility, but I didn't see it.

Describe the solution you'd like

Filter pre_http_request by creating an mu-plugin for the test case which loads a PHP file containing the mocked response.

Add this to GivenStepDefinitions.php

	/**
	 * @Given /^a request to (.*?) responds? with (.*)$/
	 */
	public function given_a_request_to_a_url_respond_with_file( $url_substring_pattern, $remote_request_response_file ) {

		$project_dir = realpath( self::get_vendor_dir() . '/../' );

		switch ( true ) {
			case is_file( $remote_request_response_file ):
				$response_file = realpath( $remote_request_response_file );
				break;
			case is_file( ltrim( $remote_request_response_file, './' ) ):
				$response_file = realpath( ltrim( $remote_request_response_file, './' ) );
				break;
			case is_file( $project_dir . '/' . $remote_request_response_file ):
				$response_file = $project_dir . '/' . $remote_request_response_file;
				break;
			default:
				WP_CLI::error( "File not found: {$remote_request_response_file}" );
		}

		if ( substr( $url_substring_pattern, 0, 1 ) !== substr( $url_substring_pattern, -1 ) ) {
			$url_substring_pattern = '/' . preg_quote( $url_substring_pattern, '/' ) . '/';
		}

		$mu_plugin_name = basename( $remote_request_response_file );

		$mu_php = <<<MU_PHP
<?php
/**
 * Plugin Name: $mu_plugin_name
 * Description: Mock a response for a remote request matching `$url_substring_pattern`.
 */
 
/**
 * Filter the HTTP request to return a mock response.
 *
 * @hooked pre_http_request
 * @see \WP_Http::request()
 * 
 * @param false|array \$pre
 * @param array \$parsed_args
 * @param string \$url The request URL.
 * 
 * @return false|array{headers:array,body:string,response:array{code:int|false,message:bool|string},cookies:array,http_response:null|array}
 */
add_filter( 'pre_http_request', function( \$pre, \$parsed_args, \$url ) { 
	if ( 1 !== preg_match( '$url_substring_pattern', \$url ) ) {
		return \$pre;
	}

	return include '$response_file';
}, 10, 3 );
MU_PHP;

		file_put_contents(
			$this->variables['RUN_DIR'] . '/wp-content/mu-plugins/' . $mu_plugin_name, 
			$mu_php 
		);
	}

And a feature would look like:

  Scenario: licence set with activate flag
    Given a WP install
    Given a plugin located at ./test-plugin

    Given a request to wp-json/slswc/v1/activate? responds with tests/_data/features/activate-success.php

    When I run `wp test-plugin licence set-key abcdefghijklmnopqrstuvwxyzn --activate`
    Then STDERR should be empty
    And STDOUT should contain:
      """
      Success: active
      """

This could be generalised to almost every filter, so maybe I missed it because I was looking for a http mock.

I need to write tests on that switch statement.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions