mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
improve e2e configuration (#5752)
* improve e2e configuration * fix login * fix login * use storage * fix * default oauth * improve share file test and add baseShareUrl init in e2e * some click script better usage
This commit is contained in:
@@ -22,14 +22,25 @@ export class ApiService {
|
||||
|
||||
apiService: AlfrescoApi;
|
||||
|
||||
config: AlfrescoApiConfig;
|
||||
config: AlfrescoApiConfig = new AlfrescoApiConfig({
|
||||
authType: 'OAUTH',
|
||||
oauth2: {
|
||||
scope: 'openid',
|
||||
secret: '',
|
||||
implicitFlow: false,
|
||||
silentLogin: false,
|
||||
redirectUri: '/',
|
||||
redirectUriLogout: '/logout'
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
constructor(clientIdOrAppConfig?: AlfrescoApiConfig | string, host?: string, hostSso?: string, provider?: string) {
|
||||
|
||||
if (browser.params.testConfig && browser.params.testConfig.appConfig) {
|
||||
this.config = { ...browser.params.testConfig.appConfig };
|
||||
this.config.hostEcm = browser.params.testConfig.appConfig.ecmHost;
|
||||
this.config.hostBpm = browser.params.testConfig.appConfig.bpmHost;
|
||||
this.config.hostEcm = browser.params.testConfig.appConfig.ecmHost;
|
||||
this.config.hostBpm = browser.params.testConfig.appConfig.bpmHost;
|
||||
}
|
||||
|
||||
if (clientIdOrAppConfig && typeof clientIdOrAppConfig !== 'string') {
|
||||
|
34
lib/testing/src/lib/core/models/application-model.ts
Normal file
34
lib/testing/src/lib/core/models/application-model.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export interface ApplicationRepresentation {
|
||||
releaseId: string;
|
||||
security: SecurityRepresentation[];
|
||||
name: string;
|
||||
infrastructure?: InfrastructureRepresentation;
|
||||
}
|
||||
|
||||
export interface SecurityRepresentation {
|
||||
role: string;
|
||||
users: string[];
|
||||
groups: string[];
|
||||
}
|
||||
|
||||
export interface InfrastructureRepresentation {
|
||||
connectors?: any;
|
||||
bridges?: any;
|
||||
}
|
@@ -18,6 +18,7 @@
|
||||
import { element, by, browser, protractor, ElementFinder } from 'protractor';
|
||||
import { BrowserVisibility } from '../utils/browser-visibility';
|
||||
import { BrowserActions } from '../utils/browser-actions';
|
||||
import { LocalStorageUtil } from '../utils/local-storage.util';
|
||||
|
||||
export class LoginSSOPage {
|
||||
|
||||
@@ -49,7 +50,10 @@ export class LoginSSOPage {
|
||||
}
|
||||
|
||||
async login(username: string, password: string) {
|
||||
if (browser.params.testConfig.appConfig.authType === 'OAUTH') {
|
||||
|
||||
const authType = await LocalStorageUtil.getConfigField('authType');
|
||||
|
||||
if (!authType || authType === 'OAUTH') {
|
||||
await this.loginSSOIdentityService(username, password);
|
||||
} else {
|
||||
await this.loginBasicAuth(username, password);
|
||||
@@ -59,16 +63,13 @@ export class LoginSSOPage {
|
||||
async loginSSOIdentityService(username: string, password: string) {
|
||||
browser.ignoreSynchronization = true;
|
||||
|
||||
let currentUrl;
|
||||
const loginURL: string = browser.baseUrl + (browser.params.loginRoute ? browser.params.loginRoute : '');
|
||||
|
||||
try {
|
||||
currentUrl = await browser.getCurrentUrl();
|
||||
} catch (e) {
|
||||
}
|
||||
await browser.get(loginURL);
|
||||
const oauth2 = await LocalStorageUtil.getConfigField('oauth2');
|
||||
|
||||
if (!currentUrl || currentUrl === '' || currentUrl === 'data:,') {
|
||||
const loginURL: string = browser.baseUrl + (browser.params.loginRoute ? browser.params.loginRoute : '');
|
||||
await browser.get(loginURL);
|
||||
if (oauth2 && oauth2.silentLogin === false) {
|
||||
await this.clickOnSSOButton();
|
||||
}
|
||||
|
||||
await BrowserVisibility.waitUntilElementIsVisible(this.usernameField);
|
||||
|
@@ -40,14 +40,14 @@ export class DateTimePickerCalendarPage {
|
||||
}
|
||||
|
||||
async setTime(): Promise<void> {
|
||||
await BrowserActions.click(this.hourTime);
|
||||
await BrowserActions.click(this.minutesTime);
|
||||
await BrowserActions.clickScript(this.hourTime);
|
||||
await BrowserActions.clickScript(this.minutesTime);
|
||||
}
|
||||
|
||||
async setDate(date?: string): Promise<boolean> {
|
||||
try {
|
||||
if (date) {
|
||||
await BrowserActions.click(element(by.cssContainingText(`.mat-datetimepicker-calendar-body-cell-content`, date)));
|
||||
await BrowserActions.clickScript(element.all(by.cssContainingText(`.mat-datetimepicker-calendar-body-cell-content`, date)).first());
|
||||
} else {
|
||||
await this.setToday();
|
||||
}
|
||||
@@ -63,12 +63,10 @@ export class DateTimePickerCalendarPage {
|
||||
}
|
||||
|
||||
async setDefaultEnabledHour(): Promise<void> {
|
||||
await BrowserVisibility.waitUntilElementIsVisible(this.hoursPicker);
|
||||
await BrowserActions.click(this.hoursPicker.all(this.firstEnabledHourSelector).first());
|
||||
}
|
||||
|
||||
async setDefaultEnabledMinutes() {
|
||||
await BrowserVisibility.waitUntilElementIsVisible(this.minutePicker);
|
||||
await BrowserActions.click(this.minutePicker.all(this.firstEnabledMinutesSelector).first());
|
||||
}
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ export class TogglePage {
|
||||
const check = await toggle.getAttribute('class');
|
||||
if (check.indexOf('mat-checked') < 0) {
|
||||
const elem = toggle.all(by.css('input')).first();
|
||||
await BrowserActions.click(elem);
|
||||
await BrowserActions.clickScript(elem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export class TogglePage {
|
||||
const check = await toggle.getAttribute('class');
|
||||
if (check.indexOf('mat-checked') >= 0) {
|
||||
const elem = toggle.all(by.css('input')).first();
|
||||
await BrowserActions.click(elem);
|
||||
await BrowserActions.clickScript(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -56,7 +56,7 @@ export class PaginationPage {
|
||||
}
|
||||
|
||||
async clickItemsPerPageDropdown(): Promise<void> {
|
||||
await BrowserActions.click(this.itemsPerPageOpenDropdown);
|
||||
await BrowserActions.clickScript(this.itemsPerPageOpenDropdown);
|
||||
}
|
||||
|
||||
async checkPaginationIsNotDisplayed() {
|
||||
|
@@ -27,16 +27,16 @@ export class BrowserActions {
|
||||
await BrowserVisibility.waitUntilElementIsClickable(elementFinder);
|
||||
await elementFinder.click();
|
||||
} catch (clickErr) {
|
||||
try {
|
||||
await browser.executeScript(`arguments[0].scrollIntoView();`, elementFinder);
|
||||
await browser.executeScript(`arguments[0].click();`, elementFinder);
|
||||
} catch (jsErr) {
|
||||
Logger.error(`click error element ${elementFinder.locator()}`);
|
||||
throw jsErr;
|
||||
}
|
||||
Logger.error(`click error element ${elementFinder.locator().toString()} consider to use directly clickScript`);
|
||||
await this.clickScript(elementFinder);
|
||||
}
|
||||
}
|
||||
|
||||
static async clickScript(elementFinder: ElementFinder): Promise<void> {
|
||||
await browser.executeScript(`arguments[0].scrollIntoView();`, elementFinder);
|
||||
await browser.executeScript(`arguments[0].click();`, elementFinder);
|
||||
}
|
||||
|
||||
static async waitUntilActionMenuIsVisible(): Promise<void> {
|
||||
const actionMenu = element.all(by.css('div[role="menu"]')).first();
|
||||
await BrowserVisibility.waitUntilElementIsVisible(actionMenu);
|
||||
|
@@ -19,6 +19,12 @@ import { browser } from 'protractor';
|
||||
|
||||
export class LocalStorageUtil {
|
||||
|
||||
static async getConfigField(field: string): Promise<any> {
|
||||
return browser.executeScript(
|
||||
'return window.adf ? window.adf.getConfigField(`' + field + '`) : null;'
|
||||
);
|
||||
}
|
||||
|
||||
static async setConfigField(field: string, value: string): Promise<void> {
|
||||
await browser.executeScript(
|
||||
'window.adf.setConfigField(`' + field + '`, `' + value + '`);'
|
||||
@@ -37,6 +43,12 @@ export class LocalStorageUtil {
|
||||
);
|
||||
}
|
||||
|
||||
static async getStorageItem(field: string): Promise<any> {
|
||||
return browser.executeScript(
|
||||
'return window.adf ? window.adf.getStorageItem(`' + field + '`) : null;'
|
||||
);
|
||||
}
|
||||
|
||||
static async setUserPreference(field: string, value: any): Promise<void> {
|
||||
await browser.executeScript(
|
||||
'window.adf.setUserPreference(`' + field + '`, `' + value + '`);'
|
||||
|
@@ -40,6 +40,11 @@ export class Application {
|
||||
Logger.info(`[Application] Application: '${applicationId}' was deleted successfully.`);
|
||||
}
|
||||
|
||||
async undeploy(applicationName: string): Promise<any> {
|
||||
await this.requestApiHelper.delete(`${this.endPoint}${applicationName}`);
|
||||
Logger.info(`[Application] Application ${applicationName} was undeployed successfully.`);
|
||||
}
|
||||
|
||||
async deleteDescriptor(name: string): Promise<void> {
|
||||
await this.requestApiHelper.delete(`v1/descriptors/${name}`);
|
||||
Logger.info(`[Descriptor] Descriptor: '${name}' was deleted successfully.`);
|
||||
|
@@ -1,69 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Api } from '../../core/actions/api';
|
||||
import { Application } from './application';
|
||||
import { Logger } from '../../core/utils/logger';
|
||||
import { browser } from 'protractor';
|
||||
import { ResultSetPaging } from '@alfresco/js-api';
|
||||
|
||||
export class DeploymentAPI extends Api {
|
||||
public application: Application;
|
||||
|
||||
constructor(ROOT: string = 'deployment-service') {
|
||||
super(ROOT);
|
||||
}
|
||||
|
||||
async setUp(): Promise<DeploymentAPI> {
|
||||
await this.login();
|
||||
this.application = new Application(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
async tearDown(): Promise<void> {
|
||||
await this.api.logout();
|
||||
}
|
||||
|
||||
private async login(): Promise<void> {
|
||||
try {
|
||||
await this.api.login(
|
||||
browser.params.adminapp.devops,
|
||||
browser.params.adminapp.devops_password
|
||||
);
|
||||
} catch (error) {
|
||||
Logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async deploy(releasedProject: any): Promise<void> {
|
||||
await this.application.deploy(releasedProject);
|
||||
}
|
||||
|
||||
async deleteDescriptor(name: string): Promise<void> {
|
||||
await this.application.deleteDescriptor(name);
|
||||
}
|
||||
|
||||
async getDescriptors(): Promise<ResultSetPaging> {
|
||||
const descriptors = await this.application.getDescriptors();
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
async getApplicationByStatus(status: string): Promise<ResultSetPaging> {
|
||||
const applications = this.application.getApplicationsByStatus(status);
|
||||
return applications;
|
||||
}
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
import { E2eRequestApiHelper } from '../../core/actions/e2e-request-api.helper';
|
||||
import { Api } from '../../core/actions/api';
|
||||
import { ApplicationRepresentation } from '../../core/models/application-model';
|
||||
import { Logger } from '../../core/utils/logger';
|
||||
import { ApiUtil } from '../../core/actions/api.util';
|
||||
|
||||
export class Descriptor {
|
||||
requestApiHelper: E2eRequestApiHelper;
|
||||
endPoint = `/v1/descriptors/`;
|
||||
|
||||
constructor(api: Api) {
|
||||
this.requestApiHelper = new E2eRequestApiHelper(api);
|
||||
}
|
||||
|
||||
async create(model: ApplicationRepresentation): Promise<void> {
|
||||
try {
|
||||
await this.requestApiHelper.post<NodeEntry>(this.endPoint, {
|
||||
bodyParam: model
|
||||
});
|
||||
Logger.info(`[Descriptor] Descriptor has been created with name: ${model.name}.`);
|
||||
} catch (error) {
|
||||
Logger.error(`[Descriptor] Create descriptor ${model.name} failed with message: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async delete(name: string): Promise<void> {
|
||||
try {
|
||||
await this.retryUntilDescriptorIsInStatus(name, `DescriptorCreated`);
|
||||
await this.requestApiHelper.delete(`${this.endPoint}${name}`);
|
||||
Logger.info(`[Descriptor] Descriptor '${name}' was deleted successfully.`);
|
||||
} catch (error) {
|
||||
Logger.error(`[Descriptor] Delete descriptor ${name} failed with message: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async get(name: string): Promise<any> {
|
||||
Logger.info(`[Descriptor] Get descriptor ${name} details.`);
|
||||
try {
|
||||
return this.requestApiHelper.get<any>(`${this.endPoint}${name}`);
|
||||
} catch (error) {
|
||||
Logger.error(`[Descriptor] Get descriptor ${name} details failed with message: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async retryUntilDescriptorIsInStatus(name: string, expectedStatus: string): Promise<any> {
|
||||
const predicate = (result: { status: string }) => {
|
||||
return result.status === expectedStatus;
|
||||
};
|
||||
const apiCall = async () => this.get(name);
|
||||
|
||||
return ApiUtil.waitForApi(apiCall, predicate);
|
||||
}
|
||||
}
|
@@ -22,7 +22,7 @@ export * from './process-instances.service';
|
||||
export * from './message-events.service';
|
||||
export * from './form-cloud.service';
|
||||
export * from './tasks.service';
|
||||
export * from './deployment-api';
|
||||
export * from './modeling-api';
|
||||
export * from './application';
|
||||
export * from './descriptor';
|
||||
export * from './project';
|
||||
|
@@ -50,25 +50,21 @@ export class ProcessFiltersCloudComponentPage {
|
||||
|
||||
async clickProcessFilter(filterName: string): Promise<void> {
|
||||
this.filter = this.getProcessFilterLocatorByFilterName(filterName);
|
||||
await BrowserVisibility.waitUntilElementIsClickable(this.filter);
|
||||
await BrowserActions.click(this.filter);
|
||||
}
|
||||
|
||||
async clickAllProcessesFilter(): Promise<void> {
|
||||
this.filter = this.getProcessFilterLocatorByFilterName('all-processes');
|
||||
await BrowserVisibility.waitUntilElementIsClickable(this.filter);
|
||||
await BrowserActions.click(this.filter);
|
||||
}
|
||||
|
||||
async clickCompletedProcessesFilter(): Promise<void> {
|
||||
this.filter = this.getProcessFilterLocatorByFilterName('completed-processes');
|
||||
await BrowserVisibility.waitUntilElementIsClickable(this.filter);
|
||||
await BrowserActions.click(this.filter);
|
||||
}
|
||||
|
||||
async clickRunningProcessesFilter(): Promise<void> {
|
||||
this.filter = this.getProcessFilterLocatorByFilterName('running-processes');
|
||||
await BrowserVisibility.waitUntilElementIsClickable(this.filter);
|
||||
await BrowserActions.click(this.filter);
|
||||
}
|
||||
|
||||
|
@@ -63,7 +63,6 @@ export class StartProcessCloudPage {
|
||||
async selectFirstOptionFromProcessDropdown(): Promise<void> {
|
||||
await this.clickProcessDropdownArrow();
|
||||
const selectFirstProcessDropdown = element.all(by.css('.mat-option-text')).first();
|
||||
await BrowserVisibility.waitUntilElementIsPresent(selectFirstProcessDropdown);
|
||||
await BrowserActions.click(selectFirstProcessDropdown);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user