Merge pull request #8891 from owncloud/tests/flaky-sharing-tests

[tests-only] retry if auto-sync is enabled but client.synchronize is false
This commit is contained in:
Sawjan Gurung
2024-07-08 10:09:25 +05:45
committed by GitHub
9 changed files with 415 additions and 106 deletions
@@ -20,7 +20,7 @@ Feature: an user gets the resources shared to them
| sharee | Brian |
| shareType | user |
| permissionsRole | <permissions-role> |
When user "Brian" lists the shares shared with him after clearing user cache using the Graph API
When user "Brian" lists the shares shared with him using the Graph API
Then the HTTP status code should be "200"
And the JSON data of the response should match
"""
@@ -42,6 +42,7 @@ use TestHelpers\HttpLogger;
use TestHelpers\OcisHelper;
use TestHelpers\GraphHelper;
use TestHelpers\WebDavHelper;
use TestHelpers\SettingsHelper;
require_once 'bootstrap.php';
@@ -167,6 +168,41 @@ class FeatureContext extends BehatVariablesContext {
private array $lastHttpStatusCodesArray = [];
private array $lastOCSStatusCodesArray = [];
/**
* Store for auto-sync settings for users
*/
private array $autoSyncSettings = [];
/**
* @param string $user
*
* @return bool
*/
public function getUserAutoSyncSetting(string $user): bool {
if (\array_key_exists($user, $this->autoSyncSettings)) {
return $this->autoSyncSettings[$user];
}
$autoSyncSetting = SettingsHelper::getAutoAcceptSharesSettingValue(
$this->baseUrl,
$user,
$this->getPasswordForUser($user),
$this->getStepLineRef()
);
$this->autoSyncSettings[$user] = $autoSyncSetting;
return $autoSyncSetting;
}
/**
* @param string $user
* @param bool $value
*
* @return void
*/
public function rememberUserAutoSyncSetting(string $user, bool $value): void {
$this->autoSyncSettings[$user] = $value;
}
public const SHARES_SPACE_ID = 'a0ca6a90-a365-4782-871e-d44447bbc668$a0ca6a90-a365-4782-871e-d44447bbc668';
private bool $useSharingNG = false;
@@ -1432,15 +1468,12 @@ class FeatureContext extends BehatVariablesContext {
*
* @param ResponseInterface|null $response
*
* @return object
* @return mixed
*/
public function getJsonDecodedResponseBodyContent(ResponseInterface $response = null):?object {
public function getJsonDecodedResponseBodyContent(ResponseInterface $response = null): mixed {
$response = $response ?? $this->response;
if ($response !== null) {
$response->getBody()->rewind();
return json_decode($response->getBody()->getContents());
}
return null;
$response->getBody()->rewind();
return HttpRequestHelper::getJsonDecodedResponseBodyContent($response);
}
/**
@@ -2503,14 +2503,38 @@ class GraphContext implements Context {
}
$credentials = $this->getAdminOrUserCredentials($user);
$this->featureContext->setResponse(
GraphHelper::getSharesSharedWithMe(
// Sometimes listing shares might not return the updated shares list
// so try again until @client.synchronize is true for the max. number of retries (i.e. 10)
// and do not retry when the share is expected to be not synced
$tryAgain = false;
$retried = 0;
do {
$response = GraphHelper::getSharesSharedWithMe(
$this->featureContext->getBaseUrl(),
$this->featureContext->getStepLineRef(),
$credentials['username'],
$credentials['password']
)
);
);
$jsonBody = $this->featureContext->getJsonDecodedResponseBodyContent($response);
foreach ($jsonBody->value as $share) {
$autoSync = $this->featureContext->getUserAutoSyncSetting($credentials['username']);
$tryAgain = !$share->{'@client.synchronize'} && $autoSync && $retried < HttpRequestHelper::numRetriesOnHttpTooEarly();
if ($tryAgain) {
$retried += 1;
echo "auto-sync share for user '$user' is enabled\n";
echo "but share '$share->name' was not auto-synced, retrying ($retried)...\n";
// wait 500ms and try again
\usleep(500 * 1000);
break;
}
}
} while ($tryAgain);
$this->featureContext->setResponse($response);
$this->featureContext->pushToLastStatusCodesArrays();
}
@@ -13,6 +13,7 @@ use Behat\Gherkin\Node\PyStringNode;
use TestHelpers\EmailHelper;
use PHPUnit\Framework\Assert;
use TestHelpers\GraphHelper;
use TestHelpers\SettingsHelper;
use Behat\Gherkin\Node\TableNode;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Message\ResponseInterface;
@@ -109,7 +110,13 @@ class NotificationContext implements Context {
*/
public function listAllNotifications(string $user):ResponseInterface {
$this->setUserRecipient($user);
$headers = ["accept-language" => $this->settingsContext->getSettingLanguageValue($user)];
$language = SettingsHelper::getLanguageSettingValue(
$this->featureContext->getBaseUrl(),
$this->featureContext->getActualUsername($user),
$this->featureContext->getPasswordForUser($user),
$this->featureContext->getStepLineRef()
);
$headers = ["accept-language" => $language];
return OcsApiHelper::sendRequest(
$this->featureContext->getBaseUrl(),
$this->featureContext->getActualUsername($user),
@@ -553,7 +553,12 @@ class OCSContext implements Context {
* @throws Exception
*/
public function getOCSResponseStatusCode(ResponseInterface $response):string {
$jsonResponse = $this->featureContext->getJsonDecodedResponseBodyContent($response);
try {
$jsonResponse = $this->featureContext->getJsonDecodedResponseBodyContent($response);
} catch (JsonException $e) {
$jsonResponse = null;
}
if (\is_object($jsonResponse) && $jsonResponse->ocs->meta->statuscode) {
return (string) $jsonResponse->ocs->meta->statuscode;
}
@@ -15,6 +15,7 @@ use Behat\Behat\Hook\Scope\BeforeScenarioScope;
use PHPUnit\Framework\Assert;
use Psr\Http\Message\ResponseInterface;
use TestHelpers\HttpRequestHelper;
use TestHelpers\SettingsHelper;
use Behat\Gherkin\Node\TableNode;
require_once 'bootstrap.php';
@@ -54,14 +55,11 @@ class SettingsContext implements Context {
* @throws Exception
*/
public function getRoles(string $user): ResponseInterface {
$fullUrl = $this->baseUrl . $this->settingsUrl . "roles-list";
return HttpRequestHelper::post(
$fullUrl,
$this->featureContext->getStepLineRef(),
return SettingsHelper::getRolesList(
$this->baseUrl,
$user,
$this->featureContext->getPasswordForUser($user),
null,
"{}"
$this->featureContext->getStepLineRef()
);
}
@@ -91,15 +89,13 @@ class SettingsContext implements Context {
* @throws Exception
*/
public function assignRoleToUser(string $user, string $userId, string $roleId): ResponseInterface {
$fullUrl = $this->baseUrl . $this->settingsUrl . "assignments-add";
$body = json_encode(["account_uuid" => $userId, "role_id" => $roleId], JSON_THROW_ON_ERROR);
return HttpRequestHelper::post(
$fullUrl,
$this->featureContext->getStepLineRef(),
return SettingsHelper::assignRoleToUser(
$this->baseUrl,
$user,
$this->featureContext->getPasswordForUser($user),
null,
$body
$userId,
$roleId,
$this->featureContext->getStepLineRef(),
);
}
@@ -107,21 +103,18 @@ class SettingsContext implements Context {
* @param string $user
* @param string $userId
*
* @return void
* @return ResponseInterface
*
* @throws GuzzleException
* @throws Exception
*/
public function getAssignmentsList(string $user, string $userId): ResponseInterface {
$fullUrl = $this->baseUrl . $this->settingsUrl . "assignments-list";
$body = json_encode(["account_uuid" => $userId], JSON_THROW_ON_ERROR);
return HttpRequestHelper::post(
$fullUrl,
$this->featureContext->getStepLineRef(),
return SettingsHelper::getAssignmentsList(
$this->baseUrl,
$user,
$this->featureContext->getPasswordForUser($user),
null,
$body
$userId,
$this->featureContext->getStepLineRef(),
);
}
@@ -300,14 +293,11 @@ class SettingsContext implements Context {
* @throws Exception
*/
public function sendRequestGetBundlesList(string $user): ResponseInterface {
$fullUrl = $this->baseUrl . $this->settingsUrl . "bundles-list";
return HttpRequestHelper::post(
$fullUrl,
$this->featureContext->getStepLineRef(),
return SettingsHelper::getBundlesList(
$this->baseUrl,
$user,
$this->featureContext->getPasswordForUser($user),
null,
"{}"
$this->featureContext->getStepLineRef(),
);
}
@@ -320,21 +310,14 @@ class SettingsContext implements Context {
* @throws GuzzleException
* @throws Exception
*/
public function getBundlesList(string $user, string $bundleName): array {
$response = $this->sendRequestGetBundlesList($user);
$this->featureContext->theHTTPStatusCodeShouldBe(
201,
"Expected response status code should be 201",
$response
public function getBundleByName(string $user, string $bundleName): array {
return SettingsHelper::getBundleByName(
$this->baseUrl,
$user,
$this->featureContext->getPasswordForUser($user),
$bundleName,
$this->featureContext->getStepLineRef()
);
$body = json_decode((string)$response->getBody(), true, 512, JSON_THROW_ON_ERROR);
foreach ($body["bundles"] as $value) {
if ($value["displayName"] === $bundleName) {
return $value;
}
}
return [];
}
/**
@@ -347,15 +330,12 @@ class SettingsContext implements Context {
* @throws Exception
*/
public function sendRequestGetSettingsValuesList(string $user, array $headers = null): ResponseInterface {
$fullUrl = $this->baseUrl . $this->settingsUrl . "values-list";
$body = json_encode(["account_uuid" => "me"], JSON_THROW_ON_ERROR);
return HttpRequestHelper::post(
$fullUrl,
$this->featureContext->getStepLineRef(),
return SettingsHelper::getValuesList(
$this->baseUrl,
$user,
$this->featureContext->getPasswordForUser($user),
$headers,
$body
$this->featureContext->getStepLineRef(),
$headers
);
}
@@ -382,37 +362,6 @@ class SettingsContext implements Context {
$this->featureContext->setResponse($this->sendRequestGetSettingsValuesList($user, $headers));
}
/**
* @param string $user
*
* @return string
*
* @throws GuzzleException
* @throws Exception
*/
public function getSettingLanguageValue(string $user): string {
$response = $this->sendRequestGetSettingsValuesList($user);
$this->featureContext->theHTTPStatusCodeShouldBe(
201,
"Expected response status code should be 201",
$response
);
$body = json_decode((string)$response->getBody(), true, 512, JSON_THROW_ON_ERROR);
// if no language is set, the request body is empty return English as the default language
if (empty($body)) {
return "en";
}
foreach ($body["values"] as $value) {
if ($value["identifier"]["setting"] === "language") {
return $value["value"]["listValue"]["values"][0]["stringValue"];
}
}
// if a language setting was still not found, return English
return "en";
}
/**
* @param string $user
* @param string $language
@@ -423,7 +372,7 @@ class SettingsContext implements Context {
* @throws Exception
*/
public function sendRequestToSwitchSystemLanguage(string $user, string $language): ResponseInterface {
$profileBundlesList = $this->getBundlesList($user, "Profile");
$profileBundlesList = $this->getBundleByName($user, "Profile");
Assert::assertNotEmpty($profileBundlesList, "bundles list is empty");
$settingId = '';
@@ -435,7 +384,6 @@ class SettingsContext implements Context {
}
Assert::assertNotEmpty($settingId, "settingId is empty");
$fullUrl = $this->baseUrl . $this->settingsUrl . "values-save";
$userId = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
$body = json_encode(
[
@@ -458,13 +406,12 @@ class SettingsContext implements Context {
],
JSON_THROW_ON_ERROR
);
return HttpRequestHelper::post(
$fullUrl,
$this->featureContext->getStepLineRef(),
return SettingsHelper::updateSettings(
$this->baseUrl,
$user,
$this->featureContext->getPasswordForUser($user),
null,
$body
$body,
$this->featureContext->getStepLineRef()
);
}
@@ -497,7 +444,6 @@ class SettingsContext implements Context {
* @throws Exception
*/
public function sendRequestToDisableAutoAccepting(string $user): ResponseInterface {
$fullUrl = $this->baseUrl . $this->settingsUrl . "values-save";
$body = json_encode(
[
"value" => [
@@ -513,13 +459,12 @@ class SettingsContext implements Context {
JSON_THROW_ON_ERROR
);
return HttpRequestHelper::post(
$fullUrl,
$this->featureContext->getStepLineRef(),
return SettingsHelper::updateSettings(
$this->baseUrl,
$user,
$this->featureContext->getPasswordForUser($user),
[],
$body
$body,
$this->featureContext->getStepLineRef()
);
}
@@ -541,5 +486,6 @@ class SettingsContext implements Context {
"Expected response status code should be 201",
$response
);
$this->featureContext->rememberUserAutoSyncSetting($user, false);
}
}
@@ -1132,6 +1132,8 @@ class SharingNgContext implements Context {
);
$this->featureContext->setResponse($response);
$this->featureContext->pushToLastStatusCodesArrays();
// disable check for client.synchronize
$this->featureContext->rememberUserAutoSyncSetting($user, false);
}
/**