@@ -87,20 +87,12 @@ public function testAllSchemasHaveVersioningInfo()
8787 $ this ->assertEmpty ($ schemas_missing_versions , 'Schemas missing versioning info: ' . implode (', ' , $ schemas_missing_versions ));
8888 }
8989
90- public function testNormalizeAPIVersion ()
91- {
92- $ this ->assertEquals ('50.2.0 ' , TestRouter::normalizeAPIVersion ('50 ' ));
93- $ this ->assertEquals ('50.1.1 ' , TestRouter::normalizeAPIVersion ('50.1.1 ' ));
94- $ this ->assertEquals ('50.1.2 ' , TestRouter::normalizeAPIVersion ('50.1 ' ));
95- $ this ->assertEquals ('50.2.0 ' , TestRouter::normalizeAPIVersion ('50.2 ' ));
96- }
97-
9890 public function testHLAPIDisabled ()
9991 {
10092 global $ CFG_GLPI ;
10193
10294 $ CFG_GLPI ['enable_hlapi ' ] = 0 ;
103- $ router = TestRouter ::getInstance ();
95+ $ router = Router ::getInstance ();
10496 $ response = $ router ->handleRequest (new Request ('GET ' , '/Computer ' ));
10597 $ this ->assertEquals (403 , $ response ->getStatusCode ());
10698 $ this ->assertStringContainsString ('The High-Level API is disabled ' , (string ) $ response ->getBody ());
@@ -110,11 +102,71 @@ public function testHLAPIDisabled()
110102 $ this ->assertEquals (403 , $ response ->getStatusCode ());
111103 $ this ->assertStringContainsString ('The High-Level API is disabled ' , (string ) $ response ->getBody ());
112104 }
105+
106+ public function testNormalizeVersion ()
107+ {
108+ // invalid version = router default
109+ $ this ->assertEquals ('51.0.0 ' , TestRouter::normalizeAPIVersion ('99 ' ));
110+ // only major version = latest API version for this major
111+ $ this ->assertEquals ('50.2.0 ' , TestRouter::normalizeAPIVersion ('50 ' ));
112+ // major.minor version = latest API version for this major.minor
113+ $ this ->assertEquals ('50.1.2 ' , TestRouter::normalizeAPIVersion ('50.1 ' ));
114+ // major.minor.patch version = same version
115+ $ this ->assertEquals ('50.1.1 ' , TestRouter::normalizeAPIVersion ('50.1.1 ' ));
116+
117+ $ this ->assertEquals ('50.2.0 ' , TestRouter::normalizeAPIVersion ('50.2 ' ));
118+ }
119+
120+ public function testRoutingByVersion ()
121+ {
122+ $ router = TestRouter::getInstance ();
123+ // 50.0 is requesting 50.0.X or earlier
124+ $ this ->assertNotEquals ('/{req} ' , $ router ->match (new Request ('GET ' , '/version500 ' , ['GLPI-API-Version ' => '50.0 ' ]))->getRoutePath ());
125+ // 50 is requesting 50.X.X or earlier
126+ $ this ->assertNotEquals ('/{req} ' , $ router ->match (new Request ('GET ' , '/version500 ' , ['GLPI-API-Version ' => '50 ' ]))->getRoutePath ());
127+ // 50.1 is requesting 50.1.X or earlier
128+ $ this ->assertNotEquals ('/{req} ' , $ router ->match (new Request ('GET ' , '/version500 ' , ['GLPI-API-Version ' => '50.1 ' ]))->getRoutePath ());
129+ $ this ->assertNotEquals ('/{req} ' , $ router ->match (new Request ('GET ' , '/version500 ' , ['GLPI-API-Version ' => '51 ' ]))->getRoutePath ());
130+
131+ $ this ->assertEquals ('/{req} ' , $ router ->match (new Request ('GET ' , '/version501 ' , ['GLPI-API-Version ' => '50.0 ' ]))->getRoutePath ());
132+ $ this ->assertNotEquals ('/{req} ' , $ router ->match (new Request ('GET ' , '/version501 ' , ['GLPI-API-Version ' => '50.1 ' ]))->getRoutePath ());
133+ $ this ->assertNotEquals ('/{req} ' , $ router ->match (new Request ('GET ' , '/version501 ' , ['GLPI-API-Version ' => '50 ' ]))->getRoutePath ());
134+
135+ $ this ->assertEquals ('/{req} ' , $ router ->match (new Request ('GET ' , '/version510 ' , ['GLPI-API-Version ' => '50.0 ' ]))->getRoutePath ());
136+ $ this ->assertEquals ('/{req} ' , $ router ->match (new Request ('GET ' , '/version510 ' , ['GLPI-API-Version ' => '50.1 ' ]))->getRoutePath ());
137+ $ this ->assertNotEquals ('/{req} ' , $ router ->match (new Request ('GET ' , '/version510 ' , ['GLPI-API-Version ' => '51 ' ]))->getRoutePath ());
138+ $ this ->assertEquals ('/{req} ' , $ router ->match (new Request ('GET ' , '/version510 ' , ['GLPI-API-Version ' => '50 ' ]))->getRoutePath ());
139+ }
140+
141+ public function testSchemaByVersion ()
142+ {
143+ // Note that schema version matching is always done against the "Router" class so it cannot be mocked with the TestRouter versions
144+ $ this ->assertEquals (['Schema200 ' , 'Schema200_2 ' , 'Schema210 ' ], array_keys (TestController::getKnownSchemas ('2 ' )));
145+ $ this ->assertEquals (['Schema200 ' , 'Schema200_2 ' ], array_keys (TestController::getKnownSchemas ('2.0 ' )));
146+ $ this ->assertEquals (['Schema200 ' , 'Schema200_2 ' ], array_keys (TestController::getKnownSchemas ('2.0.0 ' )));
147+ $ this ->assertEquals (['Schema200 ' , 'Schema200_2 ' , 'Schema210 ' ], array_keys (TestController::getKnownSchemas ('2.1 ' )));
148+ $ this ->assertEquals (['Schema200 ' , 'Schema200_2 ' , 'Schema210 ' ], array_keys (TestController::getKnownSchemas ('2.1.0 ' )));
149+
150+ // Test the filtering of fields inside schemas
151+ $ schema = TestController::getKnownSchemas ('2 ' )['Schema200 ' ];
152+ $ this ->assertArrayHasKey ('field1 ' , $ schema ['properties ' ]);
153+ $ this ->assertArrayHasKey ('field2 ' , $ schema ['properties ' ]);
154+
155+ $ schema = TestController::getKnownSchemas ('2.0 ' )['Schema200 ' ];
156+ $ this ->assertArrayHasKey ('field1 ' , $ schema ['properties ' ]);
157+ $ this ->assertArrayNotHasKey ('field2 ' , $ schema ['properties ' ]);
158+
159+ $ schema = TestController::getKnownSchemas ('2.1 ' )['Schema200 ' ];
160+ $ this ->assertArrayHasKey ('field1 ' , $ schema ['properties ' ]);
161+ $ this ->assertArrayHasKey ('field2 ' , $ schema ['properties ' ]);
162+ }
113163}
114164
115165// @codingStandardsIgnoreStart
116166class TestRouter extends Router
117167{
168+ public const API_VERSION = '51.0.0 ' ;
169+
118170 // @codingStandardsIgnoreEnd
119171 public static function getInstance (): Router
120172 {
@@ -172,14 +224,74 @@ public static function getAPIVersions(): array
172224class TestController extends AbstractController
173225{
174226 // @codingStandardsIgnoreEnd
175- /**
176- * @param RequestInterface $request
177- * @return Response
178- */
227+
228+ protected static function getRawKnownSchemas (): array
229+ {
230+ return [
231+ 'Schema200 ' => [
232+ 'type ' => 'object ' ,
233+ 'x-version-introduced ' => '2.0 ' ,
234+ 'properties ' => [
235+ 'field1 ' => [
236+ 'type ' => 'string ' ,
237+ ],
238+ 'field2 ' => [
239+ 'type ' => 'string ' ,
240+ 'x-version-introduced ' => '2.1.0 ' ,
241+ ],
242+ ],
243+ ],
244+ 'Schema200_2 ' => [
245+ 'type ' => 'object ' ,
246+ 'x-version-introduced ' => '2.0.0 ' ,
247+ 'properties ' => [
248+ 'field1 ' => [
249+ 'type ' => 'string ' ,
250+ ],
251+
252+ 'field2 ' => [
253+ 'type ' => 'string ' ,
254+ 'x-version-introduced ' => '2.1.0 ' ,
255+ ],
256+ ],
257+ ],
258+ 'Schema210 ' => [
259+ 'type ' => 'object ' ,
260+ 'x-version-introduced ' => '2.1.0 ' ,
261+ 'properties ' => [
262+ 'field1 ' => [
263+ 'type ' => 'string ' ,
264+ ],
265+ ],
266+ ],
267+ ];
268+ }
269+
179270 #[Route('/{req} ' , ['GET ' , 'POST ' , 'PATCH ' , 'PUT ' , 'DELETE ' , 'OPTIONS ' ], ['req ' => '.* ' ], -1 )]
180- #[RouteVersion(introduced: TestRouter:: API_VERSION )]
271+ #[RouteVersion(introduced: ' 50.0.0 ' )]
181272 public function defaultRoute (RequestInterface $ request ): Response
182273 {
183274 return new Response (200 , [], __FUNCTION__ );
184275 }
276+
277+ #[Route('/version500 ' , ['GET ' ])]
278+ #[RouteVersion(introduced: '50.0.0 ' )]
279+ public function testVersion500 (RequestInterface $ request ): Response
280+ {
281+ return new Response (200 , [], __FUNCTION__ );
282+ }
283+
284+ #[Route('/version501 ' , ['GET ' ])]
285+ #[RouteVersion(introduced: '50.1.0 ' )]
286+ public function testVersion501 (RequestInterface $ request ): Response
287+ {
288+ return new Response (200 , [], __FUNCTION__ );
289+ }
290+
291+ #[Route('/version510 ' , ['GET ' ])]
292+ #[RouteVersion(introduced: '51.0.0 ' )]
293+ public function testVersion510 (RequestInterface $ request ): Response
294+ {
295+ return new Response (200 , [], __FUNCTION__ );
296+ }
185297}
0 commit comments