PromQueryField.test.tsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import { getByTestId, render, screen } from '@testing-library/react';
  2. // @ts-ignore
  3. import userEvent from '@testing-library/user-event';
  4. import React from 'react';
  5. import { PanelData, LoadingState, DataFrame, CoreApp } from '@grafana/data';
  6. import { PrometheusDatasource } from '../datasource';
  7. import PromQlLanguageProvider from '../language_provider';
  8. import PromQueryField from './PromQueryField';
  9. // the monaco-based editor uses lazy-loading and that does not work
  10. // well with this test, and we do not need the monaco-related
  11. // functionality in this test anyway, so we mock it out.
  12. jest.mock('./monaco-query-field/MonacoQueryFieldLazy', () => {
  13. const fakeQueryField = (props: any) => {
  14. return <input onBlur={props.onBlur} data-testid={'dummy-code-input'} type={'text'} />;
  15. };
  16. return {
  17. MonacoQueryFieldLazy: fakeQueryField,
  18. };
  19. });
  20. const defaultProps = {
  21. datasource: {
  22. languageProvider: {
  23. start: () => Promise.resolve([]),
  24. syntax: () => {},
  25. getLabelKeys: () => [],
  26. metrics: [],
  27. },
  28. getInitHints: () => [],
  29. } as unknown as PrometheusDatasource,
  30. query: {
  31. expr: '',
  32. refId: '',
  33. },
  34. onRunQuery: () => {},
  35. onChange: () => {},
  36. history: [],
  37. };
  38. describe('PromQueryField', () => {
  39. beforeAll(() => {
  40. // @ts-ignore
  41. window.getSelection = () => {};
  42. });
  43. it('renders metrics chooser regularly if lookups are not disabled in the datasource settings', () => {
  44. const queryField = render(<PromQueryField {...defaultProps} />);
  45. expect(queryField.getAllByRole('button')).toHaveLength(1);
  46. });
  47. it('renders a disabled metrics chooser if lookups are disabled in datasource settings', () => {
  48. const props = defaultProps;
  49. props.datasource.lookupsDisabled = true;
  50. const queryField = render(<PromQueryField {...props} />);
  51. const bcButton = queryField.getByRole('button');
  52. expect(bcButton).toBeDisabled();
  53. });
  54. it('renders an initial hint if no data and initial hint provided', () => {
  55. const props = defaultProps;
  56. props.datasource.lookupsDisabled = true;
  57. props.datasource.getInitHints = () => [{ label: 'Initial hint', type: 'INFO' }];
  58. render(<PromQueryField {...props} />);
  59. expect(screen.getByText('Initial hint')).toBeInTheDocument();
  60. });
  61. it('renders query hint if data, query hint and initial hint provided', () => {
  62. const props = defaultProps;
  63. props.datasource.lookupsDisabled = true;
  64. props.datasource.getInitHints = () => [{ label: 'Initial hint', type: 'INFO' }];
  65. props.datasource.getQueryHints = () => [{ label: 'Query hint', type: 'INFO' }];
  66. render(
  67. <PromQueryField
  68. {...props}
  69. data={
  70. {
  71. series: [{ name: 'test name' }] as DataFrame[],
  72. state: LoadingState.Done,
  73. } as PanelData
  74. }
  75. />
  76. );
  77. expect(screen.getByText('Query hint')).toBeInTheDocument();
  78. expect(screen.queryByText('Initial hint')).not.toBeInTheDocument();
  79. });
  80. it('refreshes metrics when the data source changes', async () => {
  81. const defaultProps = {
  82. query: { expr: '', refId: '' },
  83. onRunQuery: () => {},
  84. onChange: () => {},
  85. history: [],
  86. };
  87. const metrics = ['foo', 'bar'];
  88. const queryField = render(
  89. <PromQueryField
  90. datasource={
  91. {
  92. languageProvider: makeLanguageProvider({ metrics: [metrics] }),
  93. getInitHints: () => [],
  94. } as unknown as PrometheusDatasource
  95. }
  96. {...defaultProps}
  97. />
  98. );
  99. const changedMetrics = ['baz', 'moo'];
  100. queryField.rerender(
  101. <PromQueryField
  102. // @ts-ignore
  103. datasource={{
  104. languageProvider: makeLanguageProvider({ metrics: [changedMetrics] }),
  105. }}
  106. {...defaultProps}
  107. />
  108. );
  109. // If we check the label browser right away it should be in loading state
  110. let labelBrowser = screen.getByRole('button');
  111. expect(labelBrowser.textContent).toContain('Loading');
  112. });
  113. it('should not run query onBlur in explore', async () => {
  114. const onRunQuery = jest.fn();
  115. const { container } = render(<PromQueryField {...defaultProps} app={CoreApp.Explore} onRunQuery={onRunQuery} />);
  116. const input = getByTestId(container, 'dummy-code-input');
  117. expect(input).toBeInTheDocument();
  118. await userEvent.type(input, 'metric');
  119. input.blur();
  120. expect(onRunQuery).not.toHaveBeenCalled();
  121. });
  122. it('should run query onBlur in dashboard', async () => {
  123. const onRunQuery = jest.fn();
  124. const { container } = render(<PromQueryField {...defaultProps} app={CoreApp.Dashboard} onRunQuery={onRunQuery} />);
  125. const input = getByTestId(container, 'dummy-code-input');
  126. expect(input).toBeInTheDocument();
  127. await userEvent.type(input, 'metric');
  128. input.blur();
  129. expect(onRunQuery).toHaveBeenCalled();
  130. });
  131. });
  132. function makeLanguageProvider(options: { metrics: string[][] }) {
  133. const metricsStack = [...options.metrics];
  134. return {
  135. histogramMetrics: [] as any,
  136. metrics: [],
  137. metricsMetadata: {},
  138. lookupsDisabled: false,
  139. getLabelKeys: () => [],
  140. start() {
  141. this.metrics = metricsStack.shift();
  142. return Promise.resolve([]);
  143. },
  144. } as any as PromQlLanguageProvider;
  145. }