diff --git a/README.md b/README.md
index bde9920..85222a7 100644
--- a/README.md
+++ b/README.md
@@ -274,17 +274,18 @@ When faking responses, you may occasionally wish to inspect the requests the cli
The `assertSent` method accepts a callback which will be given an `CodeDredd\Soap\Client\Request` instance and should return a boolean value indicating if the request matches your expectations. In order for the test to pass, at least one request must have been issued matching the given expectations:
-Right now you can only check the action
-
Soap::fake();
Soap::withHeaders([
'X-First' => 'foo',
])->baseWsdl('http://test.com/v1?wsdl')
- ->call('Get_Users');
+ ->call('Get_Users', [
+ 'name' => 'CodeDredd'
+ ]);
Soap::assertSent(function ($request) {
- return $request->action() === 'Get_Users';
+ return $request->action() === 'Get_Users' &&
+ $request->arguments() === ['name' => 'CodeDredd'];
});
//Or shortcut
Soap::assertActionSent('Get_Users')
diff --git a/composer.json b/composer.json
index cbbaedd..6825e7d 100644
--- a/composer.json
+++ b/composer.json
@@ -13,6 +13,8 @@
"php": ">=7.2.0",
"ext-soap": "*",
"ext-json": "*",
+ "ext-dom": "*",
+ "ext-simplexml": "*",
"illuminate/support": "^5.6 || ^6.0 || ^7.0",
"phpro/soap-client": "^1.1",
"php-http/guzzle6-adapter": "^2.0",
diff --git a/composer.lock b/composer.lock
index cf093e6..0f6b041 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "20b98089705da28bf322f6ed8b8b97ca",
+ "content-hash": "9257626529083d40232805d69d34add7",
"packages": [
{
"name": "brick/math",
@@ -536,16 +536,16 @@
},
{
"name": "laravel/framework",
- "version": "v7.7.0",
+ "version": "v7.7.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "3c9a67a35a4386f861ae0a5eb178a709552e4fa9"
+ "reference": "4de129177f889cd7672e732d8808020adfb7b121"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/3c9a67a35a4386f861ae0a5eb178a709552e4fa9",
- "reference": "3c9a67a35a4386f861ae0a5eb178a709552e4fa9",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/4de129177f889cd7672e732d8808020adfb7b121",
+ "reference": "4de129177f889cd7672e732d8808020adfb7b121",
"shasum": ""
},
"require": {
@@ -684,7 +684,7 @@
"framework",
"laravel"
],
- "time": "2020-04-21T13:50:23+00:00"
+ "time": "2020-04-21T18:57:12+00:00"
},
{
"name": "league/commonmark",
@@ -5684,7 +5684,9 @@
"platform": {
"php": ">=7.2.0",
"ext-soap": "*",
- "ext-json": "*"
+ "ext-json": "*",
+ "ext-dom": "*",
+ "ext-simplexml": "*"
},
"platform-dev": []
}
diff --git a/src/Client/Request.php b/src/Client/Request.php
index 19f5b07..f80bbaa 100644
--- a/src/Client/Request.php
+++ b/src/Client/Request.php
@@ -2,9 +2,15 @@
namespace CodeDredd\Soap\Client;
-use Phpro\SoapClient\Type\MultiArgumentRequest;
+use CodeDredd\Soap\Xml\SoapXml;
+use CodeDredd\Soap\Xml\XMLSerializer;
+use Illuminate\Support\Arr;
-class Request extends MultiArgumentRequest
+/**
+ * Class Request
+ * @package CodeDredd\Soap\Client
+ */
+class Request
{
/**
* The underlying PSR request.
@@ -22,8 +28,6 @@ class Request extends MultiArgumentRequest
public function __construct($request)
{
$this->request = $request;
- //@todo still need to get the arguments some how
- parent::__construct([]);
}
/**
@@ -33,4 +37,30 @@ public function action(): string
{
return $this->request->getHeaderLine('SOAPAction');
}
+
+ /**
+ * @return \Psr\Http\Message\RequestInterface
+ */
+ public function getRequest() {
+ return $this->request;
+ }
+
+ /**
+ * Return complete xml request body
+ *
+ * @return string
+ */
+ public function xmlContent() {
+ return $this->request->getBody()->getContents();
+ }
+
+ /**
+ * Return request arguments
+ *
+ * @return array
+ */
+ public function arguments(): array {
+ $xml = SoapXml::fromString($this->xmlContent());
+ return Arr::first(XMLSerializer::domNodeToArray($xml->getBody()));
+ }
}
diff --git a/src/Client/Response.php b/src/Client/Response.php
index 388a1b4..dbbdac3 100644
--- a/src/Client/Response.php
+++ b/src/Client/Response.php
@@ -5,7 +5,7 @@
use LogicException;
use ArrayAccess;
use CodeDredd\Soap\Exceptions\RequestException;
-use CodeDredd\Soap\XML\SoapXml;
+use CodeDredd\Soap\Xml\SoapXml;
use GuzzleHttp\Psr7\Response as Psr7Response;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable;
diff --git a/src/Faker/EngineFaker.php b/src/Faker/EngineFaker.php
index 2b34006..f7e5c7f 100644
--- a/src/Faker/EngineFaker.php
+++ b/src/Faker/EngineFaker.php
@@ -4,7 +4,7 @@
namespace CodeDredd\Soap\Faker;
-use CodeDredd\Soap\XML\XMLSerializer;
+use CodeDredd\Soap\Xml\XMLSerializer;
use Phpro\SoapClient\Soap\Engine\DriverInterface;
use Phpro\SoapClient\Soap\Engine\EngineInterface;
use Phpro\SoapClient\Soap\Engine\Metadata\MetadataInterface;
@@ -13,6 +13,10 @@
use Phpro\SoapClient\Soap\HttpBinding\SoapRequest;
use Phpro\SoapClient\Xml\SoapXml;
+/**
+ * Class EngineFaker
+ * @package CodeDredd\Soap\Faker
+ */
class EngineFaker implements EngineInterface
{
/**
@@ -25,8 +29,17 @@ class EngineFaker implements EngineInterface
*/
private $handler;
+ /**
+ * @var string
+ */
private $wsdl;
+ /**
+ * EngineFaker constructor.
+ * @param DriverInterface $driver
+ * @param HandlerInterface $handler
+ * @param string $wsdl
+ */
public function __construct(
DriverInterface $driver,
HandlerInterface $handler,
@@ -37,24 +50,30 @@ public function __construct(
$this->wsdl = $wsdl;
}
+ /**
+ * @return MetadataInterface
+ */
public function getMetadata(): MetadataInterface
{
return $this->driver->getMetadata();
}
+ /**
+ * @param string $method
+ * @param array $arguments
+ * @return mixed
+ */
public function request(string $method, array $arguments)
{
- $arguments = [
- 'SOAP-ENV:Body' => $arguments
- ];
- $xml = new \SimpleXMLElement('');
- XMLSerializer::arrayToXml($arguments, $xml);
- $request = new SoapRequest($xml->asXML(), $this->wsdl, $method, 1);
+ $request = new SoapRequest(XMLSerializer::arrayToSoapXml($arguments), $this->wsdl, $method, 1);
$response = $this->handler->request($request);
return json_decode($response->getResponse());
}
+ /**
+ * @return LastRequestInfo
+ */
public function collectLastRequestInfo(): LastRequestInfo
{
return $this->handler->collectLastRequestInfo();
diff --git a/src/SoapFactory.php b/src/SoapFactory.php
index 8664cfd..9f2022c 100644
--- a/src/SoapFactory.php
+++ b/src/SoapFactory.php
@@ -5,7 +5,7 @@
use Closure;
use CodeDredd\Soap\Client\Request;
use CodeDredd\Soap\Client\ResponseSequence;
-use CodeDredd\Soap\XML\XMLSerializer;
+use CodeDredd\Soap\Xml\XMLSerializer;
use GuzzleHttp\Psr7\Response as Psr7Response;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable;
diff --git a/src/XML/XMLSerializer.php b/src/XML/XMLSerializer.php
deleted file mode 100644
index c9bb6a3..0000000
--- a/src/XML/XMLSerializer.php
+++ /dev/null
@@ -1,124 +0,0 @@
-
- * Date: 16.04.2020
- * Time: 16:12
- */
-class XMLSerializer {
-
- /**
- *
- * The most advanced method of serialization.
- *
- * @param mixed $obj => can be an objectm, an array or string. may contain unlimited number of subobjects and subarrays
- * @param string $wrapper => main wrapper for the xml
- * @param array (key=>value) $replacements => an array with variable and object name replacements
- * @param boolean $add_header => whether to add header to the xml string
- * @param array (key=>value) $header_params => array with additional xml tag params
- * @param string $node_name => tag name in case of numeric array key
- */
- public static function generateValidXmlFromMixiedObj($obj, $wrapper = null, $replacements=array(), $add_header = true, $header_params=array(), $node_name = 'node')
- {
- $xml = '';
- if($add_header)
- $xml .= self::generateHeader($header_params);
- if($wrapper!=null) $xml .= '<' . $wrapper . '>';
- if(is_object($obj))
- {
- $node_block = strtolower(get_class($obj));
- if(isset($replacements[$node_block])) $node_block = $replacements[$node_block];
- $xml .= '<' . $node_block . '>';
- $vars = get_object_vars($obj);
- if(!empty($vars))
- {
- foreach($vars as $var_id => $var)
- {
- if(isset($replacements[$var_id])) $var_id = $replacements[$var_id];
- $xml .= '<' . $var_id . '>';
- $xml .= self::generateValidXmlFromMixiedObj($var, null, $replacements, false, null, $node_name);
- $xml .= '' . $var_id . '>';
- }
- }
- $xml .= '' . $node_block . '>';
- }
- else if(is_array($obj))
- {
- foreach($obj as $var_id => $var)
- {
- if(!is_object($var))
- {
- if (is_numeric($var_id))
- $var_id = $node_name;
- if(isset($replacements[$var_id])) $var_id = $replacements[$var_id];
- $xml .= '<' . $var_id . '>';
- }
- $xml .= self::generateValidXmlFromMixiedObj($var, null, $replacements, false, null, $node_name);
- if(!is_object($var))
- $xml .= '' . $var_id . '>';
- }
- }
- else
- {
- $xml .= htmlspecialchars($obj, ENT_QUOTES);
- }
-
- if($wrapper!=null) $xml .= '' . $wrapper . '>';
-
- return $xml;
- }
-
- /**
- *
- * xml header generator
- * @param array $params
- */
- public static function generateHeader($params = array())
- {
- $basic_params = array('version' => '1.0', 'encoding' => 'UTF-8');
- if(!empty($params))
- $basic_params = array_merge($basic_params,$params);
-
- $header = '$v)
- {
- $header .= ' '.$k.'='.$v;
- }
- $header .= ' ?>';
- return $header;
- }
-
- public static function arrayToXml($array, &$xml){
- foreach ($array as $key => $value) {
- if(is_array($value)){
- if(is_int($key)){
- $key = "node";
- }
- $label = $xml->addChild($key);
- self::arrayToXml($value, $label);
- }
- else {
- $xml->addChild($key, $value);
- }
- }
- }
-
- public static function to_xml(\SimpleXMLElement $object, array $data)
- {
- foreach ($data as $key => $value) {
- if (is_array($value)) {
- $new_object = $object->addChild($key);
- self::to_xml($new_object, $value);
- } else {
- // if the key is an integer, it needs text with it to actually work.
- if ($key == (int) $key) {
- $key = "key_$key";
- }
-
- $object->addChild($key, $value);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/XML/SoapXml.php b/src/Xml/SoapXml.php
similarity index 78%
rename from src/XML/SoapXml.php
rename to src/Xml/SoapXml.php
index ae0da65..0e1c260 100644
--- a/src/XML/SoapXml.php
+++ b/src/Xml/SoapXml.php
@@ -1,10 +1,12 @@
length ? $list->item(0)->firstChild->nodeValue : 'No Fault Message found';
}
-}
\ No newline at end of file
+}
diff --git a/src/Xml/XMLSerializer.php b/src/Xml/XMLSerializer.php
new file mode 100644
index 0000000..2c0d8c8
--- /dev/null
+++ b/src/Xml/XMLSerializer.php
@@ -0,0 +1,99 @@
+nodeType) {
+ case XML_CDATA_SECTION_NODE:
+ case XML_TEXT_NODE:
+ $output = trim($node->textContent);
+ break;
+ case XML_ELEMENT_NODE:
+ for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) {
+ $child = $node->childNodes->item($i);
+ $v = self::domNodeToArray($child);
+ if (isset($child->tagName)) {
+ $t = Str::after($child->tagName, ':');
+ if (!isset($output[$t])) {
+ $output[$t] = [];
+ }
+ $output[$t][] = $v;
+ } elseif ($v || $v === '0') {
+ $output = (string) $v;
+ }
+ }
+ if ($node->attributes->length && !is_array($output)) { // Has attributes but isn't an array
+ $output = ['@content' => $output]; // Change output into an array.
+ }
+ if (is_array($output)) {
+ if ($node->attributes->length) {
+ $a = [];
+ foreach ($node->attributes as $attrName => $attrNode) {
+ $a[$attrName] = (string) $attrNode->value;
+ }
+ $output['@attributes'] = $a;
+ }
+ foreach ($output as $t => $v) {
+ if (is_array($v) && count($v) == 1 && $t != '@attributes') {
+ $output[$t] = $v[0];
+ }
+ }
+ }
+ break;
+ }
+ return $output;
+ }
+
+ /**
+ * Return a valid SOAP Xml
+ *
+ * @param array $array
+ * @return mixed
+ */
+ public static function arrayToSoapXml(array $array) {
+ $array = [
+ 'SOAP-ENV:Body' => $array
+ ];
+ $xml = new SimpleXMLElement('');
+ self::addArrayToXml($array, $xml);
+
+ return $xml->asXML();
+ }
+
+ /**
+ * @param $array
+ * @param $xml
+ */
+ public static function addArrayToXml($array, &$xml){
+ foreach ($array as $key => $value) {
+ if(is_array($value)){
+ if(is_int($key)){
+ $key = "node";
+ }
+ $label = $xml->addChild($key);
+ self::addArrayToXml($value, $label);
+ }
+ else {
+ $xml->addChild($key, $value);
+ }
+ }
+ }
+}
diff --git a/tests/Unit/SoapClientTest.php b/tests/Unit/SoapClientTest.php
index 58c211d..92cef8b 100644
--- a/tests/Unit/SoapClientTest.php
+++ b/tests/Unit/SoapClientTest.php
@@ -1,103 +1,123 @@
-call('Get_Users');
- self::assertTrue($response->ok());
- Soap::assertSent(function (Request $request) {
- return $request->action() === 'Get_Users';
- });
- Soap::assertNotSent(function (Request $request) {
- return $request->action() === 'Get_User';
- });
- Soap::assertActionCalled('Get_Users');
- }
-
- public function testMagicCallByConfig()
- {
- Soap::fake();
- $response = Soap::buildClient('laravel_soap')->Get_User();
- self::assertTrue($response->ok());
- }
-
- public function testArrayAccessResponse()
- {
- Soap::fakeSequence()->push('test');
- $response = Soap::buildClient('laravel_soap')->Get_User()['response'];
- self::assertEquals('test', $response);
- }
-
- public function testSequenceFake()
- {
- $responseFake = ['user' => 'test'];
- $responseFake2 = ['user' => 'test2'];
- Soap::fakeSequence()
- ->push($responseFake)
- ->whenEmpty(Soap::response($responseFake2));
- $client = Soap::buildClient('laravel_soap');
- $response = $client->Get_User();
- $response2 = $client->Get_User();
- $response3 = $client->Get_User();
- self::assertTrue($response->ok());
- self::assertEquals($responseFake, $response->json());
- self::assertEquals($responseFake2, $response2->json());
- self::assertEquals($responseFake2, $response3->json());
- }
-
- /**
- * @dataProvider soapActionProvider
- * @param $action
- * @param $fake
- * @param $exspected
- */
- public function testSoapFake($action, $fake, $exspected)
- {
- $fake = collect($fake)->map(function ($item) {
- return Soap::response($item);
- })->all();
- Soap::fake($fake);
- $response = Soap::baseWsdl('https://laravel-soap.wsdl')
- ->call($action);
- self::assertEquals($exspected, $response->json());
- }
-
- public function soapActionProvider()
- {
- $fakeResponse = [
- 'Get_Users' => [
- 'Response_Data' => [
- 'Users' => [
- [
- 'name' => 'test',
- 'field' => 'bla'
- ]
- ]
- ]
- ],
- 'Get_Post' => 'Test'
- ];
- return [
- 'without_fake_array' => ['Get_User', null, null],
- 'with_fake_array_wrong_method' => ['Get_User', $fakeResponse, null],
- 'with_fake_array' => ['Get_Users', $fakeResponse, $fakeResponse['Get_Users']],
- 'with_fake_string' => ['Get_Post', $fakeResponse, ['response' => 'Test']],
- ];
- }
-}
\ No newline at end of file
+call('Get_Users');
+ self::assertTrue($response->ok());
+ Soap::assertSent(function (Request $request) {
+ return $request->action() === 'Get_Users';
+ });
+ Soap::assertNotSent(function (Request $request) {
+ return $request->action() === 'Get_User';
+ });
+ Soap::assertActionCalled('Get_Users');
+ }
+
+ public function testMagicCallByConfig()
+ {
+ Soap::fake();
+ $response = Soap::buildClient('laravel_soap')->Get_User();
+ self::assertTrue($response->ok());
+ }
+
+ public function testArrayAccessResponse()
+ {
+ Soap::fakeSequence()->push('test');
+ $response = Soap::buildClient('laravel_soap')->Get_User()['response'];
+ self::assertEquals('test', $response);
+ }
+
+ public function testRequestWithArguments()
+ {
+ Soap::fake();
+
+ $arguments = [
+ 'prename' => 'Corona',
+ 'lastname' => 'Pandemic',
+ ];
+
+ /** @var Response $response */
+ $response = Soap::buildClient('laravel_soap')->Submit_User($arguments);
+
+ self::assertTrue($response->ok());
+ Soap::assertSent(function (Request $request) use ($arguments) {
+ return $request->arguments() === $arguments &&
+ $request->action() === 'Submit_User';
+ });
+ }
+
+ public function testSequenceFake()
+ {
+ $responseFake = ['user' => 'test'];
+ $responseFake2 = ['user' => 'test2'];
+ Soap::fakeSequence()
+ ->push($responseFake)
+ ->whenEmpty(Soap::response($responseFake2));
+ $client = Soap::buildClient('laravel_soap');
+ $response = $client->Get_User();
+ $response2 = $client->Get_User();
+ $response3 = $client->Get_User();
+ self::assertTrue($response->ok());
+ self::assertEquals($responseFake, $response->json());
+ self::assertEquals($responseFake2, $response2->json());
+ self::assertEquals($responseFake2, $response3->json());
+ }
+
+ /**
+ * @dataProvider soapActionProvider
+ * @param $action
+ * @param $fake
+ * @param $exspected
+ */
+ public function testSoapFake($action, $fake, $exspected)
+ {
+ $fake = collect($fake)->map(function ($item) {
+ return Soap::response($item);
+ })->all();
+ Soap::fake($fake);
+ $response = Soap::baseWsdl('https://laravel-soap.wsdl')
+ ->call($action);
+ self::assertEquals($exspected, $response->json());
+ }
+
+ public function soapActionProvider()
+ {
+ $fakeResponse = [
+ 'Get_Users' => [
+ 'Response_Data' => [
+ 'Users' => [
+ [
+ 'name' => 'test',
+ 'field' => 'bla'
+ ]
+ ]
+ ]
+ ],
+ 'Get_Post' => 'Test'
+ ];
+ return [
+ 'without_fake_array' => ['Get_User', null, null],
+ 'with_fake_array_wrong_method' => ['Get_User', $fakeResponse, null],
+ 'with_fake_array' => ['Get_Users', $fakeResponse, $fakeResponse['Get_Users']],
+ 'with_fake_string' => ['Get_Post', $fakeResponse, ['response' => 'Test']],
+ ];
+ }
+}
diff --git a/tests/Unit/XML/SoapXmlTest.php b/tests/Unit/Xml/SoapXmlTest.php
similarity index 95%
rename from tests/Unit/XML/SoapXmlTest.php
rename to tests/Unit/Xml/SoapXmlTest.php
index 92dc246..202eda2 100644
--- a/tests/Unit/XML/SoapXmlTest.php
+++ b/tests/Unit/Xml/SoapXmlTest.php
@@ -1,6 +1,6 @@
+
+
+ Code
+ dredd
+
+
+XML;
+
+ protected $array = [
+ 'prename' => 'Code',
+ 'lastname' => 'dredd'
+ ];
+
+ public function testArrayToSoapXml()
+ {
+ $soapXml = XMLSerializer::arrayToSoapXml($this->array);
+
+ self::assertXmlStringEqualsXmlString($this->xml, $soapXml);
+ }
+
+ public function testDomNodeToArray()
+ {
+ $xmlDocument = SoapXml::fromString($this->xml);
+ $xmlBodyAsArray = XMLSerializer::domNodeToArray($xmlDocument->getBody());
+
+ self::assertEquals($this->array, $xmlBodyAsArray);
+ }
+}