diff --git a/e2e/content-services/lock_file.e2e.ts b/e2e/content-services/lock_file.e2e.ts new file mode 100644 index 0000000000..71cccf5701 --- /dev/null +++ b/e2e/content-services/lock_file.e2e.ts @@ -0,0 +1,361 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { LoginPage } from '../pages/adf/loginPage'; +import { NavigationBarPage } from '../pages/adf/NavigationBarPage'; +import ContentList = require('../pages/adf/dialog/contentList'); + +import { LockFilePage } from '../pages/adf/lockFilePage'; + +import AcsUserModel = require('../models/ACS/acsUserModel'); +import FileModel = require('../models/ACS/fileModel'); + +import CONSTANTS = require('../util/constants'); +import Util = require('../util/util'); + +import TestConfig = require('../test.config'); +import resources = require('../util/resources'); + +import AlfrescoApi = require('alfresco-js-api-node'); +import { UploadActions } from '../actions/ACS/upload.actions'; + +describe('Lock File', () => { + + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const contentList = new ContentList(); + const lockFilePage = new LockFilePage(); + + let adminUser = new AcsUserModel(); + let managerUser = new AcsUserModel(); + let uploadActions = new UploadActions(); + + let pngFileModel = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, + 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location + }); + + let pngFileToLock = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.PNG_B.file_name, + 'location': resources.Files.ADF_DOCUMENTS.PNG_B.file_location + }); + + let nodeId, site, documentLibrary, lockedFileNodeId; + + beforeAll(async (done) => { + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + await this.alfrescoJsApi.core.peopleApi.addPerson(adminUser); + await this.alfrescoJsApi.core.peopleApi.addPerson(managerUser); + + await this.alfrescoJsApi.login(adminUser.id, adminUser.password); + + site = await this.alfrescoJsApi.core.sitesApi.createSite({ + title: Util.generateRandomString(), + visibility: 'PRIVATE' + }); + + let resultNode = await this.alfrescoJsApi.core.nodesApi.getNodeChildren(site.entry.guid); + + documentLibrary = resultNode.list.entries[0].entry.id; + + await this.alfrescoJsApi.core.sitesApi.addSiteMember(site.entry.id, { + id: managerUser.id, + role: CONSTANTS.CS_USER_ROLES.MANAGER + }); + + done(); + + }); + + describe('Lock file interaction with the UI', () => { + + beforeAll(async (done) => { + let pngLockedUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileToLock.location, pngFileToLock.name, documentLibrary); + + lockedFileNodeId = pngLockedUploadedFile.entry.id; + + done(); + }); + + beforeEach(async (done) => { + let pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, documentLibrary); + + nodeId = pngUploadedFile.entry.id; + + loginPage.loginToContentServicesUsingUserModel(adminUser); + + navigationBarPage.openContentServicesFolder(documentLibrary); + + done(); + }); + + afterEach(async (done) => { + await this.alfrescoJsApi.login(adminUser.id, adminUser.password); + + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, nodeId); + + done(); + }); + + afterAll(async (done) => { + await this.alfrescoJsApi.login(adminUser.id, adminUser.password); + + await this.alfrescoJsApi.core.nodesApi.unlockNode(lockedFileNodeId); + + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, lockedFileNodeId); + + done(); + }); + + it('[C286604] Should be able to open Lock file option by clicking the lock image', () => { + contentList.clickContentLockIcon(pngFileModel.name); + + lockFilePage.checkLockFileCheckboxIsDisplayed(); + lockFilePage.checkCancelButtonIsDisplayed(); + lockFilePage.checkSaveButtonIsDisplayed(); + }); + + it('[C286625] Should be able to click Cancel to cancel lock file operation', () => { + contentList.clickContentLockIcon(pngFileModel.name); + + lockFilePage.checkLockFileCheckboxIsDisplayed(); + lockFilePage.clickCancelButton(); + + contentList.checkUnlockedIcon(pngFileModel.name); + }); + + it('[C286603] Should be able to click on Lock file checkbox and lock a file', () => { + contentList.clickContentLockIcon(pngFileToLock.name); + + lockFilePage.checkLockFileCheckboxIsDisplayed(); + lockFilePage.clickLockFileCheckbox(); + lockFilePage.clickSaveButton(); + + contentList.checkLockedIcon(pngFileToLock.name); + }); + + it('[C286618] Should be able to uncheck Lock file checkbox and unlock a file', () => { + contentList.clickContentLockIcon(pngFileModel.name); + + lockFilePage.checkLockFileCheckboxIsDisplayed(); + lockFilePage.clickLockFileCheckbox(); + lockFilePage.clickSaveButton(); + + contentList.checkLockedIcon(pngFileModel.name); + contentList.clickContentLockIcon(pngFileModel.name); + + lockFilePage.clickLockFileCheckbox(); + lockFilePage.clickSaveButton(); + + contentList.checkUnlockedIcon(pngFileModel.name); + }); + + }); + + describe('Locked file without owner permissions', () => { + + beforeEach(async (done) => { + let pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, documentLibrary); + + nodeId = pngUploadedFile.entry.id; + + loginPage.loginToContentServicesUsingUserModel(managerUser); + + navigationBarPage.openContentServicesFolder(documentLibrary); + + done(); + }); + + afterEach(async (done) => { + await this.alfrescoJsApi.login(adminUser.id, adminUser.password); + + await this.alfrescoJsApi.core.nodesApi.unlockNode(nodeId); + + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, nodeId); + + done(); + }); + + it('[C286610] Should not be able to delete a locked file', async () => { + await contentList.clickContentLockIcon(pngFileModel.name); + + await lockFilePage.checkLockFileCheckboxIsDisplayed(); + await lockFilePage.clickLockFileCheckbox(); + await lockFilePage.clickSaveButton(); + + try { + await this.alfrescoJsApi.core.nodesApi.deleteNode(nodeId); + + } catch (error) { + expect(error.status).toEqual(409); + } + + }); + + it('[C286611] Should not be able to rename a locked file', async () => { + await contentList.clickContentLockIcon(pngFileModel.name); + + await lockFilePage.checkLockFileCheckboxIsDisplayed(); + await lockFilePage.clickLockFileCheckbox(); + await lockFilePage.clickSaveButton(); + + try { + await this.alfrescoJsApi.core.nodesApi.updateNode(nodeId, { name: 'My new name' }); + + } catch (error) { + expect(error.status).toEqual(409); + } + + }); + + it('[C286612] Should not be able to move a locked file', async () => { + await contentList.clickContentLockIcon(pngFileModel.name); + + await lockFilePage.checkLockFileCheckboxIsDisplayed(); + await lockFilePage.clickLockFileCheckbox(); + await lockFilePage.clickSaveButton(); + + try { + await this.alfrescoJsApi.core.nodesApi.moveNode(nodeId, { targetParentId: '-my-' }); + + } catch (error) { + expect(error.status).toEqual(409); + } + }); + + it('[C286613] Should not be able to update a new version on a locked file', async () => { + await contentList.clickContentLockIcon(pngFileModel.name); + + await lockFilePage.checkLockFileCheckboxIsDisplayed(); + await lockFilePage.clickLockFileCheckbox(); + await lockFilePage.clickSaveButton(); + + try { + await this.alfrescoJsApi.core.nodesApi.updateNodeContent(nodeId, 'NEW FILE CONTENT'); + + } catch (error) { + expect(error.status).toEqual(409); + } + }); + + }); + + describe('Locked file with owner permissions', () => { + + beforeAll(async (done) => { + let pngFileToBeLocked = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileToLock.location, pngFileToLock.name, documentLibrary); + + lockedFileNodeId = pngFileToBeLocked.entry.id; + + done(); + }); + + beforeEach(async (done) => { + let pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, documentLibrary); + + nodeId = pngUploadedFile.entry.id; + + loginPage.loginToContentServicesUsingUserModel(adminUser); + + navigationBarPage.openContentServicesFolder(documentLibrary); + + done(); + }); + + afterEach(async (done) => { + await this.alfrescoJsApi.login(adminUser.id, adminUser.password); + + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, nodeId); + + done(); + + }); + + it('[C286614] Owner of the locked file should be able to rename if "Allow owner to modify" is checked', async () => { + await contentList.clickContentLockIcon(pngFileModel.name); + + await lockFilePage.checkLockFileCheckboxIsDisplayed(); + await lockFilePage.clickLockFileCheckbox(); + await lockFilePage.clickAllowOwnerCheckbox(); + await lockFilePage.clickSaveButton(); + + let response = await this.alfrescoJsApi.core.nodesApi.updateNode(nodeId, { name: 'My new name' }); + + expect(response.entry.name).toEqual('My new name'); + }); + + it('[C286615] Owner of the locked file should be able to update a new version if "Allow owner to modify" is checked', async () => { + await contentList.clickContentLockIcon(pngFileModel.name); + + await lockFilePage.checkLockFileCheckboxIsDisplayed(); + await lockFilePage.clickLockFileCheckbox(); + await lockFilePage.clickAllowOwnerCheckbox(); + await lockFilePage.clickSaveButton(); + + let response = await this.alfrescoJsApi.core.nodesApi.updateNodeContent(nodeId, 'NEW FILE CONTENT'); + + expect(response.entry.modifiedAt).toBeGreaterThan(response.entry.createdAt); + }); + + it('[C286616] Owner of the locked file should be able to move if "Allow owner to modify" is checked', async () => { + await contentList.clickContentLockIcon(pngFileModel.name); + + await lockFilePage.checkLockFileCheckboxIsDisplayed(); + await lockFilePage.clickLockFileCheckbox(); + await lockFilePage.clickAllowOwnerCheckbox(); + await lockFilePage.clickSaveButton(); + + await this.alfrescoJsApi.core.nodesApi.moveNode(nodeId, { targetParentId: '-my-' }); + + let movedFile = await this.alfrescoJsApi.core.nodesApi.getNode(nodeId); + + expect(movedFile.entry.parentId).not.toEqual(documentLibrary); + + }); + + it('[C286617] Owner of the locked file should be able to delete if "Allow owner to modify" is checked', async () => { + + loginPage.loginToContentServicesUsingUserModel(adminUser); + + navigationBarPage.openContentServicesFolder(documentLibrary); + + await contentList.clickContentLockIcon(pngFileToLock.name); + + await lockFilePage.checkLockFileCheckboxIsDisplayed(); + await lockFilePage.clickLockFileCheckbox(); + await lockFilePage.clickAllowOwnerCheckbox(); + await lockFilePage.clickSaveButton(); + + await this.alfrescoJsApi.core.nodesApi.deleteNode(lockedFileNodeId); + + try { + await this.alfrescoJsApi.core.nodesApi.getNode(lockedFileNodeId); + + } catch (error) { + expect(error.status).toEqual(404); + } + }); + + }); + +}); diff --git a/e2e/pages/adf/dialog/contentList.js b/e2e/pages/adf/dialog/contentList.js index 98eb6fab0d..3f174378ec 100644 --- a/e2e/pages/adf/dialog/contentList.js +++ b/e2e/pages/adf/dialog/contentList.js @@ -342,25 +342,45 @@ var ContentList = function () { let row = this.getRowByRowName(rowName); browser.actions().click(row, protractor.Button.RIGHT).perform(); Util.waitUntilElementIsVisible(element(by.id('adf-context-menu-content'))); - } + }; this.checkContextActionIsVisible = function (actionName) { let actionButton = element(by.css(`button[data-automation-id="context-${actionName}"`)); Util.waitUntilElementIsVisible(actionButton); Util.waitUntilElementIsClickable(actionButton); return actionButton; - } + }; this.pressContextMenuActionNamed = function (actionName) { let actionButton = this.checkContextActionIsVisible(actionName); actionButton.click(); - } + }; this.clickRowToSelect = function (rowName) { let row = this.getRowByRowName(rowName); browser.actions().keyDown(protractor.Key.COMMAND).click(row).perform(); this.checkRowIsSelected(rowName); - } + return this; + }; + + this.clickContentLockIcon = function (content) { + var lockIcon = element(by.css('div[filename="'+ content +'"] button')); + Util.waitUntilElementIsClickable(lockIcon); + lockIcon.click(); + return this; + }; + + this.checkLockedIcon = function (content) { + var lockIcon = element(by.cssContainingText('div[filename="'+ content +'"] mat-icon', 'lock')); + Util.waitUntilElementIsVisible(lockIcon); + return this; + }; + + this.checkUnlockedIcon = function (content) { + var lockIcon = element(by.cssContainingText('div[filename="'+ content +'"] mat-icon', 'lock_open')); + Util.waitUntilElementIsVisible(lockIcon); + return this; + }; }; module.exports = ContentList; diff --git a/e2e/pages/adf/lockFilePage.ts b/e2e/pages/adf/lockFilePage.ts new file mode 100644 index 0000000000..f061a857ff --- /dev/null +++ b/e2e/pages/adf/lockFilePage.ts @@ -0,0 +1,60 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Util = require('../../util/util'); +import { element, by } from 'protractor'; + +export class LockFilePage { + + cancelButton = element(by.css('button[aria-label="Close dialog"]')); + saveButton = element(by.cssContainingText('button span', 'Save')); + lockFileCheckboxText = element(by.cssContainingText('mat-checkbox label span', ' Lock file ')); + lockFileCheckbox = element(by.css('mat-checkbox[class*="adf-lock-file-name"]')); + allowOwnerCheckbox = element(by.cssContainingText('mat-checkbox[class*="adf-lock-file-name"] span', ' Allow the owner to modify this file ')); + + checkLockFileCheckboxIsDisplayed() { + return Util.waitUntilElementIsVisible(this.lockFileCheckboxText); + } + + checkCancelButtonIsDisplayed() { + return Util.waitUntilElementIsVisible(this.cancelButton); + } + + checkSaveButtonIsDisplayed() { + return Util.waitUntilElementIsVisible(this.saveButton); + } + + clickCancelButton() { + Util.waitUntilElementIsClickable(this.cancelButton); + return this.cancelButton.click(); + } + + clickLockFileCheckbox() { + Util.waitUntilElementIsClickable(this.lockFileCheckbox); + return this.lockFileCheckbox.click(); + } + + clickSaveButton() { + Util.waitUntilElementIsClickable(this.saveButton); + return this.saveButton.click(); + } + + clickAllowOwnerCheckbox() { + Util.waitUntilElementIsClickable(this.allowOwnerCheckbox); + return this.allowOwnerCheckbox.click(); + } +}