From a58075f82f817965c28908802c81e3a56966da4b Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Mon, 18 Dec 2023 16:30:26 +0530 Subject: [PATCH] [AACS-6456] migrated share-file e2es to playwright --- .../src/tests/share/share-file.spec.ts | 248 ++++++++++++++++ .../suites/actions/share/share-file.test.ts | 268 ------------------ .../src/api/nodes-api.ts | 40 +++ .../src/api/shared-links-api.ts | 13 + .../components/aca-header.component.ts | 1 + .../datetime-picker.component.ts | 58 ++++ .../page-objects/components/dialogs/index.ts | 1 + .../dialogs/share-dialog.component.ts | 106 +++++++ .../src/page-objects/components/index.ts | 1 + .../page-objects/pages/personal-files.page.ts | 4 +- .../aca-playwright-shared/src/utils/utils.ts | 4 + 11 files changed, 475 insertions(+), 269 deletions(-) create mode 100644 e2e/playwright/actions/src/tests/share/share-file.spec.ts delete mode 100755 e2e/protractor/suites/actions/share/share-file.test.ts create mode 100644 projects/aca-playwright-shared/src/page-objects/components/datetime-picker/datetime-picker.component.ts create mode 100644 projects/aca-playwright-shared/src/page-objects/components/dialogs/share-dialog.component.ts diff --git a/e2e/playwright/actions/src/tests/share/share-file.spec.ts b/e2e/playwright/actions/src/tests/share/share-file.spec.ts new file mode 100644 index 0000000000..9c5f5d2312 --- /dev/null +++ b/e2e/playwright/actions/src/tests/share/share-file.spec.ts @@ -0,0 +1,248 @@ +/*! + * 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 { ApiClientFactory, NodesApi, test, timeouts, Utils, SharedLinksApi } from '@alfresco/playwright-shared'; +import { expect } from '@playwright/test'; + +test.describe('Share a file', () => { + const random = Utils.random(); + + const username = `user-${random}`; + const parent = `parent-${random}`; + let parentId: string; + + const file3 = `file3-${random}.txt`; + const file4 = `file4-${random}.txt`; + const file5 = `file5-${random}.txt`; + const file6 = `file6-${random}.txt`; + const file7 = `file7-${random}.txt`; + const file8 = `file8-${random}.txt`; + const file9 = `file9-${random}.txt`; + + const shareLinkPreUrl = `/#/preview/s/`; + + const apiClientFactory = new ApiClientFactory(); + + test.beforeAll(async () => { + test.setTimeout(timeouts.extendedTest); + await apiClientFactory.setUpAcaBackend('admin'); + await apiClientFactory.createUser({ username }); + const nodesApi = await NodesApi.initialize(username, username); + + parentId = (await nodesApi.createFolder(parent)).entry.id; + }); + + test.afterAll(async () => { + await apiClientFactory.nodes.deleteNodes([parentId]); + }); + + test.describe('when logged out', () => { + let file6SharedLink: string; + let file6Id: string; + + test.beforeAll(async () => { + test.setTimeout(timeouts.extendedTest); + const nodesApi = await NodesApi.initialize(username, username); + const shareApi = await SharedLinksApi.initialize(username, username); + + file6Id = (await nodesApi.createFile(file6, parentId))?.entry.id; + + const sharedId = (await shareApi.shareFileById(file6Id)).entry.id; + file6SharedLink = `${shareLinkPreUrl}${sharedId}`; + await shareApi.waitForFilesToBeShared([file6Id]); + }); + + test.afterAll(async () => { + await apiClientFactory.nodes.deleteNodes([file6Id]); + }); + + test('[C286326] A non-logged user can download the shared file from the viewer', async ({ personalFiles, page }) => { + await page.goto(file6SharedLink); + await personalFiles.viewer.waitForViewerToOpen(); + + const downloadPromise = personalFiles.page.waitForEvent('download'); + await personalFiles.viewer.toolbar.sharedDownloadButton.click(); + const download = await downloadPromise; + expect(download.suggestedFilename()).toBe(file6); + }); + }); + + test.describe('when logged in', () => { + const expiryDateObj: Date = new Date(); + expiryDateObj.setFullYear(expiryDateObj.getFullYear() + 1); + const expiryDate: any = expiryDateObj.toISOString().replace('Z', '+0000'); + + test.describe('from Personal Files', () => { + let file3Id: string; + let file4Id: string; + let file5Id: string; + let file6Id: string; + let file7Id: string; + let file8Id: string; + let file9Id: string; + + test.beforeAll(async () => { + test.setTimeout(timeouts.extendedTest); + const nodesApi = await NodesApi.initialize(username, username); + const shareApi = await SharedLinksApi.initialize(username, username); + + file3Id = (await nodesApi.createFile(file3, parentId))?.entry.id; + file4Id = (await nodesApi.createFile(file4, parentId))?.entry.id; + file5Id = (await nodesApi.createFile(file5, parentId))?.entry.id; + file6Id = (await nodesApi.createFile(file6, parentId))?.entry.id; + file7Id = (await nodesApi.createFile(file7, parentId))?.entry.id; + file8Id = (await nodesApi.createFile(file8, parentId))?.entry.id; + file9Id = (await nodesApi.createFile(file9, parentId))?.entry.id; + + await shareApi.shareNodes([file6Id, file7Id], expiryDate); + await shareApi.waitForFilesToBeShared([file6Id, file7Id]); + }); + + test.beforeEach(async ({ loginPage, personalFiles, page }) => { + await loginPage.navigate(); + await loginPage.loginUser({ username: username, password: username }); + + await personalFiles.waitForPageLoad(); + await personalFiles.dataTable.getCellByColumnNameAndRowItem(parent, 'Size').dblclick(); + await page.waitForTimeout(timeouts.tiny); + }); + + test.afterAll(async () => { + const nodesApi = await NodesApi.initialize(username, username); + await nodesApi.deleteNodes([file3Id, file4Id, file5Id, file6Id, file7Id, file8Id, file9Id]); + }); + + test('[C286327] Share dialog default values', async ({ personalFiles }) => { + expect(await personalFiles.dataTable.performActionFromExpandableMenu(file3, 'Share')); + const labels = await personalFiles.shareDialog.getLabels(); + expect(await personalFiles.shareDialog.getDialogTitle()).toEqual(`Share ${file3}`); + expect(labels[0].trim()).toBe(`Share ${file3}`); + expect(await personalFiles.shareDialog.getInfoText()).toEqual('Share Link'); + expect(await personalFiles.shareDialog.getLinkUrl()).toContain(shareLinkPreUrl); + expect(await personalFiles.shareDialog.isUrlReadOnly()).toBe(true); + expect(await personalFiles.shareDialog.isShareToggleChecked()).toBe(true); + expect(labels[1].trim()).toBe('Link Expiry Date'); + expect(await personalFiles.shareDialog.isExpireToggleEnabled()).toBe(false); + expect(await personalFiles.shareDialog.isCloseEnabled()).toBe(true); + }); + + test('[C286329] Share a file', async ({ personalFiles, nodesApiAction }) => { + expect(await personalFiles.dataTable.performActionFromExpandableMenu(file3, 'Share')); + + const url = await personalFiles.shareDialog.getLinkUrl(); + await personalFiles.shareDialog.clickClose(); + + const sharedId = await nodesApiAction.getSharedId(file3Id); + expect(url).toContain(sharedId); + }); + + test('[C286330] Copy shared file URL', async ({ personalFiles, page }) => { + expect(await personalFiles.dataTable.performActionFromExpandableMenu(file4, 'Share')); + + const url = await personalFiles.shareDialog.getLinkUrl(); + expect(url).toContain(shareLinkPreUrl); + + await personalFiles.shareDialog.urlAction.click(); + + const shareSnackBar = personalFiles.snackBar; + await expect(shareSnackBar.getByMessageLocator('Link copied to the clipboard')).toBeVisible(); + + await page.goto(url); + await personalFiles.viewer.waitForViewerToOpen(); + + const downloadPromise = personalFiles.page.waitForEvent('download'); + await personalFiles.viewer.toolbar.sharedDownloadButton.click(); + + const download = await downloadPromise; + expect(download.suggestedFilename()).toBe(file4); + }); + + test('[C286332] Share a file with expiration date', async ({ personalFiles, nodesApiAction, page }) => { + expect(await personalFiles.dataTable.performActionFromExpandableMenu(file5, 'Share')); + + await personalFiles.shareDialog.expireToggle.click(); + expect(await personalFiles.shareDialog.isExpireToggleEnabled()).toBe(true); + + await personalFiles.shareDialog.datetimePickerButton.click(); + expect(await personalFiles.shareDialog.dateTimePicker.isCalendarOpen()).toBe(true); + + await personalFiles.shareDialog.dateTimePicker.pickDateTime(); + + const inputDate = await personalFiles.shareDialog.getExpireDate(); + + await page.waitForTimeout(timeouts.normal); + const expireDateProperty = await nodesApiAction.getSharedExpiryDate(file5Id); + + expect(Utils.formatDate(expireDateProperty)).toEqual(Utils.formatDate(inputDate)); + }); + + test('[C286337] Expire date is displayed correctly', async ({ personalFiles, nodesApiAction }) => { + expect(await personalFiles.dataTable.performActionFromExpandableMenu(file6, 'Share')); + const expireProperty = await nodesApiAction.getSharedExpiryDate(file6Id); + + expect(expireProperty).toEqual(expiryDate); + expect(await personalFiles.shareDialog.isExpireToggleEnabled()).toBe(true); + expect(Utils.formatDate(await personalFiles.shareDialog.getExpireDate())).toEqual(Utils.formatDate(expiryDate)); + }); + + test('[C286333] Disable the share link expiration', async ({ personalFiles, nodesApiAction, page }) => { + expect(await personalFiles.dataTable.performActionFromExpandableMenu(file7, 'Share')); + + expect(await personalFiles.shareDialog.isExpireToggleEnabled()).toBe(true); + expect(await personalFiles.shareDialog.getExpireDate()).not.toBe(''); + + await personalFiles.shareDialog.expireToggle.click(); + expect(await personalFiles.shareDialog.isExpireToggleEnabled()).toBe(false); + + page.waitForTimeout(timeouts.tiny); + await personalFiles.shareDialog.clickClose(); + expect(await nodesApiAction.getSharedExpiryDate(file7Id)).toBe(''); + }); + + test('[C286335] Shared file URL is not changed when Share dialog is closed and opened again', async ({ personalFiles }) => { + expect(await personalFiles.dataTable.performActionFromExpandableMenu(file8, 'Share')); + + const url1 = await personalFiles.shareDialog.getLinkUrl(); + await personalFiles.shareDialog.clickClose(); + + await personalFiles.dataTable.selectItem(file8); + await personalFiles.acaHeader.shareButton.click(); + const url2 = await personalFiles.shareDialog.getLinkUrl(); + + expect(url1).toEqual(url2); + }); + + test('[C286345] Share a file from the context menu', async ({ personalFiles, nodesApiAction }) => { + expect(await personalFiles.dataTable.performActionFromExpandableMenu(file9, 'Share')); + + const url = await personalFiles.shareDialog.getLinkUrl(); + await personalFiles.shareDialog.clickClose(); + + const sharedId = await nodesApiAction.getSharedId(file9Id); + expect(await nodesApiAction.isFileShared(file9Id)).toBe(true); + expect(url).toContain(sharedId); + }); + }); + }); +}); diff --git a/e2e/protractor/suites/actions/share/share-file.test.ts b/e2e/protractor/suites/actions/share/share-file.test.ts deleted file mode 100755 index ea6a4dd41c..0000000000 --- a/e2e/protractor/suites/actions/share/share-file.test.ts +++ /dev/null @@ -1,268 +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, RepoClient, ShareDialog, Viewer, Utils } from '@alfresco/aca-testing-shared'; -import { BrowserActions } from '@alfresco/adf-testing'; - -describe('Share a file', () => { - const username = `user-${Utils.random()}`; - const parent = `parent-${Utils.random()}`; - let parentId: string; - - const file3 = `file3-${Utils.random()}.txt`; - const file4 = `file4-${Utils.random()}.txt`; - const file5 = `file5-${Utils.random()}.txt`; - const file6 = `file6-${Utils.random()}.txt`; - const file7 = `file7-${Utils.random()}.txt`; - const file8 = `file8-${Utils.random()}.txt`; - const file9 = `file9-${Utils.random()}.txt`; - - const viewer = new Viewer(); - const page = new BrowsingPage(); - const { dataTable, toolbar } = page; - const shareLinkPreUrl = `/#/preview/s/`; - - const apis = { - user: new RepoClient(username, username) - }; - - const adminApiActions = new AdminActions(); - const userActions = new UserActions(); - - beforeAll(async () => { - await adminApiActions.createUser({ username }); - await userActions.login(username, username); - - parentId = await apis.user.createFolder(parent); - }); - - afterAll(async () => { - await userActions.deleteNodes([parentId]); - }); - - describe('when logged out', () => { - let file6SharedLink: string; - let file6Id: string; - - beforeAll(async () => { - file6Id = await apis.user.createFile(file6, parentId); - - const sharedId = (await apis.user.shared.shareFileById(file6Id)).entry.id; - file6SharedLink = `${shareLinkPreUrl}${sharedId}`; - await apis.user.shared.waitForFilesToBeShared([file6Id]); - }); - - afterAll(async () => { - await userActions.deleteNodes([file6Id]); - }); - - it('[C286326] A non-logged user can download the shared file from the viewer', async () => { - await browser.get(file6SharedLink); - await viewer.waitForTxtViewerToLoad(); - - expect(await viewer.getFileTitle()).toEqual(file6); - - await BrowserActions.click(viewer.toolbar.downloadButton); - expect(await Utils.fileExistsOnOS(file6)).toBe(true, 'File not found in download location'); - }); - }); - - describe('when logged in', () => { - const expiryDateObj: Date = new Date(); - expiryDateObj.setFullYear(expiryDateObj.getFullYear() + 1); - const expiryDate: any = expiryDateObj.toISOString().replace('Z', '+0000'); - - const loginPage = new LoginPage(); - const shareDialog = new ShareDialog(); - const contextMenu = dataTable.menu; - - beforeAll(async () => { - await loginPage.loginWith(username); - }); - - describe('from Personal Files', () => { - let file3Id: string; - let file4Id: string; - let file5Id: string; - let file6Id: string; - let file7Id: string; - let file8Id: string; - let file9Id: string; - - beforeAll(async () => { - file3Id = await apis.user.createFile(file3, parentId); - file4Id = await apis.user.createFile(file4, parentId); - file5Id = await apis.user.createFile(file5, parentId); - file6Id = await apis.user.createFile(file6, parentId); - file7Id = await apis.user.createFile(file7, parentId); - file8Id = await apis.user.createFile(file8, parentId); - file9Id = await apis.user.createFile(file9, parentId); - - await userActions.login(username, username); - await userActions.shareNodes([file6Id, file7Id], expiryDate); - await apis.user.shared.waitForFilesToBeShared([file6Id, file7Id]); - }); - - beforeEach(async () => { - await page.clickPersonalFilesAndWait(); - await dataTable.doubleClickOnRowByName(parent); - await dataTable.waitForHeader(); - }); - - afterEach(async () => { - await Utils.pressEscape(); - await page.closeOpenDialogs(); - }); - - afterAll(async () => { - await userActions.deleteNodes([file3Id, file4Id, file5Id, file6Id, file7Id, file8Id, file9Id]); - }); - - it('[C286327] Share dialog default values', async () => { - await dataTable.selectItem(file3); - await toolbar.shareButton.click(); - await shareDialog.waitForDialogToOpen(); - - expect(await shareDialog.getDialogTitle()).toEqual(`Share ${file3}`); - expect(await shareDialog.getInfoText()).toEqual('Share Link'); - expect(await shareDialog.labels.get(0).getText()).toEqual(`Share ${file3}`); - expect(await shareDialog.getLinkUrl()).toContain(shareLinkPreUrl); - expect(await shareDialog.isUrlReadOnly()).toBe(true, 'url is not readonly'); - expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle not checked'); - expect(await shareDialog.labels.get(1).getText()).toEqual('Link Expiry Date'); - expect(await shareDialog.isExpireToggleEnabled()).toBe(false, 'Expire toggle is checked'); - expect(await shareDialog.isCloseEnabled()).toBe(true, 'Close button is not enabled'); - }); - - it('[C286329] Share a file', async () => { - await dataTable.selectItem(file3); - await toolbar.shareButton.click(); - await shareDialog.waitForDialogToOpen(); - - const url = await shareDialog.getLinkUrl(); - await shareDialog.clickClose(); - - const sharedId = await apis.user.nodes.getSharedId(file3Id); - expect(url).toContain(sharedId); - }); - - it('[C286330] Copy shared file URL', async () => { - await dataTable.selectItem(file4); - await toolbar.shareButton.click(); - await shareDialog.waitForDialogToOpen(); - - const url = await shareDialog.getLinkUrl(); - expect(url).toContain(shareLinkPreUrl); - - await BrowserActions.click(shareDialog.urlAction); - expect(await page.getSnackBarMessage()).toBe('Link copied to the clipboard'); - - await browser.get(url); - - await viewer.waitForViewerToOpen(); - expect(await viewer.getFileTitle()).toEqual(file4); - - await page.load(); - }); - - it('[C286332] Share a file with expiration date', async () => { - await dataTable.selectItem(file5); - await toolbar.shareButton.click(); - await shareDialog.waitForDialogToOpen(); - - await BrowserActions.click(shareDialog.expireToggle); - expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expire toggle not checked'); - - await BrowserActions.click(shareDialog.datetimePickerButton); - expect(await shareDialog.dateTimePicker.isCalendarOpen()).toBe(true, 'Calendar not opened'); - await shareDialog.dateTimePicker.pickDateTime(); - await shareDialog.dateTimePicker.waitForDateTimePickerToClose(); - - const inputDate = await shareDialog.getExpireDate(); - const expireDateProperty = await apis.user.nodes.getSharedExpiryDate(file5Id); - - expect(Utils.formatDate(expireDateProperty)).toEqual(Utils.formatDate(inputDate)); - }); - - it('[C286337] Expire date is displayed correctly', async () => { - await dataTable.selectItem(file6); - await BrowserActions.click(toolbar.shareButton); - await shareDialog.waitForDialogToOpen(); - - const expireProperty = await apis.user.nodes.getSharedExpiryDate(file6Id); - expect(expireProperty).toEqual(expiryDate); - expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expiration is not checked'); - expect(Utils.formatDate(await shareDialog.getExpireDate())).toEqual(Utils.formatDate(expiryDate)); - }); - - it('[C286333] Disable the share link expiration', async () => { - await dataTable.selectItem(file7); - await BrowserActions.click(toolbar.shareButton); - await shareDialog.waitForDialogToOpen(); - - expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expiration is not checked'); - expect(await shareDialog.getExpireDate()).not.toBe('', 'Expire date input is empty'); - - await BrowserActions.click(shareDialog.expireToggle); - expect(await shareDialog.isExpireToggleEnabled()).toBe(false, 'Expiration is checked'); - expect(await shareDialog.expireInput.isDisplayed()).toBe(false, 'Expire date input is not empty'); - - await shareDialog.clickClose(); - expect(await apis.user.nodes.getSharedExpiryDate(file7Id)).toBe('', `${file7} link still has expiration`); - }); - - it('[C286335] Shared file URL is not changed when Share dialog is closed and opened again', async () => { - await dataTable.selectItem(file8); - await toolbar.shareButton.click(); - await shareDialog.waitForDialogToOpen(); - - const url1 = await shareDialog.getLinkUrl(); - await shareDialog.clickClose(); - - await page.dataTable.clearSelection(); - await dataTable.selectItem(file8); - await BrowserActions.click(toolbar.shareButton); - await shareDialog.waitForDialogToOpen(); - const url2 = await shareDialog.getLinkUrl(); - - expect(url1).toEqual(url2); - }); - - it('[C286345] Share a file from the context menu', async () => { - await dataTable.rightClickOnItem(file9); - await contextMenu.waitForMenuToOpen(); - await contextMenu.shareAction.click(); - await shareDialog.waitForDialogToOpen(); - - const url = await shareDialog.getLinkUrl(); - await shareDialog.clickClose(); - - const sharedId = await apis.user.nodes.getSharedId(file9Id); - expect(await apis.user.nodes.isFileShared(file9Id)).toBe(true, `${file9} is not shared`); - expect(url).toContain(sharedId); - }); - }); - }); -}); diff --git a/projects/aca-playwright-shared/src/api/nodes-api.ts b/projects/aca-playwright-shared/src/api/nodes-api.ts index c83f563888..8f3415f27a 100755 --- a/projects/aca-playwright-shared/src/api/nodes-api.ts +++ b/projects/aca-playwright-shared/src/api/nodes-api.ts @@ -401,4 +401,44 @@ export class NodesApi { return null; } } + + async getNodeProperty(nodeId: string, property: string): Promise { + try { + const node = await this.getNodeById(nodeId); + return (node.entry.properties && node.entry.properties[property]) || ''; + } catch (error) { + console.error(`${this.constructor.name} ${this.getNodeProperty.name}`, error); + return ''; + } + } + + async getSharedId(nodeId: string): Promise { + try { + const sharedId = await this.getNodeProperty(nodeId, 'qshare:sharedId'); + return sharedId || ''; + } catch (error) { + console.error(`${this.constructor.name} ${this.getSharedId.name}`, error); + return ''; + } + } + + async getSharedExpiryDate(nodeId: string): Promise { + try { + const expiryDate = await this.getNodeProperty(nodeId, 'qshare:expiryDate'); + return expiryDate || ''; + } catch (error) { + console.error(`${this.constructor.name} ${this.getSharedExpiryDate.name}`, error); + return ''; + } + } + + async isFileShared(nodeId: string): Promise { + try { + const sharedId = await this.getSharedId(nodeId); + return sharedId !== ''; + } catch (error) { + console.error(`${this.constructor.name} ${this.isFileShared.name}`, error); + return null; + } + } } 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 b7f995a32f..3f53db137c 100755 --- a/projects/aca-playwright-shared/src/api/shared-links-api.ts +++ b/projects/aca-playwright-shared/src/api/shared-links-api.ts @@ -77,6 +77,19 @@ export class SharedLinksApi { } } + async shareNodes(nodeIds: string[], expiresAt?: Date): Promise { + try { + for (const nodeId of nodeIds) { + await this.apiService.share.createSharedLink({ + nodeId, + expiresAt + }); + } + } catch (error) { + console.error('User Actions - shareNodes failed : ', error); + } + } + async waitForFilesToBeShared(filesIds: string[]): Promise { try { const sharedFile = async () => { 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 2e0252b67d..9f9eceefb9 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 @@ -37,6 +37,7 @@ export class AcaHeader extends BaseComponent { public fullScreenButton = this.getChild('button[id="app.viewer.fullscreen"]'); public shareButton = this.getChild('button[id="share-action-button"]'); public downloadButton = this.getChild('button[id="app.viewer.download"]'); + public sharedDownloadButton = this.getChild('button[id="app.viewer.shared.download"]'); constructor(page: Page) { super(page, AcaHeader.rootElement); diff --git a/projects/aca-playwright-shared/src/page-objects/components/datetime-picker/datetime-picker.component.ts b/projects/aca-playwright-shared/src/page-objects/components/datetime-picker/datetime-picker.component.ts new file mode 100644 index 0000000000..2af6a80110 --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/components/datetime-picker/datetime-picker.component.ts @@ -0,0 +1,58 @@ +/*! + * Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +import { Page } from '@playwright/test'; +import { BaseComponent } from '../base.component'; + +export class DateTimePicker extends BaseComponent { + private static rootElement = '.mat-calendar'; + calendar = this.getChild('.mat-datepicker-popup'); + dayPicker = this.getChild('mat-month-view'); + nextMonthBtn = this.getChild('.mat-calendar-next-button'); + rootElemLocator = this.page.locator('.mat-datepicker-popup'); + + constructor(page: Page) { + super(page, DateTimePicker.rootElement); + } + + async isCalendarOpen(): Promise { + const element = this.rootElemLocator; + return element.isVisible(); + } + + async pickDateTime(): Promise { + const today = new Date(); + const nextAvailableDay = new Date(); + nextAvailableDay.setDate(today.getDate() + 2); + if (nextAvailableDay.getMonth() !== today.getMonth()) { + await await this.nextMonthBtn.click(); + } + await this.selectDay(nextAvailableDay.getDate()); + } + + async selectDay(day: number): Promise { + const firstActiveDayElem = this.dayPicker.locator(`text=${day}`).first(); + await firstActiveDayElem.click(); + } +} 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 c1a913f24d..091bd03320 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 @@ -29,3 +29,4 @@ export * from './viewer-overlay-dialog.component'; export * from './content-node-selector-dialog'; export * from './create-from-template-dialog-component'; export * from './adf-confirm-dialog.component'; +export * from './share-dialog.component'; diff --git a/projects/aca-playwright-shared/src/page-objects/components/dialogs/share-dialog.component.ts b/projects/aca-playwright-shared/src/page-objects/components/dialogs/share-dialog.component.ts new file mode 100644 index 0000000000..6bcdc8cf4a --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/components/dialogs/share-dialog.component.ts @@ -0,0 +1,106 @@ +/*! + * Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +import { Locator, Page } from '@playwright/test'; +import { BaseComponent } from '../base.component'; +import { timeouts } from '../../../utils'; +import { DateTimePicker } from '../datetime-picker/datetime-picker.component'; + +export class ShareDialogComponent extends BaseComponent { + private static rootElement = 'adf-share-dialog'; + + constructor(page: Page) { + super(page, ShareDialogComponent.rootElement); + } + + closeButton = this.getChild('[data-automation-id="adf-share-dialog-close"]'); + dialogTitle = this.getChild('[data-automation-id="adf-share-dialog-title"]'); + infoText = this.getChild('.adf-share-link__info').first(); + labels = '.adf-share-link__label'; + shareToggle = this.getChild(`[data-automation-id='adf-share-toggle']`); + url = this.getChild(`[data-automation-id='adf-share-link']`); + urlAction = this.getChild('.adf-input-action'); + expireToggle = this.getChild(`[data-automation-id='adf-expire-toggle']`); + expireInput = this.getChild('input[formcontrolname="time"]'); + datetimePickerButton = this.getChild('.mat-datepicker-toggle'); + + dateTimePicker = new DateTimePicker(this.page); + + getDialogLabel = () => this.getChild('label').innerText(); + getErrorByText = (text: string): Locator => this.page.locator('mat-error', { hasText: text }); + + async getLabels() { + return await this.page.$$eval('.adf-share-link__label', (elements) => elements.map((element) => element.textContent)); + } + + async isErrorMessageDisplayed(errorText: string): Promise { + await this.getErrorByText(errorText).waitFor({ state: 'visible', timeout: timeouts.large }); + return await this.getErrorByText(errorText).isVisible(); + } + + async getDialogTitle(): Promise { + return await this.dialogTitle.innerText(); + } + + async getInfoText(): Promise { + return await this.infoText.innerText(); + } + + async getLinkUrl(): Promise { + return await this.url.inputValue(); + } + + async isUrlReadOnly(): Promise { + const urlAttr = await this.url.getAttribute('readonly'); + return urlAttr === 'true'; + } + + async isCloseEnabled(): Promise { + return await this.closeButton.isEnabled(); + } + + async clickClose(): Promise { + await this.page.waitForTimeout(timeouts.tiny); + await this.closeButton.click(); + } + + async isShareToggleChecked(): Promise { + const toggleClass = await this.shareToggle.getAttribute('class'); + return toggleClass.includes('checked'); + } + + async isShareToggleDisabled(): Promise { + const toggleClass = await this.shareToggle.getAttribute('class'); + return toggleClass.includes('mat-disabled'); + } + + async isExpireToggleEnabled(): Promise { + const toggleClass = await this.expireToggle.getAttribute('class'); + return toggleClass.includes('checked'); + } + + async getExpireDate(): Promise { + return await this.expireInput.inputValue(); + } +} 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..4e3182f5e4 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 './datetime-picker/datetime-picker.component'; 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..602de49a27 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, + ShareDialogComponent } 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 shareDialog= new ShareDialogComponent(this.page); async selectCreateFolder(): Promise { await this.acaHeader.createButton.click(); diff --git a/projects/aca-playwright-shared/src/utils/utils.ts b/projects/aca-playwright-shared/src/utils/utils.ts index d11ba3ed3f..3bc69e54ee 100644 --- a/projects/aca-playwright-shared/src/utils/utils.ts +++ b/projects/aca-playwright-shared/src/utils/utils.ts @@ -42,4 +42,8 @@ export class Utils { return run(retry); } + + static formatDate(date: string): string { + return new Date(date).toLocaleDateString('en-US'); + } }