mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Maps] update layers on kibana global refresh interval (#27721)
* update layers on kibana global refresh interval * store refresh in UI state * clearer function names for refresh timer * rename a bunch of things * fix store_actions jest test * add functional test to verify refresh config is loaded from saved object state * add functional tests verifing layers re-fetch data on refresh timer
This commit is contained in:
parent
9f6bd394a8
commit
72680f2fa0
24 changed files with 335 additions and 122 deletions
|
@ -25,6 +25,7 @@
|
|||
ng-class="{'kuiLocalMenuItem-isSelected': kbnTopNav.isCurrent('interval') }"
|
||||
ng-show="timefilterValues.isAutoRefreshSelectorEnabled"
|
||||
ng-click="kbnTopNav.toggle('interval')"
|
||||
data-test-subj="globalRefreshButton"
|
||||
>
|
||||
<span ng-show="timefilterValues.refreshInterval.value === 0">
|
||||
<span aria-hidden="true" class="kuiIcon fa-repeat"></span> Auto-refresh
|
||||
|
|
|
@ -194,6 +194,12 @@ export function HeaderPageProvider({ getService, getPageObjects }) {
|
|||
return testSubjects.getAttribute('globalTimepickerAutoRefreshButton', 'data-test-subj-state');
|
||||
}
|
||||
|
||||
async getRefreshConfig() {
|
||||
const refreshState = await testSubjects.getAttribute('globalTimepickerAutoRefreshButton', 'data-test-subj-state');
|
||||
const refreshConfig = await testSubjects.getVisibleText('globalRefreshButton');
|
||||
return `${refreshState} ${refreshConfig}`;
|
||||
}
|
||||
|
||||
// check if the auto refresh state is active and to pause it
|
||||
async pauseAutoRefresh() {
|
||||
let result = false;
|
||||
|
|
|
@ -9,6 +9,7 @@ import turfBooleanContains from '@turf/boolean-contains';
|
|||
|
||||
import { GIS_API_PATH } from '../../common/constants';
|
||||
import { getLayerList, getLayerListRaw, getDataFilters, getSelectedLayer } from '../selectors/map_selectors';
|
||||
import { timeService } from '../kibana_services';
|
||||
|
||||
export const SET_SELECTED_LAYER = 'SET_SELECTED_LAYER';
|
||||
export const UPDATE_LAYER_ORDER = 'UPDATE_LAYER_ORDER';
|
||||
|
@ -27,6 +28,7 @@ export const LAYER_DATA_LOAD_ERROR = 'LAYER_DATA_LOAD_ERROR';
|
|||
export const REPLACE_LAYERLIST = 'REPLACE_LAYERLIST';
|
||||
export const SET_JOINS = 'SET_JOINS';
|
||||
export const SET_TIME_FILTERS = 'SET_TIME_FILTERS';
|
||||
export const TRIGGER_REFRESH_TIMER = 'TRIGGER_REFRESH_TIMER';
|
||||
export const UPDATE_LAYER_PROP = 'UPDATE_LAYER_PROP';
|
||||
export const UPDATE_LAYER_STYLE_FOR_SELECTED_LAYER = 'UPDATE_LAYER_STYLE';
|
||||
export const PROMOTE_TEMPORARY_STYLES = 'PROMOTE_TEMPORARY_STYLES';
|
||||
|
@ -34,6 +36,7 @@ export const CLEAR_TEMPORARY_STYLES = 'CLEAR_TEMPORARY_STYLES';
|
|||
export const TOUCH_LAYER = 'TOUCH_LAYER';
|
||||
export const UPDATE_LAYER_ALPHA_VALUE = 'UPDATE_LAYER_ALPHA_VALUE';
|
||||
export const UPDATE_SOURCE_PROP = 'UPDATE_SOURCE_PROP';
|
||||
export const SET_REFRESH_CONFIG = 'SET_REFRESH_CONFIG';
|
||||
|
||||
const GIS_API_RELATIVE = `../${GIS_API_PATH}`;
|
||||
|
||||
|
@ -332,16 +335,58 @@ export function setMeta(metaJson) {
|
|||
};
|
||||
}
|
||||
|
||||
export function setTimeFilters(timeFilters) {
|
||||
export function setTimeFiltersToKbnGlobalTime() {
|
||||
return (dispatch) => {
|
||||
dispatch(setTimeFilters(timeService.getTime()));
|
||||
};
|
||||
}
|
||||
|
||||
export function setTimeFilters({ from, to }) {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: SET_TIME_FILTERS,
|
||||
...timeFilters
|
||||
from,
|
||||
to,
|
||||
});
|
||||
|
||||
// Update Kibana global time
|
||||
const kbnTime = timeService.getTime();
|
||||
if ((to && to !== kbnTime.to) || (from && from !== kbnTime.from)) {
|
||||
timeService.setTime({ from, to });
|
||||
}
|
||||
|
||||
const dataFilters = getDataFilters(getState());
|
||||
await syncDataForAllLayers(getState, dispatch, dataFilters);
|
||||
};
|
||||
}
|
||||
|
||||
export function setRefreshConfig({ isPaused, interval }) {
|
||||
return async (dispatch) => {
|
||||
dispatch({
|
||||
type: SET_REFRESH_CONFIG,
|
||||
isPaused,
|
||||
interval,
|
||||
});
|
||||
|
||||
// Update Kibana global refresh
|
||||
const kbnRefresh = timeService.getRefreshInterval();
|
||||
if (isPaused !== kbnRefresh.pause || interval !== kbnRefresh.value) {
|
||||
timeService.setRefreshInterval({
|
||||
pause: isPaused,
|
||||
value: interval,
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function triggerRefreshTimer() {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: TRIGGER_REFRESH_TIMER,
|
||||
});
|
||||
|
||||
const dataFilters = getDataFilters(getState());
|
||||
const newDataFilters = { ...dataFilters, timeFilters: { ...timeFilters } };
|
||||
await syncDataForAllLayers(getState, dispatch, newDataFilters);
|
||||
await syncDataForAllLayers(getState, dispatch, dataFilters);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
jest.mock('../selectors/map_selectors', () => ({}));
|
||||
jest.mock('../kibana_services', () => ({}));
|
||||
|
||||
import { mapExtentChanged } from './store_actions';
|
||||
|
||||
|
|
|
@ -13,7 +13,13 @@ import { timefilter } from 'ui/timefilter';
|
|||
import { Provider } from 'react-redux';
|
||||
import { getStore } from '../store/store';
|
||||
import { GisMap } from '../components/gis_map';
|
||||
import { setSelectedLayer, setTimeFilters, mapExtentChanged, replaceLayerList } from '../actions/store_actions';
|
||||
import {
|
||||
setSelectedLayer,
|
||||
setTimeFilters,
|
||||
setRefreshConfig,
|
||||
mapExtentChanged,
|
||||
replaceLayerList,
|
||||
} from '../actions/store_actions';
|
||||
import { getIsDarkTheme, updateFlyout, FLYOUT_STATE } from '../store/ui';
|
||||
import { Inspector } from 'ui/inspector';
|
||||
import { inspectorAdapters } from '../kibana_services';
|
||||
|
@ -21,7 +27,7 @@ import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_s
|
|||
import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal';
|
||||
import { showOptionsPopover } from '../components/top_nav/show_options_popover';
|
||||
import { toastNotifications } from 'ui/notify';
|
||||
import { getMapReady, getTimeFilters } from "../selectors/map_selectors";
|
||||
import { getMapReady } from "../selectors/map_selectors";
|
||||
|
||||
const REACT_ANCHOR_DOM_ELEMENT_ID = 'react-gis-root';
|
||||
|
||||
|
@ -57,6 +63,9 @@ app.controller('GisMapController', ($scope, $route, config, kbnUrl) => {
|
|||
zoom: mapState.zoom,
|
||||
center: mapState.center,
|
||||
}));
|
||||
if (mapState.refreshConfig) {
|
||||
store.dispatch(setRefreshConfig(mapState.refreshConfig));
|
||||
}
|
||||
}
|
||||
|
||||
const root = document.getElementById(REACT_ANCHOR_DOM_ELEMENT_ID);
|
||||
|
@ -73,12 +82,6 @@ app.controller('GisMapController', ($scope, $route, config, kbnUrl) => {
|
|||
updateTheme();
|
||||
}
|
||||
|
||||
const storeTime = getTimeFilters(store.getState());
|
||||
const kbnTime = timefilter.getTime();
|
||||
if (storeTime && (storeTime.to !== kbnTime.to || storeTime.from !== kbnTime.from)) {
|
||||
timefilter.setTime(storeTime);
|
||||
}
|
||||
|
||||
// Part of initial syncing of store from saved object
|
||||
// Delayed until after map is ready so map extent is known
|
||||
if (!isLayersListInitializedFromSavedObject && getMapReady(store.getState())) {
|
||||
|
@ -88,13 +91,10 @@ app.controller('GisMapController', ($scope, $route, config, kbnUrl) => {
|
|||
}
|
||||
}
|
||||
|
||||
timefilter.on('timeUpdate', dispatchTimeUpdate);
|
||||
|
||||
$scope.$on('$destroy', () => {
|
||||
if (unsubscribe) {
|
||||
unsubscribe();
|
||||
}
|
||||
timefilter.off('timeUpdate', dispatchTimeUpdate);
|
||||
const node = document.getElementById(REACT_ANCHOR_DOM_ELEMENT_ID);
|
||||
if (node) {
|
||||
unmountComponentAtNode(node);
|
||||
|
@ -192,12 +192,6 @@ app.controller('GisMapController', ($scope, $route, config, kbnUrl) => {
|
|||
timefilter.enableTimeRangeSelector();
|
||||
timefilter.enableAutoRefreshSelector();
|
||||
|
||||
async function dispatchTimeUpdate() {
|
||||
const timeFilters = timefilter.getTime();
|
||||
const store = await getStore();
|
||||
store.dispatch(setTimeFilters(timeFilters));
|
||||
}
|
||||
|
||||
function updateTheme() {
|
||||
$scope.$evalAsync(() => {
|
||||
isDarkTheme ? setDarkTheme() : setLightTheme();
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
getMapCenter,
|
||||
getLayerListRaw,
|
||||
getMapExtent,
|
||||
getRefreshConfig,
|
||||
} from '../../selectors/map_selectors';
|
||||
import { getIsDarkTheme } from '../../store/ui';
|
||||
import { TileStyle } from '../../shared/layers/styles/tile_style';
|
||||
|
@ -95,6 +96,7 @@ module.factory('SavedGisMap', function (Private) {
|
|||
zoom: getMapZoom(state),
|
||||
center: getMapCenter(state),
|
||||
timeFilters: getTimeFilters(state),
|
||||
refreshConfig: getRefreshConfig(state),
|
||||
});
|
||||
|
||||
this.uiStateJSON = JSON.stringify({
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { GisMap } from './view';
|
||||
import { getFlyoutDisplay, FLYOUT_STATE } from '../../store/ui';
|
||||
import {
|
||||
setTimeFiltersToKbnGlobalTime,
|
||||
triggerRefreshTimer,
|
||||
setRefreshConfig
|
||||
} from '../../actions/store_actions';
|
||||
|
||||
function mapStateToProps(state = {}) {
|
||||
const flyoutDisplay = getFlyoutDisplay(state);
|
||||
|
@ -17,5 +22,13 @@ function mapStateToProps(state = {}) {
|
|||
};
|
||||
}
|
||||
|
||||
const connectedGisMap = connect(mapStateToProps)(GisMap);
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
setTimeFiltersToKbnGlobalTime: () => dispatch(setTimeFiltersToKbnGlobalTime()),
|
||||
triggerRefreshTimer: () => dispatch(triggerRefreshTimer()),
|
||||
setRefreshConfig: (({ isPaused, interval }) => dispatch(setRefreshConfig({ isPaused, interval }))),
|
||||
};
|
||||
}
|
||||
|
||||
const connectedGisMap = connect(mapStateToProps, mapDispatchToProps)(GisMap);
|
||||
export { connectedGisMap as GisMap };
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import { MBMapContainer } from '../map/mb';
|
||||
import { LayerControl } from '../layer_control/index';
|
||||
import { LayerPanel } from '../layer_panel/index';
|
||||
|
@ -12,40 +12,81 @@ import { AddLayerPanel } from '../layer_addpanel/index';
|
|||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { Toasts } from '../toasts';
|
||||
|
||||
import { timeService } from '../../kibana_services';
|
||||
|
||||
export function GisMap(props) {
|
||||
const {
|
||||
layerDetailsVisible,
|
||||
addLayerVisible,
|
||||
noFlyoutVisible
|
||||
} = props;
|
||||
export class GisMap extends Component {
|
||||
|
||||
let currentPanel;
|
||||
let currentPanelClassName;
|
||||
componentDidMount() {
|
||||
timeService.on('timeUpdate', this.props.setTimeFiltersToKbnGlobalTime);
|
||||
timeService.on('refreshIntervalUpdate', this.setRefreshTimer);
|
||||
this.setRefreshTimer();
|
||||
}
|
||||
|
||||
if (noFlyoutVisible) {
|
||||
currentPanel = null;
|
||||
} else if (addLayerVisible) {
|
||||
currentPanelClassName = "gisLayerPanel-isVisible";
|
||||
currentPanel = <AddLayerPanel/>;
|
||||
} else if (layerDetailsVisible) {
|
||||
currentPanelClassName = "gisLayerPanel-isVisible";
|
||||
currentPanel = (
|
||||
<LayerPanel/>
|
||||
componentWillUnmount() {
|
||||
timeService.off('timeUpdate', this.props.setTimeFiltersToKbnGlobalTime);
|
||||
timeService.off('refreshIntervalUpdate', this.setRefreshTimer);
|
||||
this.clearRefreshTimer();
|
||||
}
|
||||
|
||||
setRefreshTimer = () => {
|
||||
this.clearRefreshTimer();
|
||||
|
||||
const { value, pause } = timeService.getRefreshInterval();
|
||||
if (!pause && value > 0) {
|
||||
this.refreshTimerId = setInterval(
|
||||
() => {
|
||||
this.props.triggerRefreshTimer();
|
||||
},
|
||||
value
|
||||
);
|
||||
}
|
||||
|
||||
this.props.setRefreshConfig({
|
||||
isPaused: pause,
|
||||
interval: value,
|
||||
});
|
||||
}
|
||||
|
||||
clearRefreshTimer = () => {
|
||||
if (this.refreshTimerId) {
|
||||
clearInterval(this.refreshTimerId);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
layerDetailsVisible,
|
||||
addLayerVisible,
|
||||
noFlyoutVisible
|
||||
} = this.props;
|
||||
|
||||
let currentPanel;
|
||||
let currentPanelClassName;
|
||||
|
||||
if (noFlyoutVisible) {
|
||||
currentPanel = null;
|
||||
} else if (addLayerVisible) {
|
||||
currentPanelClassName = "gisLayerPanel-isVisible";
|
||||
currentPanel = <AddLayerPanel/>;
|
||||
} else if (layerDetailsVisible) {
|
||||
currentPanelClassName = "gisLayerPanel-isVisible";
|
||||
currentPanel = (
|
||||
<LayerPanel/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="none" responsive={false}>
|
||||
<EuiFlexItem className="gisMapWrapper">
|
||||
<MBMapContainer/>
|
||||
<LayerControl/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem className={`gisLayerPanel ${currentPanelClassName}`} grow={false}>
|
||||
{currentPanel}
|
||||
</EuiFlexItem>
|
||||
|
||||
<Toasts/>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="none" responsive={false}>
|
||||
<EuiFlexItem className="gisMapWrapper">
|
||||
<MBMapContainer/>
|
||||
<LayerControl/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem className={`gisLayerPanel ${currentPanelClassName}`} grow={false}>
|
||||
{currentPanel}
|
||||
</EuiFlexItem>
|
||||
|
||||
<Toasts/>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -119,6 +119,10 @@ export const getMapColors = ({ map }) => {
|
|||
export const getTimeFilters = ({ map }) => map.mapState.timeFilters ?
|
||||
map.mapState.timeFilters : timefilter.getTime();
|
||||
|
||||
export const getRefreshConfig = ({ map }) => map.mapState.refreshConfig;
|
||||
|
||||
export const getRefreshTimerLastTriggeredAt = ({ map }) => map.mapState.refreshTimerLastTriggeredAt;
|
||||
|
||||
export const getMetadata = ({ config }) => config && config.meta;
|
||||
|
||||
export const getDataFilters = createSelector(
|
||||
|
@ -126,12 +130,14 @@ export const getDataFilters = createSelector(
|
|||
getMapBuffer,
|
||||
getMapZoom,
|
||||
getTimeFilters,
|
||||
(mapExtent, mapBuffer, mapZoom, timeFilters) => {
|
||||
getRefreshTimerLastTriggeredAt,
|
||||
(mapExtent, mapBuffer, mapZoom, timeFilters, refreshTimerLastTriggeredAt) => {
|
||||
return {
|
||||
extent: mapExtent,
|
||||
buffer: mapBuffer,
|
||||
zoom: mapZoom,
|
||||
timeFilters: timeFilters
|
||||
timeFilters,
|
||||
refreshTimerLastTriggeredAt,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
|
|
@ -100,10 +100,13 @@ export class HeatmapLayer extends ALayer {
|
|||
|
||||
const isSameTime = _.isEqual(dataMeta.timeFilters, dataFilters.timeFilters);
|
||||
|
||||
const updateDueToRefreshTimer = dataFilters.refreshTimerLastTriggeredAt
|
||||
&& !_.isEqual(dataMeta.refreshTimerLastTriggeredAt, dataFilters.refreshTimerLastTriggeredAt);
|
||||
|
||||
const updateDueToExtent = this.updateDueToExtent(this._source, dataMeta, dataFilters);
|
||||
|
||||
|
||||
if (isSamePrecision && isSameTime && !updateDueToExtent) {
|
||||
if (isSamePrecision && isSameTime && !updateDueToExtent && !updateDueToRefreshTimer) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,10 @@ export class ESGeohashGridSource extends VectorSource {
|
|||
return true;
|
||||
}
|
||||
|
||||
isRefreshTimerAware() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getFieldNames() {
|
||||
return this.getMetricFields().map(({ propertyKey }) => {
|
||||
return propertyKey;
|
||||
|
|
|
@ -157,10 +157,14 @@ export class ESJoinSource extends ASource {
|
|||
}
|
||||
|
||||
isFilterByMapBounds() {
|
||||
//todo
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
isRefreshTimerAware() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getJoinDescription(leftSourceName, leftFieldName) {
|
||||
const metrics = this._getValidMetrics().map(metric => {
|
||||
return metric.type !== 'count' ? `${metric.type}(${metric.field})` : 'count(*)';
|
||||
|
|
|
@ -72,6 +72,10 @@ export class ESSearchSource extends VectorSource {
|
|||
return true;
|
||||
}
|
||||
|
||||
isRefreshTimerAware() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getFieldNames() {
|
||||
return [
|
||||
this._descriptor.geoField,
|
||||
|
|
|
@ -43,6 +43,10 @@ export class ASource {
|
|||
return false;
|
||||
}
|
||||
|
||||
isRefreshTimerAware() {
|
||||
return false;
|
||||
}
|
||||
|
||||
getFieldNames() {
|
||||
return [];
|
||||
}
|
||||
|
|
|
@ -166,10 +166,11 @@ export class VectorLayer extends ALayer {
|
|||
|
||||
async _canSkipSourceUpdate(source, sourceDataId, filters) {
|
||||
const timeAware = await source.isTimeAware();
|
||||
const refreshTimerAware = await source.isRefreshTimerAware();
|
||||
const extentAware = source.isFilterByMapBounds();
|
||||
const isFieldAware = source.isFieldAware();
|
||||
|
||||
if (!timeAware && !extentAware && !isFieldAware) {
|
||||
if (!timeAware && !refreshTimerAware && !extentAware && !isFieldAware) {
|
||||
const sourceDataRequest = this._findDataRequestForSource(sourceDataId);
|
||||
if (sourceDataRequest && sourceDataRequest.hasDataOrRequestInProgress()) {
|
||||
return true;
|
||||
|
@ -192,13 +193,20 @@ export class VectorLayer extends ALayer {
|
|||
updateDueToTime = !_.isEqual(meta.timeFilters, filters.timeFilters);
|
||||
}
|
||||
|
||||
let updateDueToRefreshTimer = false;
|
||||
if (refreshTimerAware && filters.refreshTimerLastTriggeredAt) {
|
||||
updateDueToRefreshTimer = !_.isEqual(meta.refreshTimerLastTriggeredAt, filters.refreshTimerLastTriggeredAt);
|
||||
}
|
||||
|
||||
let updateDueToFields = false;
|
||||
if (isFieldAware) {
|
||||
updateDueToFields = !_.isEqual(meta.fieldNames, filters.fieldNames);
|
||||
}
|
||||
|
||||
return !updateDueToTime && !this.updateDueToExtent(source, meta, filters) && !updateDueToFields;
|
||||
|
||||
return !updateDueToTime
|
||||
&& !updateDueToRefreshTimer
|
||||
&& !this.updateDueToExtent(source, meta, filters)
|
||||
&& !updateDueToFields;
|
||||
}
|
||||
|
||||
async _syncJoin(join, { startLoading, stopLoading, onLoadError, dataFilters }) {
|
||||
|
|
|
@ -26,7 +26,9 @@ import {
|
|||
SET_JOINS,
|
||||
TOUCH_LAYER,
|
||||
UPDATE_LAYER_ALPHA_VALUE,
|
||||
UPDATE_SOURCE_PROP
|
||||
UPDATE_SOURCE_PROP,
|
||||
SET_REFRESH_CONFIG,
|
||||
TRIGGER_REFRESH_TIMER,
|
||||
} from "../actions/store_actions";
|
||||
|
||||
const getLayerIndex = (list, layerId) => list.findIndex(({ id }) => layerId === id);
|
||||
|
@ -76,6 +78,8 @@ const INITIAL_STATE = {
|
|||
},
|
||||
extent: null,
|
||||
timeFilters: null,
|
||||
refreshConfig: null,
|
||||
refreshTimerLastTriggeredAt: null,
|
||||
},
|
||||
selectedLayerId: null,
|
||||
layerList: []
|
||||
|
@ -119,6 +123,26 @@ export function map(state = INITIAL_STATE, action) {
|
|||
case SET_TIME_FILTERS:
|
||||
const { from, to } = action;
|
||||
return { ...state, mapState: { ...state.mapState, timeFilters: { from, to } } };
|
||||
case SET_REFRESH_CONFIG:
|
||||
const { isPaused, interval } = action;
|
||||
return {
|
||||
...state,
|
||||
mapState: {
|
||||
...state.mapState,
|
||||
refreshConfig: {
|
||||
isPaused,
|
||||
interval,
|
||||
}
|
||||
}
|
||||
};
|
||||
case TRIGGER_REFRESH_TIMER:
|
||||
return {
|
||||
...state,
|
||||
mapState: {
|
||||
...state.mapState,
|
||||
refreshTimerLastTriggeredAt: (new Date()).toISOString(),
|
||||
}
|
||||
};
|
||||
case SET_SELECTED_LAYER:
|
||||
const match = state.layerList.find(layer => layer.id === action.selectedLayerId);
|
||||
return { ...state, selectedLayerId: match ? action.selectedLayerId : null };
|
||||
|
|
|
@ -12,6 +12,14 @@ export default function ({ getPageObjects }) {
|
|||
|
||||
describe('layer geohashgrid aggregation source', () => {
|
||||
|
||||
async function getRequestTimestamp() {
|
||||
await PageObjects.gis.openInspectorRequestsView();
|
||||
const requestStats = await PageObjects.gis.getInspectorTableData();
|
||||
const requestTimestamp = PageObjects.gis.getInspectorStatRowHit(requestStats, 'Request timestamp');
|
||||
await PageObjects.gis.closeInspector();
|
||||
return requestTimestamp;
|
||||
}
|
||||
|
||||
describe('heatmap', () => {
|
||||
before(async () => {
|
||||
await PageObjects.gis.loadSavedMap('geohashgrid heatmap example');
|
||||
|
@ -25,6 +33,14 @@ export default function ({ getPageObjects }) {
|
|||
const EXPECTED_NUMBER_FEATURES = 6;
|
||||
const HEATMAP_PROP_NAME = '__kbn_heatmap_weight__';
|
||||
|
||||
it('should re-fetch geohashgrid aggregation with refresh timer', async () => {
|
||||
const beforeRefreshTimerTimestamp = await getRequestTimestamp();
|
||||
expect(beforeRefreshTimerTimestamp.length).to.be(24);
|
||||
await PageObjects.gis.triggerSingleRefresh(1000);
|
||||
const afterRefreshTimerTimestamp = await getRequestTimestamp();
|
||||
expect(beforeRefreshTimerTimestamp).not.to.equal(afterRefreshTimerTimestamp);
|
||||
});
|
||||
|
||||
it('should decorate feature properties with scaled doc_count property', async () => {
|
||||
const mapboxStyle = await PageObjects.gis.getMapboxStyle();
|
||||
expect(mapboxStyle.sources[LAYER_ID].data.features.length).to.equal(EXPECTED_NUMBER_FEATURES);
|
||||
|
@ -72,6 +88,14 @@ export default function ({ getPageObjects }) {
|
|||
const EXPECTED_NUMBER_FEATURES = 6;
|
||||
const MAX_OF_BYTES_PROP_NAME = 'max_of_bytes';
|
||||
|
||||
it('should re-fetch geohashgrid aggregation with refresh timer', async () => {
|
||||
const beforeRefreshTimerTimestamp = await getRequestTimestamp();
|
||||
expect(beforeRefreshTimerTimestamp.length).to.be(24);
|
||||
await PageObjects.gis.triggerSingleRefresh(1000);
|
||||
const afterRefreshTimerTimestamp = await getRequestTimestamp();
|
||||
expect(beforeRefreshTimerTimestamp).not.to.equal(afterRefreshTimerTimestamp);
|
||||
});
|
||||
|
||||
it('should decorate feature properties with metrics properterties', async () => {
|
||||
const mapboxStyle = await PageObjects.gis.getMapboxStyle();
|
||||
expect(mapboxStyle.sources[LAYER_ID].data.features.length).to.equal(EXPECTED_NUMBER_FEATURES);
|
||||
|
|
|
@ -11,19 +11,34 @@ export default function ({ getPageObjects }) {
|
|||
|
||||
describe('elasticsearch document layer', () => {
|
||||
before(async () => {
|
||||
await PageObjects.gis.loadSavedMap('logstash events');
|
||||
await PageObjects.gis.loadSavedMap('document example');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await PageObjects.gis.closeInspector();
|
||||
});
|
||||
|
||||
it('should re-fetch geohashgrid aggregation with refresh timer', async () => {
|
||||
async function getRequestTimestamp() {
|
||||
await PageObjects.gis.openInspectorRequestsView();
|
||||
const requestStats = await PageObjects.gis.getInspectorTableData();
|
||||
const requestTimestamp = PageObjects.gis.getInspectorStatRowHit(requestStats, 'Request timestamp');
|
||||
await PageObjects.gis.closeInspector();
|
||||
return requestTimestamp;
|
||||
}
|
||||
const beforeRefreshTimerTimestamp = await getRequestTimestamp();
|
||||
expect(beforeRefreshTimerTimestamp.length).to.be(24);
|
||||
await PageObjects.gis.triggerSingleRefresh(1000);
|
||||
const afterRefreshTimerTimestamp = await getRequestTimestamp();
|
||||
expect(beforeRefreshTimerTimestamp).not.to.equal(afterRefreshTimerTimestamp);
|
||||
});
|
||||
|
||||
describe('inspector', () => {
|
||||
it('should register elasticsearch request in inspector', async () => {
|
||||
await PageObjects.gis.openInspectorRequestsView();
|
||||
const requestStats = await PageObjects.gis.getInspectorTableData();
|
||||
const hits = PageObjects.gis.getInspectorStatRowHit(requestStats, 'Hits');
|
||||
expect(hits).to.equal('2048');
|
||||
expect(hits).to.equal('6');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -32,7 +32,6 @@ export default function ({ loadTestFile, getService }) {
|
|||
|
||||
loadTestFile(require.resolve('./saved_object_management'));
|
||||
loadTestFile(require.resolve('./sample_data'));
|
||||
loadTestFile(require.resolve('./load_saved_object'));
|
||||
loadTestFile(require.resolve('./es_search_source'));
|
||||
loadTestFile(require.resolve('./es_geohashgrid_source'));
|
||||
loadTestFile(require.resolve('./joins'));
|
||||
|
|
|
@ -25,6 +25,22 @@ export default function ({ getPageObjects }) {
|
|||
await PageObjects.gis.closeInspector();
|
||||
});
|
||||
|
||||
it('should re-fetch join with refresh timer', async () => {
|
||||
async function getRequestTimestamp() {
|
||||
await PageObjects.gis.openInspectorRequest('meta_for_geo_shapes*.shape_name');
|
||||
const requestStats = await PageObjects.gis.getInspectorTableData();
|
||||
const requestTimestamp = PageObjects.gis.getInspectorStatRowHit(requestStats, 'Request timestamp');
|
||||
await PageObjects.gis.closeInspector();
|
||||
return requestTimestamp;
|
||||
}
|
||||
|
||||
const beforeRefreshTimerTimestamp = await getRequestTimestamp();
|
||||
expect(beforeRefreshTimerTimestamp.length).to.be(24);
|
||||
await PageObjects.gis.triggerSingleRefresh(1000);
|
||||
const afterRefreshTimerTimestamp = await getRequestTimestamp();
|
||||
expect(beforeRefreshTimerTimestamp).not.to.equal(afterRefreshTimerTimestamp);
|
||||
});
|
||||
|
||||
it('should decorate feature properties with join property', async () => {
|
||||
const mapboxStyle = await PageObjects.gis.getMapboxStyle();
|
||||
expect(mapboxStyle.sources.n1t6f.data.features.length).to.equal(3);
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import expect from 'expect.js';
|
||||
|
||||
export default function ({ getPageObjects }) {
|
||||
const PageObjects = getPageObjects(['gis', 'header']);
|
||||
|
||||
describe('load gis-map saved objects', () => {
|
||||
before(async () => {
|
||||
await PageObjects.gis.loadSavedMap('logstash events');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await PageObjects.gis.closeInspector();
|
||||
});
|
||||
|
||||
describe('mapState', () => {
|
||||
it('should update Kibana time to time defined in mapState', async () => {
|
||||
const prettyPrint = await PageObjects.header.getPrettyDuration();
|
||||
expect(prettyPrint).to.equal('September 20th 2015, 00:00:00.000 to September 23rd 2015, 00:00:00.000');
|
||||
});
|
||||
|
||||
// TODO verify map center and zoom
|
||||
|
||||
// TODO verify map coordinate system
|
||||
});
|
||||
|
||||
// TODO verify ui state like dark mode
|
||||
});
|
||||
}
|
|
@ -8,7 +8,7 @@ import expect from 'expect.js';
|
|||
|
||||
export default function ({ getPageObjects }) {
|
||||
|
||||
const PageObjects = getPageObjects(['gis']);
|
||||
const PageObjects = getPageObjects(['gis', 'header']);
|
||||
|
||||
describe('gis-map saved object management', () => {
|
||||
|
||||
|
@ -16,6 +16,34 @@ export default function ({ getPageObjects }) {
|
|||
const MAP1_NAME = `${MAP_NAME_PREFIX}map1`;
|
||||
const MAP2_NAME = `${MAP_NAME_PREFIX}map2`;
|
||||
|
||||
describe('read', () => {
|
||||
before(async () => {
|
||||
await PageObjects.gis.loadSavedMap('join example');
|
||||
});
|
||||
|
||||
it('should update global Kibana time to value stored with map', async () => {
|
||||
const kibanaTime = await PageObjects.header.getPrettyDuration();
|
||||
expect(kibanaTime).to.equal('Last 17m');
|
||||
});
|
||||
|
||||
it('should update global Kibana refresh config to value stored with map', async () => {
|
||||
const kibanaRefreshConfig = await PageObjects.header.getRefreshConfig();
|
||||
expect(kibanaRefreshConfig).to.equal('inactive 1 second');
|
||||
});
|
||||
|
||||
it('should set map location to value stored with map', async () => {
|
||||
const { lat, lon, zoom } = await PageObjects.gis.getView();
|
||||
expect(lat).to.equal('-0.04647');
|
||||
expect(lon).to.equal('77.33426');
|
||||
expect(zoom).to.equal('3.02');
|
||||
});
|
||||
|
||||
it('should load map layers stored with map', async () => {
|
||||
const layerExists = await PageObjects.gis.doesLayerExist('geo_shapes*');
|
||||
expect(layerExists).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('create', () => {
|
||||
it('should allow saving map', async () => {
|
||||
await PageObjects.gis.openNewMap();
|
||||
|
|
|
@ -72,10 +72,10 @@
|
|||
"source": {
|
||||
"type" : "gis-map",
|
||||
"gis-map" : {
|
||||
"title" : "logstash events",
|
||||
"title" : "document example",
|
||||
"description" : "",
|
||||
"mapStateJSON" : "{\"zoom\":4,\"center\":{\"lon\":-100.41,\"lat\":32.82},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-23T00:00:00.000Z\"}}",
|
||||
"layerListJSON" : "[{\"id\":\"0hmz5\",\"label\":\"EMS base layer (road_map)\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"tmsy6\",\"label\":\"logstash events\",\"showAtAllZoomLevels\":false,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"type\":\"ES_SEARCH\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"showTooltip\":true,\"tooltipProperties\":[]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}}},\"previousStyle\":null},\"type\":\"VECTOR\"}]",
|
||||
"mapStateJSON" : "{\"zoom\":4.1,\"center\":{\"lon\":-100.61091,\"lat\":33.23887},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}",
|
||||
"layerListJSON" : "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"z52lq\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"e1a5e1a6-676c-4a89-8ea9-0d91d64b73c6\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"showTooltip\":true,\"tooltipProperties\":[]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"alphaValue\":1},\"previousStyle\":null},\"type\":\"VECTOR\"}]",
|
||||
"uiStateJSON" : "{\"isDarkMode\":false}",
|
||||
"bounds" : {
|
||||
"type" : "envelope",
|
||||
|
@ -106,7 +106,7 @@
|
|||
"gis-map" : {
|
||||
"title" : "join example",
|
||||
"description" : "",
|
||||
"mapStateJSON" : "{\"zoom\":3.02,\"center\":{\"lon\":77.33426,\"lat\":-0.04647},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\",\"mode\":\"quick\"}}",
|
||||
"mapStateJSON" : "{\"zoom\":3.02,\"center\":{\"lon\":77.33426,\"lat\":-0.04647},\"timeFilters\":{\"from\":\"now-17m\",\"to\":\"now\",\"mode\":\"quick\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}",
|
||||
"layerListJSON" : "[{\"id\":\"0hmz5\",\"label\":\"EMS base layer (road_map)\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"n1t6f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"62eca1fc-fe42-11e8-8eb2-f2801f1b9fd1\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"561253e0-f731-11e8-8487-11b9dd924f96\",\"geoField\":\"geometry\",\"limit\":2048,\"filterByMapBounds\":false,\"showTooltip\":true,\"tooltipProperties\":[]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max(prop1) group by meta_for_geo_shapes*.shape_name\",\"name\":\"__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name\",\"origin\":\"join\"},\"color\":\"Blues\"}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"alphaValue\":1},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\",\"joins\":[{\"leftField\":\"name\",\"right\":{\"id\":\"855ccb86-fe42-11e8-8eb2-f2801f1b9fd1\",\"indexPatternId\":\"e20b2a30-f735-11e8-8ce0-9723965e01e3\",\"indexPatternTitle\":\"meta_for_geo_shapes*\",\"term\":\"shape_name\",\"metrics\":[{\"type\":\"max\",\"field\":\"prop1\"}]}}]}]",
|
||||
"uiStateJSON" : "{\"isDarkMode\":false}",
|
||||
"bounds" : {
|
||||
|
@ -137,7 +137,7 @@
|
|||
"type" : "gis-map",
|
||||
"gis-map" : {
|
||||
"title" : "geohashgrid heatmap example",
|
||||
"mapStateJSON" : "{\"zoom\":3.59,\"center\":{\"lon\":-98.05765,\"lat\":38.32288},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"}}",
|
||||
"mapStateJSON" : "{\"zoom\":3.59,\"center\":{\"lon\":-98.05765,\"lat\":38.32288},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}",
|
||||
"layerListJSON" : "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"3xlvm\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"type\":\"ES_GEOHASH_GRID\",\"id\":\"427aa49d-a552-4e7d-a629-67c47db27128\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"heatmap\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"HEATMAP\",\"refinement\":\"coarse\",\"properties\":{\"alphaValue\":1},\"previousStyle\":null},\"type\":\"HEATMAP\"}]",
|
||||
"uiStateJSON" : "{\"isDarkMode\":false}",
|
||||
"bounds" : {
|
||||
|
@ -169,7 +169,7 @@
|
|||
"gis-map" : {
|
||||
"title" : "geohashgrid vector grid example",
|
||||
"description" : "",
|
||||
"mapStateJSON" : "{\"zoom\":3.59,\"center\":{\"lon\":-98.05765,\"lat\":38.32288},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"}}",
|
||||
"mapStateJSON" : "{\"zoom\":3.59,\"center\":{\"lon\":-98.05765,\"lat\":38.32288},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}",
|
||||
"layerListJSON" : "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"g1xkv\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"type\":\"ES_GEOHASH_GRID\",\"id\":\"9305f6ea-4518-4c06-95b9-33321aa38d6a\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"metrics\":[{\"type\":\"count\"},{\"type\":\"max\",\"field\":\"bytes\"}]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max of bytes\",\"name\":\"max_of_bytes\",\"origin\":\"source\"},\"color\":\"Blues\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#cccccc\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":4,\"maxSize\":32}},\"alphaValue\":1},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\"}]",
|
||||
"uiStateJSON" : "{\"isDarkMode\":false}",
|
||||
"bounds" : {
|
||||
|
|
|
@ -107,26 +107,23 @@ export function GisPageProvider({ getService, getPageObjects }) {
|
|||
async setView(lat, lon, zoom) {
|
||||
log.debug(`Set view lat: ${lat}, lon: ${lon}, zoom: ${zoom}`);
|
||||
await testSubjects.click('toggleSetViewVisibilityButton');
|
||||
|
||||
const latInput = await testSubjects.find('latitudeInput');
|
||||
await latInput.clearValue();
|
||||
await latInput.click();
|
||||
await latInput.type(lat);
|
||||
|
||||
const lonInput = await testSubjects.find('longitudeInput');
|
||||
await lonInput.clearValue();
|
||||
await lonInput.click();
|
||||
await lonInput.type(lon);
|
||||
|
||||
const zoomInput = await testSubjects.find('zoomInput');
|
||||
await zoomInput.clearValue();
|
||||
await zoomInput.click();
|
||||
await zoomInput.type(zoom);
|
||||
|
||||
await testSubjects.setValue('latitudeInput', lat);
|
||||
await testSubjects.setValue('longitudeInput', lon);
|
||||
await testSubjects.setValue('zoomInput', zoom);
|
||||
await testSubjects.click('submitViewButton');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async getView() {
|
||||
log.debug('Get view');
|
||||
await testSubjects.click('toggleSetViewVisibilityButton');
|
||||
const lat = await testSubjects.getAttribute('latitudeInput', 'value');
|
||||
const lon = await testSubjects.getAttribute('longitudeInput', 'value');
|
||||
const zoom = await testSubjects.getAttribute('zoomInput', 'value');
|
||||
await testSubjects.click('toggleSetViewVisibilityButton');
|
||||
return { lat, lon, zoom };
|
||||
}
|
||||
|
||||
async openLayerPanel(layerName) {
|
||||
log.debug(`Open layer panel, layer: ${layerName}`);
|
||||
await testSubjects.click(`mapOpenLayerButton${layerName}`);
|
||||
|
@ -245,6 +242,14 @@ export function GisPageProvider({ getService, getPageObjects }) {
|
|||
return statsRow[STATS_ROW_VALUE_INDEX];
|
||||
}
|
||||
|
||||
async triggerSingleRefresh(refreshInterval) {
|
||||
log.debug(`triggerSingleRefresh, refreshInterval: ${refreshInterval}`);
|
||||
await PageObjects.header.resumeAutoRefresh();
|
||||
log.debug('waiting to give time for refresh timer to fire');
|
||||
await PageObjects.common.sleep(refreshInterval + (refreshInterval / 2));
|
||||
await PageObjects.header.pauseAutoRefresh();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
}
|
||||
return new GisPage();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue