mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-05-12 17:04:46 +00:00
e2e tests
This commit is contained in:
parent
aba476c15f
commit
7f12841e5a
@ -1,14 +0,0 @@
|
|||||||
import { AppPage } from './app.po';
|
|
||||||
|
|
||||||
describe('alfresco-content-app App', () => {
|
|
||||||
let page: AppPage;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
page = new AppPage();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display welcome message', () => {
|
|
||||||
page.navigateTo();
|
|
||||||
expect(page.getParagraphText()).toEqual('Welcome to app!');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,11 +0,0 @@
|
|||||||
import { browser, by, element } from 'protractor';
|
|
||||||
|
|
||||||
export class AppPage {
|
|
||||||
navigateTo() {
|
|
||||||
return browser.get('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
getParagraphText() {
|
|
||||||
return element(by.css('app-root h1')).getText();
|
|
||||||
}
|
|
||||||
}
|
|
35
e2e/components/component.ts
Normal file
35
e2e/components/component.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { ElementFinder, element, by, ExpectedConditions as EC, browser } from 'protractor';
|
||||||
|
import { BROWSER_WAIT_TIMEOUT } from '../configs';
|
||||||
|
|
||||||
|
export abstract class Component {
|
||||||
|
component: ElementFinder;
|
||||||
|
|
||||||
|
constructor(selector: string, ancestor?: ElementFinder) {
|
||||||
|
const locator = by.css(selector);
|
||||||
|
|
||||||
|
this.component = ancestor
|
||||||
|
? ancestor.element(locator)
|
||||||
|
: element(locator);
|
||||||
|
}
|
||||||
|
|
||||||
|
wait() {
|
||||||
|
return browser.wait(EC.presenceOf(this.component), BROWSER_WAIT_TIMEOUT);
|
||||||
|
}
|
||||||
|
}
|
24
e2e/components/components.ts
Normal file
24
e2e/components/components.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './login/login';
|
||||||
|
export * from './header/header';
|
||||||
|
export * from './header/user-info';
|
||||||
|
export * from './data-table/data-table';
|
||||||
|
export * from './pagination/pagination';
|
||||||
|
export * from './sidenav/sidenav';
|
||||||
|
export * from './toolbar/toolbar';
|
110
e2e/components/data-table/data-table.ts
Normal file
110
e2e/components/data-table/data-table.ts
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { ElementFinder, ElementArrayFinder, promise, by, browser, ExpectedConditions as EC } from 'protractor';
|
||||||
|
import { BROWSER_WAIT_TIMEOUT } from '../../configs';
|
||||||
|
import { Component } from '../component';
|
||||||
|
|
||||||
|
export class DataTable extends Component {
|
||||||
|
private static selectors = {
|
||||||
|
root: 'adf-datatable',
|
||||||
|
|
||||||
|
head: 'table > thead',
|
||||||
|
columnHeader: 'tr > th',
|
||||||
|
sortedColumnHeader: `
|
||||||
|
th.adf-data-table__header--sorted-asc,
|
||||||
|
th.adf-data-table__header--sorted-desc
|
||||||
|
`,
|
||||||
|
|
||||||
|
body: 'table > tbody',
|
||||||
|
row: 'tr'
|
||||||
|
};
|
||||||
|
|
||||||
|
private head: ElementFinder = this.component.element(by.css(DataTable.selectors.head));
|
||||||
|
private body: ElementFinder = this.component.element(by.css(DataTable.selectors.body));
|
||||||
|
|
||||||
|
constructor(ancestor?: ElementFinder) {
|
||||||
|
super(DataTable.selectors.root, ancestor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait methods (waits for elements)
|
||||||
|
waitForHeader() {
|
||||||
|
return browser.wait(EC.presenceOf(this.head), BROWSER_WAIT_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// waitForEmptyState() {}
|
||||||
|
|
||||||
|
// Header/Column methods
|
||||||
|
getColumnHeaders(): ElementArrayFinder {
|
||||||
|
const locator = by.css(DataTable.selectors.columnHeader);
|
||||||
|
return this.head.all(locator);
|
||||||
|
}
|
||||||
|
|
||||||
|
getNthColumnHeader(nth: number): ElementFinder {
|
||||||
|
return this.getColumnHeaders().get(nth - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
getColumnHeaderByLabel(label: string): ElementFinder {
|
||||||
|
const locator = by.cssContainingText(DataTable.selectors.columnHeader, label);
|
||||||
|
return this.head.element(locator);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSortedColumnHeader(): ElementFinder {
|
||||||
|
const locator = by.css(DataTable.selectors.sortedColumnHeader);
|
||||||
|
return this.head.element(locator);
|
||||||
|
}
|
||||||
|
|
||||||
|
sortByColumn(columnName: string): Promise<void> {
|
||||||
|
const column = this.getColumnHeaderByLabel(columnName);
|
||||||
|
const click = browser.actions().mouseMove(column).click();
|
||||||
|
|
||||||
|
return click.perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rows methods
|
||||||
|
getRows(): ElementArrayFinder {
|
||||||
|
return this.body.all(by.css(DataTable.selectors.row));
|
||||||
|
}
|
||||||
|
|
||||||
|
getNthRow(nth: number): ElementFinder {
|
||||||
|
return this.getRows().get(nth - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRowByContainingText(text: string): ElementFinder {
|
||||||
|
const locator = by.cssContainingText(DataTable.selectors.row, text);
|
||||||
|
return this.body.element(locator);
|
||||||
|
}
|
||||||
|
|
||||||
|
countRows(): promise.Promise<number> {
|
||||||
|
return this.getRows().count();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigation/selection methods
|
||||||
|
doubleClickOnRowByContainingText(text: string): promise.Promise<void> {
|
||||||
|
const row = this.getRowByContainingText(text);
|
||||||
|
const dblClick = browser.actions().mouseMove(row).click().click();
|
||||||
|
|
||||||
|
return dblClick.perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
clickOnRowByContainingText(text: string): promise.Promise<void> {
|
||||||
|
const row = this.getRowByContainingText(text);
|
||||||
|
const click = browser.actions().mouseMove(row).click();
|
||||||
|
|
||||||
|
return click.perform();
|
||||||
|
}
|
||||||
|
}
|
106
e2e/components/dialog/create-edit-folder-dialog.ts
Normal file
106
e2e/components/dialog/create-edit-folder-dialog.ts
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { ElementFinder, by, browser, protractor, ExpectedConditions as EC } from 'protractor';
|
||||||
|
import { BROWSER_WAIT_TIMEOUT } from '../../configs';
|
||||||
|
import { Component } from '../component';
|
||||||
|
|
||||||
|
export class CreateOrEditFolderDialog extends Component {
|
||||||
|
private static selectors = {
|
||||||
|
root: '.mat-dialog-container',
|
||||||
|
|
||||||
|
title: '.mat-dialog-title',
|
||||||
|
nameInput: '.mat-dialog-container .mat-input-element[placeholder="Name"]',
|
||||||
|
descriptionTextArea: '.mat-dialog-container .mat-input-element[placeholder="Description"]',
|
||||||
|
button: '.mat-dialog-actions button',
|
||||||
|
validationMessage: '.mat-hint span'
|
||||||
|
};
|
||||||
|
|
||||||
|
title: ElementFinder = this.component.element(by.css(CreateOrEditFolderDialog.selectors.title));
|
||||||
|
nameInput: ElementFinder = this.component.element(by.css(CreateOrEditFolderDialog.selectors.nameInput));
|
||||||
|
descriptionTextArea: ElementFinder = this.component.element(by.css(CreateOrEditFolderDialog.selectors.descriptionTextArea));
|
||||||
|
createButton: ElementFinder = this.component.element(by.cssContainingText(CreateOrEditFolderDialog.selectors.button, 'Create'));
|
||||||
|
cancelButton: ElementFinder = this.component.element(by.cssContainingText(CreateOrEditFolderDialog.selectors.button, 'Cancel'));
|
||||||
|
updateButton: ElementFinder = this.component.element(by.cssContainingText(CreateOrEditFolderDialog.selectors.button, 'Update'));
|
||||||
|
validationMessage: ElementFinder = this.component.element(by.css(CreateOrEditFolderDialog.selectors.validationMessage));
|
||||||
|
|
||||||
|
constructor(ancestor?: ElementFinder) {
|
||||||
|
super(CreateOrEditFolderDialog.selectors.root, ancestor);
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForDialogToOpen() {
|
||||||
|
return browser.wait(EC.presenceOf(this.title), BROWSER_WAIT_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForDialogToClose() {
|
||||||
|
return browser.wait(EC.stalenessOf(this.title), BROWSER_WAIT_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTitle(): Promise<string> {
|
||||||
|
return this.title.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
isValidationMessageDisplayed(): Promise<boolean> {
|
||||||
|
return this.validationMessage.isDisplayed();
|
||||||
|
}
|
||||||
|
|
||||||
|
getValidationMessage(): Promise<string> {
|
||||||
|
return this.isValidationMessageDisplayed()
|
||||||
|
.then(() => this.validationMessage.getText())
|
||||||
|
.catch(() => '');
|
||||||
|
}
|
||||||
|
|
||||||
|
enterName(name: string): CreateOrEditFolderDialog {
|
||||||
|
const { nameInput } = this;
|
||||||
|
|
||||||
|
nameInput.clear();
|
||||||
|
nameInput.sendKeys(name);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteNameWithBackspace(): Promise<void> {
|
||||||
|
const { nameInput } = this;
|
||||||
|
|
||||||
|
return nameInput.clear()
|
||||||
|
.then(() => {
|
||||||
|
return nameInput.sendKeys(' ', protractor.Key.CONTROL, 'a', protractor.Key.NULL, protractor.Key.BACK_SPACE);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
enterDescription(description: string): CreateOrEditFolderDialog {
|
||||||
|
const { descriptionTextArea } = this;
|
||||||
|
|
||||||
|
descriptionTextArea.clear();
|
||||||
|
descriptionTextArea.sendKeys(description);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
clickCreate() {
|
||||||
|
return this.createButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
clickCancel() {
|
||||||
|
return this.cancelButton.click()
|
||||||
|
.then(() => this.waitForDialogToClose());
|
||||||
|
}
|
||||||
|
|
||||||
|
clickUpdate() {
|
||||||
|
return this.updateButton.click();
|
||||||
|
}
|
||||||
|
}
|
34
e2e/components/header/header.ts
Normal file
34
e2e/components/header/header.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { ElementFinder, by } from 'protractor';
|
||||||
|
import { Component } from '../component';
|
||||||
|
import { UserInfo } from './user-info';
|
||||||
|
|
||||||
|
export class Header extends Component {
|
||||||
|
private locators = {
|
||||||
|
logoLink: by.css('.mdl-layout-title'),
|
||||||
|
userInfo: by.css('app-current-user')
|
||||||
|
};
|
||||||
|
|
||||||
|
logoLink: ElementFinder = this.component.element(this.locators.logoLink);
|
||||||
|
userInfo: UserInfo = new UserInfo(this.component);
|
||||||
|
|
||||||
|
constructor(ancestor?: ElementFinder) {
|
||||||
|
super('app-header', ancestor);
|
||||||
|
}
|
||||||
|
}
|
56
e2e/components/header/user-info.ts
Normal file
56
e2e/components/header/user-info.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { ElementFinder, ElementArrayFinder, element, by, promise } from 'protractor';
|
||||||
|
import { Menu } from '../menu/menu';
|
||||||
|
import { Component } from '../component';
|
||||||
|
|
||||||
|
export class UserInfo extends Component {
|
||||||
|
private locators = {
|
||||||
|
avatar: by.css('.current-user__avatar'),
|
||||||
|
fullName: by.css('.current-user__full-name'),
|
||||||
|
menuItems: by.css('[md-menu-item]')
|
||||||
|
};
|
||||||
|
|
||||||
|
fullName: ElementFinder = this.component.element(this.locators.fullName);
|
||||||
|
avatar: ElementFinder = this.component.element(this.locators.avatar);
|
||||||
|
|
||||||
|
menu: Menu = new Menu();
|
||||||
|
|
||||||
|
constructor(ancestor?: ElementFinder) {
|
||||||
|
super('app-current-user', ancestor);
|
||||||
|
}
|
||||||
|
|
||||||
|
openMenu(): promise.Promise<Menu> {
|
||||||
|
const { menu, avatar } = this;
|
||||||
|
|
||||||
|
return avatar.click()
|
||||||
|
.then(() => menu.wait())
|
||||||
|
.then(() => menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
get name(): Promise<string> {
|
||||||
|
return this.fullName.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
signOut(): Promise<void> {
|
||||||
|
return this.openMenu()
|
||||||
|
.then(menu => {
|
||||||
|
menu.clickMenuItem('Sign out');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
67
e2e/components/login/login.ts
Normal file
67
e2e/components/login/login.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { by, ElementFinder } from 'protractor';
|
||||||
|
import { Component } from '../component';
|
||||||
|
|
||||||
|
export class LoginComponent extends Component {
|
||||||
|
static selector = 'alfresco-login';
|
||||||
|
|
||||||
|
private locators = {
|
||||||
|
usernameInput: by.css('input#username'),
|
||||||
|
passwordInput: by.css('input#password'),
|
||||||
|
submitButton: by.css('button#login-button'),
|
||||||
|
errorMessage: by.css('.login-error-message')
|
||||||
|
};
|
||||||
|
|
||||||
|
usernameInput: ElementFinder = this.component.element(this.locators.usernameInput);
|
||||||
|
passwordInput: ElementFinder = this.component.element(this.locators.passwordInput);
|
||||||
|
submitButton: ElementFinder = this.component.element(this.locators.submitButton);
|
||||||
|
errorMessage: ElementFinder = this.component.element(this.locators.errorMessage);
|
||||||
|
|
||||||
|
constructor(ancestor?: ElementFinder) {
|
||||||
|
super(LoginComponent.selector, ancestor);
|
||||||
|
}
|
||||||
|
|
||||||
|
enterUsername(username: string): LoginComponent {
|
||||||
|
const { usernameInput } = this;
|
||||||
|
|
||||||
|
usernameInput.clear();
|
||||||
|
usernameInput.sendKeys(username);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
enterPassword(password: string): LoginComponent {
|
||||||
|
const { passwordInput } = this;
|
||||||
|
|
||||||
|
passwordInput.clear();
|
||||||
|
passwordInput.sendKeys(password);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
enterCredentials(username: string, password: string) {
|
||||||
|
this.enterUsername(username).enterPassword(password);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
submit(): Promise<void> {
|
||||||
|
return this.submitButton.click();
|
||||||
|
}
|
||||||
|
}
|
57
e2e/components/menu/menu.ts
Normal file
57
e2e/components/menu/menu.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { ElementFinder, ElementArrayFinder, by, browser, ExpectedConditions as EC } from 'protractor';
|
||||||
|
import { BROWSER_WAIT_TIMEOUT } from '../../configs';
|
||||||
|
import { Component } from '../component';
|
||||||
|
|
||||||
|
export class Menu extends Component {
|
||||||
|
private static selectors = {
|
||||||
|
root: '.mat-menu-panel',
|
||||||
|
item: 'button.mat-menu-item'
|
||||||
|
};
|
||||||
|
|
||||||
|
items: ElementArrayFinder = this.component.all(by.css(Menu.selectors.item));
|
||||||
|
|
||||||
|
constructor(ancestor?: ElementFinder) {
|
||||||
|
super(Menu.selectors.root, ancestor);
|
||||||
|
}
|
||||||
|
|
||||||
|
wait() {
|
||||||
|
return browser.wait(EC.visibilityOf(this.items.get(0)), BROWSER_WAIT_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
getNthItem(nth: number): ElementFinder {
|
||||||
|
return this.items.get(nth - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
getItemByLabel(label: string): ElementFinder {
|
||||||
|
return this.component.element(by.cssContainingText(Menu.selectors.item, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
getItemTooltip(label: string): Promise<string> {
|
||||||
|
return this.getItemByLabel(label).getAttribute('title');
|
||||||
|
}
|
||||||
|
|
||||||
|
clicktNthItem(nth: number): Promise<void> {
|
||||||
|
return this.getNthItem(nth).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
clickMenuItem(label: string): Promise<void> {
|
||||||
|
return this.getItemByLabel(label).click();
|
||||||
|
}
|
||||||
|
}
|
67
e2e/components/pagination/pagination.ts
Normal file
67
e2e/components/pagination/pagination.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { ElementFinder, ElementArrayFinder, promise, by, browser, ExpectedConditions as EC } from 'protractor';
|
||||||
|
import { BROWSER_WAIT_TIMEOUT } from '../../configs';
|
||||||
|
import { Menu } from '../menu/menu';
|
||||||
|
import { Component } from '../component';
|
||||||
|
|
||||||
|
export class Pagination extends Component {
|
||||||
|
private static selectors = {
|
||||||
|
root: 'adf-pagination',
|
||||||
|
range: '.adf-pagination__range',
|
||||||
|
maxItems: '.adf-pagination__max-items',
|
||||||
|
currentPage: '.adf-pagination__current-page',
|
||||||
|
totalPages: '.adf-pagination__total-pages',
|
||||||
|
|
||||||
|
previousButton: '.adf-pagination__previous-button',
|
||||||
|
nextButton: '.adf-pagination__next-button',
|
||||||
|
maxItemsButton: '.adf-pagination__max-items + button[md-icon-button]',
|
||||||
|
pagesButton: '.adf-pagination__current-page + button[md-icon-button]'
|
||||||
|
};
|
||||||
|
|
||||||
|
range: ElementFinder = this.component.element(by.css(Pagination.selectors.range));
|
||||||
|
maxItems: ElementFinder = this.component.element(by.css(Pagination.selectors.maxItems));
|
||||||
|
currentPage: ElementFinder = this.component.element(by.css(Pagination.selectors.currentPage));
|
||||||
|
totalPages: ElementFinder = this.component.element(by.css(Pagination.selectors.totalPages));
|
||||||
|
previousButton: ElementFinder = this.component.element(by.css(Pagination.selectors.previousButton));
|
||||||
|
nextButton: ElementFinder = this.component.element(by.css(Pagination.selectors.nextButton));
|
||||||
|
maxItemsButton: ElementFinder = this.component.element(by.css(Pagination.selectors.maxItemsButton));
|
||||||
|
pagesButton: ElementFinder = this.component.element(by.css(Pagination.selectors.pagesButton));
|
||||||
|
|
||||||
|
menu: Menu = new Menu();
|
||||||
|
|
||||||
|
constructor(ancestor?: ElementFinder) {
|
||||||
|
super(Pagination.selectors.root, ancestor);
|
||||||
|
}
|
||||||
|
|
||||||
|
openMaxItemsMenu(): Promise<Menu> {
|
||||||
|
const { menu, maxItemsButton } = this;
|
||||||
|
|
||||||
|
return maxItemsButton.click()
|
||||||
|
.then(() => menu.wait())
|
||||||
|
.then(() => menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
openCurrentPageMenu(): Promise<Menu> {
|
||||||
|
const { menu, pagesButton } = this;
|
||||||
|
|
||||||
|
return this.pagesButton.click()
|
||||||
|
.then(() => menu.wait())
|
||||||
|
.then(() => menu);
|
||||||
|
}
|
||||||
|
}
|
63
e2e/components/sidenav/sidenav.ts
Normal file
63
e2e/components/sidenav/sidenav.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { ElementFinder, ElementArrayFinder, by, promise } from 'protractor';
|
||||||
|
import { Menu } from '../menu/menu';
|
||||||
|
import { Component } from '../component';
|
||||||
|
|
||||||
|
export class Sidenav extends Component {
|
||||||
|
private static selectors = {
|
||||||
|
root: 'app-sidenav',
|
||||||
|
link: '.sidenav-menu__item-link',
|
||||||
|
activeLink: '.sidenav-menu__item-link--active',
|
||||||
|
newButton: '.sidenav__section--new__button'
|
||||||
|
};
|
||||||
|
|
||||||
|
links: ElementArrayFinder = this.component.all(by.css(Sidenav.selectors.link));
|
||||||
|
activeLink: ElementFinder = this.component.element(by.css(Sidenav.selectors.activeLink));
|
||||||
|
newButton: ElementArrayFinder = this.component.all(by.css(Sidenav.selectors.newButton));
|
||||||
|
|
||||||
|
menu: Menu = new Menu();
|
||||||
|
|
||||||
|
constructor(ancestor?: ElementFinder) {
|
||||||
|
super(Sidenav.selectors.root, ancestor);
|
||||||
|
}
|
||||||
|
|
||||||
|
openNewMenu(): promise.Promise<Menu> {
|
||||||
|
const { menu, newButton } = this;
|
||||||
|
|
||||||
|
return newButton.click()
|
||||||
|
.then(() => menu.wait())
|
||||||
|
.then(() => menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
isActiveByLabel(label: string): promise.Promise<boolean> {
|
||||||
|
return this
|
||||||
|
.getLinkByLabel(label)
|
||||||
|
.getWebElement()
|
||||||
|
.then(element => element.getAttribute('class'))
|
||||||
|
.then(className => className.includes(Sidenav.selectors.activeLink.replace('.', '')));
|
||||||
|
}
|
||||||
|
|
||||||
|
getLinkByLabel(label: string): ElementFinder {
|
||||||
|
return this.component.element(by.cssContainingText(Sidenav.selectors.link, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateToLinkByLabel(label: string): promise.Promise<void> {
|
||||||
|
return this.getLinkByLabel(label).click();
|
||||||
|
}
|
||||||
|
}
|
56
e2e/components/toolbar/toolbar-actions.ts
Normal file
56
e2e/components/toolbar/toolbar-actions.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { ElementFinder, ElementArrayFinder, by, promise } from 'protractor';
|
||||||
|
import { Menu } from '../menu/menu';
|
||||||
|
import { Component } from '../component';
|
||||||
|
|
||||||
|
export class ToolbarActions extends Component {
|
||||||
|
private static selectors = {
|
||||||
|
root: 'adf-toolbar',
|
||||||
|
button: '.mat-icon-button'
|
||||||
|
};
|
||||||
|
|
||||||
|
menu: Menu = new Menu();
|
||||||
|
buttons: ElementArrayFinder = this.component.all(by.css(ToolbarActions.selectors.button));
|
||||||
|
|
||||||
|
constructor(ancestor?: ElementFinder) {
|
||||||
|
super(ToolbarActions.selectors.root, ancestor);
|
||||||
|
}
|
||||||
|
|
||||||
|
isEmpty(): Promise<boolean> {
|
||||||
|
return this.buttons.count().then(count => (count === 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
getButtonByLabel(label: string): ElementFinder {
|
||||||
|
return this.component.element(by.cssContainingText(ToolbarActions.selectors.button, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
getButtonByTitleAttribute(title: string): ElementFinder {
|
||||||
|
return this.component.element(by.css(`${ToolbarActions.selectors.button}[title="${title}"]`));
|
||||||
|
}
|
||||||
|
|
||||||
|
openMoreMenu(): promise.Promise<Menu> {
|
||||||
|
const { menu } = this;
|
||||||
|
const moreButton = this.getButtonByTitleAttribute('More actions');
|
||||||
|
|
||||||
|
return moreButton
|
||||||
|
.click()
|
||||||
|
.then(() => menu.wait())
|
||||||
|
.then(() => menu);
|
||||||
|
}
|
||||||
|
}
|
37
e2e/components/toolbar/toolbar-breadcrumb.ts
Normal file
37
e2e/components/toolbar/toolbar-breadcrumb.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { ElementFinder, ElementArrayFinder, by } from 'protractor';
|
||||||
|
import { Menu } from '../menu/menu';
|
||||||
|
import { Component } from '../component';
|
||||||
|
|
||||||
|
export class ToolbarBreadcrumb extends Component {
|
||||||
|
private static selectors = {
|
||||||
|
root: 'adf-breadcrumb',
|
||||||
|
item: '.adf-breadcrumb-item'
|
||||||
|
};
|
||||||
|
|
||||||
|
items: ElementArrayFinder = this.component.all(by.css(ToolbarBreadcrumb.selectors.item));
|
||||||
|
|
||||||
|
constructor(ancestor?: ElementFinder) {
|
||||||
|
super(ToolbarBreadcrumb.selectors.root, ancestor);
|
||||||
|
}
|
||||||
|
|
||||||
|
getNthItem(nth: number): ElementFinder {
|
||||||
|
return this.items.get(nth - 1);
|
||||||
|
}
|
||||||
|
}
|
34
e2e/components/toolbar/toolbar.ts
Normal file
34
e2e/components/toolbar/toolbar.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { ElementFinder, ElementArrayFinder, by } from 'protractor';
|
||||||
|
import { Component } from '../component';
|
||||||
|
import { ToolbarActions } from './toolbar-actions';
|
||||||
|
import { ToolbarBreadcrumb } from './toolbar-breadcrumb';
|
||||||
|
|
||||||
|
export class Toolbar extends Component {
|
||||||
|
private static selectors = {
|
||||||
|
root: '.inner-layout__header'
|
||||||
|
};
|
||||||
|
|
||||||
|
actions: ToolbarActions = new ToolbarActions(this.component);
|
||||||
|
breadcrumb: ToolbarBreadcrumb = new ToolbarBreadcrumb(this.component);
|
||||||
|
|
||||||
|
constructor(ancestor?: ElementFinder) {
|
||||||
|
super(Toolbar.selectors.root, ancestor);
|
||||||
|
}
|
||||||
|
}
|
53
e2e/configs.ts
Normal file
53
e2e/configs.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
export const BROWSER_RESOLUTION_WIDTH = 1200;
|
||||||
|
export const BROWSER_RESOLUTION_HEIGHT = 800;
|
||||||
|
|
||||||
|
export const BROWSER_WAIT_TIMEOUT = 10000;
|
||||||
|
|
||||||
|
// Application configs
|
||||||
|
export const APP_HOST = 'http://localhost:3000';
|
||||||
|
|
||||||
|
// Repository configs
|
||||||
|
export const REPO_API_HOST = 'http://localhost:8080';
|
||||||
|
export const REPO_API_TENANT = '-default-';
|
||||||
|
|
||||||
|
// Admin details
|
||||||
|
export const ADMIN_USERNAME = 'admin';
|
||||||
|
export const ADMIN_PASSWORD = 'admin';
|
||||||
|
export const ADMIN_FULL_NAME = 'Administrator';
|
||||||
|
|
||||||
|
// Application Routes
|
||||||
|
export const APP_ROUTES = {
|
||||||
|
FAVORITES: '/favorites',
|
||||||
|
FILE_LIBRARIES: '/libraries',
|
||||||
|
LOGIN: '/login',
|
||||||
|
LOGOUT: '/logout',
|
||||||
|
PERSONAL_FILES: '/personal-files',
|
||||||
|
RECENT_FILES: '/recent-files',
|
||||||
|
SHARED_FILES: '/shared',
|
||||||
|
TRASHCAN: '/trashcan'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sidebar labels
|
||||||
|
export const SIDEBAR_LABELS = {
|
||||||
|
PERSONAL_FILES: 'Personal Files',
|
||||||
|
FILE_LIBRARIES: 'File Libraries',
|
||||||
|
SHARED_FILES: 'Shared',
|
||||||
|
RECENT_FILES: 'Recent Files',
|
||||||
|
FAVORITES: 'Favorites',
|
||||||
|
TRASH: 'Trash'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Site visibility
|
||||||
|
export const SITE_VISIBILITY = {
|
||||||
|
PUBLIC: 'PUBLIC',
|
||||||
|
MODERATED: 'MODERATED',
|
||||||
|
PRIVATE: 'PRIVATE'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Site roles
|
||||||
|
export const SITE_ROLES = {
|
||||||
|
SITE_CONSUMER: 'SiteConsumer',
|
||||||
|
SITE_COLLABORATOR: 'SiteCollaborator',
|
||||||
|
SITE_CONTRIBUTOR: 'SiteContributor',
|
||||||
|
SITE_MANAGER: 'SiteManager'
|
||||||
|
};
|
31
e2e/pages/browsing-page.ts
Normal file
31
e2e/pages/browsing-page.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { Header, DataTable, Pagination, Toolbar, Sidenav } from '../components/components';
|
||||||
|
import { Page } from './page';
|
||||||
|
|
||||||
|
export class BrowsingPage extends Page {
|
||||||
|
header = new Header(this.app);
|
||||||
|
sidenav = new Sidenav(this.app);
|
||||||
|
toolbar = new Toolbar(this.app);
|
||||||
|
dataTable = new DataTable(this.app);
|
||||||
|
pagination = new Pagination(this.app);
|
||||||
|
|
||||||
|
signOut(): Promise<void> {
|
||||||
|
return this.header.userInfo.signOut();
|
||||||
|
}
|
||||||
|
}
|
54
e2e/pages/login-page.ts
Normal file
54
e2e/pages/login-page.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { browser, ExpectedConditions as EC } from 'protractor';
|
||||||
|
import { LoginComponent } from '../components/components';
|
||||||
|
import { Page } from './page';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ADMIN_USERNAME,
|
||||||
|
ADMIN_PASSWORD,
|
||||||
|
BROWSER_WAIT_TIMEOUT,
|
||||||
|
APP_ROUTES
|
||||||
|
} from '../configs';
|
||||||
|
|
||||||
|
export class LoginPage extends Page {
|
||||||
|
login: LoginComponent = new LoginComponent(this.app);
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
constructor() {
|
||||||
|
super(APP_ROUTES.LOGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
load(): Promise<any> {
|
||||||
|
return super.load().then(() => {
|
||||||
|
const { submitButton } = this.login;
|
||||||
|
const hasSumbitButton = EC.presenceOf(submitButton);
|
||||||
|
|
||||||
|
return browser.wait(hasSumbitButton, BROWSER_WAIT_TIMEOUT);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loginWith(username: string, password: string): Promise<void> {
|
||||||
|
return this.login.enterCredentials(username, password).submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
loginWithAdmin(): Promise<any> {
|
||||||
|
return this.loginWith(ADMIN_USERNAME, ADMIN_PASSWORD);
|
||||||
|
}
|
||||||
|
}
|
31
e2e/pages/logout-page.ts
Normal file
31
e2e/pages/logout-page.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { Page } from './page';
|
||||||
|
import { APP_ROUTES } from '../configs';
|
||||||
|
|
||||||
|
export class LogoutPage extends Page {
|
||||||
|
/** @override */
|
||||||
|
constructor() {
|
||||||
|
super(APP_ROUTES.LOGOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
load(): Promise<any> {
|
||||||
|
return super.load();
|
||||||
|
}
|
||||||
|
}
|
59
e2e/pages/page.ts
Normal file
59
e2e/pages/page.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { browser, element, by, ElementFinder } from 'protractor';
|
||||||
|
|
||||||
|
export abstract class Page {
|
||||||
|
private static USE_HASH_STRATEGY: boolean = true;
|
||||||
|
|
||||||
|
private locators = {
|
||||||
|
app: by.css('alfresco-content-app'),
|
||||||
|
overlay: by.css('.cdk-overlay-container'),
|
||||||
|
snackBar: by.css('simple-snack-bar')
|
||||||
|
};
|
||||||
|
|
||||||
|
public app: ElementFinder = element(this.locators.app);
|
||||||
|
public overlay: ElementFinder = element(this.locators.overlay);
|
||||||
|
public snackBar: ElementFinder = element(this.locators.snackBar);
|
||||||
|
|
||||||
|
constructor(public url: string = '') {}
|
||||||
|
|
||||||
|
get title(): Promise<string> {
|
||||||
|
return browser.getTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
load(relativeUrl: string = ''): Promise<void> {
|
||||||
|
const hash = Page.USE_HASH_STRATEGY ? '/#' : '';
|
||||||
|
const path = `${hash}${this.url}${relativeUrl}`;
|
||||||
|
|
||||||
|
return browser.get(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh(): Promise<void> {
|
||||||
|
return browser.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
isSnackBarDisplayed(): Promise<boolean> {
|
||||||
|
return this.snackBar.isDisplayed();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSnackBarMessage(): Promise<string> {
|
||||||
|
return this.isSnackBarDisplayed()
|
||||||
|
.then(() => this.snackBar.getText())
|
||||||
|
.catch(() => '');
|
||||||
|
}
|
||||||
|
}
|
20
e2e/pages/pages.ts
Normal file
20
e2e/pages/pages.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './browsing-page';
|
||||||
|
export * from './login-page';
|
||||||
|
export * from './logout-page';
|
277
e2e/suites/actions/create-folder.test.ts
Normal file
277
e2e/suites/actions/create-folder.test.ts
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { protractor, browser, by, ElementFinder } from 'protractor';
|
||||||
|
|
||||||
|
import { APP_ROUTES, BROWSER_WAIT_TIMEOUT } from '../../configs';
|
||||||
|
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
|
||||||
|
import { CreateOrEditFolderDialog } from '../../components/dialog/create-edit-folder-dialog';
|
||||||
|
import { LocalStorageUtility } from '../../utilities/local-storage';
|
||||||
|
import { RepoClient, NodeContentTree } from '../../utilities/repo-client/repo-client';
|
||||||
|
|
||||||
|
describe('Create folder', () => {
|
||||||
|
const username = 'jane.doe';
|
||||||
|
const password = 'jane.doe';
|
||||||
|
|
||||||
|
const folderName1 = 'my-folder1';
|
||||||
|
const folderName2 = 'my-folder2';
|
||||||
|
const folderDescription = 'description of my folder';
|
||||||
|
const duplicateFolderName = 'duplicate-folder-name';
|
||||||
|
const nameWithSpaces = ' folder name ';
|
||||||
|
|
||||||
|
const apis = {
|
||||||
|
admin: new RepoClient(),
|
||||||
|
user: new RepoClient(username, password)
|
||||||
|
};
|
||||||
|
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const logoutPage = new LogoutPage();
|
||||||
|
const personalFilesPage = new BrowsingPage(APP_ROUTES.PERSONAL_FILES);
|
||||||
|
const createDialog = new CreateOrEditFolderDialog();
|
||||||
|
const dataTable = personalFilesPage.dataTable;
|
||||||
|
|
||||||
|
function openCreateDialog(): any {
|
||||||
|
return personalFilesPage.sidenav
|
||||||
|
.openNewMenu()
|
||||||
|
.then((menu) => {
|
||||||
|
menu.clickMenuItem('Create folder');
|
||||||
|
})
|
||||||
|
.then(() => createDialog.waitForDialogToOpen());
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeAll(done => {
|
||||||
|
apis.admin.people.createUser(username, password)
|
||||||
|
.then(() => apis.user.nodes.createFolders([ duplicateFolderName ]))
|
||||||
|
.then(() => loginPage.load())
|
||||||
|
.then(() => loginPage.loginWith(username, password))
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(done => {
|
||||||
|
personalFilesPage.load()
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(done => {
|
||||||
|
browser.$('body').sendKeys(protractor.Key.ESCAPE).then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(done => {
|
||||||
|
Promise
|
||||||
|
.all([
|
||||||
|
apis.user.nodes.deleteNodes([
|
||||||
|
folderName1,
|
||||||
|
folderName2,
|
||||||
|
duplicateFolderName,
|
||||||
|
nameWithSpaces.trim()
|
||||||
|
]),
|
||||||
|
logoutPage.load()
|
||||||
|
.then(() => LocalStorageUtility.clear())
|
||||||
|
])
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('option is enabled when having enough permissions', () => {
|
||||||
|
personalFilesPage.sidenav.openNewMenu()
|
||||||
|
.then((menu) => {
|
||||||
|
const isEnabled = menu.getItemByLabel('Create folder').getWebElement().isEnabled();
|
||||||
|
|
||||||
|
expect(isEnabled).toBe(true, 'Create folder is not enabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates new folder with name', () => {
|
||||||
|
openCreateDialog()
|
||||||
|
.then(() => createDialog.enterName(folderName1).clickCreate())
|
||||||
|
.then(() => createDialog.waitForDialogToClose())
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(() => {
|
||||||
|
const isPresent = dataTable.getRowByContainingText(folderName1).isPresent();
|
||||||
|
expect(isPresent).toBe(true, 'Folder not displayed in list view');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates new folder with name and description', () => {
|
||||||
|
openCreateDialog()
|
||||||
|
.then(() => {
|
||||||
|
createDialog
|
||||||
|
.enterName(folderName2)
|
||||||
|
.enterDescription(folderDescription)
|
||||||
|
.clickCreate();
|
||||||
|
})
|
||||||
|
.then(() => createDialog.waitForDialogToClose())
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(() => {
|
||||||
|
const isPresent = dataTable.getRowByContainingText(folderName2).isPresent();
|
||||||
|
expect(isPresent).toBe(true, 'Folder not displayed in list view');
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
apis.user.nodes.getNodeDescription(folderName2)
|
||||||
|
.then((description) => {
|
||||||
|
expect(description).toEqual(folderDescription, 'Description is not correct');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('enabled option tooltip', () => {
|
||||||
|
personalFilesPage.sidenav.openNewMenu()
|
||||||
|
.then(menu => {
|
||||||
|
const action = browser.actions().mouseMove(menu.getItemByLabel('Create folder'));
|
||||||
|
action.perform();
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
})
|
||||||
|
.then((menu) => {
|
||||||
|
const tooltip = menu.getItemTooltip('Create folder');
|
||||||
|
expect(tooltip).toContain('Create new folder');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('option is disabled when not enough permissions', () => {
|
||||||
|
// refactor after implementing Breadcrumb automation component
|
||||||
|
const breadcrumbRoot: ElementFinder = protractor.element(by.css('.adf-breadcrumb-item[title="User Homes"]'));
|
||||||
|
|
||||||
|
browser.actions().mouseMove(breadcrumbRoot).click().perform()
|
||||||
|
.then(() => personalFilesPage.sidenav.openNewMenu())
|
||||||
|
.then(menu => {
|
||||||
|
const isEnabled = menu.getItemByLabel('Create folder').getWebElement().isEnabled();
|
||||||
|
expect(isEnabled).toBe(false, 'Create folder is not disabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disabled option tooltip', () => {
|
||||||
|
// refactor after implementing Breadcrumb automation component
|
||||||
|
const breadcrumbRoot: ElementFinder = protractor.element(by.css('.adf-breadcrumb-item[title="User Homes"]'));
|
||||||
|
|
||||||
|
browser.actions().mouseMove(breadcrumbRoot).click().perform()
|
||||||
|
.then(() => personalFilesPage.sidenav.openNewMenu())
|
||||||
|
.then(menu => {
|
||||||
|
const action = browser.actions().mouseMove(menu.getItemByLabel('Create folder'));
|
||||||
|
action.perform()
|
||||||
|
.then(() => {
|
||||||
|
const tooltip = menu.getItemTooltip('Create folder');
|
||||||
|
expect(tooltip).toContain(`You can't create a folder here`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('dialog UI elements', () => {
|
||||||
|
openCreateDialog().then(() => {
|
||||||
|
const dialogTitle = createDialog.getTitle();
|
||||||
|
const isFolderNameDisplayed = createDialog.nameInput.getWebElement().isDisplayed();
|
||||||
|
const isDescriptionDisplayed = createDialog.descriptionTextArea.getWebElement().isDisplayed();
|
||||||
|
const isCreateEnabled = createDialog.createButton.getWebElement().isEnabled();
|
||||||
|
const isCancelEnabled = createDialog.cancelButton.getWebElement().isEnabled();
|
||||||
|
|
||||||
|
expect(dialogTitle).toBe('Create new folder');
|
||||||
|
expect(isFolderNameDisplayed).toBe(true, 'Name input is not displayed');
|
||||||
|
expect(isDescriptionDisplayed).toBe(true, 'Description field is not displayed');
|
||||||
|
expect(isCreateEnabled).toBe(false, 'Create button is not disabled');
|
||||||
|
expect(isCancelEnabled).toBe(true, 'Cancel button is not enabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with empty folder name', () => {
|
||||||
|
openCreateDialog()
|
||||||
|
.then(() => {
|
||||||
|
createDialog.deleteNameWithBackspace();
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
const isCreateEnabled = createDialog.createButton.getWebElement().isEnabled();
|
||||||
|
const validationMessage = createDialog.getValidationMessage();
|
||||||
|
|
||||||
|
expect(isCreateEnabled).toBe(false, 'Create button is enabled');
|
||||||
|
expect(validationMessage).toMatch('Folder name is required');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with folder name ending with a dot "."', () => {
|
||||||
|
openCreateDialog()
|
||||||
|
.then(() => createDialog.enterName('folder-name.'))
|
||||||
|
.then((dialog) => {
|
||||||
|
const isCreateEnabled = dialog.createButton.getWebElement().isEnabled();
|
||||||
|
const validationMessage = dialog.getValidationMessage();
|
||||||
|
|
||||||
|
expect(isCreateEnabled).toBe(false, 'Create button is not disabled');
|
||||||
|
expect(validationMessage).toMatch(`Folder name can't end with a period .`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with folder name containing special characters', () => {
|
||||||
|
const namesWithSpecialChars = [ 'a*a', 'a"a', 'a<a', 'a>a', `a\\a`, 'a/a', 'a?a', 'a:a', 'a|a' ];
|
||||||
|
|
||||||
|
openCreateDialog()
|
||||||
|
.then(() => {
|
||||||
|
namesWithSpecialChars.forEach(name => {
|
||||||
|
createDialog.enterName(name);
|
||||||
|
|
||||||
|
const isCreateEnabled = createDialog.createButton.getWebElement().isEnabled();
|
||||||
|
const validationMessage = createDialog.getValidationMessage();
|
||||||
|
|
||||||
|
expect(isCreateEnabled).toBe(false, 'Create button is not disabled');
|
||||||
|
expect(validationMessage).toContain(`Folder name can't contain these characters`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with folder name containing only spaces', () => {
|
||||||
|
openCreateDialog()
|
||||||
|
.then(() => createDialog.enterName(' '))
|
||||||
|
.then((dialog) => {
|
||||||
|
const isCreateEnabled = dialog.createButton.getWebElement().isEnabled();
|
||||||
|
const validationMessage = dialog.getValidationMessage();
|
||||||
|
|
||||||
|
expect(isCreateEnabled).toBe(false, 'Create button is not disabled');
|
||||||
|
expect(validationMessage).toMatch(`Folder name can't contain only spaces`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancel folder creation', () => {
|
||||||
|
openCreateDialog()
|
||||||
|
.then(() => {
|
||||||
|
createDialog
|
||||||
|
.enterName('test')
|
||||||
|
.enterDescription('test description')
|
||||||
|
.clickCancel();
|
||||||
|
})
|
||||||
|
.then(() => expect(createDialog.component.isPresent()).not.toBe(true, 'dialog is not closed'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('duplicate folder name', () => {
|
||||||
|
openCreateDialog()
|
||||||
|
.then(() => createDialog.enterName(duplicateFolderName).clickCreate())
|
||||||
|
.then(() => {
|
||||||
|
personalFilesPage.getSnackBarMessage()
|
||||||
|
.then(message => {
|
||||||
|
expect(message).toEqual(`There's already a folder with this name. Try a different name.`);
|
||||||
|
expect(createDialog.component.isPresent()).toBe(true, 'dialog is not present');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('trim ending spaces from folder name', () => {
|
||||||
|
openCreateDialog()
|
||||||
|
.then(() => createDialog.enterName(nameWithSpaces).clickCreate())
|
||||||
|
.then(() => createDialog.waitForDialogToClose())
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(() => {
|
||||||
|
const isPresent = dataTable.getRowByContainingText(nameWithSpaces.trim()).isPresent();
|
||||||
|
expect(isPresent).toBe(true, 'Folder not displayed in list view');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
211
e2e/suites/actions/edit-folder.test.ts
Normal file
211
e2e/suites/actions/edit-folder.test.ts
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { protractor, element, browser, by, ElementFinder } from 'protractor';
|
||||||
|
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
|
||||||
|
import { APP_ROUTES, SITE_VISIBILITY, SITE_ROLES } from '../../configs';
|
||||||
|
import { RepoClient } from '../../utilities/repo-client/repo-client';
|
||||||
|
import { CreateOrEditFolderDialog } from '../../components/dialog/create-edit-folder-dialog';
|
||||||
|
import { LocalStorageUtility } from '../../utilities/local-storage';
|
||||||
|
|
||||||
|
describe('Edit folder', () => {
|
||||||
|
const username = 'jane.doe';
|
||||||
|
const password = 'jane.doe';
|
||||||
|
|
||||||
|
const folderName = 'my-folder';
|
||||||
|
const folderDescription = 'my folder description';
|
||||||
|
|
||||||
|
const folderNameToEdit = 'folder-to-be-edited';
|
||||||
|
const duplicateFolderName = 'duplicate-folder-name';
|
||||||
|
|
||||||
|
const folderNameEdited = 'edited-folder';
|
||||||
|
const folderDescriptionEdited = 'my folder description edited';
|
||||||
|
|
||||||
|
const siteName = 'site-private';
|
||||||
|
|
||||||
|
const apis = {
|
||||||
|
admin: new RepoClient(),
|
||||||
|
user: new RepoClient(username, password)
|
||||||
|
};
|
||||||
|
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const logoutPage = new LogoutPage();
|
||||||
|
const personalFilesPage = new BrowsingPage();
|
||||||
|
const editDialog = new CreateOrEditFolderDialog();
|
||||||
|
const dataTable = personalFilesPage.dataTable;
|
||||||
|
const editButton = personalFilesPage.toolbar.actions.getButtonByTitleAttribute('Edit');
|
||||||
|
|
||||||
|
beforeAll(done => {
|
||||||
|
Promise
|
||||||
|
.all([
|
||||||
|
apis.admin.people.createUser(username, password),
|
||||||
|
apis.admin.sites.createSite(siteName, SITE_VISIBILITY.PRIVATE)
|
||||||
|
.then(() => apis.admin.nodes.createFolders([ folderName ], `Sites/${siteName}/documentLibrary`))
|
||||||
|
])
|
||||||
|
.then(() => apis.admin.sites.addSiteMember(siteName, username, SITE_ROLES.SITE_CONSUMER))
|
||||||
|
.then(() => Promise.all([
|
||||||
|
apis.user.nodes.createNodeWithProperties( folderName, '', folderDescription ),
|
||||||
|
apis.user.nodes.createFolders([ folderNameToEdit, duplicateFolderName ]),
|
||||||
|
loginPage.load()
|
||||||
|
]))
|
||||||
|
.then(() => loginPage.loginWith(username, password))
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(done => {
|
||||||
|
personalFilesPage.load()
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(done => {
|
||||||
|
browser.$('body').sendKeys(protractor.Key.ESCAPE).then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(done => {
|
||||||
|
Promise
|
||||||
|
.all([
|
||||||
|
apis.admin.sites.deleteSite(siteName, true),
|
||||||
|
apis.user.nodes.deleteNodes([ folderName, folderNameEdited, duplicateFolderName ]),
|
||||||
|
logoutPage.load()
|
||||||
|
.then(() => LocalStorageUtility.clear())
|
||||||
|
])
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('button is enabled when having permissions', () => {
|
||||||
|
dataTable.clickOnRowByContainingText(folderName)
|
||||||
|
.then(() => {
|
||||||
|
expect(editButton.isEnabled()).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('dialog UI defaults', () => {
|
||||||
|
dataTable.clickOnRowByContainingText(folderName)
|
||||||
|
.then(() => editButton.click())
|
||||||
|
.then(() => {
|
||||||
|
expect(editDialog.getTitle()).toBe('Edit folder');
|
||||||
|
expect(editDialog.nameInput.getWebElement().getAttribute('value')).toBe(folderName);
|
||||||
|
expect(editDialog.descriptionTextArea.getWebElement().getAttribute('value')).toBe(folderDescription);
|
||||||
|
expect(editDialog.updateButton.getWebElement().isEnabled()).toBe(true, 'upload button is not enabled');
|
||||||
|
expect(editDialog.cancelButton.getWebElement().isEnabled()).toBe(true, 'cancel button is not enabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('folder properties are modified when pressing OK', () => {
|
||||||
|
dataTable.clickOnRowByContainingText(folderNameToEdit)
|
||||||
|
.then(() => editButton.click())
|
||||||
|
.then(() => {
|
||||||
|
editDialog
|
||||||
|
.enterName(folderNameEdited)
|
||||||
|
.enterDescription(folderDescriptionEdited)
|
||||||
|
.clickUpdate();
|
||||||
|
})
|
||||||
|
.then(() => editDialog.waitForDialogToClose())
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(() => {
|
||||||
|
const isPresent = dataTable.getRowByContainingText(folderNameEdited).isPresent();
|
||||||
|
expect(isPresent).toBe(true, 'Folder not displayed in list view');
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
apis.user.nodes.getNodeDescription(folderNameEdited)
|
||||||
|
.then((description) => {
|
||||||
|
expect(description).toEqual(folderDescriptionEdited);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('button is not displayed when not enough permissions', () => {
|
||||||
|
const fileLibrariesPage = new BrowsingPage();
|
||||||
|
|
||||||
|
fileLibrariesPage.sidenav.navigateToLinkByLabel('File Libraries')
|
||||||
|
.then(() => fileLibrariesPage.dataTable.doubleClickOnRowByContainingText(siteName))
|
||||||
|
.then(() => fileLibrariesPage.dataTable.clickOnRowByContainingText(folderName))
|
||||||
|
.then(() => {
|
||||||
|
expect(editButton.isPresent()).not.toBe(true, 'edit button is displayed');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with empty folder name', () => {
|
||||||
|
dataTable.clickOnRowByContainingText(folderName)
|
||||||
|
.then(() => editButton.click())
|
||||||
|
.then(() => {
|
||||||
|
editDialog.deleteNameWithBackspace();
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
expect(editDialog.updateButton.getWebElement().isEnabled()).toBe(false, 'upload button is not enabled');
|
||||||
|
expect(editDialog.getValidationMessage()).toMatch('Folder name is required');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with name with special characters', () => {
|
||||||
|
const namesWithSpecialChars = [ 'a*a', 'a"a', 'a<a', 'a>a', `a\\a`, 'a/a', 'a?a', 'a:a', 'a|a' ];
|
||||||
|
|
||||||
|
dataTable.clickOnRowByContainingText(folderName)
|
||||||
|
.then(() => editButton.click())
|
||||||
|
.then(() => {
|
||||||
|
namesWithSpecialChars.forEach(name => {
|
||||||
|
editDialog.enterName(name);
|
||||||
|
|
||||||
|
expect(editDialog.updateButton.getWebElement().isEnabled()).toBe(false, 'upload button is not disabled');
|
||||||
|
expect(editDialog.getValidationMessage()).toContain(`Folder name can't contain these characters`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with name ending with a dot', () => {
|
||||||
|
dataTable.clickOnRowByContainingText(folderName)
|
||||||
|
.then(() => editButton.click())
|
||||||
|
.then(() => editDialog.nameInput.sendKeys('.'))
|
||||||
|
.then(() => {
|
||||||
|
expect(editDialog.updateButton.getWebElement().isEnabled()).toBe(false, 'upload button is not enabled');
|
||||||
|
expect(editDialog.getValidationMessage()).toMatch(`Folder name can't end with a period .`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Cancel button', () => {
|
||||||
|
dataTable.clickOnRowByContainingText(folderName)
|
||||||
|
.then(() => editButton.click())
|
||||||
|
.then(() => editDialog.clickCancel())
|
||||||
|
.then(() => expect(editDialog.component.isPresent()).not.toBe(true, 'dialog is not closed'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with duplicate folder name', () => {
|
||||||
|
dataTable.clickOnRowByContainingText(folderName)
|
||||||
|
.then(() => editButton.click())
|
||||||
|
.then(() => editDialog.enterName(duplicateFolderName).clickUpdate())
|
||||||
|
.then(() => {
|
||||||
|
personalFilesPage.getSnackBarMessage()
|
||||||
|
.then(message => {
|
||||||
|
expect(message).toEqual(`There's already a folder with this name. Try a different name.`);
|
||||||
|
expect(editDialog.component.isPresent()).toBe(true, 'dialog is not present');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('trim ending spaces', () => {
|
||||||
|
dataTable.clickOnRowByContainingText(folderName)
|
||||||
|
.then(() => editButton.click())
|
||||||
|
.then(() => editDialog.nameInput.sendKeys(' '))
|
||||||
|
.then(() => editDialog.clickUpdate())
|
||||||
|
.then(() => editDialog.waitForDialogToClose())
|
||||||
|
.then(() => {
|
||||||
|
expect(personalFilesPage.snackBar.isPresent()).not.toBe(true, 'notification appears');
|
||||||
|
expect(dataTable.getRowByContainingText(folderName).isPresent()).toBe(true, 'Folder not displayed in list view');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
126
e2e/suites/application/page-titles.test.ts
Normal file
126
e2e/suites/application/page-titles.test.ts
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { browser } from 'protractor';
|
||||||
|
|
||||||
|
import { SIDEBAR_LABELS } from '../../configs';
|
||||||
|
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
|
||||||
|
import { LocalStorageUtility } from '../../utilities/local-storage';
|
||||||
|
|
||||||
|
describe('Page titles', () => {
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const logoutPage = new LogoutPage();
|
||||||
|
const page = new BrowsingPage();
|
||||||
|
|
||||||
|
xit('');
|
||||||
|
|
||||||
|
describe('on Login / Logout pages', () => {
|
||||||
|
it('on Login page', () => {
|
||||||
|
loginPage.load()
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getTitle()).toContain('Sign in');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('after logout', () => {
|
||||||
|
loginPage.load()
|
||||||
|
.then(() => loginPage.loginWithAdmin())
|
||||||
|
.then(() => page.signOut())
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getTitle()).toContain('Sign in');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('when pressing Back after Logout', () => {
|
||||||
|
loginPage.load()
|
||||||
|
.then(() => loginPage.loginWithAdmin())
|
||||||
|
.then(() => page.signOut())
|
||||||
|
.then(() => browser.driver.navigate().back())
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getTitle()).toContain('Sign in');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('on list views', () => {
|
||||||
|
beforeAll(done => {
|
||||||
|
loginPage.load()
|
||||||
|
.then(() => loginPage.loginWithAdmin())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(done => {
|
||||||
|
logoutPage.load()
|
||||||
|
.then(() => LocalStorageUtility.clear())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Personal Files page', () => {
|
||||||
|
const label = SIDEBAR_LABELS.PERSONAL_FILES;
|
||||||
|
|
||||||
|
page.sidenav.navigateToLinkByLabel(label)
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getTitle()).toContain(label);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('File Libraries page', () => {
|
||||||
|
const label = SIDEBAR_LABELS.FILE_LIBRARIES;
|
||||||
|
|
||||||
|
page.sidenav.navigateToLinkByLabel(label)
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getTitle()).toContain(label);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Shared Files page', () => {
|
||||||
|
const label = SIDEBAR_LABELS.SHARED_FILES;
|
||||||
|
|
||||||
|
page.sidenav.navigateToLinkByLabel(label)
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getTitle()).toContain(label);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Recent Files page', () => {
|
||||||
|
const label = SIDEBAR_LABELS.RECENT_FILES;
|
||||||
|
|
||||||
|
page.sidenav.navigateToLinkByLabel(label)
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getTitle()).toContain(label);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Favorites page', () => {
|
||||||
|
const label = SIDEBAR_LABELS.FAVORITES;
|
||||||
|
|
||||||
|
page.sidenav.navigateToLinkByLabel(label)
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getTitle()).toContain(label);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Trash page', () => {
|
||||||
|
const label = SIDEBAR_LABELS.TRASH;
|
||||||
|
|
||||||
|
page.sidenav.navigateToLinkByLabel(label)
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getTitle()).toContain(label);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
178
e2e/suites/authentication/login.test.ts
Normal file
178
e2e/suites/authentication/login.test.ts
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { browser } from 'protractor';
|
||||||
|
|
||||||
|
import { APP_ROUTES } from '../../configs';
|
||||||
|
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
|
||||||
|
import { LocalStorageUtility } from '../../utilities/local-storage';
|
||||||
|
import { RepoClient } from '../../utilities/repo-client/repo-client';
|
||||||
|
|
||||||
|
describe('Login', () => {
|
||||||
|
const peopleApi = new RepoClient().people;
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const logoutPage = new LogoutPage();
|
||||||
|
|
||||||
|
const testUser = {
|
||||||
|
username: 'test.user@alfness',
|
||||||
|
password: 'test.user'
|
||||||
|
};
|
||||||
|
|
||||||
|
const russianUser = {
|
||||||
|
username: 'пользователь',
|
||||||
|
password: '密碼中國'
|
||||||
|
};
|
||||||
|
|
||||||
|
const johnDoe = {
|
||||||
|
username: 'john.doe',
|
||||||
|
password: 'john.doe',
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe'
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeAll(done => {
|
||||||
|
Promise
|
||||||
|
.all([
|
||||||
|
peopleApi.createUser(testUser.username, testUser.password),
|
||||||
|
peopleApi.createUser(russianUser.username, russianUser.password),
|
||||||
|
peopleApi.createUser(johnDoe.username, johnDoe.password, {
|
||||||
|
firstName: johnDoe.firstName,
|
||||||
|
lastName: johnDoe.lastName
|
||||||
|
})
|
||||||
|
])
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(done => {
|
||||||
|
loginPage.load().then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(done => {
|
||||||
|
logoutPage.load()
|
||||||
|
.then(() => LocalStorageUtility.clear())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
xit('');
|
||||||
|
|
||||||
|
describe('with valid credentials', () => {
|
||||||
|
it('navigate to "Personal Files"', () => {
|
||||||
|
const { username, password } = johnDoe;
|
||||||
|
|
||||||
|
loginPage
|
||||||
|
.loginWith(username, password)
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`displays user's name in header`, () => {
|
||||||
|
const { userInfo } = new BrowsingPage(APP_ROUTES.PERSONAL_FILES).header;
|
||||||
|
const { username, password, firstName, lastName } = johnDoe;
|
||||||
|
|
||||||
|
loginPage
|
||||||
|
.loginWith(username, password)
|
||||||
|
.then(() => {
|
||||||
|
expect(userInfo.name).toEqual(`${firstName} ${lastName}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`logs in with user having username containing "@"`, () => {
|
||||||
|
const { username, password } = testUser;
|
||||||
|
|
||||||
|
loginPage
|
||||||
|
.loginWith(username, password)
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('logs in with user with non-latin characters', () => {
|
||||||
|
const { username, password } = russianUser;
|
||||||
|
|
||||||
|
loginPage
|
||||||
|
.loginWith(username, password)
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('redirects to Home Page when navigating to the Login page while already logged in', () => {
|
||||||
|
const { username, password } = johnDoe;
|
||||||
|
|
||||||
|
loginPage
|
||||||
|
.loginWith(username, password)
|
||||||
|
.then(() => browser.get(APP_ROUTES.LOGIN)
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('redirects to Personal Files when pressing browser Back while already logged in ', () => {
|
||||||
|
const { username, password } = johnDoe;
|
||||||
|
|
||||||
|
loginPage
|
||||||
|
.loginWith(username, password)
|
||||||
|
.then(() => browser.driver.navigate().back())
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with invalid credentials', () => {
|
||||||
|
const { login: loginComponent } = loginPage;
|
||||||
|
const { submitButton, errorMessage } = loginComponent;
|
||||||
|
|
||||||
|
it('disabled submit button when no credentials are entered', () => {
|
||||||
|
expect(submitButton.isEnabled()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disabled submit button when password is empty', () => {
|
||||||
|
loginComponent.enterUsername('any-username');
|
||||||
|
|
||||||
|
expect(submitButton.isEnabled()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disabled submit button when username is empty', () => {
|
||||||
|
loginPage.login.enterPassword('any-password');
|
||||||
|
|
||||||
|
expect(submitButton.isEnabled()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows error when entering nonexistent user', () => {
|
||||||
|
loginPage
|
||||||
|
.loginWith('nonexistent-user', 'any-password')
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.LOGIN);
|
||||||
|
expect(errorMessage.isDisplayed()).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows error when entering invalid password', () => {
|
||||||
|
const { username } = johnDoe;
|
||||||
|
|
||||||
|
loginPage
|
||||||
|
.loginWith(username, 'incorrect-password')
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.LOGIN);
|
||||||
|
expect(errorMessage.isDisplayed()).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
76
e2e/suites/authentication/logout.test.ts
Normal file
76
e2e/suites/authentication/logout.test.ts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { browser } from 'protractor';
|
||||||
|
|
||||||
|
import { APP_ROUTES, BROWSER_WAIT_TIMEOUT } from '../../configs';
|
||||||
|
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
|
||||||
|
import { LocalStorageUtility } from '../../utilities/local-storage';
|
||||||
|
import { RepoClient } from '../../utilities/repo-client/repo-client';
|
||||||
|
|
||||||
|
describe('Logout', () => {
|
||||||
|
const page = new BrowsingPage();
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const logoutPage = new LogoutPage();
|
||||||
|
|
||||||
|
const peopleApi = new RepoClient().people;
|
||||||
|
|
||||||
|
const johnDoe = {
|
||||||
|
username: 'john.doe',
|
||||||
|
password: 'john.doe'
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeAll((done) => {
|
||||||
|
peopleApi
|
||||||
|
.createUser(johnDoe.username, johnDoe.password)
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach((done) => {
|
||||||
|
loginPage.load()
|
||||||
|
.then(() => loginPage.loginWith(johnDoe.username, johnDoe.password))
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach((done) => {
|
||||||
|
logoutPage.load()
|
||||||
|
.then(() => LocalStorageUtility.clear())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('redirects to Login page, on sign out', () => {
|
||||||
|
page.signOut()
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.LOGIN);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
xit('redirects to Login page when logging out by URL', () => {
|
||||||
|
browser.get(APP_ROUTES.LOGOUT)
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.LOGIN);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('redirects to Login page when pressing browser Back after logout', () => {
|
||||||
|
page.signOut()
|
||||||
|
.then(() => browser.driver.navigate().back())
|
||||||
|
.then(() => {
|
||||||
|
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.LOGIN);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
180
e2e/suites/list-views/personal-files.test.ts
Normal file
180
e2e/suites/list-views/personal-files.test.ts
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { browser } from 'protractor';
|
||||||
|
|
||||||
|
import { APP_ROUTES } from '../../configs';
|
||||||
|
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
|
||||||
|
import { LocalStorageUtility } from '../../utilities/local-storage';
|
||||||
|
import { RepoClient, NodeContentTree } from '../../utilities/repo-client/repo-client';
|
||||||
|
|
||||||
|
describe('Personal Files', () => {
|
||||||
|
const username = 'jane.doe';
|
||||||
|
const password = 'jane.doe';
|
||||||
|
|
||||||
|
const apis = {
|
||||||
|
admin: new RepoClient(),
|
||||||
|
user: new RepoClient(username, password)
|
||||||
|
};
|
||||||
|
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const logoutPage = new LogoutPage();
|
||||||
|
const personalFilesPage = new BrowsingPage(APP_ROUTES.PERSONAL_FILES);
|
||||||
|
const dataTable = personalFilesPage.dataTable;
|
||||||
|
|
||||||
|
const adminContent: NodeContentTree = {
|
||||||
|
name: 'admin-folder'
|
||||||
|
};
|
||||||
|
|
||||||
|
const userContent: NodeContentTree = {
|
||||||
|
name: 'user-folder',
|
||||||
|
files: [ 'user-file.txt' ]
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeAll(done => {
|
||||||
|
Promise
|
||||||
|
.all([
|
||||||
|
apis.admin.people.createUser(username, password),
|
||||||
|
apis.admin.nodes.createContent(adminContent)
|
||||||
|
])
|
||||||
|
.then(() => apis.user.nodes.createContent(userContent))
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(done => {
|
||||||
|
Promise
|
||||||
|
.all([
|
||||||
|
apis.admin.nodes.deleteNodes([ adminContent.name ]),
|
||||||
|
apis.user.nodes.deleteNodes([ userContent.name ])
|
||||||
|
])
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
xit('');
|
||||||
|
|
||||||
|
describe(`Admin user's personal files`, () => {
|
||||||
|
beforeAll(done => {
|
||||||
|
loginPage.load()
|
||||||
|
.then(() => loginPage.loginWithAdmin())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(done => {
|
||||||
|
personalFilesPage.load()
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(done => {
|
||||||
|
logoutPage.load()
|
||||||
|
.then(() => LocalStorageUtility.clear())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has "Data Dictionary" folder', () => {
|
||||||
|
expect(dataTable.getRowByContainingText('Data Dictionary').isPresent()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has created content', () => {
|
||||||
|
expect(dataTable.getRowByContainingText('admin-folder').isPresent()).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe(`Regular user's personal files`, () => {
|
||||||
|
beforeAll(done => {
|
||||||
|
loginPage.load()
|
||||||
|
.then(() => loginPage.loginWith(username, password))
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(done => {
|
||||||
|
personalFilesPage.load()
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(done => {
|
||||||
|
logoutPage.load()
|
||||||
|
.then(() => LocalStorageUtility.clear())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has the right column count', () => {
|
||||||
|
expect(dataTable.getColumnHeaders().count()).toBe(5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has the right columns', () => {
|
||||||
|
const labels = [ 'Name', 'Size', 'Modified', 'Modified by' ];
|
||||||
|
const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label));
|
||||||
|
|
||||||
|
elements.forEach((element, index) => {
|
||||||
|
expect(element.isPresent()).toBe(true, `"${labels[index]}" is missing`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has default sorted column', () => {
|
||||||
|
expect(dataTable.getSortedColumnHeader().getText()).toBe('Modified');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has user created content', () => {
|
||||||
|
expect(dataTable.getRowByContainingText('user-folder').isPresent())
|
||||||
|
.toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to folder', () => {
|
||||||
|
const getNodeIdPromise = apis.user.nodes
|
||||||
|
.getNodeByPath('/user-folder')
|
||||||
|
.then(response => response.data.entry.id);
|
||||||
|
|
||||||
|
const navigatePromise = dataTable
|
||||||
|
.doubleClickOnRowByContainingText('user-folder')
|
||||||
|
.then(() => dataTable.waitForHeader());
|
||||||
|
|
||||||
|
Promise
|
||||||
|
.all([
|
||||||
|
getNodeIdPromise,
|
||||||
|
navigatePromise
|
||||||
|
])
|
||||||
|
.then(([ nodeId ]) => {
|
||||||
|
expect(browser.getCurrentUrl())
|
||||||
|
.toContain(nodeId, 'Node ID is not in the URL');
|
||||||
|
|
||||||
|
expect(dataTable.getRowByContainingText('user-file.txt').isPresent())
|
||||||
|
.toBe(true, '"user-file.txt" is missing');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Some tests regarding selection, breadcrumb and toolbar
|
||||||
|
// probably they can be move to a different suite
|
||||||
|
describe('Item selection', () => {
|
||||||
|
it('has toolbar when selected', done => {
|
||||||
|
const { actions } = personalFilesPage.toolbar;
|
||||||
|
|
||||||
|
dataTable
|
||||||
|
.clickOnRowByContainingText('user-folder')
|
||||||
|
.then(() => {
|
||||||
|
expect(actions.isEmpty()).toBe(false, 'Toolbar to be present');
|
||||||
|
})
|
||||||
|
.then(() => actions.openMoreMenu())
|
||||||
|
.then(menu => {
|
||||||
|
expect(menu.items.count()).toBeGreaterThan(0, 'More actions has items');
|
||||||
|
})
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
124
e2e/suites/navigation/side-navigation.test.ts
Normal file
124
e2e/suites/navigation/side-navigation.test.ts
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { browser } from 'protractor';
|
||||||
|
|
||||||
|
import { APP_ROUTES, SIDEBAR_LABELS } from '../../configs';
|
||||||
|
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
|
||||||
|
import { LocalStorageUtility } from '../../utilities/local-storage';
|
||||||
|
|
||||||
|
describe('Side navigation', () => {
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const logoutPage = new LogoutPage();
|
||||||
|
const page = new BrowsingPage();
|
||||||
|
|
||||||
|
beforeAll(done => {
|
||||||
|
loginPage.load()
|
||||||
|
.then(() => loginPage.loginWithAdmin())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(done => {
|
||||||
|
page.dataTable.wait().then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(done => {
|
||||||
|
logoutPage.load()
|
||||||
|
.then(() => LocalStorageUtility.clear())
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has "Personal Files" as default', () => {
|
||||||
|
expect(browser.getCurrentUrl())
|
||||||
|
.toContain(APP_ROUTES.PERSONAL_FILES);
|
||||||
|
|
||||||
|
expect(page.sidenav.isActiveByLabel('Personal Files'))
|
||||||
|
.toBe(true, 'Active link');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to "File Libraries"', () => {
|
||||||
|
const { sidenav, dataTable } = page;
|
||||||
|
|
||||||
|
sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.FILE_LIBRARIES)
|
||||||
|
.then(() => dataTable.wait())
|
||||||
|
.then(() => browser.getCurrentUrl())
|
||||||
|
.then(url => {
|
||||||
|
expect(url).toContain(APP_ROUTES.FILE_LIBRARIES);
|
||||||
|
expect(sidenav.isActiveByLabel(SIDEBAR_LABELS.FILE_LIBRARIES)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to "Personal Files"', () => {
|
||||||
|
const { sidenav, dataTable } = page;
|
||||||
|
|
||||||
|
sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.PERSONAL_FILES)
|
||||||
|
.then(() => dataTable.wait())
|
||||||
|
.then(() => browser.getCurrentUrl())
|
||||||
|
.then(url => {
|
||||||
|
expect(url).toContain(APP_ROUTES.PERSONAL_FILES);
|
||||||
|
expect(sidenav.isActiveByLabel(SIDEBAR_LABELS.PERSONAL_FILES)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to "Shared Files"', () => {
|
||||||
|
const { sidenav, dataTable } = page;
|
||||||
|
|
||||||
|
sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.SHARED_FILES)
|
||||||
|
.then(() => dataTable.wait())
|
||||||
|
.then(() => browser.getCurrentUrl())
|
||||||
|
.then(url => {
|
||||||
|
expect(url).toContain(APP_ROUTES.SHARED_FILES);
|
||||||
|
expect(sidenav.isActiveByLabel(SIDEBAR_LABELS.SHARED_FILES)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to "Recent Files"', () => {
|
||||||
|
const { sidenav, dataTable } = page;
|
||||||
|
|
||||||
|
sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.RECENT_FILES)
|
||||||
|
.then(() => dataTable.wait())
|
||||||
|
.then(() => browser.getCurrentUrl())
|
||||||
|
.then(url => {
|
||||||
|
expect(url).toContain(APP_ROUTES.RECENT_FILES);
|
||||||
|
expect(sidenav.isActiveByLabel(SIDEBAR_LABELS.RECENT_FILES)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to "Favorites"', () => {
|
||||||
|
const { sidenav, dataTable } = page;
|
||||||
|
|
||||||
|
sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.FAVORITES)
|
||||||
|
.then(() => dataTable.wait())
|
||||||
|
.then(() => browser.getCurrentUrl())
|
||||||
|
.then(url => {
|
||||||
|
expect(url).toContain(APP_ROUTES.FAVORITES);
|
||||||
|
expect(sidenav.isActiveByLabel(SIDEBAR_LABELS.FAVORITES)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to "Trash"', () => {
|
||||||
|
const { sidenav, dataTable } = page;
|
||||||
|
|
||||||
|
sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.TRASH)
|
||||||
|
.then(() => dataTable.wait())
|
||||||
|
.then(() => browser.getCurrentUrl())
|
||||||
|
.then(url => {
|
||||||
|
expect(url).toContain(APP_ROUTES.TRASHCAN);
|
||||||
|
expect(sidenav.isActiveByLabel(SIDEBAR_LABELS.TRASH)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
169
e2e/suites/pagination/pagination.test.ts
Normal file
169
e2e/suites/pagination/pagination.test.ts
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { browser } from 'protractor';
|
||||||
|
|
||||||
|
import { APP_ROUTES } from '../../configs';
|
||||||
|
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
|
||||||
|
import { LocalStorageUtility } from '../../utilities/local-storage';
|
||||||
|
import { RepoClient, NodeContentTree } from '../../utilities/repo-client/repo-client';
|
||||||
|
|
||||||
|
describe('Pagination', () => {
|
||||||
|
const username = 'jane.doe';
|
||||||
|
const password = 'jane.doe';
|
||||||
|
|
||||||
|
const apis = {
|
||||||
|
admin: new RepoClient(),
|
||||||
|
user: new RepoClient(username, password)
|
||||||
|
};
|
||||||
|
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const logoutPage = new LogoutPage();
|
||||||
|
|
||||||
|
beforeAll(done => {
|
||||||
|
apis.admin.people
|
||||||
|
.createUser(username, password)
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
xit('');
|
||||||
|
|
||||||
|
describe(`on Personal Files`, () => {
|
||||||
|
const personalFilesPage = new BrowsingPage(APP_ROUTES.PERSONAL_FILES);
|
||||||
|
const { dataTable, pagination } = personalFilesPage;
|
||||||
|
|
||||||
|
// Generate files
|
||||||
|
const content: NodeContentTree = {
|
||||||
|
name: 'user-folder',
|
||||||
|
files: Array(101)
|
||||||
|
.fill('file')
|
||||||
|
.map((name, index): string => `${name}-${index + 1}.txt`)
|
||||||
|
};
|
||||||
|
|
||||||
|
const { nodes: nodesApi } = apis.user;
|
||||||
|
|
||||||
|
beforeAll(done => {
|
||||||
|
nodesApi.createContent(content)
|
||||||
|
.then(() => loginPage.load())
|
||||||
|
.then(() => loginPage.loginWith(username, password))
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(done => {
|
||||||
|
personalFilesPage
|
||||||
|
.load()
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(() => dataTable.doubleClickOnRowByContainingText(content.name))
|
||||||
|
.then(() => dataTable.sortByColumn('Name'))
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(done => {
|
||||||
|
logoutPage
|
||||||
|
.load()
|
||||||
|
.then(() => LocalStorageUtility.clear())
|
||||||
|
.then(() => nodesApi.deleteNodes([ content.name ]))
|
||||||
|
.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has default details', () => {
|
||||||
|
expect(pagination.range.getText()).toContain('1-25 of 101', 'Range');
|
||||||
|
expect(pagination.maxItems.getText()).toContain('25', 'Items per page');
|
||||||
|
expect(pagination.currentPage.getText()).toContain('Page 1', 'Current page');
|
||||||
|
expect(pagination.totalPages.getText()).toContain('of 5', 'Total pages');
|
||||||
|
expect(pagination.previousButton.isEnabled()).toBe(false, 'Previous button');
|
||||||
|
expect(pagination.nextButton.isEnabled()).toBe(true, 'Next button');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has page sizes', () => {
|
||||||
|
pagination.openMaxItemsMenu()
|
||||||
|
.then(menu => {
|
||||||
|
const [ first, second, third ] = [1, 2, 3]
|
||||||
|
.map(nth => menu.getNthItem(nth).getText());
|
||||||
|
|
||||||
|
expect(first).toBe('25', 'Items per page');
|
||||||
|
expect(second).toBe('50', 'Items per page');
|
||||||
|
expect(third).toBe('100', 'Items per page');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('changes the page size', () => {
|
||||||
|
pagination.openMaxItemsMenu()
|
||||||
|
.then(menu => menu.clickMenuItem('50'))
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(() => {
|
||||||
|
expect(pagination.maxItems.getText()).toContain('50', 'Items per page');
|
||||||
|
expect(pagination.totalPages.getText()).toContain('of 3', 'Total pages');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has page items', () => {
|
||||||
|
pagination.openCurrentPageMenu()
|
||||||
|
.then(menu => {
|
||||||
|
expect(menu.items.count()).toBe(5);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('changes the current page from menu', () => {
|
||||||
|
pagination.openCurrentPageMenu()
|
||||||
|
.then(menu => menu.clicktNthItem(3))
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(() => {
|
||||||
|
expect(pagination.range.getText()).toContain('51-75 of 101', 'Range');
|
||||||
|
expect(pagination.currentPage.getText()).toContain('Page 3', 'Current page');
|
||||||
|
expect(pagination.previousButton.isEnabled()).toBe(true, 'Previous button');
|
||||||
|
expect(pagination.nextButton.isEnabled()).toBe(true, 'Next button');
|
||||||
|
expect(dataTable.getRowByContainingText('file-60.txt').isPresent())
|
||||||
|
.toBe(true, 'File not found on page');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to next page', () => {
|
||||||
|
pagination.nextButton.click()
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(() => {
|
||||||
|
expect(pagination.range.getText()).toContain('26-50 of 101', 'Range');
|
||||||
|
expect(dataTable.getRowByContainingText('file-30.txt').isPresent())
|
||||||
|
.toBe(true, 'File not found on page');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to previous page', () => {
|
||||||
|
pagination.openCurrentPageMenu()
|
||||||
|
.then(menu => menu.clicktNthItem(2))
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(() => pagination.previousButton.click())
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(() => {
|
||||||
|
expect(pagination.range.getText()).toContain('1-25 of 101', 'Range');
|
||||||
|
expect(dataTable.getRowByContainingText('file-12.txt').isPresent())
|
||||||
|
.toBe(true, 'File not found on page');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has one item on the last page', () => {
|
||||||
|
pagination.openCurrentPageMenu()
|
||||||
|
.then(menu => menu.clicktNthItem(5))
|
||||||
|
.then(() => dataTable.waitForHeader())
|
||||||
|
.then(() => {
|
||||||
|
expect(dataTable.countRows()).toBe(1, 'Single item on the last page');
|
||||||
|
expect(pagination.currentPage.getText()).toContain('Page 5', 'Last page');
|
||||||
|
expect(pagination.nextButton.isEnabled()).toBe(false, 'Next button is not enabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
34
e2e/utilities/local-storage.ts
Normal file
34
e2e/utilities/local-storage.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { browser } from 'protractor';
|
||||||
|
|
||||||
|
declare var window;
|
||||||
|
|
||||||
|
export class LocalStorageUtility {
|
||||||
|
static clear(): Promise<any> {
|
||||||
|
return browser.executeScript(() => {
|
||||||
|
return window.localStorage.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static getTicket(): Promise<any> {
|
||||||
|
return browser.executeScript(() => {
|
||||||
|
return window.localStorage.getItem('ticket-ECM');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
30
e2e/utilities/repo-client/apis/nodes/node-body-create.ts
Normal file
30
e2e/utilities/repo-client/apis/nodes/node-body-create.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const NODE_TYPE_FILE = 'cm:content';
|
||||||
|
export const NODE_TYPE_FOLDER = 'cm:folder';
|
||||||
|
export const NODE_TITLE = 'cm:title';
|
||||||
|
export const NODE_DESCRIPTION = 'cm:description';
|
||||||
|
|
||||||
|
export class NodeBodyCreate {
|
||||||
|
constructor(
|
||||||
|
public name: string,
|
||||||
|
public nodeType: string,
|
||||||
|
public relativePath: string = '/',
|
||||||
|
public properties?: any[]
|
||||||
|
) {}
|
||||||
|
}
|
77
e2e/utilities/repo-client/apis/nodes/node-content-tree.ts
Normal file
77
e2e/utilities/repo-client/apis/nodes/node-content-tree.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { NodeBodyCreate, NODE_TYPE_FILE, NODE_TYPE_FOLDER, NODE_TITLE, NODE_DESCRIPTION } from './node-body-create';
|
||||||
|
|
||||||
|
export interface NodeContentTree {
|
||||||
|
name?: string;
|
||||||
|
files?: string[];
|
||||||
|
folders?: (string|NodeContentTree)[];
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function flattenNodeContentTree(content: NodeContentTree, relativePath: string = '/'): NodeBodyCreate[] {
|
||||||
|
const { name, files, folders, title, description } = content;
|
||||||
|
let data: NodeBodyCreate[] = [];
|
||||||
|
let properties: any;
|
||||||
|
|
||||||
|
properties = {
|
||||||
|
[NODE_TITLE]: title,
|
||||||
|
[NODE_DESCRIPTION]: description
|
||||||
|
};
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
data = data.concat([{
|
||||||
|
nodeType: NODE_TYPE_FOLDER,
|
||||||
|
name,
|
||||||
|
relativePath,
|
||||||
|
properties
|
||||||
|
}]);
|
||||||
|
|
||||||
|
relativePath = (relativePath === '/')
|
||||||
|
? `/${name}`
|
||||||
|
: `${relativePath}/${name}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (folders) {
|
||||||
|
const foldersData: NodeBodyCreate[] = folders
|
||||||
|
.map((folder: (string|NodeContentTree)): NodeBodyCreate[] => {
|
||||||
|
const folderData: NodeContentTree = (typeof folder === 'string')
|
||||||
|
? { name: folder }
|
||||||
|
: folder;
|
||||||
|
|
||||||
|
return flattenNodeContentTree(folderData, relativePath);
|
||||||
|
})
|
||||||
|
.reduce((nodesData: NodeBodyCreate[], folderData: NodeBodyCreate[]) => nodesData.concat(folderData), []);
|
||||||
|
|
||||||
|
data = data.concat(foldersData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (files) {
|
||||||
|
const filesData: NodeBodyCreate[] = files
|
||||||
|
.map((filename: string): NodeBodyCreate => ({
|
||||||
|
nodeType: NODE_TYPE_FILE,
|
||||||
|
name: filename,
|
||||||
|
relativePath
|
||||||
|
}));
|
||||||
|
|
||||||
|
data = data.concat(filesData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
96
e2e/utilities/repo-client/apis/nodes/nodes-api.ts
Normal file
96
e2e/utilities/repo-client/apis/nodes/nodes-api.ts
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { RepoApi } from '../repo-api';
|
||||||
|
import { NodeBodyCreate, NODE_TYPE_FILE, NODE_TYPE_FOLDER } from './node-body-create';
|
||||||
|
import { NodeContentTree, flattenNodeContentTree } from './node-content-tree';
|
||||||
|
|
||||||
|
export class NodesApi extends RepoApi {
|
||||||
|
// nodes
|
||||||
|
getNodeByPath(relativePath: string = '/'): Promise<any> {
|
||||||
|
return this
|
||||||
|
.get(`/nodes/-my-`, { parameters: { relativePath } })
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
getNodeById(id: string): Promise<any> {
|
||||||
|
return this
|
||||||
|
.get(`/nodes/${id}`)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteNodeById(id: string): Promise<any> {
|
||||||
|
return this
|
||||||
|
.delete(`/nodes/${id}`)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteNodeByPath(path: string): Promise<any> {
|
||||||
|
return this
|
||||||
|
.getNodeByPath(path)
|
||||||
|
.then((response: any): string => response.data.entry.id)
|
||||||
|
.then((id: string): any => this.deleteNodeById(id))
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
getNodeDescription(name: string): Promise<string> {
|
||||||
|
let description = 'cm:description';
|
||||||
|
|
||||||
|
return this
|
||||||
|
.getNodeByPath(name)
|
||||||
|
.then((response: any): string => response.data.entry.properties[description])
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteNodes(names: string[], relativePath: string = ''): Promise<any> {
|
||||||
|
const deletions = names
|
||||||
|
.map((name: string): any => {
|
||||||
|
return this.deleteNodeByPath(`${relativePath}/${name}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(deletions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// children
|
||||||
|
getNodeChildren(nodeId: string): Promise<any> {
|
||||||
|
return this
|
||||||
|
.get(`/nodes/${nodeId}/children`)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
createChildren(data: NodeBodyCreate[]): Promise<any> {
|
||||||
|
return this
|
||||||
|
.post(`/nodes/-my-/children`, { data })
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
createContent(content: NodeContentTree, relativePath: string = '/'): Promise<any> {
|
||||||
|
return this.createChildren(flattenNodeContentTree(content, relativePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
createNodeWithProperties(name: string, title?: string, description?: string, relativePath: string = '/'): Promise<any> {
|
||||||
|
return this.createContent({ name, title, description }, relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
createFolders(names: string[], relativePath: string = '/'): Promise<any> {
|
||||||
|
return this.createContent({ folders: names }, relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
createFiles(names: string[], relativePath: string = '/'): Promise<any> {
|
||||||
|
return this.createContent({ files: names }, relativePath);
|
||||||
|
}
|
||||||
|
}
|
35
e2e/utilities/repo-client/apis/people/people-api-models.ts
Normal file
35
e2e/utilities/repo-client/apis/people/people-api-models.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class Person {
|
||||||
|
id?: string;
|
||||||
|
password?: string;
|
||||||
|
firstName?: string;
|
||||||
|
lastName?: string;
|
||||||
|
email?: string;
|
||||||
|
properties?: any;
|
||||||
|
|
||||||
|
constructor(username: string, password: string, details: Person) {
|
||||||
|
this.id = username;
|
||||||
|
this.password = password || username;
|
||||||
|
this.firstName = username;
|
||||||
|
this.lastName = username;
|
||||||
|
this.email = `${username}@alfresco.com`;
|
||||||
|
|
||||||
|
Object.assign(this, details);
|
||||||
|
}
|
||||||
|
}
|
52
e2e/utilities/repo-client/apis/people/people-api.ts
Normal file
52
e2e/utilities/repo-client/apis/people/people-api.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { RepoApi } from '../repo-api';
|
||||||
|
import { Person } from './people-api-models';
|
||||||
|
|
||||||
|
export class PeopleApi extends RepoApi {
|
||||||
|
getUser(username: string) {
|
||||||
|
return this
|
||||||
|
.get(`/people/${username}`)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateUser(username: string, details?: Person): Promise<any> {
|
||||||
|
if (details.id) {
|
||||||
|
delete details.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
.put(`/people/${username}`, { data: details })
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
createUser(username: string, password: string, details?: Person): Promise<any> {
|
||||||
|
const person: Person = new Person(username, password, details);
|
||||||
|
const onSuccess = (response) => response;
|
||||||
|
const onError = (response) => {
|
||||||
|
return (response.statusCode === 409)
|
||||||
|
? Promise.resolve(this.updateUser(username, person))
|
||||||
|
: Promise.reject(response);
|
||||||
|
};
|
||||||
|
|
||||||
|
return this
|
||||||
|
.post(`/people`, { data: person })
|
||||||
|
.then(onSuccess, onError)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
}
|
63
e2e/utilities/repo-client/apis/repo-api.ts
Normal file
63
e2e/utilities/repo-client/apis/repo-api.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { RestClient, RestClientArgs, RestClientResponse } from '../../rest-client/rest-client';
|
||||||
|
import { RepoClientAuth, RepoClientConfig } from '../repo-client-models';
|
||||||
|
|
||||||
|
export abstract class RepoApi {
|
||||||
|
private client: RestClient;
|
||||||
|
private defaults: RepoClientConfig = new RepoClientConfig();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
auth: RepoClientAuth = new RepoClientAuth(),
|
||||||
|
private config?: RepoClientConfig
|
||||||
|
) {
|
||||||
|
const { username, password } = auth;
|
||||||
|
|
||||||
|
this.client = new RestClient(username, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createEndpointUri(endpoint: string): string {
|
||||||
|
const { defaults, config } = this;
|
||||||
|
const { host, tenant } = Object.assign(defaults, config);
|
||||||
|
|
||||||
|
return `${host}/alfresco/api/${tenant}/public/alfresco/versions/1${endpoint}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected handleError(response: RestClientResponse) {
|
||||||
|
const { request: { method, path, data }, data: error } = response;
|
||||||
|
|
||||||
|
console.log(`ERROR on ${method}\n${path}\n${data}`);
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected get(endpoint: string, args: RestClientArgs = {}) {
|
||||||
|
return this.client.get(this.createEndpointUri(endpoint), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected post(endpoint: string, args: RestClientArgs = {}) {
|
||||||
|
return this.client.post(this.createEndpointUri(endpoint), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected put(endpoint: string, args: RestClientArgs = {}) {
|
||||||
|
return this.client.put(this.createEndpointUri(endpoint), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected delete(endpoint: string, args: RestClientArgs = {}) {
|
||||||
|
return this.client.delete(this.createEndpointUri(endpoint), args);
|
||||||
|
}
|
||||||
|
}
|
34
e2e/utilities/repo-client/apis/sites/sites-api-models.ts
Normal file
34
e2e/utilities/repo-client/apis/sites/sites-api-models.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { SITE_VISIBILITY } from '../../../../configs';
|
||||||
|
|
||||||
|
export class Site {
|
||||||
|
title?: string;
|
||||||
|
visibility?: string = SITE_VISIBILITY.PUBLIC;
|
||||||
|
id?: string;
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
constructor(title: string, visibility: string, details: Site) {
|
||||||
|
this.title = title;
|
||||||
|
this.visibility = visibility;
|
||||||
|
this.id = title;
|
||||||
|
this.description = `${title} description`;
|
||||||
|
|
||||||
|
Object.assign(this, details);
|
||||||
|
}
|
||||||
|
}
|
84
e2e/utilities/repo-client/apis/sites/sites-api.ts
Normal file
84
e2e/utilities/repo-client/apis/sites/sites-api.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { RepoApi } from '../repo-api';
|
||||||
|
import { Site } from './sites-api-models';
|
||||||
|
|
||||||
|
export class SitesApi extends RepoApi {
|
||||||
|
getSite(id: string) {
|
||||||
|
return this
|
||||||
|
.get(`/sites/${id}`)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSite(id: string, details?: Site): Promise<any> {
|
||||||
|
if (details.id) {
|
||||||
|
delete details.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
.put(`/sites/${id}`, { data: details })
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
createSite(title: string, visibility: string, details?: Site): Promise<any> {
|
||||||
|
const site: Site = new Site(title, visibility, details);
|
||||||
|
const onSuccess = (response) => response;
|
||||||
|
const onError = (response) => {
|
||||||
|
return (response.statusCode === 409)
|
||||||
|
? Promise.resolve(this.updateSite(site.id, site))
|
||||||
|
: Promise.reject(response);
|
||||||
|
};
|
||||||
|
|
||||||
|
return this
|
||||||
|
.post(`/sites`, { data: site })
|
||||||
|
.then(onSuccess, onError)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteSite(id: string, permanent: boolean = true): Promise<any> {
|
||||||
|
return this
|
||||||
|
.delete(`/sites/${id}?permanent=${permanent}`)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSiteMember(siteId: string, userId: string, role: string): Promise<any> {
|
||||||
|
return this
|
||||||
|
.put(`/sites/${siteId}/members/${userId}`, { data: { role } })
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
addSiteMember(siteId: string, userId: string, role: string): Promise<any> {
|
||||||
|
const onSuccess = (response) => response;
|
||||||
|
const onError = (response) => {
|
||||||
|
return (response.statusCode === 409)
|
||||||
|
? Promise.resolve(this.updateSiteMember(siteId, userId, role))
|
||||||
|
: Promise.reject(response);
|
||||||
|
};
|
||||||
|
|
||||||
|
return this
|
||||||
|
.post(`/sites/${siteId}/members`, { data: { role, id: userId } })
|
||||||
|
.then(onSuccess, onError)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteSiteMember(siteId: string, userId: string): Promise<any> {
|
||||||
|
return this
|
||||||
|
.delete(`/sites/${siteId}/members/${userId}`)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
}
|
38
e2e/utilities/repo-client/repo-client-models.ts
Normal file
38
e2e/utilities/repo-client/repo-client-models.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 {
|
||||||
|
ADMIN_USERNAME,
|
||||||
|
ADMIN_PASSWORD,
|
||||||
|
REPO_API_HOST,
|
||||||
|
REPO_API_TENANT
|
||||||
|
} from '../../configs';
|
||||||
|
|
||||||
|
export class RepoClientAuth {
|
||||||
|
static DEFAULT_USERNAME: string = ADMIN_USERNAME;
|
||||||
|
static DEFAULT_PASSWORD: string = ADMIN_PASSWORD;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public username: string = RepoClientAuth.DEFAULT_USERNAME,
|
||||||
|
public password: string = RepoClientAuth.DEFAULT_PASSWORD
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RepoClientConfig {
|
||||||
|
host?: string = REPO_API_HOST;
|
||||||
|
tenant?: string = REPO_API_TENANT;
|
||||||
|
}
|
45
e2e/utilities/repo-client/repo-client.ts
Normal file
45
e2e/utilities/repo-client/repo-client.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { RepoClientAuth, RepoClientConfig } from './repo-client-models';
|
||||||
|
|
||||||
|
import { PeopleApi } from './apis/people/people-api';
|
||||||
|
import { NodesApi } from './apis/nodes/nodes-api';
|
||||||
|
import { SitesApi } from './apis/sites/sites-api';
|
||||||
|
|
||||||
|
export class RepoClient {
|
||||||
|
public people: PeopleApi = new PeopleApi(this.auth, this.config);
|
||||||
|
public nodes: NodesApi = new NodesApi(this.auth, this.config);
|
||||||
|
public sites: SitesApi = new SitesApi(this.auth, this.config);
|
||||||
|
// public favorites: FavoritesApi = new FavoritesApi(this.auth, this.config);
|
||||||
|
// public shared: SharedLinksApi = new SharedLinksApi(this.auth, this.config);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private username: string = RepoClientAuth.DEFAULT_USERNAME,
|
||||||
|
private password: string = RepoClientAuth.DEFAULT_PASSWORD,
|
||||||
|
private config?: RepoClientConfig
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private get auth(): RepoClientAuth {
|
||||||
|
const { username, password } = this;
|
||||||
|
return { username, password };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from './apis/nodes/node-body-create';
|
||||||
|
export * from './apis/nodes/node-content-tree';
|
||||||
|
export * from './apis/nodes/nodes-api';
|
71
e2e/utilities/reporters/console/console-logger.ts
Normal file
71
e2e/utilities/reporters/console/console-logger.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
const chalk = require('chalk');
|
||||||
|
/* tslint:enable */
|
||||||
|
|
||||||
|
export const log = {
|
||||||
|
i: 0,
|
||||||
|
|
||||||
|
get indentation(): string {
|
||||||
|
return new Array(this.i).fill(' ').join('');
|
||||||
|
},
|
||||||
|
|
||||||
|
indent() {
|
||||||
|
this.i++;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
dedent() {
|
||||||
|
this.i--;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
log(message: string = '', options: any = { ignoreIndentation: false }) {
|
||||||
|
const indentation = (!options.ignoreIndentation)
|
||||||
|
? this.indentation
|
||||||
|
: '';
|
||||||
|
|
||||||
|
console.log(`${indentation}${message}`);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
blank() {
|
||||||
|
return this.log();
|
||||||
|
},
|
||||||
|
|
||||||
|
info(message: string = '', options: any = { bold: false, title: false }) {
|
||||||
|
const { bold } = options;
|
||||||
|
const style = (bold ? chalk.bold : chalk).gray;
|
||||||
|
|
||||||
|
return this.log(style(message), options);
|
||||||
|
},
|
||||||
|
|
||||||
|
success(message: string = '', options: any = { bold: false }) {
|
||||||
|
const style = options.bold ? chalk.bold.green : chalk.green;
|
||||||
|
|
||||||
|
return this.log(style(message), options);
|
||||||
|
},
|
||||||
|
|
||||||
|
error(message: string = '', options: any = { bold: false }) {
|
||||||
|
const style = options.bold ? chalk.bold.red : chalk.red;
|
||||||
|
|
||||||
|
return this.log(style(message), options);
|
||||||
|
}
|
||||||
|
};
|
82
e2e/utilities/reporters/console/console.ts
Normal file
82
e2e/utilities/reporters/console/console.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { log } from './console-logger';
|
||||||
|
|
||||||
|
const errors = [];
|
||||||
|
|
||||||
|
export const consoleReporter = {
|
||||||
|
jasmineStarted(suiteInfo) {
|
||||||
|
log.blank().info(
|
||||||
|
`Running ${suiteInfo.totalSpecsDefined} tests`,
|
||||||
|
{ bold: true, title: true }
|
||||||
|
).blank();
|
||||||
|
},
|
||||||
|
|
||||||
|
suiteStarted(suite) {
|
||||||
|
log.info(suite.description).indent();
|
||||||
|
},
|
||||||
|
|
||||||
|
specDone: (spec) => {
|
||||||
|
const {
|
||||||
|
status,
|
||||||
|
description,
|
||||||
|
failedExpectations
|
||||||
|
} = spec;
|
||||||
|
|
||||||
|
if (status === 'passed') {
|
||||||
|
log.success(`∙ ${description}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status === 'failed') {
|
||||||
|
log.error(`✕ ${description}`, { bold: true });
|
||||||
|
|
||||||
|
errors.push(spec);
|
||||||
|
|
||||||
|
failedExpectations.forEach((failed) => {
|
||||||
|
log.error(` ${failed.message}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
suiteDone: (result) => {
|
||||||
|
log.dedent();
|
||||||
|
},
|
||||||
|
|
||||||
|
jasmineDone: (result) => {
|
||||||
|
if (!!errors.length) {
|
||||||
|
log .blank()
|
||||||
|
.blank()
|
||||||
|
.info(`${errors.length} failing tests`, { bold: true, title: true });
|
||||||
|
|
||||||
|
errors.forEach(error => {
|
||||||
|
log .blank()
|
||||||
|
.error(`✕ ${error.fullName}`, { bold: true });
|
||||||
|
|
||||||
|
error.failedExpectations.forEach(failed => {
|
||||||
|
log .info(`${failed.message}`)
|
||||||
|
.blank()
|
||||||
|
.error(`${failed.stack}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
log.success(`All tests passed!`, { bold: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
log.blank().blank();
|
||||||
|
}
|
||||||
|
};
|
55
e2e/utilities/rest-client/rest-client-models.ts
Normal file
55
e2e/utilities/rest-client/rest-client-models.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface RequestConfig {
|
||||||
|
timeout?: number;
|
||||||
|
noDelay?: boolean;
|
||||||
|
keepAlive?: boolean;
|
||||||
|
keepAliveDelay?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ResponseConfig {
|
||||||
|
timeout?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ResponseRequest {
|
||||||
|
method: string;
|
||||||
|
path: string;
|
||||||
|
data: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NodeRestClient {
|
||||||
|
get(uri: string, callback: Function): Function;
|
||||||
|
post(uri: string, callback: Function): Function;
|
||||||
|
put(uri: string, callback: Function): Function;
|
||||||
|
delete(uri: string, callback: Function): Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RestClientArgs {
|
||||||
|
data?: any;
|
||||||
|
parameters?: any;
|
||||||
|
headers?: any;
|
||||||
|
requestConfig?: RequestConfig;
|
||||||
|
responseConfig?: ResponseConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RestClientResponse {
|
||||||
|
request: ResponseRequest;
|
||||||
|
data: any;
|
||||||
|
statusMessage: string;
|
||||||
|
statusCode: number;
|
||||||
|
}
|
81
e2e/utilities/rest-client/rest-client.ts
Normal file
81
e2e/utilities/rest-client/rest-client.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 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 { Client } from 'node-rest-client';
|
||||||
|
import { NodeRestClient, RestClientArgs, RestClientResponse } from './rest-client-models';
|
||||||
|
|
||||||
|
export * from './rest-client-models';
|
||||||
|
|
||||||
|
export class RestClient {
|
||||||
|
private static DEFAULT_HEADERS = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json'
|
||||||
|
};
|
||||||
|
|
||||||
|
private client: NodeRestClient;
|
||||||
|
|
||||||
|
constructor(user: string, password: string) {
|
||||||
|
this.client = <NodeRestClient>(new Client({ user, password }));
|
||||||
|
}
|
||||||
|
|
||||||
|
get(uri: string, args: RestClientArgs = {}): Promise<RestClientResponse> {
|
||||||
|
return this.promisify('get', uri, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
post(uri: string, args: RestClientArgs = {}): Promise<RestClientResponse> {
|
||||||
|
return this.promisify('post', uri, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
put(uri: string, args: RestClientArgs = {}): Promise<RestClientResponse> {
|
||||||
|
return this.promisify('put', uri, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(uri: string, args: RestClientArgs = {}): Promise<RestClientResponse> {
|
||||||
|
return this.promisify('delete', uri, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createArgs(args: RestClientArgs = {}): RestClientArgs {
|
||||||
|
const data = JSON.stringify(args.data);
|
||||||
|
|
||||||
|
return Object.assign({}, RestClient.DEFAULT_HEADERS, args, { data });
|
||||||
|
}
|
||||||
|
|
||||||
|
private promisify(fnName: string, uri: string, args: RestClientArgs): Promise<RestClientResponse> {
|
||||||
|
const fn: Function = this.client[fnName];
|
||||||
|
const fnArgs = [ encodeURI(uri), this.createArgs(args) ];
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const fnCallback = (data, rawResponse) => {
|
||||||
|
const {
|
||||||
|
statusCode, statusMessage,
|
||||||
|
req: { method, path }
|
||||||
|
} = rawResponse;
|
||||||
|
|
||||||
|
const response: RestClientResponse = {
|
||||||
|
data, statusCode, statusMessage,
|
||||||
|
request: { method, path, data: args.data }
|
||||||
|
};
|
||||||
|
|
||||||
|
(response.statusCode >= 400)
|
||||||
|
? reject(response)
|
||||||
|
: resolve(response);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn(...fnArgs, fnCallback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ const { SpecReporter } = require('jasmine-spec-reporter');
|
|||||||
exports.config = {
|
exports.config = {
|
||||||
allScriptsTimeout: 11000,
|
allScriptsTimeout: 11000,
|
||||||
specs: [
|
specs: [
|
||||||
'./e2e/**/*.e2e-spec.ts'
|
'./e2e/**/*.test.ts'
|
||||||
],
|
],
|
||||||
capabilities: {
|
capabilities: {
|
||||||
'browserName': 'chrome'
|
'browserName': 'chrome'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user