diff --git a/resources/schemas/ws-securitypolicy-1.2.xsd b/resources/schemas/ws-securitypolicy-1.2.xsd
index 7270463b..b52f120d 100644
--- a/resources/schemas/ws-securitypolicy-1.2.xsd
+++ b/resources/schemas/ws-securitypolicy-1.2.xsd
@@ -101,7 +101,7 @@ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
+
4.3.2 RequiredParts Assertion
diff --git a/src/Utils/XPath.php b/src/Utils/XPath.php
new file mode 100644
index 00000000..cba95d16
--- /dev/null
+++ b/src/Utils/XPath.php
@@ -0,0 +1,41 @@
+registerNamespace('addr', C::NS_ADDR);
+ $xp->registerNamespace('auth', C::NS_AUTH);
+ $xp->registerNamespace('fed', C::NS_FED);
+ $xp->registerNamespace('trust', C::NS_TRUST);
+ $xp->registerNamespace('policy', C::NS_POLICY);
+ $xp->registerNamespace('sp', C::NS_SEC_POLICY);
+ $xp->registerNamespace('wsse', C::NS_SEC_EXT);
+ $xp->registerNamespace('wsu', C::NS_SEC_UTIL);
+
+ return $xp;
+ }
+}
diff --git a/src/XML/sp/AbstractEmptyType.php b/src/XML/sp/AbstractEmptyType.php
index 817f645b..d9b15daf 100644
--- a/src/XML/sp/AbstractEmptyType.php
+++ b/src/XML/sp/AbstractEmptyType.php
@@ -6,10 +6,6 @@
use DOMElement;
use SimpleSAML\Assert\Assert;
-/use SimpleSAML\XML\Exception\InvalidDOMElementException;
-//use SimpleSAML\XML\Exception\SchemaViolationException;
-use SimpleSAML\XML\ExtendableAttributesTrait;
-use SimpleSAML\XML\XsNamespace as NS;
use function sprintf;
@@ -20,26 +16,16 @@
*/
abstract class AbstractEmptyType extends AbstractSpElement
{
- use ExtendableAttributesTrait;
-
- /** The namespace-attribute for the xs:anyAttribute element */
- public const XS_ANY_ATTR_NAMESPACE = NS::ANY;
-
-
/**
- * AbstractQNameAssertionType constructor.
- *
- * @param list<\SimpleSAML\XML\Attribute> $namespacedAttributes
+ * AbstractEmptyType constructor.
*/
final public function __construct(
- array $namespacedAttributes = []
) {
- $this->setAttributesNS($namespacedAttributes);
}
/**
- * Initialize an QNameAssertionType.
+ * Initialize an EmptyType.
*
* Note: this method cannot be used when extending this class, if the constructor has a different signature.
*
@@ -55,12 +41,12 @@ public static function fromXML(DOMElement $xml): static
Assert::eq(
$xml->localName,
$qualifiedName,
- sprintf('Unexpected name for Empty: %s. Expected: %s.', $xml->localName, $qualifiedName),
+ sprintf('Unexpected name for EmptyType: %s. Expected: %s.', $xml->localName, $qualifiedName),
InvalidDOMElementException::class
);
- return new static(self::getAttributesNSFromXML($xml));
+ return new static();
}
@@ -72,12 +58,6 @@ public static function fromXML(DOMElement $xml): static
*/
public function toXML(DOMElement $parent = null): DOMElement
{
- $e = $this->instantiateParentElement($parent);
-
- foreach ($this->getAttributesNS() as $attr) {
- $attr->toXML($e);
- }
-
- return $e;
+ return $this->instantiateParentElement($parent);
}
}
diff --git a/src/XML/sp/AbstractHeaderType.php b/src/XML/sp/AbstractHeaderType.php
new file mode 100644
index 00000000..4d323b8d
--- /dev/null
+++ b/src/XML/sp/AbstractHeaderType.php
@@ -0,0 +1,128 @@
+ $namespacedAttributes
+ */
+ final public function __construct(
+ protected string $namespace,
+ protected ?string $name = null,
+ array $namespacedAttributes = []
+ ) {
+ Assert::nullOrValidURI($namespace);
+ Assert::validQName($name);
+
+ $this->setAttributesNS($namespacedAttributes);
+ }
+
+
+ /**
+ * Collect the value of the Name property.
+ *
+ * @return string
+ */
+ public function getName(): string
+ {
+ return $this->name;
+ }
+
+
+ /**
+ * Collect the value of the Namespace property.
+ *
+ * @return string
+ */
+ public function getNamespace(): string
+ {
+ return $this->namespace;
+ }
+
+
+ /**
+ * Initialize an HeaderType.
+ *
+ * Note: this method cannot be used when extending this class, if the constructor has a different signature.
+ *
+ * @param \DOMElement $xml The XML element we should load.
+ * @return static
+ *
+ * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
+ * if the qualified name of the supplied element is wrong
+ */
+ public static function fromXML(DOMElement $xml): static
+ {
+ $qualifiedName = static::getClassName(static::class);
+ Assert::eq(
+ $xml->localName,
+ $qualifiedName,
+ sprintf('Unexpected name for HeaderType: %s. Expected: %s.', $xml->localName, $qualifiedName),
+ InvalidDOMElementException::class
+ );
+
+ $namespacedAttributes = self::getAttributesNSFromXML($xml);
+ foreach ($namespacedAttributes as $i => $attr) {
+ if ($attr->getNamespaceURI() === null) {
+ if ($attr->getAttrName() === 'Name' || $attr->getAttrName() === 'Namespace') {
+ unset($namespacedAttributes[$i]);
+ }
+ }
+ }
+
+ return new static(
+ self::getAttribute($xml, 'Namespace'),
+ self::getOptionalAttribute($xml, 'Name', null),
+ $namespacedAttributes,
+ );
+ }
+
+
+ /**
+ * Convert this element to XML.
+ *
+ * @param \DOMElement|null $parent The element we should append this element to.
+ * @return \DOMElement
+ */
+ public function toXML(DOMElement $parent = null): DOMElement
+ {
+ $e = $this->instantiateParentElement($parent);
+
+ if ($this->getName() !== null) {
+ $e->setAttribute('Name', $this->getName());
+ }
+
+ $e->setAttribute('Namespace', $this->getNamespace());
+
+ foreach ($this->getAttributesNS() as $attr) {
+ $attr->toXML($e);
+ }
+
+ return $e;
+ }
+}
diff --git a/src/XML/sp/AbstractReqPartsType.php b/src/XML/sp/AbstractReqPartsType.php
new file mode 100644
index 00000000..a08639a7
--- /dev/null
+++ b/src/XML/sp/AbstractReqPartsType.php
@@ -0,0 +1,142 @@
+setElements($details);
+ $this->setAttributesNS($namespacedAttributes);
+ }
+
+
+ /**
+ * Collect the Header
+ *
+ * @return \SimpleSAML\WSSecurity\XML\sp\Header[]
+ */
+ public function getHeader(): array
+ {
+ return $this->header;
+ }
+
+
+ /**
+ * Test if an object, at the state it's in, would produce an empty XML-element
+ *
+ * @return bool
+ */
+ public function isEmptyElement(): bool
+ {
+ return empty($this->getElements())
+ && empty($this->getHeader())
+ && empty($this->getAttributesNS());
+ }
+
+
+ /**
+ * Initialize an ReqPartsType.
+ *
+ * Note: this method cannot be used when extending this class, if the constructor has a different signature.
+ *
+ * @param \DOMElement $xml The XML element we should load.
+ * @return static
+ *
+ * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
+ * if the qualified name of the supplied element is wrong
+ */
+ public static function fromXML(DOMElement $xml): static
+ {
+ $qualifiedName = static::getClassName(static::class);
+ Assert::eq(
+ $xml->localName,
+ $qualifiedName,
+ sprintf('Unexpected name for Empty: %s. Expected: %s.', $xml->localName, $qualifiedName),
+ InvalidDOMElementException::class
+ );
+
+ $header = Header::getChildrenOfClass($xml);
+ Assert::maxcount($header, 1, TooManyElementsException::class);
+
+ $details = [];
+ foreach ($xml->childNodes as $detail) {
+ if (!($detail instanceof DOMElement)) {
+ continue;
+ } elseif ($detail->namespaceURI === static::NS) {
+ continue;
+ }
+
+ $details[] = new Chunk($detail);
+ }
+
+ return new static(
+ $header,
+ $details,
+ self::getAttributesNSFromXML($xml),
+ );
+ }
+
+
+ /**
+ * Convert this element to XML.
+ *
+ * @param \DOMElement|null $parent The element we should append this element to.
+ * @return \DOMElement
+ */
+ public function toXML(DOMElement $parent = null): DOMElement
+ {
+ $e = $this->instantiateParentElement($parent);
+
+ foreach ($this->getHeader() as $header) {
+ $header->toXML($e);
+ }
+
+ foreach ($this->getElements() as $elt) {
+ $elt->toXML($e);
+ }
+
+ foreach ($this->getAttributesNS() as $attr) {
+ $attr->toXML($e);
+ }
+
+ return $e;
+ }
+}
diff --git a/src/XML/sp/AbstractSePartsType.php b/src/XML/sp/AbstractSePartsType.php
new file mode 100644
index 00000000..c1a61492
--- /dev/null
+++ b/src/XML/sp/AbstractSePartsType.php
@@ -0,0 +1,184 @@
+setElements($details);
+ $this->setAttributesNS($namespacedAttributes);
+ }
+
+
+ /**
+ * Collect the Body
+ *
+ * @return \SimpleSAML\WSSecurity\XML\sp\Body|null
+ */
+ public function getBody(): ?Body
+ {
+ return $this->body;
+ }
+
+
+ /**
+ * Collect the Header
+ *
+ * @return \SimpleSAML\WSSecurity\XML\sp\Header[]
+ */
+ public function getHeader(): array
+ {
+ return $this->header;
+ }
+
+
+ /**
+ * Collect the Attachments
+ *
+ * @return \SimpleSAML\WSSecurity\XML\sp\Attachments|null
+ */
+ public function getAttachments(): ?Attachments
+ {
+ return $this->attachments;
+ }
+
+
+ /**
+ * Test if an object, at the state it's in, would produce an empty XML-element
+ *
+ * @return bool
+ */
+ public function isEmptyElement(): bool
+ {
+ return empty($this->getElements())
+ && empty($this->getBody())
+ && empty($this->getHeader())
+ && empty($this->getAttachments())
+ && empty($this->getAttributesNS());
+ }
+
+
+ /**
+ * Initialize an SePartsType.
+ *
+ * Note: this method cannot be used when extending this class, if the constructor has a different signature.
+ *
+ * @param \DOMElement $xml The XML element we should load.
+ * @return static
+ *
+ * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
+ * if the qualified name of the supplied element is wrong
+ */
+ public static function fromXML(DOMElement $xml): static
+ {
+ $qualifiedName = static::getClassName(static::class);
+ Assert::eq(
+ $xml->localName,
+ $qualifiedName,
+ sprintf('Unexpected name for Empty: %s. Expected: %s.', $xml->localName, $qualifiedName),
+ InvalidDOMElementException::class
+ );
+
+ $body = Body::getChildrenOfClass($xml);
+
+ $header = Header::getChildrenOfClass($xml);
+ Assert::maxcount($header, 1, TooManyElementsException::class);
+
+ $attachments = Attachments::getChildrenOfClass($xml);
+
+ $details = [];
+ foreach ($xml->childNodes as $detail) {
+ if (!($detail instanceof DOMElement)) {
+ continue;
+ } elseif ($detail->namespaceURI === static::NS) {
+ continue;
+ }
+
+ $details[] = new Chunk($detail);
+ }
+
+ return new static(
+ array_pop($body),
+ $header,
+ array_pop($attachments),
+ $details,
+ self::getAttributesNSFromXML($xml),
+ );
+ }
+
+
+ /**
+ * Convert this element to XML.
+ *
+ * @param \DOMElement|null $parent The element we should append this element to.
+ * @return \DOMElement
+ */
+ public function toXML(DOMElement $parent = null): DOMElement
+ {
+ $e = $this->instantiateParentElement($parent);
+
+ if ($this->getBody() !== null) {
+ $this->getBody()->toXML($e);
+ }
+
+ foreach ($this->getHeader() as $header) {
+ $header->toXML($e);
+ }
+
+ if ($this->getAttachments() !== null) {
+ $this->getAttachments()->toXML($e);
+ }
+
+ foreach ($this->getElements() as $elt) {
+ $elt->toXML($e);
+ }
+
+ foreach ($this->getAttributesNS() as $attr) {
+ $attr->toXML($e);
+ }
+
+ return $e;
+ }
+}
diff --git a/src/XML/sp/Attachments.php b/src/XML/sp/Attachments.php
new file mode 100644
index 00000000..65d7b910
--- /dev/null
+++ b/src/XML/sp/Attachments.php
@@ -0,0 +1,14 @@
+assertEquals(
+ self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
+ strval($attachments),
+ );
+ }
+
+
+ // test unmarshalling
+
+
+ /**
+ * Test that creating an Attachments from XML succeeds.
+ */
+ public function testUnmarshalling(): void
+ {
+ $attachments = Attachments::fromXML(self::$xmlRepresentation->documentElement);
+
+ $this->assertEquals(
+ self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
+ strval($attachments),
+ );
+ }
+}
diff --git a/tests/WSSecurity/XML/sp/BodyTest.php b/tests/WSSecurity/XML/sp/BodyTest.php
index b9403040..bf4c6f85 100644
--- a/tests/WSSecurity/XML/sp/BodyTest.php
+++ b/tests/WSSecurity/XML/sp/BodyTest.php
@@ -6,9 +6,9 @@
use DOMDocument;
use PHPUnit\Framework\TestCase;
+use SimpleSAML\Test\WSSecurity\Constants as C;
use SimpleSAML\WSSecurity\XML\sp\Body;
use SimpleSAML\XML\DOMDocumentFactory;
-use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait;
use SimpleSAML\XML\TestUtils\SerializableElementTestTrait;
use function dirname;
@@ -17,13 +17,13 @@
* Class \SimpleSAML\WSSecurity\XML\sp\BodyTest
*
* @covers \SimpleSAML\WSSecurity\XML\sp\Body
+ * @covers \SimpleSAML\WSSecurity\XML\sp\AbstractEmptyType
* @covers \SimpleSAML\WSSecurity\XML\sp\AbstractSpElement
*
* @package tvdijen/ws-security
*/
final class BodyTest extends TestCase
{
- use SchemaValidationTestTrait;
use SerializableElementTestTrait;
@@ -31,8 +31,6 @@ final class BodyTest extends TestCase
*/
public static function setUpBeforeClass(): void
{
- self::$schemaFile = dirname(__FILE__, 5) . '/resources/schemas/ws-securitypolicy-1.2.xsd';
-
self::$testedClass = Body::class;
self::$xmlRepresentation = DOMDocumentFactory::fromFile(
@@ -45,16 +43,15 @@ public static function setUpBeforeClass(): void
/**
- * Test that creating a QNameAssertionType from scratch works.
+ * Test that creating a Body from scratch works.
*/
public function testMarshalling(): void
{
- $attr = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1');
- $qns = new static::$testedClass([$attr]);
+ $body = new Body();
$this->assertEquals(
- static::$xmlRepresentation->saveXML(static::$xmlRepresentation->documentElement),
- strval($qns),
+ self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
+ strval($body),
);
}
@@ -63,15 +60,15 @@ public function testMarshalling(): void
/**
- * Test that creating a QNameAssertionType from XML succeeds.
+ * Test that creating a Body from XML succeeds.
*/
public function testUnmarshalling(): void
{
- $qna = static::$testedClass::fromXML(static::$xmlRepresentation->documentElement);
+ $body = Body::fromXML(self::$xmlRepresentation->documentElement);
$this->assertEquals(
- static::$xmlRepresentation->saveXML(static::$xmlRepresentation->documentElement),
- strval($qna),
+ self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
+ strval($body),
);
}
}
diff --git a/tests/WSSecurity/XML/sp/EncryptedPartsTest.php b/tests/WSSecurity/XML/sp/EncryptedPartsTest.php
new file mode 100644
index 00000000..42981886
--- /dev/null
+++ b/tests/WSSecurity/XML/sp/EncryptedPartsTest.php
@@ -0,0 +1,137 @@
+some'
+ )->documentElement);
+
+ $EncryptedParts = new EncryptedParts($body, [$header], $attachments, [$chunk], [$attr]);
+
+ $this->assertEquals(
+ self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
+ strval($EncryptedParts),
+ );
+ }
+
+
+ /**
+ * Adding an empty EncryptedParts element should yield an empty element.
+ */
+ public function testMarshallingEmptyElement(): void
+ {
+ $spns = C::NS_SEC_POLICY;
+ $encryptedParts = new EncryptedParts();
+ $this->assertEquals(
+ "",
+ strval($encryptedParts),
+ );
+ $this->assertTrue($encryptedParts->isEmptyElement());
+ }
+
+
+ /**
+ */
+ public function testMarshallingElementOrdering(): void
+ {
+ $attr = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1');
+ $body = new Body();
+ $header = new Header('urn:x-simplesamlphp:namespace', 'ssp:name', [$attr]);
+ $attachments = new Attachments();
+ $chunk = new Chunk(DOMDocumentFactory::fromString(
+ 'some'
+ )->documentElement);
+
+ $EncryptedParts = new EncryptedParts($body, [$header], $attachments, [$chunk], [$attr]);
+ $EncryptedPartsElement = $EncryptedParts->toXML();
+
+ // Test for a Body
+ $xpCache = XPath::getXPath($EncryptedPartsElement);
+ $EncryptedPartsElements = XPath::xpQuery($EncryptedPartsElement, './sp:Body', $xpCache);
+ $this->assertCount(1, $EncryptedPartsElements);
+
+ // Test ordering of EncryptedParts contents
+ /** @psalm-var \DOMElement[] $EncryptedPartsElements */
+ $EncryptedPartsElements = XPath::xpQuery($EncryptedPartsElement, './sp:Body/following-sibling::*', $xpCache);
+ $this->assertCount(3, $EncryptedPartsElements);
+ $this->assertEquals('sp:Header', $EncryptedPartsElements[0]->tagName);
+ $this->assertEquals('sp:Attachments', $EncryptedPartsElements[1]->tagName);
+ $this->assertEquals('ssp:Chunk', $EncryptedPartsElements[2]->tagName);
+ }
+
+
+ // test unmarshalling
+
+
+ /**
+ * Test that creating a EncryptedParts from XML succeeds.
+ */
+ public function testUnmarshalling(): void
+ {
+ $EncryptedParts = EncryptedParts::fromXML(self::$xmlRepresentation->documentElement);
+
+ $this->assertEquals(
+ self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
+ strval($EncryptedParts),
+ );
+ }
+}
diff --git a/tests/WSSecurity/XML/sp/HeaderTest.php b/tests/WSSecurity/XML/sp/HeaderTest.php
new file mode 100644
index 00000000..5cfdf543
--- /dev/null
+++ b/tests/WSSecurity/XML/sp/HeaderTest.php
@@ -0,0 +1,76 @@
+assertEquals(
+ self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
+ strval($header),
+ );
+ }
+
+
+ // test unmarshalling
+
+
+ /**
+ * Test that creating a Header from XML succeeds.
+ */
+ public function testUnmarshalling(): void
+ {
+ $header = Header::fromXML(self::$xmlRepresentation->documentElement);
+
+ $this->assertEquals(
+ self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
+ strval($header),
+ );
+ }
+}
diff --git a/tests/WSSecurity/XML/sp/RequiredPartsTest.php b/tests/WSSecurity/XML/sp/RequiredPartsTest.php
new file mode 100644
index 00000000..ed1defbf
--- /dev/null
+++ b/tests/WSSecurity/XML/sp/RequiredPartsTest.php
@@ -0,0 +1,128 @@
+assertEquals(
+ "",
+ strval($requiredParts),
+ );
+ $this->assertTrue($requiredParts->isEmptyElement());
+ }
+
+
+ /**
+ */
+ public function testMarshallingElementOrdering(): void
+ {
+ $attr = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1');
+ $header = new Header('urn:x-simplesamlphp:namespace', 'ssp:name', [$attr]);
+ $chunk = new Chunk(DOMDocumentFactory::fromString(
+ 'some'
+ )->documentElement);
+
+ $RequiredParts = new RequiredParts([$header], [$chunk], [$attr]);
+ $RequiredPartsElement = $RequiredParts->toXML();
+
+ // Test for a Header
+ $xpCache = XPath::getXPath($RequiredPartsElement);
+ $RequiredPartsElements = XPath::xpQuery($RequiredPartsElement, './sp:Header', $xpCache);
+ $this->assertCount(1, $RequiredPartsElements);
+
+ // Test ordering of RequiredParts contents
+ /** @psalm-var \DOMElement[] $RequiredPartsElements */
+ $RequiredPartsElements = XPath::xpQuery($RequiredPartsElement, './sp:Header/following-sibling::*', $xpCache);
+ $this->assertCount(1, $RequiredPartsElements);
+ $this->assertEquals('ssp:Chunk', $RequiredPartsElements[0]->tagName);
+ }
+
+
+ // test marshalling
+
+
+ /**
+ * Test that creating a RequiredParts from scratch works.
+ */
+ public function testMarshalling(): void
+ {
+ $attr = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1');
+ $header = new Header('urn:x-simplesamlphp:namespace', 'ssp:name', [$attr]);
+ $chunk = new Chunk(DOMDocumentFactory::fromString(
+ 'some'
+ )->documentElement);
+
+ $RequiredParts = new RequiredParts([$header], [$chunk], [$attr]);
+ $this->assertEquals(
+ self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
+ strval($RequiredParts),
+ );
+ }
+
+
+ // test unmarshalling
+
+
+ /**
+ * Test that creating a RequiredParts from XML succeeds.
+ */
+ public function testUnmarshalling(): void
+ {
+ $RequiredParts = RequiredParts::fromXML(self::$xmlRepresentation->documentElement);
+
+ $this->assertEquals(
+ self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
+ strval($RequiredParts),
+ );
+ }
+}
diff --git a/tests/WSSecurity/XML/sp/SignedPartsTest.php b/tests/WSSecurity/XML/sp/SignedPartsTest.php
new file mode 100644
index 00000000..acadca5f
--- /dev/null
+++ b/tests/WSSecurity/XML/sp/SignedPartsTest.php
@@ -0,0 +1,137 @@
+assertEquals(
+ "",
+ strval($signedParts),
+ );
+ $this->assertTrue($signedParts->isEmptyElement());
+ }
+
+
+ // test marshalling
+
+
+ /**
+ * Test that creating a SignedParts from scratch works.
+ */
+ public function testMarshalling(): void
+ {
+ $attr = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1');
+ $body = new Body();
+ $header = new Header('urn:x-simplesamlphp:namespace', 'ssp:name', [$attr]);
+ $attachments = new Attachments();
+ $chunk = new Chunk(DOMDocumentFactory::fromString(
+ 'some'
+ )->documentElement);
+
+ $signedParts = new SignedParts($body, [$header], $attachments, [$chunk], [$attr]);
+ $this->assertEquals(
+ self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
+ strval($signedParts),
+ );
+ }
+
+
+ /**
+ */
+ public function testMarshallingElementOrdering(): void
+ {
+ $attr = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1');
+ $body = new Body();
+ $header = new Header('urn:x-simplesamlphp:namespace', 'ssp:name', [$attr]);
+ $attachments = new Attachments();
+ $chunk = new Chunk(DOMDocumentFactory::fromString(
+ 'some'
+ )->documentElement);
+
+ $SignedParts = new SignedParts($body, [$header], $attachments, [$chunk], [$attr]);
+ $SignedPartsElement = $SignedParts->toXML();
+
+ // Test for a Body
+ $xpCache = XPath::getXPath($SignedPartsElement);
+ $SignedPartsElements = XPath::xpQuery($SignedPartsElement, './sp:Body', $xpCache);
+ $this->assertCount(1, $SignedPartsElements);
+
+ // Test ordering of SignedParts contents
+ /** @psalm-var \DOMElement[] $SignedartsElements */
+ $SignedPartsElements = XPath::xpQuery($SignedPartsElement, './sp:Body/following-sibling::*', $xpCache);
+ $this->assertCount(3, $SignedPartsElements);
+ $this->assertEquals('sp:Header', $SignedPartsElements[0]->tagName);
+ $this->assertEquals('sp:Attachments', $SignedPartsElements[1]->tagName);
+ $this->assertEquals('ssp:Chunk', $SignedPartsElements[2]->tagName);
+ }
+
+
+
+ // test unmarshalling
+
+
+ /**
+ * Test that creating a SignedParts from XML succeeds.
+ */
+ public function testUnmarshalling(): void
+ {
+ $signedParts = SignedParts::fromXML(self::$xmlRepresentation->documentElement);
+
+ $this->assertEquals(
+ self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
+ strval($signedParts),
+ );
+ }
+}
diff --git a/tests/resources/xml/sp_Attachments.xml b/tests/resources/xml/sp_Attachments.xml
new file mode 100644
index 00000000..e0295d5a
--- /dev/null
+++ b/tests/resources/xml/sp_Attachments.xml
@@ -0,0 +1 @@
+
diff --git a/tests/resources/xml/sp_Body.xml b/tests/resources/xml/sp_Body.xml
new file mode 100644
index 00000000..f4468dab
--- /dev/null
+++ b/tests/resources/xml/sp_Body.xml
@@ -0,0 +1 @@
+
diff --git a/tests/resources/xml/sp_EncryptedParts.xml b/tests/resources/xml/sp_EncryptedParts.xml
new file mode 100644
index 00000000..c9ce63b1
--- /dev/null
+++ b/tests/resources/xml/sp_EncryptedParts.xml
@@ -0,0 +1,6 @@
+
+
+
+
+ some
+
diff --git a/tests/resources/xml/sp_Header.xml b/tests/resources/xml/sp_Header.xml
new file mode 100644
index 00000000..56ef7fc3
--- /dev/null
+++ b/tests/resources/xml/sp_Header.xml
@@ -0,0 +1 @@
+
diff --git a/tests/resources/xml/sp_RequiredParts.xml b/tests/resources/xml/sp_RequiredParts.xml
new file mode 100644
index 00000000..45ddb1e9
--- /dev/null
+++ b/tests/resources/xml/sp_RequiredParts.xml
@@ -0,0 +1,4 @@
+
+
+ some
+
diff --git a/tests/resources/xml/sp_SignedParts.xml b/tests/resources/xml/sp_SignedParts.xml
new file mode 100644
index 00000000..87c91e57
--- /dev/null
+++ b/tests/resources/xml/sp_SignedParts.xml
@@ -0,0 +1,6 @@
+
+
+
+
+ some
+