From d4f21511981a29536f324a43698e60a0ca82334c Mon Sep 17 00:00:00 2001 From: James Seconde Date: Tue, 25 Jul 2023 10:28:47 -0500 Subject: [PATCH] Add Users Client (#420) * Hacks for APIcollection (again), logic for 5 endpoints * Move Users into its own namespace * PR review changes, pt 1 * PR review changes, pt 2 * Pass in hydrator * reset verify, make User full DTO * Correct auth, add more tests * Update src/Users/Client.php Co-authored-by: Chris Tankersley * Update src/Users/Client.php Co-authored-by: Chris Tankersley * Update src/Users/ClientFactory.php Co-authored-by: Chris Tankersley * Update src/Users/Client.php Co-authored-by: Chris Tankersley * Update src/Users/ClientFactory.php Co-authored-by: Chris Tankersley * Update src/Users/Client.php Co-authored-by: Chris Tankersley * pass in standard array hydrator --------- Co-authored-by: Chris Tankersley --- phpunit.xml.dist | 6 + src/Client.php | 3 + src/Entity/IterableAPICollection.php | 25 +- src/Users/Client.php | 82 +++++ src/Users/ClientFactory.php | 27 ++ src/Users/Filter/UserFilter.php | 78 +++++ src/Users/User.php | 163 ++++++++++ test/Application/ClientTest.php | 12 +- test/Users/ClientTest.php | 307 ++++++++++++++++++ test/Users/UserTest.php | 92 ++++++ test/Users/responses/create-user-success.json | 80 +++++ test/Users/responses/get-user-success.json | 80 +++++ test/Users/responses/list-user-success.json | 28 ++ test/Users/responses/update-user-success.json | 66 ++++ 14 files changed, 1041 insertions(+), 8 deletions(-) create mode 100644 src/Users/Client.php create mode 100644 src/Users/ClientFactory.php create mode 100644 src/Users/Filter/UserFilter.php create mode 100644 src/Users/User.php create mode 100644 test/Users/ClientTest.php create mode 100644 test/Users/UserTest.php create mode 100644 test/Users/responses/create-user-success.json create mode 100644 test/Users/responses/get-user-success.json create mode 100644 test/Users/responses/list-user-success.json create mode 100644 test/Users/responses/update-user-success.json diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7e707279..655c973f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -41,6 +41,12 @@ test/Meetings + + test/Application + + + test/Users + diff --git a/src/Client.php b/src/Client.php index 4ba310b7..3ff63614 100644 --- a/src/Client.php +++ b/src/Client.php @@ -53,6 +53,7 @@ use Vonage\SMS\ClientFactory as SMSClientFactory; use Vonage\Subaccount\ClientFactory as SubaccountClientFactory; use Vonage\Messages\ClientFactory as MessagesClientFactory; +use Vonage\Users\ClientFactory as UsersClientFactory; use Vonage\Verify\ClientFactory as VerifyClientFactory; use Vonage\Verify2\ClientFactory as Verify2ClientFactory; use Vonage\Verify\Verification; @@ -85,6 +86,7 @@ * @method Secrets\Client secrets() * @method SMS\Client sms() * @method Subaccount\Client subaccount() + * @method Users\Client users() * @method Verify\Client verify() * @method Verify2\Client verify2() * @method Voice\Client voice() @@ -224,6 +226,7 @@ public function __construct( 'secrets' => SecretsClientFactory::class, 'sms' => SMSClientFactory::class, 'subaccount' => SubaccountClientFactory::class, + 'users' => UsersClientFactory::class, 'verify' => VerifyClientFactory::class, 'verify2' => Verify2ClientFactory::class, 'voice' => VoiceClientFactory::class, diff --git a/src/Entity/IterableAPICollection.php b/src/Entity/IterableAPICollection.php index da7af80d..c3f41981 100644 --- a/src/Entity/IterableAPICollection.php +++ b/src/Entity/IterableAPICollection.php @@ -111,7 +111,7 @@ class IterableAPICollection implements ClientAwareInterface, Iterator, Countable protected bool $noQueryParameters = false; /** - * User set pgge sixe. + * User set pgge size. */ protected ?int $size = null; @@ -123,6 +123,12 @@ class IterableAPICollection implements ClientAwareInterface, Iterator, Countable protected $hydrator; + /** + * Used to override pagination to remove it from the URL page query + * but differs from noQueryParameters when you want to use other filters + */ + protected bool $hasPagination = true; + public function getPageIndexKey(): string { return $this->pageIndexKey; @@ -496,7 +502,7 @@ protected function fetchPage($absoluteUri): void $query[$this->pageSizeKey] = $this->size; } - if (isset($this->index)) { + if (isset($this->index) && $this->hasPagination()) { $query[$this->pageIndexKey] = $this->index; } @@ -625,4 +631,19 @@ public function setIndex(?int $index): IterableAPICollection return $this; } + + /** + * @return bool + */ + public function hasPagination(): bool + { + return $this->hasPagination; + } + + public function setHasPagination(bool $hasPagination): static + { + $this->hasPagination = $hasPagination; + + return $this; + } } diff --git a/src/Users/Client.php b/src/Users/Client.php new file mode 100644 index 00000000..86f257dd --- /dev/null +++ b/src/Users/Client.php @@ -0,0 +1,82 @@ +api; + } + + public function listUsers(FilterInterface $filter = null): IterableAPICollection + { + if (is_null($filter)) { + $filter = new EmptyFilter(); + } + + $response = $this->api->search($filter); + $response->setHydrator($this->hydrator); + $response->setPageSizeKey('page_size'); + $response->setHasPagination(false); + + return $response; + } + + public function createUser(User $user): User + { + $response = $this->api->create($user->toArray()); + + return $this->hydrator->hydrate($response); + } + + public function getUser(string $id): User + { + $response = $this->api->get($id); + return $this->hydrator->hydrate($response); + + return $returnUser; + } + + public function updateUser(User $user): User + { + if (is_null($user->getId())) { + throw new \InvalidArgumentException('User must have an ID set'); + } + + $response = $this->api->partiallyUpdate($user->getId(), $user->toArray()); + + return $this->hydrator->hydrate($response); + } + + public function deleteUser(string $id): bool + { + try { + $this->api->delete($id); + return true; + } catch (ClientException $exception) { + return false; + } + } +} diff --git a/src/Users/ClientFactory.php b/src/Users/ClientFactory.php new file mode 100644 index 00000000..c4674d28 --- /dev/null +++ b/src/Users/ClientFactory.php @@ -0,0 +1,27 @@ +make(APIResource::class); + $api + ->setBaseUri('/v1/users') + ->setCollectionName('users') + ->setAuthHandler(new KeypairHandler()); + + $hydrator = new ArrayHydrator(); + $hydrator->setPrototype(new User()); + + return new Client($api, $hydrator); + } +} diff --git a/src/Users/Filter/UserFilter.php b/src/Users/Filter/UserFilter.php new file mode 100644 index 00000000..6bcdaea4 --- /dev/null +++ b/src/Users/Filter/UserFilter.php @@ -0,0 +1,78 @@ +pageSize !== null) { + $query['page_size'] = $this->getPageSize(); + } + + if ($this->order !== null) { + $query['order'] = $this->getOrder(); + } + + if ($this->cursor !== null) { + $query['cursor'] = $this->getCursor(); + } + + return $query; + } + + public function getPageSize(): int + { + return $this->pageSize; + } + + public function setPageSize(int $pageSize): static + { + $this->pageSize = $pageSize; + + return $this; + } + + public function getOrder(): string + { + return $this->order; + } + + public function setOrder(string $order): static + { + if ($order !== self::ORDER_ASC && $order !== self::ORDER_DESC) { + throw new InvalidArgumentException('Order must be `asc` or `desc`'); + } + + $this->order = $order; + + return $this; + } + + public function getCursor(): ?string + { + return $this->cursor; + } + + public function setCursor(?string $cursor): static + { + $this->cursor = $cursor; + + return $this; + } +} diff --git a/src/Users/User.php b/src/Users/User.php new file mode 100644 index 00000000..1a31218d --- /dev/null +++ b/src/Users/User.php @@ -0,0 +1,163 @@ +id; + } + + public function setId(string $id): static + { + $this->id = $id; + return $this; + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(string $name): static + { + $this->name = $name; + return $this; + } + + public function getDisplayName(): ?string + { + return $this->displayName; + } + + public function setDisplayName(string $displayName): static + { + $this->displayName = $displayName; + return $this; + } + + public function getImageUrl(): ?string + { + return $this->imageUrl; + } + + public function setImageUrl(string $imageUrl): static + { + $this->imageUrl = $imageUrl; + return $this; + } + + public function getProperties(): ?array + { + return $this->properties; + } + + public function setProperties(array $properties): static + { + $this->properties = $properties; + + return $this; + } + + public function getChannels(): array + { + return $this->channels; + } + + public function setChannels(array $channels): static + { + $this->channels = $channels; + return $this; + } + + public function getSelfLink(): ?string + { + return $this->selfLink; + } + + public function setSelfLink(string $selfLink): static + { + $this->selfLink = $selfLink; + + return $this; + } + + public function fromArray(array $data): static + { + if (isset($data['id'])) { + $this->setId($data['id']); + } + + if (isset($data['name'])) { + $this->setName($data['name']); + } + + if (isset($data['display_name'])) { + $this->setDisplayName($data['display_name']); + } + + if (isset($data['image_url'])) { + $this->setImageUrl($data['image_url']); + } + + if (isset($data['properties'])) { + $this->setProperties($data['properties']); + } + + if (isset($data['channels'])) { + $this->setChannels($data['channels']); + } + + if (isset($data['_links']['self']['href'])) { + $this->setSelfLink($data['_links']['self']['href']); + } + + return $this; + } + + public function toArray(): array + { + $data = []; + + if ($this->id !== null) { + $data['id'] = $this->getId(); + } + + if ($this->name !== null) { + $data['name'] = $this->getName(); + } + + if ($this->displayName !== null) { + $data['display_name'] = $this->getDisplayName(); + } + + if ($this->imageUrl !== null) { + $data['image_url'] = $this->getImageUrl(); + } + + if ($this->properties !== null) { + $data['properties'] = $this->getProperties(); + } + + if ($this->channels !== null) { + $data['channels'] = $this->getChannels(); + } + + if ($this->selfLink !== null) { + $data['_links']['self']['href'] = $this->getSelfLink(); + } + + return $data; + } +} diff --git a/test/Application/ClientTest.php b/test/Application/ClientTest.php index 7b445be4..b9c0cb8b 100644 --- a/test/Application/ClientTest.php +++ b/test/Application/ClientTest.php @@ -14,23 +14,23 @@ use Exception; use Laminas\Diactoros\Request; use Laminas\Diactoros\Response; -use Vonage\Application\Hydrator; -use Vonage\Application\Webhook; -use Vonage\Application\Webhook as ApplicationWebhook; -use VonageTest\VonageTestCase; use Prophecy\Argument; use Psr\Http\Client\ClientExceptionInterface; use Psr\Http\Message\RequestInterface; use Vonage\Application\Application; use Vonage\Application\Client as ApplicationClient; +use Vonage\Application\Hydrator; use Vonage\Application\MessagesConfig; use Vonage\Application\RtcConfig; use Vonage\Application\VoiceConfig; +use Vonage\Application\Webhook; +use Vonage\Application\Webhook as ApplicationWebhook; use Vonage\Client; use Vonage\Client\APIResource; use Vonage\Client\Exception\Exception as ClientException; use Vonage\Client\Exception\Server as ServerException; use VonageTest\Psr7AssertionTrait; +use VonageTest\VonageTestCase; use function fopen; use function json_decode; @@ -40,7 +40,7 @@ class ClientTest extends VonageTestCase { use Psr7AssertionTrait; - protected $vonageClient; + protected Client|\Prophecy\Prophecy\ObjectProphecy $vonageClient; /** * @var APIResource @@ -55,7 +55,7 @@ class ClientTest extends VonageTestCase public function setUp(): void { $this->vonageClient = $this->prophesize(Client::class); - $this->vonageClient->getApiUrl()->willReturn('http://api.nexmo.com'); + $this->vonageClient->getApiUrl()->willReturn('https://api.nexmo.com'); $this->vonageClient->getCredentials()->willReturn( new Client\Credentials\Container(new Client\Credentials\Basic('abc', 'def')) ); diff --git a/test/Users/ClientTest.php b/test/Users/ClientTest.php new file mode 100644 index 00000000..3a6d0482 --- /dev/null +++ b/test/Users/ClientTest.php @@ -0,0 +1,307 @@ +vonageClient = $this->prophesize(Client::class); + $this->vonageClient->getApiUrl()->willReturn('https://api.nexmo.com'); + $this->vonageClient->getCredentials()->willReturn( + new Client\Credentials\Container(new Client\Credentials\Keypair( + file_get_contents(__DIR__ . '/../Client/Credentials/test.key'), + 'def' + )) + ); + + $apiResource = new APIResource(); + $apiResource->setClient($this->vonageClient->reveal()) + ->setBaseUri('/v1/users') + ->setCollectionName('users') + ->setAuthHandler(new Client\Credentials\Handler\KeypairHandler()); + + $hydrator = new ArrayHydrator(); + $hydrator->setPrototype(new User()); + + $this->usersClient = new UsersClient($apiResource, $hydrator); + + /** @noinspection PhpParamsInspection */ + $this->usersClient->setClient($this->vonageClient->reveal()); + } + + public function testClientWillUseJwtAuth(): void + { + $this->vonageClient->send(Argument::that(function (Request $request) { + $this->assertEquals( + 'Bearer ', + mb_substr($request->getHeaders()['Authorization'][0], 0, 7) + ); + + $this->assertEquals('GET', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('list-user-success')); + + $response = $this->usersClient->getUser('USR-82e028d9-5201-4f1e-8188-604b2d3471ec'); + } + + public function testWillListUsers(): void + { + $this->vonageClient->send(Argument::that(function (Request $request) { + $uri = $request->getUri(); + $uriString = $uri->__toString(); + $this->assertEquals( + 'https://api.nexmo.com/v1/users?page_size=10&order=asc', + $uriString + ); + + $this->assertEquals('GET', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('list-user-success')); + + $filter = new UserFilter(); + $filter->setPageSize(10) + ->setOrder('asc'); + + $response = $this->usersClient->listUsers($filter); + + foreach ($response as $user) { + $this->assertInstanceOf(User::class, $user); + } + } + + public function testWillCreateUser(): void + { + $this->vonageClient->send(Argument::that(function (Request $request) { + $uri = $request->getUri(); + $uriString = $uri->__toString(); + $this->assertEquals( + 'https://api.nexmo.com/v1/users', + $uriString + ); + + $this->assertEquals('POST', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('create-user-success')); + + $user = new User(); + + $userData = [ + "name" => "my_user_name", + "display_name" => "My User Name", + "image_url" => "https://example.com/image.png", + "channels" => [ + "pstn" => [ + [ + "property1" => "string", + "property2" => "string" + ] + ], + "sip" => [ + [ + "property1" => "string", + "property2" => "string" + ] + ], + "vbc" => [ + [ + "property1" => "string", + "property2" => "string" + ] + ], + "websocket" => [ + [ + "property1" => "string", + "property2" => "string" + ] + ], + "sms" => [ + [ + "number" => "447700900000", + "property1" => "string", + "property2" => "string" + ] + ], + "mms" => [ + [ + "number" => "447700900000", + "property1" => "string", + "property2" => "string" + ] + ], + "whatsapp" => [ + [ + "number" => "447700900000", + "property1" => "string", + "property2" => "string" + ] + ], + "viber" => [ + [ + "number" => "447700900000", + "property1" => "string", + "property2" => "string" + ] + ], + "messenger" => [ + [ + "id" => "0", + "property1" => "string", + "property2" => "string" + ] + ] + ] + ]; + + $user->fromArray($userData); + + $response = $this->usersClient->createUser($user); + $this->assertInstanceOf(User::class, $response); + $this->assertEquals('my_user_name', $user->getName()); + } + + public function testWillGetUser(): void + { + $this->vonageClient->send(Argument::that(function (Request $request) { + $uri = $request->getUri(); + $uriString = $uri->__toString(); + $this->assertEquals( + 'https://api.nexmo.com/v1/users/USR-82e028d9-5201-4f1e-8188-604b2d3471ec', + $uriString + ); + + $this->assertEquals('GET', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('get-user-success')); + + $response = $this->usersClient->getUser('USR-82e028d9-5201-4f1e-8188-604b2d3471ec'); + $this->assertInstanceOf(User::class, $response); + $this->assertEquals('USR-82e028d9-5201-4f1e-8188-604b2d3471ec', $response->getId()); + } + + public function testWillNotUpdateUserWithoutId(): void + { + $this->expectException(\InvalidArgumentException::class); + + $testData = [ + 'name' => 'Test User', + 'display_name' => 'Test Display Name', + 'image_url' => 'https://test.com/image.jpg', + 'properties' => ['prop1' => 'value1', 'prop2' => 'value2'], + 'channels' => ['channel1', 'channel2'], + '_links' => [ + 'self' => [ + 'href' => 'https://test.com/user/1' + ] + ] + ]; + + $user = new User(); + $user->fromArray($testData); + $response = $this->usersClient->updateUser($user); + } + + public function testWillUpdateUser(): void + { + $this->vonageClient->send(Argument::that(function (Request $request) { + $uri = $request->getUri(); + $uriString = $uri->__toString(); + $this->assertEquals( + 'https://api.nexmo.com/v1/users/USR-82e028d9-5201-4f1e-8188-604b2d3471ec', + $uriString + ); + + $this->assertEquals('PATCH', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('update-user-success')); + + $data = [ + "id" => "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name" => "my_patched_user_name", + "display_name" => "My Patched User Name", + "image_url" => "https://example.com/image.png", + "channels" => [ + "pstn" => [ + [ + "property1" => "string", + "property2" => "string" + ] + ], + ], + ]; + + $user = new User(); + $user->fromArray($data); + + $response = $this->usersClient->updateUser($user); + $this->assertInstanceOf(User::class, $response); + $this->assertEquals('my_patched_user_name', $user->getName()); + $this->assertEquals('My Patched User Name', $user->getDisplayName()); + } + + public function testWillDeleteUser(): void + { + // We're getting a null body back from here, so use the factory to create one + $responseFactory = new ResponseFactory(); + $response = $responseFactory->createResponse() + ->withStatus(204); + + $this->vonageClient->send(Argument::that(function (Request $request) { + $uri = $request->getUri(); + $uriString = $uri->__toString(); + $this->assertEquals( + 'https://api.nexmo.com/v1/users/USR-82e028d9-5201-4f1e-8188-604b2d3471ec', + $uriString + ); + + $this->assertEquals('DELETE', $request->getMethod()); + + return true; + }))->willReturn($response); + + $user = 'USR-82e028d9-5201-4f1e-8188-604b2d3471ec'; + + $response = $this->usersClient->deleteUser($user); + $this->assertTrue($response); + } + + /** + * Get the API response we'd expect for a call to the API. + */ + protected function getResponse(string $type = 'success', int $status = 200): Response + { + return new Response(fopen(__DIR__ . '/responses/' . $type . '.json', 'rb'), $status); + } +} diff --git a/test/Users/UserTest.php b/test/Users/UserTest.php new file mode 100644 index 00000000..07767597 --- /dev/null +++ b/test/Users/UserTest.php @@ -0,0 +1,92 @@ + '1', + 'name' => 'Test User', + 'display_name' => 'Test Display Name', + 'image_url' => 'https://test.com/image.jpg', + 'properties' => ['prop1' => 'value1', 'prop2' => 'value2'], + 'channels' => ['channel1', 'channel2'], + '_links' => [ + 'self' => [ + 'href' => 'https://test.com/user/1' + ] + ] + ]; + + protected function setUp(): void + { + $this->user = new User(); + } + + public function testGetSetId(): void + { + $this->user->setId($this->testData['id']); + $this->assertEquals($this->testData['id'], $this->user->getId()); + } + + public function testGetSetName(): void + { + $this->user->setName($this->testData['name']); + $this->assertEquals($this->testData['name'], $this->user->getName()); + } + + public function testGetSetDisplayName(): void + { + $this->user->setDisplayName($this->testData['display_name']); + $this->assertEquals($this->testData['display_name'], $this->user->getDisplayName()); + } + + public function testGetSetImageUrl(): void + { + $this->user->setImageUrl($this->testData['image_url']); + $this->assertEquals($this->testData['image_url'], $this->user->getImageUrl()); + } + + public function testGetSetProperties(): void + { + $this->user->setProperties($this->testData['properties']); + $this->assertEquals($this->testData['properties'], $this->user->getProperties()); + } + + public function testGetSetChannels(): void + { + $this->user->setChannels($this->testData['channels']); + $this->assertEquals($this->testData['channels'], $this->user->getChannels()); + } + + public function testGetSetSelfLink(): void + { + $this->user->setSelfLink($this->testData['_links']['self']['href']); + $this->assertEquals($this->testData['_links']['self']['href'], $this->user->getSelfLink()); + } + + public function testFromArray(): void + { + $this->user->fromArray($this->testData); + $this->assertEquals($this->testData['id'], $this->user->getId()); + $this->assertEquals($this->testData['name'], $this->user->getName()); + $this->assertEquals($this->testData['display_name'], $this->user->getDisplayName()); + $this->assertEquals($this->testData['image_url'], $this->user->getImageUrl()); + $this->assertEquals($this->testData['properties'], $this->user->getProperties()); + $this->assertEquals($this->testData['channels'], $this->user->getChannels()); + $this->assertEquals($this->testData['_links']['self']['href'], $this->user->getSelfLink()); + } + + public function testToArray(): void + { + $this->user->fromArray($this->testData); + $toArrayData = $this->user->toArray(); + $this->assertEquals($this->testData, $toArrayData); + } +} diff --git a/test/Users/responses/create-user-success.json b/test/Users/responses/create-user-success.json new file mode 100644 index 00000000..3b08b144 --- /dev/null +++ b/test/Users/responses/create-user-success.json @@ -0,0 +1,80 @@ +{ + "id": "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name": "my_user_name", + "display_name": "My User Name", + "image_url": "https://example.com/image.png", + "properties": { + "custom_data": {} + }, + "channels": { + "pstn": [ + { + "property1": "string", + "property2": "string" + } + ], + "sip": [ + { + "property1": "string", + "property2": "string" + } + ], + "vbc": [ + { + "property1": "string", + "property2": "string" + } + ], + "websocket": [ + { + "property1": "string", + "property2": "string" + } + ], + "sms": [ + { + "number": "447700900000", + "property1": "string", + "property2": "string" + } + ], + "mms": [ + { + "number": "447700900000", + "property1": "string", + "property2": "string" + } + ], + "whatsapp": [ + { + "number": "447700900000", + "property1": "string", + "property2": "string" + } + ], + "viber": [ + { + "number": "447700900000", + "property1": "string", + "property2": "string" + } + ], + "messenger": [ + { + "id": "0", + "property1": "string", + "property2": "string" + } + ] + }, + "_links": { + "self": { + "href": "https://api.nexmo.com/v0.3/users/USR-82e028d9-5201-4f1e-8188-604b2d3471ec" + } + }, + "timestamp": { + "created": "2020-01-01T14:00:00.00Z", + "updated": "2020-01-01T14:05:00.00Z", + "destroyed": "2020-01-01T14:20:00.00Z" + } +} \ No newline at end of file diff --git a/test/Users/responses/get-user-success.json b/test/Users/responses/get-user-success.json new file mode 100644 index 00000000..3b08b144 --- /dev/null +++ b/test/Users/responses/get-user-success.json @@ -0,0 +1,80 @@ +{ + "id": "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name": "my_user_name", + "display_name": "My User Name", + "image_url": "https://example.com/image.png", + "properties": { + "custom_data": {} + }, + "channels": { + "pstn": [ + { + "property1": "string", + "property2": "string" + } + ], + "sip": [ + { + "property1": "string", + "property2": "string" + } + ], + "vbc": [ + { + "property1": "string", + "property2": "string" + } + ], + "websocket": [ + { + "property1": "string", + "property2": "string" + } + ], + "sms": [ + { + "number": "447700900000", + "property1": "string", + "property2": "string" + } + ], + "mms": [ + { + "number": "447700900000", + "property1": "string", + "property2": "string" + } + ], + "whatsapp": [ + { + "number": "447700900000", + "property1": "string", + "property2": "string" + } + ], + "viber": [ + { + "number": "447700900000", + "property1": "string", + "property2": "string" + } + ], + "messenger": [ + { + "id": "0", + "property1": "string", + "property2": "string" + } + ] + }, + "_links": { + "self": { + "href": "https://api.nexmo.com/v0.3/users/USR-82e028d9-5201-4f1e-8188-604b2d3471ec" + } + }, + "timestamp": { + "created": "2020-01-01T14:00:00.00Z", + "updated": "2020-01-01T14:05:00.00Z", + "destroyed": "2020-01-01T14:20:00.00Z" + } +} \ No newline at end of file diff --git a/test/Users/responses/list-user-success.json b/test/Users/responses/list-user-success.json new file mode 100644 index 00000000..a49e31d6 --- /dev/null +++ b/test/Users/responses/list-user-success.json @@ -0,0 +1,28 @@ +{ + "page_size": 10, + "_embedded": { + "users": [ + { + "id": "USR-82e028d9-5201-4f1e-8188-604b2d3471ec", + "name": "my_user_name", + "display_name": "My User Name", + "_links": { + "self": { + "href": "https://api.nexmo.com/v0.3/users/USR-82e028d9-5201-4f1e-8188-604b2d3471ec" + } + } + } + ] + }, + "_links": { + "first": { + "href": "https://api.nexmo.com/v0.3/users?order=desc&page_size=10" + }, + "self": { + "href": "https://api.nexmo.com/v0.3/users?order=desc&page_size=10&cursor=7EjDNQrAcipmOnc0HCzpQRkhBULzY44ljGUX4lXKyUIVfiZay5pv9wg%3D" + }, + "prev": { + "href": "https://api.nexmo.com/v0.3/users?order=desc&page_size=10&cursor=7EjDNQrAcipmOnc0HCzpQRkhBULzY44ljGUX4lXKyUIVfiZay5pv9wg%3D" + } + } +} \ No newline at end of file diff --git a/test/Users/responses/update-user-success.json b/test/Users/responses/update-user-success.json new file mode 100644 index 00000000..352a80b2 --- /dev/null +++ b/test/Users/responses/update-user-success.json @@ -0,0 +1,66 @@ +{ + "name": "my_patched_user_name", + "display_name": "My Patched User Name", + "image_url": "https://example.com/image.png", + "channels": { + "pstn": [ + { + "property1": "string", + "property2": "string" + } + ], + "sip": [ + { + "property1": "string", + "property2": "string" + } + ], + "vbc": [ + { + "property1": "string", + "property2": "string" + } + ], + "websocket": [ + { + "property1": "string", + "property2": "string" + } + ], + "sms": [ + { + "number": "447700900000", + "property1": "string", + "property2": "string" + } + ], + "mms": [ + { + "number": "447700900000", + "property1": "string", + "property2": "string" + } + ], + "whatsapp": [ + { + "number": "447700900000", + "property1": "string", + "property2": "string" + } + ], + "viber": [ + { + "number": "447700900000", + "property1": "string", + "property2": "string" + } + ], + "messenger": [ + { + "id": "0", + "property1": "string", + "property2": "string" + } + ] + } +} \ No newline at end of file