diff --git a/e2e/playwright/actions/src/tests/create-folder.spec.ts b/e2e/playwright/actions/src/tests/create-folder.spec.ts index f15d098e3b..71fc4b5a4b 100644 --- a/e2e/playwright/actions/src/tests/create-folder.spec.ts +++ b/e2e/playwright/actions/src/tests/create-folder.spec.ts @@ -26,7 +26,7 @@ import { expect } from '@playwright/test'; import { folderErrors, getUserState, test } from '@alfresco/playwright-shared'; test.use({ storageState: getUserState('hruser') }); -test.describe('Create actions', () => { +test.describe('Create folders', () => { let randomFolderName: string; let randomFolderTitle: string; let randomFolderDescription: string; @@ -47,7 +47,7 @@ test.describe('Create actions', () => { await personalFiles.dataTable.goThroughPagesLookingForRowWithName(randomFolderName); await expect(personalFiles.dataTable.getRowByName(randomFolderName)).toBeVisible(); - await personalFiles.dataTable.performActionFromExpandableMenu(randomFolderName, 'Delete'); + await personalFiles.dataTable.performActionInExpandableMenu(randomFolderName, 'Delete'); }); test('[C216340] Create a folder with name, title and description', async ({ personalFiles }) => { @@ -59,14 +59,12 @@ test.describe('Create actions', () => { await personalFiles.folderDialog.createButton.click(); await personalFiles.dataTable.goThroughPagesLookingForRowWithName(randomFolderName); - await expect( - personalFiles.dataTable - .getCellLinkByName(randomFolderName) - .and(personalFiles.page.getByTitle(randomFolderTitle)) - .and(personalFiles.page.getByTitle(randomFolderDescription)) - ).toBeVisible(); - - await personalFiles.dataTable.performActionFromExpandableMenu(randomFolderName, 'Delete'); + await expect(personalFiles.dataTable.getCellLinkByName(randomFolderName)).toHaveAttribute( + 'title', + randomFolderTitle + `\n` + randomFolderDescription + ); + + await personalFiles.dataTable.performActionInExpandableMenu(randomFolderName, 'Delete'); }); test('[C216345] Create new folder dialog check', async ({ personalFiles }) => { @@ -152,7 +150,7 @@ test.describe('Create actions', () => { await expect(personalFiles.snackBar.getByMessageLocator(folderErrors.thereIsAlreadyAFolderWithThisName)).toBeVisible(); await personalFiles.folderDialog.cancelButton.click(); - await personalFiles.dataTable.performActionFromExpandableMenu(randomFolderName, 'Delete'); + await personalFiles.dataTable.performActionInExpandableMenu(randomFolderName, 'Delete'); }); test('[C216351] Folder created after trimmed ending spaces from a folder name', async ({ personalFiles }) => { @@ -164,6 +162,6 @@ test.describe('Create actions', () => { await personalFiles.dataTable.goThroughPagesLookingForRowWithName(randomFolderName); await expect(personalFiles.dataTable.getRowByName(randomFolderName)).toBeVisible(); - await personalFiles.dataTable.performActionFromExpandableMenu(randomFolderName, 'Delete'); + await personalFiles.dataTable.performActionInExpandableMenu(randomFolderName, 'Delete'); }); }); diff --git a/e2e/playwright/actions/src/tests/create-library.spec.ts b/e2e/playwright/actions/src/tests/create-library.spec.ts new file mode 100644 index 0000000000..a54047e4e5 --- /dev/null +++ b/e2e/playwright/actions/src/tests/create-library.spec.ts @@ -0,0 +1,263 @@ +/*! + * 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 { expect } from '@playwright/test'; +import { Utils, ApiClientFactory, getUserState, test, libraryErrors } from '@alfresco/playwright-shared'; +import { SiteBodyCreate } from '@alfresco/js-api'; + +test.use({ storageState: getUserState('hruser') }); +test.describe('Create Libraries ', () => { + const apiClientFactory = new ApiClientFactory(); + let randomLibraryName: string; + let randomLibraryId: string; + let randomLibraryDescription: string; + const libraryDialogTitle = 'Create Library'; + const libraryNameLabel = 'Name *'; + const libraryIdLabel = 'Library ID *'; + const libraryDescriptionLabel = 'Description'; + const publicVisibility = 'Public'; + const moderatedVisibility = 'Moderated'; + const privateVisibility = 'Private'; + const deleteAction = 'Delete'; + const errorMessageNotPresent = 'Error message is not displayed'; + + const commonLibraryName = `playwright-library-${Utils.random()}`; + const commonLibraryId = `libraryId-${Utils.random()}`; + const commonTrashLibraryName = `playwright-library-${Utils.random()}`; + const commonTrashLibraryId = `libraryId-${Utils.random()}`; + + test.beforeAll(async () => { + await apiClientFactory.setUpAcaBackend('hruser'); + await apiClientFactory.sites.createSite({ id: commonLibraryId, title: commonLibraryName, visibility: SiteBodyCreate.VisibilityEnum.PUBLIC }); + await apiClientFactory.sites.createSite({ + id: commonTrashLibraryId, + title: commonTrashLibraryName, + visibility: SiteBodyCreate.VisibilityEnum.PUBLIC + }); + await apiClientFactory.sites.deleteSite(commonTrashLibraryId); + }); + + test.beforeEach(async ({ myLibrariesPage }) => { + randomLibraryName = `playwright-library-${Utils.random()}`; + randomLibraryId = `libraryId-${Utils.random()}`; + randomLibraryDescription = `libraryDescription-${Utils.random()}`; + await myLibrariesPage.navigate(); + }); + + test.afterAll(async () => { + await apiClientFactory.sites.deleteSite(commonLibraryId, { permanent: true }); + }); + + test('[C280024] Create Library dialog UI', async ({ myLibrariesPage }) => { + const libraryDialog = myLibrariesPage.libraryDialog; + + await myLibrariesPage.selectCreateLibrary(); + + await expect(libraryDialog.getDialogTitle(libraryDialogTitle)).toBeVisible(); + await expect(libraryDialog.getLabelText(libraryNameLabel)).toBeVisible(); + await expect(libraryDialog.getLabelText(libraryIdLabel)).toBeVisible(); + await expect(libraryDialog.getLabelText(libraryDescriptionLabel)).toBeVisible(); + await expect(libraryDialog.getLabelText(publicVisibility)).toBeVisible(); + await expect(libraryDialog.getLabelText(publicVisibility)).toBeChecked(); + await expect(libraryDialog.getLabelText(privateVisibility)).toBeVisible(); + await expect(libraryDialog.getLabelText(moderatedVisibility)).toBeVisible(); + await expect(libraryDialog.cancelButton).toBeEnabled(); + await expect(libraryDialog.createButton).toBeDisabled(); + }); + + test('[C280025] Create a public library', async ({ myLibrariesPage }) => { + const libraryDialog = myLibrariesPage.libraryDialog; + const libraryTable = myLibrariesPage.dataTable; + const libraryBreadcrumb = myLibrariesPage.breadcrumb; + + await myLibrariesPage.selectCreateLibrary(); + await libraryDialog.getLabelText(libraryNameLabel).fill(randomLibraryName); + await expect(libraryDialog.getLabelText(libraryNameLabel)).toHaveValue(randomLibraryName); + await expect(libraryDialog.getLabelText(libraryIdLabel)).toHaveValue(randomLibraryName); + await libraryDialog.createButton.click(); + await expect(libraryBreadcrumb.getBreadcrumbItem(randomLibraryName)).toBeVisible(); + + await myLibrariesPage.navigate(); + await libraryTable.goThroughPagesLookingForRowWithName(randomLibraryName); + await expect(libraryTable.getCellByColumnNameAndRowItem(randomLibraryName, publicVisibility)).toBeVisible(); + + await libraryTable.performActionInExpandableMenu(randomLibraryName, deleteAction); + }); + + test('[C289880] Create a moderated library', async ({ myLibrariesPage }) => { + const libraryDialog = myLibrariesPage.libraryDialog; + const libraryTable = myLibrariesPage.dataTable; + const libraryBreadcrumb = myLibrariesPage.breadcrumb; + + await myLibrariesPage.selectCreateLibrary(); + await libraryDialog.createLibraryWithNameAndId(randomLibraryName, randomLibraryId, null, moderatedVisibility); + await expect(libraryBreadcrumb.getBreadcrumbItem(randomLibraryName)).toBeVisible(); + + await myLibrariesPage.navigate(); + await libraryTable.goThroughPagesLookingForRowWithName(randomLibraryName); + await expect(libraryTable.getCellByColumnNameAndRowItem(randomLibraryName, moderatedVisibility)).toBeVisible(); + + await libraryTable.performActionInExpandableMenu(randomLibraryName, deleteAction); + }); + + test('[C289881] Create a private library', async ({ myLibrariesPage }) => { + const libraryDialog = myLibrariesPage.libraryDialog; + const libraryTable = myLibrariesPage.dataTable; + const libraryBreadcrumb = myLibrariesPage.breadcrumb; + + await myLibrariesPage.selectCreateLibrary(); + await libraryDialog.createLibraryWithNameAndId(randomLibraryName, randomLibraryId, null, privateVisibility); + await expect(libraryBreadcrumb.getBreadcrumbItem(randomLibraryName)).toBeVisible(); + + await myLibrariesPage.navigate(); + await libraryTable.goThroughPagesLookingForRowWithName(randomLibraryName); + await expect(libraryTable.getCellByColumnNameAndRowItem(randomLibraryName, privateVisibility)).toBeVisible(); + + await libraryTable.performActionInExpandableMenu(randomLibraryName, deleteAction); + }); + + test('[C289882] Create a library with a given ID and description', async ({ myLibrariesPage }) => { + const libraryDialog = myLibrariesPage.libraryDialog; + const libraryTable = myLibrariesPage.dataTable; + const libraryBreadcrumb = myLibrariesPage.breadcrumb; + const libraryViewDetails = myLibrariesPage.acaHeader.viewDetails; + const libraryDetails = myLibrariesPage.libraryDetails; + + await myLibrariesPage.selectCreateLibrary(); + await libraryDialog.createLibraryWithNameAndId(randomLibraryName, randomLibraryId, randomLibraryDescription); + await expect(libraryBreadcrumb.getBreadcrumbItem(randomLibraryName)).toBeVisible(); + + await myLibrariesPage.navigate(); + await libraryTable.goThroughPagesLookingForRowWithName(randomLibraryName); + await expect(libraryTable.getCellLinkByName(randomLibraryName).and(myLibrariesPage.page.getByTitle(randomLibraryDescription))).toBeVisible(); + await libraryTable.getRowByName(randomLibraryName).click(); + await libraryViewDetails.click(); + await expect(libraryDetails.getNameField('Name').getByText(randomLibraryName)).toBeVisible(); + await expect(libraryDetails.getIdField('Library ID').getByText(randomLibraryId)).toBeVisible(); + await expect(libraryDetails.getVisibilityField('Visibility').getByText(publicVisibility)).toBeVisible(); + await expect(libraryDetails.getDescriptionField(libraryDescriptionLabel).getByText(randomLibraryDescription)).toBeVisible(); + + await apiClientFactory.sites.deleteSite(randomLibraryId, { permanent: true }); + }); + + test('[C280027] Duplicate library ID', async ({ myLibrariesPage }) => { + const libraryDialog = myLibrariesPage.libraryDialog; + + await myLibrariesPage.selectCreateLibrary(); + await libraryDialog.getLabelText(libraryNameLabel).fill(randomLibraryName); + await libraryDialog.getLabelText(libraryIdLabel).clear(); + await libraryDialog.getLabelText(libraryIdLabel).fill(commonLibraryId); + await libraryDialog.page.keyboard.press('Tab'); + await expect(libraryDialog.getLabelText(libraryIdLabel)).toHaveValue(commonLibraryId); + + await expect(libraryDialog.createButton).toBeDisabled(); + expect(await libraryDialog.isErrorMessageDisplayed(libraryErrors.libraryIdIsNotAvailable), errorMessageNotPresent).toBe(true); + }); + + test('[C280028] Create library using the ID of a library from the Trashcan', async ({ myLibrariesPage }) => { + const libraryDialog = myLibrariesPage.libraryDialog; + + await myLibrariesPage.selectCreateLibrary(); + await libraryDialog.getLabelText(libraryNameLabel).fill(randomLibraryName); + await libraryDialog.getLabelText(libraryIdLabel).clear(); + await libraryDialog.getLabelText(libraryIdLabel).fill(commonTrashLibraryId); + await libraryDialog.page.keyboard.press('Tab'); + + await expect(libraryDialog.createButton).toBeEnabled(); + await libraryDialog.createButton.click(); + await expect(libraryDialog.createButton).toBeDisabled(); + expect(await libraryDialog.isErrorMessageDisplayed(libraryErrors.libraryIdIsAlreadyUsed), errorMessageNotPresent).toBe(true); + }); + + test('[C280029] Cancel button', async ({ myLibrariesPage }) => { + const libraryDialog = myLibrariesPage.libraryDialog; + const libraryTable = myLibrariesPage.dataTable; + const libraryBreadcrumb = myLibrariesPage.breadcrumb; + + await myLibrariesPage.selectCreateLibrary(); + await expect(libraryDialog.getDialogTitle(libraryDialogTitle)).toBeVisible(); + await libraryDialog.getLabelText(libraryNameLabel).fill(randomLibraryName); + await libraryDialog.cancelButton.click(); + + await expect(libraryDialog.getDialogTitle(libraryDialogTitle)).toBeHidden(); + await expect(libraryBreadcrumb.getBreadcrumbItem(randomLibraryName)).toHaveCount(0); + await expect(libraryTable.getRowByName(randomLibraryName)).toHaveCount(0); + }); + + test('[C280026] Library ID cannot contain special characters', async ({ myLibrariesPage }) => { + const libraryDialog = myLibrariesPage.libraryDialog; + const idsWithSpecialChars = [ + 'a!a', + 'a@a', + 'a#a', + 'a%a', + 'a^a', + 'a&a', + 'a*a', + 'a(a', + 'a)a', + 'a"a', + 'aa', + `a\\a`, + 'a/a', + 'a?a', + 'a:a', + 'a|a' + ]; + + await myLibrariesPage.selectCreateLibrary(); + await libraryDialog.getLabelText(libraryNameLabel).fill(randomLibraryName); + + for (const specialLibraryId of idsWithSpecialChars) { + await libraryDialog.getLabelText(libraryIdLabel).clear(); + await libraryDialog.getLabelText(libraryIdLabel).fill(specialLibraryId); + await libraryDialog.page.keyboard.press('Tab'); + await expect(libraryDialog.getLabelText(libraryIdLabel)).toHaveValue(specialLibraryId); + expect(await libraryDialog.isErrorMessageDisplayed(libraryErrors.useNumbersAndLettersOnly), errorMessageNotPresent).toBe(true); + await expect(libraryDialog.createButton).toBeDisabled(); + } + }); + + test('[C280030] Create 2 libraries with same name but different IDs', async ({ myLibrariesPage }) => { + const libraryDialog = myLibrariesPage.libraryDialog; + const libraryTable = myLibrariesPage.dataTable; + const libraryBreadcrumb = myLibrariesPage.breadcrumb; + const libraryName = commonLibraryName + ' (' + commonLibraryId + ')'; + const libraryName2 = commonLibraryName + ' (' + randomLibraryId + ')'; + + await myLibrariesPage.selectCreateLibrary(); + await libraryDialog.createLibraryWithNameAndId(commonLibraryName, randomLibraryId); + + await expect(libraryBreadcrumb.getBreadcrumbItem(commonLibraryName)).toBeVisible(); + + await myLibrariesPage.navigate(); + await libraryTable.goThroughPagesLookingForRowWithName(libraryName); + await expect(libraryTable.getRowByName(libraryName)).toBeVisible(); + await libraryTable.goThroughPagesLookingForRowWithName(libraryName2); + await expect(libraryTable.getRowByName(libraryName2)).toBeVisible(); + + await apiClientFactory.sites.deleteSite(randomLibraryId, { permanent: true }); + }); +}); diff --git a/e2e/protractor/suites/actions/create/create-library.test.ts b/e2e/protractor/suites/actions/create/create-library.test.ts deleted file mode 100755 index 874a1f702a..0000000000 --- a/e2e/protractor/suites/actions/create/create-library.test.ts +++ /dev/null @@ -1,240 +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 { - AdminActions, - SITE_VISIBILITY, - LoginPage, - BrowsingPage, - CreateLibraryDialog, - Utils, - RepoClient, - UserActions -} from '@alfresco/aca-testing-shared'; -import { BrowserActions } from '@alfresco/adf-testing'; - -describe('Create library', () => { - const username = `user-${Utils.random()}`; - - const site1Name = `site1-${Utils.random()}`; - const site2Name = `site2-${Utils.random()}`; - const site3Name = `site3-${Utils.random()}`; - - const site4 = { - name: `site4-${Utils.random()}`, - id: `site4-id-${Utils.random()}`, - description: 'site4 description' - }; - - const duplicateSite = { - name: `duplicate-${Utils.random()}`, - id: `duplicate-${Utils.random()}` - }; - - const siteInTrash = { - name: `site-trash-${Utils.random()}`, - id: `site-trash-id-${Utils.random()}` - }; - - const apis = { - user: new RepoClient(username, username) - }; - - const loginPage = new LoginPage(); - const page = new BrowsingPage(); - const createDialog = new CreateLibraryDialog(); - const { dataTable } = page; - const adminApiActions = new AdminActions(); - const userActions = new UserActions(); - - beforeAll(async () => { - await adminApiActions.createUser({ username }); - await apis.user.sites.createSite(duplicateSite.name, SITE_VISIBILITY.PRIVATE, '', duplicateSite.id); - await apis.user.sites.createSite(siteInTrash.name, SITE_VISIBILITY.PUBLIC, '', siteInTrash.id); - await apis.user.sites.deleteSite(siteInTrash.id, false); - - await loginPage.loginWith(username); - }); - - afterEach(async () => { - await Utils.pressEscape(); - }); - - afterAll(async () => { - await apis.user.sites.deleteAllUserSites(); - await userActions.login(username, username); - await userActions.emptyTrashcan(); - }); - - it('[C280024] Create Library dialog UI', async () => { - await page.goToMyLibrariesAndWait(); - - await page.toolbar.openCreateLibraryDialog(); - await createDialog.waitForDialogToOpen(); - - expect(await createDialog.getDialogTitle()).toMatch('Create Library'); - expect(await createDialog.nameInput.isDisplayed()).toBe(true, 'Name input is not displayed'); - expect(await createDialog.libraryIdInput.isDisplayed()).toBe(true, 'Library ID input is not displayed'); - expect(await createDialog.descriptionTextArea.isDisplayed()).toBe(true, 'Description field is not displayed'); - expect(await createDialog.visibilityPublic.isDisplayed()).toBe(true, 'Public option is not displayed'); - expect(await createDialog.visibilityModerated.isDisplayed()).toBe(true, 'Moderated option is not displayed'); - expect(await createDialog.visibilityPrivate.isDisplayed()).toBe(true, 'Private option is not displayed'); - expect(await createDialog.isPublicChecked()).toBe(true, 'Public option not checked'); - expect(await createDialog.isCreateEnabled()).toBe(false, 'Create button is not disabled'); - expect(await createDialog.isCancelEnabled()).toBe(true, 'Cancel button is not enabled'); - }); - - it('[C280025] Create a public library', async () => { - await page.goToMyLibrariesAndWait(); - - await page.toolbar.openCreateLibraryDialog(); - await createDialog.waitForDialogToOpen(); - await createDialog.enterName(site1Name); - await BrowserActions.click(createDialog.createButton); - await createDialog.waitForDialogToClose(); - - expect(await page.breadcrumb.currentItem.getText()).toEqual(site1Name, `Not navigated into ${site1Name}`); - await page.goToMyLibrariesAndWait(); - expect(await dataTable.isItemPresent(site1Name)).toBe(true, `${site1Name} not in the list`); - expect((await apis.user.sites.getSite(site1Name)).entry.visibility).toEqual(SITE_VISIBILITY.PUBLIC); - }); - - it('[C289880] Create a moderated library', async () => { - await page.goToMyLibrariesAndWait(); - - await page.toolbar.openCreateLibraryDialog(); - await createDialog.waitForDialogToOpen(); - await createDialog.enterName(site2Name); - await BrowserActions.click(createDialog.visibilityModerated); - await BrowserActions.click(createDialog.createButton); - await createDialog.waitForDialogToClose(); - - expect(await page.breadcrumb.currentItem.getText()).toEqual(site2Name, `Not navigated into ${site2Name}`); - await page.goToMyLibrariesAndWait(); - expect(await dataTable.isItemPresent(site2Name)).toBe(true, `${site2Name} not in the list`); - expect((await apis.user.sites.getSite(site2Name)).entry.visibility).toEqual(SITE_VISIBILITY.MODERATED); - }); - - it('[C289881] Create a private library', async () => { - await page.goToMyLibrariesAndWait(); - - await page.toolbar.openCreateLibraryDialog(); - await createDialog.waitForDialogToOpen(); - await createDialog.enterName(site3Name); - await BrowserActions.click(createDialog.visibilityPrivate); - await BrowserActions.click(createDialog.createButton); - await createDialog.waitForDialogToClose(); - - expect(await page.breadcrumb.currentItem.getText()).toEqual(site3Name, `Not navigated into ${site3Name}`); - await page.goToMyLibrariesAndWait(); - expect(await dataTable.isItemPresent(site3Name)).toBe(true, `${site3Name} not in the list`); - expect((await apis.user.sites.getSite(site3Name)).entry.visibility).toEqual(SITE_VISIBILITY.PRIVATE); - }); - - it('[C289882] Create a library with a given ID and description', async () => { - await page.goToMyLibrariesAndWait(); - - await page.toolbar.openCreateLibraryDialog(); - await createDialog.waitForDialogToOpen(); - await createDialog.enterName(site4.name); - await createDialog.enterLibraryId(site4.id); - await createDialog.enterDescription(site4.description); - await BrowserActions.click(createDialog.visibilityPublic); - await BrowserActions.click(createDialog.createButton); - await createDialog.waitForDialogToClose(); - - expect(await page.breadcrumb.currentItem.getText()).toEqual(site4.name, `Not navigated into ${site4.name}`); - await page.goToMyLibrariesAndWait(); - expect(await dataTable.isItemPresent(site4.name)).toBe(true, `${site4.name} not in the list`); - expect((await apis.user.sites.getSite(site4.id)).entry.visibility).toEqual(SITE_VISIBILITY.PUBLIC); - expect((await apis.user.sites.getSite(site4.id)).entry.description).toEqual(site4.description); - }); - - it('[C280027] Duplicate library ID', async () => { - await page.goToMyLibrariesAndWait(); - - await page.toolbar.openCreateLibraryDialog(); - await createDialog.waitForDialogToOpen(); - await createDialog.enterName(duplicateSite.name); - await createDialog.enterLibraryId(duplicateSite.id); - - expect(await createDialog.isCreateEnabled()).toBe(false, 'Create button not disabled'); - expect(await createDialog.getErrorMessage()).toEqual(`This Library ID isn't available. Try a different Library ID.`); - }); - - it('[C280028] Create library using the ID of a library from the Trashcan', async () => { - await page.goToMyLibrariesAndWait(); - - await page.toolbar.openCreateLibraryDialog(); - await createDialog.waitForDialogToOpen(); - await createDialog.enterName(siteInTrash.name); - await createDialog.enterLibraryId(siteInTrash.id); - await BrowserActions.click(createDialog.createButton); - - expect(await createDialog.getErrorMessage()).toEqual(`This Library ID is already used. Check the trashcan.`); - }); - - it('[C280029] Cancel button', async () => { - await page.goToMyLibrariesAndWait(); - - await page.toolbar.openCreateLibraryDialog(); - await createDialog.waitForDialogToOpen(); - await createDialog.enterName('test site'); - await createDialog.enterDescription('test description'); - await createDialog.clickCancel(); - - expect(await createDialog.isDialogOpen()).not.toBe(true, 'dialog is not closed'); - }); - - it('[C280026] Library ID cannot contain special characters', async () => { - const idWithSpecialChars = ['a*a', 'a"a', 'aa', `a\\a`, 'a/a', 'a?a', 'a:a', 'a|a']; - - await page.goToMyLibrariesAndWait(); - await page.toolbar.openCreateLibraryDialog(); - await createDialog.waitForDialogToOpen(); - await createDialog.enterName('test site'); - - for (const id of idWithSpecialChars) { - await createDialog.enterLibraryId(id); - expect(await createDialog.isCreateEnabled()).toBe(false, 'Create button is not disabled'); - expect(await createDialog.getErrorMessage()).toContain(`Use numbers and letters only`); - } - }); - - it('[C280030] Create 2 libraries with same name but different IDs', async () => { - await page.goToMyLibrariesAndWait(); - - await page.toolbar.openCreateLibraryDialog(); - await createDialog.waitForDialogToOpen(); - await createDialog.enterName(duplicateSite.name); - await createDialog.enterLibraryId(`${duplicateSite.id}-2`); - await BrowserActions.click(createDialog.createButton); - await createDialog.waitForDialogToClose(); - - expect(await page.breadcrumb.currentItem.getText()).toEqual(duplicateSite.name, `Not navigated into ${duplicateSite.name}`); - await page.goToMyLibrariesAndWait(); - expect(await dataTable.isItemPresent(`${duplicateSite.name} (${duplicateSite.id}-2)`)).toBe(true, `${duplicateSite.name} not in the list`); - expect((await apis.user.sites.getSite(`${duplicateSite.id}-2`)).entry.title).toEqual(duplicateSite.name); - }); -}); diff --git a/projects/aca-content/src/lib/components/info-drawer/library-metadata-tab/library-metadata-form.component.html b/projects/aca-content/src/lib/components/info-drawer/library-metadata-tab/library-metadata-form.component.html index f11ba26e7d..febcac6b9c 100644 --- a/projects/aca-content/src/lib/components/info-drawer/library-metadata-tab/library-metadata-form.component.html +++ b/projects/aca-content/src/lib/components/info-drawer/library-metadata-tab/library-metadata-form.component.html @@ -1,7 +1,7 @@
-
+
@@ -19,7 +19,7 @@
-
+
@@ -37,7 +37,7 @@
-
+
@@ -55,7 +55,7 @@
-
+
diff --git a/projects/aca-playwright-shared/src/fixtures/page-initialization.ts b/projects/aca-playwright-shared/src/fixtures/page-initialization.ts index a30b775a1c..181f91d056 100644 --- a/projects/aca-playwright-shared/src/fixtures/page-initialization.ts +++ b/projects/aca-playwright-shared/src/fixtures/page-initialization.ts @@ -24,6 +24,7 @@ import { test as base } from '@playwright/test'; import { + MyLibrariesPage, FileActionsApi, NodesPage, PersonalFilesPage, @@ -38,6 +39,7 @@ import { interface Pages { personalFiles: PersonalFilesPage; nodesPage: NodesPage; + myLibrariesPage: MyLibrariesPage; recentFilesPage: RecentFilesPage; sharedPage: SharedPage; searchPage: SearchPage; @@ -80,5 +82,8 @@ export const test = base.extend({ // eslint-disable-next-line no-empty-pattern favoritesPageAction: async ({}, use) => { await use(await FavoritesPageApi.initialize('admin')); + }, + myLibrariesPage: async ({ page }, use) => { + await use(new MyLibrariesPage(page)); } }); 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 063aed6e8f..426a38bbb5 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 @@ -24,10 +24,10 @@ import { BaseComponent } from './base.component'; import { Page } from '@playwright/test'; - export class AcaHeader extends BaseComponent { private static rootElement = 'adf-toolbar'; public createButton = this.getChild('[id="app.toolbar.create"]'); + public viewDetails = this.getChild('[title="View Details"]'); public viewButton = this.getChild('button[title="View"]'); public searchButton = this.getChild('button[title="Search"]'); diff --git a/projects/aca-playwright-shared/src/page-objects/components/adf-info-drawer.component.ts b/projects/aca-playwright-shared/src/page-objects/components/adf-info-drawer.component.ts new file mode 100644 index 0000000000..0e859048eb --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/components/adf-info-drawer.component.ts @@ -0,0 +1,39 @@ +/*! + * 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 { BaseComponent } from './base.component'; +import { Page } from '@playwright/test'; + +export class AdfInfoDrawerComponent extends BaseComponent { + private static rootElement = 'adf-info-drawer'; + + constructor(page: Page) { + super(page, AdfInfoDrawerComponent.rootElement); + } + + public getNameField = (labelText: string) => this.getChild('[data-automation-id="library-name-properties-wrapper"]', { hasText: labelText }); + public getIdField = (labelText: string) => this.getChild('[data-automation-id="library-id-properties-wrapper"]', { hasText: labelText }); + public getVisibilityField = (labelText: string) => this.getChild('[data-automation-id="library-visibility-properties-wrapper"]', { hasText: labelText }); + public getDescriptionField = (labelText: string) => this.getChild('[data-automation-id="library-description-properties-wrapper"]', { hasText: labelText }); +} diff --git a/projects/aca-playwright-shared/src/page-objects/components/breadcrumb/breadcrumb.component.ts b/projects/aca-playwright-shared/src/page-objects/components/breadcrumb/breadcrumb.component.ts new file mode 100644 index 0000000000..d18462c820 --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/components/breadcrumb/breadcrumb.component.ts @@ -0,0 +1,36 @@ +/*! + * 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 { BaseComponent } from '../base.component'; +import { Page } from '@playwright/test'; + +export class AdfBreadcrumbComponent extends BaseComponent { + private static rootElement = 'adf-breadcrumb'; + + constructor(page: Page) { + super(page, AdfBreadcrumbComponent.rootElement); + } + + public getBreadcrumbItem = (text: string) => this.getChild('.adf-breadcrumb-item-current', { hasText: text }); +} diff --git a/projects/aca-playwright-shared/src/page-objects/components/breadcrumb/index.ts b/projects/aca-playwright-shared/src/page-objects/components/breadcrumb/index.ts new file mode 100644 index 0000000000..0d88c7dea3 --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/components/breadcrumb/index.ts @@ -0,0 +1,25 @@ +/*! + * 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 . + */ + +export * from './breadcrumb.component'; diff --git a/projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts b/projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts index 8ae4a2b822..33b079a3cc 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/dataTable/data-table.component.ts @@ -171,6 +171,11 @@ export class DataTableComponent extends BaseComponent { return this.contextMenuActions.getButtonByText(action); } + async performActionInExpandableMenu(name: string | number, action: string): Promise { + await this.getRowByName(name).click({ button: 'right' }); + await this.contextMenuActions.getButtonByText(action).click(); + } + async goThroughPagesLookingForRowWithName(name: string | number): Promise { await this.spinnerWaitForReload(); if (await this.getRowByName(name).isVisible()) { diff --git a/projects/aca-playwright-shared/src/page-objects/components/dataTable/mat-menu.component.ts b/projects/aca-playwright-shared/src/page-objects/components/dataTable/mat-menu.component.ts index 82c4669068..a38e78e0ee 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/dataTable/mat-menu.component.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/dataTable/mat-menu.component.ts @@ -35,5 +35,6 @@ export class MatMenuComponent extends BaseComponent { public getMenuItemsLocator = this.getChild('button'); public getMenuItemTextLocator = this.getChild('[data-automation-id="menu-item-title"]'); public createFolder = this.getChild('[id="app.create.folder"]'); + public createLibrary = this.getChild('[id="app.create.library"]'); public getButtonByText = (text: string) => this.getChild('button', { hasText: text }); } diff --git a/projects/aca-playwright-shared/src/page-objects/components/dialogs/adf-library-dialog.component.ts b/projects/aca-playwright-shared/src/page-objects/components/dialogs/adf-library-dialog.component.ts new file mode 100644 index 0000000000..25ae192926 --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/components/dialogs/adf-library-dialog.component.ts @@ -0,0 +1,64 @@ +/*! + * 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 { timeouts } from '../../../utils'; +import { BaseComponent } from '../base.component'; +import { Locator, Page } from '@playwright/test'; + +export class AdfLibraryDialogComponent extends BaseComponent { + private static rootElement = 'adf-library-dialog'; + + public createButton = this.getChild('[data-automation-id="create-library-id"]'); + public cancelButton = this.getChild('[data-automation-id="cancel-library-id"]'); + + constructor(page: Page) { + super(page, AdfLibraryDialogComponent.rootElement); + } + + public getLabelText = (text: string) => this.getChild('label', { hasText: text }); + public getDialogTitle = (text: string) => this.getChild('.mat-dialog-title', { hasText: text }); + public getErrorByText = (text: string): Locator => this.page.locator('mat-error', {hasText: text}); + + /** + * This method is used when we want to fill in Create Library Dialog and choose Create button + * + * @param nameInput input for the Name field + * @param libraryIdInput input for Library ID field + * @param descriptionInput input for Description field + * @param visibility visibility of the library + */ + async createLibraryWithNameAndId(nameInput: string, libraryIdInput: string, descriptionInput?: string, visibility?: string): Promise { + await this.getLabelText('Name *').fill(nameInput); + await this.getLabelText('Library ID *').clear(); + await this.getLabelText('Library ID *').fill(libraryIdInput); + if (descriptionInput) { await this.getLabelText('Description').fill(descriptionInput); } + if (visibility) { await this.getLabelText(visibility).click(); } + await this.createButton.click(); + } + + async isErrorMessageDisplayed(errorText: string): Promise { + await this.getErrorByText(errorText).waitFor({ state: 'visible', timeout: timeouts.large }); + return await this.getErrorByText(errorText).isVisible(); + } +} 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 f659ffb7d3..1177660266 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 @@ -23,3 +23,5 @@ */ export * from './adf-folder-dialog.component'; +export * from './adf-library-dialog.component'; + 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 a3f04f1fb6..df6a0f3ca3 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/index.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/index.ts @@ -31,6 +31,9 @@ export * from './spinner.component'; export * from './actions-dropdown.component'; export * from './conditions.component'; export * from './pagination.component'; +export * from './breadcrumb'; +export * from './adf-info-drawer.component'; export * from './viewer.component'; export * from './search/search-input.component'; export * from './search/search-overlay.components'; + diff --git a/projects/aca-playwright-shared/src/page-objects/pages/index.ts b/projects/aca-playwright-shared/src/page-objects/pages/index.ts index 72def0ece5..4e9a730348 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/index.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/index.ts @@ -26,6 +26,7 @@ export * from './base.page'; export * from './login.page'; export * from './nodes.page'; export * from './personal-files.page'; +export * from './my-libraries.page'; export * from './recent-files.page'; export * from './shared.page'; export * from './search.page'; 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 new file mode 100644 index 0000000000..46ba9d572a --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/pages/my-libraries.page.ts @@ -0,0 +1,49 @@ +/*! + * 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 { Page } from '@playwright/test'; +import { BasePage } from './base.page'; +import { AcaHeader } from '../components/aca-header.component'; +import { AdfBreadcrumbComponent, AdfInfoDrawerComponent, AdfLibraryDialogComponent, DataTableComponent, MatMenuComponent } from '../components'; + +export class MyLibrariesPage extends BasePage { + private static pageUrl = 'libraries'; + + constructor(page: Page) { + super(page, MyLibrariesPage.pageUrl); + } + public acaHeader = new AcaHeader(this.page); + public matMenu = new MatMenuComponent(this.page); + public libraryDialog = new AdfLibraryDialogComponent(this.page); + public dataTable = new DataTableComponent(this.page); + public breadcrumb = new AdfBreadcrumbComponent(this.page); + public libraryDetails = new AdfInfoDrawerComponent (this.page); + + async selectCreateLibrary(): Promise { + await this.acaHeader.createButton.click(); + await this.matMenu.createLibrary.click(); + } + +} diff --git a/projects/aca-playwright-shared/src/utils/index.ts b/projects/aca-playwright-shared/src/utils/index.ts index f3bdc9b5fb..d6ac3086e5 100644 --- a/projects/aca-playwright-shared/src/utils/index.ts +++ b/projects/aca-playwright-shared/src/utils/index.ts @@ -27,3 +27,5 @@ export * from './timeouts'; export * from './exclude-tests'; export * from './state-helper'; export * from './folder-errors'; +export * from './utils'; +export * from './library-errors'; diff --git a/projects/aca-playwright-shared/src/utils/library-errors.ts b/projects/aca-playwright-shared/src/utils/library-errors.ts new file mode 100644 index 0000000000..1ac8cb55d0 --- /dev/null +++ b/projects/aca-playwright-shared/src/utils/library-errors.ts @@ -0,0 +1,29 @@ +/*! + * 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 . + */ + +export const libraryErrors = { + libraryIdIsNotAvailable: "This Library ID isn't available. Try a different Library ID.", + libraryIdIsAlreadyUsed: "This Library ID is already used. Check the trashcan.", + useNumbersAndLettersOnly: "Use numbers and letters only" +} diff --git a/projects/aca-playwright-shared/src/utils/timeouts.ts b/projects/aca-playwright-shared/src/utils/timeouts.ts index 31b43b13f4..8d86987f25 100644 --- a/projects/aca-playwright-shared/src/utils/timeouts.ts +++ b/projects/aca-playwright-shared/src/utils/timeouts.ts @@ -28,6 +28,7 @@ export const timeouts = { short: 1000, normal: 2000, medium: 5000, + big: 7500, large: 10000, extraLarge: 20 * 1000, globalTest: 45 * 1000, diff --git a/projects/aca-playwright-shared/src/utils/utils.ts b/projects/aca-playwright-shared/src/utils/utils.ts new file mode 100644 index 0000000000..575fb9f8d4 --- /dev/null +++ b/projects/aca-playwright-shared/src/utils/utils.ts @@ -0,0 +1,33 @@ +/*! + * 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 . + */ + +const crypto = require('crypto'); + +export class Utils { + + static random(): string { + return crypto.getRandomValues(new Uint32Array(1))[0].toString(36).substring(0, 5).toLowerCase(); + } + +}