From 97f01386f85dfbde0d0fd5fdbf82ae43cd75fd4e Mon Sep 17 00:00:00 2001 From: Akash Rathod <41251473+akashrathod28@users.noreply.github.com> Date: Mon, 25 Sep 2023 13:00:22 +0200 Subject: [PATCH] [ACS-5923] playwright sidenav and single click test (#3442) * [ACS-5923] sidenav and singleclick test * remove protractor test and fix flaky test * test fix * Update error message for expect --- .../src/tests/breadcrumb-admin.spec.ts | 57 ++++++ .../navigation/src/tests/sidebar.spec.ts | 78 +++++++ .../navigation/src/tests/single-click.spec.ts | 89 ++++++++ .../suites/navigation/sidebar.test.ts | 193 ------------------ .../suites/navigation/single-click.test.ts | 90 -------- .../breadcrumb/breadcrumb.component.ts | 3 +- .../dataTable/data-table.component.ts | 2 + .../src/page-objects/components/index.ts | 1 + .../search/search-input.component.ts | 4 +- .../components/sidenav.component.ts | 97 +++++++++ .../pages/favorites-libraries.page.ts | 45 ++++ .../src/page-objects/pages/favorites.page.ts | 3 +- .../src/page-objects/pages/index.ts | 1 + .../page-objects/pages/my-libraries.page.ts | 4 +- .../page-objects/pages/personal-files.page.ts | 3 +- .../page-objects/pages/recent-files.page.ts | 4 +- .../src/page-objects/pages/search.page.ts | 3 +- .../src/page-objects/pages/shared.page.ts | 3 +- .../src/page-objects/pages/trash.page.ts | 3 +- .../aca-playwright-shared/src/utils/config.ts | 45 ++++ .../aca-playwright-shared/src/utils/index.ts | 1 + 21 files changed, 435 insertions(+), 294 deletions(-) create mode 100644 e2e/playwright/navigation/src/tests/breadcrumb-admin.spec.ts create mode 100644 e2e/playwright/navigation/src/tests/sidebar.spec.ts create mode 100644 e2e/playwright/navigation/src/tests/single-click.spec.ts delete mode 100755 e2e/protractor/suites/navigation/sidebar.test.ts create mode 100644 projects/aca-playwright-shared/src/page-objects/components/sidenav.component.ts create mode 100644 projects/aca-playwright-shared/src/page-objects/pages/favorites-libraries.page.ts create mode 100644 projects/aca-playwright-shared/src/utils/config.ts diff --git a/e2e/playwright/navigation/src/tests/breadcrumb-admin.spec.ts b/e2e/playwright/navigation/src/tests/breadcrumb-admin.spec.ts new file mode 100644 index 000000000..704ccda9d --- /dev/null +++ b/e2e/playwright/navigation/src/tests/breadcrumb-admin.spec.ts @@ -0,0 +1,57 @@ +/*! + * 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 { ApiClientFactory, getUserState, NodesApi, test, Utils } from '@alfresco/playwright-shared'; + +test.use({ storageState: getUserState('admin') }); +test.describe('as admin', () => { + const apiClientFactory = new ApiClientFactory(); + const userFolder = `userFolder-${Utils.random()}`; + const username = `userAdmin-${Utils.random()}`; + let userFolderId: string; + let nodesApi: NodesApi; + + test.beforeAll(async () => { + await apiClientFactory.setUpAcaBackend('admin'); + await apiClientFactory.createUser({ username }); + nodesApi = await NodesApi.initialize(username, username); + const node = await nodesApi.createFolder(userFolder); + userFolderId = node.entry.id; + }); + + test.beforeEach(async ({ personalFiles }) => { + await personalFiles.navigate({ remoteUrl: `#/personal-files}` }); + }); + + test.afterAll(async () => { + await apiClientFactory.nodes.deleteNode(userFolderId, { permanent: true }); + }); + + test(`[C260970] Breadcrumb on navigation to a user's home`, async ({ personalFiles }) => { + await personalFiles.navigate({ remoteUrl: `#/personal-files/${userFolderId}` }); + personalFiles.breadcrumb.getItemByTitle(username).waitFor({ state: 'attached' }); + expect(await personalFiles.breadcrumb.getAllItems()).toEqual(['Personal Files', 'User Homes', username, userFolder]); + }); +}); diff --git a/e2e/playwright/navigation/src/tests/sidebar.spec.ts b/e2e/playwright/navigation/src/tests/sidebar.spec.ts new file mode 100644 index 000000000..7fcc577f1 --- /dev/null +++ b/e2e/playwright/navigation/src/tests/sidebar.spec.ts @@ -0,0 +1,78 @@ +/*! + * 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 { ApiClientFactory, APP_ROUTES, getUserState, SIDEBAR_LABELS, test } from '@alfresco/playwright-shared'; + +test.use({ storageState: getUserState('hruser') }); +test.describe('Sidebar', () => { + const apiClientFactory = new ApiClientFactory(); + + test.beforeAll(async () => { + await apiClientFactory.setUpAcaBackend('hruser'); + }); + + test('[C289901] navigate to My Libraries', async ({ personalFiles, myLibrariesPage }) => { + await personalFiles.navigate(); + await personalFiles.sidenav.openPanel(SIDEBAR_LABELS.MY_LIBRARIES); + await personalFiles.dataTable.spinnerWaitForReload(); + expect(myLibrariesPage.page.url()).toContain(APP_ROUTES.MY_LIBRARIES); + expect(await myLibrariesPage.sidenav.isActive(SIDEBAR_LABELS.MY_LIBRARIES), 'My Libraries link not active').toBe(true); + }); + + test('[C277230] sidenav can be expanded when search results page is displayed', async ({ personalFiles }) => { + await personalFiles.navigate({ remoteUrl: `#/search;q=test` }); + expect(await personalFiles.sidenav.isSidenavExpanded(), 'Sidebar expanded').toBe(false); + await personalFiles.sidenav.expandSideNav(); + expect(await personalFiles.sidenav.isSidenavExpanded(), 'Sidebar not expanded').toBe(true); + }); + + test('[C269100] sidebar state is preserved on page refresh', async ({ personalFiles }) => { + await personalFiles.navigate(); + expect(await personalFiles.sidenav.isSidenavExpanded(), 'Sidebar not expanded').toBe(true); + await personalFiles.reload(); + expect(await personalFiles.sidenav.isSidenavExpanded(), 'Sidebar not expanded').toBe(true); + + await personalFiles.sidenav.collapseSideNav(); + + expect(await personalFiles.sidenav.isSidenavExpanded(), 'Sidebar expanded').toBe(false); + await personalFiles.reload(); + expect(await personalFiles.sidenav.isSidenavExpanded(), 'Sidebar expanded').toBe(false); + }); + + test('[C269096] sidebar toggle', async ({ personalFiles }) => { + await personalFiles.navigate(); + await personalFiles.sidenav.collapseSideNav(); + expect(await personalFiles.sidenav.isSidenavExpanded(), 'Sidebar expanded').toBe(false); + await personalFiles.sidenav.expandSideNav(); + expect(await personalFiles.sidenav.isSidenavExpanded(), 'Sidebar not expanded').toBe(true); + }); + + test('[C277224] sidenav returns to the default state when navigating away from the Search Results page', async ({ personalFiles, searchPage }) => { + await personalFiles.navigate({ remoteUrl: `#/search;q=test` }); + await searchPage.searchInput.getIconByName('close').click(); + await searchPage.sidenav.expandedSidenav.waitFor({ state: 'attached' }); + expect(await personalFiles.sidenav.isSidenavExpanded(), 'Sidebar not expanded').toBe(true); + }); +}); diff --git a/e2e/playwright/navigation/src/tests/single-click.spec.ts b/e2e/playwright/navigation/src/tests/single-click.spec.ts new file mode 100644 index 000000000..6d48acc27 --- /dev/null +++ b/e2e/playwright/navigation/src/tests/single-click.spec.ts @@ -0,0 +1,89 @@ +/*! + * 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 { ApiClientFactory, getUserState, test, Utils } from '@alfresco/playwright-shared'; + +test.use({ storageState: getUserState('hruser') }); +test.describe('Single click on item name', () => { + const apiClientFactory = new ApiClientFactory(); + + const folder1 = `folder1-${Utils.random()}`; + let folder1Id: string; + const folderSearch = `folder1-${Utils.random()}`; + let folderSearchId: string; + + const deletedFile1 = `file1-${Utils.random()}.txt`; + let deletedFile1Id: string; + const deletedFolder1 = `folder1-${Utils.random()}`; + let deletedFolder1Id: string; + + const siteName = `site-${Utils.random()}`; + const fileSite = `fileSite-${Utils.random()}.txt`; + + test.beforeAll(async ({ nodesApiAction, sitesApiAction }) => { + await apiClientFactory.setUpAcaBackend('hruser'); + const node = await apiClientFactory.nodes.createNode('-my-', { name: folder1, nodeType: 'cm:folder', relativePath: '/' }); + folder1Id = node.entry.id; + folderSearchId = (await nodesApiAction.createFolder(folderSearch)).entry.id; + deletedFile1Id = (await nodesApiAction.createFile(deletedFile1)).entry.id; + deletedFolder1Id = (await nodesApiAction.createFolder(deletedFolder1)).entry.id; + + await sitesApiAction.createSite(siteName); + const docLibId = await sitesApiAction.getDocLibId(siteName); + await nodesApiAction.createFile(fileSite, docLibId); + }); + + test.afterAll(async ({ nodesApiAction }) => { + await nodesApiAction.deleteNodes([deletedFolder1Id, deletedFile1Id], true); + }); + + test('[C284899] Hyperlink does not appear for items in the Trash', async ({ trashPage }) => { + await trashPage.navigate(); + expect(await trashPage.dataTable.getCellLinkByName(deletedFile1).isVisible(), 'Link on name is present').toBe(false); + expect(await trashPage.dataTable.getCellLinkByName(deletedFolder1).isVisible(), 'Link on name is present').toBe(false); + }); + + test.describe('on Personal Files', () => { + test.afterAll(async ({ nodesApiAction }) => { + await nodesApiAction.deleteNodes([folder1Id, folderSearchId], true); + }); + + test('[C280034] Navigate inside the folder when clicking the hyperlink on Personal Files', async ({ personalFiles }) => { + await personalFiles.navigate(); + await personalFiles.dataTable.getCellLinkByName(folder1).click(); + await personalFiles.dataTable.spinnerWaitForReload(); + expect(await personalFiles.breadcrumb.currentItem.innerText()).toBe(folder1); + }); + }); + + test('[C284902] Navigate inside the library when clicking the hyperlink on File Libraries', async ({ myLibrariesPage }) => { + await myLibrariesPage.navigate(); + await myLibrariesPage.dataTable.goThroughPagesLookingForRowWithName(siteName); + await myLibrariesPage.dataTable.getCellLinkByName(siteName).click(); + await myLibrariesPage.dataTable.spinnerWaitForReload(); + expect(await myLibrariesPage.breadcrumb.currentItem.innerText()).toBe(siteName); + expect(await myLibrariesPage.dataTable.getCellLinkByName(fileSite).isVisible(), `${fileSite} not displayed`).toBe(true); + }); +}); diff --git a/e2e/protractor/suites/navigation/sidebar.test.ts b/e2e/protractor/suites/navigation/sidebar.test.ts deleted file mode 100755 index 04b3475f8..000000000 --- a/e2e/protractor/suites/navigation/sidebar.test.ts +++ /dev/null @@ -1,193 +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 { browser } from 'protractor'; -import { APP_ROUTES, SIDEBAR_LABELS, LoginPage, BrowsingPage, SearchResultsPage, Utils } from '@alfresco/aca-testing-shared'; - -describe('Sidebar', () => { - const loginPage = new LoginPage(); - const page = new BrowsingPage(); - const { sidenav, toolbar } = page; - const searchResultsPage = new SearchResultsPage(); - const { searchInput } = searchResultsPage.pageLayoutHeader; - - beforeAll(async () => { - await loginPage.loginWithAdmin(); - }); - - beforeEach(async () => { - await Utils.pressEscape(); - await sidenav.expandSideNav(); - }); - - afterEach(async () => { - await Utils.pressEscape(); - await page.clickPersonalFiles(); - }); - - it('[C217149] has "Personal Files" as default', async () => { - expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES); - expect(await sidenav.isActive(SIDEBAR_LABELS.PERSONAL_FILES)).toBe(true, 'Default active link'); - }); - - it('[C289902] navigate to Favorite Libraries', async () => { - await page.goToFavoriteLibraries(); - expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.FAVORITE_LIBRARIES); - expect(await sidenav.isActive(SIDEBAR_LABELS.FAVORITE_LIBRARIES)).toBe(true, 'Favorite Libraries link not active'); - }); - - it('[C289901] navigate to My Libraries', async () => { - await page.goToMyLibraries(); - expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.MY_LIBRARIES); - expect(await sidenav.isActive(SIDEBAR_LABELS.MY_LIBRARIES)).toBe(true, 'My Libraries link not active'); - }); - - it('[C213110] navigates to "Shared Files"', async () => { - await page.clickSharedFiles(); - expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.SHARED_FILES); - expect(await sidenav.isActive(SIDEBAR_LABELS.SHARED_FILES)).toBe(true, 'Shared Files link not active'); - }); - - it('[C213166] navigates to "Recent Files"', async () => { - await page.clickRecentFiles(); - expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.RECENT_FILES); - expect(await sidenav.isActive(SIDEBAR_LABELS.RECENT_FILES)).toBe(true, 'Recent Files link not active'); - }); - - it('[C213225] navigates to "Favorites"', async () => { - await page.clickFavorites(); - expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.FAVORITES); - expect(await sidenav.isActive(SIDEBAR_LABELS.FAVORITES)).toBe(true, 'Favorites link not active'); - }); - - it('[C213216] navigates to "Trash"', async () => { - await page.clickTrash(); - expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.TRASHCAN); - expect(await sidenav.isActive(SIDEBAR_LABELS.TRASH)).toBe(true, 'Trash link not active'); - }); - - it('[C280409] navigates to "Personal Files"', async () => { - await page.clickPersonalFiles(); - expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES); - expect(await sidenav.isActive(SIDEBAR_LABELS.PERSONAL_FILES)).toBe(true, 'Personal Files link not active'); - }); - - it('[C217151] Personal Files tooltip', async () => { - await page.clickPersonalFiles(); - expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.PERSONAL_FILES)).toContain('View your Personal Files'); - }); - - it('[C213111] Shared Files tooltip', async () => { - await page.clickSharedFiles(); - expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.SHARED_FILES)).toContain('View files that have been shared'); - }); - - it('[C213167] Recent Files tooltip', async () => { - await page.clickRecentFiles(); - expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.RECENT_FILES)).toContain('View files you recently edited'); - }); - - it('[C217153] Favorites tooltip', async () => { - await page.clickFavorites(); - expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.FAVORITES)).toContain('View your favorite files and folders'); - }); - - it('[C217154] Trash tooltip', async () => { - await page.clickTrash(); - expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.TRASH)).toContain('View deleted files in the trash'); - }); - - it('[C289916] My Libraries tooltip', async () => { - await page.goToMyLibraries(); - expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.MY_LIBRARIES)).toContain('Access my libraries'); - }); - - it('[C289917] Favorite Libraries tooltip', async () => { - await page.goToFavoriteLibraries(); - expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.FAVORITE_LIBRARIES)).toContain('Access my favorite libraries'); - }); - - it('[C269095] default state is expanded', async () => { - expect(await sidenav.isSidenavExpanded()).toBe(true, 'Sidebar not expanded'); - }); - - it('[C269096] sidebar toggle', async () => { - await sidenav.collapseSideNav(); - expect(await sidenav.isSidenavExpanded()).toBe(false, 'Sidebar not collapsed'); - - await sidenav.expandSideNav(); - expect(await sidenav.isSidenavExpanded()).toBe(true, 'Sidebar not expanded'); - }); - - it('[C269100] sidebar state is preserved on page refresh', async () => { - expect(await sidenav.isSidenavExpanded()).toBe(true, 'Sidebar not expanded'); - await page.refresh(); - expect(await sidenav.isSidenavExpanded()).toBe(true, 'Sidebar not expanded'); - - await sidenav.collapseSideNav(); - expect(await sidenav.isSidenavExpanded()).toBe(false, 'Sidebar not collapsed'); - await page.refresh(); - expect(await sidenav.isSidenavExpanded()).toBe(false, 'Sidebar not collapsed'); - }); - - it('[C269102] sidebar state is preserved after logout / login', async () => { - await sidenav.collapseSideNav(); - await page.signOut(); - await loginPage.loginWithAdmin(); - - expect(await sidenav.isSidenavExpanded()).toBe(false, 'Sidebar not collapsed'); - }); - - it('[C277223] sidebar is collapsed automatically when Search Results opens', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - /* cspell:disable-next-line */ - await searchInput.searchFor('qwertyuiop'); - await searchResultsPage.waitForResults(); - - expect(await sidenav.isSidenavExpanded()).toBe(false, 'Sidebar not collapsed'); - }); - - it('[C277224] sidenav returns to the default state when navigating away from the Search Results page', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - /* cspell:disable-next-line */ - await searchInput.searchFor('qwertyuiop'); - await searchResultsPage.waitForResults(); - await page.clickFavorites(); - - expect(await sidenav.isSidenavExpanded()).toBe(true, 'Sidebar not expanded'); - }); - - it('[C277230] sidenav can be expanded when search results page is displayed', async () => { - await toolbar.clickSearchIconButton(); - await searchInput.clickSearchButton(); - /* cspell:disable-next-line */ - await searchInput.searchFor('qwertyuiop'); - await searchResultsPage.waitForResults(); - await sidenav.expandSideNav(); - - expect(await sidenav.isSidenavExpanded()).toBe(true, 'Sidebar not expanded'); - }); -}); diff --git a/e2e/protractor/suites/navigation/single-click.test.ts b/e2e/protractor/suites/navigation/single-click.test.ts index b048c48a3..a91b82fbd 100755 --- a/e2e/protractor/suites/navigation/single-click.test.ts +++ b/e2e/protractor/suites/navigation/single-click.test.ts @@ -83,96 +83,6 @@ describe('Single click on item name', () => { await userActions.emptyTrashcan(); }); - it('[C284899] Hyperlink does not appear for items in the Trash', async () => { - await page.clickTrashAndWait(); - - expect(await dataTable.hasLinkOnName(deletedFile1)).toBe(false, 'Link on name is present'); - expect(await dataTable.hasLinkOnName(deletedFolder1)).toBe(false, 'Link on name is present'); - }); - - describe('on Personal Files', () => { - beforeEach(async () => { - await page.clickPersonalFilesAndWait(); - }); - - it('[C280032] Hyperlink appears when mouse over a file/folder', async () => { - expect(await dataTable.hasLinkOnName(file1)).toBe(true, 'Link on name is missing'); - }); - - it('[C280033] File preview opens when clicking the hyperlink', async () => { - await dataTable.clickNameLink(file1); - - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - - await Utils.pressEscape(); - }); - - it('[C280034] Navigate inside the folder when clicking the hyperlink', async () => { - await dataTable.clickNameLink(folder1); - - expect(await breadcrumb.currentItem.getText()).toBe(folder1); - }); - }); - - describe('on File Libraries', () => { - beforeEach(async () => { - await page.goToMyLibrariesAndWait(); - }); - - it('[C284901] Hyperlink appears when mouse over a library', async () => { - expect(await dataTable.hasLinkOnName(siteName)).toBe(true, 'Link on site name is missing'); - }); - - it('[C284902] Navigate inside the library when clicking the hyperlink', async () => { - await dataTable.clickNameLink(siteName); - - expect(await breadcrumb.currentItem.getText()).toBe(siteName); - expect(await dataTable.isItemPresent(fileSite)).toBe(true, `${fileSite} not displayed`); - }); - }); - - describe('on Shared Files', () => { - beforeAll(async () => { - await userActions.login(username, username); - await userActions.shareNodes([file1Id]); - await apis.user.shared.waitForFilesToBeShared([file1Id]); - }); - - beforeEach(async () => { - await page.clickSharedFilesAndWait(); - }); - - it('[C284905] Hyperlink appears when mouse over a file', async () => { - expect(await dataTable.hasLinkOnName(file1)).toBe(true, 'Link on name is missing'); - }); - - it('[C284906] File preview opens when clicking the hyperlink', async () => { - await dataTable.clickNameLink(file1); - - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - - await Utils.pressEscape(); - }); - }); - - describe('on Recent Files', () => { - beforeEach(async () => { - await page.clickRecentFilesAndWait(); - }); - - it('[C284907] Hyperlink appears when mouse over a file', async () => { - expect(await dataTable.hasLinkOnName(file1)).toBe(true, 'Link on name is missing'); - }); - - it('[C284908] File preview opens when clicking the hyperlink', async () => { - await dataTable.clickNameLink(file1); - - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - - await Utils.pressEscape(); - }); - }); - describe('on Favorites', () => { beforeAll(async () => { const initialFavoriteTotalItems = await apis.user.favorites.getFavoritesTotalItems(); 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 index 970cf984b..4723cfadc 100755 --- 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 @@ -23,11 +23,12 @@ */ import { BaseComponent } from '.././base.component'; -import { Page } from '@playwright/test'; +import { Locator, Page } from '@playwright/test'; export class Breadcrumb extends BaseComponent { private static rootElement = 'adf-breadcrumb'; public items = this.getChild('.adf-breadcrumb-item'); public currentItem = this.getChild('.adf-breadcrumb-item-current'); + getItemByTitle = (name: string): Locator => this.getChild(`.adf-breadcrumb-item[title=${name}]`); constructor(page: Page) { super(page, Breadcrumb.rootElement); 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 f32c908c8..eb66e8969 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 @@ -113,6 +113,8 @@ export class DataTableComponent extends BaseComponent { getColumnHeaderByTitleLocator = (headerTitle: string): Locator => this.getChild('[role="columnheader"]', { hasText: headerTitle }); + getSearchResultLinkByName = (name: string): Locator => this.getChild('.aca-search-results-row span[role="link"]', { hasText: name }); + async sortBy(columnTitle: string, order: 'Ascending' | 'Descending'): Promise { const columnHeaderLocator = this.getColumnHeaderByTitleLocator(columnTitle); await this.spinnerWaitForReload(); 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 5812c570d..567c0403f 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/index.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/index.ts @@ -36,3 +36,4 @@ export * from './viewer.component'; export * from './search/search-input.component'; export * from './search/search-overlay.components'; export * from './breadcrumb/breadcrumb.component'; +export * from './sidenav.component'; diff --git a/projects/aca-playwright-shared/src/page-objects/components/search/search-input.component.ts b/projects/aca-playwright-shared/src/page-objects/components/search/search-input.component.ts index 1f0d182ca..c575f423a 100644 --- a/projects/aca-playwright-shared/src/page-objects/components/search/search-input.component.ts +++ b/projects/aca-playwright-shared/src/page-objects/components/search/search-input.component.ts @@ -29,6 +29,7 @@ import { timeouts } from '../../../utils'; export class SearchInputComponent extends BaseComponent { private static rootElement = 'aca-page-layout'; public searchButton = this.getChild('aca-search-input .app-search-button'); + getIconByName = (name: string): Locator => this.getChild('.mat-icon', { hasText: name }); /** * Method used in cases where user have possibility to navigate "inside" the element (it's clickable and has link attribute). @@ -43,9 +44,8 @@ export class SearchInputComponent extends BaseComponent { } async performDoubleClickFolderOrFileToOpen(name: string): Promise { - await this.getCellLinkByName(name).waitFor({ state:'visible', timeout: timeouts.normal }); + await this.getCellLinkByName(name).waitFor({ state: 'visible', timeout: timeouts.normal }); await this.getCellLinkByName(name).dblclick(); await this.spinnerWaitForReload(); } - } diff --git a/projects/aca-playwright-shared/src/page-objects/components/sidenav.component.ts b/projects/aca-playwright-shared/src/page-objects/components/sidenav.component.ts new file mode 100644 index 000000000..1886414ae --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/components/sidenav.component.ts @@ -0,0 +1,97 @@ +/*! + * 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 { SIDEBAR_LABELS } from '../../utils'; +import { BaseComponent } from './base.component'; +import { Locator, Page } from '@playwright/test'; + +export class SidenavComponent extends BaseComponent { + private static rootElement = 'app-sidenav'; + + private personalFiles = this.getChild(`[data-automation-id='app.navbar.personalFiles']`); + private fileLibraries = this.getChild(`[data-automation-id='app.navbar.libraries.menu']`); + private myLibraries = this.getChild(`[data-automation-id='app.navbar.libraries.files']`); + private favoriteLibraries = this.getChild(`[data-automation-id='app.navbar.libraries.favorite']`); + private shared = this.getChild(`[data-automation-id='app.navbar.shared']`); + private recentFiles = this.getChild(`[data-automation-id='app.navbar.recentFiles']`); + private favorites = this.getChild(`[data-automation-id='app.navbar.favorites']`); + private trash = this.getChild(`[data-automation-id='app.navbar.trashcan']`); + private sidenavToggle = this.getChild(`.sidenav-header-title-logo`); + private sidenavExpand = this.page.getByTitle('Expand navigation menu'); + public expandedSidenav = this.page.locator(`[data-automation-id='expanded']`); + + constructor(page: Page) { + super(page, SidenavComponent.rootElement); + } + + async isActive(name: string): Promise { + const cssClass = await this.getLinkLabel(name).getAttribute('class'); + return cssClass.includes('action-button--active'); + } + + async openPanel(name: string): Promise { + await this.getLinkLabel(name).click(); + } + + private getLinkLabel(name: string): Locator { + switch (name) { + case SIDEBAR_LABELS.PERSONAL_FILES: + return this.personalFiles; + case SIDEBAR_LABELS.MY_LIBRARIES: + return this.myLibraries; + case SIDEBAR_LABELS.FAVORITE_LIBRARIES: + return this.favoriteLibraries; + case SIDEBAR_LABELS.SHARED_FILES: + return this.shared; + case SIDEBAR_LABELS.RECENT_FILES: + return this.recentFiles; + case SIDEBAR_LABELS.FAVORITES: + return this.favorites; + case SIDEBAR_LABELS.TRASH: + return this.trash; + default: + return this.personalFiles; + } + } + + async isSidenavExpanded(): Promise { + return this.expandedSidenav.isVisible(); + } + + async expandSideNav(): Promise { + const expanded = await this.isSidenavExpanded(); + if (!expanded) { + await this.sidenavExpand.click(); + await this.expandedSidenav.waitFor({ state: 'attached' }); + } + } + + async collapseSideNav(): Promise { + const expanded = await this.isSidenavExpanded(); + if (expanded) { + await this.sidenavToggle.click(); + await this.expandedSidenav.waitFor({ state: 'detached' }); + } + } +} diff --git a/projects/aca-playwright-shared/src/page-objects/pages/favorites-libraries.page.ts b/projects/aca-playwright-shared/src/page-objects/pages/favorites-libraries.page.ts new file mode 100644 index 000000000..c6d57bb9e --- /dev/null +++ b/projects/aca-playwright-shared/src/page-objects/pages/favorites-libraries.page.ts @@ -0,0 +1,45 @@ +/*! + * 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 { DataTableComponent, MatMenuComponent, SidenavComponent, ViewerComponent } from '../components'; +import { AcaHeader } from '../components/aca-header.component'; +import { AdfFolderDialogComponent, ViewerOverlayDialogComponent } from '../components/dialogs'; + +export class FavoritesLibrariesPage extends BasePage { + private static pageUrl = 'favorite/libraries'; + + constructor(page: Page) { + super(page, FavoritesLibrariesPage.pageUrl); + } + + public acaHeader = new AcaHeader(this.page); + public matMenu = new MatMenuComponent(this.page); + public folderDialog = new AdfFolderDialogComponent(this.page); + public dataTable = new DataTableComponent(this.page); + public viewer = new ViewerComponent(this.page); + public viewerDialog = new ViewerOverlayDialogComponent(this.page); + public sidenav = new SidenavComponent(this.page); +} diff --git a/projects/aca-playwright-shared/src/page-objects/pages/favorites.page.ts b/projects/aca-playwright-shared/src/page-objects/pages/favorites.page.ts index 179aeed99..7b1ef705d 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/favorites.page.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/favorites.page.ts @@ -24,7 +24,7 @@ import { Page } from '@playwright/test'; import { BasePage } from './base.page'; -import { DataTableComponent, MatMenuComponent, ViewerComponent } from '../components'; +import { DataTableComponent, MatMenuComponent, ViewerComponent, SidenavComponent } from '../components'; import { AcaHeader } from '../components/aca-header.component'; import { AdfFolderDialogComponent, ViewerOverlayDialogComponent } from '../components/dialogs'; @@ -41,4 +41,5 @@ export class FavoritesPage extends BasePage { public dataTable = new DataTableComponent(this.page); public viewer = new ViewerComponent(this.page); public viewerDialog = new ViewerOverlayDialogComponent(this.page); + public sidenav = new SidenavComponent(this.page); } 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 fcee9ac8e..d0cb86604 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/index.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/index.ts @@ -32,3 +32,4 @@ export * from './shared.page'; export * from './search.page'; export * from './favorites.page'; export * from './trash.page'; +export * from './favorites-libraries.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 index 747a8250e..b05148208 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 @@ -33,7 +33,8 @@ import { ViewerComponent, ViewerOverlayDialogComponent, ContentNodeSelectorDialog, - Breadcrumb + Breadcrumb, + SidenavComponent } from '../components'; export class MyLibrariesPage extends BasePage { @@ -51,6 +52,7 @@ export class MyLibrariesPage extends BasePage { public viewerDialog = new ViewerOverlayDialogComponent(this.page); public copyMoveDialog = new ContentNodeSelectorDialog(this.page); public breadcrumb = new Breadcrumb(this.page); + public sidenav = new SidenavComponent(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 46e3bb798..9bae8882b 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 @@ -24,7 +24,7 @@ import { Page } from '@playwright/test'; import { BasePage } from './base.page'; -import { Breadcrumb, DataTableComponent, MatMenuComponent, ViewerComponent } from '../components'; +import { Breadcrumb, DataTableComponent, MatMenuComponent, ViewerComponent, SidenavComponent } from '../components'; import { AcaHeader } from '../components/aca-header.component'; import { AdfFolderDialogComponent, PasswordOverlayDialogComponent, ViewerOverlayDialogComponent } from '../components/dialogs'; @@ -43,6 +43,7 @@ export class PersonalFilesPage extends BasePage { public passwordDialog = new PasswordOverlayDialogComponent(this.page); public viewerDialog = new ViewerOverlayDialogComponent(this.page); public breadcrumb = new Breadcrumb(this.page); + public sidenav = new SidenavComponent(this.page); async selectCreateFolder(): Promise { await this.acaHeader.createButton.click(); diff --git a/projects/aca-playwright-shared/src/page-objects/pages/recent-files.page.ts b/projects/aca-playwright-shared/src/page-objects/pages/recent-files.page.ts index e971c8921..2fedf41f6 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/recent-files.page.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/recent-files.page.ts @@ -22,10 +22,9 @@ * from Hyland Software. If not, see . */ - import { Page } from '@playwright/test'; import { BasePage } from './base.page'; -import { DataTableComponent, MatMenuComponent, ViewerComponent } from '../components'; +import { DataTableComponent, MatMenuComponent, ViewerComponent, SidenavComponent } from '../components'; import { AcaHeader } from '../components/aca-header.component'; import { AdfFolderDialogComponent } from '../components/dialogs'; @@ -41,4 +40,5 @@ export class RecentFilesPage extends BasePage { public folderDialog = new AdfFolderDialogComponent(this.page); public dataTable = new DataTableComponent(this.page); public viewer = new ViewerComponent(this.page); + public sidenav = new SidenavComponent(this.page); } 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 b195a5b77..1e72c1fcf 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 @@ -24,7 +24,7 @@ import { Page } from '@playwright/test'; import { BasePage } from './base.page'; -import { DataTableComponent, MatMenuComponent, ViewerComponent, SearchInputComponent, SearchOverlayComponent } from '../components'; +import { DataTableComponent, MatMenuComponent, ViewerComponent, SearchInputComponent, SearchOverlayComponent, SidenavComponent } from '../components'; import { AcaHeader } from '../components/aca-header.component'; import { AdfFolderDialogComponent } from '../components/dialogs'; @@ -42,4 +42,5 @@ export class SearchPage extends BasePage { public viewer = new ViewerComponent(this.page); public searchInput = new SearchInputComponent(this.page); public searchOverlay = new SearchOverlayComponent(this.page); + public sidenav = new SidenavComponent(this.page); } diff --git a/projects/aca-playwright-shared/src/page-objects/pages/shared.page.ts b/projects/aca-playwright-shared/src/page-objects/pages/shared.page.ts index 891f3336b..88372b5e9 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/shared.page.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/shared.page.ts @@ -24,7 +24,7 @@ import { Page } from '@playwright/test'; import { BasePage } from './base.page'; -import { DataTableComponent, MatMenuComponent, ViewerComponent } from '../components'; +import { DataTableComponent, MatMenuComponent, ViewerComponent, SidenavComponent } from '../components'; import { AcaHeader } from '../components/aca-header.component'; import { AdfFolderDialogComponent, ViewerOverlayDialogComponent } from '../components/dialogs'; @@ -41,4 +41,5 @@ export class SharedPage extends BasePage { public dataTable = new DataTableComponent(this.page); public viewer = new ViewerComponent(this.page); public viewerDialog = new ViewerOverlayDialogComponent(this.page); + public sidenav = new SidenavComponent(this.page); } diff --git a/projects/aca-playwright-shared/src/page-objects/pages/trash.page.ts b/projects/aca-playwright-shared/src/page-objects/pages/trash.page.ts index 5927404c4..b6a512a8d 100644 --- a/projects/aca-playwright-shared/src/page-objects/pages/trash.page.ts +++ b/projects/aca-playwright-shared/src/page-objects/pages/trash.page.ts @@ -24,7 +24,7 @@ import { Page } from '@playwright/test'; import { BasePage } from './base.page'; -import { DataTableComponent, MatMenuComponent, ViewerComponent } from '../components'; +import { DataTableComponent, MatMenuComponent, ViewerComponent, SidenavComponent } from '../components'; import { AcaHeader } from '../components/aca-header.component'; import { AdfFolderDialogComponent, ViewerOverlayDialogComponent } from '../components/dialogs'; @@ -41,4 +41,5 @@ export class TrashPage extends BasePage { public dataTable = new DataTableComponent(this.page); public viewer = new ViewerComponent(this.page); public viewerDialog = new ViewerOverlayDialogComponent(this.page); + public sidenav = new SidenavComponent(this.page); } diff --git a/projects/aca-playwright-shared/src/utils/config.ts b/projects/aca-playwright-shared/src/utils/config.ts new file mode 100644 index 000000000..f85982bae --- /dev/null +++ b/projects/aca-playwright-shared/src/utils/config.ts @@ -0,0 +1,45 @@ +/*! + * 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 + * along with Alfresco. If not, see . + */ + +export const APP_ROUTES = { + FAVORITES: '/favorites', + MY_LIBRARIES: '/libraries', + FAVORITE_LIBRARIES: '/favorite/libraries', + LOGIN: '/login', + LOGOUT: '/logout', + PERSONAL_FILES: '/personal-files', + RECENT_FILES: '/recent-files', + SHARED_FILES: '/shared', + TRASHCAN: '/trashcan' +}; + +export const SIDEBAR_LABELS = { + PERSONAL_FILES: 'Personal Files', + MY_LIBRARIES: 'My Libraries', + FAVORITE_LIBRARIES: 'Favorite Libraries', + SHARED_FILES: 'Shared', + RECENT_FILES: 'Recent Files', + FAVORITES: 'Favorites', + TRASH: 'Trash' +}; diff --git a/projects/aca-playwright-shared/src/utils/index.ts b/projects/aca-playwright-shared/src/utils/index.ts index d6ac3086e..0178ddfe6 100644 --- a/projects/aca-playwright-shared/src/utils/index.ts +++ b/projects/aca-playwright-shared/src/utils/index.ts @@ -29,3 +29,4 @@ export * from './state-helper'; export * from './folder-errors'; export * from './utils'; export * from './library-errors'; +export * from './config';