buildQuery.test.ts 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. import { QueryMode, TimeGranularity, VizType } from '@superset-ui/core';
  20. import buildQuery from '../src/buildQuery';
  21. import { TableChartFormData } from '../src/types';
  22. const basicFormData: TableChartFormData = {
  23. viz_type: VizType.Table,
  24. datasource: '11__table',
  25. };
  26. const extraQueryFormData: TableChartFormData = {
  27. ...basicFormData,
  28. time_grain_sqla: TimeGranularity.MONTH,
  29. groupby: ['col1'],
  30. query_mode: QueryMode.Aggregate,
  31. show_totals: true,
  32. metrics: ['aaa', 'aaa'],
  33. adhoc_filters: [
  34. {
  35. expressionType: 'SQL',
  36. sqlExpression: "status IN ('In Process')",
  37. clause: 'WHERE',
  38. subject: null,
  39. operator: null,
  40. comparator: null,
  41. isExtra: false,
  42. isNew: false,
  43. datasourceWarning: false,
  44. filterOptionName: 'filter_v8m9t9oq5re_ndzk6g5am7',
  45. } as any,
  46. ],
  47. };
  48. describe('plugin-chart-table', () => {
  49. describe('buildQuery', () => {
  50. it('should add post-processing and ignore duplicate metrics', () => {
  51. const query = buildQuery({
  52. ...basicFormData,
  53. query_mode: QueryMode.Aggregate,
  54. metrics: ['aaa', 'aaa'],
  55. percent_metrics: ['bbb', 'bbb'],
  56. }).queries[0];
  57. expect(query.metrics).toEqual(['aaa', 'bbb']);
  58. expect(query.post_processing).toEqual([
  59. {
  60. operation: 'contribution',
  61. options: {
  62. columns: ['bbb'],
  63. rename_columns: ['%bbb'],
  64. },
  65. },
  66. ]);
  67. });
  68. it('should not add metrics in raw records mode', () => {
  69. const query = buildQuery({
  70. ...basicFormData,
  71. query_mode: QueryMode.Raw,
  72. columns: ['a'],
  73. metrics: ['aaa', 'aaa'],
  74. percent_metrics: ['bbb', 'bbb'],
  75. }).queries[0];
  76. expect(query.metrics).toBeUndefined();
  77. expect(query.post_processing).toEqual([]);
  78. });
  79. it('should not add post-processing when there is no percent metric', () => {
  80. const query = buildQuery({
  81. ...basicFormData,
  82. query_mode: QueryMode.Aggregate,
  83. metrics: ['aaa'],
  84. percent_metrics: [],
  85. }).queries[0];
  86. expect(query.metrics).toEqual(['aaa']);
  87. expect(query.post_processing).toEqual([]);
  88. });
  89. it('should not add post-processing in raw records mode', () => {
  90. const query = buildQuery({
  91. ...basicFormData,
  92. query_mode: QueryMode.Raw,
  93. metrics: ['aaa'],
  94. columns: ['rawcol'],
  95. percent_metrics: ['ccc'],
  96. }).queries[0];
  97. expect(query.metrics).toBeUndefined();
  98. expect(query.columns).toEqual(['rawcol']);
  99. expect(query.post_processing).toEqual([]);
  100. });
  101. it('should prefer extra_form_data.time_grain_sqla over formData.time_grain_sqla', () => {
  102. const query = buildQuery({
  103. ...basicFormData,
  104. groupby: ['col1'],
  105. query_mode: QueryMode.Aggregate,
  106. time_grain_sqla: TimeGranularity.MONTH,
  107. extra_form_data: { time_grain_sqla: TimeGranularity.QUARTER },
  108. temporal_columns_lookup: { col1: true },
  109. }).queries[0];
  110. expect(query.columns?.[0]).toEqual({
  111. timeGrain: TimeGranularity.QUARTER,
  112. columnType: 'BASE_AXIS',
  113. sqlExpression: 'col1',
  114. label: 'col1',
  115. expressionType: 'SQL',
  116. });
  117. });
  118. it('should fallback to formData.time_grain_sqla if extra_form_data.time_grain_sqla is not set', () => {
  119. const query = buildQuery({
  120. ...basicFormData,
  121. time_grain_sqla: TimeGranularity.MONTH,
  122. groupby: ['col1'],
  123. query_mode: QueryMode.Aggregate,
  124. temporal_columns_lookup: { col1: true },
  125. }).queries[0];
  126. expect(query.columns?.[0]).toEqual({
  127. timeGrain: TimeGranularity.MONTH,
  128. columnType: 'BASE_AXIS',
  129. sqlExpression: 'col1',
  130. label: 'col1',
  131. expressionType: 'SQL',
  132. });
  133. });
  134. it('should include time_grain_sqla in extras if temporal colum is used and keep the rest', () => {
  135. const { queries } = buildQuery({
  136. ...extraQueryFormData,
  137. temporal_columns_lookup: { col1: true },
  138. });
  139. // Extras in regular query
  140. expect(queries[0].extras?.time_grain_sqla).toEqual(TimeGranularity.MONTH);
  141. expect(queries[0].extras?.where).toEqual("(status IN ('In Process'))");
  142. // Extras in summary query
  143. expect(queries[1].extras?.time_grain_sqla).toEqual(TimeGranularity.MONTH);
  144. expect(queries[1].extras?.where).toEqual("(status IN ('In Process'))");
  145. });
  146. describe('Percent Metric Calculation Modes', () => {
  147. const baseFormDataWithPercents: TableChartFormData = {
  148. ...basicFormData,
  149. query_mode: QueryMode.Aggregate,
  150. metrics: ['count'],
  151. percent_metrics: ['sum_sales'],
  152. groupby: ['category'],
  153. };
  154. it('should default to row_limit mode with single query', () => {
  155. const { queries } = buildQuery(baseFormDataWithPercents);
  156. expect(queries).toHaveLength(1);
  157. expect(queries[0].metrics).toEqual(['count', 'sum_sales']);
  158. expect(queries[0].post_processing).toEqual([
  159. {
  160. operation: 'contribution',
  161. options: {
  162. columns: ['sum_sales'],
  163. rename_columns: ['%sum_sales'],
  164. },
  165. },
  166. ]);
  167. });
  168. it('should create extra query in all_records mode', () => {
  169. const formData = {
  170. ...baseFormDataWithPercents,
  171. percent_metric_calculation: 'all_records',
  172. };
  173. const { queries } = buildQuery(formData);
  174. expect(queries).toHaveLength(2);
  175. expect(queries[0].post_processing).toEqual([
  176. {
  177. operation: 'contribution',
  178. options: {
  179. columns: ['sum_sales'],
  180. rename_columns: ['%sum_sales'],
  181. },
  182. },
  183. ]);
  184. expect(queries[1]).toMatchObject({
  185. columns: [],
  186. metrics: ['sum_sales'],
  187. post_processing: [],
  188. row_limit: 0,
  189. row_offset: 0,
  190. orderby: [],
  191. is_timeseries: false,
  192. });
  193. });
  194. it('should work with show_totals in all_records mode', () => {
  195. const formData = {
  196. ...baseFormDataWithPercents,
  197. percent_metric_calculation: 'all_records',
  198. show_totals: true,
  199. };
  200. const { queries } = buildQuery(formData);
  201. expect(queries).toHaveLength(3);
  202. expect(queries[1].metrics).toEqual(['sum_sales']);
  203. expect(queries[2].metrics).toEqual(['count', 'sum_sales']);
  204. });
  205. it('should handle empty percent_metrics in all_records mode', () => {
  206. const formData = {
  207. ...basicFormData,
  208. query_mode: QueryMode.Aggregate,
  209. metrics: ['count'],
  210. percent_metrics: [],
  211. percent_metric_calculation: 'all_records',
  212. groupby: ['category'],
  213. };
  214. const { queries } = buildQuery(formData);
  215. expect(queries).toHaveLength(1);
  216. expect(queries[0].post_processing).toEqual([]);
  217. });
  218. });
  219. });
  220. });