epicTester.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. DefaultTimeZone,
  12. } from '@grafana/ui';
  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 toUtc = jest.fn().mockReturnValue(null);
  50. const dateTime = jest.fn().mockReturnValue(null);
  51. const defaultDependencies: EpicDependencies = {
  52. getQueryResponse,
  53. getTimeSrv,
  54. getTimeRange,
  55. getTimeZone,
  56. toUtc,
  57. dateTime,
  58. getShiftedTimeRange,
  59. };
  60. const theDependencies: EpicDependencies = { ...defaultDependencies, ...dependencies };
  61. epic(actionObservable$, stateObservable$, theDependencies).subscribe({
  62. next: action => resultingActions.push(action),
  63. });
  64. const whenActionIsDispatched = (action: ActionOf<any>) => {
  65. action$.next(action);
  66. return instance;
  67. };
  68. const whenQueryReceivesResponse = (response: DataQueryResponse) => {
  69. queryResponse$.next(response);
  70. return instance;
  71. };
  72. const whenQueryThrowsError = (error: any) => {
  73. queryResponse$.error(error);
  74. return instance;
  75. };
  76. const whenQueryObserverReceivesEvent = (event: DataStreamState) => {
  77. observer$.next(event);
  78. return instance;
  79. };
  80. const thenResultingActionsEqual = (...actions: Array<ActionOf<any>>) => {
  81. expect(actions).toEqual(resultingActions);
  82. return instance;
  83. };
  84. const thenNoActionsWhereDispatched = () => {
  85. expect(resultingActions).toEqual([]);
  86. return instance;
  87. };
  88. const getDependencyMock = (dependency: string, method?: string) => {
  89. // @ts-ignore
  90. const dep = theDependencies[dependency];
  91. let mock = null;
  92. if (dep instanceof Function) {
  93. mock = method ? dep()[method] : dep();
  94. } else {
  95. mock = method ? dep[method] : dep;
  96. }
  97. return mock;
  98. };
  99. const thenDependencyWasCalledTimes = (times: number, dependency: string, method?: string) => {
  100. const mock = getDependencyMock(dependency, method);
  101. expect(mock).toBeCalledTimes(times);
  102. return instance;
  103. };
  104. const thenDependencyWasCalledWith = (args: any[], dependency: string, method?: string) => {
  105. const mock = getDependencyMock(dependency, method);
  106. expect(mock).toBeCalledWith(...args);
  107. return instance;
  108. };
  109. const instance = {
  110. whenActionIsDispatched,
  111. whenQueryReceivesResponse,
  112. whenQueryThrowsError,
  113. whenQueryObserverReceivesEvent,
  114. thenResultingActionsEqual,
  115. thenNoActionsWhereDispatched,
  116. thenDependencyWasCalledTimes,
  117. thenDependencyWasCalledWith,
  118. };
  119. return instance;
  120. };