From ddc80fb1e8fdd616ff57939db35d26c5c26b7a4b Mon Sep 17 00:00:00 2001 From: Prarup Gurung Date: Thu, 15 Jun 2023 08:37:03 +0545 Subject: [PATCH] Added e2e tests for full text search --- .../smoke/fullTextSearch.ocis.feature | 102 ++++++++++++++++++ tests/e2e/cucumber/steps/api.ts | 19 ++++ tests/e2e/cucumber/steps/ui/resources.ts | 6 +- tests/e2e/cucumber/steps/ui/search.ts | 47 ++++++++ tests/e2e/support/objects/app-files/index.ts | 1 + .../objects/app-files/resource/actions.ts | 8 +- .../objects/app-files/resource/index.ts | 4 +- .../objects/app-files/search/actions.ts | 43 ++++++++ .../support/objects/app-files/search/index.ts | 30 ++++++ 9 files changed, 251 insertions(+), 9 deletions(-) create mode 100644 tests/e2e/cucumber/features/smoke/fullTextSearch.ocis.feature create mode 100644 tests/e2e/cucumber/steps/ui/search.ts create mode 100644 tests/e2e/support/objects/app-files/search/actions.ts create mode 100644 tests/e2e/support/objects/app-files/search/index.ts diff --git a/tests/e2e/cucumber/features/smoke/fullTextSearch.ocis.feature b/tests/e2e/cucumber/features/smoke/fullTextSearch.ocis.feature new file mode 100644 index 00000000000..6d6d6141bea --- /dev/null +++ b/tests/e2e/cucumber/features/smoke/fullTextSearch.ocis.feature @@ -0,0 +1,102 @@ +Feature: Search + As a user + I want to do full text search + So that I can find the files with the content I am looking for + + Background: + Given "Admin" creates following users using API + | id | + | Alice | + | Brian | + And "Admin" sets the default folder for received shares to "Shares" + And "Admin" disables share auto accepting + And "Admin" assigns following roles to the users using API + | id | role | + | Brian | Space Admin | + + And "Alice" logs in + And "Alice" creates the following folder in personal space using API + | name | + | folderToShare | + And "Alice" uploads the following local file into personal space using API + | localFile | to | + | filesForUpload/textfile.txt | folderToShare/fileToShare.txt | + And "Alice" shares the following resource using API + | resource | recipient | type | role | + | folderToShare | Brian | user | Can edit | + + And "Brian" logs in + And "Brian" accepts the following share using API + | name | + | folderToShare | + And "Brian" creates the following folder in personal space using API + | name | + | testFolder | + And "Brian" uploads the following local file into personal space using API + | localFile | to | + | filesForUpload/textfile.txt | textfile.txt | + | filesForUpload/textfile.txt | fileWithTag.txt | + | filesForUpload/textfile.txt | withTag.txt | + | filesForUpload/textfile.txt | testFolder/innerTextfile.txt | + + And "Brian" creates the following project spaces using API + | name | id | + | FullTextSearch | fulltextsearch.1 | + And "Brian" creates the following folder in space "FullTextSearch" using API + | name | + | spaceFolder | + And "Brian" creates the following file in space "FullTextSearch" using API + | name | content | + | spaceFolder/spaceTextfile.txt | This is test file. | + + And "Brian" opens the "files" app +# And "Brian" adds the following tags for the following resources using API +# | resource | tags | +# | fileWithTag.txt | tag 1 | +# | withTag.txt | tag 1 | + And "Brian" adds the following tags for the following resources using the sidebar panel + | resource | tags | + | fileWithTag.txt | tag 1 | + | withTag.txt | tag 1 | + + Scenario: Search for content of file + And "Brian" opens the "files" app + + When "Brian" searches "" using the global search bar + Then "Brian" should see the message "Search for files" on the webUI + + When "Brian" selects tag "tag 1" from the search result filter chip + Then following resources should be displayed in the files list for user "Brian" + | resource | + | fileWithTag.txt | + | withTag.txt | + + When "Brian" searches "file" using the global search bar + Then following resources should be displayed in the files list for user "Brian" + | resource | + | fileWithTag.txt | + + When "Brian" clears tag filter + Then following resources should be displayed in the files list for user "Brian" + | resource | + | textfile.txt | + | fileWithTag.txt | + | testFolder/innerTextfile.txt | + | fileToShare.txt | + | spaceFolder/spaceTextfile.txt | + + When "Brian" enables the option to search in file content + And "Brian" searches "Cheers" using the global search bar + Then following resources should be displayed in the files list for user "Brian" + | resource | + | textfile.txt | + | testFolder/innerTextfile.txt | + | fileToShare.txt | + | fileWithTag.txt | + | withTag.txt | + + When "Brian" opens the following file in texteditor + | resource | + | textfile.txt | + Then "Brian" should see the message "No results found" on the webUI + And "Brian" logs out diff --git a/tests/e2e/cucumber/steps/api.ts b/tests/e2e/cucumber/steps/api.ts index 80ea257e137..52842a628ce 100644 --- a/tests/e2e/cucumber/steps/api.ts +++ b/tests/e2e/cucumber/steps/api.ts @@ -298,3 +298,22 @@ Given( } } ) + +// Given( +// '{string} adds the following tags for the following resources using API', +// async function ( +// this: World, +// stepUser: string, +// stepTable: DataTable +// ): Promise { +// const user = this.usersEnvironment.getUser({ key: stepUser }) +// for (const info of stepTable.hashes()) { +// await api.graph.addTagsToTheResource({ +// user, +// shareWith: info.user, +// shareType: info.shareType, +// role: info.role +// }) +// } +// } +// ) diff --git a/tests/e2e/cucumber/steps/ui/resources.ts b/tests/e2e/cucumber/steps/ui/resources.ts index 4de7deb015f..8de33bb59a0 100644 --- a/tests/e2e/cucumber/steps/ui/resources.ts +++ b/tests/e2e/cucumber/steps/ui/resources.ts @@ -433,15 +433,15 @@ When( ) When( - /^"([^"].*)" opens the following file(?:s)? in (mediaviewer|pdfviewer)$/, + /^"([^"].*)" opens the following file(?:s)? in (mediaviewer|pdfviewer|texteditor)$/, async function (this: World, stepUser: string, actionType: string, stepTable: DataTable) { const { page } = this.actorsEnvironment.getActor({ key: stepUser }) const resourceObject = new objects.applicationFiles.Resource({ page }) for (const info of stepTable.hashes()) { - await resourceObject.openFileInViewer({ + await resourceObject.openFile({ name: info.resource, - actionType: actionType as 'mediaviewer' | 'pdfviewer' + actionType: actionType as 'mediaviewer' | 'pdfviewer' | 'texteditor' }) } } diff --git a/tests/e2e/cucumber/steps/ui/search.ts b/tests/e2e/cucumber/steps/ui/search.ts new file mode 100644 index 00000000000..a2935373874 --- /dev/null +++ b/tests/e2e/cucumber/steps/ui/search.ts @@ -0,0 +1,47 @@ +import { When, Then } from '@cucumber/cucumber' +import { World } from '../../environment' +import { objects } from '../../../support' +import { expect } from '@playwright/test' + +When( + '{string} searches {string} using the global search bar', + async function (this: World, stepUser: string, keyword: string): Promise { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const searchObject = new objects.applicationFiles.Search({ page }) + await searchObject.fullTextSearch({ keyword }) + } +) + +Then( + '{string} should see the message {string} on the webUI', + async function (this: World, stepUser: string, message: string): Promise { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const searchObject = new objects.applicationFiles.Search({ page }) + const actualMessage = await searchObject.getSearchResultMessage() + expect(actualMessage).toBe(message) + } +) + +When( + '{string} selects tag {string} from the search result filter chip', + async function (this: World, stepUser: string, tag: string): Promise { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const searchObject = new objects.applicationFiles.Search({ page }) + await searchObject.selectTagFilter({ tag }) + } +) + +When('{string} clears tag filter', async function (this: World, stepUser: string): Promise { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const searchObject = new objects.applicationFiles.Search({ page }) + await searchObject.clearTagFilter() +}) + +When( + /^"([^"]*)" (enable|disable)s the option to search in file content?$/, + async function (this: World, stepUser: string, enableOrDisable: string): Promise { + const { page } = this.actorsEnvironment.getActor({ key: stepUser }) + const searchObject = new objects.applicationFiles.Search({ page }) + await searchObject.toggleSearchInFileContent({ enableOrDisable }) + } +) diff --git a/tests/e2e/support/objects/app-files/index.ts b/tests/e2e/support/objects/app-files/index.ts index 65c97d86c35..d55795899dd 100644 --- a/tests/e2e/support/objects/app-files/index.ts +++ b/tests/e2e/support/objects/app-files/index.ts @@ -4,3 +4,4 @@ export { Resource } from './resource' export { Share } from './share' export { Spaces } from './spaces' export { Trashbin } from './trashbin' +export { Search } from './search' diff --git a/tests/e2e/support/objects/app-files/resource/actions.ts b/tests/e2e/support/objects/app-files/resource/actions.ts index 961a2343d7d..1aef295ef25 100644 --- a/tests/e2e/support/objects/app-files/resource/actions.ts +++ b/tests/e2e/support/objects/app-files/resource/actions.ts @@ -23,7 +23,7 @@ const checkBoxForTrashbin = `//*[@data-test-resource-path="%s"]//ancestor::tr//i export const fileRow = '//ancestor::*[(contains(@class, "oc-tile-card") or contains(@class, "oc-tbody-tr"))]' export const resourceNameSelector = - ':is(#files-space-table, .oc-tiles-item, #files-shared-with-me-accepted-section) [data-test-resource-name="%s"]' + ':is(#files-space-table, .oc-tiles-item, #files-shared-with-me-accepted-section, .files-table) [data-test-resource-name="%s"]' const breadcrumbResourceNameSelector = '//span[contains(@class, "oc-breadcrumb-item-text") and text()="%s"]' const addNewResourceButton = `#new-file-menu-btn` @@ -1106,13 +1106,13 @@ export const removeTagsFromResource = async (args: resourceTagsArgs): Promise => { +export const openFile = async (args: openFileArgs): Promise => { const { page, name, actionType } = args if (actionType === 'mediaviewer') { diff --git a/tests/e2e/support/objects/app-files/resource/index.ts b/tests/e2e/support/objects/app-files/resource/index.ts index bed1cf5ce98..043b3581f53 100644 --- a/tests/e2e/support/objects/app-files/resource/index.ts +++ b/tests/e2e/support/objects/app-files/resource/index.ts @@ -201,8 +201,8 @@ export class Resource { await po.editResources({ ...args, page: this.#page }) } - async openFileInViewer(args: Omit): Promise { - await po.openFileInViewer({ ...args, page: this.#page }) + async openFile(args: Omit): Promise { + await po.openFile({ ...args, page: this.#page }) } async addTags(args: Omit): Promise { diff --git a/tests/e2e/support/objects/app-files/search/actions.ts b/tests/e2e/support/objects/app-files/search/actions.ts new file mode 100644 index 00000000000..6bc900d10e4 --- /dev/null +++ b/tests/e2e/support/objects/app-files/search/actions.ts @@ -0,0 +1,43 @@ +import { Page } from 'playwright' +import util from 'util' + +const globalSearchInputSelector = '.oc-search-input' +const searchResultMessageSelector = '//p[@class="oc-text-muted"]' +const selectTagDropdownSelector = '.files-search-filter-tags' +const tagFilterChipSelector = '//button[contains(@data-test-value,"%s")]' +const clearTagFilterSelector = + '//div[contains(@class,"files-search-filter-tags")]//button[contains(@class,"oc-filter-chip-clear")]' +const enableSearchInFileContentSelector = + '//div[contains(@class,"files-search-filter-full-text")]//button[contains(@class,"oc-filter-chip-button")]' +const disableSearchInFileContentSelector = + '//div[contains(@class,"files-search-filter-full-text")]//button[contains(@class,"oc-filter-chip-clear")]' + +export interface fullTextSearchArgs { + keyword: string + page: Page +} + +export const fullTextSearch = async (args: fullTextSearchArgs): Promise => { + const { page, keyword } = args + await page.locator(globalSearchInputSelector).fill(keyword) + await page.keyboard.press('Enter') +} + +export const getSearchResultMessage = async ({ page }): Promise => { + return await page.locator(searchResultMessageSelector).innerText() +} + +export const selectTagFilter = async ({ tag, page }): Promise => { + await page.locator(selectTagDropdownSelector).click() + await page.locator(util.format(tagFilterChipSelector, tag)).click() +} + +export const clearTagFilter = async ({ page }): Promise => { + await page.locator(clearTagFilterSelector).click() +} + +export const toggleSearchInFileContent = async ({ enableOrDisable, page }): Promise => { + enableOrDisable === 'enable' + ? await page.locator(enableSearchInFileContentSelector).click() + : await page.locator(disableSearchInFileContentSelector).click() +} diff --git a/tests/e2e/support/objects/app-files/search/index.ts b/tests/e2e/support/objects/app-files/search/index.ts new file mode 100644 index 00000000000..42c4481d0a7 --- /dev/null +++ b/tests/e2e/support/objects/app-files/search/index.ts @@ -0,0 +1,30 @@ +import { Page } from 'playwright' +import * as po from '../search/actions' + +export class Search { + #page: Page + + constructor({ page }: { page: Page }) { + this.#page = page + } + + async fullTextSearch(args: Omit): Promise { + await po.fullTextSearch({ ...args, page: this.#page }) + } + + async getSearchResultMessage(): Promise { + return await po.getSearchResultMessage({ page: this.#page }) + } + + async selectTagFilter({ tag: string }): Promise { + await po.selectTagFilter({ tag: string, page: this.#page }) + } + + async clearTagFilter(): Promise { + await po.clearTagFilter({ page: this.#page }) + } + + async toggleSearchInFileContent({ enableOrDisable: string }): Promise { + await po.toggleSearchInFileContent({ enableOrDisable: string, page: this.#page }) + } +}