diff --git a/e2e/playwright/viewer/src/tests/viewer-zoom-functionality.e2e.ts b/e2e/playwright/viewer/src/tests/viewer-zoom-functionality.e2e.ts new file mode 100644 index 000000000..fa271111f --- /dev/null +++ b/e2e/playwright/viewer/src/tests/viewer-zoom-functionality.e2e.ts @@ -0,0 +1,232 @@ +/*! + * Copyright © 2005-2025 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, + SharedLinksApi, + SitesApi, + test, + TEST_FILES, + timeouts, + Utils, + TrashcanApi, + PersonalFilesPage, + MyLibrariesPage, + RecentFilesPage, + FavoritesLibrariesPage, + SharedPage, + FavoritesPage +} from '@alfresco/aca-playwright-shared'; +import { Site } from '@alfresco/js-api'; + +test.describe('viewer zoom functionality and reset', () => { + const username = `user-${Utils.random()}`; + const randomJpgName = `${TEST_FILES.JPG_FILE.name}-${Utils.random()}.jpg`; + const randomPngName = `${TEST_FILES.PNG_FILE.name}-${Utils.random()}.png`; + const randomPdfName = `${TEST_FILES.PDF.name}-${Utils.random()}.pdf`; + const randomDocxName = `${TEST_FILES.DOCX.name}-${Utils.random()}.docx`; + const randomLibraryName = `playwright-library3-${Utils.random()}`; + let docLibId: string; + let folderId: string; + let siteActionsUser: SitesApi; + let trashcanApi: TrashcanApi; + let nodesApi: NodesApi; + + test.beforeAll(async () => { + const apiClientFactory = new ApiClientFactory(); + await apiClientFactory.setUpAcaBackend('admin'); + try { + await apiClientFactory.createUser({ username }); + } catch (exception) { + if (JSON.parse(exception.message).error.statusCode !== 409) { + throw new Error(`----- beforeAll failed : ${exception}`); + } + } + + test.setTimeout(timeouts.extendedTest); + const randomFolderName = `viewer-${Utils.random()}`; + nodesApi = await NodesApi.initialize(username, username); + const fileActionApi = await FileActionsApi.initialize(username, username); + trashcanApi = await TrashcanApi.initialize(username, username); + siteActionsUser = await SitesApi.initialize(username, username); + const shareActions = await SharedLinksApi.initialize(username, username); + const favoritesActions = await FavoritesPageApi.initialize(username, username); + const node = await nodesApi.createFolder(randomFolderName); + folderId = node.entry.id; + + try { + await siteActionsUser.createSite(randomLibraryName, Site.VisibilityEnum.PRIVATE); + } catch (exception) { + if (JSON.parse(exception.message).error.statusCode !== 409) { + throw new Error(`----- beforeAll failed : ${exception}`); + } + } + + docLibId = await siteActionsUser.getDocLibId(randomLibraryName); + + await fileActionApi.uploadFile(TEST_FILES.JPG_FILE.path, randomJpgName, folderId); + await fileActionApi.uploadFile(TEST_FILES.DOCX.path, randomDocxName, docLibId); + const filePngId = (await fileActionApi.uploadFile(TEST_FILES.PNG_FILE.path, randomPngName, folderId)).entry.id; + const filePdfId = (await fileActionApi.uploadFile(TEST_FILES.PDF.path, randomPdfName, folderId)).entry.id; + + const consumerFavoritesTotalItems = await favoritesActions.getFavoritesTotalItems(username); + await shareActions.shareFileById(filePngId); + await favoritesActions.addFavoriteById('file', filePdfId); + + await Promise.all([ + favoritesActions.isFavoriteWithRetry(username, filePdfId, { expect: true }), + favoritesActions.waitForApi(username, { expect: consumerFavoritesTotalItems + 2 }) + ]); + try { + await shareActions.waitForFilesToBeShared([filePngId]); + await fileActionApi.waitForNodes(randomPngName, { expect: 1 }); + } catch (exception) { + if (JSON.parse(exception.message).error.statusCode !== 409) { + throw new Error(`----- beforeAll failed : ${exception}`); + } + } + }); + + test.beforeEach(async ({ personalFiles, loginPage }) => { + await Utils.tryLoginUser(loginPage, username, username, 'beforeEach failed'); + await personalFiles.navigate({ remoteUrl: `#/personal-files/${folderId}` }); + }); + + test.afterAll(async () => { + await Utils.deleteNodesSitesEmptyTrashcan(nodesApi, trashcanApi, 'afterAll failed', siteActionsUser, [docLibId]); + }); + + async function validateZoomScaleInViewer( + pageToValidate: PersonalFilesPage | RecentFilesPage | SharedPage | FavoritesLibrariesPage | MyLibrariesPage + ): Promise { + const defaultZoomSize: number = parseInt(await pageToValidate.viewer.zoomScale.innerText(), 10); + expect(defaultZoomSize).toBe(100); + await pageToValidate.viewer.zoomInButton.click(); + expect(parseInt(await pageToValidate.viewer.zoomScale.innerText(), 10)).toBeGreaterThan(defaultZoomSize); + await pageToValidate.viewer.zoomOutButton.click(); + expect(parseInt(await pageToValidate.viewer.zoomScale.innerText(), 10)).toEqual(defaultZoomSize); + await pageToValidate.viewer.zoomOutButton.click(); + expect(parseInt(await pageToValidate.viewer.zoomScale.innerText(), 10)).toBeLessThan(defaultZoomSize); + await pageToValidate.viewer.zoomInButton.click(); + expect(parseInt(await pageToValidate.viewer.zoomScale.innerText(), 10)).toEqual(defaultZoomSize); + } + + async function validateZoomResetButtonActivity(pageToValidate: PersonalFilesPage | RecentFilesPage | SharedPage): Promise { + await pageToValidate.viewer.zoomInButton.click(); + await pageToValidate.viewer.zoomResetButton.click(); + expect(parseInt(await pageToValidate.viewer.zoomScale.innerText(), 10)).toEqual(100); + await pageToValidate.viewer.zoomInButton.click(); + await pageToValidate.viewer.zoomResetButton.click(); + expect(parseInt(await pageToValidate.viewer.zoomScale.innerText(), 10)).toEqual(100); + } + + async function validateFitToPageButtonActivity(pageToValidate: FavoritesPage | MyLibrariesPage): Promise { + await pageToValidate.viewer.zoomInButton.click(); + await pageToValidate.viewer.fitToPageButton.click(); + expect(parseInt(await pageToValidate.viewer.zoomScale.innerText(), 10)).toEqual(100); + await pageToValidate.viewer.zoomInButton.click(); + await pageToValidate.viewer.fitToPageButton.click(); + expect(parseInt(await pageToValidate.viewer.zoomScale.innerText(), 10)).toEqual(100); + } + + test('[XAT-17637] Zoom functionality when a jpg image is opened in viewer mode in Personal Files', async ({ personalFiles }) => { + await personalFiles.dataTable.performClickFolderOrFileToOpen(randomJpgName); + expect(await personalFiles.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); + await validateZoomScaleInViewer(personalFiles); + }); + + test('[XAT-17650] Zoom functionality when a jpg file is opened in viewer mode in Recent Files', async ({ recentFilesPage }) => { + await recentFilesPage.navigate(); + await recentFilesPage.dataTable.performClickFolderOrFileToOpen(randomJpgName); + expect(await recentFilesPage.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); + await validateZoomScaleInViewer(recentFilesPage); + }); + + test('[XAT-17638] Zoom functionality when a png image is opened in viewer mode in Shared Files', async ({ sharedPage }) => { + await sharedPage.navigate(); + await sharedPage.dataTable.performClickFolderOrFileToOpen(randomPngName); + expect(await sharedPage.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); + await validateZoomScaleInViewer(sharedPage); + }); + + test('[XAT-17639] Zoom functionality when a pdf file is opened in viewer mode in Favorite Files', async ({ favoritePage }) => { + await favoritePage.navigate(); + await favoritePage.dataTable.performClickFolderOrFileToOpen(randomPdfName); + expect(await favoritePage.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); + await favoritePage.viewer.waitForZoomPercentageToDisplay(); + await validateZoomScaleInViewer(favoritePage); + }); + + test('[XAT-17640] Zoom functionality when a document is opened in viewer mode in Libraries Files', async ({ myLibrariesPage }) => { + await myLibrariesPage.navigate(); + await myLibrariesPage.dataTable.performClickFolderOrFileToOpen(randomLibraryName); + await myLibrariesPage.dataTable.performClickFolderOrFileToOpen(randomDocxName); + await myLibrariesPage.viewer.waitForViewerLoaderToFinish(); + expect(await myLibrariesPage.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); + await myLibrariesPage.viewer.waitForZoomPercentageToDisplay(); + await validateZoomScaleInViewer(myLibrariesPage); + }); + + test('[XAT-17641] User can restore the default state of jpg image in viewer mode in Personal Files', async ({ personalFiles }) => { + await personalFiles.dataTable.performClickFolderOrFileToOpen(randomJpgName); + expect(await personalFiles.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); + await validateZoomResetButtonActivity(personalFiles); + }); + + test('[XAT-17651] User can restore the default state of jpg image in viewer mode in Recent Files', async ({ recentFilesPage }) => { + await recentFilesPage.navigate(); + await recentFilesPage.dataTable.performClickFolderOrFileToOpen(randomJpgName); + expect(await recentFilesPage.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); + await validateZoomResetButtonActivity(recentFilesPage); + }); + + test('[XAT-17642] User can restore the default state of png image in viewer mode in Shared Files', async ({ sharedPage }) => { + await sharedPage.navigate(); + await sharedPage.dataTable.performClickFolderOrFileToOpen(randomPngName); + expect(await sharedPage.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); + await validateZoomResetButtonActivity(sharedPage); + }); + + test('[XAT-17643] User can restore the default state of pdf file in viewer mode in Favorites Files', async ({ favoritePage }) => { + await favoritePage.navigate(); + await favoritePage.dataTable.performClickFolderOrFileToOpen(randomPdfName); + expect(await favoritePage.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); + await favoritePage.viewer.waitForZoomPercentageToDisplay(); + await validateFitToPageButtonActivity(favoritePage); + }); + + test('[XAT-17644] User can restore the default state of doc file in viewer mode in Libraries Files', async ({ myLibrariesPage }) => { + await myLibrariesPage.navigate(); + await myLibrariesPage.dataTable.performClickFolderOrFileToOpen(randomLibraryName); + await myLibrariesPage.dataTable.performClickFolderOrFileToOpen(randomDocxName); + await myLibrariesPage.viewer.waitForViewerLoaderToFinish(); + expect(await myLibrariesPage.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); + await myLibrariesPage.viewer.waitForZoomPercentageToDisplay(); + await validateFitToPageButtonActivity(myLibrariesPage); + }); +}); diff --git a/projects/aca-playwright-shared/src/page-objects/components/viewer.component.ts b/projects/aca-playwright-shared/src/page-objects/components/viewer.component.ts index c0ef673bd..62e87b33b 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/viewer.component.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/viewer.component.ts @@ -46,6 +46,11 @@ export class ViewerComponent extends BaseComponent { public viewerPage = this.getChild('[data-automation-id="adf-page-selector"]'); public viewerMedia = this.getChild('adf-media-player'); public viewerSpinner = this.getChild('.adf-viewer-render__loading-screen'); + public zoomInButton = this.getChild('#viewer-zoom-in-button'); + public zoomOutButton = this.getChild('#viewer-zoom-out-button'); + public zoomScale = this.getChild('[data-automation-id="adf-page-scale"]'); + public zoomResetButton = this.getChild('#viewer-reset-button'); + public fitToPageButton = this.getChild('#viewer-scale-page-button'); toolbar = new AcaHeader(this.page); @@ -92,6 +97,24 @@ export class ViewerComponent extends BaseComponent { return this.fileTitleButtonLocator.isVisible(); } + async waitForZoomPercentageToDisplay(): Promise { + await this.zoomScale.waitFor({ state: 'visible', timeout: timeouts.normal }); + const startTime = Date.now(); + let textContent: string; + + while (Date.now() - startTime <= timeouts.medium) { + textContent = await this.zoomScale.innerText(); + if (textContent.trim() !== '') { + break; + } + await this.page.waitForTimeout(timeouts.tiny); + } + + if (textContent.trim() === '') { + throw new Error(`Timeout: Text did not show up within ${timeouts.medium} ms`); + } + } + async getFileTitle(): Promise { await this.fileTitleButtonLocator.waitFor({ state: 'visible', timeout: timeouts.normal }); await this.waitForViewerLoaderToFinish(); diff --git a/projects/aca-playwright-shared/src/utils/timeouts.ts b/projects/aca-playwright-shared/src/utils/timeouts.ts index 8e05847a3..1362b976c 100644 --- a/projects/aca-playwright-shared/src/utils/timeouts.ts +++ b/projects/aca-playwright-shared/src/utils/timeouts.ts @@ -35,5 +35,5 @@ export const timeouts = { extendedTest: 150 * 1000, extendedLongTest: 200 * 1000, webServer: 240 * 1000, - globalSpec: 60 * 10 * 1000 + globalSpec: 90 * 10 * 1000 };