explore.test.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. import {
  2. DEFAULT_RANGE,
  3. serializeStateToUrlParam,
  4. parseUrlState,
  5. updateHistory,
  6. clearHistory,
  7. hasNonEmptyQuery,
  8. } from './explore';
  9. import { ExploreUrlState } from 'app/types/explore';
  10. import store from 'app/core/store';
  11. const DEFAULT_EXPLORE_STATE: ExploreUrlState = {
  12. datasource: null,
  13. queries: [],
  14. range: DEFAULT_RANGE,
  15. ui: {
  16. showingGraph: true,
  17. showingTable: true,
  18. showingLogs: true,
  19. }
  20. };
  21. describe('state functions', () => {
  22. describe('parseUrlState', () => {
  23. it('returns default state on empty string', () => {
  24. expect(parseUrlState('')).toMatchObject({
  25. datasource: null,
  26. queries: [],
  27. range: DEFAULT_RANGE,
  28. });
  29. });
  30. it('returns a valid Explore state from URL parameter', () => {
  31. const paramValue =
  32. '%7B"datasource":"Local","queries":%5B%7B"expr":"metric"%7D%5D,"range":%7B"from":"now-1h","to":"now"%7D%7D';
  33. expect(parseUrlState(paramValue)).toMatchObject({
  34. datasource: 'Local',
  35. queries: [{ expr: 'metric' }],
  36. range: {
  37. from: 'now-1h',
  38. to: 'now',
  39. },
  40. });
  41. });
  42. it('returns a valid Explore state from a compact URL parameter', () => {
  43. const paramValue = '%5B"now-1h","now","Local",%7B"expr":"metric"%7D%5D';
  44. expect(parseUrlState(paramValue)).toMatchObject({
  45. datasource: 'Local',
  46. queries: [{ expr: 'metric' }],
  47. range: {
  48. from: 'now-1h',
  49. to: 'now',
  50. },
  51. });
  52. });
  53. });
  54. describe('serializeStateToUrlParam', () => {
  55. it('returns url parameter value for a state object', () => {
  56. const state = {
  57. ...DEFAULT_EXPLORE_STATE,
  58. datasource: 'foo',
  59. queries: [
  60. {
  61. expr: 'metric{test="a/b"}',
  62. },
  63. {
  64. expr: 'super{foo="x/z"}',
  65. },
  66. ],
  67. range: {
  68. from: 'now-5h',
  69. to: 'now',
  70. },
  71. };
  72. expect(serializeStateToUrlParam(state)).toBe(
  73. '{"datasource":"foo","queries":[{"expr":"metric{test=\\"a/b\\"}"},' +
  74. '{"expr":"super{foo=\\"x/z\\"}"}],"range":{"from":"now-5h","to":"now"},' +
  75. '"ui":{"showingGraph":true,"showingTable":true,"showingLogs":true}}'
  76. );
  77. });
  78. it('returns url parameter value for a state object', () => {
  79. const state = {
  80. ...DEFAULT_EXPLORE_STATE,
  81. datasource: 'foo',
  82. queries: [
  83. {
  84. expr: 'metric{test="a/b"}',
  85. },
  86. {
  87. expr: 'super{foo="x/z"}',
  88. },
  89. ],
  90. range: {
  91. from: 'now-5h',
  92. to: 'now',
  93. },
  94. };
  95. expect(serializeStateToUrlParam(state, true)).toBe(
  96. '["now-5h","now","foo",{"expr":"metric{test=\\"a/b\\"}"},{"expr":"super{foo=\\"x/z\\"}"},{"ui":[true,true,true]}]'
  97. );
  98. });
  99. });
  100. describe('interplay', () => {
  101. it('can parse the serialized state into the original state', () => {
  102. const state = {
  103. ...DEFAULT_EXPLORE_STATE,
  104. datasource: 'foo',
  105. queries: [
  106. {
  107. expr: 'metric{test="a/b"}',
  108. },
  109. {
  110. expr: 'super{foo="x/z"}',
  111. },
  112. ],
  113. range: {
  114. from: 'now - 5h',
  115. to: 'now',
  116. },
  117. };
  118. const serialized = serializeStateToUrlParam(state);
  119. const parsed = parseUrlState(serialized);
  120. expect(state).toMatchObject(parsed);
  121. });
  122. it('can parse the compact serialized state into the original state', () => {
  123. const state = {
  124. ...DEFAULT_EXPLORE_STATE,
  125. datasource: 'foo',
  126. queries: [
  127. {
  128. expr: 'metric{test="a/b"}',
  129. },
  130. {
  131. expr: 'super{foo="x/z"}',
  132. },
  133. ],
  134. range: {
  135. from: 'now - 5h',
  136. to: 'now',
  137. },
  138. };
  139. const serialized = serializeStateToUrlParam(state, true);
  140. const parsed = parseUrlState(serialized);
  141. expect(state).toMatchObject(parsed);
  142. });
  143. });
  144. });
  145. describe('updateHistory()', () => {
  146. const datasourceId = 'myDatasource';
  147. const key = `grafana.explore.history.${datasourceId}`;
  148. beforeEach(() => {
  149. clearHistory(datasourceId);
  150. expect(store.exists(key)).toBeFalsy();
  151. });
  152. test('should save history item to localStorage', () => {
  153. const expected = [
  154. {
  155. query: { refId: '1', expr: 'metric' },
  156. },
  157. ];
  158. expect(updateHistory([], datasourceId, [{ refId: '1', expr: 'metric' }])).toMatchObject(expected);
  159. expect(store.exists(key)).toBeTruthy();
  160. expect(store.getObject(key)).toMatchObject(expected);
  161. });
  162. });
  163. describe('hasNonEmptyQuery', () => {
  164. test('should return true if one query is non-empty', () => {
  165. expect(hasNonEmptyQuery([{ refId: '1', key: '2', expr: 'foo' }])).toBeTruthy();
  166. });
  167. test('should return false if query is empty', () => {
  168. expect(hasNonEmptyQuery([{ refId: '1', key: '2' }])).toBeFalsy();
  169. });
  170. test('should return false if no queries exist', () => {
  171. expect(hasNonEmptyQuery([])).toBeFalsy();
  172. });
  173. });