diff --git a/composer.json b/composer.json
index e558f038..59ac76a8 100644
--- a/composer.json
+++ b/composer.json
@@ -32,7 +32,8 @@
"friendsofphp/php-cs-fixer": "^3.0",
"php-amqplib/php-amqplib": "^3.0",
"phpstan/phpstan": "^1.9",
- "phpunit/phpunit": ">=8.5.23 <10"
+ "phpunit/phpunit": ">=8.5.23 <10",
+ "tienvx/pact-php-xml": "dev-main"
},
"autoload": {
"psr-4": {
@@ -53,7 +54,11 @@
"BinaryConsumer\\": "example/binary/consumer/src",
"BinaryConsumer\\Tests\\": "example/binary/consumer/tests",
"BinaryProvider\\": "example/binary/provider/src",
- "BinaryProvider\\Tests\\": "example/binary/provider/tests"
+ "BinaryProvider\\Tests\\": "example/binary/provider/tests",
+ "XmlConsumer\\": "example/xml/consumer/src",
+ "XmlConsumer\\Tests\\": "example/xml/consumer/tests",
+ "XmlProvider\\": "example/xml/provider/src",
+ "XmlProvider\\Tests\\": "example/xml/provider/tests"
}
},
"scripts": {
diff --git a/example/xml/consumer/phpunit.xml b/example/xml/consumer/phpunit.xml
new file mode 100644
index 00000000..62a9eb00
--- /dev/null
+++ b/example/xml/consumer/phpunit.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ ./tests
+
+
+
+
+
+
diff --git a/example/xml/consumer/src/Service/HttpClientService.php b/example/xml/consumer/src/Service/HttpClientService.php
new file mode 100644
index 00000000..a2193e03
--- /dev/null
+++ b/example/xml/consumer/src/Service/HttpClientService.php
@@ -0,0 +1,28 @@
+httpClient = new Client();
+ $this->baseUri = $baseUri;
+ }
+
+ public function getMovies(): string
+ {
+ $response = $this->httpClient->get(new Uri("{$this->baseUri}/movies"), [
+ 'headers' => ['Accept' => 'text/xml; charset=UTF8']
+ ]);
+
+ return $response->getBody();
+ }
+}
diff --git a/example/xml/consumer/tests/Service/HttpClientServiceTest.php b/example/xml/consumer/tests/Service/HttpClientServiceTest.php
new file mode 100644
index 00000000..8e33abf9
--- /dev/null
+++ b/example/xml/consumer/tests/Service/HttpClientServiceTest.php
@@ -0,0 +1,94 @@
+setMethod('GET')
+ ->setPath('/movies')
+ ->addHeader('Accept', 'text/xml; charset=UTF8');
+
+ $xmlBuilder = new XmlBuilder('1.0', 'UTF-8');
+ $xmlBuilder
+ ->start('movies')
+ ->eachLike('movie')
+ ->start('title')
+ ->contentLike('PHP: Behind the Parser')
+ ->end()
+ ->start('characters')
+ ->eachLike('character', [], new Options(examples: 2))
+ ->start('name')
+ ->contentLike('Ms. Coder')
+ ->end()
+ ->start('actor')
+ ->contentLike('Onlivia Actora')
+ ->end()
+ ->end()
+ ->end()
+ ->start('plot')
+ ->contentLike(
+ <<end()
+ ->start('great-lines')
+ ->eachLike('line')
+ ->contentLike('PHP solves all my web problems')
+ ->end()
+ ->end()
+ ->start('rating', ['type' => 'thumbs'])
+ ->contentLike(7)
+ ->end()
+ ->start('rating', ['type' => 'stars'])
+ ->contentLike(5)
+ ->end()
+ ->end()
+ ->end();
+
+ $response = new ProviderResponse();
+ $response
+ ->setStatus(200)
+ ->addHeader('Content-Type', 'text/xml')
+ ->setBody(
+ json_encode($xmlBuilder->getArray())
+ );
+
+ $config = new MockServerConfig();
+ $config
+ ->setConsumer('xmlConsumer')
+ ->setProvider('xmlProvider')
+ ->setPactDir(__DIR__.'/../../../pacts');
+ if ($logLevel = \getenv('PACT_LOGLEVEL')) {
+ $config->setLogLevel($logLevel);
+ }
+ $builder = new InteractionBuilder($config);
+ $builder
+ ->given('Movies exist')
+ ->uponReceiving('A get request to /movies')
+ ->with($request)
+ ->willRespondWith($response);
+
+ $service = new HttpClientService($config->getBaseUri());
+ $moviesResult = new \SimpleXMLElement($service->getMovies());
+ $verifyResult = $builder->verify();
+
+ $this->assertTrue($verifyResult);
+ $this->assertCount(1, $moviesResult);
+ }
+}
diff --git a/example/xml/pacts/xmlConsumer-xmlProvider.json b/example/xml/pacts/xmlConsumer-xmlProvider.json
new file mode 100644
index 00000000..8ead9538
--- /dev/null
+++ b/example/xml/pacts/xmlConsumer-xmlProvider.json
@@ -0,0 +1,122 @@
+{
+ "consumer": {
+ "name": "xmlConsumer"
+ },
+ "interactions": [
+ {
+ "description": "A get request to /movies",
+ "providerStates": [
+ {
+ "name": "Movies exist"
+ }
+ ],
+ "request": {
+ "headers": {
+ "Accept": "text/xml; charset=UTF8"
+ },
+ "method": "GET",
+ "path": "/movies"
+ },
+ "response": {
+ "body": "PHP: Behind the ParserMs. CoderOnlivia ActoraSo, this language. It's like, a programming language. Or is it a\nscripting language? All is revealed in this thrilling horror spoof\nof a documentary.PHP solves all my web problems75",
+ "headers": {
+ "Content-Type": "text/xml"
+ },
+ "matchingRules": {
+ "body": {
+ "$.movies.movie": {
+ "combine": "AND",
+ "matchers": [
+ {
+ "match": "type"
+ }
+ ]
+ },
+ "$.movies.movie.characters.character": {
+ "combine": "AND",
+ "matchers": [
+ {
+ "match": "type"
+ }
+ ]
+ },
+ "$.movies.movie.characters.character.actor.#text": {
+ "combine": "AND",
+ "matchers": [
+ {
+ "match": "type"
+ }
+ ]
+ },
+ "$.movies.movie.characters.character.name.#text": {
+ "combine": "AND",
+ "matchers": [
+ {
+ "match": "type"
+ }
+ ]
+ },
+ "$.movies.movie.great-lines.line": {
+ "combine": "AND",
+ "matchers": [
+ {
+ "match": "type"
+ }
+ ]
+ },
+ "$.movies.movie.great-lines.line.#text": {
+ "combine": "AND",
+ "matchers": [
+ {
+ "match": "type"
+ }
+ ]
+ },
+ "$.movies.movie.plot.#text": {
+ "combine": "AND",
+ "matchers": [
+ {
+ "match": "type"
+ }
+ ]
+ },
+ "$.movies.movie.rating.#text": {
+ "combine": "AND",
+ "matchers": [
+ {
+ "match": "type"
+ },
+ {
+ "match": "type"
+ }
+ ]
+ },
+ "$.movies.movie.title.#text": {
+ "combine": "AND",
+ "matchers": [
+ {
+ "match": "type"
+ }
+ ]
+ }
+ },
+ "header": {}
+ },
+ "status": 200
+ }
+ }
+ ],
+ "metadata": {
+ "pactRust": {
+ "ffi": "0.4.7",
+ "mockserver": "1.2.3",
+ "models": "1.1.9"
+ },
+ "pactSpecification": {
+ "version": "3.0.0"
+ }
+ },
+ "provider": {
+ "name": "xmlProvider"
+ }
+}
\ No newline at end of file
diff --git a/example/xml/provider/phpunit.xml b/example/xml/provider/phpunit.xml
new file mode 100644
index 00000000..62a9eb00
--- /dev/null
+++ b/example/xml/provider/phpunit.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ ./tests
+
+
+
+
+
+
diff --git a/example/xml/provider/public/index.php b/example/xml/provider/public/index.php
new file mode 100644
index 00000000..458ec3e1
--- /dev/null
+++ b/example/xml/provider/public/index.php
@@ -0,0 +1,53 @@
+createXMLArray()
+ ->start('movies')
+ ->start('movie')
+ ->add('title', 'PHP: Behind the Parser')
+ ->start('characters')
+ ->start('character')
+ ->add('name', 'Ms. Coder')
+ ->add('actor', 'Onlivia Actora')
+ ->end()
+ ->start('character')
+ ->add('name', 'Mr. Coder')
+ ->add('actor', 'El ActÓr')
+ ->end()
+ ->end()
+ ->add('plot', <<start('great-lines')
+ ->add('line', 'PHP solves all my web problems')
+ ->end()
+ ->add('rating', 7, ['type' => 'thumbs'])
+ ->add('rating', 5, ['type' => 'stars'])
+ ->end()
+ ->end();
+
+$app = AppFactory::create();
+
+$app->get('/movies', function (Request $request, Response $response) use ($xmlBuilder) {
+ $response->getBody()->write($xmlBuilder->getXml());
+
+ return $response->withHeader('Content-Type', 'text/xml');
+});
+
+$app->post('/pact-change-state', function (Request $request, Response $response) {
+ return $response;
+});
+
+$app->run();
diff --git a/example/xml/provider/tests/PactVerifyTest.php b/example/xml/provider/tests/PactVerifyTest.php
new file mode 100644
index 00000000..82a64982
--- /dev/null
+++ b/example/xml/provider/tests/PactVerifyTest.php
@@ -0,0 +1,66 @@
+process = new Process(['php', '-S', '127.0.0.1:7202', '-t', __DIR__ . '/../public/']);
+
+ $this->process->start();
+ $this->process->waitUntil(function (): bool {
+ $fp = @fsockopen('127.0.0.1', 7202);
+ $isOpen = is_resource($fp);
+ if ($isOpen) {
+ fclose($fp);
+ }
+
+ return $isOpen;
+ });
+ }
+
+ /**
+ * Stop the web server process once complete.
+ */
+ protected function tearDown(): void
+ {
+ $this->process->stop();
+ }
+
+ /**
+ * This test will run after the web server is started.
+ */
+ public function testPactVerifyConsumer()
+ {
+ $config = new VerifierConfig();
+ $config->getProviderInfo()
+ ->setName('xmlProvider') // Providers name to fetch.
+ ->setHost('localhost')
+ ->setPort(7202);
+ $config->getProviderState()
+ ->setStateChangeUrl(new Uri('http://localhost:7202/pact-change-state'))
+ ;
+ if ($level = \getenv('PACT_LOGLEVEL')) {
+ $config->setLogLevel($level);
+ }
+
+ $verifier = new Verifier($config);
+ $verifier->addFile(__DIR__ . '/../../pacts/xmlConsumer-xmlProvider.json');
+
+ $verifyResult = $verifier->verify();
+
+ $this->assertTrue($verifyResult);
+ }
+}