/tests/Middleware/AuthenticateTest.php

https://github.com/imbo/imboclient-php · PHP · 113 lines · 78 code · 13 blank · 22 comment · 1 complexity · 8104f068cb5207288f7a549641c24c59 MD5 · raw file

  1. <?php declare(strict_types=1);
  2. namespace ImboClient\Middleware;
  3. use ArrayObject;
  4. use GuzzleHttp\Promise\PromiseInterface;
  5. use GuzzleHttp\Psr7\Request;
  6. use ImboClient\Exception\RuntimeException;
  7. use PHPUnit\Framework\TestCase;
  8. use Psr\Http\Message\RequestInterface;
  9. /**
  10. * @coversDefaultClass ImboClient\Middleware\Authenticate
  11. */
  12. class AuthenticateTest extends TestCase
  13. {
  14. /**
  15. * @covers ::__construct
  16. * @covers ::__invoke
  17. * @covers ::addAuthenticationHeaders
  18. */
  19. public function testCanAddHeaders(): void
  20. {
  21. $assertions = function (RequestInterface $request, array $_options): PromiseInterface {
  22. $this->assertNotEmpty($request->getHeaderLine('x-imbo-publickey'));
  23. $this->assertNotEmpty($request->getHeaderLine('x-imbo-authenticate-signature'));
  24. $this->assertNotEmpty($request->getHeaderLine('x-imbo-authenticate-timestamp'));
  25. return $this->createMock(PromiseInterface::class);
  26. };
  27. $middleware = new Authenticate('public', 'private');
  28. $middleware($assertions)(new Request('GET', 'http://localhost'), ['require_imbo_signature' => true]);
  29. }
  30. /**
  31. * @covers ::addAuthenticationHeaders
  32. * @covers ::__invoke
  33. */
  34. public function testSignaturesAreUnique(): void
  35. {
  36. $numSignaturesToGenerate = 100;
  37. $signatures = new ArrayObject();
  38. $assertions = function (RequestInterface $request, array $_options) use ($signatures): PromiseInterface {
  39. $signatures->append($request->getHeaderLine('x-imbo-authenticate-signature'));
  40. return $this->createMock(PromiseInterface::class);
  41. };
  42. for ($i = 0; $i < $numSignaturesToGenerate; $i++) {
  43. $middleware = new Authenticate('public', uniqid('', true));
  44. $middleware($assertions)(new Request('GET', 'http://localhost/'), ['require_imbo_signature' => true]);
  45. }
  46. $this->assertCount(
  47. $numSignaturesToGenerate,
  48. $signatures,
  49. sprintf('Expected %d signatures', $numSignaturesToGenerate),
  50. );
  51. $this->assertSame(
  52. count(array_unique($signatures->getArrayCopy())),
  53. $signatures->count(),
  54. 'Did not expect duplicate signatures',
  55. );
  56. }
  57. /**
  58. * @return array<string,array{options:array<string,bool>}>
  59. */
  60. public function getOptions(): array
  61. {
  62. return [
  63. 'missing option' => [
  64. 'options' => [],
  65. ],
  66. 'option is false' => [
  67. 'options' => [
  68. 'require_imbo_signature' => false,
  69. ],
  70. ],
  71. ];
  72. }
  73. /**
  74. * @dataProvider getOptions
  75. * @covers ::__invoke
  76. */
  77. public function testDoesNotAddSignatureWhenOptionIsNotSet(array $options): void
  78. {
  79. $assertions = function (RequestInterface $request, array $_options): PromiseInterface {
  80. $this->assertEmpty($request->getHeaderLine('x-imbo-publickey'));
  81. $this->assertEmpty($request->getHeaderLine('x-imbo-authenticate-signature'));
  82. $this->assertEmpty($request->getHeaderLine('x-imbo-authenticate-timestamp'));
  83. return $this->createMock(PromiseInterface::class);
  84. };
  85. $middleware = new Authenticate('public', 'private');
  86. $middleware($assertions)(new Request('GET', 'http://localhost'), $options);
  87. }
  88. /**
  89. * @covers ::__invoke
  90. */
  91. public function testThrowsExceptionWhenHandlerResultIsIncorrect(): void
  92. {
  93. $handler = function (RequestInterface $_request, array $_options): RequestInterface {
  94. return $this->createMock(RequestInterface::class);
  95. };
  96. $middleware = new Authenticate('public', 'private');
  97. $this->expectException(RuntimeException::class);
  98. $middleware($handler)(new Request('GET', 'http://localhost'), []);
  99. }
  100. }