Fix request fetching

This commit is contained in:
Jake Barnby
2026-01-13 22:01:16 +13:00
parent 8eb09a98fe
commit cd21140572
4 changed files with 162 additions and 57 deletions
+95 -14
View File
@@ -152,7 +152,7 @@ abstract class Scope extends TestCase
}
/**
* @deprecated Use assertLastRequest instead. Used only historically in webhook tests
* @deprecated Use getLastRequestForProject instead. Used only historically in webhook tests
*/
protected function getLastRequest(): array
{
@@ -163,31 +163,112 @@ abstract class Scope extends TestCase
* Get the last webhook request for a specific project.
* Polls with retry to handle parallel test race conditions.
*/
protected function getLastRequestForProject(string $projectId, int $maxAttempts = 10, int $delayMs = 500): array
{
$hostname = 'request-catcher-webhook';
protected function getLastRequestForProject(
string $projectId,
string $type = self::REQUEST_TYPE_WEBHOOK,
array $queryParams = [],
int $maxAttempts = 10,
int $delayMs = 500,
?callable $probe = null
): array {
$hostname = match ($type) {
self::REQUEST_TYPE_WEBHOOK => 'request-catcher-webhook',
self::REQUEST_TYPE_SMS => 'request-catcher-sms',
default => throw new \Exception('Invalid request catcher type.'),
};
$enforceProjectId = $type === self::REQUEST_TYPE_WEBHOOK;
if (empty($queryParams)) {
$queryParams = [
'header_X-Appwrite-Webhook-Project-Id' => $projectId,
];
}
$query = http_build_query($queryParams);
sleep(2);
for ($attempt = 0; $attempt < $maxAttempts; $attempt++) {
$request = json_decode(file_get_contents('http://' . $hostname . ':5000/__last_request__'), true);
if ($request) {
$request['data'] = json_decode($request['data'], true);
$requests = json_decode(file_get_contents('http://' . $hostname . ':5000/__find_request__?' . $query), true);
if (is_array($requests)) {
for ($i = count($requests) - 1; $i >= 0; $i--) {
$request = $this->decodeRequestData($requests[$i]);
if ($probe !== null) {
try {
$probe($request);
return $request;
} catch (\Throwable $error) {
continue;
}
}
$requestProjectId = $request['headers']['X-Appwrite-Webhook-Project-Id'] ?? '';
if ($requestProjectId === $projectId) {
return $request;
if ($enforceProjectId) {
$requestProjectId = $request['headers']['X-Appwrite-Webhook-Project-Id'] ?? '';
if ($requestProjectId === $projectId) {
return $request;
}
} else {
return $request;
}
}
}
usleep($delayMs * 1000);
}
$request = json_decode(file_get_contents('http://' . $hostname . ':5000/__last_request__'), true);
if ($request) {
$request['data'] = json_decode($request['data'], true);
$requests = json_decode(file_get_contents('http://' . $hostname . ':5000/__find_request__?' . $query), true);
if (is_array($requests)) {
for ($i = count($requests) - 1; $i >= 0; $i--) {
$request = $this->decodeRequestData($requests[$i]);
if ($probe !== null) {
try {
$probe($request);
return $request;
} catch (\Throwable $error) {
continue;
}
}
if ($enforceProjectId) {
$requestProjectId = $request['headers']['X-Appwrite-Webhook-Project-Id'] ?? '';
if ($requestProjectId === $projectId) {
return $request;
}
} else {
return $request;
}
}
}
return $request ?? [];
return [];
}
protected function decodeRequestData(array $request): array
{
if (!array_key_exists('data', $request)) {
return $request;
}
if (is_array($request['data'])) {
return $request;
}
if (!is_string($request['data']) || $request['data'] === '') {
return $request;
}
$decoded = json_decode($request['data'], true);
if (json_last_error() === JSON_ERROR_NONE) {
$request['data'] = $decoded;
return $request;
}
parse_str($request['data'], $parsed);
if (!empty($parsed)) {
$request['data'] = $parsed;
}
return $request;
}
/**
@@ -2530,14 +2530,23 @@ class AccountCustomClientTest extends Scope
$userId = $response['body']['userId'];
$smsRequest = $this->assertLastRequest(function (array $request) use ($number) {
$this->assertEquals('Appwrite Mock Message Sender', $request['headers']['User-Agent']);
$this->assertEquals('username', $request['headers']['X-Username']);
$this->assertEquals('password', $request['headers']['X-Key']);
$this->assertEquals('POST', $request['method']);
$this->assertEquals('+123456789', $request['data']['from']);
$this->assertEquals($number, $request['data']['to']);
}, Scope::REQUEST_TYPE_SMS);
$smsRequest = $this->getLastRequestForProject(
$this->getProject()['$id'],
Scope::REQUEST_TYPE_SMS,
[
'header_X-Username' => 'username',
'header_X-Key' => 'password',
'method' => 'POST',
],
probe: function (array $request) use ($number) {
$this->assertEquals('Appwrite Mock Message Sender', $request['headers']['User-Agent'] ?? null);
$this->assertEquals('username', $request['headers']['X-Username'] ?? null);
$this->assertEquals('password', $request['headers']['X-Key'] ?? null);
$this->assertEquals('POST', $request['method'] ?? null);
$this->assertEquals('+123456789', $request['data']['from'] ?? null);
$this->assertEquals($number, $request['data']['to'] ?? null);
}
);
$data['token'] = $smsRequest['data']['message'];
$data['id'] = $userId;
@@ -2887,15 +2896,30 @@ class AccountCustomClientTest extends Scope
$tokenCreatedAt = $response['body']['$createdAt'];
$smsRequest = $this->assertLastRequest(function ($request) use ($tokenCreatedAt) {
$this->assertArrayHasKey('data', $request);
$this->assertArrayHasKey('time', $request);
$this->assertArrayHasKey('message', $request['data'], "Last request missing message: " . \json_encode($request));
$phone = $data['phone'] ?? '';
$smsQuery = [
'header_X-Username' => 'username',
'header_X-Key' => 'password',
'method' => 'POST',
];
// Ensure we are not using token from last sms login
$tokenRecievedAt = $request['time'];
$this->assertGreaterThan($tokenCreatedAt, $tokenRecievedAt);
}, Scope::REQUEST_TYPE_SMS);
$smsRequest = $this->getLastRequestForProject(
$this->getProject()['$id'],
Scope::REQUEST_TYPE_SMS,
$smsQuery,
probe: function (array $request) use ($tokenCreatedAt, $phone) {
$this->assertArrayHasKey('data', $request);
$this->assertArrayHasKey('time', $request);
$this->assertArrayHasKey('message', $request['data'], "Last request missing message: " . \json_encode($request));
if (!empty($phone)) {
$this->assertEquals($phone, $request['data']['to'] ?? null);
}
// Ensure we are not using token from last sms login
$tokenRecievedAt = $request['time'];
$this->assertGreaterThan($tokenCreatedAt, $tokenRecievedAt);
}
);
/**
* Test for FAILURE