From ebbc868aa13c9230fb29664e92e1be8cfd14ab25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C5=9Awiderski?= Date: Thu, 3 Apr 2025 10:02:43 +0200 Subject: [PATCH] [ACS-9065] [E2E] Added folder information tests in ACA (#4478) * [ACS-9065] Added folder information tests in ACA * [ACS-9065] fixed sonar issues * [ACS-9065] Changed test describe name * [ACS-9065] debugging dialog errors 1 * [ACS-9065] removed debugging reload * [ACS-9065] renamed e2e file --- .github/workflows/pull-request.yml | 2 + .../folder-information-actions/.eslintrc.json | 26 +++ .../exclude.tests.json | 1 + .../playwright.config.ts | 42 ++++ .../folder-information-actions/project.json | 31 +++ .../src/tests/folder-information.e2e.ts | 195 ++++++++++++++++++ .../tsconfig.e2e.adf.json | 15 ++ .../tsconfig.e2e.json | 15 ++ .../folder-information-dialog.component.ts | 49 +++++ .../page-objects/components/dialogs/index.ts | 2 +- .../page-objects/pages/my-libraries.page.ts | 4 +- .../page-objects/pages/personal-files.page.ts | 4 +- .../src/page-objects/pages/search.page.ts | 4 +- 13 files changed, 386 insertions(+), 4 deletions(-) create mode 100644 e2e/playwright/folder-information-actions/.eslintrc.json create mode 100644 e2e/playwright/folder-information-actions/exclude.tests.json create mode 100644 e2e/playwright/folder-information-actions/playwright.config.ts create mode 100644 e2e/playwright/folder-information-actions/project.json create mode 100644 e2e/playwright/folder-information-actions/src/tests/folder-information.e2e.ts create mode 100644 e2e/playwright/folder-information-actions/tsconfig.e2e.adf.json create mode 100755 e2e/playwright/folder-information-actions/tsconfig.e2e.json create mode 100644 projects/aca-playwright-shared/src/page-objects/components/dialogs/folder-information-dialog.component.ts diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 1f9fcfdc5..9372a8e11 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -148,6 +148,8 @@ jobs: id: 17 - name: "smoke-test" id: 18 + - name: "folder-information-actions" + id: 19 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/e2e/playwright/folder-information-actions/.eslintrc.json b/e2e/playwright/folder-information-actions/.eslintrc.json new file mode 100644 index 000000000..eaa4081d9 --- /dev/null +++ b/e2e/playwright/folder-information-actions/.eslintrc.json @@ -0,0 +1,26 @@ +{ + "extends": "../../../.eslintrc.json", + "ignorePatterns": [ + "!**/*" + ], + "overrides": [ + { + "files": [ + "*.ts" + ], + "parserOptions": { + "project": [ + "e2e/playwright/folder-information-actions/tsconfig.e2e.json" + ], + "createDefaultProgram": true + }, + "plugins": [ + "rxjs", + "unicorn" + ], + "rules": { + "@typescript-eslint/no-floating-promises": "off" + } + } + ] +} diff --git a/e2e/playwright/folder-information-actions/exclude.tests.json b/e2e/playwright/folder-information-actions/exclude.tests.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/e2e/playwright/folder-information-actions/exclude.tests.json @@ -0,0 +1 @@ +{} diff --git a/e2e/playwright/folder-information-actions/playwright.config.ts b/e2e/playwright/folder-information-actions/playwright.config.ts new file mode 100644 index 000000000..af7e4b0cd --- /dev/null +++ b/e2e/playwright/folder-information-actions/playwright.config.ts @@ -0,0 +1,42 @@ +/*! + * 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 { PlaywrightTestConfig } from '@playwright/test'; +import { CustomConfig, getGlobalConfig, getExcludedTestsRegExpArray } from '@alfresco/aca-playwright-shared'; +import EXCLUDED_JSON from './exclude.tests.json'; + +const config: PlaywrightTestConfig = { + ...getGlobalConfig, + + grepInvert: getExcludedTestsRegExpArray(EXCLUDED_JSON, 'Folder Information Actions'), + projects: [ + { + name: 'Folder Information Actions', + testDir: './src/tests', + use: {} + } + ] +}; + +export default config; diff --git a/e2e/playwright/folder-information-actions/project.json b/e2e/playwright/folder-information-actions/project.json new file mode 100644 index 000000000..4671dbb2e --- /dev/null +++ b/e2e/playwright/folder-information-actions/project.json @@ -0,0 +1,31 @@ +{ + "name": "folder-information-actions-e2e", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "e2e/playwright/folder-information-actions", + "projectType": "application", + "targets": { + "e2e": { + "executor": "nx:run-commands", + "options": { + "commands": ["npx playwright test --config=e2e/playwright/folder-information-actions/playwright.config.ts"] + }, + "configurations": { + "production": { + "devServerTarget": "content-ce:serve:production" + }, + "ui": { + "args": ["--ui"] + }, + "debug": { + "args": ["--debug"] + }, + "headed": { + "args": ["--headed"] + } + } + }, + "lint": { + "executor": "@angular-eslint/builder:lint" + } + } +} diff --git a/e2e/playwright/folder-information-actions/src/tests/folder-information.e2e.ts b/e2e/playwright/folder-information-actions/src/tests/folder-information.e2e.ts new file mode 100644 index 000000000..16b774413 --- /dev/null +++ b/e2e/playwright/folder-information-actions/src/tests/folder-information.e2e.ts @@ -0,0 +1,195 @@ +/*! + * 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, + NodesApi, + Utils, + test, + TrashcanApi, + TEST_FILES, + FileActionsApi, + PersonalFilesPage, + MyLibrariesPage, + SitesApi, + SearchPage +} from '@alfresco/aca-playwright-shared'; + +test.describe('Actions - Folder Information', () => { + const username = `user-e2e-${Utils.random()}`; + const emptyFolder = `folder17722-${Utils.random()}`; + const folder1File = `folder17715-${Utils.random()}`; + const folderXFiles = `folder17752-${Utils.random()}`; + const folderXFilesAndFolders = `folder17753-1-${Utils.random()}`; + const folderInsideFolder = `folder17753-2-${Utils.random()}`; + const folderInLibrary = `folder17758-${Utils.random()}`; + const libraryForFolder = `library17758-${Utils.random()}`; + const folderForSearch = `folder17759-${Utils.random()}`; + const folderNested1 = `folder17766-1-${Utils.random()}`; + const folderNested2 = `folder17766-1-${Utils.random()}`; + const folderNested3 = `folder17766-1-${Utils.random()}`; + const file1 = `file1-${Utils.random()}.docx`; + const file2 = `file2-${Utils.random()}.docx`; + const file3 = `file3-${Utils.random()}.docx`; + const file4 = `file4-${Utils.random()}.docx`; + const file5 = `file5-${Utils.random()}.docx`; + const file6 = `file6-${Utils.random()}.docx`; + const file7 = `file7-${Utils.random()}.docx`; + const file8 = `file8-${Utils.random()}.docx`; + const file9 = `file9-${Utils.random()}.docx`; + const file10 = `file10-${Utils.random()}.docx`; + const file11 = `file10-${Utils.random()}.docx`; + const file12 = `file10-${Utils.random()}.docx`; + const file13 = `file10-${Utils.random()}.docx`; + let nodesApi: NodesApi; + let trashcanApi: TrashcanApi; + let fileActionsApi: FileActionsApi; + let sitesApi: SitesApi; + let folder1FileId: string; + let folderXFilesId: string; + let folderXFilesAndFoldersId: string; + let folderInsideFolderId: string; + let folderInLibraryId: string; + let siteId: string; + let folderForSearchId: string; + let folderNested1Id: string; + let folderNested2Id: string; + let folderNested3Id: string; + + test.beforeAll(async () => { + const apiService = new ApiClientFactory(); + await apiService.setUpAcaBackend('admin'); + await apiService.createUser({ username: username }); + nodesApi = await NodesApi.initialize(username, username); + trashcanApi = await TrashcanApi.initialize(username, username); + fileActionsApi = await FileActionsApi.initialize(username, username); + sitesApi = await SitesApi.initialize(username, username); + + siteId = (await sitesApi.createSite(libraryForFolder)).entry.id; + const docLibId = await sitesApi.getDocLibId(siteId); + await nodesApi.createFolder(emptyFolder, '-my-'); + folder1FileId = (await nodesApi.createFolder(folder1File, '-my-')).entry.id; + folderXFilesId = (await nodesApi.createFolder(folderXFiles, '-my-')).entry.id; + folderXFilesAndFoldersId = (await nodesApi.createFolder(folderXFilesAndFolders, '-my-')).entry.id; + folderInsideFolderId = (await nodesApi.createFolder(folderInsideFolder, folderXFilesAndFoldersId)).entry.id; + folderInLibraryId = (await nodesApi.createFolder(folderInLibrary, docLibId)).entry.id; + folderForSearchId = (await nodesApi.createFolder(folderForSearch, '-my-')).entry.id; + folderNested1Id = (await nodesApi.createFolder(folderNested1, '-my-')).entry.id; + folderNested2Id = (await nodesApi.createFolder(folderNested2, folderNested1Id)).entry.id; + folderNested3Id = (await nodesApi.createFolder(folderNested3, folderNested2Id)).entry.id; + + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file1, folder1FileId); + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file2, folderXFilesId); + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file3, folderXFilesId); + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file4, folderXFilesId); + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file5, folderXFilesAndFoldersId); + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file6, folderXFilesAndFoldersId); + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file7, folderXFilesAndFoldersId); + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file8, folderInsideFolderId); + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file9, folderInsideFolderId); + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file10, folderInLibraryId); + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file11, folderForSearchId); + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file12, folderForSearchId); + await fileActionsApi.uploadFileWithRename(TEST_FILES.DOCX.path, file13, folderNested3Id); + }); + + test.beforeEach(async ({ loginPage }) => { + await Utils.tryLoginUser(loginPage, username, username, 'Main beforeEach failed'); + }); + + test.afterAll(async () => { + await Utils.deleteNodesSitesEmptyTrashcan(nodesApi, trashcanApi, 'afterAll failed'); + }); + + async function checkFolderInformation( + page: PersonalFilesPage | MyLibrariesPage | SearchPage, + folderName: string, + expectedSize: string, + location: string, + isEmptyFolder?: 'isEmpty' + ) { + await page.dataTable.selectItems(folderName); + await page.acaHeader.clickMoreActions(); + await page.matMenu.clickMenuItem('Folder Information'); + await expect(async () => { + expect(await page.folderInformationDialog.folderSize.textContent()).toContain(expectedSize); + }).toPass({ + intervals: [1_000], + timeout: 5_000 + }); + if (!isEmptyFolder) { + expect(await page.folderInformationDialog.getFolderSizeNumber()).toBeGreaterThan(0); + } + expect(await page.folderInformationDialog.folderLocation.textContent()).toContain(location); + expect(await page.folderInformationDialog.folderCreationDate.textContent()).toContain('ago'); + expect(await page.folderInformationDialog.folderModifiedDate.textContent()).toContain('ago'); + await page.folderInformationDialog.doneButton.click(); + await page.folderInformationDialog.folderName.waitFor({ state: 'hidden' }); + } + + test('[XAT-17722] Folder information Empty folder size and number of documents as 0', async ({ personalFiles }) => { + await personalFiles.navigate(); + await checkFolderInformation(personalFiles, emptyFolder, '0 bytes for 0 files', `/Company Home/User Homes/${username}`, 'isEmpty'); + }); + + test('[XAT-17715] Folder information correct folder size and number of documents - single file', async ({ personalFiles }) => { + await personalFiles.navigate(); + await checkFolderInformation(personalFiles, folder1File, 'for 1 files', `/Company Home/User Homes/${username}`); + }); + + test('[XAT-17752] Folder information correct folder size and number of documents - multiple files', async ({ personalFiles }) => { + await personalFiles.navigate(); + await checkFolderInformation(personalFiles, folderXFiles, 'for 3 files', `/Company Home/User Homes/${username}`); + }); + + test('[XAT-17753] Folder information correct folder size and number of documents - folder and files', async ({ personalFiles }) => { + await personalFiles.navigate(); + await checkFolderInformation(personalFiles, folderXFilesAndFolders, 'for 5 files', `/Company Home/User Homes/${username}`); + }); + + test('[XAT-17758] Folder information correct folder size and number of documents - from libraries', async ({ myLibrariesPage }) => { + await myLibrariesPage.navigate(); + await myLibrariesPage.dataTable.getRowByName(libraryForFolder).dblclick(); + await checkFolderInformation(myLibrariesPage, folderInLibrary, 'for 1 files', `/Company Home/Sites/${libraryForFolder}/documentLibrary`); + }); + + test('[XAT-17759] Folder information correct folder size and number of documents - from search', async ({ personalFiles, searchPage }) => { + await personalFiles.navigate(); + await searchPage.searchWithin(folderForSearch, 'folders'); + await checkFolderInformation(searchPage, folderForSearch, 'for 2 files', `/Company Home/User Homes/${username}`); + }); + + test('[XAT-17766] Folder information correct folder size and number of documents - nested folders', async ({ personalFiles }) => { + await personalFiles.navigate(); + await personalFiles.dataTable.getRowByName(folderNested1).dblclick(); + await personalFiles.dataTable.getRowByName(folderNested2).dblclick(); + await checkFolderInformation( + personalFiles, + folderNested3, + 'for 1 files', + `/Company Home/User Homes/${username}/${folderNested1}/${folderNested2}` + ); + }); +}); diff --git a/e2e/playwright/folder-information-actions/tsconfig.e2e.adf.json b/e2e/playwright/folder-information-actions/tsconfig.e2e.adf.json new file mode 100644 index 000000000..47ea883b4 --- /dev/null +++ b/e2e/playwright/folder-information-actions/tsconfig.e2e.adf.json @@ -0,0 +1,15 @@ +{ + "extends": "../../../tsconfig.adf.json", + "compilerOptions": { + "outDir": "../../out-tsc/e2e", + "baseUrl": "./", + "module": "commonjs", + "target": "es2017", + "types": ["jasmine", "jasminewd2", "node"], + "skipLibCheck": true, + "paths": { + "@alfresco/aca-playwright-shared": ["dist/@alfresco/aca-playwright-shared"] + } + }, + "exclude": ["node_modules"] +} diff --git a/e2e/playwright/folder-information-actions/tsconfig.e2e.json b/e2e/playwright/folder-information-actions/tsconfig.e2e.json new file mode 100755 index 000000000..16d87d8ec --- /dev/null +++ b/e2e/playwright/folder-information-actions/tsconfig.e2e.json @@ -0,0 +1,15 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/e2e", + "baseUrl": "./", + "module": "commonjs", + "target": "es2017", + "types": ["jasmine", "jasminewd2", "node", "@playwright/test"], + "skipLibCheck": true, + "paths": { + "@alfresco/aca-playwright-shared": ["dist/@alfresco/aca-playwright-shared"] + } + }, + "exclude": ["node_modules"] +} diff --git a/projects/aca-playwright-shared/src/page-objects/components/dialogs/folder-information-dialog.component.ts b/projects/aca-playwright-shared/src/page-objects/components/dialogs/folder-information-dialog.component.ts new file mode 100644 index 000000000..d945a7afa --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/components/dialogs/folder-information-dialog.component.ts @@ -0,0 +1,49 @@ +/*! + * 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 { Page } from '@playwright/test'; +import { BaseComponent } from '../base.component'; + +export class FolderInformationDialogComponent extends BaseComponent { + private static readonly rootElement = '[data-automation-id="adf-dialog-container"]'; + + constructor(page: Page) { + super(page, FolderInformationDialogComponent.rootElement); + } + + folderName = this.getChild('.aca-folder-info-header'); + doneButton = this.getChild('[data-automation-id="adf-dialog-actions-confirm"]'); + folderSize = this.getChild('[data-automation-id="folder-info-size"]'); + folderLocation = this.getChild('[data-automation-id="folder-info-location"]'); + folderCreationDate = this.getChild('[data-automation-id="folder-info-creation-date"]'); + folderModifiedDate = this.getChild('[data-automation-id="folder-info-modify-date"]'); + + async getFolderSizeNumber(): Promise { + const textContent = await this.folderSize.textContent(); + if (!textContent) { + throw new Error('Folder size text content is null or undefined'); + } + return parseInt(textContent.split(' ')[0].replace(/,/g, ''), 10); + } +} 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 f421cac60..10e50bae9 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 @@ -36,4 +36,4 @@ export * from './upload-dialog.component'; export * from './delete-trash-dialog.component'; export * from './link-rules.component'; export * from './edit-dialog.component'; -export * from './manage-versions-dialog.component'; +export * from './folder-information-dialog.component'; diff --git a/projects/aca-playwright-shared/src/page-objects/pages/my-libraries.page.ts b/projects/aca-playwright-shared/src/page-objects/pages/my-libraries.page.ts index 9eb8a3b9f..d8b9dbe9e 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/my-libraries.page.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/my-libraries.page.ts @@ -36,7 +36,8 @@ import { Breadcrumb, SidenavComponent, CreateFromTemplateDialogComponent, - AdfConfirmDialogComponent + AdfConfirmDialogComponent, + FolderInformationDialogComponent } from '../components'; export class MyLibrariesPage extends BasePage { @@ -58,6 +59,7 @@ export class MyLibrariesPage extends BasePage { public contentNodeSelector = new ContentNodeSelectorDialog(this.page); public createFromTemplateDialogComponent = new CreateFromTemplateDialogComponent(this.page); public confirmDialogComponent = new AdfConfirmDialogComponent(this.page); + public folderInformationDialog = new FolderInformationDialogComponent(this.page); async selectCreateLibrary(): Promise { await this.acaHeader.createButton.click(); 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 39de00d74..71959eb6c 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 @@ -45,7 +45,8 @@ import { ManageVersionsDialog, UploadDialog, SnackBarComponent, - EditDialog + EditDialog, + FolderInformationDialogComponent } from '../components'; export class PersonalFilesPage extends BasePage { @@ -76,6 +77,7 @@ export class PersonalFilesPage extends BasePage { public uploadDialog = new UploadDialog(this.page); public snackBar = new SnackBarComponent(this.page); public editDialog = new EditDialog(this.page); + public folderInformationDialog = new FolderInformationDialogComponent(this.page); async selectCreateFolder(): Promise { await this.acaHeader.createButton.click(); diff --git a/projects/aca-playwright-shared/src/page-objects/pages/search.page.ts b/projects/aca-playwright-shared/src/page-objects/pages/search.page.ts index 08bad1966..93f935ec9 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/search.page.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/search.page.ts @@ -38,7 +38,8 @@ import { SearchFiltersDate, SearchFiltersLocation, SearchFiltersLogic, - SearchFiltersProperties + SearchFiltersProperties, + FolderInformationDialogComponent } from '../components'; import { AcaHeader } from '../components/aca-header.component'; import { AdfConfirmDialogComponent, AdfFolderDialogComponent, UploadNewVersionDialog, ManageVersionsDialog } from '../components/dialogs'; @@ -71,6 +72,7 @@ export class SearchPage extends BasePage { public confirmDialogComponent = new AdfConfirmDialogComponent(this.page); public uploadNewVersionDialog = new UploadNewVersionDialog(this.page); public manageVersionsDialog = new ManageVersionsDialog(this.page); + public folderInformationDialog = new FolderInformationDialogComponent(this.page); async searchWithin(searchText: string, searchType?: SearchType): Promise { await this.acaHeader.searchButton.click();