diff --git a/e2e/playwright/folder-rules/src/tests/actions.spec.ts b/e2e/playwright/folder-rules/src/tests/actions.spec.ts index 0ca2060142..e50711ac2e 100644 --- a/e2e/playwright/folder-rules/src/tests/actions.spec.ts +++ b/e2e/playwright/folder-rules/src/tests/actions.spec.ts @@ -44,16 +44,14 @@ test.describe('Folder Rules Actions', () => { }); test.beforeEach(async ({ personalFiles }) => { - await personalFiles.navigate({ waitUntil: 'domcontentloaded' }); + await personalFiles.navigate({ remoteUrl: `#/nodes/${folderId}/rules` }); }); test.afterAll(async () => { - await apiClientFactory.nodes.deleteNode(folderId); + await apiClientFactory.nodes.deleteNode(folderId, { permanent: true }); }); - test('[C691637] Create a rule with actions', async ({ personalFiles, nodesPage }) => { - await personalFiles.dataTable.performActionFromExpandableMenu(randomFolderName, 'Manage rules'); - + test('[C691637] Create a rule with actions', async ({ nodesPage }) => { await nodesPage.toolbar.clickCreateRuleButton(); await nodesPage.manageRulesDialog.ruleNameInputLocator.type(randomRuleName); diff --git a/e2e/playwright/folder-rules/src/tests/conditions.spec.ts b/e2e/playwright/folder-rules/src/tests/conditions.spec.ts index 7d5528fa6b..1ec0740a85 100644 --- a/e2e/playwright/folder-rules/src/tests/conditions.spec.ts +++ b/e2e/playwright/folder-rules/src/tests/conditions.spec.ts @@ -45,7 +45,7 @@ test.describe('Folder Rules Conditions', () => { }); test.afterAll(async () => { - await apiClientFactory.nodes.deleteNode(folderId); + await apiClientFactory.nodes.deleteNode(folderId, { permanent: true }); }); test('[C691638] Create a rule with condition', async ({ personalFiles, nodesPage }) => { diff --git a/e2e/playwright/folder-rules/src/tests/manage-rules.spec.ts b/e2e/playwright/folder-rules/src/tests/manage-rules.spec.ts index 143b144fc9..89609dccb9 100644 --- a/e2e/playwright/folder-rules/src/tests/manage-rules.spec.ts +++ b/e2e/playwright/folder-rules/src/tests/manage-rules.spec.ts @@ -44,7 +44,7 @@ test.describe('Rules - Manage Rules', () => { }); test.afterAll(async () => { - await apiClientFactory.nodes.deleteNode(folderId); + await apiClientFactory.nodes.deleteNode(folderId, { permanent: true }); }); test('[C691651] Disable an existing rule', async ({ personalFiles, nodesPage }) => { diff --git a/e2e/playwright/viewer/exclude.tests.json b/e2e/playwright/viewer/exclude.tests.json index e43a787031..9c00daf8b7 100644 --- a/e2e/playwright/viewer/exclude.tests.json +++ b/e2e/playwright/viewer/exclude.tests.json @@ -1,6 +1,9 @@ { - "C284636" : "https://alfresco.atlassian.net/browse/ACS-5639", - "C284635" : "https://alfresco.atlassian.net/browse/ACS-5639", - "C279175" : "https://alfresco.atlassian.net/browse/ACS-5639", - "C284634" : "https://alfresco.atlassian.net/browse/ACS-5639" + "C284636" : "this have Protractor test Enabled https://alfresco.atlassian.net/browse/ACS-5639", + "C284635" : "this have Protractor test Enabled https://alfresco.atlassian.net/browse/ACS-5639", + "C279175" : "this have Protractor test Enabled https://alfresco.atlassian.net/browse/ACS-5639", + "C284634" : "this have Protractor test Enabled https://alfresco.atlassian.net/browse/ACS-5639", + "C297585" : "this have Protractor test Enabled https://alfresco.atlassian.net/browse/ACS-5639", + "C286379" : "this have Protractor test Enabled https://alfresco.atlassian.net/browse/ACS-5639", + "C286395" : "this have Protractor test Enabled https://alfresco.atlassian.net/browse/ACS-5639" } diff --git a/e2e/playwright/viewer/src/tests/viewer-action.spec.ts b/e2e/playwright/viewer/src/tests/viewer-action.spec.ts new file mode 100644 index 0000000000..0a2ed4a45a --- /dev/null +++ b/e2e/playwright/viewer/src/tests/viewer-action.spec.ts @@ -0,0 +1,163 @@ +/*! + * 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, getUserState, test, TEST_FILES, timeouts, Utils } from '@alfresco/playwright-shared'; + +test.use({ storageState: getUserState('hruser') }); +test.describe('viewer action file', () => { + const apiClientFactory = new ApiClientFactory(); + const randomFolderName = `playwright-folder-${Utils.random()}`; + const randomDocxName = `${TEST_FILES.DOCX.name}-${Utils.random()}`; + const randomDocxNameFavorite = `${TEST_FILES.DOCX.name}-${Utils.random()}`; + const randomDocxNameShare = `${TEST_FILES.DOCX.name}-${Utils.random()}`; + const randomDocxDelete = `${TEST_FILES.DOCX.name}-${Utils.random()}`; + const fileForEditOffline = `playwright-file1-${Utils.random()}.docx`; + const fileForCancelEditing = `playwright-file2-${Utils.random()}.docx`; + let folderId: string; + let fileDocxShareId: string; + + test.beforeAll(async ({ fileAction, shareAction }) => { + await apiClientFactory.setUpAcaBackend('hruser'); + const node = await apiClientFactory.nodes.createNode('-my-', { name: randomFolderName, nodeType: 'cm:folder', relativePath: '/' }); + folderId = node.entry.id; + await fileAction.uploadFile(TEST_FILES.DOCX.path, fileForCancelEditing, folderId); + await fileAction.uploadFile(TEST_FILES.DOCX.path, randomDocxName, folderId); + await fileAction.uploadFile(TEST_FILES.DOCX.path, randomDocxDelete, folderId); + const fileDocShare = await fileAction.uploadFile(TEST_FILES.DOCX.path, randomDocxNameShare, folderId); + fileDocxShareId = fileDocShare.entry.id; + await fileAction.uploadFile(TEST_FILES.DOCX.path, randomDocxNameFavorite, folderId); + await shareAction.shareFileById(fileDocxShareId); + await fileAction.uploadFile(TEST_FILES.DOCX.path, fileForEditOffline, folderId); + }); + + test.beforeEach(async ({ personalFiles }) => { + await personalFiles.navigate({ remoteUrl: `#/personal-files/${folderId}` }); + }); + + test.afterAll(async () => { + await apiClientFactory.nodes.deleteNode(folderId); + await apiClientFactory.trashCan.deleteDeletedNode(folderId); + }); + + test('[C268129] Download action', async ({ personalFiles }) => { + await personalFiles.dataTable.performClickFolderOrFileToOpen(randomDocxName); + await personalFiles.viewer.waitForViewerToOpen(); + const downloadPromise = personalFiles.page.waitForEvent('download'); + await personalFiles.acaHeader.downloadButton.click(); + const download = await downloadPromise; + expect(download.suggestedFilename()).toBe(randomDocxName); + }); + + test('[C268133] Delete action', async ({ personalFiles, trashPage }) => { + await personalFiles.dataTable.performClickFolderOrFileToOpen(randomDocxDelete); + await personalFiles.viewer.waitForViewerToOpen(); + + await personalFiles.acaHeader.clickViewerMoreActions(); + await personalFiles.viewerDialog.deleteMenuButton.click(); + await personalFiles.snackBar.getByMessageLocator(randomDocxDelete).waitFor({ state: 'attached' }); + const deleteName = await personalFiles.snackBar.getByMessageLocator(randomDocxDelete).innerText(); + expect(deleteName).toContain(`${randomDocxDelete} deleted`); + await personalFiles.dataTable.getCellLinkByName(randomDocxName).waitFor({ state: 'attached' }); + expect(await personalFiles.dataTable.getCellLinkByName(randomDocxDelete).isVisible(), 'file should not visible').toBe(false); + await trashPage.navigate({ waitUntil: 'domcontentloaded' }); + await trashPage.dataTable.goThroughPagesLookingForRowWithName(randomDocxDelete); + expect(await trashPage.dataTable.isItemPresent(randomDocxDelete), 'Item should be present in Trash').toBe(true); + }); + + test('[C297584] Edit Offline action', async ({ personalFiles }) => { + await personalFiles.dataTable.performClickFolderOrFileToOpen(fileForEditOffline); + await personalFiles.viewer.waitForViewerToOpen(); + await personalFiles.acaHeader.clickViewerMoreActions(); + await personalFiles.matMenu.clickMenuItem('Edit Offline'); + + const downloadPromise = personalFiles.page.waitForEvent('download'); + await personalFiles.acaHeader.downloadButton.click(); + const download = await downloadPromise; + expect(download.suggestedFilename(), 'File should found in download location').toBe(fileForEditOffline); + expect(await personalFiles.viewer.isViewerOpened(), 'Viewer is closed after pressing Full screen').toBe(true); + await personalFiles.reload({ waitUntil: 'domcontentloaded' }); + await personalFiles.acaHeader.clickViewerMoreActions(); + expect(await personalFiles.matMenu.isMenuItemVisible('Cancel Editing'), 'Cancel Editing menu should be visible').toBe(true); + }); + + test('[C297585] Cancel Editing action', async ({ personalFiles }) => { + await personalFiles.dataTable.performClickFolderOrFileToOpen(fileForCancelEditing); + await personalFiles.viewer.waitForViewerToOpen(); + await personalFiles.acaHeader.clickViewerMoreActions(); + await personalFiles.matMenu.clickMenuItem('Cancel Editing'); + await personalFiles.reload({ waitUntil: 'domcontentloaded' }); + await personalFiles.acaHeader.clickViewerMoreActions(); + expect(await personalFiles.matMenu.isMenuItemVisible('Edit Offline'), 'Edit offline menu should be visible').toBe(true); + }); + + test('[C279282] Full screen action', async ({ personalFiles }) => { + await personalFiles.dataTable.performClickFolderOrFileToOpen(randomDocxName); + await personalFiles.viewer.waitForViewerToOpen(); + await personalFiles.acaHeader.fullScreenButton.click(); + expect(await personalFiles.viewer.isViewerOpened(), 'Viewer is closed after pressing Full screen').toBe(true); + }); + + test('[C286314] Pressing ESC in the viewer closes only the action dialog', async ({ personalFiles }) => { + await personalFiles.dataTable.performClickFolderOrFileToOpen(randomDocxName); + await personalFiles.viewer.waitForViewerToOpen(); + await personalFiles.acaHeader.clickViewerMoreActions(); + await personalFiles.viewerDialog.clickActionsCopy(); + expect(await personalFiles.viewerDialog.isCopyDialogOpen(), 'Dialog is not open').toBe(true); + await personalFiles.page.keyboard.press('Escape'); + expect(await personalFiles.viewerDialog.isCopyDialogClose(), 'Dialog is not open').toBe(false); + expect(await personalFiles.viewer.isViewerOpened(), 'Viewer should be opened').toBe(true); + }); + + test('[C286379] Favorite action from Shared Files', async ({ sharedPage, favoritePage, shareAction }) => { + await sharedPage.navigate({ waitUntil: 'domcontentloaded' }); + await sharedPage.dataTable.performClickFolderOrFileToOpen(randomDocxNameShare); + expect(await sharedPage.viewer.isViewerOpened(), 'Viewer should be opened').toBe(true); + + await sharedPage.acaHeader.clickViewerMoreActions(); + + await favoritePage.viewerDialog.favoriteMenuButton.waitFor({ state: 'attached', timeout: timeouts.normal }); + await sharedPage.viewerDialog.favoriteMenuButton.click(); + await favoritePage.viewerDialog.favoriteMenuButton.waitFor({ state: 'detached', timeout: timeouts.normal }); + + await sharedPage.acaHeader.clickViewerMoreActions(); + expect(await sharedPage.viewerDialog.removeFavoriteMenuButton.isVisible(), 'Item should be remove favorite').toBe(true); + await sharedPage.page.keyboard.press('Escape'); + await favoritePage.navigate({ waitUntil: 'domcontentloaded' }); + expect(await favoritePage.dataTable.isItemPresent(randomDocxNameShare), 'Item is not present in Favorites list').toBe(true); + expect(await shareAction.isFavorite(randomDocxNameShare, 'hruser'), 'Item is not favorite').toBe(true); + }); + + test('[C286395] Share action from Favorites', async ({ favoritePage }) => { + await favoritePage.navigate({ waitUntil: 'domcontentloaded' }); + await favoritePage.dataTable.performClickFolderOrFileToOpen(randomDocxNameFavorite); + expect(await favoritePage.viewer.isViewerOpened(), 'Viewer should be opened').toBe(true); + + await favoritePage.acaHeader.shareButton.click(); + expect(await favoritePage.viewerDialog.shareDialogTitle.isVisible(), 'Share dialog should be open').toBe(true); + await favoritePage.viewerDialog.shareDialogClose.click(); + await favoritePage.viewerDialog.shareDialogClose.waitFor({ state: 'detached', timeout: timeouts.large }); + expect(await favoritePage.viewerDialog.shareDialogTitle.isVisible(), 'Share dialog should be open').toBe(false); + }); +}); diff --git a/e2e/playwright/viewer/src/tests/viewer-protected.spec.ts b/e2e/playwright/viewer/src/tests/viewer-protected.spec.ts index 565ab2863f..8ca3cbfb77 100644 --- a/e2e/playwright/viewer/src/tests/viewer-protected.spec.ts +++ b/e2e/playwright/viewer/src/tests/viewer-protected.spec.ts @@ -36,21 +36,20 @@ test.describe('viewer file', () => { test.beforeAll(async ({ fileAction, shareAction, favoritesPageAction: favoritesPageAction }) => { await apiClientFactory.setUpAcaBackend('hruser'); const node = await apiClientFactory.nodes.createNode('-my-', { name: randomFolderName, nodeType: 'cm:folder', relativePath: '/' }); - folderId = await node.entry.id; + folderId = node.entry.id; const fileDoc = await fileAction.uploadFile(TEST_FILES.DOCX_PROTECTED.path, randomDocxName, folderId); - fileDocxId = await fileDoc.entry.id; + fileDocxId = fileDoc.entry.id; await shareAction.shareFileById(fileDocxId); await favoritesPageAction.addFavoriteById('file', fileDocxId); }); test.beforeEach(async ({ personalFiles }) => { - const gotoNodeURL = `#/personal-files/${folderId}`; - await personalFiles.navigate({ remoteUrl: gotoNodeURL }); + await personalFiles.navigate({ remoteUrl: `#/personal-files/${folderId}` }); await personalFiles.dataTable.performClickFolderOrFileToOpen(randomDocxName); }); test.afterAll(async () => { - await apiClientFactory.nodes.deleteNode(folderId); + await apiClientFactory.nodes.deleteNode(folderId, { permanent: true }); }); test('[C268958] Password dialog appears when opening a protected file', async ({ personalFiles }) => { diff --git a/e2e/playwright/viewer/src/tests/viewer.spec.ts b/e2e/playwright/viewer/src/tests/viewer.spec.ts index e4994c6b6d..e721fcf334 100644 --- a/e2e/playwright/viewer/src/tests/viewer.spec.ts +++ b/e2e/playwright/viewer/src/tests/viewer.spec.ts @@ -25,7 +25,7 @@ import { expect } from '@playwright/test'; import { ApiClientFactory, getUserState, test, TEST_FILES, Utils } from '@alfresco/playwright-shared'; -test.use({ storageState: getUserState('admin') }); +test.use({ storageState: getUserState('hruser') }); test.describe('viewer file', () => { const apiClientFactory = new ApiClientFactory(); const randomFolderName = `playwright-folder-${Utils.random()}`; @@ -33,19 +33,18 @@ test.describe('viewer file', () => { let folderId: string; test.beforeAll(async ({ fileAction }) => { - await apiClientFactory.setUpAcaBackend('admin'); + await apiClientFactory.setUpAcaBackend('hruser'); const node = await apiClientFactory.nodes.createNode('-my-', { name: randomFolderName, nodeType: 'cm:folder', relativePath: '/' }); - folderId = await node.entry.id; + folderId = node.entry.id; await fileAction.uploadFile(TEST_FILES.DOCX.path, randomDocxName, folderId); }); test.beforeEach(async ({ personalFiles }) => { - const gotoNodeURL = `#/personal-files/${folderId}`; - await personalFiles.navigate({ remoteUrl: gotoNodeURL }); + await personalFiles.navigate({ remoteUrl: `#/personal-files/${folderId}` }); }); test.afterAll(async () => { - await apiClientFactory.nodes.deleteNode(folderId); + await apiClientFactory.nodes.deleteNode(folderId, { permanent: true }); }); test('[C279269] Viewer opens on double clicking on a file from Personal Files', async ({ personalFiles }) => { @@ -71,15 +70,11 @@ test.describe('viewer file', () => { test('[C279271] Close the viewer', async ({ personalFiles }) => { await personalFiles.dataTable.performClickFolderOrFileToOpen(randomDocxName); expect(await personalFiles.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); + expect(await personalFiles.viewer.getCloseButtonTooltip()).toEqual('Close'); await personalFiles.viewer.closeButtonLocator.click(); expect(await personalFiles.dataTable.getCellLinkByName(randomDocxName).isVisible(), 'Viewer did not close').toBe(true); }); - test('[C284632] Close button tooltip', async ({ personalFiles }) => { - await personalFiles.dataTable.performClickFolderOrFileToOpen(randomDocxName); - expect(await personalFiles.viewer.getCloseButtonTooltip()).toEqual('Close'); - }); - test('[C284636] Viewer opens for a file from Recent Files', async ({ personalFiles, recentFilesPage }) => { await personalFiles.dataTable.performClickFolderOrFileToOpen(randomDocxName); expect(await personalFiles.viewer.getCloseButtonTooltip()).toEqual('Close'); @@ -113,17 +108,17 @@ test.describe('viewer file', () => { let fileDocxId: string; test.beforeAll(async ({ fileAction, shareAction, favoritesPageAction: favoritesPageAction }) => { - await apiClientFactory.setUpAcaBackend('admin'); + await apiClientFactory.setUpAcaBackend('hruser'); const node = await apiClientFactory.nodes.createNode('-my-', { name: randomFolderName, nodeType: 'cm:folder', relativePath: '/' }); - folderId = await node.entry.id; + folderId = node.entry.id; const fileDoc = await fileAction.uploadFile(TEST_FILES.DOCX.path, randomDocxName, folderId); - fileDocxId = await fileDoc.entry.id; + fileDocxId = fileDoc.entry.id; await shareAction.shareFileById(fileDocxId); await favoritesPageAction.addFavoriteById('file', fileDocxId); }); test.afterAll(async () => { - await apiClientFactory.nodes.deleteNode(folderId); + await apiClientFactory.nodes.deleteNode(folderId, { permanent: true }); }); test('[C279285] Viewer opens when accessing the preview URL for a file', async ({ personalFiles }) => { @@ -136,7 +131,7 @@ test.describe('viewer file', () => { test('[C284635] Viewer opens for a file from Shared Files', async ({ sharedPage }) => { await sharedPage.navigate(); - await sharedPage.reload(); + await sharedPage.reload({ waitUntil: 'domcontentloaded' }); await sharedPage.dataTable.goThroughPagesLookingForRowWithName(randomDocxName); await sharedPage.dataTable.performClickFolderOrFileToOpen(randomDocxName); expect(await sharedPage.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); diff --git a/e2e/protractor/protractor.excludes.json b/e2e/protractor/protractor.excludes.json index 6fb5bff913..99183958b9 100644 --- a/e2e/protractor/protractor.excludes.json +++ b/e2e/protractor/protractor.excludes.json @@ -22,6 +22,11 @@ "C268958" : "test migrated to playwright https://alfresco.atlassian.net/browse/ACS-5604", "C268959" : "test migrated to playwright https://alfresco.atlassian.net/browse/ACS-5604", "C268960" : "test migrated to playwright https://alfresco.atlassian.net/browse/ACS-5604", - "C268961" : "test migrated to playwright https://alfresco.atlassian.net/browse/ACS-5604" + "C268961" : "test migrated to playwright https://alfresco.atlassian.net/browse/ACS-5604", + "C286314" : "test migrated to playwright https://alfresco.atlassian.net/browse/ACS-5650", + "C279282" : "test migrated to playwright https://alfresco.atlassian.net/browse/ACS-5650", + "C297584" : "test migrated to playwright https://alfresco.atlassian.net/browse/ACS-5650", + "C268133" : "test migrated to playwright https://alfresco.atlassian.net/browse/ACS-5650", + "C268129" : "test migrated to playwright https://alfresco.atlassian.net/browse/ACS-5650" } diff --git a/projects/aca-playwright-shared/src/api/api-client-factory.ts b/projects/aca-playwright-shared/src/api/api-client-factory.ts index 53453aaa95..0d18c19e1b 100644 --- a/projects/aca-playwright-shared/src/api/api-client-factory.ts +++ b/projects/aca-playwright-shared/src/api/api-client-factory.ts @@ -37,7 +37,8 @@ import { SitesApi, UploadApi, SharedlinksApi, - FavoritesApi + FavoritesApi, + TrashcanApi } from '@alfresco/js-api'; import { logger } from '@alfresco/adf-cli/scripts/logger'; import { ActionTypes, Rule } from './rules-api'; @@ -49,6 +50,7 @@ export interface AcaBackend { nodes: NodesApi; share: SharedlinksApi; favorites: FavoritesApi; + trashCan: TrashcanApi; tearDown(): Promise; } @@ -79,6 +81,7 @@ export class ApiClientFactory { public contentClient: ContentClient; public share: SharedlinksApi; public favorites: FavoritesApi; + public trashCan: TrashcanApi; constructor() { this.alfrescoApi = new AlfrescoApi(config); @@ -100,6 +103,7 @@ export class ApiClientFactory { this.securityMarksApi = new SecurityMarksApi(this.alfrescoApi); this.share = new SharedlinksApi(this.alfrescoApi); this.favorites = new FavoritesApi(this.alfrescoApi); + this.trashCan = new TrashcanApi(this.alfrescoApi); return this; } diff --git a/projects/aca-playwright-shared/src/api/shared-links-api.ts b/projects/aca-playwright-shared/src/api/shared-links-api.ts index 0c24e75598..69d97a996f 100755 --- a/projects/aca-playwright-shared/src/api/shared-links-api.ts +++ b/projects/aca-playwright-shared/src/api/shared-links-api.ts @@ -23,23 +23,22 @@ */ import { ApiClientFactory } from './api-client-factory'; -import { SharedLinkEntry } from '@alfresco/js-api'; +import { FavoritePaging, SharedLinkEntry } from '@alfresco/js-api'; import { users } from '../base-config/global-variables'; +import { logger } from '@alfresco/adf-cli/scripts/logger'; export class SharedLinksApi extends ApiClientFactory { private apiService: ApiClientFactory; constructor() { super(); - this.apiService = new ApiClientFactory(); + this.apiService = new ApiClientFactory(); + } + static async initialize(userProfile: keyof typeof users): Promise { + const classObj = new SharedLinksApi(); + await classObj.apiService.setUpAcaBackend(userProfile); + return classObj; } - static async initialize( - userProfile: keyof typeof users - ): Promise { - const classObj = new SharedLinksApi(); - await classObj.apiService.setUpAcaBackend(userProfile); - return classObj; - } async shareFileById(id: string, expireDate?: Date): Promise { try { @@ -52,4 +51,22 @@ export class SharedLinksApi extends ApiClientFactory { return null; } } + + private async getFavorites(userName: string): Promise { + try { + return await this.apiService.favorites.listFavorites(userName); + } catch (error) { + logger.error(`\n--- Error while fetching favourites list ${error} :`); + return null; + } + } + + async isFavorite(nodeId: string, userName: string): Promise { + try { + return JSON.stringify((await this.getFavorites(userName)).list.entries).includes(nodeId); + } catch (error) { + logger.error(`\n--- Error while checking favourite node ${error} ${error} :`); + return null; + } + } } diff --git a/projects/aca-playwright-shared/src/fixtures/page-initialization.ts b/projects/aca-playwright-shared/src/fixtures/page-initialization.ts index 181f91d056..d97cc25deb 100644 --- a/projects/aca-playwright-shared/src/fixtures/page-initialization.ts +++ b/projects/aca-playwright-shared/src/fixtures/page-initialization.ts @@ -33,7 +33,8 @@ import { SharedPage, SearchPage, FavoritesPage, - FavoritesPageApi + FavoritesPageApi, + TrashPage } from '../'; interface Pages { @@ -44,6 +45,7 @@ interface Pages { sharedPage: SharedPage; searchPage: SearchPage; favoritePage: FavoritesPage; + trashPage: TrashPage; } interface Api { @@ -71,17 +73,20 @@ export const test = base.extend({ favoritePage: async ({ page }, use) => { await use(new FavoritesPage(page)); }, + trashPage: async ({ page }, use) => { + await use(new TrashPage(page)); + }, // eslint-disable-next-line no-empty-pattern fileAction: async ({}, use) => { - await use(await FileActionsApi.initialize('admin')); + await use(await FileActionsApi.initialize('hruser')); }, // eslint-disable-next-line no-empty-pattern shareAction: async ({}, use) => { - await use(await SharedLinksApi.initialize('admin')); + await use(await SharedLinksApi.initialize('hruser')); }, // eslint-disable-next-line no-empty-pattern favoritesPageAction: async ({}, use) => { - await use(await FavoritesPageApi.initialize('admin')); + await use(await FavoritesPageApi.initialize('hruser')); }, myLibrariesPage: async ({ page }, use) => { await use(new MyLibrariesPage(page)); diff --git a/projects/aca-playwright-shared/src/page-objects/components/aca-header.component.ts b/projects/aca-playwright-shared/src/page-objects/components/aca-header.component.ts index 426a38bbb5..ce88658f10 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/aca-header.component.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/aca-header.component.ts @@ -1,37 +1,46 @@ /*! - * 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 . - */ + * 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 { BaseComponent } from './base.component'; import { Page } from '@playwright/test'; export class AcaHeader extends BaseComponent { private static rootElement = 'adf-toolbar'; + private moreActionsButton = this.getChild('button[id="app.viewer.toolbar.more"]'); public createButton = this.getChild('[id="app.toolbar.create"]'); public viewDetails = this.getChild('[title="View Details"]'); public viewButton = this.getChild('button[title="View"]'); public searchButton = this.getChild('button[title="Search"]'); + public fullScreenButton = this.getChild('button[id="app.viewer.fullscreen"]'); + public shareButton = this.getChild('button[id="app.viewer.fullscreen"]'); + public downloadButton = this.getChild('button[id="app.viewer.download"]'); constructor(page: Page) { super(page, AcaHeader.rootElement); } + + async clickViewerMoreActions(): Promise { + await this.moreActionsButton.waitFor({ state: 'attached' }); + await this.moreActionsButton.click(); + } } diff --git a/projects/aca-playwright-shared/src/page-objects/components/actions-dropdown.component.ts b/projects/aca-playwright-shared/src/page-objects/components/actions-dropdown.component.ts index 2bc2b12093..475c630119 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/actions-dropdown.component.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/actions-dropdown.component.ts @@ -52,7 +52,7 @@ export enum ActionType { export class ActionsDropdownComponent extends BaseComponent { private static rootElement = 'aca-rule-action-list'; - private getOptionLocator = (optionName: string): Locator => this.page.locator('.mat-select-panel .mat-option-text', { hasText: optionName }); + private getOptionLocator = (optionName: string): Locator => this.page.locator('.mat-select-panel .mat-option-text', { hasText: optionName }).first(); private ruleActionLocator = this.getChild('aca-rule-action [data-automation-id="rule-action-card-view"]'); private addActionButtonLocator = this.getChild('[data-automation-id="rule-action-list-add-action-button"]'); private actionDropdownLocator = this.getChild('[data-automation-id="rule-action-select"]'); @@ -75,9 +75,8 @@ export class ActionsDropdownComponent extends BaseComponent { await this.addActionButtonLocator.click(); } await this.actionDropdownLocator.nth(index).click(); - await this.spinnerWaitForReload(); const option = this.getOptionLocator(action); - await option.nth(0).click(); + await option.click(); } async dropdownSelection(selectValue: string, locator: string, index: number): Promise { 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 c1be07e465..f32c908c81 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 @@ -165,6 +165,11 @@ export class DataTableComponent extends BaseComponent { await this.spinnerWaitForReload(); } + async isItemPresent(name: string): Promise { + await this.goThroughPagesLookingForRowWithName(name); + return this.getRowByName(name).isVisible(); + } + async getActionLocatorFromExpandableMenu(name: string | number, action: string): Promise { await this.getRowByName(name).click({ button: 'right' }); return this.contextMenuActions.getButtonByText(action); @@ -199,7 +204,7 @@ export class DataTableComponent extends BaseComponent { async selectItem(name: string): Promise { const isSelected = await this.hasCheckMarkIcon(name); if (!isSelected) { - const row = await this.getRowByName(name); + const row = this.getRowByName(name); await row.locator('.mat-checkbox[id*="mat-checkbox"]').check(); } } diff --git a/projects/aca-playwright-shared/src/page-objects/components/dataTable/mat-menu.component.ts b/projects/aca-playwright-shared/src/page-objects/components/dataTable/mat-menu.component.ts index a38e78e0ee..1f48038a6c 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/dataTable/mat-menu.component.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/dataTable/mat-menu.component.ts @@ -37,4 +37,17 @@ export class MatMenuComponent extends BaseComponent { public createFolder = this.getChild('[id="app.create.folder"]'); public createLibrary = this.getChild('[id="app.create.library"]'); public getButtonByText = (text: string) => this.getChild('button', { hasText: text }); + + async clickMenuItem(menuItem: string): Promise { + const menuElement = this.getButtonByText(menuItem); + await menuElement.waitFor({ state: 'attached' }); + await menuElement.click(); + await menuElement.waitFor({ state: 'detached' }); + } + + async isMenuItemVisible(menuItem: string): Promise { + const menuElement = this.getButtonByText(menuItem); + await menuElement.waitFor({ state: 'attached' }); + return await menuElement.isVisible(); + } } diff --git a/projects/aca-playwright-shared/src/page-objects/components/dialogs/index.ts b/projects/aca-playwright-shared/src/page-objects/components/dialogs/index.ts index 8a0e9a2a04..5a9d3c9676 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/dialogs/index.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/dialogs/index.ts @@ -25,3 +25,4 @@ export * from './adf-folder-dialog.component'; export * from './adf-library-dialog.component'; export * from './password-overlay-dialog.component'; +export * from './viewer-overlay-dialog.component'; diff --git a/projects/aca-playwright-shared/src/page-objects/components/dialogs/viewer-overlay-dialog.component.ts b/projects/aca-playwright-shared/src/page-objects/components/dialogs/viewer-overlay-dialog.component.ts new file mode 100644 index 0000000000..542fc1cfda --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/components/dialogs/viewer-overlay-dialog.component.ts @@ -0,0 +1,62 @@ +/*! + * 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'; +import { timeouts } from '../../../utils'; + +export class ViewerOverlayDialogComponent extends BaseComponent { + private static rootElement = '.cdk-overlay-pane'; + + public closeButton = this.getChild('[data-automation-id="adf-password-dialog-close"]'); + public submitButton = this.getChild('[data-automation-id="adf-password-dialog-submit"]'); + public passwordInput = this.getChild('[data-automation-id="adf-password-dialog-input"]'); + public errorMessage = this.getChild('[data-automation-id="adf-password-dialog-error"]'); + public copyDialog = this.getChild('[data-automation-id="content-node-selector-title"]'); + public copyMenuButton = this.getChild('[id="app.viewer.copy"]'); + public deleteMenuButton = this.getChild('[id="app.viewer.delete"]'); + public favoriteMenuButton = this.getChild('[id="app.viewer.favorite.add"]'); + public removeFavoriteMenuButton = this.getChild('[id="app.viewer.favorite.remove"]'); + public shareDialogTitle = this.getChild('[data-automation-id="adf-share-dialog-title"]'); + public shareDialogClose = this.getChild('[data-automation-id="adf-share-dialog-close"]'); + + constructor(page: Page, rootElement = ViewerOverlayDialogComponent.rootElement) { + super(page, rootElement); + } + + async isCopyDialogOpen(): Promise { + await this.copyDialog.waitFor({ state: 'attached', timeout: timeouts.medium }); + return this.copyDialog.isVisible(); + } + + async isCopyDialogClose(): Promise { + await this.copyDialog.waitFor({ state: 'detached', timeout: timeouts.medium }); + return this.copyDialog.isVisible(); + } + + async clickActionsCopy(): Promise { + await this.copyMenuButton.waitFor({ state: 'attached', timeout: timeouts.medium }); + await this.copyMenuButton.click(); + } +} diff --git a/projects/aca-playwright-shared/src/page-objects/pages/favorites.page.ts b/projects/aca-playwright-shared/src/page-objects/pages/favorites.page.ts index 2d0a13cde7..179aeed990 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/favorites.page.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/favorites.page.ts @@ -26,7 +26,7 @@ import { Page } from '@playwright/test'; import { BasePage } from './base.page'; import { DataTableComponent, MatMenuComponent, ViewerComponent } from '../components'; import { AcaHeader } from '../components/aca-header.component'; -import { AdfFolderDialogComponent } from '../components/dialogs'; +import { AdfFolderDialogComponent, ViewerOverlayDialogComponent } from '../components/dialogs'; export class FavoritesPage extends BasePage { private static pageUrl = 'favorites'; @@ -40,4 +40,5 @@ export class FavoritesPage extends BasePage { public folderDialog = new AdfFolderDialogComponent(this.page); public dataTable = new DataTableComponent(this.page); public viewer = new ViewerComponent(this.page); + public viewerDialog = new ViewerOverlayDialogComponent(this.page); } diff --git a/projects/aca-playwright-shared/src/page-objects/pages/index.ts b/projects/aca-playwright-shared/src/page-objects/pages/index.ts index 4e9a730348..fcee9ac8e6 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/index.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/index.ts @@ -31,3 +31,4 @@ export * from './recent-files.page'; export * from './shared.page'; export * from './search.page'; export * from './favorites.page'; +export * from './trash.page'; 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 6fa495d1a4..bb63844c5b 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 @@ -26,7 +26,7 @@ import { Page } from '@playwright/test'; import { BasePage } from './base.page'; import { DataTableComponent, MatMenuComponent, ViewerComponent } from '../components'; import { AcaHeader } from '../components/aca-header.component'; -import { AdfFolderDialogComponent, PasswordOverlayDialogComponent } from '../components/dialogs'; +import { AdfFolderDialogComponent, PasswordOverlayDialogComponent, ViewerOverlayDialogComponent } from '../components/dialogs'; export class PersonalFilesPage extends BasePage { private static pageUrl = 'personal-files'; @@ -41,6 +41,7 @@ export class PersonalFilesPage extends BasePage { public dataTable = new DataTableComponent(this.page); public viewer = new ViewerComponent(this.page); public passwordDialog = new PasswordOverlayDialogComponent(this.page); + public viewerDialog = new ViewerOverlayDialogComponent(this.page); async selectCreateFolder(): Promise { await this.acaHeader.createButton.click(); diff --git a/projects/aca-playwright-shared/src/page-objects/pages/shared.page.ts b/projects/aca-playwright-shared/src/page-objects/pages/shared.page.ts index c70bbe57d8..891f3336bf 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/shared.page.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/shared.page.ts @@ -26,7 +26,7 @@ import { Page } from '@playwright/test'; import { BasePage } from './base.page'; import { DataTableComponent, MatMenuComponent, ViewerComponent } from '../components'; import { AcaHeader } from '../components/aca-header.component'; -import { AdfFolderDialogComponent } from '../components/dialogs'; +import { AdfFolderDialogComponent, ViewerOverlayDialogComponent } from '../components/dialogs'; export class SharedPage extends BasePage { private static pageUrl = 'shared'; @@ -40,4 +40,5 @@ export class SharedPage extends BasePage { public folderDialog = new AdfFolderDialogComponent(this.page); public dataTable = new DataTableComponent(this.page); public viewer = new ViewerComponent(this.page); + public viewerDialog = new ViewerOverlayDialogComponent(this.page); } 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 new file mode 100644 index 0000000000..5927404c46 --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/pages/trash.page.ts @@ -0,0 +1,44 @@ +/*! + * 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 { BasePage } from './base.page'; +import { DataTableComponent, MatMenuComponent, ViewerComponent } from '../components'; +import { AcaHeader } from '../components/aca-header.component'; +import { AdfFolderDialogComponent, ViewerOverlayDialogComponent } from '../components/dialogs'; + +export class TrashPage extends BasePage { + private static pageUrl = 'trashcan'; + + constructor(page: Page) { + super(page, TrashPage.pageUrl); + } + + public acaHeader = new AcaHeader(this.page); + public matMenu = new MatMenuComponent(this.page); + public folderDialog = new AdfFolderDialogComponent(this.page); + public dataTable = new DataTableComponent(this.page); + public viewer = new ViewerComponent(this.page); + public viewerDialog = new ViewerOverlayDialogComponent(this.page); +}