From 8f8819c3951f24775dc6c4ce117b0a7fa790392c Mon Sep 17 00:00:00 2001 From: Dharan <14145706+dhrn@users.noreply.github.com> Date: Mon, 22 Mar 2021 14:55:50 +0530 Subject: [PATCH] [ADF-5318] E2E Content Change type (#6799) * [ADF-5318] E2E Content Change type * Update metadata-content-type.e2e.ts --- .../metadata/metadata-content-type.e2e.ts | 160 ++++++++++++++++++ e2e/core/pages/metadata-view.page.ts | 31 +++- .../content-type-dialog.component.html | 2 +- .../content-type-dialog.component.spec.ts | 2 +- .../content-services/actions/model.actions.ts | 50 ++++++ .../content-services/actions/public-api.ts | 1 + 6 files changed, 243 insertions(+), 3 deletions(-) create mode 100644 e2e/content-services/metadata/metadata-content-type.e2e.ts create mode 100644 lib/testing/src/lib/content-services/actions/model.actions.ts diff --git a/e2e/content-services/metadata/metadata-content-type.e2e.ts b/e2e/content-services/metadata/metadata-content-type.e2e.ts new file mode 100644 index 0000000000..4c1434ac48 --- /dev/null +++ b/e2e/content-services/metadata/metadata-content-type.e2e.ts @@ -0,0 +1,160 @@ +/*! + * @license + * Copyright 2019 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 { + ApiService, + BrowserActions, + LoginPage, + ModelActions, + UploadActions, + UserModel, + UsersActions, + ViewerPage +} from '@alfresco/adf-testing'; +import { CustomModel, CustomType } from '@alfresco/js-api'; +import { FileModel } from '../../models/ACS/file.model'; +import { browser } from 'protractor'; +import { MetadataViewPage } from '../../core/pages/metadata-view.page'; +import { NavigationBarPage } from '../../core/pages/navigation-bar.page'; + +describe('content type', () => { + const apiService = new ApiService(); + const usersActions = new UsersActions(apiService); + const modelActions = new ModelActions(apiService); + + const viewerPage = new ViewerPage(); + const metadataViewPage = new MetadataViewPage(); + const navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + + const model: CustomModel = { + name: 'test', + namespaceUri: 'http://www.customModel.com/model/e2e/1.0', + namespacePrefix: 'e2e', + author: 'E2e Automation User', + description: 'Custom type e2e model', + status: 'DRAFT' + }; + const type: CustomType = { name: 'test', parentName: 'cm:content', title: 'Test type' }; + const pdfFile = new FileModel({ name: browser.params.resources.Files.ADF_DOCUMENTS.PDF.file_name }); + const docxFileModel = new FileModel({ + name: browser.params.resources.Files.ADF_DOCUMENTS.TEST.file_name, + location: browser.params.resources.Files.ADF_DOCUMENTS.TEST.file_path + }); + let acsUser: UserModel; + + beforeAll( async () => { + try { + await apiService.loginWithProfile('admin'); + + const typePaging = await modelActions.listTypes({where: `(namespaceUri matches('http://www.customModel.*'))`}); + if (typePaging.list.pagination.count === 0) { + await modelActions.createModel(model); + await modelActions.createType(model.name, type); + await modelActions.activateCustomModel(model.name); + } + + acsUser = await usersActions.createUser(); + await apiService.login(acsUser.username, acsUser.password); + + const uploadActions = new UploadActions(apiService); + const filePdfNode = await uploadActions.uploadFile(pdfFile.location, pdfFile.name, '-my-'); + pdfFile.id = filePdfNode.entry.id; + const docsNode = await uploadActions.uploadFile(docxFileModel.location, docxFileModel.name, '-my-'); + docxFileModel.id = docsNode.entry.id; + + await loginPage.login(acsUser.username, acsUser.password); + } catch (e) { + console.error('Failed to setup custom types', JSON.stringify(e, null, 2)); + fail(); + } + }); + + it('[C593560] Should the user be able to select a new content type and save it only after the confirmation dialog', async () => { + await BrowserActions.getUrl(browser.baseUrl + `/(overlay:files/${pdfFile.id}/view)`); + + await viewerPage.clickInfoButton(); + await viewerPage.checkInfoSideBarIsDisplayed(); + await metadataViewPage.clickOnPropertiesTab(); + await metadataViewPage.editIconIsDisplayed(); + + await expect(await viewerPage.getActiveTab()).toEqual('PROPERTIES'); + await metadataViewPage.hasContentType('Content'); + + await metadataViewPage.editIconClick(); + + await metadataViewPage.changeContentType(type.title); + await metadataViewPage.clickSaveMetadata(); + + await metadataViewPage.checkConfirmDialogDisplayed(); + await metadataViewPage.applyNodeProperties(); + + await navigationBarPage.clickLogoutButton(); + await loginPage.login(acsUser.username, acsUser.password); + await navigationBarPage.navigateToContentServices(); + + await viewerPage.viewFile(pdfFile.name); + await viewerPage.checkFileIsLoaded(); + + await viewerPage.clickInfoButton(); + await viewerPage.checkInfoSideBarIsDisplayed(); + await metadataViewPage.clickOnPropertiesTab(); + await metadataViewPage.editIconIsDisplayed(); + + await expect(await viewerPage.getActiveTab()).toEqual('PROPERTIES'); + await metadataViewPage.hasContentType(type.title); + + await viewerPage.clickCloseButton(); + }); + + it('[C593559] Should the user be able to select a new content type and not save it when press cancel in the confirmation dialog', async () => { + await BrowserActions.getUrl(browser.baseUrl + `/(overlay:files/${docxFileModel.id}/view)`); + + await viewerPage.clickInfoButton(); + await viewerPage.checkInfoSideBarIsDisplayed(); + await metadataViewPage.clickOnPropertiesTab(); + await metadataViewPage.editIconIsDisplayed(); + + await expect(await viewerPage.getActiveTab()).toEqual('PROPERTIES'); + await metadataViewPage.hasContentType('Content'); + + await metadataViewPage.editIconClick(); + + await metadataViewPage.changeContentType(type.title); + await metadataViewPage.clickSaveMetadata(); + + await metadataViewPage.checkConfirmDialogDisplayed(); + await metadataViewPage.cancelNodeProperties(); + + await navigationBarPage.clickLogoutButton(); + await loginPage.login(acsUser.username, acsUser.password); + await navigationBarPage.navigateToContentServices(); + + await viewerPage.viewFile(docxFileModel.name); + await viewerPage.checkFileIsLoaded(); + + await viewerPage.clickInfoButton(); + await viewerPage.checkInfoSideBarIsDisplayed(); + await metadataViewPage.clickOnPropertiesTab(); + await metadataViewPage.editIconIsDisplayed(); + + await expect(await viewerPage.getActiveTab()).toEqual('PROPERTIES'); + await metadataViewPage.hasContentType('Content'); + + await viewerPage.clickCloseButton(); + }); +}); diff --git a/e2e/core/pages/metadata-view.page.ts b/e2e/core/pages/metadata-view.page.ts index 33c3674e3f..996b587d4a 100644 --- a/e2e/core/pages/metadata-view.page.ts +++ b/e2e/core/pages/metadata-view.page.ts @@ -16,7 +16,7 @@ */ import { Locator, by, element, Key, protractor } from 'protractor'; -import { BrowserVisibility, BrowserActions } from '@alfresco/adf-testing'; +import { BrowserVisibility, BrowserActions, DropdownPage, TestElement } from '@alfresco/adf-testing'; export class MetadataViewPage { @@ -216,6 +216,35 @@ export class MetadataViewPage { await BrowserVisibility.waitUntilElementIsVisible(property); } + async hasContentType(contentType: string): Promise { + const nodeType = TestElement.byText('div[data-automation-id="header-nodeType"] .adf-property-value', contentType); + return nodeType.waitVisible(); + } + + async changeContentType(option: string): Promise { + const nodeType = TestElement.byCss('div[data-automation-id="header-nodeType"] mat-form-field'); + await nodeType.waitPresent(); + await nodeType.click(); + const typesDropDownPage = new DropdownPage(nodeType.elementFinder); + await typesDropDownPage.checkOptionIsDisplayed(option); + await typesDropDownPage.selectOption(option); + } + + async checkConfirmDialogDisplayed(): Promise { + const confirmButton = TestElement.byCss('adf-content-type-dialog'); + await confirmButton.waitPresent(); + } + + async applyNodeProperties(): Promise { + const confirmButton = TestElement.byId('content-type-dialog-apply-button'); + await confirmButton.click(); + } + + async cancelNodeProperties(): Promise { + const cancelButton = TestElement.byId('content-type-dialog-actions-cancel'); + await cancelButton.click(); + } + async checkPropertyIsNotVisible(propertyName: string, type: string): Promise { const property = element(by.css('div[data-automation-id="card-' + type + '-label-' + propertyName + '"]')); await BrowserVisibility.waitUntilElementIsNotVisible(property); diff --git a/lib/content-services/src/lib/content-type/content-type-dialog.component.html b/lib/content-services/src/lib/content-type/content-type-dialog.component.html index ad81b1489a..13749d1500 100644 --- a/lib/content-services/src/lib/content-type/content-type-dialog.component.html +++ b/lib/content-services/src/lib/content-type/content-type-dialog.component.html @@ -37,7 +37,7 @@ + id="content-type-dialog-actions-cancel">{{'CORE.METADATA.CONTENT_TYPE.DIALOG.CANCEL' | translate }} diff --git a/lib/content-services/src/lib/content-type/content-type-dialog.component.spec.ts b/lib/content-services/src/lib/content-type/content-type-dialog.component.spec.ts index 3a1e118628..01d19807ec 100644 --- a/lib/content-services/src/lib/content-type/content-type-dialog.component.spec.ts +++ b/lib/content-services/src/lib/content-type/content-type-dialog.component.spec.ts @@ -129,7 +129,7 @@ describe('Content Type Dialog Component', () => { it('should complete the select stream Cancel button is clicked', (done) => { data.select.subscribe(() => { }, () => { }, () => done()); - const cancelButton: HTMLButtonElement = fixture.nativeElement.querySelector('#conten-type-dialog-actions-cancel'); + const cancelButton: HTMLButtonElement = fixture.nativeElement.querySelector('#content-type-dialog-actions-cancel'); expect(cancelButton).toBeDefined(); cancelButton.click(); fixture.detectChanges(); diff --git a/lib/testing/src/lib/content-services/actions/model.actions.ts b/lib/testing/src/lib/content-services/actions/model.actions.ts new file mode 100644 index 0000000000..1f79fe2c5f --- /dev/null +++ b/lib/testing/src/lib/content-services/actions/model.actions.ts @@ -0,0 +1,50 @@ +/*! + * @license + * Copyright 2019 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 { ApiService } from '../../core/actions/api.service'; +import { CustomModel, CustomModelApi, CustomType, TypePaging, TypesApi } from '@alfresco/js-api'; + +export class ModelActions { + + customModelApi: CustomModelApi; + typesApi: TypesApi; + + constructor(api: ApiService) { + this.customModelApi = new CustomModelApi(api.getInstance()); + this.typesApi = new TypesApi(api.getInstance()); + } + + async createModel({status, description, name, namespaceUri, namespacePrefix, author}: CustomModel): Promise<{ entry: CustomModel }> { + return this.customModelApi.createCustomModel(status, description, name, namespaceUri, namespacePrefix, author); + } + + async createType(modelName, { name, parentName, title, description}: CustomType ): Promise<{ entry: CustomType }> { + return this.customModelApi.createCustomType(modelName, name, parentName, title, description); + } + + async activateCustomModel(modelName: string): Promise<{ entry: CustomModel }> { + return this.customModelApi.activateCustomModel(modelName); + } + + async deactivateCustomModel(modelName: string): Promise<{ entry: CustomModel }> { + return this.customModelApi.deactivateCustomModel(modelName); + } + + async listTypes(opts?: any): Promise { + return this.typesApi.listTypes(opts); + } +} diff --git a/lib/testing/src/lib/content-services/actions/public-api.ts b/lib/testing/src/lib/content-services/actions/public-api.ts index 5eeb0e8f70..261740e8dd 100644 --- a/lib/testing/src/lib/content-services/actions/public-api.ts +++ b/lib/testing/src/lib/content-services/actions/public-api.ts @@ -17,3 +17,4 @@ export * from './upload.actions'; export * from './permission.actions'; +export * from './model.actions';