vonbraunlabs/slimx

View on GitHub
SlimX/Tests/WebTestClient.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

namespace SlimX\Tests;

/**
 * Based on WebTestClient from
 * git@github.com:there4/slim-unit-testing-example.git
 */

use \Slim\Http\Body;
use \Slim\Http\Environment;

/**
 * Mocks the client request and response.
 */
class WebTestClient
{
    private $app;
    private $request;
    private $response;

    /**
     * Abstract way to make a request to SlimPHP, this allows us to mock the
     * slim environment.
     *
     * @param  string $method          Method name.
     * @param  string $path            URI.
     * @param  array  $data            Data request.
     * @param  array  $optionalHeaders Optional headers.
     * @return mixed.
     */
    private function request(
        string $method,
        string $path,
        $data = array(),
        array $optionalHeaders = array()
    ) {
        // Capture STDOUT
        ob_start();

        $options = array(
            'REQUEST_METHOD' => strtoupper($method),
            'REQUEST_URI'      => $path,
        );

        if ($method === 'get') {
            $options['QUERY_STRING'] = http_build_query($data);
        } elseif (is_array($data)) {
            $options['slim.input']   = http_build_query($data);
        } else {
            $options['slim.input']   = $data;
        }

        // Prepare a mock environment
        $env = Environment::mock($options);
        $request = \Slim\Http\Request::createFromEnvironment($env);

        foreach ($optionalHeaders as $key => $value) {
            $request = $request->withHeader($key, $value);
        }

        if ('get' !== $method && is_array($data)) {
            $request = $request->withParsedBody($data);
        } elseif ('get' !== $method && is_string($data)) {
            $body = new Body(fopen('php://temp', 'r+'));
            $body->write($data);
            $body->rewind();
            $request = $request->withBody($body);
        }

        // Execute our app
        $response = new \Slim\Http\Response();
        $this->response = $this->app->process($request, $response);
        $this->request = $request;

        // Return the application output. Also available in `response->body()`
        return ob_get_clean();
    }


    // We support these methods for testing. These are available via
    // `this->get()` and `$this->post()`. This is accomplished with the
    // `__call()` magic method below.
    private $testingMethods = array(
        'get', 'post', 'patch', 'put', 'delete', 'head', 'options'
    );

    /**
     * Set the Slim app.
     *
     * @param \Slim\App $app Slim app instance.
     */
    public function __construct(\Slim\App $app)
    {
        $this->app = $app;
    }

    /**
     * Implement our `get`, `post`, and other http operations, as defined on
     * $testingMethods.
     *
     * @param  string $method    Method being called.
     * @param  array  $arguments List of arguments.
     * @return mixed.
     */
    public function __call(string $method, array $arguments)
    {
        if (in_array(strtolower($method), $this->testingMethods)) {
            list($path, $data, $headers) = array_pad($arguments, 3, array());
            return $this->request($method, $path, $data, $headers);
        }
        throw new \BadMethodCallException(
            strtoupper($method) . ' is not supported'
        );
    }

    /**
     * Get the response objects.
     *
     * @return \Slim\Http\Response Response object.
     */
    public function getResponse()
    {
        return $this->response;
    }

    /**
     * Get the request object.
     *
     * @return \Slim\Http\Request Request object.
     */
    public function getRequest()
    {
        return $this->request;
    }
}