1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace communication_matrix\local; 18 19 use GuzzleHttp\Handler\MockHandler; 20 use GuzzleHttp\Psr7\Request; 21 use GuzzleHttp\Psr7\Response; 22 use ReflectionMethod; 23 24 defined('MOODLE_INTERNAL') || die(); 25 require_once(dirname(__DIR__) . '/matrix_client_test_trait.php'); 26 27 /** 28 * Tests for the Matrix command class. 29 * 30 * @package communication_matrix 31 * @category test 32 * @copyright 2023 Andrew Lyons <andrew@nicols.co.uk> 33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 * @covers \communication_matrix\local\command 35 * @coversDefaultClass \communication_matrix\local\command 36 */ 37 class command_test extends \advanced_testcase { 38 use \communication_matrix\matrix_client_test_trait; 39 40 /** 41 * Test instantiation of a command when no method is provided. 42 */ 43 public function test_standard_instantiation(): void { 44 $instance = $this->get_mocked_instance_for_version('v1.7'); 45 $command = new command( 46 $instance, 47 method: 'PUT', 48 endpoint: 'example/endpoint', 49 ); 50 51 // Check the standard functionality. 52 $this->assertEquals('/example/endpoint', $command->getUri()->getPath()); 53 $this->assertEquals('PUT', $command->getMethod()); 54 $this->assertArrayHasKey('Authorization', $command->getHeaders()); 55 } 56 57 /** 58 * Test instantiation of a command when no method is provided. 59 */ 60 public function test_instantiation_without_auth(): void { 61 $instance = $this->get_mocked_instance_for_version('v1.7'); 62 $command = new command( 63 $instance, 64 method: 'PUT', 65 endpoint: 'example/endpoint', 66 requireauthorization: false, 67 ); 68 69 // Check the standard functionality. 70 $this->assertEquals('/example/endpoint', $command->getUri()->getPath()); 71 $this->assertEquals('PUT', $command->getMethod()); 72 $this->assertArrayNotHasKey('Authorization', $command->getHeaders()); 73 } 74 75 /** 76 * Test processing of command URL properties. 77 * 78 * @dataProvider url_parsing_provider 79 * @param string $url 80 * @param array $params 81 * @param string $expected 82 */ 83 public function test_url_parsing( 84 string $url, 85 array $params, 86 string $expected, 87 ): void { 88 $instance = $this->get_mocked_instance_for_version('v1.7'); 89 90 $command = new command( 91 $instance, 92 method: 'PUT', 93 endpoint: $url, 94 params: $params, 95 ); 96 97 $this->assertEquals($expected, $command->getUri()->getPath()); 98 } 99 100 /** 101 * Data provider for url parsing tests. 102 * 103 * @return array 104 */ 105 public static function url_parsing_provider(): array { 106 return [ 107 [ 108 'example/:id/endpoint', 109 [':id' => '39492'], 110 '/example/39492/endpoint', 111 ], 112 [ 113 'example/:id/endpoint/:id', 114 [':id' => '39492'], 115 '/example/39492/endpoint/39492', 116 ], 117 [ 118 'example/:id/endpoint/:id/:name', 119 [ 120 ':id' => '39492', 121 ':name' => 'matrix', 122 ], 123 '/example/39492/endpoint/39492/matrix', 124 ], 125 ]; 126 } 127 128 /** 129 * Test processing of command URL properties with an array which contains untranslated parameters. 130 */ 131 public function test_url_parsing_extra_properties(): void { 132 $instance = $this->get_mocked_instance_for_version('v1.7'); 133 $this->expectException(\OutOfRangeException::class); 134 $this->expectExceptionMessage("URL contains untranslated parameters 'example/:id/endpoint'"); 135 136 new command( 137 $instance, 138 method: 'PUT', 139 endpoint: 'example/:id/endpoint', 140 ); 141 } 142 143 /** 144 * Test processing of command URL properties with an array which contains untranslated parameters. 145 */ 146 public function test_url_parsing_unused_properites(): void { 147 $instance = $this->get_mocked_instance_for_version('v1.7'); 148 $this->expectException(\OutOfRangeException::class); 149 $this->expectExceptionMessage("Parameter not found in URL ':id'"); 150 151 new command( 152 $instance, 153 method: 'PUT', 154 endpoint: 'example/:ids/endpoint', 155 params: [ 156 ':id' => 12345, 157 ], 158 ); 159 } 160 161 /** 162 * Test the parameter fetching, processing, and parsing. 163 * 164 * @dataProvider parameter_and_option_provider 165 * @param string $endpoint 166 * @param array $params 167 * @param array $remainingparams 168 * @param array $allparams 169 * @param array $options 170 */ 171 public function test_parameters( 172 string $endpoint, 173 array $params, 174 array $remainingparams, 175 array $allparams, 176 array $options, 177 ): void { 178 $instance = $this->get_mocked_instance_for_version('v1.7'); 179 180 $command = new command( 181 $instance, 182 method: 'PUT', 183 endpoint: $endpoint, 184 params: $params, 185 ); 186 187 $this->assertSame($remainingparams, $command->get_remaining_params()); 188 $this->assertSame($allparams, $command->get_all_params()); 189 $this->assertSame($options, $command->get_options()); 190 } 191 192 /** 193 * Data provider for parameter tests. 194 * 195 * @return array 196 */ 197 public static function parameter_and_option_provider(): array { 198 $command = [ 199 'method' => 'PUT', 200 'endpoint' => 'example/:id/endpoint', 201 ]; 202 203 return [ 204 'no parameters' => [ 205 'endpoint' => 'example/endpoint', 206 'params' => [], 207 'remainingparams' => [], 208 'allparams' => [], 209 'options' => [ 210 'json' => [], 211 ], 212 ], 213 'named params' => [ 214 'endpoint' => 'example/:id/endpoint', 215 'params' => [ 216 ':id' => 12345, 217 ], 218 'remainingparams' => [], 219 'allparams' => [ 220 ':id' => 12345, 221 ], 222 'options' => [ 223 'json' => [], 224 ], 225 ], 226 'mixture of params' => [ 227 'endpoint' => 'example/:id/endpoint', 228 'params' => [ 229 ':id' => 12345, 230 'name' => 'matrix', 231 ], 232 'remainingparams' => [ 233 'name' => 'matrix', 234 ], 235 'allparams' => [ 236 ':id' => 12345, 237 'name' => 'matrix', 238 ], 239 'options' => [ 240 'json' => [ 241 'name' => 'matrix', 242 ], 243 ], 244 ], 245 ]; 246 } 247 248 /** 249 * Test the query parameter handling. 250 * 251 * @dataProvider query_provider 252 * @param array $query 253 * @param string $expected 254 */ 255 public function test_query_parameters( 256 array $query, 257 string $expected, 258 ): void { 259 // The query parameter is only added at the time we call send. 260 // That's because it can only be provided to Guzzle as an Option, not as part of the URL. 261 // Options can only be applied at time of transfer. 262 // Unfortuantely that leads to slightly less ideal testing that we'd like here. 263 $mock = new MockHandler(); 264 $instance = $this->get_mocked_instance_for_version( 265 'v1.7', 266 mock: $mock, 267 ); 268 269 $mock->append(function (Request $request) use ($expected): Response { 270 $this->assertSame( 271 $expected, 272 $request->getUri()->getQuery(), 273 ); 274 return new Response(); 275 }); 276 $command = new command( 277 $instance, 278 method: 'PUT', 279 endpoint: 'example/endpoint', 280 query: $query, 281 ); 282 283 $execute = new ReflectionMethod($instance, 'execute'); 284 $execute->setAccessible(true); 285 $execute->invoke($instance, $command); 286 } 287 288 /** 289 * Data provider for query parameter tests. 290 * @return array 291 */ 292 public static function query_provider(): array { 293 return [ 294 'no query' => [ 295 'query' => [], 296 'expected' => '', 297 ], 298 'single query' => [ 299 'query' => [ 300 'name' => 'matrix', 301 ], 302 'expected' => 'name=matrix', 303 ], 304 'multiple queries' => [ 305 'query' => [ 306 'name' => 'matrix', 307 'type' => 'room', 308 ], 309 'expected' => 'name=matrix&type=room', 310 ], 311 ]; 312 } 313 314 /** 315 * Test the sendasjson constructor parameter. 316 * 317 * @dataProvider sendasjson_provider 318 * @param bool $sendasjson 319 * @param string $endpoint 320 * @param array $params 321 * @param array $remainingparams 322 * @param array $allparams 323 * @param array $expectedoptions 324 */ 325 public function test_send_as_json( 326 bool $sendasjson, 327 string $endpoint, 328 array $params, 329 array $remainingparams, 330 array $allparams, 331 array $expectedoptions, 332 ): void { 333 $instance = $this->get_mocked_instance_for_version('v1.7'); 334 335 $command = new command( 336 $instance, 337 method: 'PUT', 338 endpoint: $endpoint, 339 params: $params, 340 sendasjson: $sendasjson, 341 ); 342 343 $this->assertSame($remainingparams, $command->get_remaining_params()); 344 $this->assertSame($allparams, $command->get_all_params()); 345 $this->assertSame($expectedoptions, $command->get_options()); 346 } 347 348 /** 349 * Test the sendasjosn option to the command constructor. 350 * 351 * @return array 352 */ 353 public static function sendasjson_provider(): array { 354 return [ 355 'As JSON' => [ 356 'sendasjon' => true, 357 'endpoint' => 'example/:id/endpoint', 358 'params' => [ 359 ':id' => 12345, 360 'name' => 'matrix', 361 ], 362 'remainingparams' => [ 363 'name' => 'matrix', 364 ], 365 'allparams' => [ 366 ':id' => 12345, 367 'name' => 'matrix', 368 ], 369 'expectedoptions' => [ 370 'json' => [ 371 'name' => 'matrix', 372 ], 373 ], 374 ], 375 'Not as JSON' => [ 376 'sendasjson' => false, 377 'endpoint' => 'example/:id/endpoint', 378 'params' => [ 379 ':id' => 12345, 380 'name' => 'matrix', 381 ], 382 'remainingparams' => [ 383 'name' => 'matrix', 384 ], 385 'allparams' => [ 386 ':id' => 12345, 387 'name' => 'matrix', 388 ], 389 'expectedoptions' => [ 390 ], 391 ], 392 ]; 393 } 394 395 /** 396 * Test the sendasjosn option to the command constructor. 397 */ 398 public function test_ignorehttperrors(): void { 399 $instance = $this->get_mocked_instance_for_version('v1.7'); 400 401 $command = new command( 402 $instance, 403 method: 'PUT', 404 endpoint: 'example/endpoint', 405 ignorehttperrors: true, 406 ); 407 408 $options = $command->get_options(); 409 $this->assertArrayHasKey('http_errors', $options); 410 $this->assertFalse($options['http_errors']); 411 } 412 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body