@@ -154,6 +154,21 @@ class AnnotationGeneratorTest extends TestCase
154154 * @throws Exception
155155 */ ' ;
156156
157+ /**
158+ * @var array
159+ */
160+ private static $ normalisedExamples ;
161+
162+ /**
163+ * @var array
164+ */
165+ private static $ truncatedExamples ;
166+
167+ /**
168+ * @var array
169+ */
170+ private static $ exampleSchemas ;
171+
157172 /**
158173 * @var AnnotationGenerator
159174 */
@@ -171,7 +186,7 @@ public function setUp(): void
171186 * @return string String contents of the raw response body. If the file isn't found, an empty string is returned.
172187 * @throws \Exception
173188 */
174- private function getRawExampleResponseForApiEndpoint (string $ apiEndpoint , string $ format = 'json ' ): string
189+ private static function getRawExampleResponseForApiEndpoint (string $ apiEndpoint , string $ format = 'json ' ): string
175190 {
176191 if (!in_array (strtolower ($ format ), ['json ' , 'xml ' , 'tsv ' ])) {
177192 throw new \Exception ('Invalid format: ' . $ format . '. Must be: "json", "xml", or "tsv" ' );
@@ -188,42 +203,65 @@ private function getRawExampleResponseForApiEndpoint(string $apiEndpoint, string
188203 * @return string String contents of the raw response body. If the file isn't found, an empty string is returned.
189204 * @throws \Exception
190205 */
191- private function getRawExampleResponseForPluginMethod (string $ plugin , string $ method , string $ format = 'json ' ): string
206+ private static function getRawExampleResponseForPluginMethod (string $ plugin , string $ method , string $ format = 'json ' ): string
192207 {
193- return $ this -> getRawExampleResponseForApiEndpoint ("{$ plugin }. {$ method }" , $ format );
208+ return self :: getRawExampleResponseForApiEndpoint ("{$ plugin }. {$ method }" , $ format );
194209 }
195210
196211 /**
197- * Get the map of example responses. The default is returning the map for all the example responses after they've
198- * been normalised for schema generation, but before being truncated.
212+ * Get the map of example responses which have been normalised in preparation of building schemas.
199213 *
200- * @param bool $exampleResponseSchemas Return the generated schemas of the example responses.
201- * @param bool $onlyExamplesThatWereTruncated Return only the example responses that were truncated.
214+ * @return array The map of example responses for a bunch of API endpoints.
215+ * E.g. ['plugin.method' => ['json' => '...', 'xml' => '...', 'tsv' => '...']]
216+ */
217+ private static function getNormalisedExamples (): array
218+ {
219+ if (empty (self ::$ normalisedExamples )) {
220+ $ demoExampleResponsesString = file_get_contents (self ::TEST_RESOURCES_DIR . '/ExampleResponsesNormalised/ExamplesFromDemoByType.json ' ) ?: '' ;
221+ $ localExampleResponsesString = file_get_contents (self ::TEST_RESOURCES_DIR . '/ExampleResponsesNormalised/ExamplesFromLocalByType.json ' ) ?: '' ;
222+ $ demoJson = json_decode ($ demoExampleResponsesString , true ) ?? [];
223+ $ localJson = json_decode ($ localExampleResponsesString , true ) ?? [];
224+ self ::$ normalisedExamples = array_merge ($ demoJson , $ localJson );
225+ }
226+
227+ return self ::$ normalisedExamples ;
228+ }
229+
230+ /**
231+ * Get the map of example responses which have been normalised and truncated.
202232 *
203233 * @return array The map of example responses for a bunch of API endpoints.
204234 * E.g. ['plugin.method' => ['json' => '...', 'xml' => '...', 'tsv' => '...']]
205235 */
206- private function getExampleResponsesMap (bool $ exampleResponseSchemas = false , bool $ onlyExamplesThatWereTruncated = false ): array
236+ private static function getTruncatedExamples (bool $ onlyTruncated = false ): array
207237 {
208- if ($ exampleResponseSchemas && $ onlyExamplesThatWereTruncated ) {
209- throw new \Exception ('Only one type of example response can be returned at a time. ' );
238+ if (empty (self ::$ truncatedExamples )) {
239+ $ exampleResponsesPostTruncationString = file_get_contents (self ::TEST_RESOURCES_DIR . '/ExampleResponsesNormalised/ExamplesPostTruncationByType.json ' ) ?: '' ;
240+ self ::$ truncatedExamples = json_decode ($ exampleResponsesPostTruncationString , true ) ?? [];
210241 }
211242
212- if ($ exampleResponseSchemas ) {
213- $ exampleResponseSchemasString = file_get_contents (self ::TEST_RESOURCES_DIR . '/ExampleResponsesNormalised/ExamplesSchemasByType.json ' ) ?: '' ;
214- return json_decode ($ exampleResponseSchemasString , true ) ?? [];
243+ if ($ onlyTruncated ) {
244+ return self ::$ truncatedExamples ;
215245 }
216246
217- if ($ onlyExamplesThatWereTruncated ) {
218- $ exampleResponsesPostTruncationString = file_get_contents (self ::TEST_RESOURCES_DIR . '/ExampleResponsesNormalised/ExamplesPostTruncationByType.json ' ) ?: '' ;
219- return json_decode ($ exampleResponsesPostTruncationString , true ) ?? [];
247+ // Return the normalised examples with any truncated examples overriding them
248+ return array_merge (self ::getNormalisedExamples (), self ::$ truncatedExamples );
249+ }
250+
251+ /**
252+ * Get the map of example schemas.
253+ *
254+ * @return array The map of example schemas for a bunch of API endpoints.
255+ * E.g. ['plugin.method' => ['json' => '...', 'xml' => '...', 'tsv' => '...']]
256+ */
257+ private static function getExampleSchemas (): array
258+ {
259+ if (empty (self ::$ exampleSchemas )) {
260+ $ exampleResponseSchemasString = file_get_contents (self ::TEST_RESOURCES_DIR . '/ExampleResponsesNormalised/ExamplesSchemasByType.json ' ) ?: '' ;
261+ self ::$ exampleSchemas = json_decode ($ exampleResponseSchemasString , true ) ?? [];
220262 }
221263
222- $ demoExampleResponsesString = file_get_contents (self ::TEST_RESOURCES_DIR . '/ExampleResponsesNormalised/ExamplesFromDemoByType.json ' ) ?: '' ;
223- $ localExampleResponsesString = file_get_contents (self ::TEST_RESOURCES_DIR . '/ExampleResponsesNormalised/ExamplesFromLocalByType.json ' ) ?: '' ;
224- $ demoJson = json_decode ($ demoExampleResponsesString , true ) ?? [];
225- $ localJson = json_decode ($ localExampleResponsesString , true ) ?? [];
226- return array_merge ($ demoJson , $ localJson );
264+ return self ::$ exampleSchemas ;
227265 }
228266
229267 public function testGeneratePluginApiAnnotations (): void
@@ -274,7 +312,7 @@ public function testGetResponseInfoFromDocBlock(): void
274312 {
275313 // TODO - Update to use resource file and/or dataprovider to test more than one comment block
276314 $ expected = [
277- 'type ' => 'array '
315+ 'type ' => 'array ' ,
278316 ];
279317 $ this ->assertEquals ($ expected , $ this ->annotationGenerator ->getResponseInfoFromDocBlock (self ::EXAMPLE_API_METHOD_DOC_BLOCK1 ));
280318 }
@@ -297,7 +335,7 @@ public function testBuildVirtualPath(string $pathTemplate, string $pluginName, s
297335 /**
298336 * @return iterable<string, string, string, string>
299337 */
300- public function getTestDataForBuildVirtualPath (): iterable
338+ public static function getTestDataForBuildVirtualPath (): iterable
301339 {
302340 yield 'should be empty when all values are empty ' => ['' , '' , '' , '' ];
303341 yield 'should be empty when template is empty ' => ['' , 'SomePlugin ' , 'SomeMethod ' , '' ];
@@ -729,14 +767,33 @@ public function testGetReportExampleUrlFromMetadata(): void
729767 $ this ->expectNotToPerformAssertions ();
730768 }
731769
732- public function testConvertExampleXmlToObject (): void
770+ /**
771+ * @dataProvider getTestXmlExampleObjectData
772+ *
773+ * @param string $endpoint
774+ * @param string $content
775+ * @param string $expected
776+ *
777+ * @return void
778+ * @throws \Exception
779+ */
780+ public function testConvertExampleXmlToObject (string $ endpoint , string $ content , string $ expected ): void
781+ {
782+ $ this ->assertNotEmpty ($ content , 'The example response should not be empty for endpoint: ' . $ endpoint );
783+ $ this ->assertEquals ($ expected , json_encode ($ this ->annotationGenerator ->convertExampleXmlToObject ($ content )), "The converted XML was not as expected for endpoint $ endpoint. " );
784+ }
785+
786+ /**
787+ * @return iterable<string, string, string>
788+ * @throws \Exception
789+ */
790+ public static function getTestXmlExampleObjectData (): iterable
733791 {
734- $ normalisedMap = $ this -> getExampleResponsesMap ();
792+ $ normalisedMap = self :: getNormalisedExamples ();
735793 foreach (self ::EXAMPLE_API_ENDPOINTS as $ endpoint ) {
736- $ content = $ this ->getRawExampleResponseForApiEndpoint ($ endpoint , 'xml ' );
737- $ this ->assertNotEmpty ($ content , 'The example response should not be empty for endpoint: ' . $ endpoint );
794+ $ content = self ::getRawExampleResponseForApiEndpoint ($ endpoint , 'xml ' );
738795 $ expected = $ normalisedMap [$ endpoint ]['xml ' ] ?? [];
739- $ this -> assertEquals ( $ expected , json_encode ( $ this -> annotationGenerator -> convertExampleXmlToObject ( $ content )), " The converted XML was not as expected for endpoint $ endpoint. " ) ;
796+ yield " converted XML should match expected JSON for $ endpoint endpoint " => [ $ endpoint , $ content , $ expected ] ;
740797 }
741798 }
742799
@@ -746,10 +803,32 @@ public function testDetermineResponses(): void
746803 $ this ->expectNotToPerformAssertions ();
747804 }
748805
749- public function testCutExampleCloseToCharLimit (): void
806+ /**
807+ * @dataProvider getTestTruncatedExampleObjectData
808+ *
809+ * @param string $endpoint
810+ * @param string $type
811+ * @param string $normalisedExample
812+ * @param string $expectedExample
813+ *
814+ * @return void
815+ */
816+ public function testCutExampleCloseToCharLimit (string $ endpoint , string $ type , string $ normalisedExample , string $ expectedExample ): void
750817 {
751- $ truncatedMap = $ this ->getExampleResponsesMap (false , true );
752- $ normalisedMap = $ this ->getExampleResponsesMap ();
818+ $ this ->assertNotEmpty ($ normalisedExample , "The example response should not be empty for endpoint ' $ endpoint' and type ' $ type'. " );
819+ $ result = $ this ->annotationGenerator ->cutExampleCloseToCharLimit ($ normalisedExample , $ type );
820+ // Add a little wiggle room since the truncation isn't exact and might allow a little over the limit
821+ $ this ->assertLessThanOrEqual (AnnotationGenerator::EXAMPLE_CHAR_LIMIT + 30 , strlen ($ result ), "The example response should not exceed the character limit for endpoint ' $ endpoint' and type ' $ type'. " );
822+ $ this ->assertEquals ($ expectedExample , $ result , "The truncated example was not as expected for endpoint ' $ endpoint' and type ' $ type'. " );
823+ }
824+
825+ /**
826+ * @return iterable<string, string, string, string>
827+ */
828+ public static function getTestTruncatedExampleObjectData (): iterable
829+ {
830+ $ truncatedMap = self ::getTruncatedExamples ();
831+ $ normalisedMap = self ::getNormalisedExamples ();
753832 foreach (self ::EXAMPLE_API_ENDPOINTS as $ endpoint ) {
754833 $ normalisedExamples = $ normalisedMap [$ endpoint ] ?? [];
755834
@@ -775,11 +854,7 @@ public function testCutExampleCloseToCharLimit(): void
775854 continue ;
776855 }
777856
778- $ this ->assertNotEmpty ($ normalisedExample , "The example response should not be empty for endpoint ' $ endpoint' and type ' $ type'. " );
779- $ result = $ this ->annotationGenerator ->cutExampleCloseToCharLimit ($ normalisedExample , $ type );
780- // Add a little wiggle room
781- $ this ->assertLessThanOrEqual (AnnotationGenerator::EXAMPLE_CHAR_LIMIT + 30 , strlen ($ result ), "The example response should not exceed the character limit for endpoint ' $ endpoint' and type ' $ type'. " );
782- $ this ->assertEquals ($ expectedExample , $ result , "The truncated example was not as expected for endpoint ' $ endpoint' and type ' $ type'. " );
857+ yield "truncated example should match expected JSON for $ endpoint endpoint and $ type type " => [$ endpoint , $ type , $ normalisedExample , $ expectedExample ];
783858 }
784859 }
785860 }
@@ -796,20 +871,34 @@ public function testBuildPropertyAnnotationFromJsonExample(): void
796871 $ this ->expectNotToPerformAssertions ();
797872 }
798873
799- public function testBuildSchemaAnnotationFromXmlExample (): void
874+ /**
875+ * @dataProvider getTestXmlSchemaData
876+ *
877+ * @param string $endpoint
878+ * @param array $normalisedObject
879+ * @param array $expected
880+ *
881+ * @return void
882+ */
883+ public function testBuildSchemaAnnotationFromXmlExample (string $ endpoint , array $ normalisedObject , array $ expected ): void
884+ {
885+ $ this ->assertNotEmpty ($ normalisedObject , 'The decoded example response should not be empty for endpoint: ' . $ endpoint );
886+ $ result = $ this ->annotationGenerator ->buildSchemaAnnotationFromXmlExample ($ normalisedObject );
887+ $ this ->assertEquals ($ expected , $ result , "The XML schema was not as expected for endpoint $ endpoint. " );
888+ }
889+
890+ /**
891+ * @return iterable<string, array, array>
892+ */
893+ public static function getTestXmlSchemaData (): iterable
800894 {
801- $ normalisedMap = $ this -> getExampleResponsesMap ();
802- $ schemasMap = $ this -> getExampleResponsesMap ( true );
895+ $ normalisedMap = self :: getNormalisedExamples ();
896+ $ schemasMap = self :: getExampleSchemas ( );
803897 foreach (self ::EXAMPLE_API_ENDPOINTS as $ endpoint ) {
804898 $ normalisedString = $ normalisedMap [$ endpoint ]['xml ' ] ?? '' ;
805- $ this ->assertNotEmpty ($ normalisedString , 'The normalised example response should not be empty for endpoint: ' . $ endpoint );
806899 $ normalisedObject = json_decode ($ normalisedString , true ) ?? [];
807- $ this ->assertNotEmpty ($ normalisedObject , 'The decoded example response should not be empty for endpoint: ' . $ endpoint );
808900 $ expected = json_decode ($ schemasMap [$ endpoint ]['xml ' ] ?? '' , true ) ?? [];
809- $ result = $ this ->annotationGenerator ->buildSchemaAnnotationFromXmlExample ($ normalisedObject );
810- $ result = json_encode ($ result );
811- $ expected = json_encode ($ expected );
812- $ this ->assertEquals ($ expected , $ result , "The XML schema was not as expected for endpoint $ endpoint. " );
901+ yield "should match expected XML schema for $ endpoint endpoint " => [$ endpoint , $ normalisedObject , $ expected ];
813902 }
814903 }
815904
@@ -834,7 +923,7 @@ public function testRemoveTrailingCommaFromLastLine(array $lines, array $expecte
834923 }
835924
836925 /**
837- * @return iterable<array, array} >
926+ * @return iterable<array, array>
838927 */
839928 public function getTestDataForRemoveTrailingCommaFromLastLine (): iterable
840929 {
@@ -871,7 +960,7 @@ public function getTestDataForRemoveTrailingCommaFromLastLine(): iterable
871960 ' ) ' ,
872961 ' ) ' ,
873962 ') ' ,
874- ]
963+ ],
875964 ];
876965 }
877966
0 commit comments