From d2ce82454c05628a11a1c1135ce5be5e85e65714 Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Tue, 24 Dec 2024 00:07:06 +0100 Subject: [PATCH] add tests --- composer.json | 7 ++ phpunit.xml | 20 +++ tests/ApiTestCase.php | 75 ++++++++++++ tests/README.md | 11 ++ tests/sensitiveMessageFormatterTest.php | 154 ++++++++++++++++++++++++ 5 files changed, 267 insertions(+) create mode 100644 phpunit.xml create mode 100644 tests/ApiTestCase.php create mode 100644 tests/README.md create mode 100644 tests/sensitiveMessageFormatterTest.php diff --git a/composer.json b/composer.json index 6e17baa..1a2fdbe 100644 --- a/composer.json +++ b/composer.json @@ -25,6 +25,7 @@ }, "require-dev": { "php": "^8.2", + "phpunit/phpunit": "^10.5", "friendsofphp/php-cs-fixer": "^3.65", "phpstan/phpstan": "^2.0" }, @@ -33,7 +34,13 @@ "D3\\SensitiveMessageFormatter\\": "src/" } }, + "autoload-dev": { + "psr-4": { + "D3\\SensitiveMessageFormatter\\tests\\": "tests/" + } + }, "scripts": { + "test": "./vendor/bin/phpunit", "check-style": "./vendor/bin/php-cs-fixer fix --verbose --dry-run", "fix-style": "./vendor/bin/php-cs-fixer fix --verbose", "check-code": "./vendor/bin/phpstan analyse -c phpstan.neon --no-progress --ansi" diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..0efe48b --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,20 @@ + + + + + src + + + + + + + ./tests + + + diff --git a/tests/ApiTestCase.php b/tests/ApiTestCase.php new file mode 100644 index 0000000..97e94f5 --- /dev/null +++ b/tests/ApiTestCase.php @@ -0,0 +1,75 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\SensitiveMessageFormatter\tests; + +use PHPUnit\Framework\TestCase; +use ReflectionClass; +use ReflectionException; + +abstract class ApiTestCase extends TestCase +{ + /** + * Calls a private or protected object method. + * + * @param object $object + * @param string $methodName + * @param array $arguments + * + * @return mixed + * @throws ReflectionException + */ + public function callMethod(object $object, string $methodName, array $arguments = []): mixed + { + $class = new ReflectionClass($object); + $method = $class->getMethod($methodName); + $method->setAccessible(true); + return $method->invokeArgs($object, $arguments); + } + + /** + * Sets a private or protected property in defined class instance + * + * @param object $object + * @param string $valueName + * @param $value + * @throws ReflectionException + */ + public function setValue(object $object, string $valueName, $value): void + { + $reflection = new ReflectionClass($object); + $property = $reflection->getProperty($valueName); + $property->setAccessible(true); + $property->setValue($object, $value); + } + + /** + * get a private or protected property from defined class instance + * + * @param object $object + * @param string $valueName + * @return mixed + * @throws ReflectionException + */ + public function getValue(object $object, string $valueName): mixed + { + $reflection = new ReflectionClass($object); + $property = $reflection->getProperty($valueName); + $property->setAccessible(true); + return $property->getValue($object); + } +} diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..71edeae --- /dev/null +++ b/tests/README.md @@ -0,0 +1,11 @@ +# Installation + +``` +composer create-project -s dev --prefer-source [--repository '{"type": "vcs", "url": "repository url"}'] d3/sensitive-message-formatter . +``` + +# Run tests + +``` +./vendor/bin/phpunit [--no-coverage] [--coverage-html=cov] +``` diff --git a/tests/sensitiveMessageFormatterTest.php b/tests/sensitiveMessageFormatterTest.php new file mode 100644 index 0000000..d5ad5f6 --- /dev/null +++ b/tests/sensitiveMessageFormatterTest.php @@ -0,0 +1,154 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\SensitiveMessageFormatter\tests; + +use D3\SensitiveMessageFormatter\sensitiveMessageFormatter; +use Generator; +use GuzzleHttp\Psr7\Request; +use GuzzleHttp\Psr7\Response; +use ReflectionException; + +/** + * @covers \D3\SensitiveMessageFormatter\sensitiveMessageFormatter + */ +class sensitiveMessageFormatterTest extends ApiTestCase +{ + protected sensitiveMessageFormatter $sut; + + public function setUp(): void + { + parent::setUp(); + + $this->sut = new sensitiveMessageFormatter( + '{method} {uri} HTTP/{version} {req_headers} {req_body} -- RESPONSE: {code} - {res_headers} {res_body}' + ); + } + + /** + * @test + * @throws ReflectionException + * @covers \D3\SensitiveMessageFormatter\sensitiveMessageFormatter::__construct + */ + public function testConstruct(): void + { + $sutMock = $this->getMockBuilder(sensitiveMessageFormatter::class) + ->disableOriginalConstructor() + ->onlyMethods(['createReplacements']) + ->getMock(); + $sutMock->expects($this->once())->method('createReplacements'); + + $sutMock->__construct(); + + $this->assertSame( + '*', + $this->getValue( + $this->sut, + 'replaceChar' + ) + ); + } + + /** + * @test + * @throws ReflectionException + * @dataProvider createReplacementsDataProvider + * @covers \D3\SensitiveMessageFormatter\sensitiveMessageFormatter::createReplacements + */ + public function testCreateReplacements(array $input, array $expected, ?string $replacement = null): void + { + if ($replacement) { + $this->setValue( + $this->sut, + 'replaceChar', + $replacement + ); + } + + $this->callMethod( + $this->sut, + 'createReplacements', + [$input] + ); + + $this->assertSame( + $expected, + $this->getValue( + $this->sut, + 'anonymizations' + ) + ); + } + + public static function createReplacementsDataProvider(): Generator + { + yield 'simple' => [['abc'], ['abc' => '***']]; + yield 'multiple' => [['def', 'def'], ['def' => '***']]; + yield 'urlencoded' => [['1&c'], ['1&c' => '***', '1%26c' => '***' ]]; + yield 'different replace char' => [['abcd'], ['abcd' => '####'], '#']; + } + + /** + * @test + * @throws ReflectionException + * @dataProvider formatDataProvider + * @covers \D3\SensitiveMessageFormatter\sensitiveMessageFormatter::format + */ + public function testFormat(array $replacements, $expected): void + { + $this->callMethod( + $this->sut, + 'createReplacements', + [$replacements] + ); + + $request = new Request( + 'POST', + 'google.com', + ['header1' => 'value1', 'header2' => 'val%26ue2'], + 'Body value1 + value2' + ); + $response = new Response( + 200, + ['header1' => 'value1', 'header2' => 'value2'], + 'Body value1 + value2' + ); + + $this->assertEquals( + $expected, + preg_replace( + '@(\r\n|\r|\n)@', + '==', + $this->callMethod( + $this->sut, + 'format', + [$request, $response] + ) + ) + ); + } + + public static function formatDataProvider(): Generator + { + yield [ + ['value1', 'val&ue2'], + 'POST google.com HTTP/1.1 POST google.com HTTP/1.1=='. + 'header1: ******==header2: ******* Body ****** + value2 -- RESPONSE: 200 - HTTP/1.1 200 OK=='. + 'header1: ******==header2: value2 Body ****** + value2', + ]; + } +}