diff --git a/tests/e2e/cucumber/features/integrations/search.feature b/tests/e2e/cucumber/features/integrations/search.feature new file mode 100644 index 00000000000..a099809e64e --- /dev/null +++ b/tests/e2e/cucumber/features/integrations/search.feature @@ -0,0 +1,93 @@ +Feature: Search + As a user + I want to search for resources + So that I can find them quickly + + Background: + Given "Admin" sets the default folder for received shares to "Shares" + And "Admin" disables share auto accepting + + Scenario: Search in personal spaces + Given "Admin" creates following users + | id | + | Alice | + | Brian | + When "Brian" logs in + And "Brian" opens the "files" app + And "Brian" creates the following resources + | resource | type | + | folder_from_brian | folder | + And "Brian" uploads the following resources + | resource | + | new-lorem-big.txt | + And "Brian" shares the following resource using the sidebar panel + | resource | recipient | type | role | + | folder_from_brian | Alice | user | viewer | + | new-lorem-big.txt | Alice | user | viewer | + And "Brian" logs out + When "Alice" logs in + And "Alice" navigates to the shared with me page + And "Alice" accepts the following share + | name | + | folder_from_brian | + | new-lorem-big.txt | + And "Alice" opens the "files" app + And "Alice" creates the following resources + | resource | type | + | folder | folder | + | FolDer | folder | + | PARENT/child | folder | + | PARENT/child-one | folder | + | PARENT/child-one/child-two | folder | + And "Alice" enables the option to display the hidden file + And "Alice" uploads the following resources + | resource | + | new-lorem.txt | + | .hidden-file.txt | + And "Alice" searches "new" using the global search + Then following resources should be displayed in the search list for user "Alice" + | resource | + | new-lorem.txt | +# enable these steps after issue https://github.com/owncloud/web/issues/7629 is fixed + # | new-lorem-big.txt | + But following resources should not be displayed in the search list for user "Alice" + | resource | + | PARENT | + | folder_from_brian | + | .hidden-file.txt | + When "Alice" searches "foldeR" using the global search + Then following resources should be displayed in the search list for user "Alice" + | resource | + | folder | + | FolDer | + # enable these steps after issue https://github.com/owncloud/web/issues/7629 is fixed + # | folder_from_brian | + But following resources should not be displayed in the search list for user "Alice" + | resource | + | new-lorem.txt | + | new-lorem-big.txt | + | .hidden-file.txt | + When "Alice" searches "hidden" using the global search + Then following resources should be displayed in the search list for user "Alice" + | resource | + | .hidden-file.txt | + But following resources should not be displayed in the search list for user "Alice" + | resource | + | folder | + | FolDer | + | PARENT | + | folder_from_brian | + | new-lorem.txt | + | new-lorem-big.txt | + When "Alice" opens folder "PARENT" + And "Alice" searches "child" using the global search + Then following resources should be displayed in the search list for user "Alice" + | resource | + | child | + | child-one | + When "Alice" opens folder "child-one" + And "Alice" searches "child" using the global search + Then following resources should be displayed in the search list for user "Alice" + | resource | + | child-two | + And "Alice" logs out diff --git a/tests/e2e/cucumber/features/integrations/share.oc10.feature b/tests/e2e/cucumber/features/integrations/share.oc10.feature index d51d3279d83..0fcba22723e 100644 --- a/tests/e2e/cucumber/features/integrations/share.oc10.feature +++ b/tests/e2e/cucumber/features/integrations/share.oc10.feature @@ -1,7 +1,7 @@ Feature: share Background: - And "admin" sets the default folder for received shares to "Shares" + Given "admin" sets the default folder for received shares to "Shares" And "Admin" disables share auto accepting Scenario: folder diff --git a/tests/e2e/cucumber/steps/app-files/resource.ts b/tests/e2e/cucumber/steps/app-files/resource.ts index 3d7c8b258e1..e8255c6bdaf 100644 --- a/tests/e2e/cucumber/steps/app-files/resource.ts +++ b/tests/e2e/cucumber/steps/app-files/resource.ts @@ -207,6 +207,51 @@ Then( } } ) +When( + '{string} searches {string} using the global search', + async function (this: World, stepUser: string, keyword: string): Promise { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const resourceObject = new objects.applicationFiles.Resource({ page }) + await resourceObject.searchResource({ keyword }) + } +) + +Then( + /^following resources (should|should not) be displayed in the search list for user "([^"]*)"?$/, + async function ( + this: World, + actionType: string, + stepUser: string, + stepTable: DataTable + ): Promise { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const resourceObject = new objects.applicationFiles.Resource({ page }) + const actualList = await resourceObject.getDisplayedResources() + for (const info of stepTable.hashes()) { + const found = actualList.includes(info.resource) + if (actionType === 'should') expect(found).toBe(true) + else expect(found).toBe(false) + } + } +) + +When( + '{string} opens folder {string}', + async function (this: World, stepUser: string, resource: string): Promise { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const resourceObject = new objects.applicationFiles.Resource({ page }) + await resourceObject.openFolder(resource) + } +) + +When( + '{string} enables the option to display the hidden file', + async function (this: World, stepUser: string): Promise { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const resourceObject = new objects.applicationFiles.Resource({ page }) + await resourceObject.showHiddenFiles() + } +) export const processDownload = async ( stepTable: DataTable, diff --git a/tests/e2e/filesForUpload/.hidden-file.txt b/tests/e2e/filesForUpload/.hidden-file.txt new file mode 100644 index 00000000000..a99de05b077 --- /dev/null +++ b/tests/e2e/filesForUpload/.hidden-file.txt @@ -0,0 +1 @@ +this is a hidden file diff --git a/tests/e2e/support/objects/app-files/resource/actions.ts b/tests/e2e/support/objects/app-files/resource/actions.ts index b9d565ec386..1cf8eebe19e 100644 --- a/tests/e2e/support/objects/app-files/resource/actions.ts +++ b/tests/e2e/support/objects/app-files/resource/actions.ts @@ -1,4 +1,5 @@ import { Download, Page } from 'playwright' +import { expect } from '@playwright/test' import util from 'util' import { resourceExists, waitForResources } from './utils' import path from 'path' @@ -29,6 +30,13 @@ const emptyTrashBinButton = '.oc-files-actions-empty-trash-bin-trigger' const notificationMessageDialog = '.oc-notification-message-title' const permanentDeleteButton = '.oc-files-actions-delete-permanent-trigger' const restoreResourceButton = '.oc-files-actions-restore-trigger' +const globalSearchInput = '.oc-search-input' +const searchList = + '//div[@id="files-global-search-options"]//li[contains(@class,"preview")]//span[@class="oc-resource-name"]' +const globalSearchOptions = '#files-global-search-options' +const loadingSpinner = '#files-global-search-bar .oc-spinner' +const filesViewOptionButton = '#files-view-options-btn' +const hiddenFilesToggleButton = '//*[@data-testid="files-switch-hidden-files"]//button' export const clickResource = async ({ page, @@ -370,12 +378,7 @@ export const emptyTrashBinResources = async (page): Promise => { return message.trim().toLowerCase() } -export interface deleteResourceTrashbinArgs { - resource: string - page: Page -} - -export const deleteResourceTrashbin = async (args: deleteResourceTrashbinArgs): Promise => { +export const deleteResourceTrashbin = async (args: deleteResourceArgs): Promise => { const { page, resource } = args const resourceCheckbox = page.locator(util.format(checkBoxForTrashbin, resource)) if (!(await resourceCheckbox.isChecked())) { @@ -418,3 +421,28 @@ export const restoreResourceTrashbin = async ( const message = await page.locator(notificationMessageDialog).textContent() return message.trim().toLowerCase() } + +export interface searchResourceGlobalSearchArgs { + keyword: string + page: Page +} + +export const searchResourceGlobalSearch = async ( + args: searchResourceGlobalSearchArgs +): Promise => { + const { page, keyword } = args + await page.locator(globalSearchInput).fill(keyword) + await expect(page.locator(globalSearchOptions)).toBeVisible() + await expect(page.locator(loadingSpinner)).not.toBeVisible() +} + +export const getDisplayedResourcesFromSearch = async (page): Promise => { + const result = await page.locator(searchList).allInnerTexts() + // the result has values like `test\n.txt` so remove new line + return result.map((result) => result.replace('\n', '')) +} + +export const showHiddenResources = async (page): Promise => { + await page.locator(filesViewOptionButton).click() + await page.locator(hiddenFilesToggleButton).click() +} diff --git a/tests/e2e/support/objects/app-files/resource/index.ts b/tests/e2e/support/objects/app-files/resource/index.ts index fbf4ca36476..68315b62d5c 100644 --- a/tests/e2e/support/objects/app-files/resource/index.ts +++ b/tests/e2e/support/objects/app-files/resource/index.ts @@ -5,7 +5,6 @@ import { deleteResource, deleteResourceArgs, deleteResourceTrashbin, - deleteResourceTrashbinArgs, downloadResources, downloadResourcesArgs, downloadResourceVersion, @@ -20,7 +19,12 @@ import { uploadResource, uploadResourceArgs, restoreResourceTrashbinArgs, - restoreResourceTrashbin + restoreResourceTrashbin, + searchResourceGlobalSearch, + searchResourceGlobalSearchArgs, + getDisplayedResourcesFromSearch, + clickResource, + showHiddenResources } from './actions' export class Resource { @@ -100,7 +104,7 @@ export class Resource { return await emptyTrashBinResources(this.#page) } - async deleteTrashBin(args: Omit): Promise { + async deleteTrashBin(args: Omit): Promise { const startUrl = this.#page.url() const message = await deleteResourceTrashbin({ ...args, page: this.#page }) await this.#page.goto(startUrl) @@ -113,4 +117,20 @@ export class Resource { await this.#page.goto(startUrl) return message } + + async searchResource(args: Omit): Promise { + await searchResourceGlobalSearch({ ...args, page: this.#page }) + } + + getDisplayedResources(): Promise { + return getDisplayedResourcesFromSearch(this.#page) + } + + async openFolder(resource): Promise { + await clickResource({ page: this.#page, path: resource }) + } + + async showHiddenFiles(): Promise { + await showHiddenResources(this.#page) + } }