Skip to content

Commit

Permalink
Code Coverage Improvements (#533)
Browse files Browse the repository at this point in the history
* Test all client factory configurations

* Ignore coverage output

* Add coverage for hardcoded error handler

* Fixed the Signature Body and wrote test for it

* Added exception and credentials testing

* More tests
  • Loading branch information
SecondeJK authored Feb 3, 2025
1 parent ca5a904 commit 966324b
Show file tree
Hide file tree
Showing 53 changed files with 1,928 additions and 40 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ logs
.php_cs.cache
.phpunit.result.cache
coverage.xml
**/.DS_Store
**/.DS_Store
coverage
coverage.txt
15 changes: 15 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
<include>
<directory suffix=".php">src</directory>
</include>
<report>
<html outputDirectory="coverage"/>
</report>
</coverage>
<testsuites>
<testsuite name="default">
Expand All @@ -23,9 +26,18 @@
<testsuite name="verify">
<directory>test/Verify</directory>
</testsuite>
<testsuite name="handlers">
<directory>test/Client/Credentials/Handler</directory>
</testsuite>
<testsuite name="account">
<directory>test/Account</directory>
</testsuite>
<testsuite name="application">
<directory>test/Application</directory>
</testsuite>
<testsuite name="conversion">
<directory>test/Conversion</directory>
</testsuite>
<testsuite name="verify2">
<directory>test/Verify2</directory>
</testsuite>
Expand Down Expand Up @@ -74,6 +86,9 @@
<testsuite name="users">
<directory>test/Users</directory>
</testsuite>
<testsuite name="insights">
<directory>test/Insights</directory>
</testsuite>
</testsuites>
<php>
<ini name='error_reporting' value='E_ALL' />
Expand Down
1 change: 0 additions & 1 deletion src/Account/ClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Psr\Container\ContainerInterface;
use Vonage\Client\APIResource;
use Vonage\Client\Credentials\Handler\BasicHandler;
use Vonage\Client\Credentials\Handler\BasicQueryHandler;

class ClientFactory
{
Expand Down
11 changes: 11 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,17 @@ public function __get($name)
return $this->factory->get($name);
}

public function getDebug(): mixed
{
return $this->debug;
}

public function setDebug(mixed $debug): Client
{
$this->debug = $debug;
return $this;
}

/**
* @deprecated Use the Verify Client, this shouldn't be here and will be removed.
*/
Expand Down
5 changes: 5 additions & 0 deletions src/Client/APIExceptionHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ public function setRfc7807Format(string $format): void
$this->rfc7807Format = $format;
}

public function getRfc7807Format(): string
{
return $this->rfc7807Format;
}

/**
* @throws Exception\Exception
*
Expand Down
7 changes: 4 additions & 3 deletions src/Client/Credentials/Handler/SignatureBodyFormHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Vonage\Client\Credentials\Handler;

use GuzzleHttp\Psr7\Utils;
use Psr\Http\Message\RequestInterface;
use Vonage\Client\Credentials\CredentialsInterface;
use Vonage\Client\Credentials\SignatureSecret;
Expand All @@ -17,6 +18,7 @@ public function __invoke(RequestInterface $request, CredentialsInterface $creden
$body = $request->getBody();
$body->rewind();
$content = $body->getContents();

$params = [];
parse_str($content, $params);
$params['api_key'] = $credentialsArray['api_key'];
Expand All @@ -28,9 +30,8 @@ public function __invoke(RequestInterface $request, CredentialsInterface $creden
);

$params = $signature->getSignedParams();
$body->rewind();
$body->write(http_build_query($params, '', '&'));

return $request;
$newBody = Utils::streamFor(http_build_query($params, '', '&'));
return $request->withBody($newBody);
}
}
2 changes: 1 addition & 1 deletion src/Conversion/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ protected function getException(ResponseInterface $response): ClientException\Ex

if ($status === 402) {
$e = new ClientException\Request('This endpoint may need activating on your account. ' .
'"Please email [email protected] for more information', $status);
'Please email [email protected] for more information', $status);
} elseif ($status >= 400 && $status < 500) {
$e = new ClientException\Request($body['error_title'], $status);
} elseif ($status >= 500 && $status < 600) {
Expand Down
39 changes: 16 additions & 23 deletions test/Account/ClientFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,30 @@

namespace VonageTest\Account;

use VonageTest\VonageTestCase;
use Vonage\Account\ClientFactory;
use PHPUnit\Framework\TestCase;
use Vonage\Client;
use Vonage\Client\APIResource;
use Vonage\Client\Factory\MapFactory;
use Vonage\Account\ClientFactory;

class ClientFactoryTest extends VonageTestCase
class ClientFactoryTest extends TestCase
{
/**
* @var MapFactory
*/
protected $mapFactory;

protected $vonageClient;

public function setUp(): void
public function testInvokeCreatesClientWithConfiguredApiResource(): void
{
$this->vonageClient = $this->prophesize(Client::class);
$this->vonageClient->getRestUrl()->willReturn('https://rest.nexmo.com');
$this->vonageClient->getApiUrl()->willReturn('https://api.nexmo.com');
$mockServices = [
'account' => ClientFactory::class,
APIResource::class => APIResource::class,
];

/** @noinspection PhpParamsInspection */
$this->mapFactory = new MapFactory([APIResource::class => APIResource::class], $this->vonageClient->reveal());
}

public function testURIsAreCorrect(): void
{
$mockClient = $this->createMock(Client::class);
$container = new MapFactory($mockServices, $mockClient);
$factory = new ClientFactory();
$client = $factory($this->mapFactory);

$this->assertSame('/account', $client->getAPIResource()->getBaseUri());
$this->assertSame('https://rest.nexmo.com', $client->getAPIResource()->getBaseUrl());
$result = $factory($container);
$this->assertInstanceOf(\Vonage\Account\Client::class, $result);
$this->assertEquals('/account', $result->getAPIResource()->getBaseUri());
$this->assertInstanceOf(Client\Credentials\Handler\BasicHandler::class, $result->getAPIResource()
->getAuthHandlers()[0]);
$this->assertFalse($result->getAPIResource()->isHAL());
}
}
33 changes: 33 additions & 0 deletions test/Application/ClientFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace VonageTest\Application;

use PHPUnit\Framework\TestCase;
use Vonage\Client;
use Vonage\Client\APIResource;
use Vonage\Client\Factory\MapFactory;
use Vonage\Application\ClientFactory;

class ClientFactoryTest extends TestCase
{
public function testInvokeCreatesClientWithConfiguredApiResource(): void
{
$mockServices = [
'account' => ClientFactory::class,
APIResource::class => APIResource::class,
];

$mockClient = $this->createMock(Client::class);
$container = new MapFactory($mockServices, $mockClient);
$factory = new ClientFactory();

$result = $factory($container);
$this->assertInstanceOf(\Vonage\Application\Client::class, $result);
$this->assertEquals('/v2/applications', $result->getAPIResource()->getBaseUri());
$this->assertInstanceOf(Client\Credentials\Handler\BasicHandler::class, $result->getAPIResource()
->getAuthHandlers()[0]);
$this->assertEquals('applications', $result->getAPIResource()->getCollectionName());
}
}
97 changes: 97 additions & 0 deletions test/Client/CallbackTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

declare(strict_types=1);

namespace Tests\Vonage\Client\Callback;

use PHPUnit\Framework\TestCase;
use Vonage\Client\Callback\Callback;
use RuntimeException;
use InvalidArgumentException;

class CallbackTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();

// Mocking the $_GET and $_POST superglobals for testing purposes
$_GET = [
'key1' => 'value1',
'key2' => 'value2',
];

$_POST = [
'key3' => 'value3',
'key4' => 'value4',
];
}

public function testConstructorWithMissingKeys(): void
{
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('missing expected callback keys: key1, key2');

$callback = new class (['key3' => 'value3']) extends Callback {
protected array $expected = ['key1', 'key2'];
};
}

public function testConstructorWithAllKeys(): void
{
$callback = new class ([
'key1' => 'value1',
'key2' => 'value2',
]) extends Callback {
protected array $expected = ['key1', 'key2'];
};

$this->assertSame([
'key1' => 'value1',
'key2' => 'value2',
], $callback->getData());
}

public function testFromEnvPost(): void
{
$callback = Callback::fromEnv(Callback::ENV_POST);

$this->assertInstanceOf(Callback::class, $callback);
$this->assertSame([
'key3' => 'value3',
'key4' => 'value4',
], $callback->getData());
}

public function testFromEnvGet(): void
{
$callback = Callback::fromEnv(Callback::ENV_GET);

$this->assertInstanceOf(Callback::class, $callback);
$this->assertSame([
'key1' => 'value1',
'key2' => 'value2',
], $callback->getData());
}

public function testFromEnvAll(): void
{
$callback = Callback::fromEnv(Callback::ENV_ALL);

$this->assertInstanceOf(Callback::class, $callback);
$this->assertSame([
'key1' => 'value1',
'key2' => 'value2',
'key3' => 'value3',
'key4' => 'value4',
], $callback->getData());
}

public function testFromEnvInvalidSource(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('invalid source: invalid');

Callback::fromEnv('invalid');
}
}
38 changes: 38 additions & 0 deletions test/Client/Credentials/Handler/SignatureBodyFormHandlerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace VonageTest\Client\Credentials\Handler;

use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Utils;
use Vonage\Client\Credentials\SignatureSecret;
use VonageTest\VonageTestCase;
use Vonage\Client\Credentials\Handler\SignatureBodyFormHandler;

class SignatureBodyFormHandlerTest extends VonageTestCase
{
public function testSignatureBodyFormHandler()
{
$initialBody = http_build_query(['param1' => 'value1', 'param2' => 'value2']);

$request = new Request(
'POST',
'/test',
['Content-Type' => 'application/x-www-form-urlencoded'],
Utils::streamFor($initialBody)
);

$credentials = new SignatureSecret('secret', 'sha256');

$handler = new SignatureBodyFormHandler();
$authRequest = $handler($request, $credentials);
$authRequest->getBody()->rewind();
$newBody = $authRequest->getBody()->getContents();

parse_str($newBody, $params);

$this->assertArrayHasKey('api_key', $params);
$this->assertArrayHasKey('sig', $params);
}
}
36 changes: 36 additions & 0 deletions test/Client/Credentials/Handler/SignatureBodyHandlerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace VonageTest\Client\Credentials\Handler;

use GuzzleHttp\Psr7\Request;
use Vonage\Client\Credentials\Handler\SignatureBodyHandler;
use Vonage\Client\Credentials\SignatureSecret;
use VonageTest\VonageTestCase;

class SignatureBodyHandlerTest extends VonageTestCase
{
public function testSignatureBodyHandler(): void
{
$request = new Request(
'POST',
'/test',
['Content-Type' => 'application/json'],
json_encode(['foo' => 'bar'])
);

$credentials = new SignatureSecret('secret', 'sha256');

$handler = new SignatureBodyHandler();
$authRequest = $handler($request, $credentials);
$authRequest->getBody()->rewind();
$newBody = $authRequest->getBody()->getContents();
$newBodyArray = json_decode($newBody, true);

$this->assertIsArray($newBodyArray);
$this->assertArrayHasKey('foo', $newBodyArray);
$this->assertEquals('bar', $newBodyArray['foo']);
$this->assertArrayHasKey('sig', $newBodyArray);
}
}
Loading

0 comments on commit 966324b

Please sign in to comment.