mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Variables: migrates interval variable type to React/Redux (#22797)
* Feature: migrates interval variable type to React/Redux
This commit is contained in:
parent
fd99bfab1d
commit
fb789e8398
@ -16,6 +16,7 @@ import { createCustomVariableAdapter } from '../variables/custom/adapter';
|
||||
import { createTextBoxVariableAdapter } from '../variables/textbox/adapter';
|
||||
import { createConstantVariableAdapter } from '../variables/constant/adapter';
|
||||
import { createDataSourceVariableAdapter } from '../variables/datasource/adapter';
|
||||
import { createIntervalVariableAdapter } from '../variables/interval/adapter';
|
||||
|
||||
coreModule.factory('templateSrv', () => templateSrv);
|
||||
|
||||
@ -35,3 +36,4 @@ variableAdapters.set('custom', createCustomVariableAdapter());
|
||||
variableAdapters.set('textbox', createTextBoxVariableAdapter());
|
||||
variableAdapters.set('constant', createConstantVariableAdapter());
|
||||
variableAdapters.set('datasource', createDataSourceVariableAdapter());
|
||||
variableAdapters.set('interval', createIntervalVariableAdapter());
|
||||
|
@ -23,13 +23,13 @@ export interface VariableAdapter<Model extends VariableModel> {
|
||||
}
|
||||
|
||||
const allVariableAdapters: Record<VariableType, VariableAdapter<any> | null> = {
|
||||
interval: null,
|
||||
query: null,
|
||||
textbox: null,
|
||||
constant: null,
|
||||
datasource: null,
|
||||
custom: null,
|
||||
interval: null,
|
||||
constant: null,
|
||||
adhoc: null,
|
||||
textbox: null,
|
||||
};
|
||||
|
||||
export interface VariableAdapters {
|
||||
|
@ -44,7 +44,7 @@ describe('constant actions', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating([variable]))
|
||||
.whenAsyncActionIsDispatched(updateConstantVariableOptions(toVariablePayload(variable)), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [createAction, setCurrentAction] = actions;
|
||||
const expectedNumberOfActions = 2;
|
||||
|
||||
|
@ -57,7 +57,7 @@ describe('custom actions', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating([variable]))
|
||||
.whenAsyncActionIsDispatched(updateCustomVariableOptions(toVariablePayload(variable)), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [createAction, setCurrentAction] = actions;
|
||||
const expectedNumberOfActions = 2;
|
||||
|
||||
|
@ -52,7 +52,7 @@ describe('data source actions', () => {
|
||||
true
|
||||
);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
createDataSourceOptions(
|
||||
toVariablePayload({ type: 'datasource', uuid: '0' }, { sources, regex: (undefined as unknown) as RegExp })
|
||||
),
|
||||
@ -103,7 +103,7 @@ describe('data source actions', () => {
|
||||
true
|
||||
);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
createDataSourceOptions(
|
||||
toVariablePayload({ type: 'datasource', uuid: '0' }, { sources, regex: /.*(second-name).*/ })
|
||||
),
|
||||
@ -157,7 +157,7 @@ describe('data source actions', () => {
|
||||
.givenRootReducer(getTemplatingRootReducer())
|
||||
.whenAsyncActionIsDispatched(initDataSourceVariableEditor(dependencies));
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
changeVariableEditorExtended({
|
||||
propName: 'dataSourceTypes',
|
||||
propValue: [
|
||||
|
@ -0,0 +1,119 @@
|
||||
import React, { ChangeEvent, FocusEvent, PureComponent } from 'react';
|
||||
|
||||
import { IntervalVariableModel } from '../../templating/variable';
|
||||
import { VariableEditorProps } from '../editor/types';
|
||||
import { FormLabel, Switch } from '@grafana/ui';
|
||||
|
||||
export interface Props extends VariableEditorProps<IntervalVariableModel> {}
|
||||
|
||||
export class IntervalVariableEditor extends PureComponent<Props> {
|
||||
onAutoChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
this.props.onPropChange({
|
||||
propName: 'auto',
|
||||
propValue: event.target.checked,
|
||||
updateOptions: true,
|
||||
});
|
||||
};
|
||||
|
||||
onQueryChanged = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
this.props.onPropChange({
|
||||
propName: 'query',
|
||||
propValue: event.target.value,
|
||||
});
|
||||
};
|
||||
|
||||
onQueryBlur = (event: FocusEvent<HTMLInputElement>) => {
|
||||
this.props.onPropChange({
|
||||
propName: 'query',
|
||||
propValue: event.target.value,
|
||||
updateOptions: true,
|
||||
});
|
||||
};
|
||||
|
||||
onAutoCountChanged = (event: ChangeEvent<HTMLSelectElement>) => {
|
||||
this.props.onPropChange({
|
||||
propName: 'auto_count',
|
||||
propValue: event.target.value,
|
||||
updateOptions: true,
|
||||
});
|
||||
};
|
||||
|
||||
onAutoMinChanged = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
this.props.onPropChange({
|
||||
propName: 'auto_min',
|
||||
propValue: event.target.value,
|
||||
updateOptions: true,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<div className="gf-form-group">
|
||||
<h5 className="section-heading">Interval Options</h5>
|
||||
|
||||
<div className="gf-form">
|
||||
<span className="gf-form-label width-9">Values</span>
|
||||
<input
|
||||
type="text"
|
||||
className="gf-form-input"
|
||||
value={this.props.variable.query}
|
||||
placeholder="1m,10m,1h,6h,1d,7d"
|
||||
onChange={this.onQueryChanged}
|
||||
onBlur={this.onQueryBlur}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="gf-form-inline">
|
||||
<Switch
|
||||
label="Auto Option"
|
||||
labelClass="width-9"
|
||||
checked={this.props.variable.auto}
|
||||
onChange={this.onAutoChange}
|
||||
tooltip={'Enables multiple values to be selected at the same time'}
|
||||
/>
|
||||
|
||||
{this.props.variable.auto && (
|
||||
<>
|
||||
<div className="gf-form">
|
||||
<FormLabel
|
||||
width={9}
|
||||
tooltip={'How many times should the current time range be divided to calculate the value'}
|
||||
>
|
||||
Step count
|
||||
</FormLabel>
|
||||
<div className="gf-form-select-wrapper max-width-10">
|
||||
<select
|
||||
className="gf-form-input"
|
||||
value={this.props.variable.auto_count}
|
||||
onChange={this.onAutoCountChanged}
|
||||
>
|
||||
{[1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 100, 200, 300, 400, 500].map(count => (
|
||||
<option key={`auto_count_key-${count}`} label={`${count}`}>
|
||||
{count}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="gf-form">
|
||||
<FormLabel width={9} tooltip={'The calculated value will not go below this threshold'}>
|
||||
Min interval
|
||||
</FormLabel>
|
||||
<input
|
||||
type="text"
|
||||
className="gf-form-input max-width-10"
|
||||
value={this.props.variable.auto_min}
|
||||
onChange={this.onAutoMinChanged}
|
||||
placeholder="10s"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
188
public/app/features/variables/interval/actions.test.ts
Normal file
188
public/app/features/variables/interval/actions.test.ts
Normal file
@ -0,0 +1,188 @@
|
||||
import { getTemplatingRootReducer, variableMockBuilder } from '../state/helpers';
|
||||
import { reduxTester } from '../../../../test/core/redux/reduxTester';
|
||||
import { TemplatingState } from '../state/reducers';
|
||||
import { initDashboardTemplating } from '../state/actions';
|
||||
import { toVariableIdentifier } from '../state/types';
|
||||
import {
|
||||
updateAutoValue,
|
||||
UpdateAutoValueDependencies,
|
||||
updateIntervalVariableOptions,
|
||||
UpdateIntervalVariableOptionsDependencies,
|
||||
} from './actions';
|
||||
import { createIntervalOptions } from './reducer';
|
||||
import { setCurrentVariableValue } from '../state/sharedReducer';
|
||||
import { variableAdapters } from '../adapters';
|
||||
import { createIntervalVariableAdapter } from './adapter';
|
||||
import { Emitter } from 'app/core/core';
|
||||
import { AppEvents, dateTime } from '@grafana/data';
|
||||
import { getTimeSrv, setTimeSrv, TimeSrv } from '../../dashboard/services/TimeSrv';
|
||||
import { TemplateSrv } from '../../templating/template_srv';
|
||||
|
||||
describe('interval actions', () => {
|
||||
variableAdapters.set('interval', createIntervalVariableAdapter());
|
||||
describe('when updateIntervalVariableOptions is dispatched', () => {
|
||||
it('then correct actions are dispatched', async () => {
|
||||
const interval = variableMockBuilder('interval')
|
||||
.withUuid('0')
|
||||
.withQuery('1s,1m,1h,1d')
|
||||
.withAuto(false)
|
||||
.create();
|
||||
|
||||
const tester = await reduxTester<{ templating: TemplatingState }>()
|
||||
.givenRootReducer(getTemplatingRootReducer())
|
||||
.whenActionIsDispatched(initDashboardTemplating([interval]))
|
||||
.whenAsyncActionIsDispatched(updateIntervalVariableOptions(toVariableIdentifier(interval)), true);
|
||||
|
||||
tester.thenDispatchedActionsShouldEqual(
|
||||
createIntervalOptions({ type: 'interval', uuid: '0', data: undefined }),
|
||||
setCurrentVariableValue({
|
||||
type: 'interval',
|
||||
uuid: '0',
|
||||
data: { option: { text: '1s', value: '1s', selected: false } },
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when updateIntervalVariableOptions is dispatched but something throws', () => {
|
||||
it('then an app event should be emitted', async () => {
|
||||
const timeSrvMock = ({
|
||||
timeRange: jest.fn().mockReturnValue({
|
||||
from: dateTime(new Date())
|
||||
.subtract(1, 'days')
|
||||
.toDate(),
|
||||
to: new Date(),
|
||||
raw: {
|
||||
from: 'now-1d',
|
||||
to: 'now',
|
||||
},
|
||||
}),
|
||||
} as unknown) as TimeSrv;
|
||||
const originalTimeSrv = getTimeSrv();
|
||||
setTimeSrv(timeSrvMock);
|
||||
const interval = variableMockBuilder('interval')
|
||||
.withUuid('0')
|
||||
.withQuery('1s,1m,1h,1d')
|
||||
.withAuto(true)
|
||||
.withAutoMin('1') // illegal interval string
|
||||
.create();
|
||||
const appEventMock = ({
|
||||
emit: jest.fn(),
|
||||
} as unknown) as Emitter;
|
||||
const dependencies: UpdateIntervalVariableOptionsDependencies = { appEvents: appEventMock };
|
||||
|
||||
await reduxTester<{ templating: TemplatingState }>()
|
||||
.givenRootReducer(getTemplatingRootReducer())
|
||||
.whenActionIsDispatched(initDashboardTemplating([interval]))
|
||||
.whenAsyncActionIsDispatched(updateIntervalVariableOptions(toVariableIdentifier(interval), dependencies), true);
|
||||
|
||||
expect(appEventMock.emit).toHaveBeenCalledTimes(1);
|
||||
expect(appEventMock.emit).toHaveBeenCalledWith(AppEvents.alertError, [
|
||||
'Templating',
|
||||
'Invalid interval string, expecting a number followed by one of "Mwdhmsy"',
|
||||
]);
|
||||
setTimeSrv(originalTimeSrv);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when updateAutoValue is dispatched', () => {
|
||||
describe('and auto is false', () => {
|
||||
it('then no dependencies are called', async () => {
|
||||
const interval = variableMockBuilder('interval')
|
||||
.withUuid('0')
|
||||
.withAuto(false)
|
||||
.create();
|
||||
|
||||
const dependencies: UpdateAutoValueDependencies = {
|
||||
kbn: {
|
||||
calculateInterval: jest.fn(),
|
||||
},
|
||||
getTimeSrv: () => {
|
||||
return ({
|
||||
timeRange: jest.fn().mockReturnValue({
|
||||
from: '2001-01-01',
|
||||
to: '2001-01-02',
|
||||
raw: {
|
||||
from: '2001-01-01',
|
||||
to: '2001-01-02',
|
||||
},
|
||||
}),
|
||||
} as unknown) as TimeSrv;
|
||||
},
|
||||
templateSrv: ({
|
||||
setGrafanaVariable: jest.fn(),
|
||||
} as unknown) as TemplateSrv,
|
||||
};
|
||||
|
||||
await reduxTester<{ templating: TemplatingState }>()
|
||||
.givenRootReducer(getTemplatingRootReducer())
|
||||
.whenActionIsDispatched(initDashboardTemplating([interval]))
|
||||
.whenAsyncActionIsDispatched(updateAutoValue(toVariableIdentifier(interval), dependencies), true);
|
||||
|
||||
expect(dependencies.kbn.calculateInterval).toHaveBeenCalledTimes(0);
|
||||
expect(dependencies.getTimeSrv().timeRange).toHaveBeenCalledTimes(0);
|
||||
expect(dependencies.templateSrv.setGrafanaVariable).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('and auto is true', () => {
|
||||
it('then correct dependencies are called', async () => {
|
||||
const interval = variableMockBuilder('interval')
|
||||
.withUuid('0')
|
||||
.withName('intervalName')
|
||||
.withAuto(true)
|
||||
.withAutoCount(33)
|
||||
.withAutoMin('13s')
|
||||
.create();
|
||||
|
||||
const timeRangeMock = jest.fn().mockReturnValue({
|
||||
from: '2001-01-01',
|
||||
to: '2001-01-02',
|
||||
raw: {
|
||||
from: '2001-01-01',
|
||||
to: '2001-01-02',
|
||||
},
|
||||
});
|
||||
const setGrafanaVariableMock = jest.fn();
|
||||
const dependencies: UpdateAutoValueDependencies = {
|
||||
kbn: {
|
||||
calculateInterval: jest.fn().mockReturnValue({ interval: '10s' }),
|
||||
},
|
||||
getTimeSrv: () => {
|
||||
return ({
|
||||
timeRange: timeRangeMock,
|
||||
} as unknown) as TimeSrv;
|
||||
},
|
||||
templateSrv: ({
|
||||
setGrafanaVariable: setGrafanaVariableMock,
|
||||
} as unknown) as TemplateSrv,
|
||||
};
|
||||
|
||||
await reduxTester<{ templating: TemplatingState }>()
|
||||
.givenRootReducer(getTemplatingRootReducer())
|
||||
.whenActionIsDispatched(initDashboardTemplating([interval]))
|
||||
.whenAsyncActionIsDispatched(updateAutoValue(toVariableIdentifier(interval), dependencies), true);
|
||||
|
||||
expect(dependencies.kbn.calculateInterval).toHaveBeenCalledTimes(1);
|
||||
expect(dependencies.kbn.calculateInterval).toHaveBeenCalledWith(
|
||||
{
|
||||
from: '2001-01-01',
|
||||
to: '2001-01-02',
|
||||
raw: {
|
||||
from: '2001-01-01',
|
||||
to: '2001-01-02',
|
||||
},
|
||||
},
|
||||
33,
|
||||
'13s'
|
||||
);
|
||||
expect(timeRangeMock).toHaveBeenCalledTimes(1);
|
||||
expect(setGrafanaVariableMock).toHaveBeenCalledTimes(2);
|
||||
expect(setGrafanaVariableMock.mock.calls[0][0]).toBe('$__auto_interval_intervalName');
|
||||
expect(setGrafanaVariableMock.mock.calls[0][1]).toBe('10s');
|
||||
expect(setGrafanaVariableMock.mock.calls[1][0]).toBe('$__auto_interval');
|
||||
expect(setGrafanaVariableMock.mock.calls[1][1]).toBe('10s');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
56
public/app/features/variables/interval/actions.ts
Normal file
56
public/app/features/variables/interval/actions.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { AppEvents } from '@grafana/data';
|
||||
|
||||
import { toVariablePayload, VariableIdentifier } from '../state/types';
|
||||
import { ThunkResult } from '../../../types';
|
||||
import { createIntervalOptions } from './reducer';
|
||||
import { validateVariableSelectionState } from '../state/actions';
|
||||
import { getVariable } from '../state/selectors';
|
||||
import { IntervalVariableModel } from '../../templating/variable';
|
||||
import kbn from '../../../core/utils/kbn';
|
||||
import { getTimeSrv } from '../../dashboard/services/TimeSrv';
|
||||
import templateSrv from '../../templating/template_srv';
|
||||
import appEvents from '../../../core/app_events';
|
||||
|
||||
export interface UpdateIntervalVariableOptionsDependencies {
|
||||
appEvents: typeof appEvents;
|
||||
}
|
||||
|
||||
export const updateIntervalVariableOptions = (
|
||||
identifier: VariableIdentifier,
|
||||
dependencies: UpdateIntervalVariableOptionsDependencies = { appEvents: appEvents }
|
||||
): ThunkResult<void> => async dispatch => {
|
||||
try {
|
||||
await dispatch(createIntervalOptions(toVariablePayload(identifier)));
|
||||
await dispatch(updateAutoValue(identifier));
|
||||
await dispatch(validateVariableSelectionState(identifier));
|
||||
} catch (error) {
|
||||
dependencies.appEvents.emit(AppEvents.alertError, ['Templating', error.message]);
|
||||
}
|
||||
};
|
||||
|
||||
export interface UpdateAutoValueDependencies {
|
||||
kbn: typeof kbn;
|
||||
getTimeSrv: typeof getTimeSrv;
|
||||
templateSrv: typeof templateSrv;
|
||||
}
|
||||
|
||||
export const updateAutoValue = (
|
||||
identifier: VariableIdentifier,
|
||||
dependencies: UpdateAutoValueDependencies = {
|
||||
kbn: kbn,
|
||||
getTimeSrv: getTimeSrv,
|
||||
templateSrv: templateSrv,
|
||||
}
|
||||
): ThunkResult<void> => (dispatch, getState) => {
|
||||
const variableInState = getVariable<IntervalVariableModel>(identifier.uuid, getState());
|
||||
if (variableInState.auto) {
|
||||
const res = dependencies.kbn.calculateInterval(
|
||||
dependencies.getTimeSrv().timeRange(),
|
||||
variableInState.auto_count,
|
||||
variableInState.auto_min
|
||||
);
|
||||
dependencies.templateSrv.setGrafanaVariable('$__auto_interval_' + variableInState.name, res.interval);
|
||||
// for backward compatibility, to be removed eventually
|
||||
dependencies.templateSrv.setGrafanaVariable('$__auto_interval', res.interval);
|
||||
}
|
||||
};
|
42
public/app/features/variables/interval/adapter.ts
Normal file
42
public/app/features/variables/interval/adapter.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import { IntervalVariableModel } from '../../templating/variable';
|
||||
import { dispatch } from '../../../store/store';
|
||||
import { setOptionAsCurrent, setOptionFromUrl } from '../state/actions';
|
||||
import { VariableAdapter } from '../adapters';
|
||||
import { initialIntervalVariableModelState, intervalVariableReducer } from './reducer';
|
||||
import { OptionsPicker } from '../pickers';
|
||||
import { toVariableIdentifier } from '../state/types';
|
||||
import { IntervalVariableEditor } from './IntervalVariableEditor';
|
||||
import { updateAutoValue, updateIntervalVariableOptions } from './actions';
|
||||
|
||||
export const createIntervalVariableAdapter = (): VariableAdapter<IntervalVariableModel> => {
|
||||
return {
|
||||
description: 'Define a timespan interval (ex 1m, 1h, 1d)',
|
||||
label: 'Interval',
|
||||
initialState: initialIntervalVariableModelState,
|
||||
reducer: intervalVariableReducer,
|
||||
picker: OptionsPicker,
|
||||
editor: IntervalVariableEditor,
|
||||
dependsOn: () => {
|
||||
return false;
|
||||
},
|
||||
setValue: async (variable, option, emitChanges = false) => {
|
||||
await dispatch(updateAutoValue(toVariableIdentifier(variable)));
|
||||
await dispatch(setOptionAsCurrent(toVariableIdentifier(variable), option, emitChanges));
|
||||
},
|
||||
setValueFromUrl: async (variable, urlValue) => {
|
||||
await dispatch(updateAutoValue(toVariableIdentifier(variable)));
|
||||
await dispatch(setOptionFromUrl(toVariableIdentifier(variable), urlValue));
|
||||
},
|
||||
updateOptions: async variable => {
|
||||
await dispatch(updateIntervalVariableOptions(toVariableIdentifier(variable)));
|
||||
},
|
||||
getSaveModel: variable => {
|
||||
const { index, uuid, initLock, global, ...rest } = cloneDeep(variable);
|
||||
return rest;
|
||||
},
|
||||
getValueForUrl: variable => {
|
||||
return variable.current.value;
|
||||
},
|
||||
};
|
||||
};
|
123
public/app/features/variables/interval/reducer.test.ts
Normal file
123
public/app/features/variables/interval/reducer.test.ts
Normal file
@ -0,0 +1,123 @@
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
|
||||
import { getVariableTestContext } from '../state/helpers';
|
||||
import { toVariablePayload } from '../state/types';
|
||||
import { createIntervalVariableAdapter } from './adapter';
|
||||
import { IntervalVariableModel } from '../../templating/variable';
|
||||
import { reducerTester } from '../../../../test/core/redux/reducerTester';
|
||||
import { VariablesState } from '../state/variablesReducer';
|
||||
import { createIntervalOptions, intervalVariableReducer } from './reducer';
|
||||
|
||||
describe('intervalVariableReducer', () => {
|
||||
const adapter = createIntervalVariableAdapter();
|
||||
describe('when createIntervalOptions is dispatched', () => {
|
||||
describe('and auto is false', () => {
|
||||
it('then state should be correct', () => {
|
||||
const uuid = '0';
|
||||
const query = '1s,1m,1h,1d';
|
||||
const auto = false;
|
||||
const { initialState } = getVariableTestContext<IntervalVariableModel>(adapter, { uuid, query, auto });
|
||||
const payload = toVariablePayload({ uuid: '0', type: 'interval' });
|
||||
|
||||
reducerTester<VariablesState>()
|
||||
.givenReducer(intervalVariableReducer, cloneDeep(initialState))
|
||||
.whenActionIsDispatched(createIntervalOptions(payload))
|
||||
.thenStateShouldEqual({
|
||||
'0': {
|
||||
...initialState['0'],
|
||||
uuid: '0',
|
||||
query: '1s,1m,1h,1d',
|
||||
auto: false,
|
||||
options: [
|
||||
{ text: '1s', value: '1s', selected: false },
|
||||
{ text: '1m', value: '1m', selected: false },
|
||||
{ text: '1h', value: '1h', selected: false },
|
||||
{ text: '1d', value: '1d', selected: false },
|
||||
],
|
||||
} as IntervalVariableModel,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('and auto is true', () => {
|
||||
it('then state should be correct', () => {
|
||||
const uuid = '0';
|
||||
const query = '1s,1m,1h,1d';
|
||||
const auto = true;
|
||||
const { initialState } = getVariableTestContext<IntervalVariableModel>(adapter, { uuid, query, auto });
|
||||
const payload = toVariablePayload({ uuid: '0', type: 'interval' });
|
||||
|
||||
reducerTester<VariablesState>()
|
||||
.givenReducer(intervalVariableReducer, cloneDeep(initialState))
|
||||
.whenActionIsDispatched(createIntervalOptions(payload))
|
||||
.thenStateShouldEqual({
|
||||
'0': {
|
||||
...initialState['0'],
|
||||
uuid: '0',
|
||||
query: '1s,1m,1h,1d',
|
||||
auto: true,
|
||||
options: [
|
||||
{ text: 'auto', value: '$__auto_interval_0', selected: false },
|
||||
{ text: '1s', value: '1s', selected: false },
|
||||
{ text: '1m', value: '1m', selected: false },
|
||||
{ text: '1h', value: '1h', selected: false },
|
||||
{ text: '1d', value: '1d', selected: false },
|
||||
],
|
||||
} as IntervalVariableModel,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('and query contains "', () => {
|
||||
it('then state should be correct', () => {
|
||||
const uuid = '0';
|
||||
const query = '"kalle, anka","donald, duck"';
|
||||
const auto = false;
|
||||
const { initialState } = getVariableTestContext<IntervalVariableModel>(adapter, { uuid, query, auto });
|
||||
const payload = toVariablePayload({ uuid: '0', type: 'interval' });
|
||||
|
||||
reducerTester<VariablesState>()
|
||||
.givenReducer(intervalVariableReducer, cloneDeep(initialState))
|
||||
.whenActionIsDispatched(createIntervalOptions(payload))
|
||||
.thenStateShouldEqual({
|
||||
'0': {
|
||||
...initialState['0'],
|
||||
uuid: '0',
|
||||
query: '"kalle, anka","donald, duck"',
|
||||
auto: false,
|
||||
options: [
|
||||
{ text: 'kalle, anka', value: 'kalle, anka', selected: false },
|
||||
{ text: 'donald, duck', value: 'donald, duck', selected: false },
|
||||
],
|
||||
} as IntervalVariableModel,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("and query contains '", () => {
|
||||
it('then state should be correct', () => {
|
||||
const uuid = '0';
|
||||
const query = "'kalle, anka','donald, duck'";
|
||||
const auto = false;
|
||||
const { initialState } = getVariableTestContext<IntervalVariableModel>(adapter, { uuid, query, auto });
|
||||
const payload = toVariablePayload({ uuid: '0', type: 'interval' });
|
||||
|
||||
reducerTester<VariablesState>()
|
||||
.givenReducer(intervalVariableReducer, cloneDeep(initialState))
|
||||
.whenActionIsDispatched(createIntervalOptions(payload))
|
||||
.thenStateShouldEqual({
|
||||
'0': {
|
||||
...initialState['0'],
|
||||
uuid: '0',
|
||||
query: "'kalle, anka','donald, duck'",
|
||||
auto: false,
|
||||
options: [
|
||||
{ text: 'kalle, anka', value: 'kalle, anka', selected: false },
|
||||
{ text: 'donald, duck', value: 'donald, duck', selected: false },
|
||||
],
|
||||
} as IntervalVariableModel,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
55
public/app/features/variables/interval/reducer.ts
Normal file
55
public/app/features/variables/interval/reducer.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import { IntervalVariableModel, VariableHide, VariableOption, VariableRefresh } from '../../templating/variable';
|
||||
import { EMPTY_UUID, getInstanceState, VariablePayload } from '../state/types';
|
||||
import { initialVariablesState, VariablesState } from '../state/variablesReducer';
|
||||
import _ from 'lodash';
|
||||
|
||||
export const initialIntervalVariableModelState: IntervalVariableModel = {
|
||||
uuid: EMPTY_UUID,
|
||||
global: false,
|
||||
type: 'interval',
|
||||
name: '',
|
||||
label: '',
|
||||
hide: VariableHide.dontHide,
|
||||
skipUrlSync: false,
|
||||
auto_count: 30,
|
||||
auto_min: '10s',
|
||||
options: [],
|
||||
auto: false,
|
||||
query: '1m,10m,30m,1h,6h,12h,1d,7d,14d,30d',
|
||||
refresh: VariableRefresh.onTimeRangeChanged,
|
||||
current: {} as VariableOption,
|
||||
index: -1,
|
||||
initLock: null,
|
||||
};
|
||||
|
||||
export const intervalVariableSlice = createSlice({
|
||||
name: 'templating/interval',
|
||||
initialState: initialVariablesState,
|
||||
reducers: {
|
||||
createIntervalOptions: (state: VariablesState, action: PayloadAction<VariablePayload>) => {
|
||||
const instanceState = getInstanceState<IntervalVariableModel>(state, action.payload.uuid!);
|
||||
const options: VariableOption[] = _.map(instanceState.query.match(/(["'])(.*?)\1|\w+/g), text => {
|
||||
text = text.replace(/["']+/g, '');
|
||||
return { text: text.trim(), value: text.trim(), selected: false };
|
||||
});
|
||||
|
||||
if (instanceState.auto) {
|
||||
// add auto option if missing
|
||||
if (options.length && options[0].text !== 'auto') {
|
||||
options.unshift({
|
||||
text: 'auto',
|
||||
value: '$__auto_interval_' + instanceState.name,
|
||||
selected: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
instanceState.options = options;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const intervalVariableReducer = intervalVariableSlice.reducer;
|
||||
|
||||
export const { createIntervalOptions } = intervalVariableSlice.actions;
|
@ -62,7 +62,7 @@ describe('options picker actions', () => {
|
||||
tags: [] as any[],
|
||||
};
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [setCurrentValue, changeQueryValue, updateOption, hideAction] = actions;
|
||||
const expectedNumberOfActions = 4;
|
||||
|
||||
@ -93,7 +93,7 @@ describe('options picker actions', () => {
|
||||
.whenActionIsDispatched(navigateOptions(NavigationKey.moveDown, false))
|
||||
.whenAsyncActionIsDispatched(navigateOptions(key, clearOthers), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [toggleOptionAction] = actions;
|
||||
const expectedNumberOfActions = 1;
|
||||
|
||||
@ -118,7 +118,7 @@ describe('options picker actions', () => {
|
||||
.whenActionIsDispatched(navigateOptions(NavigationKey.moveDown, clearOthers))
|
||||
.whenAsyncActionIsDispatched(navigateOptions(key, clearOthers), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [toggleOptionAction] = actions;
|
||||
const expectedNumberOfActions = 1;
|
||||
|
||||
@ -145,7 +145,7 @@ describe('options picker actions', () => {
|
||||
.whenActionIsDispatched(navigateOptions(NavigationKey.moveDown, clearOthers))
|
||||
.whenAsyncActionIsDispatched(navigateOptions(key, clearOthers), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [toggleOptionAction] = actions;
|
||||
const expectedNumberOfActions = 1;
|
||||
|
||||
@ -173,7 +173,7 @@ describe('options picker actions', () => {
|
||||
.whenActionIsDispatched(navigateOptions(NavigationKey.moveUp, clearOthers))
|
||||
.whenAsyncActionIsDispatched(navigateOptions(key, clearOthers), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [toggleOptionAction] = actions;
|
||||
const expectedNumberOfActions = 1;
|
||||
|
||||
@ -208,7 +208,7 @@ describe('options picker actions', () => {
|
||||
tags: [] as any[],
|
||||
};
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [toggleOptionAction, setCurrentValue, changeQueryValue, updateOption, hideAction] = actions;
|
||||
const expectedNumberOfActions = 5;
|
||||
|
||||
@ -237,7 +237,7 @@ describe('options picker actions', () => {
|
||||
.whenActionIsDispatched(showOptions(variable))
|
||||
.whenAsyncActionIsDispatched(filterOrSearchOptions(filter), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [updateQueryValue, updateAndFilter] = actions;
|
||||
const expectedNumberOfActions = 2;
|
||||
|
||||
@ -267,7 +267,7 @@ describe('options picker actions', () => {
|
||||
tags: [] as any[],
|
||||
};
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [setCurrentValue, changeQueryValue, hideAction] = actions;
|
||||
const expectedNumberOfActions = 3;
|
||||
|
||||
@ -303,7 +303,7 @@ describe('options picker actions', () => {
|
||||
tags: [] as any[],
|
||||
};
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [setCurrentValue, changeQueryValue, updateOption, hideAction] = actions;
|
||||
const expectedNumberOfActions = 4;
|
||||
|
||||
@ -334,7 +334,7 @@ describe('options picker actions', () => {
|
||||
|
||||
const option = createOption('A');
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [toggleOptionAction] = actions;
|
||||
const expectedNumberOfActions = 1;
|
||||
|
||||
@ -356,7 +356,7 @@ describe('options picker actions', () => {
|
||||
.whenActionIsDispatched(showOptions(variable))
|
||||
.whenAsyncActionIsDispatched(toggleAndFetchTag(tag), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [toggleTagAction] = actions;
|
||||
const expectedNumberOfActions = 1;
|
||||
|
||||
@ -383,7 +383,7 @@ describe('options picker actions', () => {
|
||||
.whenActionIsDispatched(showOptions(variable))
|
||||
.whenAsyncActionIsDispatched(toggleAndFetchTag(tag), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [toggleTagAction] = actions;
|
||||
const expectedNumberOfActions = 1;
|
||||
|
||||
|
@ -64,7 +64,7 @@ describe('query actions', () => {
|
||||
|
||||
const option = createOption(ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [updateOptions, updateTags, setCurrentAction] = actions;
|
||||
const expectedNumberOfActions = 3;
|
||||
|
||||
@ -91,7 +91,7 @@ describe('query actions', () => {
|
||||
|
||||
const option = createOption('A');
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [updateOptions, updateTags, setCurrentAction] = actions;
|
||||
const expectedNumberOfActions = 3;
|
||||
|
||||
@ -117,7 +117,7 @@ describe('query actions', () => {
|
||||
|
||||
const option = createOption('A');
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [updateOptions, setCurrentAction] = actions;
|
||||
const expectedNumberOfActions = 2;
|
||||
|
||||
@ -142,7 +142,7 @@ describe('query actions', () => {
|
||||
|
||||
const option = createOption(ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [updateOptions, setCurrentAction] = actions;
|
||||
const expectedNumberOfActions = 2;
|
||||
|
||||
@ -168,7 +168,7 @@ describe('query actions', () => {
|
||||
|
||||
const option = createOption(ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [clearErrors, updateOptions, setCurrentAction] = actions;
|
||||
const expectedNumberOfActions = 3;
|
||||
|
||||
@ -193,7 +193,7 @@ describe('query actions', () => {
|
||||
.whenActionIsDispatched(setIdInEditor({ id: variable.uuid! }))
|
||||
.whenAsyncActionIsDispatched(updateQueryVariableOptions(toVariablePayload(variable)), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [clearErrors, errorOccurred] = actions;
|
||||
const expectedNumberOfActions = 2;
|
||||
|
||||
@ -221,7 +221,7 @@ describe('query actions', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating([variable]))
|
||||
.whenAsyncActionIsDispatched(initQueryVariableEditor(toVariablePayload(variable)), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [updateDatasources, setDatasource, setEditor] = actions;
|
||||
const expectedNumberOfActions = 3;
|
||||
|
||||
@ -254,7 +254,7 @@ describe('query actions', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating([variable]))
|
||||
.whenAsyncActionIsDispatched(initQueryVariableEditor(toVariablePayload(variable)), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [updateDatasources, setDatasource, setEditor] = actions;
|
||||
const expectedNumberOfActions = 3;
|
||||
|
||||
@ -286,7 +286,7 @@ describe('query actions', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating([variable]))
|
||||
.whenAsyncActionIsDispatched(initQueryVariableEditor(toVariablePayload(variable)), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [updateDatasources, setDatasource, setEditor] = actions;
|
||||
const expectedNumberOfActions = 3;
|
||||
|
||||
@ -312,7 +312,7 @@ describe('query actions', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating([variable]))
|
||||
.whenAsyncActionIsDispatched(initQueryVariableEditor(toVariablePayload(variable)), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [updateDatasources] = actions;
|
||||
const expectedNumberOfActions = 1;
|
||||
|
||||
@ -336,7 +336,7 @@ describe('query actions', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating([variable]))
|
||||
.whenAsyncActionIsDispatched(changeQueryVariableDataSource(toVariablePayload(variable), 'datasource'), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [updateDatasource, updateEditor] = actions;
|
||||
const expectedNumberOfActions = 2;
|
||||
|
||||
@ -366,7 +366,7 @@ describe('query actions', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating([variable]))
|
||||
.whenAsyncActionIsDispatched(changeQueryVariableDataSource(toVariablePayload(variable), 'datasource'), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [updateDatasource, updateEditor] = actions;
|
||||
const expectedNumberOfActions = 2;
|
||||
|
||||
@ -400,7 +400,7 @@ describe('query actions', () => {
|
||||
|
||||
const option = createOption(ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [clearError, changeQuery, changeDefinition, updateOptions, updateTags, setOption] = actions;
|
||||
const expectedNumberOfActions = 6;
|
||||
|
||||
@ -437,7 +437,7 @@ describe('query actions', () => {
|
||||
|
||||
const option = createOption(ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [clearError, changeQuery, changeDefinition, updateOptions, setOption] = actions;
|
||||
const expectedNumberOfActions = 5;
|
||||
|
||||
@ -472,7 +472,7 @@ describe('query actions', () => {
|
||||
|
||||
const option = createOption('A');
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [clearError, changeQuery, changeDefinition, updateOptions, setOption] = actions;
|
||||
const expectedNumberOfActions = 5;
|
||||
|
||||
@ -504,7 +504,7 @@ describe('query actions', () => {
|
||||
|
||||
const errorText = 'Query cannot contain a reference to itself. Variable: $' + variable.name;
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [editorError] = actions;
|
||||
const expectedNumberOfActions = 1;
|
||||
|
||||
|
@ -30,7 +30,7 @@ describe('shared actions', () => {
|
||||
reduxTester<{ templating: TemplatingState }>()
|
||||
.givenRootReducer(getTemplatingRootReducer())
|
||||
.whenActionIsDispatched(initDashboardTemplating(list))
|
||||
.thenDispatchedActionPredicateShouldEqual(dispatchedActions => {
|
||||
.thenDispatchedActionsPredicateShouldEqual(dispatchedActions => {
|
||||
expect(dispatchedActions.length).toEqual(8);
|
||||
expect(dispatchedActions[0]).toEqual(
|
||||
addVariable(toVariablePayload(query, { global: false, index: 0, model: query }))
|
||||
@ -85,7 +85,7 @@ describe('shared actions', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating(list))
|
||||
.whenAsyncActionIsDispatched(processVariables(), true);
|
||||
|
||||
await tester.thenDispatchedActionPredicateShouldEqual(dispatchedActions => {
|
||||
await tester.thenDispatchedActionsPredicateShouldEqual(dispatchedActions => {
|
||||
expect(dispatchedActions.length).toEqual(8);
|
||||
|
||||
expect(dispatchedActions[0]).toEqual(
|
||||
@ -142,7 +142,7 @@ describe('shared actions', () => {
|
||||
.whenActionIsDispatched(addVariable(toVariablePayload(custom, { global: false, index: 0, model: custom })))
|
||||
.whenAsyncActionIsDispatched(setOptionFromUrl(toVariableIdentifier(custom), urlValue), true);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
setCurrentVariableValue(
|
||||
toVariablePayload(
|
||||
{ type: 'custom', uuid: '0' },
|
||||
@ -191,7 +191,7 @@ describe('shared actions', () => {
|
||||
true
|
||||
);
|
||||
|
||||
await tester.thenDispatchedActionPredicateShouldEqual(dispatchedActions => {
|
||||
await tester.thenDispatchedActionsPredicateShouldEqual(dispatchedActions => {
|
||||
const expectedActions: AnyAction[] = !withOptions
|
||||
? []
|
||||
: [
|
||||
@ -249,7 +249,7 @@ describe('shared actions', () => {
|
||||
true
|
||||
);
|
||||
|
||||
await tester.thenDispatchedActionPredicateShouldEqual(dispatchedActions => {
|
||||
await tester.thenDispatchedActionsPredicateShouldEqual(dispatchedActions => {
|
||||
const expectedActions: AnyAction[] = !withOptions
|
||||
? []
|
||||
: [
|
||||
|
@ -111,6 +111,21 @@ export const variableMockBuilder = (type: VariableType) => {
|
||||
return instance;
|
||||
};
|
||||
|
||||
const withAuto = (auto: boolean) => {
|
||||
model.auto = auto;
|
||||
return instance;
|
||||
};
|
||||
|
||||
const withAutoCount = (autoCount: number) => {
|
||||
model.auto_count = autoCount;
|
||||
return instance;
|
||||
};
|
||||
|
||||
const withAutoMin = (autoMin: string) => {
|
||||
model.auto_min = autoMin;
|
||||
return instance;
|
||||
};
|
||||
|
||||
const create = () => model;
|
||||
|
||||
const instance = {
|
||||
@ -122,6 +137,9 @@ export const variableMockBuilder = (type: VariableType) => {
|
||||
withQuery,
|
||||
withMulti,
|
||||
withRegEx,
|
||||
withAuto,
|
||||
withAutoCount,
|
||||
withAutoMin,
|
||||
create,
|
||||
};
|
||||
|
||||
|
@ -111,7 +111,9 @@ describe('processVariable', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating(list))
|
||||
.whenAsyncActionIsDispatched(processVariable(toVariableIdentifier(custom), queryParams), true);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(resolveInitLock(toVariablePayload({ type: 'custom', uuid: '0' })));
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
resolveInitLock(toVariablePayload({ type: 'custom', uuid: '0' }))
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -124,7 +126,7 @@ describe('processVariable', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating(list))
|
||||
.whenAsyncActionIsDispatched(processVariable(toVariableIdentifier(custom), queryParams), true);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
setCurrentVariableValue(
|
||||
toVariablePayload({ type: 'custom', uuid: '0' }, { option: { text: ['B'], value: ['B'], selected: false } })
|
||||
),
|
||||
@ -149,7 +151,7 @@ describe('processVariable', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating(list))
|
||||
.whenAsyncActionIsDispatched(processVariable(toVariableIdentifier(queryNoDepends), queryParams), true);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
resolveInitLock(toVariablePayload({ type: 'query', uuid: '2' }))
|
||||
);
|
||||
});
|
||||
@ -165,7 +167,7 @@ describe('processVariable', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating(list))
|
||||
.whenAsyncActionIsDispatched(processVariable(toVariableIdentifier(queryNoDepends), queryParams), true);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
updateVariableOptions(
|
||||
toVariablePayload({ type: 'query', uuid: '2' }, [
|
||||
{ value: 'A', text: 'A' },
|
||||
@ -196,7 +198,7 @@ describe('processVariable', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating(list))
|
||||
.whenAsyncActionIsDispatched(processVariable(toVariableIdentifier(queryNoDepends), queryParams), true);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
setCurrentVariableValue(
|
||||
toVariablePayload(
|
||||
{ type: 'query', uuid: '2' },
|
||||
@ -222,7 +224,7 @@ describe('processVariable', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating(list))
|
||||
.whenAsyncActionIsDispatched(processVariable(toVariableIdentifier(queryNoDepends), queryParams), true);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
updateVariableOptions(
|
||||
toVariablePayload({ type: 'query', uuid: '2' }, [
|
||||
{ value: 'A', text: 'A' },
|
||||
@ -267,7 +269,7 @@ describe('processVariable', () => {
|
||||
true
|
||||
);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
resolveInitLock(toVariablePayload({ type: 'query', uuid: '1' }))
|
||||
);
|
||||
});
|
||||
@ -288,7 +290,7 @@ describe('processVariable', () => {
|
||||
true
|
||||
);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
updateVariableOptions(
|
||||
toVariablePayload({ type: 'query', uuid: '1' }, [
|
||||
{ value: 'AA', text: 'AA' },
|
||||
@ -327,7 +329,7 @@ describe('processVariable', () => {
|
||||
true
|
||||
);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
setCurrentVariableValue(
|
||||
toVariablePayload(
|
||||
{ type: 'query', uuid: '1' },
|
||||
@ -358,7 +360,7 @@ describe('processVariable', () => {
|
||||
true
|
||||
);
|
||||
|
||||
await tester.thenDispatchedActionShouldEqual(
|
||||
await tester.thenDispatchedActionsShouldEqual(
|
||||
updateVariableOptions(
|
||||
toVariablePayload({ type: 'query', uuid: '1' }, [
|
||||
{ value: 'AA', text: 'AA' },
|
||||
|
@ -44,7 +44,7 @@ describe('textbox actions', () => {
|
||||
.whenActionIsDispatched(initDashboardTemplating([variable]))
|
||||
.whenAsyncActionIsDispatched(updateTextBoxVariableOptions(toVariablePayload(variable)), true);
|
||||
|
||||
tester.thenDispatchedActionPredicateShouldEqual(actions => {
|
||||
tester.thenDispatchedActionsPredicateShouldEqual(actions => {
|
||||
const [createAction, setCurrentAction] = actions;
|
||||
const expectedNumberOfActions = 2;
|
||||
|
||||
|
@ -21,8 +21,8 @@ export interface ReduxTesterWhen<State> {
|
||||
}
|
||||
|
||||
export interface ReduxTesterThen<State> {
|
||||
thenDispatchedActionShouldEqual: (...dispatchedAction: AnyAction[]) => ReduxTesterWhen<State>;
|
||||
thenDispatchedActionPredicateShouldEqual: (
|
||||
thenDispatchedActionsShouldEqual: (...dispatchedActions: AnyAction[]) => ReduxTesterWhen<State>;
|
||||
thenDispatchedActionsPredicateShouldEqual: (
|
||||
predicate: (dispatchedActions: AnyAction[]) => boolean
|
||||
) => ReduxTesterWhen<State>;
|
||||
}
|
||||
@ -85,7 +85,7 @@ export const reduxTester = <State>(args?: ReduxTesterArguments<State>): ReduxTes
|
||||
return instance;
|
||||
};
|
||||
|
||||
const thenDispatchedActionShouldEqual = (...actions: AnyAction[]): ReduxTesterWhen<State> => {
|
||||
const thenDispatchedActionsShouldEqual = (...actions: AnyAction[]): ReduxTesterWhen<State> => {
|
||||
if (debug) {
|
||||
console.log('Dispatched Actions', JSON.stringify(dispatchedActions, null, 2));
|
||||
}
|
||||
@ -98,7 +98,7 @@ export const reduxTester = <State>(args?: ReduxTesterArguments<State>): ReduxTes
|
||||
return instance;
|
||||
};
|
||||
|
||||
const thenDispatchedActionPredicateShouldEqual = (
|
||||
const thenDispatchedActionsPredicateShouldEqual = (
|
||||
predicate: (dispatchedActions: AnyAction[]) => boolean
|
||||
): ReduxTesterWhen<State> => {
|
||||
if (debug) {
|
||||
@ -113,8 +113,8 @@ export const reduxTester = <State>(args?: ReduxTesterArguments<State>): ReduxTes
|
||||
givenRootReducer,
|
||||
whenActionIsDispatched,
|
||||
whenAsyncActionIsDispatched,
|
||||
thenDispatchedActionShouldEqual,
|
||||
thenDispatchedActionPredicateShouldEqual,
|
||||
thenDispatchedActionsShouldEqual,
|
||||
thenDispatchedActionsPredicateShouldEqual,
|
||||
};
|
||||
|
||||
return instance;
|
||||
|
Loading…
Reference in New Issue
Block a user