diff --git a/src/MatrixHttpApi.php b/src/MatrixHttpApi.php index 7e46800..597406d 100644 --- a/src/MatrixHttpApi.php +++ b/src/MatrixHttpApi.php @@ -6,6 +6,7 @@ use Aryess\PhpMatrixSdk\Exceptions\MatrixException; use Aryess\PhpMatrixSdk\Exceptions\MatrixHttpLibException; use Aryess\PhpMatrixSdk\Exceptions\MatrixRequestException; use GuzzleHttp\Client; +use GuzzleHttp\Exception\GuzzleException; /** * Contains all raw Matrix HTTP Client-Server API calls. @@ -23,6 +24,7 @@ use GuzzleHttp\Client; class MatrixHttpApi { const MATRIX_V2_API_PATH = "/_matrix/client/r0"; + const VERSION = '0.0.1-dev'; /** * @var string @@ -106,7 +108,7 @@ class MatrixHttpApi { * @param string|null $setPresence * @return array|string * @throws MatrixException - * @throws \GuzzleHttp\Exception\GuzzleException + * @throws GuzzleException */ public function sync(?string $since = null, int $timeoutMs = 30000, $filter = null, bool $fullState = false, ?string $setPresence = null) { @@ -195,13 +197,12 @@ class MatrixHttpApi { * @param bool $returnJson * @return array|string * @throws MatrixException - * @throws \GuzzleHttp\Exception\GuzzleException */ private function send(string $method, string $path, $content = null, array $queryParams = [], array $headers = [], $apiPath = self::MATRIX_V2_API_PATH, $returnJson = true) { $options = []; if (!in_array('User-Agent', $headers)) { - $headers['User-Agent'] = 'php-matrix-sdk/0.0.1-dev'; //TODO: add version + $headers['User-Agent'] = 'php-matrix-sdk/'.self::VERSION; } $method = strtoupper($method); @@ -239,7 +240,7 @@ class MatrixHttpApi { while (true) { try { $response = $this->client->request($method, $endpoint, $options); - } catch (RequestException $e) { + } catch (GuzzleException $e) { throw new MatrixHttpLibException($e, $method, $endpoint); } diff --git a/tests/BaseTestCase.php b/tests/BaseTestCase.php new file mode 100644 index 0000000..55b2520 --- /dev/null +++ b/tests/BaseTestCase.php @@ -0,0 +1,42 @@ +getMethod($methodName); + $method->setAccessible(true); + + return $method->invokeArgs($object, $parameters); + } + + protected function getMockClientHandler(array $responses, array &$container): HandlerStack { + $mock = new MockHandler($responses); + $history = Middleware::history($container); + $handler = HandlerStack::create($mock); + $handler->push($history); + + return $handler; + } +} \ No newline at end of file diff --git a/tests/MatrixHttpApiTest.php b/tests/MatrixHttpApiTest.php new file mode 100644 index 0000000..ecff36a --- /dev/null +++ b/tests/MatrixHttpApiTest.php @@ -0,0 +1,94 @@ +token); + + $r = sprintf('{"application/json": {"user_id": "%s"}}', $this->userId); + $container = []; + $handler = $this->getMockClientHandler([new Response(200, [], $r)], $container); + $mapi->setClient(new Client(['handler' => $handler])); + + $this->invokePrivateMethod($mapi, 'send', ['GET', $this->testPath]); + /** @var Request $req */ + $req = array_get($container, '0.request'); + + $this->assertEquals('GET', $req->getMethod()); + $this->assertEquals(sprintf('Bearer %s', $this->token), $req->getHeader('Authorization')[0]); + } + + public function testSendUserAgentHeader() { + $mapi = new MatrixHttpApi("http://example.com", $this->token); + + $r = sprintf('{"application/json": {"user_id": "%s"}}', $this->userId); + $container = []; + $handler = $this->getMockClientHandler([new Response(200, [], $r)], $container); + $mapi->setClient(new Client(['handler' => $handler])); + + $this->invokePrivateMethod($mapi, 'send', ['GET', $this->testPath]); + /** @var Request $req */ + $req = array_get($container, '0.request'); + + $this->assertEquals('GET', $req->getMethod()); + $this->assertEquals('php-matrix-sdk/'.$mapi::VERSION, $req->getHeader('User-Agent')[0]); + } + + public function testSendTokenQuery() { + $mapi = new MatrixHttpApi("http://example.com", $this->token, null, 500, false); + + $r = sprintf('{"application/json": {"user_id": "%s"}}', $this->userId); + $container = []; + $handler = $this->getMockClientHandler([new Response(200, [], $r)], $container); + $mapi->setClient(new Client(['handler' => $handler])); + + $this->invokePrivateMethod($mapi, 'send', ['GET', $this->testPath]); + /** @var Request $req */ + $req = array_get($container, '0.request'); + + $this->assertEquals('GET', $req->getMethod()); + $this->assertContains($this->token, $req->getRequestTarget()); + } + + public function testSendUserId() { + $mapi = new MatrixHttpApi("http://example.com", $this->token, $this->userId); + + $r = sprintf('{"application/json": {"user_id": "%s"}}', $this->userId); + $container = []; + $handler = $this->getMockClientHandler([new Response(200, [], $r)], $container); + $mapi->setClient(new Client(['handler' => $handler])); + + $this->invokePrivateMethod($mapi, 'send', ['GET', $this->testPath]); + /** @var Request $req */ + $req = array_get($container, '0.request'); + + $this->assertEquals('GET', $req->getMethod()); + $this->assertContains(urlencode($this->userId), $req->getRequestTarget()); + } + + public function testSendUnsupMethod() { + $this->expectException(MatrixException::class); + $mapi = new MatrixHttpApi("http://example.com", $this->token, $this->userId); + $this->invokePrivateMethod($mapi, 'send', ['GOT', $this->testPath]); + } + + public function testSendRequestError() { + $this->expectException(MatrixHttpLibException::class); + $mapi = new MatrixHttpApi("http://example.com"); + $this->invokePrivateMethod($mapi, 'send', ['GET', $this->testPath]); + } +} \ No newline at end of file diff --git a/tests/TestHelper.php b/tests/TestHelper.php new file mode 100644 index 0000000..a75d96e --- /dev/null +++ b/tests/TestHelper.php @@ -0,0 +1,190 @@ + "s72595_4483_1934", + "presence" => [ + "events" => [ + [ + "sender" => "@alice:example.com", + "type" => "m.presence", + "content" => [ + "presence" => "online", + ], + ], + ], + ], + "account_data" => [ + "events" => [ + [ + "type" => "org.example.custom.config", + "content" => [ + "custom_config_key" => "custom_config_value", + ], + ], + ], + ], + "rooms" => [ + "join" => [ + "!726s6s6q:example.com" => [ + "state" => [ + "events" => [ + [ + "sender" => "@alice:example.com", + "type" => "m.room.member", + "state_key" => "@alice:example.com", + "content" => [ + "membership" => "join", + ], + "origin_server_ts" => 1417731086795, + "event_id" => "$66697273743031:example.com", + ], + ], + ], + "timeline" => [ + "events" => [ + [ + "sender" => "@bob:example.com", + "type" => "m.room.member", + "state_key" => "@bob:example.com", + "content" => [ + "membership" => "join", + ], + "prev_content" => [ + "membership" => "invite", + ], + "origin_server_ts" => 1417731086795, + "event_id" => "$7365636s6r6432:example.com", + ], + [ + "sender" => "@alice:example.com", + "type" => "m.room.message", + "age" => 124524, + "txn_id" => "1234", + "content" => [ + "body" => "I am a fish", + "msgtype" => "m.text", + ], + "origin_server_ts" => 1417731086797, + "event_id" => "$74686972643033:example.com", + ], + ], + "limited" => true, + "prev_batch" => "t34-23535_0_0", + ], + "ephemeral" => [ + "events" => [ + [ + "type" => "m.typing", + "content" => [ + "user_ids" => [ + "@alice:example.com", + ], + ], + ], + ], + ], + "account_data" => [ + "events" => [ + [ + "type" => "m.tag", + "content" => [ + "tags" => [ + "work" => [ + "order" => 1, + ], + ], + ], + ], + [ + "type" => "org.example.custom.room.config", + "content" => [ + "custom_config_key" => "custom_config_value", + ], + ], + ], + ], + ], + ], + "invite" => [ + "!696r7674:example.com" => [ + "invite_state" => [ + "events" => [ + [ + "sender" => "@alice:example.com", + "type" => "m.room.name", + "state_key" => "", + "content" => [ + "name" => "My Room Name", + ], + ], + [ + "sender" => "@alice:example.com", + "type" => "m.room.member", + "state_key" => "@bob:example.com", + "content" => [ + "membership" => "invite", + ], + ], + ], + ], + ], + ], + "leave" => [], + ], + ]; + + const EXAMPLE_PL_EVENT = [ + 'age' => 242352, + 'content' => [ + 'ban' => 50, + 'events' => [ + 'm.room.name' => 100, + 'm.room.power_levels' => 100, + ], + 'events_default' => 0, + 'invite' => 50, + 'kick' => 50, + 'redact' => 50, + 'state_default' => 50, + 'users' => [ + '@example:localhost' => 100, + ], + 'users_default' => 0, + ], + 'event_id' => '$WLGTSEFSEF:localhost', + 'origin_server_ts' => 1431961217939, + 'room_id' => '!Cuyf34gef24t:localhost', + 'sender' => '@example:localhost', + 'state_key' => '', + 'type' => 'm.room.power_levels', + ]; + + const EXAMPLE_EVENT_RESPONSE = [ + 'event_id' => 'YUwRidLecu', + ]; + + const EXAMPLE_KEY_UPLOAD_RESPONSE = [ + 'one_time_key_counts' => [ + 'curve25519' => 10, + 'signed_curve25519' => 20, + ], + ]; + + const EXAMPLE_SUCCESS_LOGIN_RESPONSE = [ + 'user_id' => '@example:localhost', + 'access_token' => 'abc123', + 'home_server' => 'matrix.org', + 'device_id' => 'GHTYAJCE', + ]; + + const EXAMPLE_PREVIEW_URL = [ + 'matrix:image:size' => 102400, + 'og:description' => 'This is a really cool blog post from matrix.org', + 'og:image' => 'mxc://example.com/ascERGshawAWawugaAcauga', + 'og:image:height' => 48, + 'og:image:type' => 'image/png', + 'og:image:width' => 48, + 'og:title' => 'Matrix Blog Post', + ]; +} \ No newline at end of file