wsdl_docs-3.0.0-beta3/tests/src/Kernel/SoapClientManagerTest.php
tests/src/Kernel/SoapClientManagerTest.php
<?php
declare(strict_types = 1);
namespace Drupal\Tests\wsdl_docs\Kernel;
use Drupal;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\node\Entity\Node;
/**
* Class SoapClientManagerTest.
*
* @group wsdl_docs
*/
class SoapClientManagerTest extends EntityKernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
protected static $modules = [
'node',
'field',
'options',
'text',
'file',
'path',
'link',
'menu_ui',
'wsdl_docs',
'views',
];
/**
* Profile to enable.
*
* @var string
*/
protected string $profile = 'standard';
/**
* Admin user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected Drupal\Core\Session\AccountInterface $adminUser;
/**
* Soap Client manager.
*
* @var \Drupal\wsdl_docs\Services\SoapClientManager
*/
protected mixed $soapManagerService;
/**
* Amazon test WSDL url.
*
* @var string
*/
protected string $soapTestUrl;
/**
* Set up initial prerequisites.
*/
public function setUp(): void {
parent::setUp();
$this->installConfig(['node', 'wsdl_docs']);
$this->installSchema('wsdl_docs', 'wsdl_docs_soap_services');
try {
$this->setUpCurrentUser();
}
catch (EntityStorageException $e) {
}
$this->soapManagerService = Drupal::service('wsdl_docs.soap_client_manager');
$this->soapTestUrl = 'http://s3.amazonaws.com/ec2-downloads/ec2.wsdl';
}
/**
* Test Soap Service node validations.
*/
public function testViolations() {
$node = Node::create(
[
'title' => [['value' => '']],
'body' => [['value' => '']],
'field_wsdl_docs_source' => [['uri' => '']],
'type' => 'soap_service',
]
);
$violations = $node->validate();
$this->assertEquals(2, count($violations));
$this->assertEquals('title', $violations[0]->getPropertyPath());
$this->assertEquals('This value should not be null.', $violations[0]->getMessage());
$this->assertEquals('field_wsdl_docs_source', $violations[1]->getPropertyPath());
$this->assertEquals('This value should not be null.', $violations[1]->getMessage());
}
/**
* Test creation of WSDL Docs operations from Soap Service.
*/
public function testSoapClientManager() {
// Creates a soap service node with test amazon wsdl.
$node = Node::create(
[
'title' => [['value' => 'Amazon SOAP Test']],
'body' => [['value' => 'A test SOAP Service using a large Amazon WSDL.']],
'field_wsdl_docs_source' => [['uri' => $this->soapTestUrl]],
'type' => 'soap_service',
'status' => 1,
]
);
try {
$node->save();
}
catch (EntityStorageException $e) {
$this->assertNotEmpty($node->id(), 'Service node was created successfully with label' . $node->label());
}
$this->assertNotEmpty($node->id(), 'Service node was created successfully with nid ' . $node->id());
// Code below verifies wsdl_doc_operation nodes.
$client = $this->soapManagerService->loadUrl($this->soapTestUrl);
$this->assertNotEmpty($client, 'Created a SoapClient for amazon test SOAP endpoint url.');
$data_types = $this->soapManagerService->parseSoapTypes($client->__getTypes());
$this->assertNotEmpty($data_types, 'Successfully loaded a list of SOAP types.');
// Load WSDL file.
$wsdl = file_get_contents($this->soapTestUrl);
$this->assertNotEmpty($wsdl, 'Get contents of WSDL file ' . $this->soapTestUrl . '.');
$domDocument = $this->soapManagerService->getDomdocument($wsdl);
$this->assertNotEmpty($domDocument, 'Loads DOMDocument object if XML validates, FALSE if invalid');
$documentations = $styles = $outputs = $outputs_messages = $inputs = $inputs_messages = $messages_elements = $elements_types = [];
$portTypes = $domDocument->getElementsByTagName('portType');
foreach ($portTypes as $portType) {
$operations = $portType->getElementsByTagName('operation');
foreach ($operations as $operation) {
$operation_name = $operation->getAttribute('name');
// Parse documentation element.
if (!isset($documentations[$operation_name])) {
$documentation = $operation->getElementsByTagName('documentation');
if ($documentation->length > 0) {
$documentations[$operation_name] = $documentation[0]->nodeValue;
}
}
// For input/output (step 1):
// parsing correct input/output like WSDL viewer is multi step process.
$message = $operation->getElementsByTagName('output')[0]->getAttribute('message');
// Remove "tns:" namespace so we can parse the element.
$message = $this->soapManagerService->removeMethodNamespace($message);
$outputs_messages[$message] = $operation_name;
$_outputs_messages[$operation_name][] = $message;
// Repeat for input.
$message = $operation->getElementsByTagName('input')[0]->getAttribute('message');
// Remove "tns:" namespace so we can parse the element.
$message = $this->soapManagerService->removeMethodNamespace($message);
$inputs_messages[$message] = $operation_name;
$_inputs_messages[$operation_name][] = $message;
}
}
// For input/output (step 2)
$messages = $domDocument->getElementsByTagName('message');
foreach ($messages as $message) {
$message_name = $message->getAttribute('name');
if (isset($outputs_messages[$message_name]) || isset($inputs_messages[$message_name])) {
$part = $message->getElementsByTagName('part')[0];
$part_name = $part->getAttribute('name');
if ($part->hasAttribute('element')) {
$element = $part->getAttribute('element');
// Remove "tns:".
$element = $this->soapManagerService->removeMethodNamespace($element);
$messages_elements[$element][] = $message_name;
$_messages_elements[$message_name] = [
'name' => $part_name,
'element' => $element,
];
}
elseif ($part->hasAttribute('type')) {
$type = $part->getAttribute('type');
// Remove "tns:" namespace so we can parse the element.
$type = $this->soapManagerService->removeMethodNamespace($type);
$messages_elements[$type][] = $message_name;
$_messages_elements[$message_name] = [
'name' => $part_name,
'type' => $type,
];
}
}
}
// Parse input/output (step 3)
$schemas = $domDocument->getElementsByTagName('types')[0]->getElementsByTagName('schema');
foreach ($schemas as $schema) {
$elements = $schema->childNodes;
foreach ($elements as $element) {
if ($element->localName == 'element') {
$element_name = $element->getAttribute('name');
$element2_name = $element_name;
if (isset($messages_elements[$element_name])) {
// Parse complexType element.
if (!$element->hasAttribute('type')) {
$element = $element->getElementsByTagName('element')[0];
$element2_name = $element->getAttribute('name');
}
if ($element->hasAttribute('type')) {
$element_type = $element->getAttribute('type');
// Remove "tns:".
$element_type = $this->soapManagerService->removeMethodNamespace($element_type);
$elements_types[$element_type][] = $element_name;
$_elements_types[$element_name] = [
'name' => $element2_name,
'type' => $element_type,
];
}
}
}
}
}
// Parse input/output (step 4)
foreach ($elements_types as $type => $element) {
$_types_properties[$type] = $data_types[$type]['property info'];
}
$operations = $domDocument->getElementsByTagName('binding')[0]->childNodes;
foreach ($operations as $operation) {
if ($operation->localName == 'operation') {
$name = $operation->getAttribute('name');
// Parse style element.
$operation2 = $operation->getElementsByTagName('operation')[0];
if ($operation2->hasAttribute('style')) {
$styles[$name] = $operation2->getAttribute('style');
}
// Parse body element.
$outputs[$name] = $this->soapManagerService->renderOperation($name, $_outputs_messages, $_messages_elements, $_elements_types, $_types_properties, $data_types);
$inputs[$name] = $this->soapManagerService->renderOperation($name, $_inputs_messages, $_messages_elements, $_elements_types, $_types_properties, $data_types);
}
}
// List of new operations.
$operations = $this->soapManagerService->parseSoapOperations($client->__getFunctions());
// Find number of WSDL Docs operation nodes.
$current_operation = $this->entityTypeManager->getStorage('node')
->loadByProperties([
'type' => 'wsdl_docs_operation',
'field_wsdl_docs_soap_ref' => $node->id(),
]);
// Match of no of operations with wsdl docs operation
// nodes referencing soap service node.
$this->assertEquals(count($operations), count($current_operation), 'Number of operations should match with WSDL Docs operation nodes.');
// New operations left.
foreach ($operations as $name => $operation) {
$current_operation = $this->entityTypeManager->getStorage('node')
->loadByProperties([
'type' => 'wsdl_docs_operation',
'field_wsdl_docs_soap_ref' => $node->id(),
'title' => $operation['label'],
]);
// Check if no matching wsdl docs operation node present.
$this->assertNotEmpty($current_operation, 'Load wsdl operation node with matching label ' . $operation['label'] . ' and Soap service node id' . $node->id() . '.');
// WSDL Docs operations node.
$current_operation = reset($current_operation);
// Compare.
$docstyle = $styles[$operation['label']] ?? '';
$this->assertEquals($current_operation->field_wsdl_docs_style->value, $docstyle, 'Input field "field_wsdl_docs_style" value should match for WSDL Docs Operation node with ' . $current_operation->label() . '.');
$documentation = $documentations[$operation['label']] ?? '';
$this->assertEquals($documentation, $current_operation->field_wsdl_docs_documentation->value, 'Input field "field_wsdl_docs_documentation" value should match for WSDL Docs Operation node with ' . $current_operation->label() . '.');
$output = $outputs[$operation['label']] ?? '';
$this->assertEquals($current_operation->field_wsdl_docs_output->value, $output, 'Input field "field_wsdl_docs_output" value should match for WSDL Docs Operation node with ' . $current_operation->label() . '.');
$input = $inputs[$operation['label']] ?? '';
$this->assertEquals($current_operation->field_wsdl_docs_input->value, $input, 'Input field "field_wsdl_docs_input" value should match for WSDL Docs Operation node with ' . $current_operation->label() . '.');
}
}
}
