mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-09-10 04:38:15 -04:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4636a9c696 |
No files matched your search
@@ -47,5 +47,10 @@ func addGeopointSibling(m map[string]any, dottedPath string) {
|
||||
if !hasLon || !hasLat {
|
||||
return
|
||||
}
|
||||
// corrupt EXIF: OpenSearch rejects the whole document on an out-of-range
|
||||
// geo_point, bleve would index it at the pole; both index it without one
|
||||
if lat < -90 || lat > 90 || lon < -180 || lon > 180 {
|
||||
return
|
||||
}
|
||||
parent[leaf+GeopointSuffix] = map[string]any{"lat": lat, "lon": lon}
|
||||
}
|
||||
@@ -64,6 +64,27 @@ var _ = Describe("PrepareForIndex geopoint", func() {
|
||||
Expect(gp["lon"]).To(Equal(lon))
|
||||
})
|
||||
|
||||
It("skips out-of-range geopoints but keeps the object", func() {
|
||||
type geoDoc struct {
|
||||
Location *struct {
|
||||
Longitude *float64 `json:"longitude,omitempty"`
|
||||
Latitude *float64 `json:"latitude,omitempty"`
|
||||
} `json:"location,omitempty"`
|
||||
}
|
||||
for _, c := range [][2]float64{{11.1, 100}, {11.1, -90.5}, {180.5, 49.4}, {-181, 49.4}} {
|
||||
lon, lat := c[0], c[1]
|
||||
doc := geoDoc{Location: &struct {
|
||||
Longitude *float64 `json:"longitude,omitempty"`
|
||||
Latitude *float64 `json:"latitude,omitempty"`
|
||||
}{Longitude: &lon, Latitude: &lat}}
|
||||
|
||||
m, err := PrepareForIndex(doc, map[string]FieldOpts{"location": {Type: TypeGeopoint}})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(m).To(HaveKey("location"), "lon=%v lat=%v", lon, lat)
|
||||
Expect(m).ToNot(HaveKey("location"+GeopointSuffix), "lon=%v lat=%v", lon, lat)
|
||||
}
|
||||
})
|
||||
|
||||
It("skips incomplete geopoints", func() {
|
||||
type geoDoc struct {
|
||||
Location *struct {
|
||||
|
||||
@@ -687,9 +687,11 @@ Fixtures:
|
||||
|
||||
- `some_song.mp3`, ID = 1$1!5, MimeType = audio/mpeg
|
||||
- `team.jpg`, ID = 1$1!6, MimeType = image/jpeg
|
||||
- `lost.jpg`, ID = 1$1!7, MimeType = image/jpeg
|
||||
|
||||
| Case | Query | expected | bleve | OpenSearch | same? |
|
||||
|---|---|---|---|---|---|
|
||||
| METADATA-01 | `*song*` reads `Audio` | all 16 fields unchanged | all 16 fields unchanged | all 16 fields unchanged | ✅ |
|
||||
| METADATA-02 | `*team*` reads `Location` | all 3 fields unchanged | all 3 fields unchanged | all 3 fields unchanged | ✅ |
|
||||
| METADATA-04 | `*lost*` reads `Location` | Latitude=100, Longitude=11.1 | Latitude=100, Longitude=11.1 | Latitude=100, Longitude=11.1 | ✅ |
|
||||
| METADATA-03 | `*team*` reads `Audio` | none | none | none | ✅ |
|
||||
@@ -43,6 +43,17 @@ func metadataGroup() responseGroup {
|
||||
}),
|
||||
)
|
||||
|
||||
// corrupt EXIF: latitude beyond 90 must not lose the file from the index
|
||||
lost := fixtureDoc("lost.jpg",
|
||||
withID("1$1!7"),
|
||||
withMime("image/jpeg"),
|
||||
withLocation(&libregraph.GeoCoordinates{
|
||||
Altitude: libregraph.PtrFloat64(0),
|
||||
Latitude: libregraph.PtrFloat64(100),
|
||||
Longitude: libregraph.PtrFloat64(11.1),
|
||||
}),
|
||||
)
|
||||
|
||||
indexed := []string{
|
||||
"Album=Some Album",
|
||||
"AlbumArtist=Some AlbumArtist",
|
||||
@@ -70,7 +81,7 @@ func metadataGroup() responseGroup {
|
||||
|
||||
return responseGroup{
|
||||
name: "metadata",
|
||||
fixtures: []search.Resource{song, team},
|
||||
fixtures: []search.Resource{song, team, lost},
|
||||
cases: []responseCase{
|
||||
{
|
||||
id: 1, query: `*song*`, reads: "Audio", want: unchanged(indexed),
|
||||
@@ -109,6 +120,17 @@ func metadataGroup() responseGroup {
|
||||
})
|
||||
}),
|
||||
},
|
||||
{
|
||||
id: 4, query: `*lost*`, reads: "Location", want: []string{"Latitude=100", "Longitude=11.1"},
|
||||
read: readsMany(func(m *searchMessage.Match) []string {
|
||||
location := m.GetEntity().GetLocation()
|
||||
|
||||
return []string{
|
||||
fmt.Sprintf("Latitude=%v", location.GetLatitude()),
|
||||
fmt.Sprintf("Longitude=%v", location.GetLongitude()),
|
||||
}
|
||||
}),
|
||||
},
|
||||
{
|
||||
id: 3, query: `*team*`, reads: "Audio", want: []string{"none"},
|
||||
read: reads(func(m *searchMessage.Match) string {
|
||||
|
||||
@@ -39,25 +39,16 @@ class WaitHelper {
|
||||
/**
|
||||
* Repeat $makeAttempt until $shouldStop returns true or the timeout elapses.
|
||||
*
|
||||
* @param callable $makeAttempt makes one attempt (e.g. sends a request) and returns its result
|
||||
* @param callable $shouldStop receives that result, returns true to stop polling
|
||||
* @param int|null $intervalMs pause between attempts in ms; defaults to self::INTERVAL_MS
|
||||
* @param int|null $timeoutSeconds overall time to keep polling; defaults to self::TIMEOUT_SECONDS
|
||||
* @param callable $makeAttempt makes one attempt (e.g. sends a request) and returns its result
|
||||
* @param callable $shouldStop receives that result, returns true to stop polling
|
||||
*
|
||||
* @return mixed the last result from $makeAttempt
|
||||
*/
|
||||
public static function waitUntil(
|
||||
callable $makeAttempt,
|
||||
callable $shouldStop,
|
||||
?int $intervalMs = null,
|
||||
?int $timeoutSeconds = null
|
||||
): mixed {
|
||||
$intervalMs ??= self::INTERVAL_MS;
|
||||
$timeoutSeconds ??= self::TIMEOUT_SECONDS;
|
||||
$deadline = \microtime(true) + $timeoutSeconds;
|
||||
public static function waitUntil(callable $makeAttempt, callable $shouldStop): mixed {
|
||||
$deadline = \microtime(true) + self::TIMEOUT_SECONDS;
|
||||
$result = $makeAttempt();
|
||||
while (!$shouldStop($result) && \microtime(true) < $deadline) {
|
||||
\usleep($intervalMs * 1000);
|
||||
\usleep(self::INTERVAL_MS * 1000);
|
||||
$result = $makeAttempt();
|
||||
}
|
||||
return $result;
|
||||
|
||||
@@ -150,7 +150,7 @@ class SearchContext implements Context {
|
||||
): void {
|
||||
// NOTE: because indexing of newly uploaded files or directories with OpenCloud is decoupled and occurs asynchronously
|
||||
// short wait is necessary before searching
|
||||
sleep(2);
|
||||
sleep(10);
|
||||
// remember the query so "should eventually contain" steps can re-search
|
||||
$this->lastSearchQuery = [
|
||||
"user" => $user,
|
||||
@@ -176,25 +176,6 @@ class SearchContext implements Context {
|
||||
string $path,
|
||||
string $user,
|
||||
TableNode $properties
|
||||
): void {
|
||||
$assert = fn () => $this->assertFileOrFolderInSearchResultContainsProperties($path, $user, $properties);
|
||||
$this->retrySearchUntilSatisfied($assert);
|
||||
$assert();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $user
|
||||
* @param TableNode $properties
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function assertFileOrFolderInSearchResultContainsProperties(
|
||||
string $path,
|
||||
string $user,
|
||||
TableNode $properties
|
||||
): void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$this->featureContext->verifyTableNodeColumns($properties, ['name', 'value']);
|
||||
@@ -253,7 +234,8 @@ class SearchContext implements Context {
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function assertSearchResultContainsEntriesWithHighlight(
|
||||
#[Then('/^the search result should contain these (?:files|entries) with highlight on keyword "([^"]*)"/')]
|
||||
public function theSearchResultShouldContainEntriesWithHighlight(
|
||||
TableNode $expectedFiles,
|
||||
string $expectedContent
|
||||
): void {
|
||||
@@ -302,15 +284,8 @@ class SearchContext implements Context {
|
||||
): void {
|
||||
// NOTE: since indexing of newly uploaded files or directories with OpenCloud is decoupled and occurs asynchronously,
|
||||
// a short wait is necessary before searching
|
||||
sleep(2);
|
||||
$this->lastSearchQuery = [
|
||||
"user" => $user,
|
||||
"pattern" => $pattern,
|
||||
"scopeType" => $scopeType,
|
||||
"scope" => $scope,
|
||||
"spaceName" => $spaceName,
|
||||
];
|
||||
$response = $this->searchFiles($user, $pattern, null, $scopeType, $scope, $spaceName);
|
||||
sleep(5);
|
||||
$response = $this-> searchFiles($user, $pattern, null, $scopeType, $scope, $spaceName);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
@@ -325,7 +300,7 @@ class SearchContext implements Context {
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function retrySearchUntilSatisfied(callable $assert): void {
|
||||
private function retrySearchUntilSatisfied(callable $assert): void {
|
||||
Assert::assertNotEmpty(
|
||||
$this->lastSearchQuery,
|
||||
'No search to retry. Use a "searches for ... using the WebDAV API" step first.'
|
||||
@@ -335,67 +310,33 @@ class SearchContext implements Context {
|
||||
fn () => $this->searchFiles(
|
||||
$query["user"],
|
||||
$query["pattern"],
|
||||
$query["limit"] ?? null,
|
||||
$query["scopeType"] ?? null,
|
||||
$query["scope"] ?? null,
|
||||
$query["spaceName"] ?? null,
|
||||
$query["properties"] ?? null
|
||||
$query["limit"],
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$query["properties"]
|
||||
),
|
||||
function ($response) use ($assert) {
|
||||
$this->featureContext->setResponse($response);
|
||||
try {
|
||||
$assert();
|
||||
return true;
|
||||
} catch (\Throwable) {
|
||||
} catch (\Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
2000,
|
||||
20
|
||||
}
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $numFiles
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[Then('the search result should contain :numFiles files/entries')]
|
||||
public function theSearchResultShouldContainNumEntries(int $numFiles): void {
|
||||
$assert = fn () => $this->featureContext->checkIFResponseContainsNumberEntries($numFiles);
|
||||
$this->retrySearchUntilSatisfied($assert);
|
||||
$assert();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $user
|
||||
* @param int $expectedNumber
|
||||
* @param TableNode $expectedFiles
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[Then('the search result of user :user should contain any :expectedNumber of these files/entries:')]
|
||||
public function theSearchResultShouldContainAnyOfTheseEntries(
|
||||
string $user,
|
||||
int $expectedNumber,
|
||||
TableNode $expectedFiles
|
||||
): void {
|
||||
$assert = fn () => $this->featureContext->checkIfSearchResultContainsFiles($user, $expectedNumber, $expectedFiles);
|
||||
$this->retrySearchUntilSatisfied($assert);
|
||||
$assert();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param TableNode $expectedFiles
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[Then('/^the search result of user "([^"]*)" should contain only these (?:files|entries):$/')]
|
||||
public function theSearchResultShouldContainOnlyEntries(string $user, TableNode $expectedFiles): void {
|
||||
#[Then('/^the search result of user "([^"]*)" should eventually contain only these (?:files|entries):$/')]
|
||||
public function theSearchResultShouldEventuallyContainOnlyEntries(string $user, TableNode $expectedFiles): void {
|
||||
$assert = fn () => $this->featureContext->thePropfindResultShouldContainOnlyEntries($user, $expectedFiles);
|
||||
$this->retrySearchUntilSatisfied($assert);
|
||||
$assert();
|
||||
@@ -407,31 +348,9 @@ class SearchContext implements Context {
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[Then('/^the search result of user "([^"]*)" should contain these (?:files|entries):$/')]
|
||||
public function theSearchResultShouldContainEntries(string $user, TableNode $expectedFiles): void {
|
||||
$this->assertSearchResultContainsEntries($user, "", $expectedFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param TableNode $expectedFiles
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[Then('/^the search result of user "([^"]*)" should not contain these (?:files|entries):$/')]
|
||||
public function theSearchResultShouldNotContainEntries(string $user, TableNode $expectedFiles): void {
|
||||
$this->assertSearchResultContainsEntries($user, "not", $expectedFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $shouldOrNot (not|)
|
||||
* @param TableNode $expectedFiles
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function assertSearchResultContainsEntries(string $user, string $shouldOrNot, TableNode $expectedFiles): void {
|
||||
$assert = fn () => $this->featureContext->thePropfindResultShouldContainEntries($user, $shouldOrNot, $expectedFiles);
|
||||
#[Then('/^the search result of user "([^"]*)" should eventually contain these (?:files|entries):$/')]
|
||||
public function theSearchResultShouldEventuallyContainEntries(string $user, TableNode $expectedFiles): void {
|
||||
$assert = fn () => $this->featureContext->thePropfindResultShouldContainEntries($user, '', $expectedFiles);
|
||||
$this->retrySearchUntilSatisfied($assert);
|
||||
$assert();
|
||||
}
|
||||
@@ -442,12 +361,9 @@ class SearchContext implements Context {
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[Then('/^the search result should contain these (?:files|entries) with highlight on keyword "([^"]*)"$/')]
|
||||
public function theSearchResultShouldContainEntriesWithHighlight(
|
||||
TableNode $expectedFiles,
|
||||
string $expectedContent
|
||||
): void {
|
||||
$assert = fn () => $this->assertSearchResultContainsEntriesWithHighlight($expectedFiles, $expectedContent);
|
||||
#[Then('/^the search result should eventually contain these (?:files|entries) with highlight on keyword "([^"]*)"$/')]
|
||||
public function theSearchResultShouldEventuallyContainEntriesWithHighlight(TableNode $expectedFiles, string $expectedContent): void {
|
||||
$assert = fn () => $this->theSearchResultShouldContainEntriesWithHighlight($expectedFiles, $expectedContent);
|
||||
$this->retrySearchUntilSatisfied($assert);
|
||||
$assert();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ class SpacesContext implements Context {
|
||||
private ChecksumContext $checksumContext;
|
||||
private FilesVersionsContext $filesVersionsContext;
|
||||
private ArchiverContext $archiverContext;
|
||||
private SearchContext $searchContext;
|
||||
|
||||
/**
|
||||
* key is space name and value is the username that created the space
|
||||
@@ -513,7 +512,6 @@ class SpacesContext implements Context {
|
||||
$this->checksumContext = BehatHelper::getContext($scope, $environment, 'ChecksumContext');
|
||||
$this->filesVersionsContext = BehatHelper::getContext($scope, $environment, 'FilesVersionsContext');
|
||||
$this->archiverContext = BehatHelper::getContext($scope, $environment, 'ArchiverContext');
|
||||
$this->searchContext = BehatHelper::getContext($scope, $environment, 'SearchContext');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3927,47 +3925,41 @@ class SpacesContext implements Context {
|
||||
*/
|
||||
#[Then('for user :user the search result should contain space :spaceName')]
|
||||
public function searchResultShouldContainSpace(string $user, string $spaceName): void {
|
||||
// searching a space by name goes through the asynchronous file index, so
|
||||
// re-run the search until the space shows up (or the timeout elapses).
|
||||
$assert = function () use ($user, $spaceName): void {
|
||||
$responseArray = json_decode(
|
||||
json_encode(
|
||||
HttpRequestHelper::getResponseXml($this->featureContext->getResponse())->xpath("//d:response/d:href")
|
||||
),
|
||||
true,
|
||||
512,
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
Assert::assertNotEmpty($responseArray, "search result is empty");
|
||||
$responseArray = json_decode(
|
||||
json_encode(
|
||||
HttpRequestHelper::getResponseXml($this->featureContext->getResponse())->xpath("//d:response/d:href")
|
||||
),
|
||||
true,
|
||||
512,
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
Assert::assertNotEmpty($responseArray, "search result is empty");
|
||||
|
||||
// for mountpoint, id looks a little different than for project space
|
||||
if (str_contains($spaceName, 'mountpoint')) {
|
||||
$splitSpaceName = explode("/", $spaceName);
|
||||
$space = $this->getSpaceByName($user, $splitSpaceName[1]);
|
||||
$splitSpaceId = explode("$", $space['id']);
|
||||
$spaceId = str_replace('!', '%21', $splitSpaceId[1]);
|
||||
} else {
|
||||
$space = $this->getSpaceByName($user, $spaceName);
|
||||
$spaceId = $space['id'];
|
||||
}
|
||||
$suffixPath = $user;
|
||||
$davPathVersion = $this->featureContext->getDavPathVersion();
|
||||
if ($davPathVersion === WebDavHelper::DAV_VERSION_SPACES) {
|
||||
$suffixPath = $spaceId;
|
||||
}
|
||||
// for mountpoint, id looks a little different than for project space
|
||||
if (str_contains($spaceName, 'mountpoint')) {
|
||||
$splitSpaceName = explode("/", $spaceName);
|
||||
$space = $this->getSpaceByName($user, $splitSpaceName[1]);
|
||||
$splitSpaceId = explode("$", $space['id']);
|
||||
$spaceId = str_replace('!', '%21', $splitSpaceId[1]);
|
||||
} else {
|
||||
$space = $this->getSpaceByName($user, $spaceName);
|
||||
$spaceId = $space['id'];
|
||||
}
|
||||
$suffixPath = $user;
|
||||
$davPathVersion = $this->featureContext->getDavPathVersion();
|
||||
if ($davPathVersion === WebDavHelper::DAV_VERSION_SPACES) {
|
||||
$suffixPath = $spaceId;
|
||||
}
|
||||
|
||||
$topWebDavPath = "/" . WebDavHelper::getDavPath($davPathVersion, $suffixPath);
|
||||
$topWebDavPath = "/" . WebDavHelper::getDavPath($davPathVersion, $suffixPath);
|
||||
|
||||
$spaceFound = false;
|
||||
foreach ($responseArray as $value) {
|
||||
if ($topWebDavPath === $value[0]) {
|
||||
$spaceFound = true;
|
||||
}
|
||||
$spaceFound = false;
|
||||
foreach ($responseArray as $value) {
|
||||
if ($topWebDavPath === $value[0]) {
|
||||
$spaceFound = true;
|
||||
}
|
||||
Assert::assertTrue($spaceFound, "response does not contain the space '$spaceName'");
|
||||
};
|
||||
$this->searchContext->retrySearchUntilSatisfied($assert);
|
||||
$assert();
|
||||
}
|
||||
Assert::assertTrue($spaceFound, "response does not contain the space '$spaceName'");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,7 +25,6 @@ use Behat\Gherkin\Node\TableNode;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TestHelpers\GraphHelper;
|
||||
use TestHelpers\WaitHelper;
|
||||
use TestHelpers\BehatHelper;
|
||||
use Behat\Step\Given;
|
||||
use Behat\Step\Then;
|
||||
@@ -39,7 +38,6 @@ require_once 'bootstrap.php';
|
||||
class TagContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
private SpacesContext $spacesContext;
|
||||
private array $lastTagsQuery = [];
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
@@ -177,79 +175,19 @@ class TagContext implements Context {
|
||||
*/
|
||||
#[When('user :user lists all available tag(s) via the Graph API')]
|
||||
public function theUserGetsAllAvailableTags(string $user): void {
|
||||
// Note: after creating or deleting tags, in some cases tags do not appear or disappear immediately
|
||||
sleep(2);
|
||||
$this->lastTagsQuery = ["user" => $user];
|
||||
$this->featureContext->setResponse($this->fetchTags($user));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws Exception
|
||||
*/
|
||||
private function fetchTags(string $user): ResponseInterface {
|
||||
return GraphHelper::getTags(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$this->featureContext->getStepLineRef()
|
||||
// Note: after creating or deleting tags, in some cases tags do not appear or disappear immediately,
|
||||
// So wait is necessary before listing tags
|
||||
sleep(5);
|
||||
$this->featureContext->setResponse(
|
||||
GraphHelper::getTags(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$this->featureContext->getStepLineRef()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* re-run the last tag listing until the assertion passes or the WaitHelper
|
||||
*
|
||||
* @param callable $assert
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function retryTagsUntilSatisfied(callable $assert): void {
|
||||
Assert::assertNotEmpty(
|
||||
$this->lastTagsQuery,
|
||||
'No tag listing to retry. Use a "lists all available tags via the Graph API" step first.'
|
||||
);
|
||||
$query = $this->lastTagsQuery;
|
||||
$response = WaitHelper::waitUntil(
|
||||
fn () => $this->fetchTags($query["user"]),
|
||||
function ($response) use ($assert) {
|
||||
$this->featureContext->setResponse($response);
|
||||
try {
|
||||
$assert();
|
||||
return true;
|
||||
} catch (\Throwable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
#[Then('/^the response should contain following tags:$/')]
|
||||
public function theResponseShouldContainFollowingTags(TableNode $table): void {
|
||||
$this->assertResponseContainsFollowingTags("", $table);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
#[Then('/^the response should not contain following tags:$/')]
|
||||
public function theResponseShouldNotContainFollowingTags(TableNode $table): void {
|
||||
$this->assertResponseContainsFollowingTags("not", $table);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $shouldOrNot (not|)
|
||||
@@ -258,29 +196,27 @@ class TagContext implements Context {
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function assertResponseContainsFollowingTags(string $shouldOrNot, TableNode $table): void {
|
||||
$assert = function () use ($shouldOrNot, $table): void {
|
||||
#[Then('/^the response should (not|)\\s?contain following tag(s):$/')]
|
||||
public function theFollowingTagsShouldExistForUser(string $shouldOrNot, TableNode $table): void {
|
||||
$rows = $table->getRows();
|
||||
foreach ($rows as $row) {
|
||||
$responseArray = $this->featureContext->getJsonDecodedResponse(
|
||||
$this->featureContext->getResponse()
|
||||
)['value'];
|
||||
foreach ($table->getRows() as $row) {
|
||||
if ($shouldOrNot === "not") {
|
||||
Assert::assertFalse(
|
||||
\in_array($row[0], $responseArray),
|
||||
"the response should not contain the tag $row[0].\nResponse\n"
|
||||
. print_r($responseArray, true)
|
||||
);
|
||||
} else {
|
||||
Assert::assertTrue(
|
||||
\in_array($row[0], $responseArray),
|
||||
"the response does not contain the tag $row[0].\nResponse\n"
|
||||
. print_r($responseArray, true)
|
||||
);
|
||||
}
|
||||
if ($shouldOrNot === "not") {
|
||||
Assert::assertFalse(
|
||||
\in_array($row[0], $responseArray),
|
||||
"the response should not contain the tag $row[0].\nResponse\n"
|
||||
. print_r($responseArray, true)
|
||||
);
|
||||
} else {
|
||||
Assert::assertTrue(
|
||||
\in_array($row[0], $responseArray),
|
||||
"the response does not contain the tag $row[0].\nResponse\n"
|
||||
. print_r($responseArray, true)
|
||||
);
|
||||
}
|
||||
};
|
||||
$this->retryTagsUntilSatisfied($assert);
|
||||
$assert();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4014,7 +4014,7 @@ trait WebDav {
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
#[Then('/^the propfind result of user "([^"]*)" should (not|)\\s?contain these (?:files|entries):$/')]
|
||||
#[Then('/^the (?:propfind|search) result of user "([^"]*)" should (not|)\\s?contain these (?:files|entries):$/')]
|
||||
public function thePropfindResultShouldContainEntries(
|
||||
string $user,
|
||||
string $shouldOrNot,
|
||||
@@ -4036,7 +4036,7 @@ trait WebDav {
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
#[Then('/^the propfind result of user "([^"]*)" should contain only these (?:files|entries):$/')]
|
||||
#[Then('/^the (?:propfind|search) result of user "([^"]*)" should contain only these (?:files|entries):$/')]
|
||||
public function thePropfindResultShouldContainOnlyEntries(
|
||||
string $user,
|
||||
TableNode $expectedFiles
|
||||
@@ -4063,7 +4063,7 @@ trait WebDav {
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[Then('the propfind result should contain :numFiles files/entries')]
|
||||
#[Then('the propfind/search result should contain :numFiles files/entries')]
|
||||
public function propfindResultShouldContainNumEntries(int $numFiles): void {
|
||||
$this->checkIFResponseContainsNumberEntries($numFiles);
|
||||
}
|
||||
@@ -4110,7 +4110,7 @@ trait WebDav {
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
#[Then('the propfind result of user :user should contain any :expectedNumber of these files/entries:')]
|
||||
#[Then('the propfind/search result of user :user should contain any :expectedNumber of these files/entries:')]
|
||||
public function theSearchResultOfUserShouldContainAnyOfTheseEntries(
|
||||
string $user,
|
||||
int $expectedNumber,
|
||||
|
||||
@@ -186,6 +186,15 @@
|
||||
|
||||
- [apiServiceAvailability/serviceAvailabilityCheck.feature:123](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiServiceAvailability/serviceAvailabilityCheck.feature#L123)
|
||||
|
||||
#### [Missing properties in REPORT response](https://github.com/owncloud/ocis/issues/9780), [d:getetag property has empty value in REPORT response](https://github.com/owncloud/ocis/issues/9783)
|
||||
|
||||
- [apiSearch1/search.feature:437](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L437)
|
||||
- [apiSearch1/search.feature:438](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L438)
|
||||
- [apiSearch1/search.feature:439](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L439)
|
||||
- [apiSearch1/search.feature:465](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L465)
|
||||
- [apiSearch1/search.feature:466](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L466)
|
||||
- [apiSearch1/search.feature:467](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L467)
|
||||
|
||||
## Scenarios from core API tests that are expected to fail with decomposed storage
|
||||
|
||||
### File
|
||||
|
||||
@@ -186,6 +186,15 @@
|
||||
|
||||
- [apiServiceAvailability/serviceAvailabilityCheck.feature:123](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiServiceAvailability/serviceAvailabilityCheck.feature#L123)
|
||||
|
||||
#### [Missing properties in REPORT response](https://github.com/owncloud/ocis/issues/9780), [d:getetag property has empty value in REPORT response](https://github.com/owncloud/ocis/issues/9783)
|
||||
|
||||
- [apiSearch1/search.feature:437](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L437)
|
||||
- [apiSearch1/search.feature:438](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L438)
|
||||
- [apiSearch1/search.feature:439](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L439)
|
||||
- [apiSearch1/search.feature:465](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L465)
|
||||
- [apiSearch1/search.feature:466](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L466)
|
||||
- [apiSearch1/search.feature:467](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L467)
|
||||
|
||||
## Scenarios from core API tests that are expected to fail with posix storage
|
||||
|
||||
### File
|
||||
|
||||
@@ -409,7 +409,7 @@ Feature: Search
|
||||
| new |
|
||||
| spaces |
|
||||
|
||||
@skip @issue-3501 @issue-9780
|
||||
@issue-4712 @issue-9780 @issue-9781 @issue-9783 @issue-10329
|
||||
Scenario Outline: report extra properties in search entries for a file
|
||||
Given using <dav-path-version> DAV path
|
||||
When user "Alice" searches for "*insideTheFo*" using the WebDAV API requesting these properties:
|
||||
@@ -438,7 +438,7 @@ Feature: Search
|
||||
| new |
|
||||
| spaces |
|
||||
|
||||
@skip @issue-3501 @issue-9780
|
||||
@issue-4712 @issue-9780 @issue-9781 @issue-9783 @issue-10329
|
||||
Scenario Outline: report extra properties in search entries for a folder
|
||||
Given using <dav-path-version> DAV path
|
||||
When user "Alice" searches for "*folderMain*" using the WebDAV API requesting these properties:
|
||||
|
||||
@@ -16,7 +16,7 @@ Feature: content search
|
||||
And user "Alice" has uploaded file with content "namaste from nepal" to "hello.txt"
|
||||
When user "Alice" searches for "Content:hello" using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Alice" should contain only these files:
|
||||
And the search result of user "Alice" should eventually contain only these files:
|
||||
| keywordAtStart.txt |
|
||||
| keywordAtMiddle.txt |
|
||||
| keywordAtLast.txt |
|
||||
@@ -34,15 +34,15 @@ Feature: content search
|
||||
And user "Alice" has uploaded file with content "alan@example.org want to say hello" to "findByEmail.docs"
|
||||
When user "Alice" searches for "Content:k6" using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Alice" should contain only these files:
|
||||
And the search result of user "Alice" should eventually contain only these files:
|
||||
| wordWithNumber.md |
|
||||
When user "Alice" searches for "Content:https://opencloud.eu/" using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Alice" should contain only these files:
|
||||
And the search result of user "Alice" should eventually contain only these files:
|
||||
| findByWebSite.txt |
|
||||
When user "Alice" searches for "Content:alan@" using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Alice" should contain only these files:
|
||||
And the search result of user "Alice" should eventually contain only these files:
|
||||
| findByEmail.docs |
|
||||
Examples:
|
||||
| dav-path-version |
|
||||
@@ -71,11 +71,11 @@ Feature: content search
|
||||
And user "Alice" has uploaded file with content "He has expirience, we must to have, I have to find ...." to "fileWithStopWords.txt"
|
||||
When user "Alice" searches for 'Content:"he has"' using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Alice" should contain only these files:
|
||||
And the search result of user "Alice" should eventually contain only these files:
|
||||
| fileWithStopWords.txt |
|
||||
When user "Alice" searches for 'Content:"I have"' using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Alice" should contain only these files:
|
||||
And the search result of user "Alice" should eventually contain only these files:
|
||||
| fileWithStopWords.txt |
|
||||
Examples:
|
||||
| dav-path-version |
|
||||
@@ -101,7 +101,7 @@ Feature: content search
|
||||
And user "Brian" has a share "uploadFolder" synced
|
||||
When user "Brian" searches for "Content:hello" using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Brian" should contain only these files:
|
||||
And the search result of user "Brian" should eventually contain only these files:
|
||||
| keywordAtStart.txt |
|
||||
| keywordAtMiddle.txt |
|
||||
| keywordAtLast.txt |
|
||||
@@ -121,7 +121,7 @@ Feature: content search
|
||||
And user "Alice" has deleted file "keywordAtLast.txt"
|
||||
When user "Alice" searches for "Content:hello" using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Alice" should contain only these files:
|
||||
And the search result of user "Alice" should eventually contain only these files:
|
||||
| keywordAtStart.txt |
|
||||
| keywordAtMiddle.txt |
|
||||
Examples:
|
||||
@@ -139,7 +139,7 @@ Feature: content search
|
||||
And user "Alice" has restored the file with original path "keywordAtStart.txt"
|
||||
When user "Alice" searches for "Content:hello" using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Alice" should contain only these files:
|
||||
And the search result of user "Alice" should eventually contain only these files:
|
||||
| keywordAtStart.txt |
|
||||
Examples:
|
||||
| dav-path-version |
|
||||
@@ -154,7 +154,7 @@ Feature: content search
|
||||
And user "Alice" has restored version index "1" of file "test.txt"
|
||||
When user "Alice" searches for "Content:hello" using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Alice" should contain only these files:
|
||||
And the search result of user "Alice" should eventually contain only these files:
|
||||
| test.txt |
|
||||
Examples:
|
||||
| dav-path-version |
|
||||
@@ -175,7 +175,7 @@ Feature: content search
|
||||
And using <dav-path-version> DAV path
|
||||
When user "Alice" searches for "Content:hello" using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Alice" should contain only these files:
|
||||
And the search result of user "Alice" should eventually contain only these files:
|
||||
| keywordAtStart.txt |
|
||||
| keywordAtMiddle.txt |
|
||||
| keywordAtLast.txt |
|
||||
@@ -204,7 +204,7 @@ Feature: content search
|
||||
And using <dav-path-version> DAV path
|
||||
When user "Brian" searches for "Content:hello" using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Alice" should contain only these files:
|
||||
And the search result of user "Alice" should eventually contain only these files:
|
||||
| keywordAtStart.txt |
|
||||
| keywordAtMiddle.txt |
|
||||
| keywordAtLast.txt |
|
||||
@@ -224,7 +224,7 @@ Feature: content search
|
||||
| technical task.txt | test |
|
||||
When user "Alice" searches for '<pattern>' using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result of user "Alice" should contain these entries:
|
||||
And the search result of user "Alice" should eventually contain these entries:
|
||||
| <search-result-1> |
|
||||
| <search-result-2> |
|
||||
And the search result should contain "<result-count>" entries
|
||||
@@ -251,7 +251,7 @@ Feature: content search
|
||||
And user "Alice" has uploaded a file inside space "project-space" with content "this is a simple odt file" to "test-odt-file.odt"
|
||||
When user "Alice" searches for "Content:simple" using the WebDAV API
|
||||
Then the HTTP status code should be "207"
|
||||
And the search result should contain these entries with highlight on keyword "simple"
|
||||
And the search result should eventually contain these entries with highlight on keyword "simple"
|
||||
| test-text-file.txt |
|
||||
| test-pdf-file.pdf |
|
||||
| test-cpp-file.cpp |
|
||||
|
||||
Reference in new issue
Block a user