Skip to content

Commit

Permalink
feat(client): add a catchpoint client
Browse files Browse the repository at this point in the history
Include methods for authentication, this involves logging in, refreshing
a token, and revoking a token
  • Loading branch information
jefflembeck committed Jan 20, 2022
1 parent fb615e2 commit 731a0c2
Show file tree
Hide file tree
Showing 22 changed files with 466 additions and 74 deletions.
14 changes: 7 additions & 7 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions tests/models/AuthTokenTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php declare(strict_types=1);

use PHPUnit\Framework\TestCase;
use WebPageTest\AuthToken;

final class AuthTokenTest extends TestCase {
public function testConstructorSetsValues () : void {
$options = array(
'access_token' => 'abcdef123',
'expires_in' => 4,
'refresh_token' => 'bcedef1234',
'scope' => 'ohno',
'token_type' => 'id'
);
$auth_token = new AuthToken($options);
$this->assertEquals('abcdef123', $auth_token->access_token);
$this->assertEquals(4, $auth_token->expires_in);
$this->assertEquals('bcedef1234', $auth_token->refresh_token);
$this->assertEquals('ohno', $auth_token->scope);
$this->assertEquals('id', $auth_token->token_type);
}
}
?>
266 changes: 266 additions & 0 deletions tests/models/CPClientTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
<?php declare(strict_types=1);

use PHPUnit\Framework\TestCase;
use WebPageTest\CPClient;
use WebPageTest\AuthToken;
use WebPageTest\Exception\ClientException;

use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Middleware;

final class CPClientTest extends TestCase {
public function testConstructorSetsDefaults () : void {
$host = 'http://127.0.0.1';

$client = new CPClient($host, array());

$this->assertNull($client->client_id);
$this->assertNull($client->client_secret);
$this->assertNull($client->grant_type);
}

public function testConstructorSetsValues () : void {
$auth_client_options = array (
'client_id' => '123',
'client_secret' => '345',
'grant_type' => 'these are good to have'
);
$host = 'http://127.0.0.1';

$client = new CPClient($host, array(
'auth_client_options' => $auth_client_options
));

$this->assertEquals('123', $client->client_id);
$this->assertEquals('345', $client->client_secret);
$this->assertEquals('these are good to have', $client->grant_type);
}

public function testLoginCallsCorrectEndpointWithBody () : void {
$results = [];
$handler = $this->createRequestMock($results);
$host = "http://webpagetest.org";
$username = "janet";
$password = "ihaveapassword";
$base = 'http://127.0.0.1';
$client = new CPClient($host, array( 'auth_client_options' => [
'base_uri' => $base,
'client_id' => '123',
'client_secret' => '345',
'grant_type' => 'these are good to have',
'handler' => $handler
]
));
try {
$client->login($username, $password);
} catch (Exception $e) {
// this tries to live hit your local machine, kill it instantly
}

$this->assertCount(1, $results);
$transaction = $results[0];
$expected_method = 'POST';
$expected_body = 'client_id=123&client_secret=345&grant_type=these+are+good+to+have&username=janet&password=ihaveapassword';
$expected_uri = "{$base}/auth/connect/token";

$this->assertEquals($expected_method, $transaction['request']->getMethod());
$this->assertEquals($expected_body, $transaction['request']->getBody());
$this->assertEquals($expected_uri, $transaction['request']->getURI());
}

public function testLoginRespondsWithAuthToken () : void {
$handler = $this->createMockResponse(200, '{
"access_token": "abcdef123",
"expires_in": 4,
"refresh_token": "bcedef1234",
"scope": "ohno",
"token_type": "id"
}');
$host = "http://webpagetest.org";
$username = "janet";
$password = "ihaveapassword";
$client = new CPClient($host, array(
'auth_client_options' => [
'client_id' => '123',
'client_secret' => '345',
'grant_type' => 'these are good to have',
'handler' => $handler
]
));

$auth_token = $client->login($username, $password);
$this->assertInstanceOf(AuthToken::class, $auth_token);
$this->assertEquals('abcdef123', $auth_token->access_token);
}

public function testBadLoginResponse () : void {
$handler = $this->createMockResponse(400, '{ "error": "invalid" }');
$host = "http://webpagetest.org";
$username = "janet";
$password = "ihaveapassword";
$client = new CPClient($host, array(
'auth_client_options' => [
'client_id' => '123',
'client_secret' => '345',
'grant_type' => 'these are good to have',
'handler' => $handler
]
));

$this->expectException(ClientException::class);
$client->login($username, $password);
}

public function testRefreshAuthTokenCallsCorrectEndpoint () : void {
$results = [];
$handler = $this->createRequestMock($results);
$host = "http://webpagetest.org";
$refresh_token = "janetno";
$base = 'http://127.0.0.1';
$client = new CPClient($host, array( 'auth_client_options' => [
'base_uri' => $base,
'client_id' => '123',
'client_secret' => '345',
'grant_type' => 'these are good to have',
'handler' => $handler
]
));
try {
$client->refreshAuthToken($refresh_token);
} catch (Exception $e) {
// this tries to live hit your local machine, kill it instantly
}

$this->assertCount(1, $results);
$transaction = $results[0];
$expected_method = 'POST';
$expected_body = 'client_id=123&client_secret=345&grant_type=refresh_token&refresh_token=janetno';
$expected_uri = "{$base}/auth/connect/token";

$this->assertEquals($expected_method, $transaction['request']->getMethod());
$this->assertEquals($expected_body, $transaction['request']->getBody());
$this->assertEquals($expected_uri, $transaction['request']->getURI());
}

public function testRefreshAuthTokenRespondsWithAuthToken () : void {
$handler = $this->createMockResponse(200, '{
"access_token": "123",
"expires_in": 4,
"id_token": "abcdef139",
"refresh_token": "DEF",
"scope": "openid",
"token_type": "sure"
}');
$host = "http://webpagetest.org";
$refresh_token = "janetno";
$client = new CPClient($host, array(
'auth_client_options' => [
'client_id' => '123',
'client_secret' => '345',
'grant_type' => 'these are good to have',
'handler' => $handler
]
));

$auth_token = $client->refreshAuthToken($refresh_token);
$this->assertInstanceOf(AuthToken::class, $auth_token);
$this->assertEquals('123', $auth_token->access_token);
}

public function testRefreshAuthTokenBadResponse () : void {
$handler = $this->createMockResponse(400, '{ "error": "invalid" }');
$host = "http://webpagetest.org";
$refresh_token = "janetno";
$client = new CPClient($host, array(
'auth_client_options' => [
'client_id' => '123',
'client_secret' => '345',
'grant_type' => 'these are good to have',
'handler' => $handler
]
));

$this->expectException(ClientException::class);
$client->refreshAuthToken($refresh_token);
}

public function testRevokeTokenCallsCorrectEndpoint () : void {
$results = [];
$handler = $this->createRequestMock($results);
$host = "http://webpagetest.org";
$token = "janetno";
$base = 'http://127.0.0.1';
$client = new CPClient($host, array( 'auth_client_options' => [
'base_uri' => $base,
'client_id' => '123',
'client_secret' => '345',
'grant_type' => 'these are good to have',
'handler' => $handler
]
));
try {
$client->revokeToken($token);
} catch (Exception $e) {
// this tries to live hit your local machine, kill it instantly
}

$this->assertCount(1, $results);
$transaction = $results[0];
$expected_method = 'POST';
$expected_body = 'token=janetno&token_type_hint=access_token&client_id=123&client_secret=345';
$expected_uri = "{$base}/auth/connect/revocation";

$this->assertEquals($expected_method, $transaction['request']->getMethod());
$this->assertEquals($expected_body, $transaction['request']->getBody());
$this->assertEquals($expected_uri, $transaction['request']->getURI());
}

public function testRevokeTokenThrowsNoErrorOnOk () : void {
$handler = $this->createMockResponse(200, '');
$host = "http://webpagetest.org";
$token = "janetno";
$client = new CPClient($host, array(
'auth_client_options' => [
'client_id' => '123',
'client_secret' => '345',
'grant_type' => 'these are good to have',
'handler' => $handler
]
));

$this->assertNull($client->revokeToken($token));
}

public function testRevokeTokenBadResponse () : void {
$handler = $this->createMockResponse(400, '{ "error": "invalid" }');
$host = "http://webpagetest.org";
$token = "janetno";
$client = new CPClient($host, array(
'auth_client_options' => [
'client_id' => '123',
'client_secret' => '345',
'grant_type' => 'these are good to have',
'handler' => $handler
]
));

$this->expectException(ClientException::class);
$client->revokeToken($token);
}

private function createMockResponse (int $status, string $body) : HandlerStack {
$mock = new MockHandler([new Response($status, [], $body)]);
return HandlerStack::create($mock);
}

private function createRequestMock (array &$results) : HandlerStack {
$history = Middleware::history($results);
$handler = HandlerStack::create();
$handler->push($history);
return $handler;
}
}

?>
2 changes: 1 addition & 1 deletion vendor/autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInit14af0ddfbc16c4126602920a26b812c3::getLoader();
return ComposerAutoloaderInit9c12fec4b6151122c0ac4f5652ab47b7::getLoader();
4 changes: 2 additions & 2 deletions vendor/composer/autoload_files.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
$baseDir = dirname($vendorDir);

return array(
'ec07570ca5a812141189b1fa81503674' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert/Functions.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'ec07570ca5a812141189b1fa81503674' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert/Functions.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
);
4 changes: 2 additions & 2 deletions vendor/composer/autoload_psr4.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
$baseDir = dirname($vendorDir);

return array(
'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'),
'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/type-resolver/src', $vendorDir . '/phpdocumentor/reflection-docblock/src'),
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
'WebPageTest\\' => array($baseDir . '/www/models'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'),
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'),
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
Expand Down
Loading

0 comments on commit 731a0c2

Please sign in to comment.