Json drill for coreApiCapabilities Suite (#5672)

Refactor acording to core

Signed-off-by: sagargurung1001@gmail.com <sagargurung1001@gmail.com>

Review Address

Co-authored-by: sagargurung1001@gmail.com <sagargurung1001@gmail.com>
This commit is contained in:
Sawjan Gurung
2023-02-28 15:13:36 +05:45
committed by GitHub
parent 5902679277
commit 0c4f53a03e
8 changed files with 611 additions and 171 deletions

View File

@@ -739,7 +739,7 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers
#### [Default capabilities for normal user and admin user not same as in oC-core](https://github.com/owncloud/ocis/issues/1285)
- [coreApiCapabilities/capabilities.feature:8](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiCapabilities/capabilities.feature#L8)
- [coreApiCapabilities/capabilities.feature:35](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiCapabilities/capabilities.feature#L35)
- [coreApiCapabilities/capabilities.feature:44](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiCapabilities/capabilities.feature#L44)
- [coreApiCapabilities/capabilities.feature:133](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiCapabilities/capabilities.feature#L133)
- [coreApiCapabilities/capabilities.feature:172](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiCapabilities/capabilities.feature#L172)
Note: always have an empty line at the end of this file.
The bash script that processes this file requires that the last line has a newline on the end.

View File

@@ -132,7 +132,21 @@ class AppConfigurationContext implements Context {
* @throws GuzzleException
* @throws JsonException
*/
public function userGetsCapabilities(string $username):void {
public function userRetrievesCapabilities(string $username): void {
$user = $this->featureContext->getActualUsername($username);
$this->userGetsCapabilities($user, true);
}
/**
*
* @param string $username
* @param boolean $formatJson // if true then formats the response in json
*
* @return void
* @throws GuzzleException
* @throws JsonException
*/
public function userGetsCapabilities(string $username, ?bool $formatJson = false):void {
$user = $this->featureContext->getActualUsername($username);
$password = $this->featureContext->getPasswordForUser($user);
$this->featureContext->setResponse(
@@ -141,7 +155,7 @@ class AppConfigurationContext implements Context {
$user,
$password,
'GET',
'/cloud/capabilities',
'/cloud/capabilities' . ($formatJson ? '?format=json' : ''),
$this->featureContext->getStepLineRef(),
[],
$this->featureContext->getOcsApiVersion()
@@ -214,7 +228,8 @@ class AppConfigurationContext implements Context {
* @return void
*/
public function theAdministratorGetsCapabilities():void {
$this->userGetsCapabilities($this->getAdminUsernameForCapabilitiesCheck());
$user = $this->getAdminUsernameForCapabilitiesCheck();
$this->userGetsCapabilities($user, true);
}
/**

View File

@@ -39,72 +39,6 @@ class CapabilitiesContext implements Context {
*/
private $featureContext;
/**
* @Then the capabilities should contain
*
* @param TableNode|null $formData
*
* @return void
* @throws Exception
*/
public function checkCapabilitiesResponse(TableNode $formData):void {
$capabilitiesXML = $this->featureContext->appConfigurationContext->getCapabilitiesXml(__METHOD__);
$assertedSomething = false;
$this->featureContext->verifyTableNodeColumns($formData, ['value', 'path_to_element', 'capability']);
foreach ($formData->getHash() as $row) {
$row['value'] = $this->featureContext->substituteInLineCodes($row['value']);
Assert::assertEquals(
$row['value'] === "EMPTY" ? '' : $row['value'],
$this->featureContext->appConfigurationContext->getParameterValueFromXml(
$capabilitiesXML,
$row['capability'],
$row['path_to_element']
),
"Failed field {$row['capability']} {$row['path_to_element']}"
);
$assertedSomething = true;
}
Assert::assertTrue(
$assertedSomething,
'there was nothing in the table of expected capabilities'
);
}
/**
* @Then the version data in the response should contain
*
* @param TableNode|null $formData
*
* @return void
* @throws Exception
*/
public function checkVersionResponse(TableNode $formData):void {
$versionXML = $this->featureContext->appConfigurationContext->getVersionXml(__METHOD__);
$assertedSomething = false;
$this->featureContext->verifyTableNodeColumns($formData, ['name', 'value']);
foreach ($formData->getHash() as $row) {
$row['value'] = $this->featureContext->substituteInLineCodes($row['value']);
$actualValue = $versionXML->{$row['name']};
Assert::assertEquals(
$row['value'] === "EMPTY" ? '' : $row['value'],
$actualValue,
"Failed field {$row['name']}"
);
$assertedSomething = true;
}
Assert::assertTrue(
$assertedSomething,
'there was nothing in the table of expected version data'
);
}
/**
* @Then the major-minor-micro version data in the response should match the version string
*
@@ -112,8 +46,9 @@ class CapabilitiesContext implements Context {
* @throws Exception
*/
public function checkVersionMajorMinorMicroResponse():void {
$versionXML = $this->featureContext->appConfigurationContext->getVersionXml(__METHOD__);
$versionString = (string) $versionXML->string;
$jsonResponse = $this->featureContext->getJsonDecodedResponseBodyContent();
$versionData = $jsonResponse->ocs->data->version;
$versionString = (string) $versionData->string;
// We expect that versionString will be in a format like "10.9.2 beta" or "10.9.2-alpha" or "10.9.2"
$result = \preg_match('/^[0-9]+\.[0-9]+\.[0-9]+/', $versionString, $matches);
Assert::assertSame(
@@ -126,9 +61,9 @@ class CapabilitiesContext implements Context {
$expectedMajor = $semVerParts[0];
$expectedMinor = $semVerParts[1];
$expectedMicro = $semVerParts[2];
$actualMajor = (string) $versionXML->major;
$actualMinor = (string) $versionXML->minor;
$actualMicro = (string) $versionXML->micro;
$actualMajor = (string) $versionData->major;
$actualMinor = (string) $versionData->minor;
$actualMicro = (string) $versionData->micro;
Assert::assertSame(
$expectedMajor,
$actualMajor,
@@ -175,35 +110,6 @@ class CapabilitiesContext implements Context {
);
}
/**
* @Then the capabilities should not contain
*
* @param TableNode|null $formData
*
* @return void
*/
public function theCapabilitiesShouldNotContain(TableNode $formData):void {
$capabilitiesXML = $this->featureContext->appConfigurationContext->getCapabilitiesXml(__METHOD__);
$assertedSomething = false;
foreach ($formData->getHash() as $row) {
Assert::assertFalse(
$this->featureContext->appConfigurationContext->parameterValueExistsInXml(
$capabilitiesXML,
$row['capability'],
$row['path_to_element']
),
"Capability {$row['capability']} {$row['path_to_element']} exists but it should not exist"
);
$assertedSomething = true;
}
Assert::assertTrue(
$assertedSomething,
'there was nothing in the table of not expected capabilities'
);
}
/**
* This will run before EVERY scenario.
* It will set the properties for this object.

View File

@@ -24,6 +24,7 @@
use Behat\Behat\Hook\Scope\BeforeStepScope;
use GuzzleHttp\Exception\GuzzleException;
use Helmich\JsonAssert\JsonAssertions;
use rdx\behatvars\BehatVariablesContext;
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
use Behat\Gherkin\Node\PyStringNode;
@@ -1642,6 +1643,55 @@ class FeatureContext extends BehatVariablesContext {
$this->emptyLastHTTPStatusCodesArray();
}
/**
* @param PyStringNode $schemaString
*
* @return mixed
*/
private function getJSONSchema(PyStringNode $schemaString) {
$schemaRawString = $schemaString->getRaw();
// substitute the inline codes or values
$schemaRawString = $this->substituteInLineCodes($schemaRawString);
$schema = json_decode($schemaRawString);
Assert::assertNotNull($schema, 'schema is not valid JSON');
return $schema;
}
/**
* returns json decoded body content of a json response as an object
*
* @param ResponseInterface|null $response
*
* @return object
*/
public function getJsonDecodedResponseBodyContent(ResponseInterface $response = null):?object {
$response = $response ?? $this->response;
if ($response !== null) {
$response->getBody()->rewind();
return json_decode($response->getBody()->getContents());
}
return null;
}
/**
* @Then the JSON data of the response should match
*
* @param PyStringNode $schemaString
*
* @return void
*
* @throws Exception
*/
public function theDataOfTheResponseShouldMatch(
PyStringNode $schemaString
): void {
$jsonResponse = $this->getJsonDecodedResponseBodyContent();
JsonAssertions::assertJsonDocumentMatchesSchema(
$jsonResponse->ocs->data,
$this->getJSONSchema($schemaString)
);
}
/**
* @Then /^the HTTP status code should be "([^"]*)"$/
*

View File

@@ -931,12 +931,17 @@ class OCSContext implements Context {
* @throws Exception
*/
public function getOCSResponseStatusCode(ResponseInterface $response):string {
$jsonResponse = $this->featureContext->getJsonDecodedResponseBodyContent($response);
if (\is_object($jsonResponse) && $jsonResponse->ocs->meta->statuscode) {
return (string) $jsonResponse->ocs->meta->statuscode;
}
// go to xml response when json response is null (it means not formated and get status code)
$responseXml = $this->featureContext->getResponseXml($response, __METHOD__);
if (isset($responseXml->meta[0], $responseXml->meta[0]->statuscode)) {
return (string) $responseXml->meta[0]->statuscode;
}
throw new Exception(
"No OCS status code found in responseXml"
"No OCS status code found in response"
);
}

View File

@@ -9,59 +9,289 @@ Feature: capabilities
When the administrator retrieves the capabilities using the capabilities API
Then the OCS status code should be "100"
And the HTTP status code should be "200"
And the capabilities should contain
| capability | path_to_element | value |
| files_sharing | user@@@profile_picture | 1 |
And the JSON data of the response should match
"""
{
"type": "object",
"required": [
"capabilities"
],
"properties": {
"capabilities": {
"type": "object",
"required": [
"files_sharing"
],
"properties": {
"files_sharing": {
"type": "object",
"required": [
"user"
],
"properties": {
"user": {
"type": "object",
"required": [
"profile_picture"
],
"properties": {
"profile_picture": {
"type": "boolean",
"enum": [
true
]
}
}
}
}
}
}
}
}
}
"""
@files_trashbin-app-required @skipOnReva
Scenario: getting trashbin app capability with admin user
When the administrator retrieves the capabilities using the capabilities API
Then the OCS status code should be "100"
And the HTTP status code should be "200"
And the capabilities should contain
| capability | path_to_element | value |
| files | undelete | 1 |
And the JSON data of the response should match
"""
{
"type": "object",
"required": [
"capabilities"
],
"properties": {
"capabilities": {
"type": "object",
"required": [
"files"
],
"properties": {
"files": {
"type": "object",
"required": [
"undelete"
],
"properties": {
"undelete": {
"type": "boolean",
"enum": [
true
]
}
}
}
}
}
}
}
"""
@files_versions-app-required @skipOnReva
Scenario: getting versions app capability with admin user
When the administrator retrieves the capabilities using the capabilities API
Then the OCS status code should be "100"
And the HTTP status code should be "200"
And the capabilities should contain
| capability | path_to_element | value |
| files | versioning | 1 |
And the JSON data of the response should match
"""
{
"type": "object",
"required": [
"capabilities"
],
"properties": {
"capabilities": {
"type": "object",
"required": [
"files"
],
"properties": {
"files": {
"type": "object",
"required": [
"versioning"
],
"properties": {
"versioning": {
"type": "boolean",
"enum": [
true
]
}
}
}
}
}
}
}
"""
@issue-ocis-1285
Scenario: getting default_permissions capability with admin user
When the administrator retrieves the capabilities using the capabilities API
Then the OCS status code should be "100"
And the HTTP status code should be "200"
And the capabilities should contain
| capability | path_to_element | value |
| files_sharing | default_permissions | 31 |
And the JSON data of the response should match
"""
{
"type": "object",
"required": [
"capabilities"
],
"properties": {
"capabilities": {
"type": "object",
"required": [
"files_sharing"
],
"properties": {
"files_sharing": {
"type": "object",
"required": [
"default_permissions"
],
"properties": {
"default_permissions": {
"type": "number",
"enum": [
31
]
}
}
}
}
}
}
}
"""
@issue-ocis-1285
Scenario: .htaccess is reported as a blacklisted file by default
When the administrator retrieves the capabilities using the capabilities API
Then the OCS status code should be "100"
And the HTTP status code should be "200"
And the capabilities should contain
| capability | path_to_element | value |
| files | blacklisted_files@@@element[0] | .htaccess |
And the JSON data of the response should match
"""
{
"type": "object",
"required": [
"capabilities"
],
"properties": {
"capabilities": {
"type": "object",
"required": [
"files"
],
"properties": {
"files": {
"type": "object",
"required": [
"blacklisted_files"
],
"properties": {
"blacklisted_files": {
"type": "array",
"minItems": 1,
"items": {
"type": "string",
"enum": [".htaccess"]
}
}
}
}
}
}
}
}
"""
@smokeTest
Scenario: getting default capabilities with admin user
When the administrator retrieves the capabilities using the capabilities API
Then the capabilities should contain
| capability | path_to_element | value |
| core | status@@@edition | %edition% |
| core | status@@@product | %productname% |
| core | status@@@productname | %productname% |
| core | status@@@version | %version% |
| core | status@@@versionstring | %versionstring% |
And the version data in the response should contain
| name | value |
| string | %versionstring% |
| edition | %edition% |
| product | %productname% |
And the JSON data of the response should match
"""
{
"type": "object",
"required": [
"capabilities",
"version"
],
"properties": {
"capabilities": {
"type": "object",
"required": [
"core"
],
"properties": {
"core": {
"type": "object",
"required": [
"status"
],
"properties": {
"status": {
"type": "object",
"required": [
"edition",
"product",
"productname",
"version",
"versionstring"
],
"properties": {
"edition": {
"type": "string",
"enum": ["%edition%"]
},
"product": {
"type": "string",
"enum": ["%productname%"]
},
"productname": {
"type": "string",
"enum": ["%productname%"]
},
"version": {
"type": "string",
"enum": ["%version%"]
},
"versionstring": {
"type": "string",
"enum": ["%versionstring%"]
}
}
}
}
}
}
},
"version": {
"type": "object",
"required": [
"string",
"edition",
"product"
],
"properties": {
"string": {
"type": "string",
"enum": ["%versionstring%"]
},
"edition": {
"type": "string",
"enum": ["%edition%"]
},
"product": {
"type": "string",
"enum": ["%productname%"]
}
}
}
}
}
"""
And the major-minor-micro version data in the response should match the version string

View File

@@ -12,40 +12,273 @@ Feature: default capabilities for normal user
When user "Alice" retrieves the capabilities using the capabilities API
Then the OCS status code should be "100"
And the HTTP status code should be "200"
And the capabilities should contain
| capability | path_to_element | value |
| core | pollinterval | 30000 |
| core | webdav-root | remote.php/webdav |
| core | status@@@edition | %edition% |
| core | status@@@productname | %productname% |
| core | status@@@version | %version% |
| core | status@@@versionstring | %versionstring% |
| files_sharing | api_enabled | 1 |
| files_sharing | default_permissions | 31 |
| files_sharing | search_min_length | 2 |
| files_sharing | public@@@enabled | 1 |
| files_sharing | public@@@multiple | 1 |
| files_sharing | public@@@upload | 1 |
| files_sharing | public@@@supports_upload_only | 1 |
| files_sharing | public@@@send_mail | EMPTY |
| files_sharing | public@@@social_share | 1 |
| files_sharing | public@@@enforced | EMPTY |
| files_sharing | public@@@enforced_for@@@read_only | EMPTY |
| files_sharing | public@@@enforced_for@@@read_write | EMPTY |
| files_sharing | public@@@enforced_for@@@upload_only | EMPTY |
| files_sharing | public@@@enforced_for@@@read_write_delete | EMPTY |
| files_sharing | public@@@expire_date@@@enabled | EMPTY |
| files_sharing | public@@@defaultPublicLinkShareName | Public link |
| files_sharing | resharing | 1 |
| files_sharing | federation@@@outgoing | 1 |
| files_sharing | federation@@@incoming | 1 |
| files_sharing | group_sharing | 1 |
| files_sharing | share_with_group_members_only | EMPTY |
| files_sharing | share_with_membership_groups_only | EMPTY |
| files_sharing | auto_accept_share | 1 |
| files_sharing | user_enumeration@@@enabled | 1 |
| files_sharing | user_enumeration@@@group_members_only | EMPTY |
| files_sharing | user@@@send_mail | EMPTY |
| files | bigfilechunking | 1 |
| files | privateLinks | 1 |
| files | privateLinksDetailsParam | 1 |
And the JSON data of the response should match
"""
{
"type": "object",
"required": [
"capabilities"
],
"properties": {
"capabilities": {
"type": "object",
"required": [
"core",
"files",
"files_sharing"
],
"properties": {
"core": {
"type": "object",
"required": [
"pollinterval",
"webdav-root",
"status"
],
"properties": {
"pollinterval": {
"type": "integer",
"enum": [
30000
]
},
"webdav-root": {
"type": "string",
"enum": [
"remote.php/webdav"
]
},
"status": {
"type": "object",
"required": [
"version",
"versionstring",
"edition",
"productname"
],
"properties": {
"version": {
"type": "string",
"enum": [
"%version%"
]
},
"versionstring": {
"type": "string",
"enum": [
"%versionstring%"
]
},
"edition": {
"type": "string",
"enum": [
"%edition%"
]
},
"productname": {
"type": "string",
"enum": [
"%productname%"
]
}
}
}
}
},
"files": {
"type": "object",
"required": [
"bigfilechunking",
"privateLinks",
"privateLinksDetailsParam"
],
"properties": {
"bigfilechunking": {
"type": "boolean",
"enum": [
true
]
},
"privateLinks": {
"type": "boolean",
"enum": [
true
]
},
"privateLinksDetailsParam": {
"type": "boolean",
"enum": [
true
]
}
}
},
"files_sharing": {
"type": "object",
"required": [
"api_enabled",
"default_permissions",
"search_min_length",
"public",
"resharing",
"federation",
"group_sharing",
"share_with_group_members_only",
"share_with_membership_groups_only",
"auto_accept_share",
"user_enumeration"
],
"properties": {
"api_enabled": {
"type": "boolean",
"enum": [
true
]
},
"default_permissions": {
"type": "integer",
"enum": [
31
]
},
"search_min_length": {
"type": "integer",
"enum": [
2
]
},
"public": {
"type": "object",
"required": [
"enabled",
"multiple",
"upload",
"supports_upload_only",
"send_mail",
"social_share",
"defaultPublicLinkShareName"
],
"properties": {
"enabled": {
"type": "boolean",
"enum": [
true
]
},
"multiple": {
"type": "boolean",
"enum": [
true
]
},
"upload": {
"type": "boolean",
"enum": [
true
]
},
"supports_upload_only": {
"type": "boolean",
"enum": [
true
]
},
"send_mail": {
"type": "boolean",
"enum": [
false
]
},
"social_share": {
"type": "boolean",
"enum": [
true
]
},
"defaultPublicLinkShareName": {
"type": "string",
"enum": [
"Public link"
]
}
}
},
"resharing": {
"type": "boolean",
"enum": [
true
]
},
"federation": {
"type": "object",
"required": [
"outgoing",
"incoming"
],
"properties": {
"outgoing": {
"type": "boolean",
"enum": [
true
]
},
"incoming": {
"type": "boolean",
"enum": [
true
]
}
}
},
"group_sharing": {
"type": "boolean",
"enum": [
true
]
},
"share_with_group_members_only": {
"type": "boolean",
"enum": [
false
]
},
"share_with_membership_groups_only": {
"type": "boolean",
"enum": [
false
]
},
"auto_accept_share": {
"type": "boolean",
"enum": [
true
]
},
"user_enumeration": {
"type": "object",
"required": [
"enabled",
"group_members_only"
],
"properties": {
"enabled": {
"type": "boolean",
"enum": [
true
]
},
"group_members_only": {
"type": "boolean",
"enum": [
false
]
}
}
}
}
}
}
}
}
}
"""

View File

@@ -21,6 +21,7 @@
"phpunit/phpunit": "^9.5",
"laminas/laminas-ldap": "^2.10",
"ankitpokhrel/tus-php": "^2.1",
"wapmorgan/unified-archive": "^1.1.3"
"wapmorgan/unified-archive": "^1.1.3",
"helmich/phpunit-json-assert": "^3.4"
}
}