diff --git a/example/xml/consumer/tests/Service/HttpClientServiceTest.php b/example/xml/consumer/tests/Service/HttpClientServiceTest.php index 032e1664..fdb27044 100644 --- a/example/xml/consumer/tests/Service/HttpClientServiceTest.php +++ b/example/xml/consumer/tests/Service/HttpClientServiceTest.php @@ -72,11 +72,42 @@ public function testGetMovies() $xmlBuilder->attribute('type', $matcher->regex('stars', 'stars|thumbs')), $xmlBuilder->contentLike(6), ), - // TODO: implement XML generators - // $xmlBuilder->add( - // $xmlBuilder->name('release-date'), - // $xmlBuilder->content($matcher->date('dd-MM-yyyy')), - // ), + // Generators + $xmlBuilder->add( + $xmlBuilder->name('release-date'), + $xmlBuilder->content($matcher->date('dd-MM-yyyy')), + $xmlBuilder->add( + $xmlBuilder->name('china'), + $xmlBuilder->content($matcher->date('dd-MM-yyyy')), + ), + ), + $xmlBuilder->add( + $xmlBuilder->name('specs'), + $xmlBuilder->attribute('runtime', $matcher->regex(null, '\d+ hours [0-5]?[0-9] minutes')), + $xmlBuilder->attribute('aspect-ratio', $matcher->regex(null, '([0-9]+[.])?[0-9]+:[0-9]+')), + $xmlBuilder->attribute('color', $matcher->regex(null, 'color|black&white')), + ), + $xmlBuilder->add( + $xmlBuilder->name('also-known-as'), + $xmlBuilder->content($matcher->string()), + $xmlBuilder->attribute('xmlns:aka', 'http://example.com/movies'), + $xmlBuilder->add( + $xmlBuilder->name('aka:united-states'), + $xmlBuilder->content($matcher->string()), + ), + $xmlBuilder->add( + $xmlBuilder->name('aka:australia'), + $xmlBuilder->content($matcher->string()), + ), + $xmlBuilder->add( + $xmlBuilder->name('aka:argentina'), + $xmlBuilder->content($matcher->string()), + ), + $xmlBuilder->add( + $xmlBuilder->name('aka:brazil'), + $xmlBuilder->content($matcher->string()), + ), + ), ), ); @@ -107,18 +138,56 @@ public function testGetMovies() $this->assertTrue($verifyResult); $this->assertCount(1, $movies->movie); - $this->assertEquals('Big Buck Bunny', $movies->movie[0]->title); + $this->assertXmlContent('Big Buck Bunny', $movies->movie[0]->title); // TODO: investigate why mock server replace "\r\n" by "\n" on Windows - $this->assertEquals(str_replace("\r\n", "\n", $plot), $movies->movie[0]->plot); - $this->assertCount(1, $movies->movie[0]->{'great-lines'}->line); - $this->assertEquals('Open source movie', $movies->movie[0]->{'great-lines'}->line[0]); - $this->assertEquals('6', $movies->movie[0]->rating); + $this->assertXmlContent(str_replace("\r\n", "\n", $plot), $movies->movie[0]->plot); + $this->assertXmlContent('Open source movie', $movies->movie[0]->{'great-lines'}->line); + $this->assertXmlContent('6', $movies->movie[0]->rating); + $this->assertXmlAttribute('stars', 'type', $movies->movie[0]->rating); $this->assertCount(2, $movies->movie[0]->characters->character); - $this->assertEquals('Big Buck Bunny', $movies->movie[0]->characters->character[0]->name); - $this->assertEquals('Jan Morgenstern', $movies->movie[0]->characters->character[0]->actor); - // TODO: implement XML generators - $this->assertEquals('', $movies->movie[0]->characters->character[1]->name); - $this->assertEquals('', $movies->movie[0]->characters->character[1]->actor); - //$this->assertEquals('', $movies->movie[0]->{'release-date'}[0]); + $this->assertXmlContent('Big Buck Bunny', $movies->movie[0]->characters->character[0]->name); + $this->assertXmlContent('Jan Morgenstern', $movies->movie[0]->characters->character[0]->actor); + // TODO: investigate why content of the second element (examples = 2) is empty + $this->assertXmlContent('', $movies->movie[0]->characters->character[1]->name); + $this->assertXmlContent('', $movies->movie[0]->characters->character[1]->actor); + // Generators + $this->assertXmlContentGenerated($movies->movie[0]->{'release-date'}); + $this->assertXmlContentGenerated($movies->movie[0]->{'release-date'}[0]->china); + $this->assertXmlAttributeGenerated('runtime', $movies->movie[0]->specs); + $this->assertXmlAttributeGenerated('aspect-ratio', $movies->movie[0]->specs); + $this->assertXmlAttributeGenerated('color', $movies->movie[0]->specs); + $this->assertXmlContentGenerated($movies->movie[0]->{'also-known-as'}); + $this->assertXmlContentGenerated($movies->movie[0]->{'also-known-as'}->children('aka', true)->{'united-states'}); + $this->assertXmlContentGenerated($movies->movie[0]->{'also-known-as'}->children('aka', true)->{'australia'}); + $this->assertXmlContentGenerated($movies->movie[0]->{'also-known-as'}->children('aka', true)->{'argentina'}); + $this->assertXmlContentGenerated($movies->movie[0]->{'also-known-as'}->children('aka', true)->{'brazil'}); + } + + private function assertXmlContent(string $expected, \SimpleXMLElement $element): void + { + $this->assertCount(1, $element); + $this->assertSame($expected, (string)$element[0]); + } + + private function assertXmlContentGenerated(\SimpleXMLElement $element): void + { + $this->assertCount(1, $element); + $this->assertNotSame('', (string)$element[0]); + } + + private function assertXmlAttribute(string $expected, string $key, \SimpleXMLElement $element): void + { + $this->assertCount(1, $element); + $attributes = $element[0]->attributes(); + $this->assertNotNull($attributes); + $this->assertSame($expected, (string)$attributes[$key]); + } + + private function assertXmlAttributeGenerated(string $key, \SimpleXMLElement $element): void + { + $this->assertCount(1, $element); + $attributes = $element[0]->attributes(); + $this->assertNotNull($attributes); + $this->assertNotSame('', (string)$attributes[$key]); } } diff --git a/example/xml/pacts/xmlConsumer-xmlProvider.json b/example/xml/pacts/xmlConsumer-xmlProvider.json index 1caa5069..66633daa 100644 --- a/example/xml/pacts/xmlConsumer-xmlProvider.json +++ b/example/xml/pacts/xmlConsumer-xmlProvider.json @@ -31,7 +31,51 @@ "path": "/movies" }, "response": { - "body": "Big Buck BunnyBig Buck BunnyJan MorgensternThe plot follows a day in the life of Big Buck Bunny, during which time he meets three bullying rodents: the leader, Frank the flying squirrel, and his sidekicks Rinky the red squirrel and Gimera the chinchilla.\nThe rodents amuse themselves by harassing helpless creatures of the forest by throwing fruits, nuts, and rocks at them.Open source movie6List of movies", + "body": "Big Buck BunnyBig Buck BunnyJan MorgensternThe plot follows a day in the life of Big Buck Bunny, during which time he meets three bullying rodents: the leader, Frank the flying squirrel, and his sidekicks Rinky the red squirrel and Gimera the chinchilla.\nThe rodents amuse themselves by harassing helpless creatures of the forest by throwing fruits, nuts, and rocks at them.Open source movie6List of movies", + "generators": { + "body": { + "$.movies.movie.also-known-as.#text": { + "size": 10, + "type": "RandomString" + }, + "$.movies.movie.also-known-as.aka:argentina.#text": { + "size": 10, + "type": "RandomString" + }, + "$.movies.movie.also-known-as.aka:australia.#text": { + "size": 10, + "type": "RandomString" + }, + "$.movies.movie.also-known-as.aka:brazil.#text": { + "size": 10, + "type": "RandomString" + }, + "$.movies.movie.also-known-as.aka:united-states.#text": { + "size": 10, + "type": "RandomString" + }, + "$.movies.movie.release-date.#text": { + "format": "dd-MM-yyyy", + "type": "Date" + }, + "$.movies.movie.release-date.china.#text": { + "format": "dd-MM-yyyy", + "type": "Date" + }, + "$.movies.movie.specs['@aspect-ratio']": { + "regex": "([0-9]+[.])?[0-9]+:[0-9]+", + "type": "Regex" + }, + "$.movies.movie.specs['@color']": { + "regex": "color|black&white", + "type": "Regex" + }, + "$.movies.movie.specs['@runtime']": { + "regex": "\\d+ hours [0-5]?[0-9] minutes", + "type": "Regex" + } + } + }, "headers": { "Content-Type": "application/xml" }, @@ -45,6 +89,46 @@ } ] }, + "$.movies.movie.also-known-as.#text": { + "combine": "AND", + "matchers": [ + { + "match": "type" + } + ] + }, + "$.movies.movie.also-known-as.aka:argentina.#text": { + "combine": "AND", + "matchers": [ + { + "match": "type" + } + ] + }, + "$.movies.movie.also-known-as.aka:australia.#text": { + "combine": "AND", + "matchers": [ + { + "match": "type" + } + ] + }, + "$.movies.movie.also-known-as.aka:brazil.#text": { + "combine": "AND", + "matchers": [ + { + "match": "type" + } + ] + }, + "$.movies.movie.also-known-as.aka:united-states.#text": { + "combine": "AND", + "matchers": [ + { + "match": "type" + } + ] + }, "$.movies.movie.characters.character": { "combine": "AND", "matchers": [ @@ -110,6 +194,51 @@ } ] }, + "$.movies.movie.release-date.#text": { + "combine": "AND", + "matchers": [ + { + "format": "dd-MM-yyyy", + "match": "date" + } + ] + }, + "$.movies.movie.release-date.china.#text": { + "combine": "AND", + "matchers": [ + { + "format": "dd-MM-yyyy", + "match": "date" + } + ] + }, + "$.movies.movie.specs['@aspect-ratio']": { + "combine": "AND", + "matchers": [ + { + "match": "regex", + "regex": "([0-9]+[.])?[0-9]+:[0-9]+" + } + ] + }, + "$.movies.movie.specs['@color']": { + "combine": "AND", + "matchers": [ + { + "match": "regex", + "regex": "color|black&white" + } + ] + }, + "$.movies.movie.specs['@runtime']": { + "combine": "AND", + "matchers": [ + { + "match": "regex", + "regex": "\\d+ hours [0-5]?[0-9] minutes" + } + ] + }, "$.movies.movie.title.#text": { "combine": "AND", "matchers": [ @@ -129,8 +258,7 @@ } ] } - }, - "status": {} + } }, "status": 200 } @@ -138,9 +266,9 @@ ], "metadata": { "pactRust": { - "ffi": "0.4.22", - "mockserver": "1.2.9", - "models": "1.2.3" + "ffi": "0.4.27", + "mockserver": "1.2.11", + "models": "1.2.7" }, "pactSpecification": { "version": "3.0.0" diff --git a/src/PhpPact/Xml/XmlText.php b/src/PhpPact/Xml/XmlText.php index b21b251e..9f135954 100644 --- a/src/PhpPact/Xml/XmlText.php +++ b/src/PhpPact/Xml/XmlText.php @@ -3,6 +3,7 @@ namespace PhpPact\Xml; use JsonSerializable; +use PhpPact\Consumer\Matcher\Formatters\Xml\XmlContentFormatter; use PhpPact\Consumer\Matcher\Model\MatcherInterface; class XmlText implements JsonSerializable @@ -14,7 +15,7 @@ public function __construct(private string|float|int|bool|null|MatcherInterface public function jsonSerialize(): mixed { if ($this->content instanceof MatcherInterface) { - return $this->content->jsonSerialize(); + return $this->content->withFormatter(new XmlContentFormatter())->jsonSerialize(); } return [