diff --git a/e2e/components/components.ts b/e2e/components/components.ts index a1440fa84..252410cb3 100755 --- a/e2e/components/components.ts +++ b/e2e/components/components.ts @@ -29,6 +29,7 @@ export * from './header/user-info'; export * from './data-table/data-table'; export * from './dialog/confirm-dialog'; export * from './dialog/create-edit-folder-dialog'; +export * from './dialog/password-dialog'; export * from './pagination/pagination'; export * from './sidenav/sidenav'; export * from './toolbar/toolbar'; diff --git a/e2e/components/dialog/password-dialog.ts b/e2e/components/dialog/password-dialog.ts new file mode 100755 index 000000000..c5bdc8a06 --- /dev/null +++ b/e2e/components/dialog/password-dialog.ts @@ -0,0 +1,109 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2019 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 . + */ + +import { ElementFinder, by, browser, ExpectedConditions as EC, until } from 'protractor'; +import { BROWSER_WAIT_TIMEOUT } from '../../configs'; +import { Component } from '../component'; + +export class PasswordDialog extends Component { + private static selectors = { + root: 'adf-pdf-viewer-password-dialog', + + title: '.mat-dialog-title', + content: '.mat-dialog-content', + passwordInput: 'input[type="Password"]', + actionButtons: '.mat-dialog-actions', + errorMessage: '.mat-error' + }; + + title: ElementFinder = this.component.element(by.css(PasswordDialog.selectors.title)); + content: ElementFinder = this.component.element(by.css(PasswordDialog.selectors.content)); + passwordInput: ElementFinder = this.component.element(by.css(PasswordDialog.selectors.passwordInput)); + errorMessage: ElementFinder = this.component.element(by.css(PasswordDialog.selectors.errorMessage)); + closeButton: ElementFinder = this.component.element(by.buttonText('Close')); + submitButton: ElementFinder = this.component.element(by.buttonText('Submit')); + + constructor(ancestor?: ElementFinder) { + super(PasswordDialog.selectors.root, ancestor); + } + + async waitForDialogToClose() { + await browser.wait(EC.stalenessOf(this.title), BROWSER_WAIT_TIMEOUT); + } + + async waitForDialogToOpen() { + await browser.wait(EC.presenceOf(this.title), BROWSER_WAIT_TIMEOUT); + } + + async isDialogOpen() { + return await browser.isElementPresent(by.css(PasswordDialog.selectors.root)); + } + + async getTitle() { + return await this.title.getText(); + } + + async isCloseEnabled() { + return await this.closeButton.isEnabled(); + } + + async isSubmitEnabled() { + return await this.submitButton.isEnabled(); + } + + async clickClose() { + return await this.closeButton.click(); + } + + async clickSubmit() { + return await this.submitButton.click(); + } + + async isPasswordInputDisplayed() { + const present = await browser.isElementPresent(this.passwordInput); + if (present) { + return await this.passwordInput.isDisplayed(); + } else { + return false; + } + } + + async isErrorDisplayed() { + const elem = await browser.wait(until.elementLocated(by.css(PasswordDialog.selectors.errorMessage)), BROWSER_WAIT_TIMEOUT, '------- timeout waiting for error message to appear') + return await browser.isElementPresent(elem); + } + + async getErrorMessage() { + if (await this.isErrorDisplayed()) { + return await this.errorMessage.getText(); + } + return ''; + } + + async enterPassword(password: string) { + await this.passwordInput.clear(); + await this.passwordInput.sendKeys(password); + } +} diff --git a/e2e/components/viewer/viewer.ts b/e2e/components/viewer/viewer.ts index d687c3bce..944aa928e 100755 --- a/e2e/components/viewer/viewer.ts +++ b/e2e/components/viewer/viewer.ts @@ -23,7 +23,7 @@ * along with Alfresco. If not, see . */ -import { ElementFinder, by, browser, ExpectedConditions as EC } from 'protractor'; +import { ElementFinder, by, browser, ExpectedConditions as EC, ElementArrayFinder } from 'protractor'; import { Component } from '../component'; import { BROWSER_WAIT_TIMEOUT } from '../../configs'; import { Toolbar } from '../toolbar/toolbar'; @@ -37,7 +37,9 @@ export class Viewer extends Component { closeBtn: '.adf-viewer-close-button', fileTitle: '.adf-viewer__file-title', - viewerExtensionContent: 'adf-preview-extension' + viewerExtensionContent: 'adf-preview-extension', + + pdfViewerContentPage: '.adf-pdf-viewer__content .page' }; root: ElementFinder = browser.$(Viewer.selectors.root); @@ -46,6 +48,7 @@ export class Viewer extends Component { closeButton: ElementFinder = this.component.element(by.css(Viewer.selectors.closeBtn)); fileTitle: ElementFinder = this.component.element(by.css(Viewer.selectors.fileTitle)); viewerExtensionContent: ElementFinder = this.component.element(by.css(Viewer.selectors.viewerExtensionContent)); + pdfViewerContentPages: ElementArrayFinder = this.component.all(by.css(Viewer.selectors.pdfViewerContentPage)); toolbar = new Toolbar(this.component); @@ -63,7 +66,6 @@ export class Viewer extends Component { async isViewerOpened() { return await browser.isElementPresent(this.viewerLayout); - // return await this.viewerLayout.isPresent(); } async isViewerContentDisplayed() { @@ -103,4 +105,9 @@ export class Viewer extends Component { return await this.viewerExtensionContent.getAttribute('data-automation-id'); } } + + async isPdfViewerContentDisplayed() { + const count = await this.pdfViewerContentPages.count(); + return count > 0; + } } diff --git a/e2e/configs.ts b/e2e/configs.ts index c663f1c01..542be231c 100755 --- a/e2e/configs.ts +++ b/e2e/configs.ts @@ -113,7 +113,11 @@ export const FILES = { xlsxFile: 'file-xlsx.xlsx', xlsxFile2: 'file2-xlsx.xlsx', pdfFile: 'file-pdf.pdf', - unsupportedFile: 'file_unsupported.3DS' + unsupportedFile: 'file_unsupported.3DS', + protectedFile: { + name: 'protected.pdf', + password: '0000' + } }; export const EXTENSIBILITY_CONFIGS = { diff --git a/e2e/resources/test-files/protected.pdf b/e2e/resources/test-files/protected.pdf new file mode 100644 index 000000000..d0d083f11 Binary files /dev/null and b/e2e/resources/test-files/protected.pdf differ diff --git a/e2e/suites/viewer/viewer-protected-file.test.ts b/e2e/suites/viewer/viewer-protected-file.test.ts new file mode 100755 index 000000000..b6ecebd46 --- /dev/null +++ b/e2e/suites/viewer/viewer-protected-file.test.ts @@ -0,0 +1,119 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2019 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 . + */ + +import { LoginPage, BrowsingPage } from '../../pages/pages'; +import { FILES } from '../../configs'; +import { RepoClient } from '../../utilities/repo-client/repo-client'; +import { Utils } from '../../utilities/utils'; +import { Viewer } from '../../components/viewer/viewer'; +import { PasswordDialog } from './../../components/dialog/password-dialog'; + +describe('Viewer - password protected file', () => { + const username = `user-${Utils.random()}`; + + const parent = `parent-${Utils.random()}`; let parentId; + + const protectedFile = FILES.protectedFile; + + const apis = { + admin: new RepoClient(), + user: new RepoClient(username, username) + }; + + const loginPage = new LoginPage(); + const page = new BrowsingPage(); + const { dataTable } = page; + const viewer = new Viewer(); + const passwordDialog = new PasswordDialog(); + + beforeAll(async (done) => { + await apis.admin.people.createUser({ username }); + parentId = (await apis.user.nodes.createFolder(parent)).entry.id; + await apis.user.upload.uploadFile(protectedFile.name, parentId); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.header.expandSideNav(); + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(parent); + await dataTable.waitForHeader(); + await dataTable.doubleClickOnRowByName(protectedFile.name); + await viewer.waitForViewerToOpen(); + await page.waitForDialog(); + done(); + }); + + afterEach(async (done) => { + if (await passwordDialog.isDialogOpen()) { + await passwordDialog.clickClose(); + } + await Utils.pressEscape(); + done(); + }); + + afterAll(async (done) => { + await apis.user.nodes.deleteNodeById(parentId); + done(); + }); + + it('Password dialog appears when opening a protected file - [C268958]', async () => { + expect(await passwordDialog.isDialogOpen()).toBe(true, 'Password dialog not open'); + expect(await passwordDialog.isPasswordInputDisplayed()).toBe(true, 'Password input not displayed'); + expect(await passwordDialog.isSubmitEnabled()).toBe(false, 'Submit button not disabled'); + expect(await passwordDialog.isCloseEnabled()).toBe(true, 'Close button not enabled'); + expect(await viewer.isPdfViewerContentDisplayed()).toBe(false, 'file content is displayed'); + }); + + it('File content is displayed when entering the correct password - [C268959]', async () => { + await passwordDialog.enterPassword(protectedFile.password); + expect(await passwordDialog.isSubmitEnabled()).toBe(true, 'Submit button not enabled'); + + await passwordDialog.clickSubmit(); + await passwordDialog.waitForDialogToClose(); + + expect(await viewer.isPdfViewerContentDisplayed()).toBe(true, 'file content not displayed'); + }); + + it('Error appears when entering an incorrect password - [C268960]', async () => { + await passwordDialog.enterPassword('incorrect'); + expect(await passwordDialog.isSubmitEnabled()).toBe(true, 'Submit button not enabled'); + await passwordDialog.clickSubmit(); + + expect(await passwordDialog.getErrorMessage()).toBe('Password is wrong'); + expect(await viewer.isPdfViewerContentDisplayed()).toBe(false, 'file content is displayed'); + }); + + it('Refresh the page while Password dialog is open - [C268961]', async () => { + await passwordDialog.enterPassword(protectedFile.password); + await page.refresh(); + await viewer.waitForViewerToOpen(); + + expect(await viewer.isPdfViewerContentDisplayed()).toBe(false, 'file content is displayed'); + expect(await passwordDialog.isDialogOpen()).toBe(true, 'Password dialog not open'); + }); +});