diff --git a/e2e/playwright/list-views/src/tests/empty-list.spec.ts b/e2e/playwright/list-views/src/tests/empty-list.spec.ts new file mode 100755 index 0000000000..6a4236d0b4 --- /dev/null +++ b/e2e/playwright/list-views/src/tests/empty-list.spec.ts @@ -0,0 +1,78 @@ +/*! + * 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, LoginPage, Utils, test } from '@alfresco/playwright-shared'; + +test.describe('Empty list views', () => { + const username = `user-${Utils.random()}`; + + test.beforeAll(async () => { + const apiClientFactory = new ApiClientFactory(); + await apiClientFactory.setUpAcaBackend('admin'); + await apiClientFactory.createUser({ username }); + }); + + test.beforeEach(async ({ page }) => { + const loginPage = new LoginPage(page); + await loginPage.loginUser( + { username, password: username }, + { + withNavigation: true, + waitForLoading: true + } + ); + }); + + test('[C217099] empty My Libraries', async ({ myLibrariesPage }) => { + await myLibrariesPage.navigate(); + expect(await myLibrariesPage.dataTable.isEmpty(), 'list is not empty').toBe(true); + expect(await myLibrariesPage.dataTable.getEmptyStateTitle()).toContain(`You aren't a member of any File Libraries yet`); + expect(await myLibrariesPage.dataTable.getEmptyStateSubtitle()).toContain('Join libraries to upload, view, and share files.'); + }); + + test('[C280134] [C280120] Empty Trash - pagination controls not displayed', async ({ trashPage }) => { + await trashPage.navigate(); + expect(await trashPage.dataTable.isEmpty(), 'list is not empty').toBe(true); + expect(await trashPage.dataTable.getEmptyStateTitle()).toContain('Trash is empty'); + expect(await trashPage.dataTable.getEmptyListText()).toContain('Items you delete are moved to the Trash.'); + expect(await trashPage.dataTable.getEmptyListText()).toContain('Empty Trash to permanently delete items.'); + expect(await trashPage.pagination.isRangePresent(), 'Range is present').toBe(false); + expect(await trashPage.pagination.isMaxItemsPresent(), 'Max items is present').toBe(false); + }); + + test('[C290123] [C290031] Empty Search results - pagination controls not displayed', async ({ personalFiles, searchPage }) => { + await personalFiles.acaHeader.searchButton.click(); + await searchPage.searchInput.searchButton.click(); + await searchPage.searchOverlay.checkFilesAndFolders(); + await searchPage.searchOverlay.searchFor('InvalidText'); + await searchPage.reload({ waitUntil: 'domcontentloaded' }); + await searchPage.dataTable.spinnerWaitForReload(); + + expect(await personalFiles.pagination.isRangePresent(), 'Range is present').toBe(false); + expect(await personalFiles.pagination.isMaxItemsPresent(), 'Max items is present').toBe(false); + expect(await personalFiles.dataTable.isEmpty(), 'list is not empty').toBe(true); + expect(await personalFiles.dataTable.emptySearchText.innerText()).toContain('Your search returned 0 results'); + }); +}); diff --git a/e2e/playwright/list-views/src/tests/generic-errors.spec.ts b/e2e/playwright/list-views/src/tests/generic-errors.spec.ts new file mode 100755 index 0000000000..616726344b --- /dev/null +++ b/e2e/playwright/list-views/src/tests/generic-errors.spec.ts @@ -0,0 +1,99 @@ +/*! + * 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, LoginPage, NodesApi, TrashcanApi, Utils, test } from '@alfresco/playwright-shared'; + +test.describe('Generic errors', () => { + const username = `user-${Utils.random()}`; + const username2 = `user2-${Utils.random()}`; + let parentId: string; + let file1Id: string; + let file2Id: string; + let actionUser: NodesApi; + + test.beforeAll(async () => { + try { + const parent = `folder-${Utils.random()}`; + const file1 = `file1-${Utils.random()}.txt`; + const file2 = `file2-${Utils.random()}.txt`; + const apiClientFactory = new ApiClientFactory(); + await apiClientFactory.setUpAcaBackend('admin'); + await apiClientFactory.createUser({ username }); + await apiClientFactory.createUser({ username: username2 }); + + actionUser = await NodesApi.initialize(username, username); + parentId = (await actionUser.createFolder(parent)).entry.id; + file1Id = (await actionUser.createFile(file1, parentId)).entry.id; + file2Id = (await actionUser.createFile(file2, parentId)).entry.id; + } catch (error) { + console.error(`----- beforeAll failed : ${error}`); + } + }); + + test.beforeEach(async ({ page }) => { + const loginPage = new LoginPage(page); + await loginPage.loginUser( + { username, password: username }, + { + withNavigation: true, + waitForLoading: true + } + ); + }); + + test.afterAll(async () => { + actionUser = await NodesApi.initialize(username, username); + const trashcanApi = await TrashcanApi.initialize(username, username); + await actionUser.deleteNodeById(parentId); + await trashcanApi.emptyTrashcan(); + }); + + test('[C217313] File / folder not found', async ({ personalFiles }) => { + await actionUser.deleteNodeById(file1Id, false); + await personalFiles.navigate({ remoteUrl: `#/personal-files/${file1Id}` }); + + expect(await personalFiles.errorDialog.genericError.isVisible(), 'Generic error page not displayed').toBe(true); + expect(await personalFiles.errorDialog.genericErrorTitle.innerText()).toContain( + `This item no longer exists or you don't have permission to view it.` + ); + }); + + test('[C217314] Permission denied', async ({ personalFiles, loginPage }) => { + await loginPage.logoutUser(); + await loginPage.loginUser( + { username: username2, password: username2 }, + { + withNavigation: true, + waitForLoading: true + } + ); + await personalFiles.navigate({ remoteUrl: `#/personal-files/${file2Id}` }); + + expect(await personalFiles.errorDialog.genericError.isVisible(), 'Generic error page not displayed').toBe(true); + expect(await personalFiles.errorDialog.genericErrorTitle.innerText()).toContain( + `This item no longer exists or you don't have permission to view it.` + ); + }); +}); diff --git a/e2e/playwright/list-views/src/tests/permissions.spec.ts b/e2e/playwright/list-views/src/tests/permissions.spec.ts new file mode 100755 index 0000000000..5f610bb889 --- /dev/null +++ b/e2e/playwright/list-views/src/tests/permissions.spec.ts @@ -0,0 +1,205 @@ +/*! + * 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, + FavoritesPageApi, + FileActionsApi, + LoginPage, + NodesApi, + SharedLinksApi, + SitesApi, + Utils, + test, + timeouts +} from '@alfresco/playwright-shared'; +import { Site } from '@alfresco/js-api'; + +test.describe('Special permissions', () => { + const username = `userPermissions-${Utils.random()}`; + let siteApiAdmin: SitesApi; + test.beforeAll(async () => { + const apiClientFactory = new ApiClientFactory(); + await apiClientFactory.setUpAcaBackend('admin'); + await apiClientFactory.createUser({ username }); + }); + + test.describe('file not displayed if user no longer has permissions on it', () => { + const sitePrivate = `private-${Utils.random()}`; + const fileName = `file-${Utils.random()}.txt`; + + test.beforeAll(async () => { + test.setTimeout(timeouts.webServer); + const userFavoritesApi = await FavoritesPageApi.initialize(username, username); + const userFileActionApi = await FileActionsApi.initialize(username, username); + siteApiAdmin = await SitesApi.initialize('admin'); + const nodeApiAdmin = await NodesApi.initialize('admin'); + const shareApiAdmin = await SharedLinksApi.initialize('admin'); + const shareApiUser = await SharedLinksApi.initialize(username, username); + + await siteApiAdmin.createSite(sitePrivate, Site.VisibilityEnum.PRIVATE); + await siteApiAdmin.addSiteMember(sitePrivate, username, Site.RoleEnum.SiteCollaborator); + const docLibId = await siteApiAdmin.getDocLibId(sitePrivate); + const fileId = (await nodeApiAdmin.createFile(fileName, docLibId)).entry.id; + await shareApiAdmin.shareFileById(fileId); + await userFavoritesApi.addFavoriteById('file', fileId); + + await userFileActionApi.updateNodeContent(fileId, 'edited by user'); + + await userFileActionApi.waitForNodes(username, { expect: 1 }); + + await shareApiAdmin.waitForFilesToBeShared([fileId]); + await shareApiUser.waitForFilesToBeShared([fileId]); + }); + + test.beforeEach(async ({ page }) => { + const loginPage = new LoginPage(page); + await loginPage.loginUser( + { username, password: username }, + { + withNavigation: true, + waitForLoading: true + } + ); + }); + + test.afterEach(async () => { + await siteApiAdmin.addSiteMember(sitePrivate, username, Site.RoleEnum.SiteCollaborator); + }); + + test.afterAll(async () => { + await siteApiAdmin.deleteSites([sitePrivate]); + }); + + test('[C213173] on Recent Files', async ({ recentFilesPage }) => { + await recentFilesPage.navigate(); + expect(await recentFilesPage.dataTable.getRowsCount(), 'Incorrect number of items').toBe(2); + await siteApiAdmin.deleteSiteMember(sitePrivate, username); + await recentFilesPage.reload(); + expect(await recentFilesPage.dataTable.isEmpty(), 'Items are still displayed').toBe(true); + }); + + test('[C213227] on Favorites', async ({ favoritePage }) => { + await favoritePage.navigate(); + expect(await favoritePage.dataTable.getRowsCount(), 'Incorrect number of items').toBe(2); + await siteApiAdmin.deleteSiteMember(sitePrivate, username); + await favoritePage.reload(); + expect(await favoritePage.dataTable.isEmpty(), 'Items are still displayed').toBe(true); + }); + + test('[C213116] on Shared Files', async ({ sharedPage }) => { + await sharedPage.navigate(); + expect(await sharedPage.dataTable.getRowsCount(), 'Incorrect number of items').toBe(2); + await siteApiAdmin.deleteSiteMember(sitePrivate, username); + await sharedPage.reload(); + expect(await sharedPage.dataTable.getRowsCount(), 'Incorrect number of items').toBe(0); + }); + + test('[C290122] on Search Results', async ({ personalFiles, searchPage }) => { + await personalFiles.acaHeader.searchButton.click(); + await searchPage.searchInput.searchButton.click(); + await searchPage.searchOverlay.checkFilesAndFolders(); + await searchPage.searchOverlay.searchFor(fileName); + await searchPage.dataTable.spinnerWaitForReload(); + + expect(await searchPage.dataTable.getRowsCount(), 'Incorrect number of items').toBe(2); + + await siteApiAdmin.deleteSiteMember(sitePrivate, username); + + await searchPage.reload(); + await searchPage.dataTable.spinnerWaitForReload(); + + expect(await searchPage.dataTable.getRowsCount(), 'Incorrect number of items').toBe(0); + }); + }); + + test.describe(`Location column is empty if user doesn't have permissions on the file's parent folder`, () => { + const sitePrivate = `private-${Utils.random()}`; + const fileName = `file-${Utils.random()}.txt`; + let adminSiteApiActions: SitesApi; + + test.beforeAll(async () => { + test.setTimeout(timeouts.webServer); + const userFavoritesApi = await FavoritesPageApi.initialize(username, username); + const userShareActionApi = await SharedLinksApi.initialize(username, username); + const userNodeActionApi = await NodesApi.initialize(username, username); + adminSiteApiActions = await SitesApi.initialize('admin'); + + await adminSiteApiActions.createSite(sitePrivate, Site.VisibilityEnum.PRIVATE); + await adminSiteApiActions.addSiteMember(sitePrivate, username, Site.RoleEnum.SiteCollaborator); + const docLibId = await adminSiteApiActions.getDocLibId(sitePrivate); + const fileId = (await userNodeActionApi.createFile(fileName, docLibId)).entry.id; + await userFavoritesApi.addFavoriteById('file', fileId); + + await userShareActionApi.shareFileById(fileId); + await userShareActionApi.waitForFilesToBeShared([fileId]); + await adminSiteApiActions.deleteSiteMember(sitePrivate, username); + }); + + test.beforeEach(async ({ page }) => { + const loginPage = new LoginPage(page); + await loginPage.loginUser( + { username, password: username }, + { + withNavigation: true, + waitForLoading: true + } + ); + }); + + test.afterAll(async () => { + await adminSiteApiActions.deleteSites([sitePrivate]); + }); + + test('[C213178] on Recent Files', async ({ recentFilesPage }) => { + await recentFilesPage.navigate(); + expect(await recentFilesPage.dataTable.getRowsCount(), 'Incorrect number of items').toBe(2); + expect(await recentFilesPage.dataTable.getItemLocationText(fileName)).toEqual('Unknown'); + }); + + test('[C213672] on Favorites', async ({ favoritePage }) => { + await favoritePage.navigate(); + expect(await favoritePage.dataTable.getRowsCount(), 'Incorrect number of items').toBe(2); + expect(await favoritePage.dataTable.getItemLocationText(fileName)).toEqual('Unknown'); + }); + + test(`[C213668] on Shared Files`, async ({ sharedPage }) => { + await sharedPage.navigate(); + expect(await sharedPage.dataTable.getRowsCount(), 'Incorrect number of items').toBe(2); + expect(await sharedPage.dataTable.getItemLocationText(fileName)).toEqual('Unknown'); + }); + + test('[C306868] on Search results', async ({ personalFiles, searchPage }) => { + await personalFiles.acaHeader.searchButton.click(); + await searchPage.searchInput.searchButton.click(); + await searchPage.searchOverlay.checkFilesAndFolders(); + await searchPage.searchOverlay.searchFor(fileName); + await searchPage.dataTable.spinnerWaitForReload(); + + expect(await searchPage.dataTable.getRowsCount(), 'Incorrect number of items').toBe(2); + expect(await searchPage.dataTable.getItemLocationText(fileName)).toEqual('Unknown'); + }); + }); +}); diff --git a/e2e/playwright/list-views/src/tests/sort-list.spec.ts b/e2e/playwright/list-views/src/tests/sort-list.spec.ts new file mode 100644 index 0000000000..ac61d43280 --- /dev/null +++ b/e2e/playwright/list-views/src/tests/sort-list.spec.ts @@ -0,0 +1,265 @@ +/*! + * 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, + FavoritesPageApi, + FileActionsApi, + NodesApi, + PersonalFilesPage, + TEST_FILES, + Utils, + test, + timeouts +} from '@alfresco/playwright-shared'; + +async function getSortState(myPersonalFiles: PersonalFilesPage): Promise<{ [key: string]: string }> { + return { + sortingColumn: await myPersonalFiles.dataTable.getSortedColumnHeaderText(), + sortingOrder: await myPersonalFiles.dataTable.getSortingOrder(), + firstElement: await myPersonalFiles.dataTable.getFirstElementDetail('Name') + }; +} + +test.describe('Remember sorting', () => { + const user1 = `userSort1-${Utils.random()}`; + const user2 = `userSort2-${Utils.random()}`; + const pdfFileNames = [...new Array(14).fill(100)].map((v, i) => `file-${v + i}.pdf`); + const jpgFileNames = [...new Array(12).fill(114)].map((v, i) => `file-${v + i}.jpg`); + const folderToMove = `folder1`; + const folderToContain = `folder2`; + const uiCreatedFolder = `folder3`; + + const testData = { + user1: { + files: { + jpg: jpgFileNames, + pdf: pdfFileNames + } + }, + user2: { + files: [pdfFileNames[0], jpgFileNames[0]] + } + }; + + let initialSortState: { [key: string]: string }; + let nodeActionUser1: NodesApi; + + test.beforeAll(async () => { + test.setTimeout(timeouts.extendedTest); + const apiClientFactory = new ApiClientFactory(); + await apiClientFactory.setUpAcaBackend('admin'); + await apiClientFactory.createUser({ username: user1 }); + await apiClientFactory.createUser({ username: user2 }); + const fileActionUser1 = await FileActionsApi.initialize(user1, user1); + const fileActionUser2 = await FileActionsApi.initialize(user2, user2); + const favoritesActions = await FavoritesPageApi.initialize(user1, user1); + nodeActionUser1 = await NodesApi.initialize(user1, user1); + const filesIdsUser1: { [key: string]: string } = {}; + const filesIdsUser2: { [key: string]: string } = {}; + await Promise.all( + testData.user1.files.pdf.map( + async (i) => (filesIdsUser1[i] = (await fileActionUser1.uploadFileWithRename(TEST_FILES.PDF.path, i, '-my-')).entry.id) + ) + ); + await Promise.all( + testData.user1.files.jpg.map( + async (i) => (filesIdsUser1[i] = (await fileActionUser1.uploadFileWithRename(TEST_FILES.JPG_FILE.path, i, '-my-')).entry.id) + ) + ); + await Promise.all( + testData.user2.files.map( + async (i) => (filesIdsUser2[i] = (await fileActionUser2.uploadFileWithRename(TEST_FILES.PDF.path, i, '-my-')).entry.id) + ) + ); + await favoritesActions.addFavoritesByIds('file', [filesIdsUser1[pdfFileNames[0]], filesIdsUser1[pdfFileNames[1]]]); + }); + + test.beforeEach(async ({ loginPage, personalFiles }) => { + await NodesApi.initialize(user1, user1); + await loginPage.loginUser( + { username: user1, password: user1 }, + { + withNavigation: true, + waitForLoading: true + } + ); + await personalFiles.dataTable.sortBy('Name', 'asc'); + await personalFiles.dataTable.spinnerWaitForReload(); + initialSortState = await getSortState(personalFiles); + }); + + test.afterAll(async () => { + nodeActionUser1 = await NodesApi.initialize(user1, user1); + const nodeActionUser2 = await NodesApi.initialize(user2, user2); + await nodeActionUser1.deleteCurrentUserNodes(); + await nodeActionUser2.deleteCurrentUserNodes(); + }); + + test('[C261136] Sort order is retained when navigating to another part of the app', async ({ personalFiles, favoritePage }) => { + await personalFiles.dataTable.sortBy('Name', 'desc'); + await personalFiles.dataTable.spinnerWaitForReload(); + + const expectedSortData = await getSortState(personalFiles); + expect(expectedSortData).not.toEqual(initialSortState); + + await favoritePage.navigate(); + await personalFiles.navigate(); + + const actualSortData = await getSortState(personalFiles); + expect(actualSortData).toEqual(expectedSortData); + }); + + test('[C589205] Size sort order is retained after viewing a file and closing the viewer', async ({ personalFiles }) => { + await personalFiles.dataTable.sortBy('Size', 'desc'); + await personalFiles.dataTable.spinnerWaitForReload(); + const expectedSortData = await getSortState(personalFiles); + + await personalFiles.dataTable.performClickFolderOrFileToOpen(expectedSortData.firstElement); + await personalFiles.viewer.closeButtonLocator.click(); + await personalFiles.waitForPageLoad(); + + const actualSortData = await getSortState(personalFiles); + expect(actualSortData).toEqual(expectedSortData); + }); + + test('[C261153] Sort order should be remembered separately on each list view', async ({ personalFiles, favoritePage }) => { + await personalFiles.dataTable.sortBy('Size', 'desc'); + await personalFiles.dataTable.spinnerWaitForReload(); + const personalFilesSortData = await getSortState(personalFiles); + + await favoritePage.navigate(); + await favoritePage.dataTable.sortBy('Name', 'asc'); + await favoritePage.dataTable.spinnerWaitForReload(); + + const favouritesSortData = await getSortState(personalFiles); + expect(favouritesSortData).not.toEqual(personalFilesSortData); + + await personalFiles.navigate(); + const personalFilesSortDataAfterFavSort = await getSortState(personalFiles); + expect(personalFilesSortDataAfterFavSort).toEqual(personalFilesSortData); + }); + + test('[C261147] Sort order is retained when user changes the page from pagination', async ({ personalFiles }) => { + const lastFileInArray = testData.user1.files.jpg.slice(-1).pop(); + const firstFileInArray = testData.user1.files.pdf[0]; + + await personalFiles.pagination.clickOnNextPage(); + await personalFiles.dataTable.spinnerWaitForReload(); + + let expectedPersonalFilesSortDataPage2 = { + sortingColumn: 'Name', + sortingOrder: 'asc', + firstElement: lastFileInArray + }; + + let currentPersonalFilesSortDataPage2 = await getSortState(personalFiles); + expect(currentPersonalFilesSortDataPage2).toEqual(expectedPersonalFilesSortDataPage2); + + await personalFiles.dataTable.sortBy('Name', 'desc'); + await personalFiles.dataTable.spinnerWaitForReload(); + expectedPersonalFilesSortDataPage2 = { + sortingColumn: 'Name', + sortingOrder: 'desc', + firstElement: firstFileInArray + }; + + currentPersonalFilesSortDataPage2 = await getSortState(personalFiles); + expect(expectedPersonalFilesSortDataPage2).toEqual(currentPersonalFilesSortDataPage2); + }); + + test.describe('Folder actions', () => { + test.beforeAll(async () => { + const folderIds: { [key: string]: string } = {}; + folderIds[folderToContain] = (await nodeActionUser1.createFolder(folderToContain)).entry.id; + folderIds[folderToMove] = (await nodeActionUser1.createFolder(folderToMove)).entry.id; + }); + + test('[C261138] Sort order is retained when creating a new folder', async ({ personalFiles }) => { + await personalFiles.dataTable.sortBy('Name', 'desc'); + await personalFiles.dataTable.spinnerWaitForReload(); + + const expectedSortData = { + sortingColumn: await personalFiles.dataTable.getSortedColumnHeaderText(), + sortingOrder: await personalFiles.dataTable.getSortingOrder(), + firstElement: uiCreatedFolder + }; + + await personalFiles.selectCreateFolder(); + await personalFiles.folderDialog.createNewFolderDialog(uiCreatedFolder); + await personalFiles.dataTable.isItemPresent(uiCreatedFolder); + + const actualSortData = await getSortState(personalFiles); + expect(actualSortData).toEqual(expectedSortData); + }); + + test('[C261139] Sort order is retained when moving a file', async ({ personalFiles }) => { + const expectedSortData = { + sortingColumn: await personalFiles.dataTable.getSortedColumnHeaderText(), + sortingOrder: await personalFiles.dataTable.getSortingOrder(), + firstElement: folderToContain + }; + await personalFiles.copyOrMoveContentInDatatable([folderToMove], folderToContain, 'Move'); + await personalFiles.dataTable.spinnerWaitForReload(); + const actualSortData = await getSortState(personalFiles); + expect(actualSortData).toEqual(expectedSortData); + }); + }); + + test.describe('User Tests', () => { + test('[C261137] Size sort order is retained when user logs out and logs back in', async ({ personalFiles, loginPage }) => { + await personalFiles.dataTable.sortBy('Name', 'desc'); + await personalFiles.dataTable.spinnerWaitForReload(); + const expectedSortData = await getSortState(personalFiles); + expect(expectedSortData).not.toEqual(initialSortState); + + await loginPage.logoutUser(); + await FileActionsApi.initialize(user1, user1); + await loginPage.loginUser({ username: user1, password: user1 }, { withNavigation: true, waitForLoading: true }); + + const actualSortData = await getSortState(personalFiles); + expect(actualSortData).toEqual(expectedSortData); + }); + + test('[C261150] Sort order is not retained between different users', async ({ personalFiles, loginPage }) => { + await personalFiles.dataTable.sortBy('Size', 'asc'); + await personalFiles.dataTable.spinnerWaitForReload(); + const expectedSortData = await getSortState(personalFiles); + + await loginPage.logoutUser(); + await FileActionsApi.initialize(user2, user2); + await loginPage.loginUser( + { username: user2, password: user2 }, + { + withNavigation: true, + waitForLoading: true + } + ); + + const actualSortData = await getSortState(personalFiles); + expect(actualSortData).not.toEqual(expectedSortData); + }); + }); +}); diff --git a/e2e/playwright/list-views/src/tests/trash-admin.spec.ts b/e2e/playwright/list-views/src/tests/trash-admin.spec.ts new file mode 100755 index 0000000000..b84eda52e1 --- /dev/null +++ b/e2e/playwright/list-views/src/tests/trash-admin.spec.ts @@ -0,0 +1,63 @@ +/*! + * 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, NodesApi, Utils, getUserState, test } from '@alfresco/playwright-shared'; + +test.use({ storageState: getUserState('admin') }); +test.describe('Trash admin', () => { + const folderAdmin = `deleteFolder-${Utils.random()}`; + let folderAdminId: string; + let adminApiActions: NodesApi; + + test.beforeAll(async () => { + try { + const apiClientFactory = new ApiClientFactory(); + await apiClientFactory.setUpAcaBackend('admin'); + adminApiActions = await NodesApi.initialize('admin'); + folderAdminId = (await adminApiActions.createFolder(folderAdmin)).entry.id; + await adminApiActions.deleteNodeById(folderAdminId, false); + } catch (error) { + console.error(`----- beforeAll failed : ${error}`); + } + }); + + test.afterAll(async () => { + try { + await adminApiActions.deleteDeletedNode(folderAdminId); + } catch (error) { + console.error(`----- afterAll failed : ${error}`); + } + }); + + test.describe('as admin', () => { + test('[C213217] has the correct columns', async ({ trashPage }) => { + await trashPage.navigate(); + const expectedColumns = ['Name', 'Location', 'Size', 'Deleted', 'Deleted by']; + const actualColumns = await trashPage.dataTable.getColumnHeaders(); + + expect(actualColumns).toEqual(expectedColumns); + }); + }); +}); diff --git a/e2e/protractor/protractor.excludes.json b/e2e/protractor/protractor.excludes.json index c96b1052fa..3e61b1fd1b 100644 --- a/e2e/protractor/protractor.excludes.json +++ b/e2e/protractor/protractor.excludes.json @@ -1,5 +1,4 @@ { - "C589205": "https://alfresco.atlassian.net/browse/ACA-4353", "C261153": "https://alfresco.atlassian.net/browse/AAE-7517", "C306959": "https://alfresco.atlassian.net/browse/ACA-4620", "C213134": "temp, see https://alfresco.atlassian.net/browse/ACS-5189", diff --git a/e2e/protractor/suites/list-views/empty-list.test.ts b/e2e/protractor/suites/list-views/empty-list.test.ts index cdcc0a09d2..e620c61cb4 100755 --- a/e2e/protractor/suites/list-views/empty-list.test.ts +++ b/e2e/protractor/suites/list-views/empty-list.test.ts @@ -37,13 +37,6 @@ describe('Empty list views', () => { await loginPage.loginWith(username); }); - it('[C217099] empty My Libraries', async () => { - await page.goToMyLibraries(); - expect(await dataTable.isEmpty()).toBe(true, 'list is not empty'); - expect(await dataTable.getEmptyStateTitle()).toContain(`You aren't a member of any File Libraries yet`); - expect(await dataTable.getEmptyStateSubtitle()).toContain('Join libraries to upload, view, and share files.'); - }); - it('[C289911] empty Favorite Libraries', async () => { await page.goToFavoriteLibraries(); expect(await dataTable.isEmpty()).toBe(true, 'list is not empty'); @@ -65,14 +58,6 @@ describe('Empty list views', () => { expect(await dataTable.getEmptyStateSubtitle()).toContain('Favorite items that you want to easily find later.'); }); - it('[C280134] empty Trash', async () => { - await page.clickTrash(); - expect(await dataTable.isEmpty()).toBe(true, 'list is not empty'); - expect(await dataTable.getEmptyStateTitle()).toContain('Trash is empty'); - expect(await dataTable.getEmptyListText()).toContain('Items you delete are moved to the Trash.'); - expect(await dataTable.getEmptyListText()).toContain('Empty Trash to permanently delete items.'); - }); - it('[C280111] Favorites - pagination controls not displayed', async () => { await page.clickFavorites(); expect(await pagination.isRangePresent()).toBe(false, 'Range is present'); @@ -133,21 +118,6 @@ describe('Empty list views', () => { expect(await pagination.isNextButtonPresent()).toBe(false, 'Next button is present'); }); - it('[C290123] Search results - pagination controls not displayed', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - /* cspell:disable-next-line */ - await searchInput.searchFor('qwertyuiop'); - await dataTable.waitForBody(); - - expect(await pagination.isRangePresent()).toBe(false, 'Range is present'); - expect(await pagination.isMaxItemsPresent()).toBe(false, 'Max items is present'); - expect(await pagination.isCurrentPagePresent()).toBe(false, 'Current page is present'); - expect(await pagination.isTotalPagesPresent()).toBe(false, 'Total pages is present'); - expect(await pagination.isPreviousButtonPresent()).toBe(false, 'Previous button is present'); - expect(await pagination.isNextButtonPresent()).toBe(false, 'Next button is present'); - }); - it('[C290020] Empty Search results - Libraries', async () => { await page.goToMyLibraries(); await toolbar.clickSearchIconButton(); @@ -160,17 +130,4 @@ describe('Empty list views', () => { expect(await dataTable.isEmpty()).toBe(true, 'list is not empty'); expect(await dataTable.emptySearchText.getText()).toContain('Your search returned 0 results'); }); - - it('[C290031] Empty Search results - Files / Folders', async () => { - await page.clickPersonalFiles(); - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkFilesAndFolders(); - /* cspell:disable-next-line */ - await searchInput.searchFor('qwertyuiop'); - await dataTable.waitForBody(); - - expect(await dataTable.isEmpty()).toBe(true, 'list is not empty'); - expect(await dataTable.emptySearchText.getText()).toContain('Your search returned 0 results'); - }); }); diff --git a/e2e/protractor/suites/list-views/generic-errors.test.ts b/e2e/protractor/suites/list-views/generic-errors.test.ts deleted file mode 100755 index 71b6eead7b..0000000000 --- a/e2e/protractor/suites/list-views/generic-errors.test.ts +++ /dev/null @@ -1,104 +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 { browser } from 'protractor'; -import { AdminActions, UserActions, LoginPage, BrowsingPage, Utils, RepoClient } from '@alfresco/aca-testing-shared'; -import { Logger } from '@alfresco/adf-testing'; - -describe('Generic errors', () => { - const username = `user-${Utils.random()}`; - const username2 = `user2-${Utils.random()}`; - - const parent = `folder-${Utils.random()}`; - let parentId: string; - const file1 = `file1-${Utils.random()}.txt`; - let file1Id: string; - const file2 = `file2-${Utils.random()}.txt`; - - const apis = { - user: new RepoClient(username, username) - }; - - const loginPage = new LoginPage(); - const page = new BrowsingPage(); - const { dataTable } = page; - - const adminApiActions = new AdminActions(); - const userActions = new UserActions(); - - beforeAll(async () => { - try { - await adminApiActions.createUser({ username }); - await adminApiActions.createUser({ username: username2 }); - await userActions.login(username, username); - - parentId = await apis.user.createFolder(parent); - file1Id = await apis.user.createFile(file1, parentId); - await apis.user.nodes.createFile(file2, parentId); - - await loginPage.loginWith(username); - } catch (error) { - Logger.error(`----- beforeAll failed : ${error}`); - } - }); - - afterAll(async () => { - await userActions.login(username, username); - await userActions.deleteNodes([parentId]); - await userActions.emptyTrashcan(); - }); - - it('[C217313] File / folder not found', async () => { - await page.clickPersonalFilesAndWait(); - await dataTable.doubleClickOnRowByName(parent); - await dataTable.doubleClickOnRowByName(file1); - const URL = await browser.getCurrentUrl(); - await userActions.deleteNodes([file1Id], false); - await browser.get(URL); - - expect(await page.genericError.isDisplayed()).toBe(true, 'Generic error page not displayed'); - expect(await page.genericErrorTitle.getText()).toContain(`This item no longer exists or you don't have permission to view it.`); - }); - - it('[C217315] Invalid URL', async () => { - await page.load('/invalid page'); - - expect(await page.genericError.isDisplayed()).toBe(true, 'Generic error page not displayed'); - expect(await page.genericErrorTitle.getText()).toContain(`This item no longer exists or you don't have permission to view it.`); - }); - - it('[C217314] Permission denied', async () => { - await page.clickPersonalFilesAndWait(); - await dataTable.doubleClickOnRowByName(parent); - await dataTable.doubleClickOnRowByName(file2); - const URL = await browser.getCurrentUrl(); - await loginPage.loginWith(username2); - await browser.get(URL); - - expect(await page.genericError.isDisplayed()).toBe(true, 'Generic error page not displayed'); - expect(await page.genericErrorTitle.getText()).toContain(`This item no longer exists or you don't have permission to view it.`); - - await loginPage.loginWith(username); - }); -}); diff --git a/e2e/protractor/suites/list-views/permissions.test.ts b/e2e/protractor/suites/list-views/permissions.test.ts deleted file mode 100755 index b79ed7001b..0000000000 --- a/e2e/protractor/suites/list-views/permissions.test.ts +++ /dev/null @@ -1,177 +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, UserActions, SITE_VISIBILITY, SITE_ROLES, LoginPage, BrowsingPage, Utils, RepoClient } from '@alfresco/aca-testing-shared'; - -describe('Special permissions', () => { - const username = `user-${Utils.random()}`; - - const apis = { - user: new RepoClient(username, username) - }; - - const loginPage = new LoginPage(); - const page = new BrowsingPage(); - const { dataTable, toolbar } = page; - const { searchInput } = page.pageLayoutHeader; - - const adminApiActions = new AdminActions(); - const userActions = new UserActions(); - - beforeAll(async () => { - await adminApiActions.createUser({ username }); - }); - - describe('file not displayed if user no longer has permissions on it', () => { - const sitePrivate = `private-${Utils.random()}`; - const fileName = `file-${Utils.random()}.txt`; - let fileId: string; - - beforeAll(async () => { - await adminApiActions.login(); - await adminApiActions.sites.createSite(sitePrivate, SITE_VISIBILITY.PRIVATE); - await adminApiActions.sites.addSiteMember(sitePrivate, username, SITE_ROLES.SITE_COLLABORATOR.ROLE); - const docLibId = await adminApiActions.sites.getDocLibId(sitePrivate); - fileId = (await adminApiActions.nodes.createFile(fileName, docLibId)).entry.id; - await apis.user.favorites.addFavoriteById('file', fileId); - - await adminApiActions.login(); - await adminApiActions.shareNodes([fileId]); - await apis.user.nodes.updateNodeContent(fileId, 'edited by user'); - - await apis.user.search.waitForApi(username, { expect: 1 }); - - await adminApiActions.login(); - await adminApiActions.shared.waitForFilesToBeShared([fileId]); - - await loginPage.loginWith(username); - }); - - afterEach(async () => { - await adminApiActions.sites.addSiteMember(sitePrivate, username, SITE_ROLES.SITE_COLLABORATOR.ROLE); - }); - - afterAll(async () => { - await adminApiActions.sites.deleteSite(sitePrivate); - }); - - it('[C213173] on Recent Files', async () => { - await page.clickRecentFilesAndWait(); - expect(await dataTable.getRowsCount()).toBe(1, 'Incorrect number of items'); - await adminApiActions.sites.deleteSiteMember(sitePrivate, username); - await page.refresh(); - expect(await dataTable.isEmpty()).toBe(true, 'Items are still displayed'); - }); - - it('[C213227] on Favorites', async () => { - await page.clickFavoritesAndWait(); - expect(await dataTable.getRowsCount()).toBe(1, 'Incorrect number of items'); - await adminApiActions.sites.deleteSiteMember(sitePrivate, username); - await page.refresh(); - expect(await dataTable.isEmpty()).toBe(true, 'Items are still displayed'); - }); - - it('[C213116] on Shared Files', async () => { - await page.clickSharedFilesAndWait(); - expect(await dataTable.isItemPresent(fileName)).toBe(true, `${fileName} not displayed`); - await adminApiActions.sites.deleteSiteMember(sitePrivate, username); - await page.refresh(); - expect(await dataTable.isItemPresent(fileName)).toBe(false, `${fileName} is displayed`); - }); - - it('[C290122] on Search Results', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkFilesAndFolders(); - await searchInput.searchFor(fileName); - await dataTable.waitForBody(); - - expect(await dataTable.isItemPresent(fileName)).toBe(true, `${fileName} is not displayed`); - - await adminApiActions.sites.deleteSiteMember(sitePrivate, username); - - await searchInput.clickSearchButton(); - await searchInput.checkFilesAndFolders(); - await searchInput.searchFor(fileName); - await dataTable.waitForBody(); - - expect(await dataTable.isItemPresent(fileName)).toBe(false, `${fileName} is displayed`); - }); - }); - - describe(`Location column is empty if user doesn't have permissions on the file's parent folder`, () => { - const sitePrivate = `private-${Utils.random()}`; - const fileName = `file-${Utils.random()}.txt`; - let fileId; - - beforeAll(async () => { - await adminApiActions.sites.createSite(sitePrivate, SITE_VISIBILITY.PRIVATE); - await adminApiActions.sites.addSiteMember(sitePrivate, username, SITE_ROLES.SITE_COLLABORATOR.ROLE); - const docLibId = await adminApiActions.sites.getDocLibId(sitePrivate); - fileId = (await apis.user.nodes.createFile(fileName, docLibId)).entry.id; - await apis.user.favorites.addFavoriteById('file', fileId); - - await userActions.login(username, username); - await userActions.shareNodes([fileId]); - await apis.user.shared.waitForFilesToBeShared([fileId]); - - await apis.user.search.waitForApi(username, { expect: 1 }); - await adminApiActions.sites.deleteSiteMember(sitePrivate, username); - await loginPage.loginWith(username); - }); - - afterAll(async () => { - await adminApiActions.sites.deleteSite(sitePrivate); - }); - - it('[C213178] on Recent Files', async () => { - await page.clickRecentFilesAndWait(); - expect(await dataTable.getRowsCount()).toBe(1, 'Incorrect number of items'); - expect(await dataTable.getItemLocation(fileName)).toEqual('Unknown'); - }); - - it('[C213672] on Favorites', async () => { - await page.clickFavoritesAndWait(); - expect(await dataTable.getRowsCount()).toBe(1, 'Incorrect number of items'); - expect(await dataTable.getItemLocation(fileName)).toEqual('Unknown'); - }); - - it(`[C213668] on Shared Files`, async () => { - await page.clickSharedFilesAndWait(); - expect(await dataTable.isItemPresent(fileName)).toBe(true, `${fileName} not displayed`); - expect(await dataTable.getItemLocation(fileName)).toEqual('Unknown'); - }); - - it('[C306868] on Search results', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - await searchInput.checkFilesAndFolders(); - await searchInput.searchFor(fileName); - await dataTable.waitForBody(); - - expect(await dataTable.isItemPresent(fileName)).toBe(true, `${fileName} is not displayed`); - expect(await dataTable.getItemLocation(fileName)).toEqual('Unknown'); - }); - }); -}); diff --git a/e2e/protractor/suites/list-views/sort-list.test.ts b/e2e/protractor/suites/list-views/sort-list.test.ts deleted file mode 100644 index d826938b17..0000000000 --- a/e2e/protractor/suites/list-views/sort-list.test.ts +++ /dev/null @@ -1,348 +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, RepoClient, FILES, BrowsingPage, DataTable, CreateOrEditFolderDialog } from '@alfresco/aca-testing-shared'; -import { BrowserActions, ContentNodeSelectorDialogPage, DocumentListPage, PaginationPage, ViewerPage } from '@alfresco/adf-testing'; - -describe('Remember sorting', () => { - interface NodesIds { - [index: string]: string; - } - - const timestamp = new Date().getTime(); - const user1 = `user1-${timestamp}`; - const user2 = `user2-${timestamp}`; - const pdfFileNames = [...new Array(14).fill(100)].map((v, i) => `file-${v + i}.pdf`); - const jpgFileNames = [...new Array(12).fill(114)].map((v, i) => `file-${v + i}.jpg`); - const folderToMove = `folder1`; - const folderToContain = `folder2`; - const uiCreatedFolder = `folder3`; - const filesIdsUser1: NodesIds = {}; - const filesIdsUser2: NodesIds = {}; - const folderIds: NodesIds = {}; - - const testData = { - user1: { - files: { - jpg: jpgFileNames, - pdf: pdfFileNames - } - }, - user2: { - files: [pdfFileNames[0], jpgFileNames[0]] - } - }; - - let initialSortState: { - sortingColumn: string; - sortingOrder: string; - firstElement: string; - }; - - const apis = { - user1: new RepoClient(user1, user1), - user2: new RepoClient(user2, user2) - }; - - const loginPage = new LoginPage(); - const browsingPage = new BrowsingPage(); - const dataTable = new DataTable(); - const documentListPage = new DocumentListPage(); - const viewerPage = new ViewerPage(); - const adminApiActions = new AdminActions(); - const createDialog = new CreateOrEditFolderDialog(); - const contentNodeSelectorDialogPage = new ContentNodeSelectorDialogPage(); - const paginationPage = new PaginationPage(); - - beforeAll(async () => { - await adminApiActions.createUser({ username: user1 }); - await adminApiActions.createUser({ username: user2 }); - await Promise.all( - testData.user1.files.pdf.map( - async (i) => (filesIdsUser1[i] = (await apis.user1.upload.uploadFileWithRename(FILES.pdfFile, '-my-', i)).entry.id) - ) - ); - await Promise.all( - testData.user1.files.jpg.map( - async (i) => (filesIdsUser1[i] = (await apis.user1.upload.uploadFileWithRename(FILES.jpgFile, '-my-', i)).entry.id) - ) - ); - await Promise.all( - testData.user2.files.map(async (i) => (filesIdsUser2[i] = (await apis.user2.upload.uploadFileWithRename(FILES.pdfFile, '-my-', i)).entry.id)) - ); - await apis.user1.favorites.addFavoritesByIds('file', [filesIdsUser1[pdfFileNames[0]], filesIdsUser1[pdfFileNames[1]]]); - await loginPage.loginWith(user1); - }); - - beforeEach(async () => { - await browsingPage.clickPersonalFilesAndWait(); - await dataTable.sortBy('Name', 'asc'); - await dataTable.waitForBody(); - initialSortState = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - }); - - afterAll(async () => { - await Promise.all(Object.keys(filesIdsUser1).map((i) => apis.user1.nodes.deleteNodeById(filesIdsUser1[i]))); - await Promise.all(Object.keys(filesIdsUser2).map((i) => apis.user2.nodes.deleteNodeById(filesIdsUser2[i]))); - }); - - it('[C261136] Sort order is retained when navigating to another part of the app', async () => { - await dataTable.sortBy('Name', 'desc'); - await dataTable.waitForFirstElementToChange(initialSortState.firstElement); - await dataTable.waitForBody(); - - const expectedSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - expect(expectedSortData).not.toEqual(initialSortState); - - await browsingPage.clickFavorites(); - await browsingPage.clickPersonalFilesAndWait(); - - const actualSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - expect(actualSortData).toEqual(expectedSortData); - }); - - it('[C261137] Size sort order is retained when user logs out and logs back in', async () => { - await dataTable.sortBy('Name', 'desc'); - await dataTable.waitForFirstElementToChange(initialSortState.firstElement); - await dataTable.waitForBody(); - - const expectedSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - expect(expectedSortData).not.toEqual(initialSortState); - - await browsingPage.signOut(); - await loginPage.loginWith(user1); - - const actualSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - expect(actualSortData).toEqual(expectedSortData); - }); - - describe('Folder actions', () => { - beforeAll(async () => { - folderIds[folderToContain] = (await apis.user1.nodes.createFolder(folderToContain)).entry.id; - folderIds[folderToMove] = (await apis.user1.nodes.createFolder(folderToMove)).entry.id; - }); - - afterAll(async () => { - folderIds[uiCreatedFolder] = await apis.user1.nodes.getNodeIdFromParent(uiCreatedFolder, '-my-'); - await Promise.all(Object.keys(folderIds).map((i) => apis.user1.nodes.deleteNodeById(folderIds[i]))); - }); - - it('[C261138] Sort order is retained when creating a new folder', async () => { - await dataTable.sortBy('Name', 'desc'); - await dataTable.waitForFirstElementToChange(initialSortState.firstElement); - await dataTable.waitForBody(); - - const expectedSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: uiCreatedFolder - }; - - await browsingPage.sidenav.openCreateFolderDialog(); - await createDialog.waitForDialogToOpen(); - await createDialog.enterName(uiCreatedFolder); - await BrowserActions.click(createDialog.createButton); - await createDialog.waitForDialogToClose(); - await documentListPage.dataTable.checkRowContentIsDisplayed(uiCreatedFolder); - - const actualSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - expect(actualSortData).toEqual(expectedSortData); - }); - - it('[C261139] Sort order is retained when moving a file', async () => { - const expectedSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: folderToContain - }; - - await browsingPage.dataTable.rightClickOnItem(folderToMove); - await dataTable.menu.clickMenuItem('Move'); - await contentNodeSelectorDialogPage.clickContentNodeSelectorResult(folderToContain); - await contentNodeSelectorDialogPage.clickMoveCopyButton(); - await documentListPage.dataTable.checkRowContentIsNotDisplayed(folderToMove); - - const actualSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - expect(actualSortData).toEqual(expectedSortData); - }); - }); - - it('[C589205] Size sort order is retained after viewing a file and closing the viewer', async () => { - await dataTable.sortBy('Size', 'desc'); - await dataTable.waitForFirstElementToChange(initialSortState.firstElement); - await dataTable.waitForBody(); - - const expectedSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - await dataTable.doubleClickOnRowByName(expectedSortData.firstElement); - await viewerPage.clickCloseButton(); - await browsingPage.clickPersonalFilesAndWait(); - - const actualSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - expect(actualSortData).toEqual(expectedSortData); - }); - - it('[C261153] Sort order should be remembered separately on each list view', async () => { - await dataTable.sortBy('Size', 'desc'); - await dataTable.waitForFirstElementToChange(initialSortState.firstElement); - await dataTable.waitForBody(); - - const personalFilesSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - await browsingPage.clickFavoritesAndWait(); - await dataTable.sortBy('Name', 'asc'); - await dataTable.waitForFirstElementToChange(personalFilesSortData.firstElement); - await dataTable.waitForBody(); - - const favouritesSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - expect(favouritesSortData).not.toEqual(personalFilesSortData); - - await browsingPage.clickPersonalFilesAndWait(); - - const personalFilesSortDataAfterFavSort = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - expect(personalFilesSortDataAfterFavSort).toEqual(personalFilesSortData); - }); - - it('[C261147] Sort order is retained when user changes the page from pagination', async () => { - const lastFileInArray = testData.user1.files.jpg.slice(-1).pop(); - const firstFileInArray = testData.user1.files.pdf[0]; - - await paginationPage.clickOnNextPage(); - await dataTable.waitForBody(); - - let expectedPersonalFilesSortDataPage2 = { - sortingColumn: 'Name', - sortingOrder: 'asc', - firstElement: lastFileInArray - }; - - let currentPersonalFilesSortDataPage2 = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - expect(currentPersonalFilesSortDataPage2).toEqual(expectedPersonalFilesSortDataPage2); - - await dataTable.sortBy('Name', 'desc'); - await dataTable.waitForFirstElementToChange(currentPersonalFilesSortDataPage2.firstElement); - await dataTable.waitForBody(); - - expectedPersonalFilesSortDataPage2 = { - sortingColumn: 'Name', - sortingOrder: 'desc', - firstElement: firstFileInArray - }; - - currentPersonalFilesSortDataPage2 = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - expect(expectedPersonalFilesSortDataPage2).toEqual(currentPersonalFilesSortDataPage2); - }); - - it('[C261150] Sort order is not retained between different users', async () => { - await dataTable.sortBy('Size', 'asc'); - await dataTable.waitForFirstElementToChange(initialSortState.firstElement); - await dataTable.waitForBody(); - - const expectedSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - await browsingPage.signOut(); - await loginPage.loginWith(user2); - - const actualSortData = { - sortingColumn: await dataTable.getSortedColumnHeaderText(), - sortingOrder: await dataTable.getSortingOrder(), - firstElement: await documentListPage.dataTable.getFirstElementDetail('Name') - }; - - expect(actualSortData).not.toEqual(expectedSortData); - - await browsingPage.signOut(); - }); -}); diff --git a/e2e/protractor/suites/list-views/trash.test.ts b/e2e/protractor/suites/list-views/trash.test.ts deleted file mode 100755 index b6cae2a866..0000000000 --- a/e2e/protractor/suites/list-views/trash.test.ts +++ /dev/null @@ -1,123 +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, UserActions, SITE_VISIBILITY, SITE_ROLES, LoginPage, BrowsingPage, Utils, RepoClient } from '@alfresco/aca-testing-shared'; -import { Logger } from '@alfresco/adf-testing'; - -describe('Trash', () => { - const username = `user-${Utils.random()}`; - - const siteName = `site-${Utils.random()}`; - const fileSite = `file-${Utils.random()}.txt`; - let fileSiteId: string; - - const folderAdmin = `folder-${Utils.random()}`; - let folderAdminId: string; - const fileAdmin = `file-${Utils.random()}.txt`; - let fileAdminId: string; - - const folderUser = `folder-${Utils.random()}`; - let folderUserId: string; - const fileUser = `file-${Utils.random()}.txt`; - let fileUserId: string; - - const folderDeleted = `folder-${Utils.random()}`; - let folderDeletedId: string; - const fileDeleted = `file-${Utils.random()}.txt`; - let fileDeletedId: string; - - const folderNotDeleted = `folder-${Utils.random()}`; - let folderNotDeletedId: string; - const fileInFolder = `file-${Utils.random()}.txt`; - let fileInFolderId: string; - - const apis = { - user: new RepoClient(username, username) - }; - - const loginPage = new LoginPage(); - const page = new BrowsingPage(); - const { dataTable } = page; - - const adminApiActions = new AdminActions(); - const userActions = new UserActions(); - - beforeAll(async () => { - try { - await adminApiActions.createUser({ username }); - - fileAdminId = (await adminApiActions.nodes.createFiles([fileAdmin])).entry.id; - folderAdminId = (await adminApiActions.nodes.createFolders([folderAdmin])).entry.id; - await adminApiActions.sites.createSite(siteName, SITE_VISIBILITY.PUBLIC); - await adminApiActions.sites.addSiteMember(siteName, username, SITE_ROLES.SITE_MANAGER.ROLE); - const docLibId = await adminApiActions.sites.getDocLibId(siteName); - fileSiteId = (await adminApiActions.nodes.createFile(fileSite, docLibId)).entry.id; - - await adminApiActions.nodes.deleteNodesById([fileAdminId, folderAdminId], false); - - fileUserId = (await apis.user.nodes.createFiles([fileUser])).entry.id; - folderUserId = (await apis.user.nodes.createFolders([folderUser])).entry.id; - folderDeletedId = (await apis.user.nodes.createFolder(folderDeleted)).entry.id; - fileDeletedId = (await apis.user.nodes.createFiles([fileDeleted], folderDeleted)).entry.id; - folderNotDeletedId = (await apis.user.nodes.createFolder(folderNotDeleted)).entry.id; - fileInFolderId = (await apis.user.nodes.createFiles([fileInFolder], folderNotDeleted)).entry.id; - - await apis.user.nodes.deleteNodesById([fileSiteId, fileUserId, folderUserId, fileInFolderId, fileDeletedId, folderDeletedId], false); - } catch (error) { - Logger.error(`----- beforeAll failed : ${error}`); - } - }); - - afterAll(async () => { - try { - await adminApiActions.login(); - await adminApiActions.deleteSites([siteName]); - await adminApiActions.trashcanApi.deleteDeletedNode(fileAdminId); - await adminApiActions.trashcanApi.deleteDeletedNode(folderAdminId); - - await userActions.login(username, username); - await userActions.deleteNodes([folderNotDeletedId]); - await userActions.emptyTrashcan(); - } catch (error) { - Logger.error(`----- afterAll failed : ${error}`); - } - }); - - describe('as admin', () => { - beforeAll(async () => { - await loginPage.loginWithAdmin(); - }); - - beforeEach(async () => { - await page.clickTrashAndWait(); - }); - - it('[C213217] has the correct columns', async () => { - const expectedColumns = ['Name', 'Location', 'Size', 'Deleted', 'Deleted by']; - const actualColumns = await dataTable.getColumnHeadersText(); - - expect(actualColumns).toEqual(expectedColumns); - }); - }); -}); diff --git a/projects/aca-playwright-shared/src/api/file-actions.ts b/projects/aca-playwright-shared/src/api/file-actions.ts index f2883c5383..1e67b1957c 100644 --- a/projects/aca-playwright-shared/src/api/file-actions.ts +++ b/projects/aca-playwright-shared/src/api/file-actions.ts @@ -41,7 +41,7 @@ export class FileActionsApi { return classObj; } - async uploadFile(fileLocation: string, fileName: string, parentFolderId: string): Promise { + async uploadFile(fileLocation: string, fileName: string, parentFolderId: string): Promise { const file = fs.createReadStream(fileLocation); return this.apiService.upload.uploadFile(file, '', parentFolderId, null, { name: fileName, @@ -50,7 +50,13 @@ export class FileActionsApi { }); } - async uploadFileWithRename(fileLocation: string, newName: string, parentId: string = '-my-', title: string = '', description: string = '') { + async uploadFileWithRename( + fileLocation: string, + newName: string, + parentId: string = '-my-', + title: string = '', + description: string = '' + ): Promise { const file = fs.createReadStream(fileLocation); const nodeProps = { properties: { @@ -68,10 +74,11 @@ export class FileActionsApi { return await this.apiService.upload.uploadFile(file, '', parentId, nodeProps, opts); } catch (error) { Logger.error(`${this.constructor.name} ${this.uploadFileWithRename.name}`, error); + return Promise.reject(error); } } - async lockNodes(nodeIds: string[], lockType: string = 'ALLOW_OWNER_CHANGES') { + async lockNodes(nodeIds: string[], lockType: string = 'ALLOW_OWNER_CHANGES'): Promise { try { for (const nodeId of nodeIds) { await this.apiService.nodes.lockNode(nodeId, { type: lockType }); @@ -93,7 +100,7 @@ export class FileActionsApi { async getNodeProperty(nodeId: string, property: string): Promise { try { const node = await this.getNodeById(nodeId); - return (node.entry.properties?.[property]) || ''; + return node.entry.properties?.[property] || ''; } catch (error) { Logger.error(`${this.constructor.name} ${this.getNodeProperty.name}`, error); return ''; @@ -145,7 +152,7 @@ export class FileActionsApi { return this.apiService.search.search(data); } catch (error) { Logger.error(`SearchApi queryNodesNames : catch : `, error); - return new ResultSetPaging; + return new ResultSetPaging(); } } @@ -167,4 +174,18 @@ export class FileActionsApi { Logger.error(`\tExpected: ${data.expect} items, but found ${error}`); } } + + async updateNodeContent(nodeId: string, content: string, majorVersion: boolean = true, comment?: string, newName?: string): Promise { + try { + const opts: { [key: string]: string | boolean } = { + majorVersion: majorVersion, + comment: comment, + name: newName + }; + return await this.apiService.nodes.updateNodeContent(nodeId, content, opts); + } catch (error) { + console.error(`${this.constructor.name} ${this.updateNodeContent.name}`, error); + return Promise.reject(error); + } + } } diff --git a/projects/aca-playwright-shared/src/api/nodes-api.ts b/projects/aca-playwright-shared/src/api/nodes-api.ts index c83f563888..4037ffd87e 100755 --- a/projects/aca-playwright-shared/src/api/nodes-api.ts +++ b/projects/aca-playwright-shared/src/api/nodes-api.ts @@ -81,6 +81,14 @@ export class NodesApi { } } + async deleteDeletedNode(name: string): Promise { + try { + await this.apiService.trashCan.deleteDeletedNode(name); + } catch (error) { + console.error(`${this.constructor.name} ${this.deleteDeletedNode.name}: ${error}`); + } + } + private async createNode( nodeType: string, name: string, diff --git a/projects/aca-playwright-shared/src/api/sites-api.ts b/projects/aca-playwright-shared/src/api/sites-api.ts index 1b33218104..a2e27f2b3c 100755 --- a/projects/aca-playwright-shared/src/api/sites-api.ts +++ b/projects/aca-playwright-shared/src/api/sites-api.ts @@ -23,7 +23,16 @@ */ import { ApiClientFactory } from './api-client-factory'; -import { Site, SiteBodyCreate, SiteEntry, SiteMemberEntry, SiteMembershipBodyCreate, SiteMembershipBodyUpdate, SiteMembershipRequestBodyCreate, SiteMembershipRequestEntry } from '@alfresco/js-api'; +import { + Site, + SiteBodyCreate, + SiteEntry, + SiteMemberEntry, + SiteMembershipBodyCreate, + SiteMembershipBodyUpdate, + SiteMembershipRequestBodyCreate, + SiteMembershipRequestEntry +} from '@alfresco/js-api'; export class SitesApi { private apiService: ApiClientFactory; @@ -88,7 +97,7 @@ export class SitesApi { return await this.apiService.sites.updateSiteMembership(siteId, userId, siteRole); } catch (error) { console.error(`SitesApi updateSiteMember : catch : `, error); - return new SiteMemberEntry; + return new SiteMemberEntry(); } } @@ -105,7 +114,7 @@ export class SitesApi { return this.updateSiteMember(siteId, userId, role); } else { console.error(`SitesApi addSiteMember : catch : `, error); - return new SiteMemberEntry; + return new SiteMemberEntry(); } } } @@ -141,4 +150,12 @@ export class SitesApi { return null; } } + + async deleteSiteMember(siteId: string, userId: string) { + try { + return await this.apiService.sites.deleteSiteMembership(siteId, userId); + } catch (error) { + console.error(`SitesApi deleteSiteMember : catch : `, error); + } + } } 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 430c3de7ae..95df52d4be 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 @@ -44,6 +44,11 @@ export class DataTableComponent extends BaseComponent { sortedColumnHeader = this.getChild(`.adf-datatable__header--sorted-asc .adf-datatable-cell-header-content .adf-datatable-cell-value, .adf-datatable__header--sorted-desc .adf-datatable-cell-header-content .adf-datatable-cell-value`); columnHeaders = this.getChild('.adf-datatable-row .adf-datatable-cell-header .adf-datatable-cell-value'); + emptyList = this.getChild('div.adf-no-content-container'); + emptyListTitle = this.getChild('.adf-empty-content__title'); + emptyListSubtitle = this.getChild('.adf-empty-content__subtitle'); + emptySearchText = this.getChild('.empty-search__text'); + emptyListTest = this.getChild('adf-custom-empty-content-template'); /** Locator for row (or rows) */ getRowLocator = this.getChild(`adf-datatable-row`); @@ -123,17 +128,21 @@ export class DataTableComponent extends BaseComponent { getSearchResultLinkByName = (name: string): Locator => this.getChild('.aca-search-results-row span[role="link"]', { hasText: name }); - async sortBy(columnTitle: string, order: 'Ascending' | 'Descending'): Promise { - const columnHeaderLocator = this.getColumnHeaderByTitleLocator(columnTitle); - await this.spinnerWaitForReload(); - await columnHeaderLocator.click(); + getColumnValuesByName = (name: string): Locator => this.getChild(`div[title="${name}"] span`); - const sortAttribute = await columnHeaderLocator.getAttribute('aria-sort'); - if (sortAttribute !== order) { - await columnHeaderLocator.click(); - } + getColumnHeaderByName = (headerTitle: string): Locator => + this.getChild('.adf-datatable-row .adf-datatable-cell-header .adf-datatable-cell-value', { hasText: headerTitle }); - await this.spinnerWaitForReload(); + async sortBy(label: string, order: 'asc' | 'desc'): Promise { + const sortColumn = await this.getSortedColumnHeaderText(); + let sortOrder = await this.getSortingOrder(); + if (sortColumn !== label) { + await this.getColumnHeaderByName(label).click({ force: true }); + sortOrder = await this.getSortingOrder(); + } + if (sortOrder !== order) { + await this.getChild('span[class*="adf-datatable__header--sorted"]').click(); + } } /** @@ -281,4 +290,29 @@ export class DataTableComponent extends BaseComponent { async getRowAllInnerTexts(name: string): Promise { return (await this.getRowByName(name).locator('span').allInnerTexts()).toString(); } + + async getFirstElementDetail(name: string): Promise { + const firstNode = this.getColumnValuesByName(name).first(); + return firstNode.innerText(); + } + + async isEmpty(): Promise { + return this.emptyList.isVisible(); + } + + async getEmptyStateTitle(): Promise { + return (await this.isEmpty()) ? this.emptyListTitle.innerText() : ''; + } + + async getEmptyStateSubtitle(): Promise { + return (await this.isEmpty()) ? this.emptyListSubtitle.innerText() : ''; + } + + async getEmptyListText(): Promise { + return (await this.isEmpty()) ? this.emptyListTest.innerText() : ''; + } + + async getRowsCount(): Promise { + return this.getRowLocator.count(); + } } diff --git a/projects/aca-playwright-shared/src/page-objects/components/error.component.ts b/projects/aca-playwright-shared/src/page-objects/components/error.component.ts new file mode 100644 index 0000000000..cbdcd16656 --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/components/error.component.ts @@ -0,0 +1,36 @@ +/*! + * 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 { Page } from '@playwright/test'; +import { BaseComponent } from './base.component'; + +export class ErrorComponent extends BaseComponent { + private static rootElement = 'aca-page-layout'; + genericError = this.getChild('aca-generic-error'); + genericErrorTitle = this.getChild('.generic-error__title'); + + constructor(page: Page) { + super(page, ErrorComponent.rootElement); + } +} 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 3083c6a25c..ec64165a7d 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/index.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/index.ts @@ -38,3 +38,4 @@ export * from './search/search-overlay.components'; export * from './breadcrumb/breadcrumb.component'; export * from './sidenav.component'; export * from './aca-header.component'; +export * from './error.component'; diff --git a/projects/aca-playwright-shared/src/page-objects/components/pagination.component.ts b/projects/aca-playwright-shared/src/page-objects/components/pagination.component.ts index cafbcb512c..ff58672902 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/pagination.component.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/pagination.component.ts @@ -105,7 +105,7 @@ export class PaginationComponent extends BaseComponent { if (await this.isNextEnabled()) { await this.nextButton.click(); } - } catch(error) { + } catch (error) { throw new Error(`Failed on previous click: ${error}`); } } @@ -115,7 +115,7 @@ export class PaginationComponent extends BaseComponent { if (await this.isPreviousEnabled()) { await this.previousButton.click(); } - } catch(error) { + } catch (error) { throw new Error(`Failed on previous click: ${error}`); } } @@ -166,4 +166,12 @@ export class PaginationComponent extends BaseComponent { async closeMenu(): Promise { await this.page.keyboard.press('Escape'); } + + async isRangePresent(): Promise { + return this.range.isVisible(); + } + + async isMaxItemsPresent(): Promise { + return this.maxItems.isVisible(); + } } diff --git a/projects/aca-playwright-shared/src/page-objects/pages/personal-files.page.ts b/projects/aca-playwright-shared/src/page-objects/pages/personal-files.page.ts index af46e02ef8..9d014df8ea 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/personal-files.page.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/personal-files.page.ts @@ -36,7 +36,8 @@ import { MatMenuComponent, ViewerComponent, SidenavComponent, - PaginationComponent + PaginationComponent, + ErrorComponent } from '../components'; export class PersonalFilesPage extends BasePage { @@ -58,6 +59,7 @@ export class PersonalFilesPage extends BasePage { public sidenav = new SidenavComponent(this.page); public createFromTemplateDialogComponent = new CreateFromTemplateDialogComponent(this.page); public pagination = new PaginationComponent(this.page); + public errorDialog = new ErrorComponent(this.page); async selectCreateFolder(): Promise { await this.acaHeader.createButton.click(); diff --git a/projects/aca-playwright-shared/src/page-objects/pages/trash.page.ts b/projects/aca-playwright-shared/src/page-objects/pages/trash.page.ts index 09a57e123e..848f5367c3 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/trash.page.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/trash.page.ts @@ -24,7 +24,7 @@ import { Page } from '@playwright/test'; import { BasePage } from './base.page'; -import { DataTableComponent, MatMenuComponent, ViewerComponent, SidenavComponent, Breadcrumb } from '../components'; +import { DataTableComponent, MatMenuComponent, ViewerComponent, SidenavComponent, Breadcrumb, PaginationComponent } from '../components'; import { AcaHeader } from '../components/aca-header.component'; import { AdfFolderDialogComponent, ViewerOverlayDialogComponent } from '../components/dialogs'; @@ -43,4 +43,5 @@ export class TrashPage extends BasePage { public viewerDialog = new ViewerOverlayDialogComponent(this.page); public sidenav = new SidenavComponent(this.page); public breadcrumb = new Breadcrumb(this.page); + public pagination = new PaginationComponent(this.page); }