epicTester.ts 4.0 KB

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