Skip to content

Commit

Permalink
Merge pull request #11 from Ricorocks-Digital-Agency/tracing
Browse files Browse the repository at this point in the history
Tracing
  • Loading branch information
lukeraymonddowning authored Dec 10, 2020
2 parents 5ebe3b7 + 972785d commit 66c25cb
Show file tree
Hide file tree
Showing 10 changed files with 285 additions and 15 deletions.
29 changes: 24 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ A Laravel SOAP client that provides a clean interface for handling requests and
* [Call](#call)
* [Parameters](#parameters)
* [Nodes](#nodes)
- [Tracing](#Tracing)
- [Hooks](#hooks)
- [Faking](#faking)
- [Faking](#faking)
- [Configuration](#configuration)
* [Include](#include)

Expand Down Expand Up @@ -147,6 +148,24 @@ Now, just by adding or removing a body to the `soap_node()` the outputted array

A node can be made with either the Facade `Soap::node()` or the helper method `soap_node()`.

## Tracing
Soap allows you to easily trace your interactions with the SOAP endpoint being accessed.

To trace all requests, set the following in the register method of your `ServiceProvider`:

```php
Soap::trace()
```
Now, all `Response` objects returned will have a `Trace` object attached, accessible via `$response->getTrace()`. This has two properties `xmlRequest` and `xmlResponse` - storing the raw XML values for each.

Tracing can also be declared locally:
```php
Soap::to('...')->trace()->call('...')
```
Now, just this `Response` will have a valid `Trace`.

Tracing is null safe. If `$response->getTrace()` is called when a `Trace` hasn't been set, a new `Trace` is returned. This `Trace`'s properties will all return `null`.

## Hooks

Hooks allow you to perform actions before and after Soap makes a request.
Expand Down Expand Up @@ -225,20 +244,20 @@ you can use this method, passing in the desired count as a parameter.

#### `Soap::assertSent(callable $callback)`

You can dive a little deeper and test that a particular request was
You can dive a little deeper and test that a particular request was
actually sent, and that it returned the expected response. You should
pass a closure into this method, which receives the `$request` and `$response` as parameters, and return `true` if they match your
expectations.

#### `Soap::assertNotSent(callable $callback)`

This is the opposite of `Soap::assertSent`. You can make sure that a
This is the opposite of `Soap::assertSent`. You can make sure that a
particular request wasn't made. Again, returning `true` from the
closure will cause it to pass.

#### `Soap::assertNothingSent()`

If you just want to make sure that absolutely nothing was sent out, you
If you just want to make sure that absolutely nothing was sent out, you
can call this. It does what it says on the tin.

## Configuration
Expand All @@ -257,7 +276,7 @@ You can even use dot syntax on your array keys to permeate deeper into the reque

```php
Soap::include(['login.credentials' => soap_node(['user' => '...', 'password' => '...'])])->for('...');
```
```


### Changelog
Expand Down
2 changes: 2 additions & 0 deletions src/Request/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@ public function getMethod();
public function getBody();

public function set($key, $value): self;

public function trace($shouldTrace = true): self;
}
32 changes: 27 additions & 5 deletions src/Request/SoapClientRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@

use RicorocksDigitalAgency\Soap\Parameters\Builder;
use RicorocksDigitalAgency\Soap\Response\Response;
use SoapClient;
use RicorocksDigitalAgency\Soap\Support\Tracing\Trace;

class SoapClientRequest implements Request
{
protected string $endpoint;
protected string $method;
protected $body = [];
protected SoapClient $client;
protected $client;
protected Builder $builder;
protected Response $response;
protected $hooks = [];
protected $shouldTrace = false;

public function __construct(Builder $builder)
{
Expand Down Expand Up @@ -48,8 +49,23 @@ public function call($method, $parameters = [])

protected function getResponse()
{
return $this->response ??= Response::new($this->makeRequest())
->withXml($this->client()->__getLastRequest(), $this->client()->__getLastResponse());
return $this->response ??= $this->getRealResponse();
}

protected function getRealResponse()
{
return tap(
Response::new($this->makeRequest()),
fn($response) => $this->shouldTrace ? $this->addTrace($response) : $response
);
}

protected function addTrace($response)
{
return $response->setTrace(
Trace::thisXmlRequest($this->client()->__getLastRequest())
->thisXmlResponse($this->client()->__getLastResponse())
);
}

protected function makeRequest()
Expand All @@ -59,7 +75,7 @@ protected function makeRequest()

protected function client()
{
return $this->client ??= new SoapClient($this->endpoint, ['trace' => true]);
return $this->client ??= app(\SoapClient::class, ['wsdl' => $this->endpoint, 'options' => ['trace' => $this->shouldTrace]]);
}

public function getMethod()
Expand Down Expand Up @@ -109,4 +125,10 @@ public function set($key, $value): Request
data_set($this->body, $key, $value);
return $this;
}

public function trace($shouldTrace = true): Request
{
$this->shouldTrace = $shouldTrace;
return $this;
}
}
15 changes: 10 additions & 5 deletions src/Response/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

namespace RicorocksDigitalAgency\Soap\Response;

use RicorocksDigitalAgency\Soap\Support\Tracing\Trace;

class Response
{
public $response;
public $xmlRequest = null;
public $xmlResponse = null;
protected Trace $trace;

public static function new($response = []): self
{
Expand All @@ -18,13 +19,17 @@ public function __get($name)
return data_get($this->response, $name);
}

public function withXml($xmlRequest, $xmlResponse)
public function setTrace(Trace $trace)
{
$this->xmlRequest = $xmlRequest;
$this->xmlResponse = $xmlResponse;
$this->trace = $trace;
return $this;
}

public function trace()
{
return $this->trace ??= app(Trace::class);
}

public function set($key, $value): self
{
data_set($this->response, $key, $value);
Expand Down
6 changes: 6 additions & 0 deletions src/Soap.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ public function afterRequesting(callable $hook)
return $this;
}

public function trace($shouldTrace = true)
{
$this->beforeRequesting(fn($request) => $request->trace($shouldTrace));
return $this;
}

public function __call($method, $parameters)
{
if (static::hasMacro($method)) {
Expand Down
19 changes: 19 additions & 0 deletions src/Support/Tracing/Trace.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace RicorocksDigitalAgency\Soap\Support\Tracing;

class Trace
{
public $xmlRequest;
public $xmlResponse;

public static function thisXmlRequest($xml): self
{
return tap(new static, fn($instance) => $instance->xmlRequest = $xml);
}

public function thisXmlResponse($xml): self
{
return tap($this, fn($self) => $self->xmlResponse = $xml);
}
}
94 changes: 94 additions & 0 deletions tests/Mocks/MockSoapClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php


namespace RicorocksDigitalAgency\Soap\Tests\Mocks;


class MockSoapClient
{
protected $shouldTrace = false;

/* Methods */
public function __construct($wsdl, $options = [])
{
if ($options['trace'] ?? false) {
$this->shouldTrace = true;
}
}

public function __call(string $function_name, array $arguments)
{
}

public function __doRequest(string $request, string $location, string $action, int $version, $one_way = 0)
{
}

public function __getCookies()
{
}

public function __getFunctions()
{
return [
"The mock client does not actually have functions!"
];
}

public function __getLastRequest()
{
if (!$this->shouldTrace) {
return null;
}

return '<?xml version="1.0" encoding="UTF-8"?><FooBar><Hello>World</Hello></FooBar>';
}

public function __getLastRequestHeaders()
{
}

public function __getLastResponse()
{
if (!$this->shouldTrace) {
return null;
}

return '<?xml version="1.0" encoding="UTF-8"?><Status>Success!</Status>';
}

public function __getLastResponseHeaders()
{
}

public function __getTypes()
{
}

public function __setCookie(string $name, string $value = null)
{
}

public function __setLocation(string $new_location = null)
{
}

public function __setSoapHeaders($soapheaders)
{
}

public function __soapCall(
string $function_name,
array $arguments,
array $options = [],
$input_headers = [],
&$output_headers = []
) {
}

public function SoapClient(mixed $wsdl, array $options = [])
{
return new static($wsdl, $options);
}

}
6 changes: 6 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@

use Orchestra\Testbench\TestCase as OrchestraTestCase;
use RicorocksDigitalAgency\Soap\Providers\SoapServiceProvider;
use RicorocksDigitalAgency\Soap\Tests\Mocks\MockSoapClient;

abstract class TestCase extends OrchestraTestCase
{
const EXAMPLE_SOAP_ENDPOINT = "http://www.dneonline.com/calculator.asmx?WSDL";

protected function fakeClient()
{
$this->app->bind(\SoapClient::class, MockSoapClient::class);
}

protected function getPackageProviders($app)
{
return [SoapServiceProvider::class];
Expand Down
49 changes: 49 additions & 0 deletions tests/Tracing/SoapTracingTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace RicorocksDigitalAgency\Soap\Tests\Tracing;

use RicorocksDigitalAgency\Soap\Facades\Soap;
use RicorocksDigitalAgency\Soap\Support\Tracing\Trace;
use RicorocksDigitalAgency\Soap\Tests\TestCase;

class SoapTracingTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
$this->fakeClient();
}

/** @test */
public function a_trace_can_be_requested_at_time_of_request()
{
$response = Soap::to(static::EXAMPLE_SOAP_ENDPOINT)
->trace()
->call('Add', ['intA' => 10, 'intB' => 25]);

$this->assertEquals('<?xml version="1.0" encoding="UTF-8"?><FooBar><Hello>World</Hello></FooBar>', $response->trace()->xmlRequest);
$this->assertEquals('<?xml version="1.0" encoding="UTF-8"?><Status>Success!</Status>', $response->trace()->xmlResponse);
}

/** @test */
public function a_trace_can_be_requested_globally()
{
Soap::trace();

$response = Soap::to(static::EXAMPLE_SOAP_ENDPOINT)
->call('Add', ['intA' => 10, 'intB' => 25]);

$this->assertEquals('<?xml version="1.0" encoding="UTF-8"?><FooBar><Hello>World</Hello></FooBar>', $response->trace()->xmlRequest);
$this->assertEquals('<?xml version="1.0" encoding="UTF-8"?><Status>Success!</Status>', $response->trace()->xmlResponse);
}

/** @test */
public function by_default_the_trace_has_no_content_on_the_response()
{
$response = Soap::to(static::EXAMPLE_SOAP_ENDPOINT)
->call('Add', ['intA' => 10, 'intB' => 25]);

$this->assertEmpty($response->trace()->xmlRequest);
$this->assertEmpty($response->trace()->xmlResponse);
}
}
Loading

0 comments on commit 66c25cb

Please sign in to comment.