Skip to content

Commit 4a06474

Browse files
committed
I-5 Implement logic to get most similar notMatched request and show a diff
1 parent 1643555 commit 4a06474

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

src/Client/MockServer.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace DEVizzent\CodeceptionMockServerHelper\Client;
44

5+
use DEVizzent\CodeceptionMockServerHelper\MockServerHelper;
56
use GuzzleHttp\Client;
67
use GuzzleHttp\Psr7\Request;
78
use PHPUnit\Framework\Assert;
@@ -33,6 +34,21 @@ public function verify(string $expectationId, ?int $times = null): void
3334
$response->getBody()->getContents()
3435
);
3536
}
37+
38+
public function getNotMatchedRequests(): array
39+
{
40+
$notMatchedRequests = [];
41+
$request = new Request('PUT', '/mockserver/retrieve?format=json&type=request_responses');
42+
$response = $this->mockserverClient->sendRequest($request);
43+
$requestResponses = json_decode($response->getBody()->getContents(), true);
44+
foreach ($requestResponses as $requestResponse) {
45+
$message = $requestResponse['httpResponse']['body']['message'] ?? '';
46+
if ($message === 'Request not matched by MockServer') {
47+
$notMatchedRequests[] = $requestResponse['httpRequest'];
48+
}
49+
}
50+
return $notMatchedRequests;
51+
}
3652
public function create(string $json): void
3753
{
3854
$request = new Request(

src/MockServerHelper.php

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use DEVizzent\CodeceptionMockServerHelper\Config\ExpectationsPath;
1111
use DEVizzent\CodeceptionMockServerHelper\Config\NotMatchedRequest;
1212
use GuzzleHttp\Client;
13+
use Jfcherng\Diff\DiffHelper;
1314
use PHPUnit\Framework\Assert;
1415
use PHPUnit\Framework\AssertionFailedError;
1516
use PHPUnit\Framework\ExpectationFailedException;
@@ -25,6 +26,7 @@ class MockServerHelper extends Module
2526
private CleanUpBefore $cleanUpBefore;
2627
private NotMatchedRequest $notMatchedRequest;
2728
private ExpectationsPath $expectationPath;
29+
2830
/** @param array<string, string>|null $config */
2931
public function __construct(ModuleContainer $moduleContainer, ?array $config = null)
3032
{
@@ -49,7 +51,7 @@ public function _initialize(): void
4951
$this->expectationPath = new ExpectationsPath($this->config[self::CONFIG_EXPECTATIONS_PATH]);
5052
}
5153
$this->mockserver = new MockServer(new Client([
52-
'base_uri' => $this->config[self::CONFIG_URL]
54+
'base_uri' => $this->config[self::CONFIG_URL]
5355
]));
5456
if ($this->notMatchedRequest->isEnabled()) {
5557
$this->createMockRequestFromJsonFile(__DIR__ . '/not-matched-request.json');
@@ -84,7 +86,29 @@ public function _before(TestInterface $test): void
8486

8587
public function seeMockRequestWasCalled(string $expectationId, ?int $times = null): void
8688
{
87-
$this->mockserver->verify($expectationId, $times);
89+
try {
90+
$this->mockserver->verify($expectationId, $times);
91+
} catch (AssertionFailedError $exception) {
92+
//throw $exception;
93+
preg_match('#(.|\n)* expected:<(?<expected>\{(.|\n)*\})> but was:<(.|\n)*>#', $exception->getMessage(), $matches);
94+
if (empty($matches)) {
95+
throw $exception;
96+
}
97+
$expected = json_decode($matches['expected'], true);
98+
$notMatchedRequests = $this->mockserver->getNotMatchedRequests();
99+
$currentSimilityRatio = 0;
100+
$expectedFormatted = $this->formatMockServerRequest($expected);
101+
foreach ($notMatchedRequests as $notMatchedRequest) {
102+
$diff = DiffHelper::calculate($expectedFormatted, $this->formatMockServerRequest($notMatchedRequest));
103+
$statistics = DiffHelper::getStatistics();
104+
$similityRatio = $statistics['unmodified'] - $statistics['inserted'] - $statistics['deleted'];
105+
if ($currentSimilityRatio < $similityRatio) {
106+
$currentSimilityRatio = $similityRatio;
107+
$bestDiff = $diff;
108+
}
109+
}
110+
throw new AssertionFailedError('Impossible match request: '. PHP_EOL . $bestDiff);
111+
}
88112
}
89113

90114
public function seeMockRequestWasNotCalled(string $expectationId): void
@@ -138,4 +162,10 @@ public function createMockRequestFromJsonFile(string $expectationFile): void
138162
Assert::assertIsString($expectationJson);
139163
$this->createMockRequest($expectationJson);
140164
}
165+
166+
public function formatMockServerRequest(array $mockServerRequest): string
167+
{
168+
ksort($mockServerRequest);
169+
return json_encode($mockServerRequest, JSON_PRETTY_PRINT);
170+
}
141171
}

tests/Integration/SeeMockRequestWasCalledTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Codeception\Lib\ModuleContainer;
66
use DEVizzent\CodeceptionMockServerHelper\MockServerHelper;
77
use GuzzleHttp\Client;
8+
use PHPUnit\Framework\AssertionFailedError;
89
use PHPUnit\Framework\ExpectationFailedException;
910
use PHPUnit\Framework\TestCase;
1011

@@ -56,4 +57,28 @@ public function testExpectationNotWasCalledThrowException2(): void
5657
);
5758
$this->sot->seeMockRequestWasCalled('not-existing-expectation');
5859
}
60+
61+
public function testExpectationWasCalledButWasNotWithGoodRecomendation(): void
62+
{
63+
$this->client->request('GET', 'https://jsonplaceholder.typicode.com/posts/2', ['http_errors'=>false]);
64+
$this->client->request('GET', 'https://jsonplaceholder.typicode.com/posts/2', ['http_errors'=>false]);
65+
$this->client->request('GET', 'https://jsonplaceholder.typicode.com/posts/5', ['http_errors'=>false, 'headers' => ['randomHeader' => 'value']]);
66+
$this->client->request('GET', 'https://jsonplaceholder.typicode.com/users/3/albums', ['http_errors'=>false]);
67+
68+
$this->expectException(AssertionFailedError::class);
69+
$this->expectExceptionMessageMatches('#.*"path": "\\\/users\\\/3\\\/albums".*#');
70+
$this->sot->seeMockRequestWasCalled('get-post-1');
71+
}
72+
73+
public function testExpectationWasCalledButWasNotWithGoodRecomendation2(): void
74+
{
75+
$this->client->request('GET', 'https://jsonplaceholder.typicode.com/posts/2', ['http_errors'=>false]);
76+
$this->client->request('GET', 'https://jsonplaceholder.typicode.com/posts/2', ['http_errors'=>false]);
77+
$this->client->request('GET', 'https://jsonplaceholder.typicode.com/posts/5', ['http_errors'=>false]);
78+
$this->client->request('GET', 'https://jsonplaceholder.typicode.com/users/3/albums', ['http_errors'=>false, 'headers' => ['randomHeader' => 'value']]);
79+
80+
$this->expectException(AssertionFailedError::class);
81+
$this->expectExceptionMessageMatches('#.*"path": "\\\/posts\\\/5".*#');
82+
$this->sot->seeMockRequestWasCalled('get-post-1');
83+
}
5984
}

0 commit comments

Comments
 (0)