* @link https://www.oxidmodule.com */ declare(strict_types=1); namespace D3\SensitiveMessageFormatter\tests; use D3\SensitiveMessageFormatter\sensitiveMessageFormatter; use Generator; use GuzzleHttp\MessageFormatter; use GuzzleHttp\Psr7\Request; use GuzzleHttp\Psr7\Response; use ReflectionException; /** * @covers \D3\SensitiveMessageFormatter\sensitiveMessageFormatter */ class sensitiveMessageFormatterTest extends ApiTestCase { /** * @test * @throws ReflectionException * @covers \D3\SensitiveMessageFormatter\sensitiveMessageFormatter::__construct * @dataProvider constructDataProvider */ public function testConstruct(?string $replacement, string $expected): void { $sutMock = $this->getMockBuilder(sensitiveMessageFormatter::class) ->disableOriginalConstructor() ->onlyMethods(['convertStringsToRegex']) ->getMock(); $sutMock->expects($this->once())->method('convertStringsToRegex'); $sutMock->__construct(MessageFormatter::CLF, [], $replacement); $this->assertSame( $expected, $this->getValue( $sutMock, 'replacement' ) ); } public static function constructDataProvider(): Generator { yield 'without custom replacement' => [null, '*****']; yield 'with custom replacement' => ['-.-', '-.-']; } /** * @test * @throws ReflectionException * @dataProvider convertStringsToRegexDataProvider * @covers \D3\SensitiveMessageFormatter\sensitiveMessageFormatter::convertStringsToRegex */ public function testConvertStringsToRegex( array $input, array $expected ): void { $sutMock = $this->getMockBuilder(sensitiveMessageFormatter::class) ->disableOriginalConstructor() ->getMock(); $this->callMethod( $sutMock, 'convertStringsToRegex', [$input] ); $this->assertSame( $expected, $this->getValue( $sutMock, 'anonymizations' ) ); } public static function convertStringsToRegexDataProvider(): Generator { yield 'simple' => [['abc'], ['/abc/i']]; yield 'multiple' => [['def', 'ghi'], ['/def/i', '/ghi/i']]; yield 'urlencoded' => [['1&c'], ['/1&c/i', '/1%26c/i']]; yield 'delimiter' => [['de/fg'], ['/de\/fg/i', '/de%2Ffg/i']]; yield 'regex' => [['/abc/mi'], ['/abc/mi']]; yield 'mixed' => [['/abc/mi', 'def', '/ghi/mi'], ['/abc/mi', '/def/i', '/ghi/mi']]; } /** * @test * @throws ReflectionException * @dataProvider formatDataProvider * @covers \D3\SensitiveMessageFormatter\sensitiveMessageFormatter::format */ public function testFormat(array $replacements, $expected): void { $sut = new sensitiveMessageFormatter( '{method} {uri} HTTP/{version} {req_headers} {req_body} -- RESPONSE: {code} - {res_headers} {res_body}', $replacements ); $request = new Request( 'POST', 'google.com', ['header1' => 'value1', 'header2' => 'val%26ue2'], 'Body value1 + value2, Body value1 + value2 aBodyb' ); $response = new Response( 200, ['header1' => 'value1', 'header2' => 'value2'], 'Body value1 + value2' ); $this->assertEquals( $expected, preg_replace( '@(\r\n|\r|\n)@', '==', $this->callMethod( $sut, 'format', [$request, $response] ) ) ); } public static function formatDataProvider(): Generator { yield 'plain' => [ ['value1', 'val&ue2'], 'POST google.com HTTP/1.1 POST google.com HTTP/1.1=='. 'header1: *****==header2: ***** Body ***** + value2, Body ***** + value2 aBodyb -- RESPONSE: 200 - HTTP/1.1 200 OK=='. 'header1: *****==header2: value2 Body ***** + value2', ]; yield 'regex placeholders' => [ ['/go.?gle/i'], 'POST *****.com HTTP/1.1 POST *****.com HTTP/1.1=='. 'header1: value1==header2: val%26ue2 Body value1 + value2, Body value1 + value2 aBodyb -- RESPONSE: 200 - HTTP/1.1 200 OK=='. 'header1: value1==header2: value2 Body value1 + value2', ]; yield 'regex control chars + look behind' => [ ['/\bbody\b/i', '/(?<=RESPONSE:\s)200/i'], 'POST google.com HTTP/1.1 POST google.com HTTP/1.1=='. 'header1: value1==header2: val%26ue2 ***** value1 + value2, ***** value1 + value2 aBodyb -- RESPONSE: ***** - HTTP/1.1 200 OK=='. 'header1: value1==header2: value2 ***** value1 + value2', ]; } }