epicTester.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import { Epic, ActionsObservable, StateObservable } from 'redux-observable';
  2. import { Subject } from 'rxjs';
  3. import {
  4. DataSourceApi,
  5. DataQuery,
  6. DataSourceJsonData,
  7. DataQueryRequest,
  8. DataStreamObserver,
  9. DataQueryResponse,
  10. DataStreamState,
  11. } from '@grafana/ui';
  12. import { DefaultTimeZone } from '@grafana/data';
  13. import { ActionOf } from 'app/core/redux/actionCreatorFactory';
  14. import { StoreState } from 'app/types/store';
  15. import { EpicDependencies } from 'app/store/configureStore';
  16. import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
  17. import { DEFAULT_RANGE } from 'app/core/utils/explore';
  18. export const MOCKED_ABSOLUTE_RANGE = { from: 1, to: 2 };
  19. export const epicTester = (
  20. epic: Epic<ActionOf<any>, ActionOf<any>, StoreState, EpicDependencies>,
  21. state?: Partial<StoreState>,
  22. dependencies?: Partial<EpicDependencies>
  23. ) => {
  24. const resultingActions: Array<ActionOf<any>> = [];
  25. const action$ = new Subject<ActionOf<any>>();
  26. const state$ = new Subject<StoreState>();
  27. const actionObservable$ = new ActionsObservable(action$);
  28. const stateObservable$ = new StateObservable(state$, (state as StoreState) || ({} as StoreState));
  29. const queryResponse$ = new Subject<DataQueryResponse>();
  30. const observer$ = new Subject<DataStreamState>();
  31. const getQueryResponse = (
  32. datasourceInstance: DataSourceApi<DataQuery, DataSourceJsonData>,
  33. options: DataQueryRequest<DataQuery>,
  34. observer?: DataStreamObserver
  35. ) => {
  36. if (observer) {
  37. observer$.subscribe({ next: event => observer(event) });
  38. }
  39. return queryResponse$;
  40. };
  41. const init = jest.fn();
  42. const getTimeSrv = (): TimeSrv => {
  43. const timeSrvMock: TimeSrv = {} as TimeSrv;
  44. return Object.assign(timeSrvMock, { init });
  45. };
  46. const getTimeRange = jest.fn().mockReturnValue(DEFAULT_RANGE);
  47. const getShiftedTimeRange = jest.fn().mockReturnValue(MOCKED_ABSOLUTE_RANGE);
  48. const getTimeZone = jest.fn().mockReturnValue(DefaultTimeZone);
  49. const dateTimeForTimeZone = jest.fn().mockReturnValue(null);
  50. const defaultDependencies: EpicDependencies = {
  51. getQueryResponse,
  52. getTimeSrv,
  53. getTimeRange,
  54. getTimeZone,
  55. getShiftedTimeRange,
  56. dateTimeForTimeZone,
  57. };
  58. const theDependencies: EpicDependencies = { ...defaultDependencies, ...dependencies };
  59. epic(actionObservable$, stateObservable$, theDependencies).subscribe({
  60. next: action => resultingActions.push(action),
  61. });
  62. const whenActionIsDispatched = (action: ActionOf<any>) => {
  63. action$.next(action);
  64. return instance;
  65. };
  66. const whenQueryReceivesResponse = (response: DataQueryResponse) => {
  67. queryResponse$.next(response);
  68. return instance;
  69. };
  70. const whenQueryThrowsError = (error: any) => {
  71. queryResponse$.error(error);
  72. return instance;
  73. };
  74. const whenQueryObserverReceivesEvent = (event: DataStreamState) => {
  75. observer$.next(event);
  76. return instance;
  77. };
  78. const thenResultingActionsEqual = (...actions: Array<ActionOf<any>>) => {
  79. expect(actions).toEqual(resultingActions);
  80. return instance;
  81. };
  82. const thenNoActionsWhereDispatched = () => {
  83. expect(resultingActions).toEqual([]);
  84. return instance;
  85. };
  86. const getDependencyMock = (dependency: string, method?: string) => {
  87. // @ts-ignore
  88. const dep = theDependencies[dependency];
  89. let mock = null;
  90. if (dep instanceof Function) {
  91. mock = method ? dep()[method] : dep();
  92. } else {
  93. mock = method ? dep[method] : dep;
  94. }
  95. return mock;
  96. };
  97. const thenDependencyWasCalledTimes = (times: number, dependency: string, method?: string) => {
  98. const mock = getDependencyMock(dependency, method);
  99. expect(mock).toBeCalledTimes(times);
  100. return instance;
  101. };
  102. const thenDependencyWasCalledWith = (args: any[], dependency: string, method?: string) => {
  103. const mock = getDependencyMock(dependency, method);
  104. expect(mock).toBeCalledWith(...args);
  105. return instance;
  106. };
  107. const instance = {
  108. whenActionIsDispatched,
  109. whenQueryReceivesResponse,
  110. whenQueryThrowsError,
  111. whenQueryObserverReceivesEvent,
  112. thenResultingActionsEqual,
  113. thenNoActionsWhereDispatched,
  114. thenDependencyWasCalledTimes,
  115. thenDependencyWasCalledWith,
  116. };
  117. return instance;
  118. };