setup.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import { within } from '@testing-library/dom';
  2. import { render, screen } from '@testing-library/react';
  3. import { fromPairs } from 'lodash';
  4. import React from 'react';
  5. import { Provider } from 'react-redux';
  6. import { Route, Router } from 'react-router-dom';
  7. import { DataSourceApi, DataSourceInstanceSettings, DataSourceRef, QueryEditorProps, ScopedVars } from '@grafana/data';
  8. import { locationService, setDataSourceSrv, setEchoSrv } from '@grafana/runtime';
  9. import { GrafanaRoute } from 'app/core/navigation/GrafanaRoute';
  10. import { Echo } from 'app/core/services/echo/Echo';
  11. import { configureStore } from 'app/store/configureStore';
  12. import { RICH_HISTORY_KEY, RichHistoryLocalStorageDTO } from '../../../../core/history/RichHistoryLocalStorage';
  13. import { RICH_HISTORY_SETTING_KEYS } from '../../../../core/history/richHistoryLocalStorageUtils';
  14. import { LokiDatasource } from '../../../../plugins/datasource/loki/datasource';
  15. import { LokiQuery } from '../../../../plugins/datasource/loki/types';
  16. import { ExploreId } from '../../../../types';
  17. import { initialUserState } from '../../../profile/state/reducers';
  18. import Wrapper from '../../Wrapper';
  19. type DatasourceSetup = { settings: DataSourceInstanceSettings; api: DataSourceApi };
  20. type SetupOptions = {
  21. // default true
  22. clearLocalStorage?: boolean;
  23. datasources?: DatasourceSetup[];
  24. urlParams?: { left: string; right?: string };
  25. searchParams?: string;
  26. };
  27. export function setupExplore(options?: SetupOptions): {
  28. datasources: { [name: string]: DataSourceApi };
  29. store: ReturnType<typeof configureStore>;
  30. unmount: () => void;
  31. container: HTMLElement;
  32. } {
  33. // Clear this up otherwise it persists data source selection
  34. // TODO: probably add test for that too
  35. if (options?.clearLocalStorage !== false) {
  36. window.localStorage.clear();
  37. }
  38. // Create this here so any mocks are recreated on setup and don't retain state
  39. const defaultDatasources: DatasourceSetup[] = [
  40. makeDatasourceSetup(),
  41. makeDatasourceSetup({ name: 'elastic', id: 2 }),
  42. ];
  43. const dsSettings = options?.datasources || defaultDatasources;
  44. setDataSourceSrv({
  45. getList(): DataSourceInstanceSettings[] {
  46. return dsSettings.map((d) => d.settings);
  47. },
  48. getInstanceSettings(ref: DataSourceRef) {
  49. return dsSettings.map((d) => d.settings).find((x) => x.name === ref || x.uid === ref || x.uid === ref.uid);
  50. },
  51. get(name?: string | null, scopedVars?: ScopedVars): Promise<DataSourceApi> {
  52. return Promise.resolve(
  53. (name ? dsSettings.find((d) => d.api.name === name || d.api.uid === name) : dsSettings[0])!.api
  54. );
  55. },
  56. } as any);
  57. setEchoSrv(new Echo());
  58. const store = configureStore();
  59. store.getState().user = {
  60. ...initialUserState,
  61. orgId: 1,
  62. timeZone: 'utc',
  63. };
  64. store.getState().navIndex = {
  65. explore: {
  66. id: 'explore',
  67. text: 'Explore',
  68. subTitle: 'Explore your data',
  69. icon: 'compass',
  70. url: '/explore',
  71. },
  72. };
  73. locationService.push({ pathname: '/explore', search: options?.searchParams });
  74. if (options?.urlParams) {
  75. locationService.partial(options.urlParams);
  76. }
  77. const route = { component: Wrapper };
  78. const { unmount, container } = render(
  79. <Provider store={store}>
  80. <Router history={locationService.getHistory()}>
  81. <Route path="/explore" exact render={(props) => <GrafanaRoute {...props} route={route as any} />} />
  82. </Router>
  83. </Provider>
  84. );
  85. return { datasources: fromPairs(dsSettings.map((d) => [d.api.name, d.api])), store, unmount, container };
  86. }
  87. function makeDatasourceSetup({ name = 'loki', id = 1 }: { name?: string; id?: number } = {}): DatasourceSetup {
  88. const meta: any = {
  89. info: {
  90. logos: {
  91. small: '',
  92. },
  93. },
  94. id: id.toString(),
  95. };
  96. return {
  97. settings: {
  98. id,
  99. uid: name,
  100. type: 'logs',
  101. name,
  102. meta,
  103. access: 'proxy',
  104. jsonData: {},
  105. },
  106. api: {
  107. components: {
  108. QueryEditor(props: QueryEditorProps<LokiDatasource, LokiQuery>) {
  109. return (
  110. <div>
  111. <input
  112. aria-label="query"
  113. defaultValue={props.query.expr}
  114. onChange={(event) => {
  115. props.onChange({ ...props.query, expr: event.target.value });
  116. }}
  117. />
  118. {name} Editor input: {props.query.expr}
  119. </div>
  120. );
  121. },
  122. },
  123. name: name,
  124. uid: name,
  125. query: jest.fn(),
  126. getRef: jest.fn().mockReturnValue(name),
  127. meta,
  128. } as any,
  129. };
  130. }
  131. export const waitForExplore = async (exploreId: ExploreId = ExploreId.left) => {
  132. return await withinExplore(exploreId).findByText(/Editor/i);
  133. };
  134. export const tearDown = () => {
  135. window.localStorage.clear();
  136. };
  137. export const withinExplore = (exploreId: ExploreId) => {
  138. const container = screen.getAllByTestId('data-testid Explore');
  139. return within(container[exploreId === ExploreId.left ? 0 : 1]);
  140. };
  141. export const localStorageHasAlreadyBeenMigrated = () => {
  142. window.localStorage.setItem(RICH_HISTORY_SETTING_KEYS.migrated, 'true');
  143. };
  144. export const setupLocalStorageRichHistory = (dsName: string) => {
  145. window.localStorage.setItem(
  146. RICH_HISTORY_KEY,
  147. JSON.stringify([
  148. {
  149. ts: Date.now(),
  150. datasourceName: dsName,
  151. starred: true,
  152. comment: '',
  153. queries: [{ refId: 'A' }],
  154. } as RichHistoryLocalStorageDTO,
  155. ])
  156. );
  157. };