diff --git a/e2e/playwright/search/src/tests/search-sorting.spec.ts b/e2e/playwright/search/src/tests/search-sorting.spec.ts new file mode 100644 index 000000000..ce98d0312 --- /dev/null +++ b/e2e/playwright/search/src/tests/search-sorting.spec.ts @@ -0,0 +1,180 @@ +/*! + * Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { expect } from '@playwright/test'; +import { + ApiClientFactory, + Utils, + test, + TrashcanApi, + NodesApi, + FileActionsApi, + TEST_FILES, + SearchPage, + SortByDirection, + SortByType +} from '@alfresco/playwright-shared'; + +test.describe('Search sorting', () => { + const random = Utils.random(); + + const user1 = `user1-${random}`; + const user2 = `user2-${random}`; + + const parent = `parent-${random}`; + let parentId: string; + + const fileJpg = { + name: `search-sort-${random}-file-1.jpg`, + source: TEST_FILES.JPG_FILE.path + }; + + const filePdf = { + name: `search-sort-${random}-file-2.pdf`, + title: 'search sort title', + description: 'search-sort-${random}-file', + source: TEST_FILES.PDF.path + }; + + let nodesApi1: NodesApi; + let trashcanApi1: TrashcanApi; + let fileActionsApi1: FileActionsApi; + let nodesApi2: NodesApi; + let trashcanApi2: TrashcanApi; + let fileActionsApi2: FileActionsApi; + + test.beforeAll(async () => { + try { + const apiClientFactory = new ApiClientFactory(); + await apiClientFactory.setUpAcaBackend('admin'); + await apiClientFactory.createUser({ username: user1 }); + await apiClientFactory.createUser({ username: user2 }); + nodesApi1 = await NodesApi.initialize(user1, user1); + trashcanApi1 = await TrashcanApi.initialize(user1, user1); + fileActionsApi1 = await FileActionsApi.initialize(user1, user1); + nodesApi2 = await NodesApi.initialize(user2, user2); + trashcanApi2 = await TrashcanApi.initialize(user2, user2); + fileActionsApi2 = await FileActionsApi.initialize(user2, user2); + } catch (error) { + console.error(`beforeAll failed : ${error}`); + } + + parentId = (await nodesApi1.createFolder(parent)).entry.id; + + await nodesApi1.setGranularPermission(parentId, true, user2, 'Collaborator'); + + await fileActionsApi1.uploadFileWithRename(fileJpg.source, fileJpg.name, parentId); + await fileActionsApi2.uploadFileWithRename(filePdf.source, filePdf.name, parentId, filePdf.title, filePdf.description); + + await fileActionsApi1.waitForNodes(fileJpg.name, { expect: 1 }); + await fileActionsApi2.waitForNodes(filePdf.name, { expect: 1 }); + }); + + test.beforeEach(async ({ loginPage }) => { + await Utils.tryLoginUser(loginPage, user1, user1, 'beforeEach failed'); + }); + + test.afterAll(async () => { + await Utils.deleteNodesSitesEmptyTrashcan(nodesApi1, trashcanApi1, 'afterAll failed'); + await Utils.deleteNodesSitesEmptyTrashcan(nodesApi2, trashcanApi2, 'afterAll failed'); + }); + + async function testSearchSorting( + searchPage: SearchPage, + sortBy: SortByType, + sortOrder: SortByDirection, + expectedFirstFile: string, + expectedSecondFile: string + ) { + await searchPage.searchWithin(`search-sort *${random}`, 'files'); + + await searchPage.searchSortingPicker.sortBy(sortBy, sortOrder); + + expect(await searchPage.dataTable.getNthRow(1).textContent()).toContain(expectedFirstFile); + expect(await searchPage.dataTable.getNthRow(2).textContent()).toContain(expectedSecondFile); + } + + [ + { + column: 'Name', + id: 'C277728', + firstFile: fileJpg.name, + secondFile: filePdf.name + }, + { + column: 'Type', + id: 'C277740', + firstFile: filePdf.name, + secondFile: fileJpg.name + }, + { + column: 'Size', + id: 'C277738', + firstFile: filePdf.name, + secondFile: fileJpg.name + }, + { + column: 'Created date', + id: 'C277734', + firstFile: fileJpg.name, + secondFile: filePdf.name + }, + { + column: 'Modified date', + id: 'C277736', + firstFile: fileJpg.name, + secondFile: filePdf.name + }, + { + column: 'Relevance', + id: 'C277727', + firstFile: fileJpg.name, + secondFile: filePdf.name + }, + { + column: 'Modifier', + id: 'C277732', + firstFile: fileJpg.name, + secondFile: filePdf.name + } + ].forEach((testCase) => { + test(`[${testCase.id}] Sort by ${testCase.column}`, async ({ searchPage }) => { + await testSearchSorting(searchPage, testCase.column as SortByType, 'asc', testCase.firstFile, testCase.secondFile); + }); + }); + + test('[C277722] Sorting options are displayed', async ({ searchPage }) => { + await searchPage.searchWithin(`search-sort *${random}`, 'files'); + await searchPage.searchSortingPicker.actionMenu.click(); + + expect(await searchPage.searchSortingPicker.isSortOrderButtonDisplayed()).toBe(true); + + await searchPage.searchSortingPicker.clickSortByDropdown(); + + const expectedOptions = ['Relevance', 'Filename', 'Title', 'Modified date', 'Modifier', 'Created date', 'Size', 'Type']; + expectedOptions.sort((a, b) => a.localeCompare(b)); + const optionListed = await searchPage.searchSortingPicker.getSortByOptionsList(); + expect(optionListed).toEqual(expectedOptions); + }); +}); diff --git a/e2e/protractor/suites/search/search-input.test.ts b/e2e/protractor/suites/search/search-input.test.ts deleted file mode 100644 index 1c35e196d..000000000 --- a/e2e/protractor/suites/search/search-input.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -/*! - * Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * Alfresco Example Content Application - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * from Hyland Software. If not, see . - */ - -import { BrowsingPage, LoginPage, Utils } from '@alfresco/aca-testing-shared'; - -describe('Search input', () => { - const loginPage = new LoginPage(); - const page = new BrowsingPage(); - const { toolbar } = page; - const { searchInput } = page.pageLayoutHeader; - - beforeAll(async () => { - await loginPage.loginWithAdmin(); - }); - - beforeEach(async () => { - await Utils.pressEscape(); - await page.clickPersonalFiles(); - }); - - it('[C289847] Search icon is displayed in toolbar and clicking on it displays search input container', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - - expect(await searchInput.isSearchContainerDisplayed()).toBe(true, 'search controls not displayed'); - }); - - it('[C289848] Search options are displayed when clicking in the search input', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - expect(await searchInput.isOptionsAreaDisplayed()).toBe(true, 'Search options not displayed'); - expect(await searchInput.isFilesOptionEnabled()).toBe(true, 'Files option not enabled'); - expect(await searchInput.isFoldersOptionEnabled()).toBe(true, 'Folders option not enabled'); - expect(await searchInput.isLibrariesOptionEnabled()).toBe(true, 'Libraries option not enabled'); - expect(await searchInput.isFilesOptionChecked()).toBe(false, 'Files option is checked'); - expect(await searchInput.isFoldersOptionChecked()).toBe(false, 'Folders option is checked'); - expect(await searchInput.isLibrariesOptionChecked()).toBe(false, 'Libraries option is checked'); - }); - - it('[C289849] Search options are correctly enabled / disabled', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - - await searchInput.clickFilesOption(); - expect(await searchInput.isFoldersOptionEnabled()).toBe(true, 'Folders option not enabled'); - expect(await searchInput.isLibrariesOptionEnabled()).toBe(false, 'Libraries option not disabled'); - - await searchInput.clickFilesOption(); - expect(await searchInput.isFoldersOptionEnabled()).toBe(true, 'Folders option not enabled'); - expect(await searchInput.isLibrariesOptionEnabled()).toBe(true, 'Folders option not enabled'); - - await searchInput.clickFoldersOption(); - expect(await searchInput.isFilesOptionEnabled()).toBe(true, 'Files option not enabled'); - expect(await searchInput.isLibrariesOptionEnabled()).toBe(false, 'Libraries option not disabled'); - - await searchInput.clickFoldersOption(); - expect(await searchInput.isFilesOptionEnabled()).toBe(true, 'Files option not enabled'); - expect(await searchInput.isLibrariesOptionEnabled()).toBe(true, 'Libraries option not enabled'); - - await searchInput.clickLibrariesOption(); - expect(await searchInput.isFilesOptionEnabled()).toBe(false, 'Files option not disabled'); - expect(await searchInput.isFoldersOptionEnabled()).toBe(false, 'Folders option not disabled'); - - await searchInput.clickLibrariesOption(); - expect(await searchInput.isFilesOptionEnabled()).toBe(true, 'Files option not enabled'); - expect(await searchInput.isFoldersOptionEnabled()).toBe(true, 'Folders option not enabled'); - }); -}); diff --git a/e2e/protractor/suites/search/search-results-files-folders.test.ts b/e2e/protractor/suites/search/search-results-files-folders.test.ts deleted file mode 100644 index 982d5b83c..000000000 --- a/e2e/protractor/suites/search/search-results-files-folders.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -/*! - * Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * Alfresco Example Content Application - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * from Hyland Software. If not, see . - */ - -import { AdminActions, LoginPage, SearchResultsPage, RepoClient, Utils } from '@alfresco/aca-testing-shared'; - -describe('Search results - files and folders', () => { - const random = Utils.random(); - const username = `user-${random}`; - - const file = `test-file-${random}.txt`; - let fileId: string; - const fileTitle = 'file title'; - const fileDescription = 'file description'; - - /* cspell:disable-next-line */ - const fileRussian = `любимый-сайт-${random}`; - let fileRussianId: string; - - const folder = `test-folder-${random}`; - let folderId: string; - const folderTitle = 'folder title'; - const folderDescription = 'folder description'; - - const site = `test-site-${random}`; - - const apis = { - user: new RepoClient(username, username) - }; - - const loginPage = new LoginPage(); - const page = new SearchResultsPage(); - const { searchInput } = page.pageLayoutHeader; - const { dataTable, breadcrumb, toolbar } = page; - const adminApiActions = new AdminActions(); - - beforeAll(async () => { - await adminApiActions.createUser({ username }); - - fileId = (await apis.user.nodes.createFile(file, '-my-', fileTitle, fileDescription)).entry.id; - await apis.user.nodes.updateNodeContent(fileId, 'edited by user'); - folderId = (await apis.user.nodes.createFolder(folder, '-my-', folderTitle, folderDescription)).entry.id; - fileRussianId = (await apis.user.nodes.createFile(fileRussian)).entry.id; - await apis.user.sites.createSite(site); - - await apis.user.search.waitForApi(username, { expect: 2 }); - await apis.user.queries.waitForSites(site, { expect: 1 }); - - await loginPage.loginWith(username); - }); - - beforeEach(async () => { - await page.refresh(); - await page.clickPersonalFilesAndWait(); - }); - - afterAll(async () => { - await Promise.all([ - apis.user.nodes.deleteNodeById(fileId), - apis.user.nodes.deleteNodeById(fileRussianId), - apis.user.nodes.deleteNodeById(folderId), - apis.user.sites.deleteSite(site) - ]); - }); - - it('[C290029] Search file with special characters', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkFilesAndFolders(); - await searchInput.searchFor(fileRussian); - await dataTable.waitForBody(); - - expect(await dataTable.isItemPresent(fileRussian)).toBe(true, `${fileRussian} is not displayed`); - }); - - it('[C279177] Location column redirect - file in user Home', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkFilesAndFolders(); - await searchInput.searchFor(file); - await dataTable.waitForBody(); - - await dataTable.clickItemLocation(file); - expect(await breadcrumb.getAllItems()).toEqual(['Personal Files']); - }); -}); diff --git a/e2e/protractor/suites/search/search-results-general.test.ts b/e2e/protractor/suites/search/search-results-general.test.ts deleted file mode 100644 index 6b7e8df17..000000000 --- a/e2e/protractor/suites/search/search-results-general.test.ts +++ /dev/null @@ -1,156 +0,0 @@ -/*! - * Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * Alfresco Example Content Application - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * from Hyland Software. If not, see . - */ - -import { AdminActions, LoginPage, SearchResultsPage, RepoClient, Utils } from '@alfresco/aca-testing-shared'; -import { browser } from 'protractor'; - -describe('Search results general', () => { - const random = Utils.random(); - const username = `user-${random}`; - - const file = `test-file-${random}.txt`; - let fileId: string; - const folder = `test-folder-${random}`; - let folderId: string; - const site = `test-site-${random}`; - - const apis = { - user: new RepoClient(username, username) - }; - - const loginPage = new LoginPage(); - const page = new SearchResultsPage(); - const { searchInput, toolbar } = page.pageLayoutHeader; - const dataTable = page.dataTable; - const adminApiActions = new AdminActions(); - - beforeAll(async () => { - await adminApiActions.createUser({ username }); - - fileId = (await apis.user.nodes.createFile(file)).entry.id; - folderId = (await apis.user.nodes.createFolder(folder)).entry.id; - await apis.user.sites.createSite(site); - - await apis.user.search.waitForApi(username, { expect: 1 }); - await apis.user.queries.waitForSites(site, { expect: 1 }); - - await loginPage.loginWith(username); - }); - - afterAll(async () => { - await Promise.all([apis.user.nodes.deleteNodeById(fileId), apis.user.nodes.deleteNodeById(folderId), apis.user.sites.deleteSite(site)]); - }); - - beforeEach(async () => { - await page.refresh(); - }); - - afterEach(async () => { - await Utils.pressEscape(); - await page.clickPersonalFiles(); - }); - - it('[C290005] Only files are returned when Files option is the only one checked', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkOnlyFiles(); - await searchInput.searchFor(`*${random}`); - await dataTable.waitForBody(); - - expect(await dataTable.isItemPresent(file)).toBe(true, `${file} not displayed`); - expect(await dataTable.isItemPresent(folder)).toBe(false, `${folder} is displayed`); - expect(await dataTable.isItemPresent(site)).toBe(false, `${site} is displayed`); - }); - - it('[C290006] Only folders are returned when Folders option is the only one checked', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkOnlyFolders(); - await searchInput.searchFor(`*${random}`); - await page.waitForResults(); - - expect(await dataTable.isItemPresent(file)).toBe(false, `${file} is displayed`); - expect(await dataTable.isItemPresent(folder)).toBe(true, `${folder} not displayed`); - expect(await dataTable.isItemPresent(site)).toBe(false, `${site} is displayed`); - }); - - it('[C290007] Files and folders are returned when both Files and Folders options are checked', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkFilesAndFolders(); - await searchInput.searchFor(`*${random}`); - await page.waitForResults(); - - expect(await dataTable.isItemPresent(file)).toBe(true, `${file} not displayed`); - expect(await dataTable.isItemPresent(folder)).toBe(true, `${folder} not displayed`); - expect(await dataTable.isItemPresent(site)).toBe(false, `${site} is displayed`); - }); - - it('[C290008] Only libraries are returned when Libraries option is checked', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkLibraries(); - await searchInput.searchForLibrary(`*${random}`); - await page.waitForResults(); - - expect(await dataTable.isItemPresent(file)).toBe(false, `${file} is displayed`); - expect(await dataTable.isItemPresent(folder)).toBe(false, `${folder} is displayed`); - expect(await dataTable.isItemPresent(site)).toBe(true, `${site} not displayed`); - }); - - it('[C279162] Results are updated automatically when changing the search term', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.searchFor(file); - await page.waitForResults(); - - expect(await dataTable.isItemPresent(file)).toBe(true, `${file} is not displayed`); - expect(await dataTable.isItemPresent(folder)).toBe(false, `${folder} is displayed`); - - await searchInput.clickSearchButton(); - await searchInput.searchFor(folder); - await page.waitForResults(); - - expect(await dataTable.isItemPresent(file)).toBe(false, `${file} is displayed`); - expect(await dataTable.isItemPresent(folder)).toBe(true, `${folder} is not displayed`); - }); - - it('[C279178] Results are returned when accessing an URL containing a search query', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkLibraries(); - await searchInput.searchForLibrary(site); - await page.waitForResults(); - - expect(await dataTable.isItemPresent(site)).toBe(true, `${site} not displayed`); - - const url = await browser.getCurrentUrl(); - - await page.clickPersonalFiles(); - await browser.get(url); - await page.waitForResults(); - - expect(await dataTable.isItemPresent(site)).toBe(true, `${site} not displayed`); - }); -}); diff --git a/e2e/protractor/suites/search/search-results-libraries.test.ts b/e2e/protractor/suites/search/search-results-libraries.test.ts deleted file mode 100644 index 847541f4f..000000000 --- a/e2e/protractor/suites/search/search-results-libraries.test.ts +++ /dev/null @@ -1,245 +0,0 @@ -/*! - * Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * Alfresco Example Content Application - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * from Hyland Software. If not, see . - */ - -import { AdminActions, LoginPage, SearchResultsPage, RepoClient, Utils, SITE_VISIBILITY, SITE_ROLES } from '@alfresco/aca-testing-shared'; - -describe('Search results - libraries', () => { - const random = Utils.random(); - const username = `user-${random}`; - - const site1 = { - name: `lib-${random}-1`, - id: `site-${random}-1` - }; - const site2 = { - name: `site-2-${random}`, - id: `site-${random}-2` - }; - const site3 = { - name: `my-lib-${random}`, - id: `site3-${random}` - }; - const site4 = { - name: `my-site-${random}`, - id: `site4-${random}`, - description: 'site description' - }; - - const userSitePrivate = `user-site-${random}-private`; - const userSiteModerated = `user-site-${random}-moderated`; - const userSitePublic = `user-site-${random}-public`; - - const siteRussian = { - /* cspell:disable-next-line */ - name: `любимый-сайт-${random}`, - id: `site-russian-id-${random}` - }; - - const adminSite1 = `admin-${random}-site1`; - const adminSite2 = `admin-${random}-site2`; - const adminSite3 = `admin-${random}-site3`; - const adminSite4 = `admin-${random}-site4`; - const adminPrivate = `admin-${random}-sitePrivate`; - - const apis = { - user: new RepoClient(username, username) - }; - - const loginPage = new LoginPage(); - const page = new SearchResultsPage(); - const { searchInput, toolbar } = page.pageLayoutHeader; - const dataTable = page.dataTable; - const adminApiActions = new AdminActions(); - - beforeAll(async () => { - try { - await adminApiActions.createUser({ username }); - - await apis.user.sites.createSite(site1.name, SITE_VISIBILITY.PUBLIC, '', site1.id); - await apis.user.sites.createSite(site2.name, SITE_VISIBILITY.PUBLIC, '', site2.id); - await apis.user.sites.createSite(site3.name, SITE_VISIBILITY.PUBLIC, '', site3.id); - await apis.user.sites.createSite(site4.name, SITE_VISIBILITY.PUBLIC, site4.description, site4.id); - - await apis.user.sites.createSite(userSitePublic, SITE_VISIBILITY.PUBLIC); - await apis.user.sites.createSite(userSiteModerated, SITE_VISIBILITY.MODERATED); - await apis.user.sites.createSite(userSitePrivate, SITE_VISIBILITY.PRIVATE); - - await apis.user.sites.createSite(siteRussian.name, SITE_VISIBILITY.PUBLIC, '', siteRussian.id); - - await adminApiActions.sites.createSite(adminSite1, SITE_VISIBILITY.PUBLIC); - await adminApiActions.sites.createSite(adminSite2, SITE_VISIBILITY.PUBLIC); - await adminApiActions.sites.createSite(adminSite3, SITE_VISIBILITY.PUBLIC); - await adminApiActions.sites.createSite(adminSite4, SITE_VISIBILITY.PUBLIC); - await adminApiActions.sites.addSiteMember(adminSite1, username, SITE_ROLES.SITE_CONSUMER.ROLE); - await adminApiActions.sites.addSiteMember(adminSite2, username, SITE_ROLES.SITE_CONTRIBUTOR.ROLE); - await adminApiActions.sites.addSiteMember(adminSite3, username, SITE_ROLES.SITE_COLLABORATOR.ROLE); - await adminApiActions.sites.addSiteMember(adminSite4, username, SITE_ROLES.SITE_MANAGER.ROLE); - - await adminApiActions.sites.createSite(adminPrivate, SITE_VISIBILITY.PRIVATE); - - await adminApiActions.login(); - await adminApiActions.sites.waitForSitesToBeCreated([adminSite1, adminSite2, adminSite3, adminSite4]); - - await apis.user.sites.waitForSitesToBeCreated([ - site1.id, - site2.id, - site3.id, - site4.id, - userSitePublic, - userSiteModerated, - userSitePrivate, - siteRussian.id - ]); - - await apis.user.queries.waitForSites(random, { expect: 12 }); - - await loginPage.loginWith(username); - } catch {} - }); - - afterAll(async () => { - try { - await adminApiActions.sites.deleteSites([adminSite1, adminSite2, adminSite3, adminSite4, adminPrivate]); - await apis.user.sites.deleteSites([site1.id, site2.id, site3.id, site4.id, userSitePublic, userSiteModerated, userSitePrivate, siteRussian.id]); - } catch {} - }); - - beforeEach(async () => { - await Utils.pressEscape(); - await page.clickPersonalFiles(); - }); - - it('[C290012] Search library - full name match', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkLibraries(); - await searchInput.searchForLibrary(site1.name); - await dataTable.waitForBody(); - - expect(await dataTable.isItemPresent(site1.name)).toBe(true, `${site1.name} not displayed`); - expect(await dataTable.isItemPresent(site2.name)).toBe(false, `${site2.name} displayed`); - expect(await dataTable.isItemPresent(site3.name)).toBe(false, `${site3.name} displayed`); - expect(await dataTable.isItemPresent(site4.name)).toBe(false, `${site4.name} displayed`); - }); - - it('[C290013] Search library - partial name match', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkLibraries(); - await searchInput.searchForLibrary(`lib-${random}`); - await dataTable.waitForBody(); - - expect(await dataTable.isItemPresent(site1.name)).toBe(true, `${site1.name} not displayed`); - expect(await dataTable.isItemPresent(site2.name)).toBe(false, `${site2.name} displayed`); - expect(await dataTable.isItemPresent(site3.name)).toBe(true, `${site3.name} not displayed`); - expect(await dataTable.isItemPresent(site4.name)).toBe(false, `${site4.name} displayed`); - }); - - it('[C290014] Search library - description match', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkLibraries(); - await searchInput.searchForLibrary(site4.description); - await dataTable.waitForBody(); - - expect(await dataTable.isItemPresent(site1.name)).toBe(false, `${site1.name} displayed`); - expect(await dataTable.isItemPresent(site2.name)).toBe(false, `${site2.name} displayed`); - expect(await dataTable.isItemPresent(site3.name)).toBe(false, `${site3.name} displayed`); - expect(await dataTable.isItemPresent(site4.name)).toBe(true, `${site4.name} not displayed`); - }); - - it('[C290016] Results page columns', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkLibraries(); - await searchInput.searchForLibrary(site1.name); - await dataTable.waitForBody(); - - const expectedColumns = ['Name', 'Description', 'My Role', 'Visibility']; - const actualColumns = await dataTable.getColumnHeadersText(); - - await expect(actualColumns).toEqual(expectedColumns); - }); - - it('[C290017] Library visibility is correctly displayed', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkLibraries(); - await searchInput.searchForLibrary(`user-site-${random}`); - await dataTable.waitForBody(); - - const expectedSitesVisibility = { - [userSitePrivate]: SITE_VISIBILITY.PRIVATE, - [userSiteModerated]: SITE_VISIBILITY.MODERATED, - [userSitePublic]: SITE_VISIBILITY.PUBLIC - }; - - const sitesList = await dataTable.getSitesNameAndVisibility(); - - for (const site of Object.keys(expectedSitesVisibility)) { - expect(sitesList[site]).toEqual(expectedSitesVisibility[site]); - } - }); - - it('[C290018] User role is correctly displayed', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkLibraries(); - await searchInput.searchForLibrary(`admin-${random}-site`); - await dataTable.waitForBody(); - - const expectedSitesRoles = { - [adminSite1]: SITE_ROLES.SITE_CONSUMER.LABEL, - [adminSite2]: SITE_ROLES.SITE_CONTRIBUTOR.LABEL, - [adminSite3]: SITE_ROLES.SITE_COLLABORATOR.LABEL, - [adminSite4]: SITE_ROLES.SITE_MANAGER.LABEL - }; - - const sitesList: any = await dataTable.getSitesNameAndRole(); - - for (const site of Object.keys(expectedSitesRoles)) { - expect(sitesList[site]).toEqual(expectedSitesRoles[site]); - } - }); - - it('[C290019] Private sites are not displayed when user is not a member', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkLibraries(); - await searchInput.searchForLibrary(`admin-${random}-site`); - await dataTable.waitForBody(); - - expect(await dataTable.isItemPresent(adminPrivate)).toBe(false, `${adminPrivate} is displayed`); - }); - - it('[C290028] Search libraries with special characters', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkLibraries(); - await searchInput.searchForLibrary(siteRussian.name); - await dataTable.waitForBody(); - - expect(await dataTable.isItemPresent(siteRussian.name)).toBe(true, `${siteRussian.name} not displayed`); - }); -}); diff --git a/e2e/protractor/suites/search/search-sorting.test.ts b/e2e/protractor/suites/search/search-sorting.test.ts deleted file mode 100644 index 27a542f02..000000000 --- a/e2e/protractor/suites/search/search-sorting.test.ts +++ /dev/null @@ -1,180 +0,0 @@ -/*! - * Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * Alfresco Example Content Application - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * from Hyland Software. If not, see . - */ - -import { AdminActions, LoginPage, SearchResultsPage, RepoClient, Utils, FILES } from '@alfresco/aca-testing-shared'; - -describe('Search sorting', () => { - const random = Utils.random(); - - const user1 = `user1-${random}`; - const user2 = `user2-${random}`; - - const parent = `parent-${random}`; - let parentId: string; - - const fileJpg = { - name: `search-sort-${random}-file-1.jpg`, - source: FILES.jpgFile - }; - - const filePdf = { - name: `search-sort-${random}-file-2.pdf`, - title: 'search sort title', - description: 'search sort', - source: FILES.pdfFile - }; - - const apis = { - user1: new RepoClient(user1, user1), - user2: new RepoClient(user2, user2) - }; - - const loginPage = new LoginPage(); - const page = new SearchResultsPage(); - const { searchInput } = page.pageLayoutHeader; - const { dataTable, toolbar } = page; - const adminApiActions = new AdminActions(); - - beforeAll(async () => { - await adminApiActions.createUser({ username: user1 }); - await adminApiActions.createUser({ username: user2 }); - parentId = (await apis.user1.nodes.createFolder(parent)).entry.id; - - await apis.user1.nodes.setGranularPermission(parentId, true, user2, 'Collaborator'); - - await apis.user1.upload.uploadFileWithRename(fileJpg.source, parentId, fileJpg.name); - await apis.user2.upload.uploadFileWithRename(filePdf.source, parentId, filePdf.name, filePdf.title, filePdf.description); - - await apis.user1.search.waitForNodes(`search-sort-${random}`, { expect: 2 }); - - await loginPage.loginWith(user1); - }); - - beforeEach(async () => { - await Utils.pressEscape(); - await page.clickPersonalFilesAndWait(); - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.searchFor(`search-sort *${random}`); - await dataTable.waitForBody(); - }); - - afterAll(async () => { - await apis.user1.nodes.deleteNodeById(parentId); - }); - - it('[C277722] Sorting options are displayed', async () => { - expect(await page.sortingPicker.isSortOrderButtonDisplayed()).toBe(true, 'Sort order button not displayed'); - - await page.sortingPicker.clickSortByDropdown(); - - const expectedOptions = ['Relevance', 'Filename', 'Title', 'Modified date', 'Modifier', 'Created date', 'Size', 'Type']; - const optionListed = await page.sortingPicker.getSortByOptionsList(); - expect(optionListed).toEqual(expectedOptions, 'Incorrect sort options list'); - }); - - it('[C277728] Sort by Name', async () => { - await page.sortingPicker.sortBy('Filename', 'asc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(fileJpg.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(filePdf.name); - - await page.sortingPicker.sortBy('Filename', 'desc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(filePdf.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(fileJpg.name); - }); - - it('[C277740] Sort by Type', async () => { - await page.sortingPicker.sortBy('Type', 'asc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(filePdf.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(fileJpg.name); - - await page.sortingPicker.sortBy('Type', 'desc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(fileJpg.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(filePdf.name); - }); - - it('[C277738] Sort by Size', async () => { - await page.sortingPicker.sortBy('Size', 'asc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(filePdf.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(fileJpg.name); - - await page.sortingPicker.sortBy('Size', 'desc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(fileJpg.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(filePdf.name); - }); - - it('[C277734] Sort by Created date', async () => { - await page.sortingPicker.sortBy('Created date', 'asc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(fileJpg.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(filePdf.name); - - await page.sortingPicker.sortBy('Created date', 'desc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(filePdf.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(fileJpg.name); - }); - - it('[C277736] Sort by Modified date', async () => { - await page.sortingPicker.sortBy('Modified date', 'asc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(fileJpg.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(filePdf.name); - - await page.sortingPicker.sortBy('Modified date', 'desc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(filePdf.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(fileJpg.name); - }); - - it('[C277727] Sort by Relevance', async () => { - await page.sortingPicker.sortBy('Relevance', 'asc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(fileJpg.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(filePdf.name); - - await page.sortingPicker.sortBy('Relevance', 'desc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(filePdf.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(fileJpg.name); - }); - - it('[C277732] Sort by Modifier', async () => { - await page.sortingPicker.sortBy('Modifier', 'asc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(fileJpg.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(filePdf.name); - - await page.sortingPicker.sortBy('Modifier', 'desc'); - - expect(await dataTable.getNthSearchResultsRow(1).getText()).toContain(filePdf.name); - expect(await dataTable.getNthSearchResultsRow(2).getText()).toContain(fileJpg.name); - }); -}); diff --git a/projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts b/projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts index f67e69324..f86006d3d 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts @@ -78,6 +78,13 @@ export class DataTableComponent extends BaseComponent { getRowByColumnTitleAndItsCellValue = (columnTitle: string, cellValue: string | number): Locator => this.page.locator(`//div[contains(@title, '${columnTitle}')]//span[contains(text(), '${cellValue}')]/ancestor::adf-datatable-row`); + /** + * Method used in cases where we want to retrieve a row from the datatable based on its numerical order within the array. + * + * @returns reference to cell element which contains text. + */ + getNthRow = (orderNum: number): Locator => this.getRowLocator.nth(orderNum); + /** * Method used in cases where user have possibility to navigate "inside" the element (it's clickable and has link attribute). * Perform action .click() to navigate inside it diff --git a/projects/aca-playwright-shared/src/page-objects/components/index.ts b/projects/aca-playwright-shared/src/page-objects/components/index.ts index 74c2a84a5..301a91697 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/index.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/index.ts @@ -35,6 +35,7 @@ export * from './adf-info-drawer.component'; export * from './viewer.component'; export * from './search/search-input.component'; export * from './search/search-overlay.components'; +export * from './search/search-sorting-picker.components'; export * from './breadcrumb/breadcrumb.component'; export * from './sidenav.component'; export * from './aca-header.component'; diff --git a/projects/aca-playwright-shared/src/page-objects/components/search/search-sorting-picker.components.ts b/projects/aca-playwright-shared/src/page-objects/components/search/search-sorting-picker.components.ts new file mode 100755 index 000000000..63e3f9240 --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/components/search/search-sorting-picker.components.ts @@ -0,0 +1,85 @@ +/*! + * Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +import { Page } from '@playwright/test'; +import { BaseComponent } from '../base.component'; + +export type SortByType = 'Relevance' | 'Title' | 'Filename' | 'Modified date' | 'Modifier' | 'Created date' | 'Size' | 'Type'; +export type SortByDirection = 'asc' | 'desc'; + +export class SearchSortingPicker extends BaseComponent { + private static rootElement = '#aca-button-action-menu'; + + public actionMenu = this.page.locator('[data-automation-id="auto_header_content_id_$thumbnail"]'); + public sortOrderButton = this.page.locator('#aca-button-sorting-menu'); + public sortByDropdownExpanded = this.page.locator('.mat-menu-panel').first(); + public sortByList = this.page.locator('.mat-menu-panel button'); + + constructor(page: Page, rootElement = SearchSortingPicker.rootElement) { + super(page, rootElement); + } + + async waitForSortByDropdownToExpand(): Promise { + await this.sortByDropdownExpanded.waitFor(); + } + + async isSortOrderButtonDisplayed(): Promise { + return this.sortOrderButton.isVisible(); + } + + async isSortByDropdownExpanded(): Promise { + return this.sortByDropdownExpanded.isVisible(); + } + + async clickSortByDropdown(): Promise { + await this.sortOrderButton.click(); + await this.waitForSortByDropdownToExpand(); + } + + async getSortByOptionsList(): Promise { + let sortOptionsCount = await this.sortByList.count(); + let sortByOptions: string[] = []; + for (let i = 1; i < sortOptionsCount; i++) { + let textContent = (await this.sortByList.nth(i).textContent()).trim(); + sortByOptions.push(textContent); + } + sortByOptions.sort((a, b) => a.localeCompare(b)); + return sortByOptions; +} + + async sortBy(option: SortByType, direction: SortByDirection): Promise { + await this.actionMenu.click(); + await this.clickSortByDropdown(); + + if (!(await this.isSortByDropdownExpanded())) { + await this.clickSortByDropdown(); + } + const elem = this.sortByList.getByText(option); + const optionId = await elem.getAttribute('id'); + await elem.click(); + const directionSortElement = this.page.locator(`[id="${optionId}-${direction.toLocaleLowerCase()}"]`); + await directionSortElement.click(); + await this.progressBarWaitForReload(); + } +} diff --git a/projects/aca-playwright-shared/src/page-objects/pages/search.page.ts b/projects/aca-playwright-shared/src/page-objects/pages/search.page.ts index 13b59d41a..3efe7f421 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/search.page.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/search.page.ts @@ -24,7 +24,7 @@ import { Page } from '@playwright/test'; import { BasePage } from './base.page'; -import { DataTableComponent, MatMenuComponent, ViewerComponent, SearchInputComponent, SearchOverlayComponent, SidenavComponent } from '../components'; +import { DataTableComponent, MatMenuComponent, ViewerComponent, SearchInputComponent, SearchOverlayComponent, SidenavComponent, SearchSortingPicker } from '../components'; import { AcaHeader } from '../components/aca-header.component'; import { AdfConfirmDialogComponent, AdfFolderDialogComponent } from '../components/dialogs'; @@ -44,6 +44,7 @@ export class SearchPage extends BasePage { public viewer = new ViewerComponent(this.page); public searchInput = new SearchInputComponent(this.page); public searchOverlay = new SearchOverlayComponent(this.page); + public searchSortingPicker = new SearchSortingPicker(this.page); public sidenav = new SidenavComponent(this.page); public confirmDialogComponent = new AdfConfirmDialogComponent(this.page);