@urbanos/react-discovery-ui 2.1.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +118 -0
  3. package/lib/ReactDiscoveryUI.js +103 -0
  4. package/lib/ReactDiscoveryUI.scss +13 -0
  5. package/lib/assets/arrow.svg +6 -0
  6. package/lib/assets/blk-database.svg +48 -0
  7. package/lib/assets/chart.svg +1 -0
  8. package/lib/assets/down.png +0 -0
  9. package/lib/assets/down.svg +1 -0
  10. package/lib/assets/folder_icon.png +0 -0
  11. package/lib/assets/folder_icon.svg +1 -0
  12. package/lib/assets/ic_arrow.svg +15 -0
  13. package/lib/assets/loadingicon.svg +57 -0
  14. package/lib/assets/no_image.png +0 -0
  15. package/lib/assets/plus.png +0 -0
  16. package/lib/assets/plus.svg +1 -0
  17. package/lib/assets/user.svg +1 -0
  18. package/lib/auth/auth0-client-provider.js +37 -0
  19. package/lib/auth/auth0-client-provider.test.js +33 -0
  20. package/lib/auth/auth0-wrapper.js +155 -0
  21. package/lib/auth/auth0-wrapper.test.js +100 -0
  22. package/lib/components/auth0-login-zone/auth0-login-zone.js +147 -0
  23. package/lib/components/auth0-login-zone/auth0-login-zone.test.js +177 -0
  24. package/lib/components/auth0-login-zone/index.js +9 -0
  25. package/lib/components/code-editor/code-editor.css +173 -0
  26. package/lib/components/code-editor/code-editor.js +64 -0
  27. package/lib/components/code-editor/index.js +9 -0
  28. package/lib/components/collapsable-box/collapsable-box.js +81 -0
  29. package/lib/components/collapsable-box/collapsable-box.scss +39 -0
  30. package/lib/components/collapsable-box/collapsable-box.test.js +87 -0
  31. package/lib/components/collapsable-box/index.js +9 -0
  32. package/lib/components/data-card/data-card.js +63 -0
  33. package/lib/components/data-card/data-card.scss +93 -0
  34. package/lib/components/data-card/data-card.test.js +74 -0
  35. package/lib/components/data-card/index.js +9 -0
  36. package/lib/components/data-view/data-view.js +194 -0
  37. package/lib/components/data-view/data-view.scss +39 -0
  38. package/lib/components/data-view/data-view.test.js +155 -0
  39. package/lib/components/data-view/index.js +9 -0
  40. package/lib/components/dataset-api-doc/api-example.js +120 -0
  41. package/lib/components/dataset-api-doc/api-example.scss +84 -0
  42. package/lib/components/dataset-api-doc/api-example.test.js +88 -0
  43. package/lib/components/dataset-api-doc/dataset-api-doc.js +117 -0
  44. package/lib/components/dataset-api-doc/dataset-api-doc.scss +8 -0
  45. package/lib/components/dataset-api-doc/dataset-api-doc.test.js +42 -0
  46. package/lib/components/dataset-api-doc/index.js +9 -0
  47. package/lib/components/dataset-details/dataset-details.js +64 -0
  48. package/lib/components/dataset-details/dataset-details.scss +58 -0
  49. package/lib/components/dataset-details/dataset-details.test.js +38 -0
  50. package/lib/components/dataset-details/index.js +9 -0
  51. package/lib/components/dataset-dictionary/dataset-dictionary.js +127 -0
  52. package/lib/components/dataset-dictionary/dataset-dictionary.scss +42 -0
  53. package/lib/components/dataset-dictionary/dataset-dictionary.test.js +286 -0
  54. package/lib/components/dataset-dictionary/index.js +9 -0
  55. package/lib/components/dataset-list/dataset-list.js +22 -0
  56. package/lib/components/dataset-list/dataset-list.scss +9 -0
  57. package/lib/components/dataset-list/dataset-list.test.js +16 -0
  58. package/lib/components/dataset-list/index.js +9 -0
  59. package/lib/components/dataset-metadata/dataset-metadata.js +169 -0
  60. package/lib/components/dataset-metadata/dataset-metadata.scss +34 -0
  61. package/lib/components/dataset-metadata/dataset-metadata.test.js +24 -0
  62. package/lib/components/dataset-metadata/index.js +9 -0
  63. package/lib/components/dataset-preview/connector.js +26 -0
  64. package/lib/components/dataset-preview/dataset-preview.js +58 -0
  65. package/lib/components/dataset-preview/dataset-preview.scss +24 -0
  66. package/lib/components/dataset-preview/dataset-preview.test.js +34 -0
  67. package/lib/components/dataset-preview/index.js +9 -0
  68. package/lib/components/dataset-quality/dataset-quality.js +56 -0
  69. package/lib/components/dataset-quality/dataset-quality.scss +24 -0
  70. package/lib/components/dataset-quality/dataset-quality.test.js +34 -0
  71. package/lib/components/dataset-quality/index.js +9 -0
  72. package/lib/components/dataset-recommendations/connector.js +24 -0
  73. package/lib/components/dataset-recommendations/dataset-recommendations.js +47 -0
  74. package/lib/components/dataset-recommendations/dataset-recommendations.scss +17 -0
  75. package/lib/components/dataset-recommendations/dataset-recommendations.test.js +37 -0
  76. package/lib/components/dataset-recommendations/index.js +9 -0
  77. package/lib/components/detail-toggle-icon/detail-toggle-icon.js +41 -0
  78. package/lib/components/detail-toggle-icon/detail-toggle-icon.scss +13 -0
  79. package/lib/components/detail-toggle-icon/detail-toggle-icon.test.js +20 -0
  80. package/lib/components/detail-toggle-icon/index.js +9 -0
  81. package/lib/components/facet-list/facet-list.js +47 -0
  82. package/lib/components/facet-list/facet-list.scss +19 -0
  83. package/lib/components/facet-list/facet-list.test.js +94 -0
  84. package/lib/components/facet-list/index.js +9 -0
  85. package/lib/components/facet-sidebar/facet-sidebar.js +101 -0
  86. package/lib/components/facet-sidebar/facet-sidebar.scss +129 -0
  87. package/lib/components/facet-sidebar/facet-sidebar.test.js +93 -0
  88. package/lib/components/facet-sidebar/index.js +9 -0
  89. package/lib/components/generic-elements/alert-component/alert-component.js +51 -0
  90. package/lib/components/generic-elements/alert-component/alert-component.scss +26 -0
  91. package/lib/components/generic-elements/alert-component/alert-component.test.js +26 -0
  92. package/lib/components/generic-elements/alert-component/index.js +9 -0
  93. package/lib/components/generic-elements/arrow-button/arrow-button.js +30 -0
  94. package/lib/components/generic-elements/arrow-button/index.js +9 -0
  95. package/lib/components/generic-elements/auto-anchoring-popover/index.js +61 -0
  96. package/lib/components/generic-elements/back-button/back-button.js +14 -0
  97. package/lib/components/generic-elements/back-button/back-button.scss +14 -0
  98. package/lib/components/generic-elements/back-button/index.js +9 -0
  99. package/lib/components/generic-elements/call-to-action-button/call-to-action-button.js +118 -0
  100. package/lib/components/generic-elements/call-to-action-button/call-to-action-button.scss +19 -0
  101. package/lib/components/generic-elements/call-to-action-button/call-to-action-button.test.js +68 -0
  102. package/lib/components/generic-elements/call-to-action-button/index.js +9 -0
  103. package/lib/components/generic-elements/chart-icon/index.js +23 -0
  104. package/lib/components/generic-elements/checkbox/checkbox.js +50 -0
  105. package/lib/components/generic-elements/checkbox/checkbox.scss +44 -0
  106. package/lib/components/generic-elements/checkbox/checkbox.test.js +71 -0
  107. package/lib/components/generic-elements/checkbox/index.js +9 -0
  108. package/lib/components/generic-elements/error-component/error-component.js +21 -0
  109. package/lib/components/generic-elements/error-component/error-component.scss +16 -0
  110. package/lib/components/generic-elements/error-component/error-component.test.js +12 -0
  111. package/lib/components/generic-elements/error-component/index.js +9 -0
  112. package/lib/components/generic-elements/folder-icon/index.js +23 -0
  113. package/lib/components/generic-elements/generated-link/generated-link.js +25 -0
  114. package/lib/components/generic-elements/generated-link/index.js +13 -0
  115. package/lib/components/generic-elements/loading-element/index.js +9 -0
  116. package/lib/components/generic-elements/loading-element/loading-element.js +22 -0
  117. package/lib/components/generic-elements/loading-element/loading-element.scss +6 -0
  118. package/lib/components/generic-elements/loading-element/loading-element.test.js +11 -0
  119. package/lib/components/generic-elements/paginator/index.js +9 -0
  120. package/lib/components/generic-elements/paginator/paginator.js +84 -0
  121. package/lib/components/generic-elements/paginator/paginator.scss +38 -0
  122. package/lib/components/generic-elements/paginator/paginator.test.js +140 -0
  123. package/lib/components/generic-elements/plus-icon/index.js +21 -0
  124. package/lib/components/generic-elements/save-indicator/index.js +9 -0
  125. package/lib/components/generic-elements/save-indicator/save-indicator.js +39 -0
  126. package/lib/components/generic-elements/save-indicator/save-indicator.scss +31 -0
  127. package/lib/components/generic-elements/save-indicator/save-indicator.test.js +89 -0
  128. package/lib/components/generic-elements/search/index.js +9 -0
  129. package/lib/components/generic-elements/search/search.js +93 -0
  130. package/lib/components/generic-elements/search/search.scss +90 -0
  131. package/lib/components/generic-elements/search/search.test.js +41 -0
  132. package/lib/components/generic-elements/select/index.js +9 -0
  133. package/lib/components/generic-elements/select/select.js +44 -0
  134. package/lib/components/generic-elements/select/select.scss +22 -0
  135. package/lib/components/generic-elements/select/select.test.js +34 -0
  136. package/lib/components/generic-elements/share-link/index.js +9 -0
  137. package/lib/components/generic-elements/share-link/share-link.js +23 -0
  138. package/lib/components/generic-elements/share-link/share-link.scss +17 -0
  139. package/lib/components/generic-elements/share-link/share-link.test.js +28 -0
  140. package/lib/components/generic-elements/sql-icon/index.js +20 -0
  141. package/lib/components/generic-elements/tab-button/index.js +9 -0
  142. package/lib/components/generic-elements/tab-button/tab-button.js +25 -0
  143. package/lib/components/generic-elements/tab-button/tab-button.scss +27 -0
  144. package/lib/components/generic-elements/visualize-button/index.js +9 -0
  145. package/lib/components/generic-elements/visualize-button/visualize-button.js +37 -0
  146. package/lib/components/generic-elements/visualize-button/visualize-button.scss +14 -0
  147. package/lib/components/login-zone/connector.js +25 -0
  148. package/lib/components/login-zone/index.js +9 -0
  149. package/lib/components/login-zone/login-svgs-and-text.js +39 -0
  150. package/lib/components/login-zone/login-zone.js +21 -0
  151. package/lib/components/login-zone/login-zone.scss +115 -0
  152. package/lib/components/login-zone/login-zone.test.js +17 -0
  153. package/lib/components/login-zone/login.js +48 -0
  154. package/lib/components/login-zone/logout.js +39 -0
  155. package/lib/components/network-loading-element/connector.js +17 -0
  156. package/lib/components/network-loading-element/index.js +9 -0
  157. package/lib/components/network-loading-element/network-loading-element.js +23 -0
  158. package/lib/components/network-loading-element/network-loading-element.scss +21 -0
  159. package/lib/components/network-loading-element/network-loading-element.test.js +34 -0
  160. package/lib/components/organization/index.js +9 -0
  161. package/lib/components/organization/organization.js +27 -0
  162. package/lib/components/organization/organization.scss +32 -0
  163. package/lib/components/protected-route/protected-route.js +101 -0
  164. package/lib/components/protected-route/protected-route.scss +4 -0
  165. package/lib/components/protected-route/protected-route.test.js +63 -0
  166. package/lib/components/query-form/index.js +9 -0
  167. package/lib/components/query-form/query-form.js +262 -0
  168. package/lib/components/query-form/query-form.scss +167 -0
  169. package/lib/components/query-form/query-form.test.js +248 -0
  170. package/lib/components/recommendation-list/index.js +9 -0
  171. package/lib/components/recommendation-list/recommendation-list.js +72 -0
  172. package/lib/components/recommendation-list/recommendation-list.scss +61 -0
  173. package/lib/components/recommendation-list/recommendation-list.test.js +38 -0
  174. package/lib/components/remote-toggle/__snapshots__/remote-toggle.test.js.snap +3 -0
  175. package/lib/components/remote-toggle/index.js +13 -0
  176. package/lib/components/remote-toggle/remote-toggle.js +35 -0
  177. package/lib/components/remote-toggle/remote-toggle.scss +0 -0
  178. package/lib/components/remote-toggle/remote-toggle.test.js +10 -0
  179. package/lib/components/share/index.js +9 -0
  180. package/lib/components/share/share.js +109 -0
  181. package/lib/components/share/share.scss +66 -0
  182. package/lib/components/streaming-api-doc/index.js +9 -0
  183. package/lib/components/streaming-api-doc/streaming-api-doc.js +76 -0
  184. package/lib/components/streaming-api-doc/streaming-api-doc.scss +23 -0
  185. package/lib/components/streaming-api-doc/streaming-api-doc.test.js +24 -0
  186. package/lib/components/tooltip/index.js +9 -0
  187. package/lib/components/tooltip/tooltip.js +17 -0
  188. package/lib/components/tooltip/tooltip.scss +16 -0
  189. package/lib/components/tooltip/tooltip.test.js +19 -0
  190. package/lib/components/visualization-list-menu-item/index.js +9 -0
  191. package/lib/components/visualization-list-menu-item/visualization-list-menu-item.js +53 -0
  192. package/lib/components/visualization-list-menu-item/visualization-list-menu-item.scss +21 -0
  193. package/lib/components/visualization-list-menu-item/visualization-list-menu-item.test.js +42 -0
  194. package/lib/components/visualization-save-menu-item/index.js +9 -0
  195. package/lib/components/visualization-save-menu-item/visualization-save-menu-item.js +101 -0
  196. package/lib/components/visualization-save-menu-item/visualization-save-menu-item.scss +37 -0
  197. package/lib/components/visualization-save-menu-item/visualization-save-menu-item.test.js +185 -0
  198. package/lib/components/visualizations/geojson/connector.js +29 -0
  199. package/lib/components/visualizations/geojson/geojson-visualization.js +151 -0
  200. package/lib/components/visualizations/geojson/geojson-visualization.scss +24 -0
  201. package/lib/components/visualizations/geojson/geojson-visualization.test.js +238 -0
  202. package/lib/components/visualizations/geojson/index.js +9 -0
  203. package/lib/pages/apikey-view/apiKey-view.test.js +204 -0
  204. package/lib/pages/apikey-view/apikey-view.js +166 -0
  205. package/lib/pages/apikey-view/apikey-view.scss +340 -0
  206. package/lib/pages/apikey-view/connector.js +31 -0
  207. package/lib/pages/apikey-view/index.js +9 -0
  208. package/lib/pages/chart-view/chart-view.js +92 -0
  209. package/lib/pages/chart-view/chart-view.scss +35 -0
  210. package/lib/pages/chart-view/chart-view.test.js +206 -0
  211. package/lib/pages/chart-view/connector.js +30 -0
  212. package/lib/pages/chart-view/index.js +9 -0
  213. package/lib/pages/dataset-detail-view/connector.js +38 -0
  214. package/lib/pages/dataset-detail-view/dataset-detail-view-connector.test.js +42 -0
  215. package/lib/pages/dataset-detail-view/dataset-detail-view.js +99 -0
  216. package/lib/pages/dataset-detail-view/dataset-detail-view.scss +190 -0
  217. package/lib/pages/dataset-detail-view/dataset-detail-view.test.js +305 -0
  218. package/lib/pages/dataset-detail-view/index.js +9 -0
  219. package/lib/pages/dataset-list-view/connector.js +30 -0
  220. package/lib/pages/dataset-list-view/dataset-list-view.js +132 -0
  221. package/lib/pages/dataset-list-view/dataset-list-view.scss +242 -0
  222. package/lib/pages/dataset-list-view/dataset-list-view.test.js +162 -0
  223. package/lib/pages/dataset-list-view/index.js +9 -0
  224. package/lib/pages/dataset-view/connector.js +55 -0
  225. package/lib/pages/dataset-view/dataset-view-connector.test.js +78 -0
  226. package/lib/pages/dataset-view/dataset-view.js +175 -0
  227. package/lib/pages/dataset-view/dataset-view.scss +95 -0
  228. package/lib/pages/dataset-view/dataset-view.test.js +157 -0
  229. package/lib/pages/dataset-view/index.js +9 -0
  230. package/lib/pages/login-view/connector.js +25 -0
  231. package/lib/pages/login-view/index.js +9 -0
  232. package/lib/pages/login-view/login-view.js +83 -0
  233. package/lib/pages/login-view/login-view.scss +62 -0
  234. package/lib/pages/login-view/login-view.test.js +23 -0
  235. package/lib/pages/oauth-error-view/index.js +9 -0
  236. package/lib/pages/oauth-error-view/oauth-error-view.js +25 -0
  237. package/lib/pages/oauth-error-view/oauth-error-view.scss +13 -0
  238. package/lib/pages/oauth-error-view/oauth-error-view.test.js +13 -0
  239. package/lib/pages/oauth-view/connector.js +22 -0
  240. package/lib/pages/oauth-view/index.js +9 -0
  241. package/lib/pages/oauth-view/oauth-view.js +124 -0
  242. package/lib/pages/oauth-view/oauth-view.scss +7 -0
  243. package/lib/pages/oauth-view/oauth-view.test.js +195 -0
  244. package/lib/pages/query-view/connector.js +40 -0
  245. package/lib/pages/query-view/index.js +9 -0
  246. package/lib/pages/query-view/query-view.js +80 -0
  247. package/lib/pages/query-view/query-view.scss +39 -0
  248. package/lib/pages/query-view/query-view.test.js +104 -0
  249. package/lib/pages/user-profile-view/connector.js +39 -0
  250. package/lib/pages/user-profile-view/index.js +9 -0
  251. package/lib/pages/user-profile-view/user-profile-view.js +154 -0
  252. package/lib/pages/user-profile-view/user-profile-view.scss +81 -0
  253. package/lib/pages/user-profile-view/user-profile-view.test.js +129 -0
  254. package/lib/pages/visualization-view/connector.js +52 -0
  255. package/lib/pages/visualization-view/index.js +9 -0
  256. package/lib/pages/visualization-view/visualization-view-connector.test.js +62 -0
  257. package/lib/pages/visualization-view/visualization-view.js +128 -0
  258. package/lib/pages/visualization-view/visualization-view.scss +115 -0
  259. package/lib/pages/visualization-view/visualization-view.test.js +188 -0
  260. package/lib/routes.js +18 -0
  261. package/lib/search-params/search-params-manager.js +171 -0
  262. package/lib/search-params/search-params-manager.test.js +490 -0
  263. package/lib/store/actions.js +428 -0
  264. package/lib/store/dataset-selectors.js +47 -0
  265. package/lib/store/dataset-selectors.test.js +154 -0
  266. package/lib/store/query-selectors.js +53 -0
  267. package/lib/store/query-selectors.test.js +153 -0
  268. package/lib/store/reducers/index.js +20 -0
  269. package/lib/store/reducers/query-reducer.js +52 -0
  270. package/lib/store/reducers/query-reducer.test.js +89 -0
  271. package/lib/store/reducers/reducers.js +196 -0
  272. package/lib/store/reducers/reducers.test.js +309 -0
  273. package/lib/store/reducers/visualization-reducer.js +167 -0
  274. package/lib/store/reducers/visualization-reducer.test.js +426 -0
  275. package/lib/store/sagas/api-invoker.js +79 -0
  276. package/lib/store/sagas/api-invoker.test.js +139 -0
  277. package/lib/store/sagas/apiKey-saga.js +81 -0
  278. package/lib/store/sagas/apiKey-saga.test.js +57 -0
  279. package/lib/store/sagas/dataset-download-saga.js +43 -0
  280. package/lib/store/sagas/dataset-list-saga.js +49 -0
  281. package/lib/store/sagas/dataset-list-saga.test.js +72 -0
  282. package/lib/store/sagas/dataset-preview-saga.js +44 -0
  283. package/lib/store/sagas/dataset-query-saga.js +43 -0
  284. package/lib/store/sagas/dataset-recommendation-saga.js +40 -0
  285. package/lib/store/sagas/dataset-saga.js +50 -0
  286. package/lib/store/sagas/freestyle-query-saga.js +127 -0
  287. package/lib/store/sagas/freestyle-query-saga.test.js +145 -0
  288. package/lib/store/sagas/index.js +44 -0
  289. package/lib/store/sagas/login-saga.js +85 -0
  290. package/lib/store/sagas/login-saga.test.js +84 -0
  291. package/lib/store/sagas/logout-saga.js +96 -0
  292. package/lib/store/sagas/oauth-saga.js +78 -0
  293. package/lib/store/sagas/oauth-saga.test.js +51 -0
  294. package/lib/store/sagas/process-login-saga.js +62 -0
  295. package/lib/store/sagas/process-login-saga.test.js +83 -0
  296. package/lib/store/sagas/visualization-saga.js +371 -0
  297. package/lib/store/sagas/visualization-saga.test.js +388 -0
  298. package/lib/store/selectors.js +83 -0
  299. package/lib/store/visualization-selectors.js +85 -0
  300. package/lib/store/visualization-selectors.test.js +195 -0
  301. package/lib/styles/mixins.scss +117 -0
  302. package/lib/styles/variables.scss +41 -0
  303. package/lib/utils/file-type-utils.js +18 -0
  304. package/lib/utils/file-type-utils.test.js +29 -0
  305. package/lib/utils/geojson-utils.js +70 -0
  306. package/lib/utils/geojson-utils.test.js +129 -0
  307. package/lib/utils/http-clients.js +218 -0
  308. package/lib/utils/http-clients.test.js +88 -0
  309. package/lib/utils/index.js +34 -0
  310. package/lib/utils/modified-date-string-builder.js +29 -0
  311. package/lib/utils/modified-date-string-builder.test.js +93 -0
  312. package/lib/utils/query-string-builder.js +38 -0
  313. package/lib/utils/query-string-builder.test.js +33 -0
  314. package/lib/utils/recommendation-utils.js +12 -0
  315. package/lib/utils/recommendation-utils.test.js +9 -0
  316. package/package.json +172 -0
@@ -0,0 +1,104 @@
1
+ import { shallow } from 'enzyme'
2
+
3
+ import QueryView from './query-view'
4
+ import QueryForm from '../../components/query-form'
5
+ import LoadingElement from '../../components/generic-elements/loading-element'
6
+ import ReactTable from 'react-table'
7
+
8
+ // Currently, shallow rendering is not compatible with React hooks.
9
+ // We've utilized a strategy found here https://blog.carbonfive.com/2019/08/05/shallow-testing-hooks-with-enzyme/
10
+ // which should become unneccessary in the near future
11
+ const runUseEffect = () => {
12
+ const useEffect = jest.spyOn(React, 'useEffect')
13
+ useEffect.mockImplementationOnce(f => f())
14
+ }
15
+
16
+ describe('query view', () => {
17
+ let subject
18
+
19
+ describe('before load', () => {
20
+ beforeEach(() => {
21
+ subject = createSubject({ isQueryLoading: true, queryData: [] })
22
+ })
23
+
24
+ it('shows full page loading icon', () => {
25
+ expect(subject.find(LoadingElement).length).toEqual(1)
26
+ })
27
+ })
28
+
29
+ describe('after load', () => {
30
+ let queryCallback
31
+
32
+ beforeEach(() => {
33
+ runUseEffect()
34
+ queryCallback = jest.fn()
35
+ subject = createSubject({ executeQuery: queryCallback })
36
+ })
37
+
38
+ it('does not show full page loading icon', () => {
39
+ expect(subject.find(LoadingElement).length).toEqual(0)
40
+ })
41
+
42
+ describe('executeQuery', () => {
43
+ const newText = 'SELECT * FROM great_org__awesome_dataset LIMIT 55'
44
+
45
+ beforeEach(() => {
46
+ subject
47
+ .find(QueryForm)
48
+ .props()
49
+ .executeQuery(newText)
50
+ })
51
+
52
+ test('runs query', () => {
53
+ expect(queryCallback).toHaveBeenCalledWith(newText)
54
+ })
55
+ })
56
+ })
57
+
58
+ it('should not render full page loading when user has submitted query', () => {
59
+ runUseEffect()
60
+
61
+ subject = createSubject({})
62
+
63
+ subject
64
+ .find(QueryForm)
65
+ .props()
66
+ .executeQuery('SELECT * FROM sky')
67
+ subject.setProps({ isQueryLoading: true })
68
+
69
+ expect(subject.find(LoadingElement).length).toEqual(0)
70
+ })
71
+
72
+ it('does not automatically execute the query when instructed not to', () => {
73
+ runUseEffect()
74
+ const executeQuery = jest.fn()
75
+
76
+ subject = createSubject({ shouldAutoExecuteQuery: false, executeQuery })
77
+
78
+ expect(executeQuery).toHaveBeenCalledTimes(0)
79
+ })
80
+
81
+ it('automatically executes the query when instructed to', () => {
82
+ runUseEffect()
83
+ const executeQuery = jest.fn()
84
+
85
+ subject = createSubject({ shouldAutoExecuteQuery: true, executeQuery })
86
+
87
+ expect(executeQuery).toHaveBeenCalledTimes(1)
88
+ })
89
+ })
90
+
91
+ function createSubject (params) {
92
+ const defaultParams = {
93
+ isQueryLoading: false,
94
+ queryData: [{ data: {} }],
95
+ executeQuery: jest.fn(),
96
+ dataSources: { data: ['sources'] },
97
+ cancelQuery: jest.fn(),
98
+ setQueryText: jest.fn(),
99
+ shouldAutoExecuteQuery: false
100
+ }
101
+ const paramsWithDefaults = Object.assign({}, defaultParams, params)
102
+
103
+ return shallow(<QueryView {...paramsWithDefaults} />)
104
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _reactRedux = require("react-redux");
8
+ var _userProfileView = _interopRequireDefault(require("./user-profile-view"));
9
+ var _actions = require("../../store/actions");
10
+ var _visualizationSelectors = require("../../store/visualization-selectors");
11
+ var _auth0Wrapper = _interopRequireDefault(require("../../auth/auth0-wrapper"));
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ var mapStateToProps = function mapStateToProps(state) {
14
+ return {
15
+ visualizations: (0, _visualizationSelectors.userVisualizations)(state),
16
+ loading: (0, _visualizationSelectors.visualizationLoading)(state),
17
+ loadFailure: (0, _visualizationSelectors.visualizationLoadFailure)(state),
18
+ loadSuccess: (0, _visualizationSelectors.visualizationLoadSuccess)(state),
19
+ deleteFailure: (0, _visualizationSelectors.visualizationDeleteFailure)(state),
20
+ deleteSuccess: (0, _visualizationSelectors.visualizationDeleteSuccess)(state),
21
+ deleting: (0, _visualizationSelectors.visualizationDeleting)(state)
22
+ };
23
+ };
24
+ var mapDispatchToProps = function mapDispatchToProps(dispatch) {
25
+ return {
26
+ getUserVisualizations: function getUserVisualizations() {
27
+ return dispatch((0, _actions.visualizationsLoadAll)());
28
+ },
29
+ deleteVisualization: function deleteVisualization(id) {
30
+ return dispatch((0, _actions.visualizationDelete)({
31
+ id: id
32
+ }));
33
+ },
34
+ clearDeleteVisualizationState: function clearDeleteVisualizationState() {
35
+ return dispatch((0, _actions.visualizationDeleteClear)());
36
+ }
37
+ };
38
+ };
39
+ var _default = exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)((0, _auth0Wrapper.default)(_userProfileView.default));
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _connector = _interopRequireDefault(require("./connector"));
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
+ var _default = exports.default = _connector.default;
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+
3
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _react = _interopRequireWildcard(require("react"));
9
+ var _auth0LoginZone = _interopRequireDefault(require("../../components/auth0-login-zone"));
10
+ var _reactTable = _interopRequireDefault(require("react-table"));
11
+ var _reactModal = _interopRequireDefault(require("react-modal"));
12
+ var _reactAriaModal = _interopRequireDefault(require("react-aria-modal"));
13
+ var _DeleteForever = _interopRequireDefault(require("@material-ui/icons/DeleteForever"));
14
+ require("./user-profile-view.scss");
15
+ var _loadingElement = _interopRequireDefault(require("../../components/generic-elements/loading-element"));
16
+ var _errorComponent = _interopRequireDefault(require("../../components/generic-elements/error-component"));
17
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
19
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
20
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
21
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
22
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
23
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
24
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
25
+ var UserProfileView = function UserProfileView(props) {
26
+ var _useState = (0, _react.useState)(false),
27
+ _useState2 = _slicedToArray(_useState, 2),
28
+ modalIsOpen = _useState2[0],
29
+ setModalIsOpen = _useState2[1];
30
+ var _useState3 = (0, _react.useState)(null),
31
+ _useState4 = _slicedToArray(_useState3, 2),
32
+ datasetToDelete = _useState4[0],
33
+ setVisualizationToDelete = _useState4[1];
34
+ var visualizations = props.visualizations,
35
+ getUserVisualizations = props.getUserVisualizations,
36
+ deleteVisualization = props.deleteVisualization,
37
+ isAuthenticated = props.auth.isAuthenticated,
38
+ loading = props.loading,
39
+ loadFailure = props.loadFailure,
40
+ loadSuccess = props.loadSuccess,
41
+ deleteFailure = props.deleteFailure,
42
+ deleting = props.deleting,
43
+ clearDeleteVisualizationState = props.clearDeleteVisualizationState;
44
+ var showModal = modalIsOpen || deleting || deleteFailure;
45
+ (0, _react.useEffect)(function () {
46
+ getUserVisualizations();
47
+ }, []);
48
+ var openDeleteModalForVisualization = function openDeleteModalForVisualization(id) {
49
+ setModalIsOpen(true);
50
+ setVisualizationToDelete(id);
51
+ };
52
+ var confirmDeletion = function confirmDeletion(id) {
53
+ deleteVisualization(id);
54
+ setModalIsOpen(false);
55
+ };
56
+ var cancelDeletion = function cancelDeletion() {
57
+ setModalIsOpen(false);
58
+ setVisualizationToDelete(null);
59
+ clearDeleteVisualizationState();
60
+ };
61
+ var requestHasNotRun = !loadFailure && !loadSuccess;
62
+ if (loading || requestHasNotRun) {
63
+ return /*#__PURE__*/_react.default.createElement("user-profile-view", null, /*#__PURE__*/_react.default.createElement(_loadingElement.default, null));
64
+ }
65
+ if (!isAuthenticated) {
66
+ return /*#__PURE__*/_react.default.createElement(_errorComponent.default, {
67
+ errorText: "You must be signed in to see your saved visualizations"
68
+ });
69
+ }
70
+ _reactModal.default.setAppElement('*');
71
+ var columns = [{
72
+ Header: 'Title',
73
+ accessor: 'title',
74
+ headerClassName: 'table-header'
75
+ }, {
76
+ Header: 'Date Created',
77
+ accessor: 'created',
78
+ headerClassName: 'table-header'
79
+ }, {
80
+ Header: 'Date Modified',
81
+ accessor: 'updated',
82
+ headerClassName: 'table-header'
83
+ }, {
84
+ Header: '',
85
+ accessor: 'delete',
86
+ headerClassName: 'table-header',
87
+ className: 'centered',
88
+ width: 50,
89
+ Cell: function Cell(_ref) {
90
+ var original = _ref.original;
91
+ return /*#__PURE__*/_react.default.createElement("span", {
92
+ className: "delete-icon",
93
+ tabIndex: "0",
94
+ "aria-label": "Delete",
95
+ role: "button",
96
+ onKeyDownCapture: function onKeyDownCapture(event) {
97
+ if (event.key === ' ' || event.key === 'Enter') {
98
+ openDeleteModalForVisualization(original.id);
99
+ }
100
+ },
101
+ onClick: function onClick() {
102
+ openDeleteModalForVisualization(original.id);
103
+ }
104
+ }, /*#__PURE__*/_react.default.createElement(_DeleteForever.default, null));
105
+ }
106
+ }];
107
+ var modal = showModal ? /*#__PURE__*/_react.default.createElement(_reactAriaModal.default, {
108
+ titleText: "Confirm Delete Workspace"
109
+ }, /*#__PURE__*/_react.default.createElement("div", {
110
+ className: "modal-container"
111
+ }, /*#__PURE__*/_react.default.createElement("div", {
112
+ className: "modal-header-box"
113
+ }, /*#__PURE__*/_react.default.createElement("div", {
114
+ className: "modal-title"
115
+ }, "Confirm Workspace Deletion")), /*#__PURE__*/_react.default.createElement("div", {
116
+ className: "paragraph-text"
117
+ }, deleteFailure && /*#__PURE__*/_react.default.createElement("p", {
118
+ className: "modal-error-text"
119
+ }, "There was an error deleting the visualization")), /*#__PURE__*/_react.default.createElement("div", {
120
+ className: "modal-button-group"
121
+ }, /*#__PURE__*/_react.default.createElement("button", {
122
+ className: "modal-confirm-button",
123
+ onClick: function onClick() {
124
+ confirmDeletion(datasetToDelete);
125
+ }
126
+ }, "Delete"), /*#__PURE__*/_react.default.createElement("button", {
127
+ className: "modal-cancel-button",
128
+ onClick: cancelDeletion
129
+ }, "Cancel")))) : false;
130
+ return /*#__PURE__*/_react.default.createElement("user-profile-view", null, /*#__PURE__*/_react.default.createElement("div", {
131
+ className: "left-section"
132
+ }, /*#__PURE__*/_react.default.createElement(_auth0LoginZone.default, null)), /*#__PURE__*/_react.default.createElement("div", {
133
+ className: "saved-workspaces right-section"
134
+ }, /*#__PURE__*/_react.default.createElement("div", {
135
+ className: "header-container"
136
+ }, /*#__PURE__*/_react.default.createElement("div", {
137
+ className: "header-text-items"
138
+ }, /*#__PURE__*/_react.default.createElement("h1", {
139
+ className: "workspaces-header"
140
+ }, "Saved Workspaces"))), /*#__PURE__*/_react.default.createElement("div", {
141
+ id: "user-visualizations-table"
142
+ }, /*#__PURE__*/_react.default.createElement(_reactTable.default, {
143
+ data: visualizations,
144
+ columns: columns,
145
+ defaultSorted: [{
146
+ id: 'updated',
147
+ desc: true
148
+ }],
149
+ loading: props.loading,
150
+ defaultPageSize: 10,
151
+ className: "-striped -highlight"
152
+ }))), modal);
153
+ };
154
+ var _default = exports.default = UserProfileView;
@@ -0,0 +1,81 @@
1
+ @import "../../styles/variables.scss";
2
+ @import "../../styles/mixins.scss";
3
+
4
+ user-profile-view {
5
+ @include page-with-left-bar();
6
+
7
+ loading-element {
8
+ @include default-loading-icon();
9
+ }
10
+
11
+ .saved-workspaces {
12
+ border: 1px solid $light-grey;
13
+
14
+ .header-container {
15
+ display: flex;
16
+ justify-content: space-between;
17
+ }
18
+
19
+ .header-text-items {
20
+ margin: 1rem;
21
+ }
22
+
23
+ .table-header {
24
+ background-color: $header-grey;
25
+ text-align: left;
26
+ font-weight: 800;
27
+ }
28
+
29
+ .workspaces-header {
30
+ @include header();
31
+ }
32
+ }
33
+
34
+ .delete-icon {
35
+ text-align: center;
36
+ color: $almost-black;
37
+ margin: auto;
38
+ cursor: pointer;
39
+
40
+ &:hover {
41
+ color: $error-color
42
+ }
43
+
44
+ &:active {
45
+ color: $medium-grey
46
+ }
47
+ }
48
+
49
+ .centered {
50
+ text-align: center;
51
+ }
52
+ }
53
+
54
+ div.modal-button-group {
55
+ justify-content: space-evenly;
56
+ display: flex;
57
+ }
58
+
59
+ button.modal-button {
60
+ outline: none;
61
+ color: white;
62
+ padding: 1rem;
63
+ letter-spacing: 0.05rem;
64
+
65
+ &:active {
66
+ background-color: $medium-grey;
67
+ }
68
+ }
69
+
70
+ button.modal-confirm {
71
+ @include button();
72
+ }
73
+
74
+ button.modal-cancel {
75
+ @include button($almost-black);
76
+ }
77
+
78
+ .modal-error-text {
79
+ color: $error-color;
80
+ text-align: center;
81
+ }
@@ -0,0 +1,129 @@
1
+ import { shallow, mount } from 'enzyme'
2
+ import UserProfileView from './user-profile-view'
3
+ import LoadingElement from '../../components/generic-elements/loading-element'
4
+ import ReactTable from 'react-table'
5
+ import ErrorComponent from '../../components/generic-elements/error-component'
6
+ import AriaModal from 'react-aria-modal'
7
+ import createAuth0Client from '@auth0/auth0-spa-js'
8
+
9
+ jest.mock('@auth0/auth0-spa-js')
10
+
11
+ createAuth0Client.mockImplementation(() => {
12
+ const loginWithRedirect = jest.fn()
13
+ const logout = jest.fn()
14
+
15
+ return Promise.resolve({
16
+ isAuthenticated: jest.fn(() => Promise.resolve(true)),
17
+ handleRedirectCallback: jest.fn(() => Promise.resolve({})),
18
+ loginWithRedirect,
19
+ logout
20
+ })
21
+ })
22
+
23
+ describe('user profile view', () => {
24
+ let subject
25
+
26
+ it('shows the loading element on page load', () => {
27
+ subject = createSubject()
28
+ expect(subject.find(LoadingElement)).toHaveLength(1)
29
+ })
30
+
31
+ describe('when the user is signed in', () => {
32
+ beforeEach(() => {
33
+ const visualizations = [
34
+ { title: 'title1', id: 'id1', created: '2019-12-09T21:04:06', updated: '2019-12-09T21:17:14' },
35
+ { title: 'title2', id: 'id2' }
36
+ ]
37
+
38
+ subject = createSubject({
39
+ visualizations: visualizations,
40
+ auth: { isAuthenticated: true },
41
+ loadSuccess: true
42
+ })
43
+ })
44
+
45
+ it("provides a table with the visualizations' information", () => {
46
+ expect(subject.find(ReactTable)).toHaveLength(1)
47
+ expect(subject.find(ReactTable).props().data).toHaveLength(2)
48
+ expect(subject.find(ReactTable).props().data[0].id).toEqual('id1')
49
+ expect(subject.find(ReactTable).props().data[1].id).toEqual('id2')
50
+ })
51
+ })
52
+
53
+ describe('when the user is not logged in', () => {
54
+ beforeEach(() => {
55
+ subject = createSubject({ auth: { isAuthenticated: false }, loadFailure: true })
56
+ })
57
+
58
+ it('shows an error message', () => {
59
+ expect(subject.find(ErrorComponent)).toHaveLength(1)
60
+ expect(subject.find(ReactTable)).toHaveLength(0)
61
+ })
62
+ })
63
+
64
+ describe('deleting a visualization', () => {
65
+ let deleteElements, deleteFunction, clearFunction
66
+ beforeEach(() => {
67
+ deleteFunction = jest.fn()
68
+ clearFunction = jest.fn()
69
+ subject = createSubject({ clearDeleteVisualizationState: clearFunction, deleteVisualization: deleteFunction, auth: { isAuthenticated: true }, loadSuccess: true, visualizations: [{ title: 'Bobviz', id: '2' }] }, mount)
70
+ deleteElements = subject.find('.delete-icon')
71
+ deleteElements.at(0).simulate('click')
72
+ setTimeout(() => {}, 100)
73
+ })
74
+
75
+ it('shows a delete element', () => {
76
+ expect(deleteElements).toHaveLength(1)
77
+ })
78
+
79
+ it('shows a confirmation modal, when the delete element is clicked', () => {
80
+ expect(subject.find(AriaModal).length).toBe(1)
81
+ })
82
+
83
+ it('closes the modal when the cancel button is clicked', () => {
84
+ subject.find('.modal-cancel-button').simulate('click')
85
+ expect(subject.find(AriaModal).length).toBe(0)
86
+ })
87
+
88
+ it('dispatches a request to clear the state, when the cancel button is clicked', () => {
89
+ subject.find('.modal-cancel-button').simulate('click')
90
+ expect(clearFunction).toHaveBeenCalled()
91
+ })
92
+
93
+ it('dispatches a request to delete a visualization when the confirm button is clicked', () => {
94
+ subject.find('.modal-confirm-button').simulate('click')
95
+ expect(deleteFunction).toHaveBeenCalledWith('2')
96
+ })
97
+
98
+ it('keeps the modal open while deleting', () => {
99
+ subject.find('.modal-confirm-button').simulate('click')
100
+ subject.setProps({ deleting: true })
101
+ expect(subject.find(AriaModal).length).toBe(1)
102
+ })
103
+
104
+ it('shows an error message and does not close the modal when deletion fails', () => {
105
+ subject.setProps({ deleteFailure: true })
106
+ expect(subject.find('.modal-error-text')).toHaveLength(1)
107
+ expect(subject.find(AriaModal).length).toBe(1)
108
+ })
109
+ })
110
+ })
111
+
112
+ const createSubject = (props = {}, depth = shallow) => {
113
+ const defaultProps = {
114
+ visualizations: [],
115
+ loading: false,
116
+ auth: { isAuthenticated: false },
117
+ loadFailure: false,
118
+ loadSuccess: false,
119
+ deleting: false,
120
+ deleteFailure: false,
121
+ getUserVisualizations: jest.fn(),
122
+ deleteVisualization: jest.fn(),
123
+ clearDeleteVisualizationState: jest.fn()
124
+ }
125
+
126
+ const propsWithDefaults = Object.assign({}, defaultProps, props)
127
+
128
+ return depth(<UserProfileView {...propsWithDefaults} />)
129
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _reactRedux = require("react-redux");
8
+ var _visualizationView = _interopRequireDefault(require("./visualization-view"));
9
+ var _actions = require("../../store/actions");
10
+ var _querySelectors = require("../../store/query-selectors");
11
+ var _visualizationSelectors = require("../../store/visualization-selectors");
12
+ var _auth0Wrapper = _interopRequireDefault(require("../../auth/auth0-wrapper"));
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
+ var mapStateToProps = function mapStateToProps(state) {
15
+ return {
16
+ id: (0, _visualizationSelectors.visualizationID)(state),
17
+ title: (0, _visualizationSelectors.visualizationTitle)(state),
18
+ query: (0, _querySelectors.getFreestyleQueryText)(state),
19
+ allowedActions: (0, _visualizationSelectors.visualizationAllowedActions)(state),
20
+ isLoadFailure: (0, _visualizationSelectors.visualizationLoadFailure)(state),
21
+ isSaving: (0, _visualizationSelectors.visualizationSaving)(state),
22
+ isSaveFailure: (0, _visualizationSelectors.visualizationSaveFailure)(state),
23
+ isSaveSuccess: (0, _visualizationSelectors.visualizationSaveSuccess)(state),
24
+ isSaveable: (0, _visualizationSelectors.isVisualizationSaveable)(state),
25
+ chart: (0, _visualizationSelectors.visualizationChart)(state)
26
+ };
27
+ };
28
+ var mapDispatchToProps = function mapDispatchToProps(dispatch) {
29
+ return {
30
+ load: function load(id) {
31
+ return dispatch((0, _actions.visualizationLoad)(id));
32
+ },
33
+ reset: function reset() {
34
+ dispatch((0, _actions.visualizationReset)());
35
+ dispatch((0, _actions.resetQuery)());
36
+ dispatch((0, _actions.resetDatasetReferences)());
37
+ },
38
+ save: function save(_ref) {
39
+ var id = _ref.id,
40
+ title = _ref.title,
41
+ query = _ref.query,
42
+ shouldCreateCopy = _ref.shouldCreateCopy;
43
+ return dispatch((0, _actions.visualizationSave)({
44
+ id: id,
45
+ title: title,
46
+ query: query,
47
+ shouldCreateCopy: shouldCreateCopy
48
+ }));
49
+ }
50
+ };
51
+ };
52
+ var _default = exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)((0, _auth0Wrapper.default)(_visualizationView.default));
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _connector = _interopRequireDefault(require("./connector"));
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
+ var _default = exports.default = _connector.default;
@@ -0,0 +1,62 @@
1
+ import { Provider } from 'react-redux'
2
+ import configureStore from 'redux-mock-store'
3
+ import { mount } from 'enzyme'
4
+ import { Router } from 'react-router'
5
+ import { createMemoryHistory } from 'history'
6
+ import ConnectedVisualizationView from '.'
7
+ import VisualizationSaveMenuItem from '../../components/visualization-save-menu-item'
8
+ import { visualizationSave } from '../../store/actions'
9
+ import Auth0Client from '../../auth/auth0-client-provider'
10
+
11
+ const fakeAuth0Client = {
12
+ isAuthenticated: () => Promise.resolve(false)
13
+ }
14
+
15
+ describe('visualization view', () => {
16
+ let storeMocker, state, store, subject
17
+
18
+ const id = 'id'
19
+ const query = 'query'
20
+ const title = 'title'
21
+ const chart = { data: [], layout: {}, frames: [] }
22
+
23
+ beforeEach(() => {
24
+ Auth0Client.get = jest.fn(() => Promise.resolve(fakeAuth0Client))
25
+ storeMocker = configureStore([])
26
+ state = {
27
+ visualization: {
28
+ visualization: {
29
+ id, title, allowedActions: [{ name: 'create_copy' }]
30
+ },
31
+ chart
32
+ },
33
+ queryReducer: { queryText: query, isQueryLoading: false },
34
+ datasetReducer: {},
35
+ presentation: {}
36
+ }
37
+
38
+ store = storeMocker(state)
39
+
40
+ const fakeRouterMatch = { params: { id } }
41
+ const history = createMemoryHistory()
42
+ subject = mount(
43
+ <Provider store={store}>
44
+ <Router history={history}>
45
+ <ConnectedVisualizationView match={fakeRouterMatch} />
46
+ </Router>
47
+ </Provider>
48
+ )
49
+ })
50
+
51
+ it('visualization allowedActions are passed to VisualizationSaveMenuItem', () => {
52
+ expect(subject.find(VisualizationSaveMenuItem).props().allowedActions).toEqual(['create_copy'])
53
+ })
54
+
55
+ it('dispatches the proper visualizationSave action when visualization is saved as a copy', () => {
56
+ const shouldCreateCopy = true
57
+
58
+ subject.find(VisualizationSaveMenuItem).props().handleSaveOrUpdate({ shouldCreateCopy })
59
+
60
+ expect(store.getActions()).toContainEqual(visualizationSave({ id, query, title, shouldCreateCopy }))
61
+ })
62
+ })