From 86e1b33dec2b9b4e38e85b19a9be5328805e8b17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C5=9Awiderski?= Date: Fri, 11 Sep 2026 12:16:31 +0200 Subject: [PATCH] [ACS-12817] automated ACS-12663 and updated lock api --- .../copy-move-actions/src/tests/copy.e2e.ts | 14 +- .../copy-move-actions/src/tests/move.e2e.ts | 6 +- .../src/tests/delete-undo-delete.e2e.ts | 4 +- .../src/tests/edit-offline.e2e.ts | 168 +++++++++++++----- .../tests/special-permissions-actions.e2e.ts | 6 +- .../src/tests/upload-new-version.e2e.ts | 2 +- .../src/tests/viewer-action.e2e.ts | 8 +- .../src/api/file-actions.ts | 12 -- .../src/api/nodes-api.ts | 12 +- 9 files changed, 142 insertions(+), 90 deletions(-) diff --git a/e2e/playwright/copy-move-actions/src/tests/copy.e2e.ts b/e2e/playwright/copy-move-actions/src/tests/copy.e2e.ts index e34a4e86d..8e27facd4 100644 --- a/e2e/playwright/copy-move-actions/src/tests/copy.e2e.ts +++ b/e2e/playwright/copy-move-actions/src/tests/copy.e2e.ts @@ -51,10 +51,6 @@ test.describe('Copy actions', () => { } }); - test.afterAll(async () => { - await Utils.deleteNodesSitesEmptyTrashcan(nodesApi, trashcanApi, 'afterAll failed'); - }); - test.beforeEach(async ({ personalFiles, page }) => { sourceFile = `source-file-${Utils.random()}.txt`; sourceFileInsideFolder = `source-file-inside-folder-${Utils.random()}.txt`; @@ -72,6 +68,10 @@ test.describe('Copy actions', () => { await personalFiles.navigate(); }); + test.afterAll(async () => { + await Utils.deleteNodesSitesEmptyTrashcan(nodesApi, trashcanApi, 'afterAll failed'); + }); + const copyContentInPersonalFiles = async (personalFilesPage: PersonalFilesPage, sourceFileList: string[], destinationName: string) => { await personalFilesPage.copyOrMoveContentInDatatable(sourceFileList, destinationName, 'Copy'); const msg = await personalFilesPage.snackBar.message.innerText(); @@ -148,8 +148,7 @@ test.describe('Copy actions', () => { }); test('[XAT-4947] Copy locked file', async ({ personalFiles }) => { - const lockType = 'ALLOW_OWNER_CHANGES'; - await nodesApi.lockNodes([sourceFileId], lockType); + await nodesApi.checkoutNodes([sourceFileId]); await Utils.reloadPageIfRowNotVisible(personalFiles, sourceFile); await copyContentInPersonalFiles(personalFiles, [sourceFile], destinationFolder); expect.soft(await personalFiles.dataTable.isItemPresent(sourceFile)).toBe(true); @@ -159,8 +158,7 @@ test.describe('Copy actions', () => { }); test('[XAT-4948] Copy folder that contains locked file', async ({ personalFiles }) => { - const lockType = 'ALLOW_OWNER_CHANGES'; - await nodesApi.lockNodes([sourceFileInsideFolderId], lockType); + await nodesApi.checkoutNodes([sourceFileInsideFolderId]); await copyFolderAndVerifyContent(personalFiles); }); diff --git a/e2e/playwright/copy-move-actions/src/tests/move.e2e.ts b/e2e/playwright/copy-move-actions/src/tests/move.e2e.ts index a5b4c3131..9df47917e 100644 --- a/e2e/playwright/copy-move-actions/src/tests/move.e2e.ts +++ b/e2e/playwright/copy-move-actions/src/tests/move.e2e.ts @@ -130,8 +130,7 @@ test.describe('Move actions', () => { }); test('[XAT-4989] Move locked file', async ({ personalFiles }) => { - const lockType = 'ALLOW_OWNER_CHANGES'; - await nodesApi.lockNodes([sourceFileId], lockType); + await nodesApi.checkoutNodes([sourceFileId]); await Utils.reloadPageIfRowNotVisible(personalFiles, sourceFile); await moveContentInPersonalFiles(personalFiles, [sourceFile], destinationFolder); const msg = await personalFiles.snackBar.message.innerText(); @@ -168,8 +167,7 @@ test.describe('Move actions', () => { async function moveFolderWithContent(personalFiles: PersonalFilesPage, lockedFile: boolean) { if (lockedFile) { - const lockType = 'ALLOW_OWNER_CHANGES'; - await nodesApi.lockNodes([sourceFileInsideFolderId], lockType); + await nodesApi.checkoutNodes([sourceFileInsideFolderId]); } await Utils.reloadPageIfRowNotVisible(personalFiles, sourceFolder); await moveContentInPersonalFiles(personalFiles, [sourceFolder], destinationFolder); diff --git a/e2e/playwright/delete-actions/src/tests/delete-undo-delete.e2e.ts b/e2e/playwright/delete-actions/src/tests/delete-undo-delete.e2e.ts index 5586d7d35..9266ad017 100755 --- a/e2e/playwright/delete-actions/src/tests/delete-undo-delete.e2e.ts +++ b/e2e/playwright/delete-actions/src/tests/delete-undo-delete.e2e.ts @@ -104,7 +104,7 @@ test.describe('Delete and undo delete', () => { fileLocked4Id = (await nodesApi.createFile(fileLocked4, folder5Id)).entry.id; await nodesApi.createFile(file2InFolder, folder6Id); - await nodesApi.lockNodes([fileLocked1Id, fileLocked2Id, fileLocked3Id, fileLocked4Id], 'FULL'); + await nodesApi.checkoutNodes([fileLocked1Id, fileLocked2Id, fileLocked3Id, fileLocked4Id]); }); test.beforeEach(async ({ loginPage, personalFiles }) => { @@ -114,7 +114,7 @@ test.describe('Delete and undo delete', () => { }); test.afterAll(async () => { - await nodesApi.unlockNodes([fileLocked1Id, fileLocked2Id, fileLocked3Id, fileLocked4Id]); + await nodesApi.cancelCheckout([fileLocked1Id, fileLocked2Id, fileLocked3Id, fileLocked4Id]); await Utils.deleteNodesSitesEmptyTrashcan(nodesApi, trashcanApi, 'afterAll failed'); }); diff --git a/e2e/playwright/edit-actions/src/tests/edit-offline.e2e.ts b/e2e/playwright/edit-actions/src/tests/edit-offline.e2e.ts index 0426923eb..d0194d123 100644 --- a/e2e/playwright/edit-actions/src/tests/edit-offline.e2e.ts +++ b/e2e/playwright/edit-actions/src/tests/edit-offline.e2e.ts @@ -26,70 +26,140 @@ import { expect } from '@playwright/test'; import { ApiClientFactory, NodesApi, Utils, test, TrashcanApi, FileActionsApi, TEST_FILES } from '@alfresco/aca-playwright-shared'; test.describe('Edit offline - on Personal Files', () => { - const apiClientFactory = new ApiClientFactory(); + const username = `user-${Utils.random()}`; let nodesApi: NodesApi; let trashcanApi: TrashcanApi; let fileActionsApi: FileActionsApi; - let parentPFId: string; - let fileLockedId: string; - let fileLocked2Id: string; - - const username = `user-${Utils.random()}`; - - const file1 = `file1-${Utils.random()}.docx`; - const fileLocked = `file-locked-${Utils.random()}.docx`; - const fileLocked2 = `file-locked2-${Utils.random()}.docx`; - const parentPF = `parentPersonal-${Utils.random()}`; - test.beforeAll(async () => { - try { - await apiClientFactory.setUpAcaBackend('admin'); - await apiClientFactory.createUser({ username }); - nodesApi = await NodesApi.initialize(username, username); - trashcanApi = await TrashcanApi.initialize(username, username); - fileActionsApi = await FileActionsApi.initialize(username, username); - - parentPFId = (await nodesApi.createFolder(parentPF)).entry.id; - fileLockedId = (await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, fileLocked, parentPFId)).entry.id; - fileLocked2Id = (await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, fileLocked2, parentPFId)).entry.id; - await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file1, parentPFId); - - await nodesApi.lockNodes([fileLockedId, fileLocked2Id]); - } catch (error) { - console.error(`beforeAll failed : ${error}`); - } - }); - - test.beforeEach(async ({ loginPage, personalFiles }) => { - await Utils.tryLoginUser(loginPage, username, username, 'beforeEach failed'); - await personalFiles.dataTable.performClickFolderOrFileToOpen(parentPF); + const apiClientFactory = new ApiClientFactory(); + await apiClientFactory.setUpAcaBackend('admin'); + await apiClientFactory.createUser({ username }); + nodesApi = await NodesApi.initialize(username, username); + trashcanApi = await TrashcanApi.initialize(username, username); + fileActionsApi = await FileActionsApi.initialize(username, username); }); test.afterAll(async () => { await Utils.deleteNodesSitesEmptyTrashcan(nodesApi, trashcanApi, 'afterAll failed'); }); - test('[XAT-5304] File is locked and downloaded when clicking Edit offline', async ({ personalFiles }) => { - await personalFiles.dataTable.selectItems(file1); - await personalFiles.acaHeader.clickMoreActions(); - const [download] = await Promise.all([ - personalFiles.page.waitForEvent('download', { timeout: 5000 }), - personalFiles.matMenu.clickMenuItem('Edit Offline') - ]); - expect(download.suggestedFilename()).toBe(file1); + test.describe('[XAT-5304] File is locked and downloaded when clicking Edit offline', () => { + const file5304 = `file-5304-${Utils.random()}.docx`; + let file5304Id: string; + + test.beforeAll(async () => { + try { + file5304Id = (await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file5304)).entry.id; + } catch (error) { + console.error(`beforeAll failed : ${error}`); + } + }); + + test.beforeEach(async ({ loginPage, personalFiles }) => { + await Utils.tryLoginUser(loginPage, username, username, 'beforeEach failed'); + await personalFiles.navigate(); + }); + + test.afterAll(async () => { + await nodesApi.cancelCheckout([file5304Id]); + }); + + test('[XAT-5304] File is locked and downloaded when clicking Edit offline', async ({ personalFiles }) => { + await personalFiles.dataTable.selectItems(file5304); + await personalFiles.acaHeader.clickMoreActions(); + const [download] = await Promise.all([ + personalFiles.page.waitForEvent('download', { timeout: 5000 }), + personalFiles.matMenu.clickMenuItem('Edit Offline') + ]); + expect(download.suggestedFilename()).toBe(file5304); + }); }); - test('[XAT-5305] Lock information is displayed', async ({ personalFiles }) => { - expect(await personalFiles.dataTable.isItemPresent(fileLocked2)).toBe(true); - expect(await personalFiles.dataTable.getLockOwner(fileLocked2)).toContain(username); + test.describe('[XAT-5305] Lock information is displayed', () => { + const fileLocked5305 = `file-locked-5305-${Utils.random()}.docx`; + let fileLocked5305Id: string; + + test.beforeAll(async () => { + try { + fileLocked5305Id = (await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, fileLocked5305)).entry.id; + await nodesApi.checkoutNodes([fileLocked5305Id]); + } catch (error) { + console.error(`beforeAll failed : ${error}`); + } + }); + + test.beforeEach(async ({ loginPage, personalFiles }) => { + await Utils.tryLoginUser(loginPage, username, username, 'beforeEach failed'); + await personalFiles.navigate(); + }); + + test.afterAll(async () => { + await nodesApi.cancelCheckout([fileLocked5305Id]); + }); + + test('[XAT-5305] Lock information is displayed', async ({ personalFiles }) => { + expect(await personalFiles.dataTable.isItemPresent(fileLocked5305)).toBe(true); + expect(await personalFiles.dataTable.getLockOwner(fileLocked5305)).toContain(username); + }); }); - test('[XAT-5306] Cancel Editing unlocks the file', async ({ personalFiles }) => { - await personalFiles.dataTable.selectItems(fileLocked); - await personalFiles.acaHeader.clickMoreActions(); - await personalFiles.matMenu.clickMenuItemFromHeaderMenu('Cancel Editing'); + test.describe('[XAT-5306] Cancel Editing unlocks the file', () => { + const fileLocked5306 = `file-locked-5306-${Utils.random()}.docx`; + let fileLocked5306Id: string; - expect(await nodesApi.isFileLockedWrite(fileLockedId), `${fileLocked} is still locked`).not.toEqual('WRITE_LOCK'); + test.beforeAll(async () => { + try { + fileLocked5306Id = (await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, fileLocked5306)).entry.id; + await nodesApi.checkoutNodes([fileLocked5306Id]); + } catch (error) { + console.error(`beforeAll failed : ${error}`); + } + }); + + test.beforeEach(async ({ loginPage, personalFiles }) => { + await Utils.tryLoginUser(loginPage, username, username, 'beforeEach failed'); + await personalFiles.navigate(); + }); + + test('[XAT-5306] Cancel Editing unlocks the file', async ({ personalFiles }) => { + await personalFiles.dataTable.selectItems(fileLocked5306); + await personalFiles.acaHeader.clickMoreActions(); + await personalFiles.matMenu.clickMenuItemFromHeaderMenu('Cancel Editing'); + + expect(await nodesApi.isFileLockedWrite(fileLocked5306Id), `${fileLocked5306} is still locked`).not.toEqual('WRITE_LOCK'); + }); + }); + + test.describe('[XAT-20171] Cancel Editing option should not persists after uploading a new file version', () => { + const file20171 = `file-20171-${Utils.random()}.docx`; + + test.beforeAll(async () => { + try { + await fileActionsApi.uploadFileWithRename(TEST_FILES.JPG_FILE.path, file20171); + } catch (error) { + console.error(`beforeAll failed : ${error}`); + } + }); + + test.beforeEach(async ({ loginPage, personalFiles }) => { + await Utils.tryLoginUser(loginPage, username, username, 'beforeEach failed'); + await personalFiles.navigate(); + }); + + test('[XAT-20171] Cancel Editing option should not persists after uploading a new file version', async ({ personalFiles }) => { + await personalFiles.dataTable.selectItems(file20171); + await personalFiles.acaHeader.clickMoreActions(); + const [fileChooser] = await Promise.all([ + personalFiles.page.waitForEvent('filechooser'), + personalFiles.acaHeader.matMenu.clickMenuItem('Upload New Version') + ]); + await fileChooser.setFiles(TEST_FILES.PNG_FILE.path); + await personalFiles.uploadNewVersionDialog.uploadButton.click(); + expect(await personalFiles.dataTable.isItemPresent(TEST_FILES.PNG_FILE.name)).toBe(true); + await personalFiles.dataTable.selectItems(TEST_FILES.PNG_FILE.name); + await personalFiles.acaHeader.clickMoreActions(); + await expect(personalFiles.matMenu.getButtonByText('Upload New Version')).toBeVisible(); + }); }); }); diff --git a/e2e/playwright/special-permissions-actions-available/src/tests/special-permissions-actions.e2e.ts b/e2e/playwright/special-permissions-actions-available/src/tests/special-permissions-actions.e2e.ts index 08780b6ce..650efa31a 100644 --- a/e2e/playwright/special-permissions-actions-available/src/tests/special-permissions-actions.e2e.ts +++ b/e2e/playwright/special-permissions-actions-available/src/tests/special-permissions-actions.e2e.ts @@ -122,7 +122,7 @@ test.describe('Special permissions : ', () => { fileSharedFavLockedId ]); - await managerNodeActions.lockNodes([fileLockedId, fileFavLockedId, fileSharedLockedId, fileSharedFavLockedId]); + await managerNodeActions.checkoutNodes([fileLockedId, fileFavLockedId, fileSharedLockedId, fileSharedFavLockedId]); await Promise.all([ consumerFavoritesActions.waitForApi(userConsumer, { expect: consumerFavoritesTotalItems + 6 }), @@ -243,7 +243,7 @@ test.describe('Special permissions : ', () => { fileLockedByUserId = (await managerNodeActions.createFile(testData.fileLockedByUser.name, docLibId, '', '', '', true, ['cm:versionable'])).entry .id; - await demotedUserActions.lockNodes([fileLockedByUserId]); + await demotedUserActions.checkoutNodes([fileLockedByUserId]); await demotedUserFavoritesActions.addFavoriteById('file', fileLockedByUserId); await demotedUserShareActions.shareFileById(fileLockedByUserId); await managerSiteActions.updateSiteMember(sitePrivate, userDemoted, Site.RoleEnum.SiteConsumer); @@ -301,7 +301,7 @@ test.describe('Special permissions : ', () => { fileLockedByUserId = (await managerNodeActions.createFile(testData.fileLockedByUser.name, docLibId, '', '', '', true, ['cm:versionable'])).entry .id; - await demotedUserActions.lockNodes([fileLockedByUserId]); + await demotedUserActions.checkoutNodes([fileLockedByUserId]); await demotedUserShareActions.shareFileById(fileLockedByUserId); await managerFavoritesActions.addFavoriteById('file', fileLockedByUserId); diff --git a/e2e/playwright/upload-download-actions/src/tests/upload-new-version.e2e.ts b/e2e/playwright/upload-download-actions/src/tests/upload-new-version.e2e.ts index 997cec57f..e4bdf2e23 100755 --- a/e2e/playwright/upload-download-actions/src/tests/upload-new-version.e2e.ts +++ b/e2e/playwright/upload-download-actions/src/tests/upload-new-version.e2e.ts @@ -142,7 +142,7 @@ test.describe('Upload new version', () => { fileLocked1Id = (await nodesApi.createFile(fileToUpload1, parentPFId)).entry.id; fileLocked2Id = (await nodesApi.createFile(fileLocked2, parentPFId)).entry.id; - await nodesApi.lockNodes([fileLocked1Id, fileLocked2Id]); + await nodesApi.checkoutNodes([fileLocked1Id, fileLocked2Id]); }); test.beforeEach(async ({ loginPage, personalFiles }) => { diff --git a/e2e/playwright/viewer-actions/src/tests/viewer-action.e2e.ts b/e2e/playwright/viewer-actions/src/tests/viewer-action.e2e.ts index d1a8d48e8..81b8125be 100644 --- a/e2e/playwright/viewer-actions/src/tests/viewer-action.e2e.ts +++ b/e2e/playwright/viewer-actions/src/tests/viewer-action.e2e.ts @@ -238,7 +238,6 @@ test.describe('viewer action file', () => { const username = `user-${Utils.random()}`; const fileForCancelEditing = `playwright-file2-${Utils.random()}.docx`; let folderIdCancelEdit: string; - let workingCopyName: string; let nodesApi: NodesApi; let trashcanApi: TrashcanApi; @@ -251,8 +250,7 @@ test.describe('viewer action file', () => { const { fileActionsApi } = apis; folderIdCancelEdit = (await nodesApi.createFolder(`viewer-action-5424-${Utils.random()}`)).entry.id; const fileForCancelEditingId = (await fileActionsApi.uploadFile(TEST_FILES.DOCX.path, fileForCancelEditing, folderIdCancelEdit)).entry.id; - const workingCopy = await fileActionsApi.checkoutNode(fileForCancelEditingId); - workingCopyName = workingCopy.entry.name; + await nodesApi.checkoutNodes([fileForCancelEditingId]); await fileActionsApi.isFileCheckedOutWithRetry(fileForCancelEditingId, true); } catch (error) { console.error(`beforeAll failed: ${error}`); @@ -270,7 +268,7 @@ test.describe('viewer action file', () => { }); test('[XAT-5424] Viewer - Cancel Editing action - Personal Files', async ({ personalFiles }) => { - await openFileInViewer(personalFiles, workingCopyName); + await openFileInViewer(personalFiles, fileForCancelEditing); await personalFiles.viewer.toolbar.clickMoreActions(); await personalFiles.matMenu.clickMenuItem('Cancel Editing'); await personalFiles.viewer.waitForViewerToOpen(); @@ -322,7 +320,7 @@ test.describe('viewer action file', () => { await fileActionsApi.uploadFileWithRename(TEST_FILES.JPG_FILE.path, file5714, folder5714Id); await fileActionsApi.uploadFileWithRename(TEST_FILES.JPG_FILE.path, file5717, folder5717Id); await fileActionsApi.uploadFileWithRename(TEST_FILES.JPG_FILE.path, file5720, folder5720Id); - await fileActionsApi.lockNodes([file17781Id]); + await nodesApi.checkoutNodes([file17781Id]); } catch (error) { console.error(`beforeAll failed: ${error}`); throw error; diff --git a/projects/aca-playwright-shared/src/api/file-actions.ts b/projects/aca-playwright-shared/src/api/file-actions.ts index 27267e3c6..8283a58ce 100644 --- a/projects/aca-playwright-shared/src/api/file-actions.ts +++ b/projects/aca-playwright-shared/src/api/file-actions.ts @@ -127,18 +127,6 @@ export class FileActionsApi { } } - async lockNodes(nodeIds: string[], lockType: string = 'ALLOW_OWNER_CHANGES'): Promise { - try { - for (const nodeId of nodeIds) { - await this.apiService.nodes.lockNode(nodeId, { type: lockType }); - } - } catch {} - } - - async checkoutNode(nodeId: string): Promise { - return this.apiService.nodes.checkoutNode(nodeId); - } - async getNodeById(id: string): Promise { try { return this.apiService.nodes.getNode(id); diff --git a/projects/aca-playwright-shared/src/api/nodes-api.ts b/projects/aca-playwright-shared/src/api/nodes-api.ts index fc3283040..c929e7eb6 100755 --- a/projects/aca-playwright-shared/src/api/nodes-api.ts +++ b/projects/aca-playwright-shared/src/api/nodes-api.ts @@ -208,23 +208,23 @@ export class NodesApi { } } - async lockNodes(nodeIds: string[], lockType: string = 'ALLOW_OWNER_CHANGES') { + async checkoutNodes(nodeIds: string[]) { try { for (const nodeId of nodeIds) { - await this.apiService.nodes.lockNode(nodeId, { type: lockType }); + await this.apiService.nodes.checkoutNode(nodeId); } } catch (error) { - logger.error(`${this.constructor.name} ${this.lockNodes.name}: ${error}`); + logger.error(`${this.constructor.name} ${this.checkoutNodes.name}: ${JSON.stringify(error)}`); } } - async unlockNodes(nodeIds: string[]) { + async cancelCheckout(nodeIds: string[]) { try { for (const nodeId of nodeIds) { - await this.apiService.nodes.unlockNode(nodeId); + await this.apiService.nodes.cancelCheckoutNode(nodeId); } } catch (error) { - logger.error(`${this.constructor.name} ${this.unlockNodes.name}: ${error}`); + logger.error(`${this.constructor.name} ${this.cancelCheckout.name}: ${JSON.stringify(error)}`); } }