From fe52b0f468607b767804dddef0c39bcf249abc35 Mon Sep 17 00:00:00 2001
From: Adina Parpalita <adina.parpalita@ness.com>
Date: Mon, 10 Feb 2020 14:14:21 +0200
Subject: [PATCH] [ACA-2840] automate tests for the destination picker (#1332)

* automate tests for the destination picker

* fix spellcheck
---
 e2e/components/data-table/data-table.ts       |   1 -
 .../dialog/content-node-selector-dialog.ts    | 157 +++++++++
 e2e/components/dialog/copy-move-dialog.ts     | 126 -------
 .../actions/{ => copy-move}/copy.test.ts      |  18 +-
 .../destination-picker-dialog.test.ts         | 332 ++++++++++++++++++
 .../actions/{ => copy-move}/move.test.ts      |  26 +-
 e2e/suites/viewer/viewer-actions.test.ts      |   4 +-
 protractor.conf.js                            |   2 +-
 8 files changed, 514 insertions(+), 152 deletions(-)
 create mode 100755 e2e/components/dialog/content-node-selector-dialog.ts
 delete mode 100755 e2e/components/dialog/copy-move-dialog.ts
 rename e2e/suites/actions/{ => copy-move}/copy.test.ts (98%)
 create mode 100755 e2e/suites/actions/copy-move/destination-picker-dialog.test.ts
 rename e2e/suites/actions/{ => copy-move}/move.test.ts (97%)

diff --git a/e2e/components/data-table/data-table.ts b/e2e/components/data-table/data-table.ts
index 57ea8cf7a..d383f075d 100755
--- a/e2e/components/data-table/data-table.ts
+++ b/e2e/components/data-table/data-table.ts
@@ -72,7 +72,6 @@ export class DataTable extends Component {
   emptyFolderDragAndDrop: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyFolderDragAndDrop));
   emptyListTitle: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyListTitle));
   emptyListSubtitle: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyListSubtitle));
-  emptyListContainerText: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyListContainer));
 
   emptySearchText: ElementFinder = this.component.element(by.css(DataTable.selectors.emptySearchText));
 
diff --git a/e2e/components/dialog/content-node-selector-dialog.ts b/e2e/components/dialog/content-node-selector-dialog.ts
new file mode 100755
index 000000000..0bac88b04
--- /dev/null
+++ b/e2e/components/dialog/content-node-selector-dialog.ts
@@ -0,0 +1,157 @@
+/*!
+ * @license
+ * Alfresco Example Content Application
+ *
+ * Copyright (C) 2005 - 2020 Alfresco Software Limited
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+import { ElementFinder, by, browser, ExpectedConditions as EC, protractor } from 'protractor';
+import { BROWSER_WAIT_TIMEOUT } from '../../configs';
+import { Component } from '../component';
+import { Utils } from '../../utilities/utils';
+import { DropDownBreadcrumb } from '../breadcrumb/dropdown-breadcrumb';
+import { DataTable } from '../data-table/data-table';
+
+export class ContentNodeSelectorDialog extends Component {
+  private static selectors = {
+    root: '.adf-content-node-selector-dialog',
+
+    title: '.mat-dialog-title',
+    locationDropDown: 'site-dropdown-container',
+    locationOption: '.mat-option .mat-option-text',
+
+    dataTable: '.adf-datatable-body',
+    selectedRow: '.adf-is-selected',
+
+    button: '.mat-dialog-actions button',
+    chooseAction: '.adf-choose-action',
+
+    searchInput: '#searchInput',
+    toolbarTitle: '.adf-toolbar-title'
+  };
+
+  title: ElementFinder = this.component.element(by.css(ContentNodeSelectorDialog.selectors.title));
+  locationDropDown: ElementFinder = this.component.element(by.id(ContentNodeSelectorDialog.selectors.locationDropDown));
+  locationPersonalFiles: ElementFinder = browser.element(by.cssContainingText(ContentNodeSelectorDialog.selectors.locationOption, 'Personal Files'));
+  locationFileLibraries: ElementFinder = browser.element(by.cssContainingText(ContentNodeSelectorDialog.selectors.locationOption, 'File Libraries'));
+
+  cancelButton: ElementFinder = this.component.element(by.cssContainingText(ContentNodeSelectorDialog.selectors.button, 'Cancel'));
+  copyButton: ElementFinder = this.component.element(by.css(ContentNodeSelectorDialog.selectors.chooseAction));
+  moveButton: ElementFinder = this.component.element(by.cssContainingText(ContentNodeSelectorDialog.selectors.button, 'Move'));
+
+  searchInput: ElementFinder = this.component.element(by.css(ContentNodeSelectorDialog.selectors.searchInput));
+  toolbarTitle: ElementFinder = this.component.element(by.css(ContentNodeSelectorDialog.selectors.toolbarTitle));
+
+  breadcrumb: DropDownBreadcrumb = new DropDownBreadcrumb();
+  dataTable: DataTable = new DataTable(ContentNodeSelectorDialog.selectors.root);
+
+  constructor(ancestor?: string) {
+    super(ContentNodeSelectorDialog.selectors.root, ancestor);
+  }
+
+  async waitForDialogToOpen(): Promise<void> {
+    await browser.wait(EC.presenceOf(this.title), BROWSER_WAIT_TIMEOUT, 'timeout waiting for dialog title');
+    await browser.wait(EC.presenceOf(browser.element(by.css('.cdk-overlay-backdrop'))), BROWSER_WAIT_TIMEOUT, 'timeout waiting for overlay backdrop');
+  }
+
+  async waitForDialogToClose(): Promise<void> {
+    await browser.wait(EC.stalenessOf(this.title), BROWSER_WAIT_TIMEOUT);
+  }
+
+  async waitForDropDownToOpen(): Promise<void> {
+    await browser.wait(EC.presenceOf(this.locationPersonalFiles), BROWSER_WAIT_TIMEOUT);
+  }
+
+  async waitForDropDownToClose(): Promise<void> {
+    await browser.wait(EC.stalenessOf(browser.$(ContentNodeSelectorDialog.selectors.locationOption)), BROWSER_WAIT_TIMEOUT);
+  }
+
+  async waitForRowToBeSelected(): Promise<void> {
+    await browser.wait(EC.presenceOf(this.component.element(by.css(ContentNodeSelectorDialog.selectors.selectedRow))), BROWSER_WAIT_TIMEOUT);
+  }
+
+  async isDialogOpen(): Promise<boolean> {
+    return browser.$(ContentNodeSelectorDialog.selectors.root).isDisplayed();
+  }
+
+  async getTitle(): Promise<string> {
+    return this.title.getText();
+  }
+
+  async clickCancel(): Promise<void> {
+    await this.cancelButton.click();
+    await this.waitForDialogToClose();
+  }
+
+  async clickCopy(): Promise<void> {
+    await this.copyButton.click();
+  }
+
+  async clickMove(): Promise<void> {
+    await this.moveButton.click();
+  }
+
+  async selectLocation(location: 'Personal Files' | 'File Libraries'): Promise<void> {
+    await this.locationDropDown.click();
+    await this.waitForDropDownToOpen();
+
+    if (location === 'Personal Files') {
+      await this.locationPersonalFiles.click();
+    } else {
+      await this.locationFileLibraries.click();
+    }
+
+    await this.waitForDropDownToClose();
+  }
+
+  async selectDestination(folderName: string): Promise<void> {
+    const row = this.dataTable.getRowByName(folderName);
+    await Utils.waitUntilElementClickable(row);
+    await row.click();
+    await this.waitForRowToBeSelected();
+  }
+
+  async isSearchInputPresent(): Promise<boolean> {
+    return await this.searchInput.isPresent();
+  }
+
+  async isSelectLocationDropdownDisplayed(): Promise<boolean> {
+    return (await this.locationDropDown.isPresent()) && (await this.locationDropDown.isDisplayed());
+  }
+
+  async isCopyButtonEnabled(): Promise<boolean> {
+    return (await this.copyButton.isPresent()) && (await this.copyButton.isEnabled());
+  }
+
+  async isCancelButtonEnabled(): Promise<boolean> {
+    return (await this.cancelButton.isPresent()) && (await this.cancelButton.isEnabled());
+  }
+
+  async searchFor(text: string): Promise<void> {
+    await Utils.clearFieldWithBackspace(this.searchInput);
+    await this.searchInput.sendKeys(text);
+    await this.searchInput.sendKeys(protractor.Key.ENTER);
+  }
+
+  async getToolbarTitle(): Promise<string> {
+    return await this.toolbarTitle.getText();
+  }
+}
diff --git a/e2e/components/dialog/copy-move-dialog.ts b/e2e/components/dialog/copy-move-dialog.ts
deleted file mode 100755
index 7f54623ff..000000000
--- a/e2e/components/dialog/copy-move-dialog.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-/*!
- * @license
- * Alfresco Example Content Application
- *
- * Copyright (C) 2005 - 2020 Alfresco Software Limited
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-import { ElementFinder, by, browser, ExpectedConditions as EC } from 'protractor';
-import { BROWSER_WAIT_TIMEOUT } from '../../configs';
-import { Component } from '../component';
-import { Utils } from './../../utilities/utils';
-
-export class CopyMoveDialog extends Component {
-  private static selectors = {
-    root: '.adf-content-node-selector-dialog',
-
-    title: '.mat-dialog-title',
-    locationDropDown: 'site-dropdown-container',
-    locationOption: '.mat-option .mat-option-text',
-
-    dataTable: '.adf-datatable-body',
-    selectedRow: '.adf-is-selected',
-
-    button: '.mat-dialog-actions button'
-  };
-
-  title: ElementFinder = this.component.element(by.css(CopyMoveDialog.selectors.title));
-  dataTable: ElementFinder = this.component.element(by.css(CopyMoveDialog.selectors.dataTable));
-  locationDropDown: ElementFinder = this.component.element(by.id(CopyMoveDialog.selectors.locationDropDown));
-  locationPersonalFiles: ElementFinder = browser.element(by.cssContainingText(CopyMoveDialog.selectors.locationOption, 'Personal Files'));
-  locationFileLibraries: ElementFinder = browser.element(by.cssContainingText(CopyMoveDialog.selectors.locationOption, 'File Libraries'));
-
-  cancelButton: ElementFinder = this.component.element(by.cssContainingText(CopyMoveDialog.selectors.button, 'Cancel'));
-  copyButton: ElementFinder = this.component.element(by.cssContainingText(CopyMoveDialog.selectors.button, 'Copy'));
-  moveButton: ElementFinder = this.component.element(by.cssContainingText(CopyMoveDialog.selectors.button, 'Move'));
-
-  constructor(ancestor?: string) {
-    super(CopyMoveDialog.selectors.root, ancestor);
-  }
-
-  async waitForDialogToClose() {
-    await browser.wait(EC.stalenessOf(this.title), BROWSER_WAIT_TIMEOUT);
-  }
-
-  async waitForDropDownToOpen() {
-    await browser.wait(EC.presenceOf(this.locationPersonalFiles), BROWSER_WAIT_TIMEOUT);
-  }
-
-  async waitForDropDownToClose() {
-    await browser.wait(EC.stalenessOf(browser.$(CopyMoveDialog.selectors.locationOption)), BROWSER_WAIT_TIMEOUT);
-  }
-
-  async waitForRowToBeSelected() {
-    await browser.wait(EC.presenceOf(this.component.element(by.css(CopyMoveDialog.selectors.selectedRow))), BROWSER_WAIT_TIMEOUT);
-  }
-
-  async isDialogOpen() {
-    return browser.$(CopyMoveDialog.selectors.root).isDisplayed();
-  }
-
-  async getTitle() {
-    return this.title.getText();
-  }
-
-  async clickCancel() {
-    await this.cancelButton.click();
-    await this.waitForDialogToClose();
-  }
-
-  async clickCopy() {
-    await this.copyButton.click();
-  }
-
-  async clickMove() {
-    await this.moveButton.click();
-  }
-
-  getRow(folderName: string) {
-    return this.dataTable.element(by.cssContainingText('.adf-name-location-cell', folderName));
-  }
-
-  async doubleClickOnRow(name: string) {
-    const item = this.getRow(name);
-    await Utils.waitUntilElementClickable(item);
-    await browser.actions().mouseMove(item).perform();
-    await browser.actions().click().click().perform();
-  }
-
-  async selectLocation(location: 'Personal Files' | 'File Libraries') {
-    await this.locationDropDown.click();
-    await this.waitForDropDownToOpen();
-
-    if (location === 'Personal Files') {
-      await this.locationPersonalFiles.click();
-    } else {
-      await this.locationFileLibraries.click();
-    }
-
-    await this.waitForDropDownToClose();
-  }
-
-  async selectDestination(folderName: string) {
-    const row = this.getRow(folderName);
-    await Utils.waitUntilElementClickable(row);
-    await row.click();
-    await this.waitForRowToBeSelected();
-  }
-}
diff --git a/e2e/suites/actions/copy.test.ts b/e2e/suites/actions/copy-move/copy.test.ts
similarity index 98%
rename from e2e/suites/actions/copy.test.ts
rename to e2e/suites/actions/copy-move/copy.test.ts
index 662c06560..ac421b607 100755
--- a/e2e/suites/actions/copy.test.ts
+++ b/e2e/suites/actions/copy-move/copy.test.ts
@@ -23,10 +23,10 @@
  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
  */
 
-import { LoginPage, BrowsingPage } from '../../pages/pages';
-import { CopyMoveDialog } from './../../components/dialog/copy-move-dialog';
-import { RepoClient } from '../../utilities/repo-client/repo-client';
-import { Utils } from '../../utilities/utils';
+import { LoginPage, BrowsingPage } from '../../../pages/pages';
+import { ContentNodeSelectorDialog } from '../../../components/dialog/content-node-selector-dialog';
+import { RepoClient } from '../../../utilities/repo-client/repo-client';
+import { Utils } from '../../../utilities/utils';
 
 describe('Copy content', () => {
   const username = `user-${Utils.random()}`;
@@ -86,7 +86,7 @@ describe('Copy content', () => {
   const loginPage = new LoginPage();
   const page = new BrowsingPage();
   const { dataTable, toolbar } = page;
-  const copyDialog = new CopyMoveDialog();
+  const copyDialog = new ContentNodeSelectorDialog();
   const { searchInput } = page.header;
 
   beforeAll(async (done) => {
@@ -539,8 +539,8 @@ describe('Copy content', () => {
     await dataTable.selectMultipleItems(items, location);
     await toolbar.clickMoreActionsCopy();
     await copyDialog.selectLocation('File Libraries');
-    await copyDialog.doubleClickOnRow(siteName);
-    await copyDialog.doubleClickOnRow('documentLibrary');
+    await copyDialog.dataTable.doubleClickOnRowByName(siteName);
+    await copyDialog.dataTable.doubleClickOnRowByName('documentLibrary');
     await copyDialog.selectDestination(destination);
     await copyDialog.clickCopy();
     const msg = await page.getSnackBarMessage();
@@ -665,7 +665,7 @@ describe('Copy content', () => {
     await dataTable.selectItem(fileName, location);
     await toolbar.clickMoreActionsCopy();
     await copyDialog.selectLocation('Personal Files');
-    await copyDialog.doubleClickOnRow(source);
+    await copyDialog.dataTable.doubleClickOnRowByName(source);
     await copyDialog.selectDestination(destination);
     await copyDialog.clickCopy();
     const msg = await page.getSnackBarMessage();
@@ -692,7 +692,7 @@ describe('Copy content', () => {
     await dataTable.selectItem(folderName, location);
     await toolbar.clickMoreActionsCopy();
     await copyDialog.selectLocation('Personal Files');
-    await copyDialog.doubleClickOnRow(destination);
+    await copyDialog.dataTable.doubleClickOnRowByName(destination);
     await copyDialog.clickCopy();
     const msg = await page.getSnackBarMessage();
     expect(msg).toContain('Copied 1 item');
diff --git a/e2e/suites/actions/copy-move/destination-picker-dialog.test.ts b/e2e/suites/actions/copy-move/destination-picker-dialog.test.ts
new file mode 100755
index 000000000..02c0e372e
--- /dev/null
+++ b/e2e/suites/actions/copy-move/destination-picker-dialog.test.ts
@@ -0,0 +1,332 @@
+/*!
+ * @license
+ * Alfresco Example Content Application
+ *
+ * Copyright (C) 2005 - 2020 Alfresco Software Limited
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+import { LoginPage, BrowsingPage } from '../../../pages/pages';
+import { ContentNodeSelectorDialog } from '../../../components/dialog/content-node-selector-dialog';
+import { RepoClient } from '../../../utilities/repo-client/repo-client';
+import { Utils } from '../../../utilities/utils';
+import { AdminActions } from '../../../utilities/admin-actions';
+
+describe('Destination picker dialog : ', () => {
+  const random = Utils.random();
+
+  const username = `user-${random}`;
+
+  const consumer = `consumer-${random}`;
+  const contributor = `contributor-${random}`;
+  const collaborator = `collaborator-${random}`;
+
+  const file = `file-${random}.txt`;
+  let fileId: string;
+  let fileIdConsumer: string;
+  let fileIdContributor: string;
+  let fileIdCollaborator: string;
+
+  const adminFolder = `admin-folder-${random}`;
+  let adminFolderId: string;
+
+  const destination = `destination-folder-${random}`;
+  let destinationId: string;
+  const fileInDestination = `file-in-dest-${random}.txt`;
+  const folderInDestination = `folder-in-dest-${random}`;
+  const folder2InDestination = `folder2-in-dest-${random}`;
+  let folderLink: string;
+
+  const searchFolder = `search-${random}`;
+  let searchFolderId: string;
+  let searchFolderSiteId: string;
+  const searchSubFolder1 = `sub-folder-${random}`;
+  let searchSubFolder1Id: string;
+  let searchSubFolder1SiteId: string;
+  const searchSubFolder2 = `sub-folder-${random}`;
+
+  const site = `site-${random}`;
+
+  const userApi = new RepoClient(username, username);
+  const consumerApi = new RepoClient(consumer, consumer);
+  const contributorApi = new RepoClient(contributor, contributor);
+  const collaboratorApi = new RepoClient(collaborator, collaborator);
+  const adminApiActions = new AdminActions();
+
+  const loginPage = new LoginPage();
+  const page = new BrowsingPage();
+  const { dataTable, toolbar } = page;
+  const contentNodeSelector = new ContentNodeSelectorDialog();
+
+  beforeAll(async () => {
+    await adminApiActions.createUser({ username });
+    await adminApiActions.createUser({ username: consumer });
+    await adminApiActions.createUser({ username: contributor });
+    await adminApiActions.createUser({ username: collaborator });
+
+    fileId = (await userApi.nodes.createFile(file)).entry.id;
+
+    destinationId = (await userApi.nodes.createFolder(destination)).entry.id;
+    await userApi.nodes.createFile(fileInDestination, destinationId);
+    await userApi.nodes.createFolder(folderInDestination, destinationId);
+    const folder2Id = (await userApi.nodes.createFolder(folder2InDestination, destinationId)).entry.id;
+    folderLink = (await userApi.nodes.createFolderLink(folder2Id, destinationId)).entry.name;
+    searchFolderId = (await userApi.nodes.createFolder(searchFolder, destinationId)).entry.id;
+    searchSubFolder1Id = (await userApi.nodes.createFolder(searchSubFolder1, searchFolderId)).entry.id;
+    await userApi.nodes.createFolder(searchSubFolder2, searchSubFolder1Id);
+
+    await userApi.sites.createSitePrivate(site);
+    const docLibId = await userApi.sites.getDocLibId(site);
+    searchFolderSiteId = (await userApi.nodes.createFolder(searchFolder, docLibId)).entry.id;
+    searchSubFolder1SiteId = (await userApi.nodes.createFolder(searchSubFolder1, searchFolderSiteId)).entry.id;
+    await userApi.nodes.createFolder(searchSubFolder2, searchSubFolder1SiteId);
+
+    await userApi.sites.addSiteConsumer(site, consumer);
+    await userApi.sites.addSiteContributor(site, contributor);
+    await userApi.sites.addSiteCollaborator(site, collaborator);
+
+    fileIdConsumer = (await consumerApi.nodes.createFile(file)).entry.id;
+    fileIdContributor = (await contributorApi.nodes.createFile(file)).entry.id;
+    fileIdCollaborator = (await collaboratorApi.nodes.createFile(file)).entry.id;
+
+    adminFolderId = (await adminApiActions.nodes.createFolder(adminFolder)).entry.id;
+
+    await userApi.search.waitForNodes(searchFolder, { expect: 2 });
+  });
+
+  afterAll(async () => {
+    await userApi.nodes.deleteNodeById(fileId);
+    await userApi.nodes.deleteNodeById(destinationId);
+    await userApi.sites.deleteSite(site);
+
+    await consumerApi.nodes.deleteNodeById(fileIdConsumer);
+    await contributorApi.nodes.deleteNodeById(fileIdContributor);
+    await collaboratorApi.nodes.deleteNodeById(fileIdCollaborator);
+
+    await adminApiActions.nodes.deleteNodeById(adminFolderId);
+  });
+
+  afterEach(async () => {
+    await page.closeOpenDialogs();
+  });
+
+  describe('general', () => {
+    beforeAll(async () => {
+      await loginPage.loginWith(username);
+    });
+
+    beforeEach(async () => {
+      await dataTable.selectItem(file);
+      await toolbar.clickMoreActionsCopy();
+      await contentNodeSelector.waitForDialogToOpen();
+    });
+
+    it('Dialog UI - [C263875]', async () => {
+      expect(await contentNodeSelector.getTitle()).toEqual(`Copy '${file}' to...`);
+      expect(await contentNodeSelector.isSearchInputPresent()).toBe(true, 'Search input is not displayed');
+      expect(await contentNodeSelector.isSelectLocationDropdownDisplayed()).toBe(true, 'Select Location dropdown not displayed');
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual('Personal Files');
+      expect(await contentNodeSelector.dataTable.isItemPresent(destination)).toBe(true, 'Personal Files content not displayed');
+      expect(await contentNodeSelector.isCopyButtonEnabled()).toBe(true, 'Copy button is not disabled');
+      expect(await contentNodeSelector.isCancelButtonEnabled()).toBe(true, 'Cancel button is not enabled');
+    });
+
+    it('Files are not displayed - [C263880]', async () => {
+      await contentNodeSelector.selectLocation('Personal Files');
+      expect(await contentNodeSelector.dataTable.isItemPresent(destination)).toBe(true, 'destination folder not displayed');
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(destination);
+      expect(await contentNodeSelector.dataTable.isItemPresent(folderInDestination)).toBe(true, 'folder is not displayed');
+      expect(await contentNodeSelector.dataTable.isItemPresent(fileInDestination)).toBe(false, 'file is displayed');
+    });
+
+    it('Folder links are not displayed - [C263881]', async() => {
+      await contentNodeSelector.selectLocation('Personal Files');
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(destination);
+
+      expect(await contentNodeSelector.dataTable.isItemPresent(folderInDestination)).toBe(true, `${folderInDestination} is not displayed`);
+      expect(await contentNodeSelector.dataTable.isItemPresent(folder2InDestination)).toBe(true, `${folder2InDestination} is not displayed`);
+      expect(await contentNodeSelector.dataTable.isItemPresent(folderLink)).toBe(false, 'Link to folder is displayed');
+    });
+
+    it('User can see his Libraries - [C263885]', async () => {
+      await contentNodeSelector.selectLocation('File Libraries');
+      expect(await contentNodeSelector.dataTable.isItemPresent(site)).toBe(true, 'user site is not displayed');
+    });
+
+    it('Search - No results displayed - [C263889]', async () => {
+      await contentNodeSelector.searchFor('nonexistent-folder');
+      expect(await contentNodeSelector.dataTable.isEmpty()).toBe(true, 'datatable not empty');
+      expect(await contentNodeSelector.dataTable.getEmptyListText()).toEqual('No results found');
+    });
+
+    it('Search - results found - [C263888]', async () => {
+      await contentNodeSelector.searchFor(searchFolder);
+      expect(await contentNodeSelector.dataTable.isItemPresent(searchFolder, username)).toBe(true, 'folder from Personal Files not displayed');
+      expect(await contentNodeSelector.dataTable.isItemPresent(searchFolder, site)).toBe(true, 'folder from site not displayed');
+    });
+  });
+
+  describe('multiple selection', () => {
+    beforeAll(async () => {
+      await loginPage.loginWith(username);
+    });
+
+    beforeEach(async () => {
+      await dataTable.selectMultipleItems([file, destination]);
+      await toolbar.clickMoreActionsCopy();
+      await contentNodeSelector.waitForDialogToOpen();
+    });
+
+    it('Dialog title - multiple selection - [C263879]', async () => {
+      expect(await contentNodeSelector.getTitle()).toEqual(`Copy 2 items to...`);
+    });
+  });
+
+  describe('breadcrumb', () => {
+    beforeAll(async () => {
+      await loginPage.loginWith(username);
+    });
+
+    beforeEach(async () => {
+      await dataTable.selectItem(file);
+      await toolbar.clickMoreActionsCopy();
+      await contentNodeSelector.waitForDialogToOpen();
+    });
+
+    it('Personal Files breadcrumb - main node - [C263890]', async () => {
+      await contentNodeSelector.selectLocation('Personal Files');
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual('Personal Files');
+    });
+
+    it('File Libraries breadcrumb - main node - [C263891]', async () => {
+      await contentNodeSelector.selectLocation('File Libraries');
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual('File Libraries');
+    });
+
+    it('Search results breadcrumb - [C263899]', async () => {
+      await contentNodeSelector.searchFor(searchFolder);
+      expect(await contentNodeSelector.getToolbarTitle()).toEqual('Search results');
+    });
+
+    it('Search results breadcrumb when selecting a folder - [C263900]', async () => {
+      await contentNodeSelector.searchFor(searchFolder);
+      await contentNodeSelector.dataTable.selectItem(searchFolder, site);
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual(searchFolder);
+    });
+
+    it('Personal Files breadcrumb - folder structure - [C263897]', async () => {
+      await contentNodeSelector.selectLocation('Personal Files');
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(destination);
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual(destination);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(searchFolder);
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual(searchFolder);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(searchSubFolder1);
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual(searchSubFolder1);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(searchSubFolder2);
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual(searchSubFolder2);
+      await contentNodeSelector.breadcrumb.openPath();
+      expect(await contentNodeSelector.breadcrumb.getPathItems()).toEqual([searchSubFolder1, searchFolder, destination, 'Personal Files']);
+    });
+
+    it('File Libraries breadcrumb - folder structure - [C263898]', async () => {
+      await contentNodeSelector.selectLocation('File Libraries');
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(site);
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual(site);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName('documentLibrary');
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual(site);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(searchFolder);
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual(searchFolder);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(searchSubFolder1);
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual(searchSubFolder1);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(searchSubFolder2);
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual(searchSubFolder2);
+      await contentNodeSelector.breadcrumb.openPath();
+      expect(await contentNodeSelector.breadcrumb.getPathItems()).toEqual([searchSubFolder1, searchFolder, site, 'File Libraries']);
+    });
+
+    it('Select a node from the breadcrumb path - [C263895]', async () => {
+      await contentNodeSelector.selectLocation('Personal Files');
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(destination);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(searchFolder);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(searchSubFolder1);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(searchSubFolder2);
+      await contentNodeSelector.breadcrumb.openPath();
+
+      await contentNodeSelector.breadcrumb.clickPathItem(destination);
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual(destination);
+      expect(await contentNodeSelector.dataTable.isItemPresent(searchFolder)).toBe(true, 'folder not displayed');
+    });
+  });
+
+  describe('Users with different permissions', () => {
+
+    it('Consumer user cannot select the folder as destination - [C263876]', async () => {
+      await loginPage.loginWith(consumer);
+      await dataTable.selectItem(file);
+      await toolbar.clickMoreActionsCopy();
+      await contentNodeSelector.waitForDialogToOpen();
+
+      await contentNodeSelector.selectLocation('File Libraries');
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(site);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName('documentLibrary');
+      await contentNodeSelector.dataTable.selectItem(searchFolder);
+
+      expect(await contentNodeSelector.isCopyButtonEnabled()).toBe(false, 'Copy should be disabled');
+    });
+
+    it('Contributor user can select the folder as destination - [C263877]', async () => {
+      await loginPage.loginWith(contributor);
+      await dataTable.selectItem(file);
+      await toolbar.clickMoreActionsCopy();
+      await contentNodeSelector.waitForDialogToOpen();
+
+      await contentNodeSelector.selectLocation('File Libraries');
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(site);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName('documentLibrary');
+      await contentNodeSelector.dataTable.selectItem(searchFolder);
+
+      expect(await contentNodeSelector.isCopyButtonEnabled()).toBe(true, 'Copy should be disabled');
+    });
+
+    it('Collaborator user can select the folder as destination - [C263878]', async () => {
+      await loginPage.loginWith(collaborator);
+      await dataTable.selectItem(file);
+      await toolbar.clickMoreActionsCopy();
+      await contentNodeSelector.waitForDialogToOpen();
+
+      await contentNodeSelector.selectLocation('File Libraries');
+      await contentNodeSelector.dataTable.doubleClickOnRowByName(site);
+      await contentNodeSelector.dataTable.doubleClickOnRowByName('documentLibrary');
+      await contentNodeSelector.dataTable.selectItem(searchFolder);
+
+      expect(await contentNodeSelector.isCopyButtonEnabled()).toBe(true, 'Copy should be disabled');
+    });
+
+    it('Admin user - Personal Files breadcrumb main node - [C263892]', async () => {
+      await loginPage.loginWithAdmin();
+      await dataTable.selectItem(adminFolder);
+      await toolbar.clickMoreActionsCopy();
+      await contentNodeSelector.waitForDialogToOpen();
+
+      await contentNodeSelector.selectLocation('Personal Files');
+      expect(await contentNodeSelector.breadcrumb.getCurrentFolderName()).toEqual('Company Home');
+    });
+  });
+});
diff --git a/e2e/suites/actions/move.test.ts b/e2e/suites/actions/copy-move/move.test.ts
similarity index 97%
rename from e2e/suites/actions/move.test.ts
rename to e2e/suites/actions/copy-move/move.test.ts
index 721b3b76c..a6536e352 100755
--- a/e2e/suites/actions/move.test.ts
+++ b/e2e/suites/actions/copy-move/move.test.ts
@@ -23,10 +23,10 @@
  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
  */
 
-import { LoginPage, BrowsingPage } from '../../pages/pages';
-import { CopyMoveDialog } from './../../components/dialog/copy-move-dialog';
-import { RepoClient } from '../../utilities/repo-client/repo-client';
-import { Utils } from '../../utilities/utils';
+import { LoginPage, BrowsingPage } from '../../../pages/pages';
+import { ContentNodeSelectorDialog } from '../../../components/dialog/content-node-selector-dialog';
+import { RepoClient } from '../../../utilities/repo-client/repo-client';
+import { Utils } from '../../../utilities/utils';
 
 describe('Move content', () => {
   const username = `user-${Utils.random()}`;
@@ -57,7 +57,7 @@ describe('Move content', () => {
   const loginPage = new LoginPage();
   const page = new BrowsingPage();
   const { dataTable, toolbar } = page;
-  const moveDialog = new CopyMoveDialog();
+  const moveDialog = new ContentNodeSelectorDialog();
 
   beforeAll(async (done) => {
     await apis.admin.people.createUser({ username });
@@ -254,8 +254,8 @@ describe('Move content', () => {
       await dataTable.selectMultipleItems([file4, folder2]);
       await toolbar.clickMoreActionsMove();
       await moveDialog.selectLocation('File Libraries');
-      await moveDialog.doubleClickOnRow(siteName);
-      await moveDialog.doubleClickOnRow('documentLibrary');
+      await moveDialog.dataTable.doubleClickOnRowByName(siteName);
+      await moveDialog.dataTable.doubleClickOnRowByName('documentLibrary');
       await moveDialog.selectDestination(folderSitePF);
       await moveDialog.clickMove();
       const msg = await page.getSnackBarMessage();
@@ -374,8 +374,8 @@ describe('Move content', () => {
       await dataTable.selectItem(file4, sourceRF);
       await toolbar.clickMoreActionsMove();
       await moveDialog.selectLocation('File Libraries');
-      await moveDialog.doubleClickOnRow(siteName);
-      await moveDialog.doubleClickOnRow('documentLibrary');
+      await moveDialog.dataTable.doubleClickOnRowByName(siteName);
+      await moveDialog.dataTable.doubleClickOnRowByName('documentLibrary');
       await moveDialog.selectDestination(folderSiteRF);
       await moveDialog.clickMove();
       const msg = await page.getSnackBarMessage();
@@ -496,8 +496,8 @@ describe('Move content', () => {
       await dataTable.selectItem(file4, sourceSF);
       await toolbar.clickMoreActionsMove();
       await moveDialog.selectLocation('File Libraries');
-      await moveDialog.doubleClickOnRow(siteName);
-      await moveDialog.doubleClickOnRow('documentLibrary');
+      await moveDialog.dataTable.doubleClickOnRowByName(siteName);
+      await moveDialog.dataTable.doubleClickOnRowByName('documentLibrary');
       await moveDialog.selectDestination(folderSiteSF);
       await moveDialog.clickMove();
       const msg = await page.getSnackBarMessage();
@@ -686,8 +686,8 @@ describe('Move content', () => {
       await dataTable.selectMultipleItems([file4, folder2], sourceFav);
       await toolbar.clickMoreActionsMove();
       await moveDialog.selectLocation('File Libraries');
-      await moveDialog.doubleClickOnRow(siteName);
-      await moveDialog.doubleClickOnRow('documentLibrary');
+      await moveDialog.dataTable.doubleClickOnRowByName(siteName);
+      await moveDialog.dataTable.doubleClickOnRowByName('documentLibrary');
       await moveDialog.selectDestination(folderSiteFav);
       await moveDialog.clickMove();
       const msg = await page.getSnackBarMessage();
diff --git a/e2e/suites/viewer/viewer-actions.test.ts b/e2e/suites/viewer/viewer-actions.test.ts
index 52f7d9c22..0c9801403 100755
--- a/e2e/suites/viewer/viewer-actions.test.ts
+++ b/e2e/suites/viewer/viewer-actions.test.ts
@@ -28,7 +28,7 @@ import { FILES } from '../../configs';
 import { RepoClient } from '../../utilities/repo-client/repo-client';
 import { Utils } from '../../utilities/utils';
 import { Viewer } from '../../components/viewer/viewer';
-import { CopyMoveDialog } from './../../components/dialog/copy-move-dialog';
+import { ContentNodeSelectorDialog } from './../../components/dialog/content-node-selector-dialog';
 import { ShareDialog } from './../../components/dialog/share-dialog';
 import { ManageVersionsDialog } from './../../components/dialog/manage-versions-dialog';
 import { UploadNewVersionDialog } from './../../components/dialog/upload-new-version-dialog';
@@ -51,7 +51,7 @@ describe('Viewer actions', () => {
   const dataTable = page.dataTable;
   const viewer = new Viewer();
   const { toolbar } = viewer;
-  const copyMoveDialog = new CopyMoveDialog();
+  const copyMoveDialog = new ContentNodeSelectorDialog();
   const shareDialog = new ShareDialog();
   const manageVersionsDialog = new ManageVersionsDialog();
   const uploadNewVersionDialog = new UploadNewVersionDialog();
diff --git a/protractor.conf.js b/protractor.conf.js
index 4e74a0823..9a233b22e 100755
--- a/protractor.conf.js
+++ b/protractor.conf.js
@@ -52,7 +52,7 @@ exports.config = {
     './e2e/suites/pagination/*.test.ts',
     './e2e/suites/search/*.test.ts',
     './e2e/suites/actions-available/**/*.test.ts',
-    './e2e/suites/actions/*.test.ts',
+    './e2e/suites/actions/**/*.test.ts',
     './e2e/suites/viewer/*.test.ts',
     './e2e/suites/info-drawer/*.test.ts',
     './e2e/suites/extensions/*.test.ts'