ui/cypress/support/utils/datalake/DataLakeUtils.ts (429 lines of code) (raw):
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 { DataLakeFilterConfig } from '../../model/DataLakeFilterConfig';
import { DataExplorerWidget } from '../../model/DataExplorerWidget';
import { DataSetUtils } from '../DataSetUtils';
import { PrepareTestDataUtils } from '../PrepareTestDataUtils';
import { FileManagementUtils } from '../FileManagementUtils';
import { ConnectUtils } from '../connect/ConnectUtils';
import { ConnectBtns } from '../connect/ConnectBtns';
import { AdapterBuilder } from '../../builder/AdapterBuilder';
import { differenceInMonths } from 'date-fns';
export class DataLakeUtils {
public static goToDatalake() {
cy.visit('#/dataexplorer');
}
public static goToDashboard() {
cy.wait(1000);
cy.visit('#/dashboard');
}
public static initDataLakeTests() {
cy.initStreamPipesTest();
DataLakeUtils.loadRandomDataSetIntoDataLake();
}
public static getDataLakeTestSetAdapter(
name: string,
storeInDataLake: boolean = true,
format: 'csv' | 'json_array',
) {
const adapterBuilder = AdapterBuilder.create('File_Stream')
.setName(name)
.setTimestampProperty('timestamp')
.addDimensionProperty('randomtext')
.addProtocolInput(
'radio',
'speed',
'fastest_\\(ignore_original_time\\)',
)
.setStartAdapter(true);
if (format === 'csv') {
adapterBuilder
.setFormat('csv')
.addFormatInput('input', ConnectBtns.csvDelimiter(), ';')
.addFormatInput('checkbox', ConnectBtns.csvHeader(), 'check');
} else {
adapterBuilder.setFormat('json_array');
}
if (storeInDataLake) {
adapterBuilder.setStoreInDataLake();
}
return adapterBuilder.build();
}
public static loadDataIntoDataLake(
dataSet: string,
format: 'csv' | 'json_array' = 'csv',
) {
// Create adapter with dataset
FileManagementUtils.addFile(dataSet);
const adapter = this.getDataLakeTestSetAdapter(
'datalake_configuration',
true,
format,
);
ConnectUtils.addAdapter(adapter);
ConnectUtils.startAdapter(adapter);
}
public static addDataViewAndWidget(
dataViewName: string,
dataSet: string,
widgetType: string,
) {
DataLakeUtils.goToDatalake();
DataLakeUtils.createAndEditDataView();
DataLakeUtils.selectTimeRange(
new Date(2020, 10, 20, 22, 44),
DataLakeUtils.getFutureDate(),
);
// DataLakeUtils.addNewWidget();
DataLakeUtils.selectDataSet(dataSet);
DataLakeUtils.dataConfigSelectAllFields();
DataLakeUtils.selectAppearanceConfig();
DataLakeUtils.selectDataViewName(dataViewName);
DataLakeUtils.openVisualizationConfig();
DataLakeUtils.selectVisualizationType(widgetType);
cy.wait(1000);
}
public static addDataViewAndTableWidget(
dataViewName: string,
dataSet: string,
) {
this.addDataViewAndWidget(
dataViewName,
dataSet,
DataExplorerWidget.TABLE,
);
}
public static addDataViewAndTimeSeriesWidget(
dataViewName: string,
dataSet: string,
) {
this.addDataViewAndWidget(
dataViewName,
dataSet,
DataExplorerWidget.TIME_SERIES,
);
}
public static loadRandomDataSetIntoDataLake() {
PrepareTestDataUtils.loadDataIntoDataLake('fileTest/random.csv');
}
public static createAndEditDashboard(name: string) {
// Create new data view
cy.dataCy('open-new-dashboard-dialog').click();
// Configure data view
cy.dataCy('data-view-name').type(name);
cy.dataCy('save-data-view').click();
this.editDashboard(name);
}
public static addDataViewToDashboard(
dataViewName: string,
ignoreTimeRange = false,
) {
if (!ignoreTimeRange) {
this.selectTimeRange(
new Date(2020, 10, 20, 22, 44),
this.getFutureDate(),
);
}
cy.dataCy('add-data-view-btn-' + dataViewName).click();
}
public static createAndEditDataView() {
// Create new data view
cy.dataCy('open-new-data-view', { timeout: 10000 }).click();
}
public static removeWidget(dataViewName: string) {
cy.dataCy('remove-' + dataViewName).click();
}
public static editDashboard(dashboardName: string) {
// Click edit button
// following only works if single view is available
cy.dataCy('edit-dashboard-' + dashboardName).click();
}
public static editDataView(dataViewName: string) {
// Click edit button
// following only works if single view is available
cy.dataCy('edit-data-view-' + dataViewName).click();
}
public static saveDataViewConfiguration() {
cy.dataCy('save-data-view-btn', { timeout: 10000 }).click({
force: true,
});
}
public static saveDashboardConfiguration() {
cy.dataCy('save-dashboard-btn', { timeout: 10000 }).click();
}
public static getEmptyDashboardInformation() {
return cy.dataCy('empty-dashboard');
}
public static deleteDashboard(dashboardName: string) {
cy.dataCy('delete-dashboard-' + dashboardName, {
timeout: 10000,
}).click();
cy.dataCy('confirm-delete', { timeout: 10000 }).click();
}
public static deleteDataView(dataViewName: string) {
cy.dataCy('delete-data-view-' + dataViewName, {
timeout: 10000,
}).click();
cy.dataCy('confirm-delete', { timeout: 10000 }).click();
}
public static cancelDeleteDashboard(dashboardName: string) {
cy.dataCy('delete-dashboard-' + dashboardName, {
timeout: 10000,
}).click();
cy.dataCy('cancel-delete', { timeout: 10000 }).click();
}
public static cancelDeleteDataView(dataViewName: string) {
cy.dataCy('delete-data-view-' + dataViewName, {
timeout: 10000,
}).click();
cy.dataCy('cancel-delete', { timeout: 10000 }).click();
}
public static editWidget(widgetName: string) {
cy.dataCy('edit-' + widgetName).click();
}
public static startEditWidget(widgetName: string) {
cy.dataCy('more-options-' + widgetName).click();
cy.dataCy('start-edit-' + widgetName).click();
}
public static saveAndReEditWidget(dataViewName: string) {
// Save data view configuration
DataLakeUtils.saveDataViewConfiguration();
DataLakeUtils.editDataView(dataViewName);
}
public static saveAndReEditDashboard(dashboardName: string) {
// Save dashboard configuration
DataLakeUtils.saveDashboardConfiguration();
DataLakeUtils.editDashboard(dashboardName);
}
public static clickTab(tabName: string) {
// Click start tab to go to overview
cy.get('div').contains(tabName).parent().click();
}
public static goBackToOverview() {
cy.dataCy('save-data-explorer-go-back-to-overview').click();
}
public static addNewWidget() {
cy.dataCy('add-new-widget').click();
}
public static selectDataSet(dataSet: string) {
cy.dataCy('data-explorer-select-data-set')
.click()
.get('mat-option')
.contains(dataSet)
.click();
}
/**
* Checks if in the widget configuration the filters are set or not
* @param amountOfFilter the amount of filters that should be set. 0 if no filter should be visible
*/
public static checkIfFilterIsSet(amountOfFilter: number) {
if (amountOfFilter === 0) {
cy.dataCy('design-panel-data-settings-filter-field').should(
'not.exist',
);
} else {
cy.dataCy('design-panel-data-settings-filter-field', {
timeout: 20000,
}).should('be.visible');
}
}
/**
* This method validates that the defined filter options are available in the UI
* @param expectedFilterOptions
*/
public static validateFilterOptions(
expectedFilterOptions: ('=' | '<' | '<=' | '>=' | '>' | '!=')[],
) {
cy.dataCy('design-panel-data-settings-filter-operator')
.click()
.dataCy('operator-', {}, true)
.should('have.length', expectedFilterOptions.length);
expectedFilterOptions.forEach(option => {
const escapedOption = option.replace(/([=<>!])/g, '\\$1');
cy.dataCy('operator-' + escapedOption).should('be.visible');
});
cy.dataCy('design-panel-data-settings-filter-operator').click({
force: true,
});
}
public static validateAutoCompleteOptions(options: string[]) {
cy.dataCy('design-panel-data-settings-filter-value')
.click({ force: true })
.dataCy('autocomplete-value-', {}, true)
.should('have.length', options.length);
options.forEach(option => {
cy.dataCy('autocomplete-value-' + option).should('be.visible');
});
cy.dataCy('design-panel-data-settings-filter-value').click({
force: true,
});
}
/**
* In the data set panel select all property fields
*/
public static dataConfigSelectAllFields() {
cy.dataCy('data-explorer-data-set-field-select-all').click();
}
public static dataConfigAddFilter(filterConfig: DataLakeFilterConfig) {
cy.dataCy('design-panel-data-settings-add-filter').click();
// Select field
cy.dataCy('design-panel-data-settings-filter-field')
.click()
.get('mat-option')
.contains(filterConfig.field)
.click();
// Select value
cy.dataCy('design-panel-data-settings-filter-value').type(
filterConfig.value,
);
// Select operator
cy.dataCy('design-panel-data-settings-filter-operator')
.click()
.get('mat-option')
.contains(filterConfig.operator)
.click();
}
public static dataConfigRemoveFilter() {
cy.dataCy('design-panel-data-settings-remove-filter')
.first()
.click({ force: true });
}
public static clickGroupBy(propertyName: string) {
cy.dataCy('data-explorer-group-by-' + propertyName)
.children()
.click();
}
public static clickOrderBy(order: String) {
if (order == 'ascending') {
cy.dataCy('ascending-radio-button').click();
} else {
cy.dataCy('descending-radio-button').click();
}
}
/**
* Select visualization type
*/
public static selectVisualizationType(type: string | 'table') {
// Select visualization type
cy.dataCy('data-explorer-select-visualization-type', { timeout: 10000 })
.click()
.dataCy(`select-widget-${type}`)
.click();
}
public static selectDataConfig() {
cy.get('.mdc-tab__text-label').contains('Data').parent().click();
}
public static openVisualizationConfig() {
cy.get('.mdc-tab__text-label')
.contains('Visualization')
.parent()
.click();
}
public static selectAppearanceConfig() {
cy.get('.mdc-tab__text-label').contains('Appearance').parent().click();
}
public static selectDataViewName(dataViewName: string) {
cy.dataCy('appearance-config-widget-title').clear().type(dataViewName);
}
public static clickCreateButton() {
// Create widget
cy.dataCy('data-explorer-select-data-set-create-btn').click();
}
public static goToDatalakeConfiguration() {
cy.visit('#/configuration/datalake');
}
public static checkResults(
measurementName: string,
fileRoute: string,
ignoreTime: boolean,
) {
const fileType = this.getFileType(fileRoute);
this.fetchDataLakeResults(measurementName, fileType).then(
actualResultString =>
this.compareResults(
actualResultString,
fileRoute,
fileType,
ignoreTime,
),
);
}
private static getFileType(fileRoute: string): 'csv' | 'json' {
return fileRoute.endsWith('.csv') ? 'csv' : 'json';
}
private static fetchDataLakeResults(
measurementName: string,
fileType: 'csv' | 'json',
): Cypress.Chainable<string> {
return cy
.request({
method: 'GET',
url: `/streampipes-backend/api/v4/datalake/measurements/${measurementName}/download?format=${fileType}&delimiter=semicolon`,
headers: {
'content-type': 'application/octet-stream',
},
auth: {
bearer: window.localStorage.getItem('auth-token'),
},
})
.then(response => response.body);
}
private static compareResults(
actualResultString: string,
fileRoute: string,
fileType: 'csv' | 'json',
ignoreTime?: boolean,
) {
cy.readFile(fileRoute).then(expectedResult => {
if (fileType === 'csv') {
DataSetUtils.csvEqual(
actualResultString,
expectedResult,
ignoreTime,
);
} else if (fileType === 'json') {
DataSetUtils.jsonFilesEqual(
actualResultString,
expectedResult,
ignoreTime,
);
}
});
}
public static selectTimeRange(from: Date, to: Date) {
DataLakeUtils.openTimeSelectorMenu();
const monthsBack = Math.abs(differenceInMonths(from, new Date())) + 1;
DataLakeUtils.navigateCalendar('previous', monthsBack);
DataLakeUtils.selectDay(from.getDate());
const monthsForward = Math.abs(differenceInMonths(from, to));
DataLakeUtils.navigateCalendar('next', monthsForward);
DataLakeUtils.selectDay(to.getDate());
DataLakeUtils.setTimeInput('time-selector-start-time', from);
DataLakeUtils.setTimeInput('time-selector-end-time', to);
DataLakeUtils.applyCustomTimeSelection();
}
public static navigateCalendar(direction: string, numberOfMonths: number) {
for (let i = 0; i < numberOfMonths; i++) {
cy.get(`button.mat-calendar-${direction}-button`).click();
}
}
public static selectDay(day: number) {
cy.get(
`button:has(span.mat-calendar-body-cell-content:contains("${day}"))`,
)
.first()
.click();
}
public static openTimeSelectorMenu() {
cy.dataCy('time-selector-menu', { timeout: 10000 }).click();
}
public static applyCustomTimeSelection() {
cy.dataCy('apply-custom-time').click();
}
public static setTimeInput(field: string, date: Date) {
cy.dataCy(field).type(DataLakeUtils.makeTimeString(date));
}
public static makeTimeString(date: Date) {
return date.toTimeString().slice(0, 5);
}
public static getFutureDate() {
const currentDate = new Date();
currentDate.setMonth(currentDate.getMonth() + 1);
return currentDate;
}
public static waitForCountingResults() {
cy.dataCy('datalake-number-of-events-spinner', {
timeout: 10000,
}).should('exist');
cy.dataCy('datalake-number-of-events-spinner', {
timeout: 10000,
}).should('not.exist');
}
public static getDatalakeNumberOfEvents(): Cypress.Chainable<string> {
return cy
.dataCy('datalake-number-of-events', { timeout: 10000 })
.should('be.visible')
.invoke('text')
.then(text => text.trim());
}
public static checkRowsDashboardTable(amount: number) {
cy.dataCy('dashboard-table-overview', {
timeout: 10000,
}).should('have.length', amount);
}
public static checkRowsViewsTable(amount: number) {
cy.dataCy('data-views-table-overview', {
timeout: 10000,
}).should('have.length', amount);
}
public static checkIfConfirmationDialogIsShowing(): void {
cy.get('confirmation-dialog').should('be.visible');
}
}