From c67b4dc203697aa4d5bb4ff91b93319dc5bfbb64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C5=9Awiderski?= Date: Tue, 19 May 2026 11:56:56 +0200 Subject: [PATCH] [ACS-11762] Automated MNT 25285 (#5190) * [ACS-11762] Automated MNT 25285 * [ACS-11762] small refactoring * [ACS-11762] more fixes for viewer tests * [ACS-11762] NOSONAR added for type issue * [ACS-11762] copilot review fixes 1 * [ACS-11762] copilot review fixes 2 * [ACS-11762] copilot review fixes 3 * [ACS-11762] review fixes 1 * [ACS-11762] race condition fixed --- .../list-views/src/tests/permissions.e2e.ts | 2 +- .../list-views/src/tests/recent-files.e2e.ts | 2 +- .../list-views/src/tests/shared-files.e2e.ts | 2 +- .../smoke-test/src/tests/viewer/viewer.e2e.ts | 6 ++-- .../viewer/src/tests/viewer-file-types.e2e.ts | 3 +- .../src/tests/viewer-version-actions.e2e.ts | 35 ++++++++++++------- .../tests/viewer-zoom-functionality.e2e.ts | 10 +++--- e2e/playwright/viewer/src/tests/viewer.e2e.ts | 6 ++-- .../src/api/file-actions.ts | 9 +++-- .../components/viewer.component.ts | 30 ++++++++++------ 10 files changed, 63 insertions(+), 42 deletions(-) diff --git a/e2e/playwright/list-views/src/tests/permissions.e2e.ts b/e2e/playwright/list-views/src/tests/permissions.e2e.ts index 12a29e3e3..2c0f7e97d 100755 --- a/e2e/playwright/list-views/src/tests/permissions.e2e.ts +++ b/e2e/playwright/list-views/src/tests/permissions.e2e.ts @@ -48,7 +48,7 @@ test.describe('Special permissions', () => { try { await apiClientFactory.createUser({ username }); } catch (exception) { - if (JSON.parse(exception.message).error.statusCode !== 409) { + if (!String(exception).includes('409')) { throw new Error(`----- beforeAll failed : ${exception}`); } } diff --git a/e2e/playwright/list-views/src/tests/recent-files.e2e.ts b/e2e/playwright/list-views/src/tests/recent-files.e2e.ts index 37b50853d..fc9c46992 100755 --- a/e2e/playwright/list-views/src/tests/recent-files.e2e.ts +++ b/e2e/playwright/list-views/src/tests/recent-files.e2e.ts @@ -49,7 +49,7 @@ test.describe('Recent Files', () => { try { await apiClientFactory.createUser({ username }); } catch (exception) { - if (JSON.parse(exception.message).error.statusCode !== 409) { + if (!String(exception).includes('409')) { throw new Error(`----- beforeAll failed : ${exception}`); } } diff --git a/e2e/playwright/list-views/src/tests/shared-files.e2e.ts b/e2e/playwright/list-views/src/tests/shared-files.e2e.ts index 04b76404a..8fe1c01c0 100644 --- a/e2e/playwright/list-views/src/tests/shared-files.e2e.ts +++ b/e2e/playwright/list-views/src/tests/shared-files.e2e.ts @@ -48,7 +48,7 @@ test.describe('Shared Files', () => { try { await apiClientFactory.createUser({ username }); } catch (exception) { - if (JSON.parse(exception.message).error.statusCode !== 409) { + if (!String(exception).includes('409')) { throw new Error(`----- beforeAll failed : ${exception}`); } } diff --git a/e2e/playwright/smoke-test/src/tests/viewer/viewer.e2e.ts b/e2e/playwright/smoke-test/src/tests/viewer/viewer.e2e.ts index f02014042..05394b544 100644 --- a/e2e/playwright/smoke-test/src/tests/viewer/viewer.e2e.ts +++ b/e2e/playwright/smoke-test/src/tests/viewer/viewer.e2e.ts @@ -55,7 +55,7 @@ test.describe('viewer file', () => { try { await apiClientFactory.createUser({ username: usernameViewer }); } catch (exception) { - if (JSON.parse(exception.message).error.statusCode !== 409) { + if (!String(exception).includes('409')) { throw new Error(`----- beforeAll failed : ${exception}`); } } @@ -71,7 +71,7 @@ test.describe('viewer file', () => { try { await siteActionsAdmin.createSite(siteAdmin, Site.VisibilityEnum.PRIVATE); } catch (exception) { - if (JSON.parse(exception.message).error.statusCode !== 409) { + if (!String(exception).includes('409')) { throw new Error(`----- beforeAll failed : ${exception}`); } } @@ -109,7 +109,7 @@ test.describe('viewer file', () => { test('[XAT-17738] Viewer with preview URL', async ({ personalFiles }) => { const previewURL = `#/personal-files/${folderId}/(viewer:view/${fileDocxId})`; await personalFiles.navigate({ remoteUrl: previewURL }); - await personalFiles.viewer.waitForViewerLoaderToFinish(timeouts.sixtySeconds); + await personalFiles.viewer.waitForViewerLoaderToFinish(); await expect(personalFiles.viewer.fileTitleButtonLocator).toHaveText(randomDocxName); }); }); diff --git a/e2e/playwright/viewer/src/tests/viewer-file-types.e2e.ts b/e2e/playwright/viewer/src/tests/viewer-file-types.e2e.ts index 6849cf803..b3b42305c 100644 --- a/e2e/playwright/viewer/src/tests/viewer-file-types.e2e.ts +++ b/e2e/playwright/viewer/src/tests/viewer-file-types.e2e.ts @@ -32,7 +32,6 @@ import { Utils, TrashcanApi, PersonalFilesPage, - timeouts, logger } from '@alfresco/aca-playwright-shared'; @@ -99,7 +98,7 @@ test.describe('viewer file types', () => { async function openFileInViewer(page: PersonalFilesPage, fileName: string) { await page.dataTable.performClickFolderOrFileToOpen(fileName); expect(await page.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); - await page.viewer.waitForViewerLoaderToFinish(timeouts.fortySeconds); + await page.viewer.waitForViewerLoaderToFinish(); await Utils.delayInSeconds(1); } diff --git a/e2e/playwright/viewer/src/tests/viewer-version-actions.e2e.ts b/e2e/playwright/viewer/src/tests/viewer-version-actions.e2e.ts index 48c871093..89292457f 100644 --- a/e2e/playwright/viewer/src/tests/viewer-version-actions.e2e.ts +++ b/e2e/playwright/viewer/src/tests/viewer-version-actions.e2e.ts @@ -37,8 +37,7 @@ import { PersonalFilesPage, FavoritesPage, SharedPage, - SearchPage, - timeouts + SearchPage } from '@alfresco/aca-playwright-shared'; test.describe('Version actions', () => { @@ -48,13 +47,12 @@ test.describe('Version actions', () => { let sharedLinksApi: SharedLinksApi; let favoritesApi: FavoritesPageApi; const random = Utils.random(); - const filesToUpload = [TEST_FILES.PDF, TEST_FILES.DOCX]; - const filenameBeforeUpdate = `${filesToUpload[0].name}-${random}`; - const filenameAfterUpdate = `${filesToUpload[1].name}-${random}`; + const filesToUpload = [TEST_FILES.PDF, TEST_FILES.JPG_FILE]; + const filenameBeforeUpdate = `${filesToUpload[0].name}-1-${random}.pdf`; + const filenameAfterUpdate = `${filesToUpload[1].name}-2-${random}.jpg`; const username = `user-${random}`; - const parentFolder = `parent-version-${random}`; - let parentFolderId: string; let fileId: string; + let fileAfterUpdateId: string; async function viewFirstFileVersion(page: PersonalFilesPage | RecentFilesPage | FavoritesPage | SharedPage | SearchPage) { await page.dataTable.selectItems(filenameAfterUpdate); @@ -75,10 +73,11 @@ test.describe('Version actions', () => { favoritesApi = await FavoritesPageApi.initialize(username, username); sharedLinksApi = await SharedLinksApi.initialize(username, username); - parentFolderId = (await nodesApi.createFolder(parentFolder)).entry.id; - fileId = (await fileActionsApi.uploadFile(filesToUpload[0].path, filenameBeforeUpdate, parentFolderId)).entry.id; + fileId = (await fileActionsApi.uploadFile(filesToUpload[0].path, filenameBeforeUpdate, '-my-')).entry.id; - await fileActionsApi.updateNodeContent(fileId, filesToUpload[1].path, true, 'new major version description', filenameAfterUpdate); + fileAfterUpdateId = ( + await fileActionsApi.updateNodeContentFromFile(fileId, filesToUpload[1].path, true, 'new major version description', filenameAfterUpdate) + ).entry.id; await favoritesApi.addFavoritesByIds('file', [fileId]); await favoritesApi.waitForApi(username, { expect: 1 }); @@ -97,8 +96,6 @@ test.describe('Version actions', () => { test.beforeEach(async ({ loginPage, personalFiles }) => { await Utils.tryLoginUser(loginPage, username, username, 'beforeEach failed'); await personalFiles.navigate(); - await personalFiles.dataTable.performClickFolderOrFileToOpen(parentFolder); - await personalFiles.dataTable.spinnerWaitForReload(); await viewFirstFileVersion(personalFiles); }); @@ -117,6 +114,18 @@ test.describe('Version actions', () => { const [download] = await Promise.all([personalFiles.page.waitForEvent('download'), await personalFiles.viewer.downloadButton.click()]); expect(download.suggestedFilename()).toBe(filenameBeforeUpdate); }); + + test('[XAT-19377] Can view previous version of a document after a viewer is opened from Manage Versions dialog', async ({ personalFiles }) => { + await personalFiles.viewer.waitForViewerToOpen(); + await personalFiles.viewer.toolbar.clickViewerMoreActions(); + await personalFiles.matMenu.clickMenuItem('Manage Versions'); + await personalFiles.manageVersionsDialog.clickListActionButtonForVersion('2.0'); + await Promise.all([Utils.waitForApiResponse(personalFiles, '2.0', 200), personalFiles.matMenu.clickMenuItem('View')]); + await personalFiles.viewer.waitForViewerLoaderToFinish(); + await expect(personalFiles.viewer.unknownFormat).toBeHidden(); + expect(await personalFiles.viewer.getFileTitle()).toContain(filenameAfterUpdate); + expect(personalFiles.page.url()).toContain(fileAfterUpdateId); + }); }); test.describe('on Recent Files', () => { @@ -181,7 +190,7 @@ test.describe('Version actions', () => { test('[XAT-5506] Previous document version title should be the same in Preview mode as in Version Manager - Shared Files', async ({ sharedPage }) => { - await sharedPage.viewer.waitForViewerLoaderToFinish(timeouts.fortySeconds); + await sharedPage.viewer.waitForViewerLoaderToFinish(); expect(await sharedPage.viewer.getFileTitle()).toContain(filenameBeforeUpdate); }); diff --git a/e2e/playwright/viewer/src/tests/viewer-zoom-functionality.e2e.ts b/e2e/playwright/viewer/src/tests/viewer-zoom-functionality.e2e.ts index 4fa3d4eb6..1c1d6ce79 100644 --- a/e2e/playwright/viewer/src/tests/viewer-zoom-functionality.e2e.ts +++ b/e2e/playwright/viewer/src/tests/viewer-zoom-functionality.e2e.ts @@ -63,7 +63,7 @@ test.describe('viewer zoom functionality and reset', () => { try { await apiClientFactory.createUser({ username }); } catch (exception) { - if (JSON.parse(exception.message).error.statusCode !== 409) { + if (!String(exception).includes('409')) { throw new Error(`----- beforeAll failed : ${exception}`); } } @@ -82,7 +82,7 @@ test.describe('viewer zoom functionality and reset', () => { try { await siteActionsUser.createSite(randomLibraryName, Site.VisibilityEnum.PRIVATE); } catch (exception) { - if (JSON.parse(exception.message).error.statusCode !== 409) { + if (!String(exception).includes('409')) { throw new Error(`----- beforeAll failed : ${exception}`); } } @@ -106,7 +106,7 @@ test.describe('viewer zoom functionality and reset', () => { await shareActions.waitForFilesToBeShared([filePngId]); await fileActionApi.waitForNodes(randomPngName, { expect: 1 }); } catch (exception) { - if (JSON.parse(exception.message).error.statusCode !== 409) { + if (!String(exception).includes('409')) { throw new Error(`----- beforeAll failed : ${exception}`); } } @@ -186,7 +186,7 @@ test.describe('viewer zoom functionality and reset', () => { await myLibrariesPage.navigate(); await myLibrariesPage.dataTable.performClickFolderOrFileToOpen(randomLibraryName); await myLibrariesPage.dataTable.performClickFolderOrFileToOpen(randomDocxName); - await myLibrariesPage.viewer.waitForViewerLoaderToFinish(timeouts.fortySeconds); + await myLibrariesPage.viewer.waitForViewerLoaderToFinish(); expect(await myLibrariesPage.viewer.isViewerOpened(), 'Viewer is not opened').toBe(true); await myLibrariesPage.viewer.waitForZoomPercentageToDisplay(); await validateZoomScaleInViewer(myLibrariesPage); @@ -224,7 +224,7 @@ test.describe('viewer zoom functionality and reset', () => { await myLibrariesPage.navigate(); await myLibrariesPage.dataTable.performClickFolderOrFileToOpen(randomLibraryName); await myLibrariesPage.dataTable.performClickFolderOrFileToOpen(randomDocxName); - await myLibrariesPage.viewer.waitForViewerLoaderToFinish(timeouts.fortySeconds); + 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/e2e/playwright/viewer/src/tests/viewer.e2e.ts b/e2e/playwright/viewer/src/tests/viewer.e2e.ts index 973f6e411..bf39e2550 100644 --- a/e2e/playwright/viewer/src/tests/viewer.e2e.ts +++ b/e2e/playwright/viewer/src/tests/viewer.e2e.ts @@ -32,7 +32,6 @@ import { SitesApi, test, TEST_FILES, - timeouts, Utils, TrashcanApi } from '@alfresco/aca-playwright-shared'; @@ -210,7 +209,8 @@ test.describe('viewer file', () => { const apiClientFactory = new ApiClientFactory(); await apiClientFactory.setUpAcaBackend('admin'); await apiClientFactory.createUser({ username: username1 }); - user2Id = (await apiClientFactory.createUser({ username: username2 })).entry.id; + const user2 = await apiClientFactory.createUser({ username: username2 }); + user2Id = user2?.entry.id ?? username2; nodesApi1 = await NodesApi.initialize(username1, username1); trashcanApi1 = await TrashcanApi.initialize(username1, username1); sitesApi1 = await SitesApi.initialize(username1, username1); @@ -281,7 +281,7 @@ test.describe('viewer file', () => { test('[XAT-5476] Viewer opens when accessing the preview URL for a file', async ({ personalFiles }) => { const previewURL = `#/personal-files/${folderId}/(viewer:view/${fileJpgId})`; await personalFiles.navigate({ remoteUrl: previewURL }); - await personalFiles.viewer.waitForViewerLoaderToFinish(timeouts.fortySeconds); + await personalFiles.viewer.waitForViewerLoaderToFinish(); await expect(personalFiles.viewer.fileTitleButtonLocator).toContainText(randomJpgName); }); }); diff --git a/projects/aca-playwright-shared/src/api/file-actions.ts b/projects/aca-playwright-shared/src/api/file-actions.ts index 5827915c2..5e4e5bd6d 100644 --- a/projects/aca-playwright-shared/src/api/file-actions.ts +++ b/projects/aca-playwright-shared/src/api/file-actions.ts @@ -239,7 +239,7 @@ export class FileActionsApi { } } - async updateNodeContent(nodeId: string, content: string, majorVersion: boolean = true, comment?: string, newName?: string): Promise { + async updateNodeContent(nodeId: string, content: string | Buffer, majorVersion = true, comment?: string, newName?: string): Promise { try { const opts: { [key: string]: string | boolean } = { majorVersion }; if (comment !== undefined) { @@ -248,10 +248,15 @@ export class FileActionsApi { if (newName !== undefined) { opts['name'] = newName; } - return await this.apiService.nodes.updateNodeContent(nodeId, content, opts); + return await this.apiService.nodes.updateNodeContent(nodeId, content as unknown as string, opts); // NOSONAR } catch (error) { logger.error(`${this.constructor.name} ${this.updateNodeContent.name}: ${error}`); return Promise.reject(error); } } + + async updateNodeContentFromFile(nodeId: string, fileLocation: string, majorVersion = true, comment?: string, newName?: string): Promise { + const fileContent = await fs.promises.readFile(fileLocation); + return this.updateNodeContent(nodeId, fileContent, majorVersion, comment, newName); + } } 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 ee0cc47d2..3b9fc08e0 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 @@ -44,7 +44,7 @@ export class ViewerComponent extends BaseComponent { public thumbnailsCloseButton = this.getChild('[data-automation-id="adf-thumbnails-close"]'); 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 viewerSpinner = this.getChild('.adf-viewer-render__loading-screen__spinner'); 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"]'); @@ -75,13 +75,9 @@ export class ViewerComponent extends BaseComponent { await this.viewerLocator.waitFor({ state: 'visible', timeout: timeouts.large }); } - async waitForViewerLoaderToFinish(customTimeout?: number): Promise { - try { - await this.viewerSpinner.waitFor({ state: 'hidden', timeout: customTimeout || timeouts.extraLarge }); - } catch (error) { - this.logger.log('waitForViewerLoaderToFinish: Timeout reached while waiting for viewer loader to finish.'); - throw error; - } + async waitForViewerLoaderToFinish(): Promise { + await this.viewerSpinner.waitFor({ state: 'attached', timeout: timeouts.medium }).catch(() => {}); + await this.viewerSpinner.waitFor({ state: 'detached', timeout: timeouts.fortySeconds }).catch(() => {}); } async checkViewerActivePage(pageNumber: number): Promise { @@ -105,7 +101,7 @@ export class ViewerComponent extends BaseComponent { async waitForZoomPercentageToDisplay(): Promise { await this.zoomScale.waitFor({ state: 'visible', timeout: timeouts.normal }); const startTime = Date.now(); - let textContent: string; + let textContent = ''; while (Date.now() - startTime <= timeouts.medium) { textContent = await this.zoomScale.innerText(); @@ -123,12 +119,24 @@ export class ViewerComponent extends BaseComponent { async getFileTitle(): Promise { await this.fileTitleButtonLocator.waitFor({ state: 'visible', timeout: timeouts.normal }); await this.waitForViewerLoaderToFinish(); - return this.fileTitleButtonLocator.textContent(); + const title = await this.fileTitleButtonLocator.textContent(); + if (!title) { + const errorMessage = 'File title is not displayed in the viewer'; + this.logger.error(errorMessage); + throw new Error(errorMessage); + } + return title; } async getCloseButtonTooltip(): Promise { await this.closeButtonLocator.waitFor({ state: 'visible', timeout: timeouts.normal }); - return this.closeButtonLocator.getAttribute('title'); + const tooltip = await this.closeButtonLocator.getAttribute('title'); + if (!tooltip) { + const errorMessage = 'Close button tooltip is not available'; + this.logger.error(errorMessage); + throw new Error(errorMessage); + } + return tooltip; } async verifyViewerPrimaryActions(expectedToolbarPrimary: string[]): Promise {