@looker/api-explorer 0.9.26 → 0.9.27

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 (214) hide show
  1. package/CHANGELOG.md +47 -1
  2. package/e2e/e2e.spec.ts +1 -1
  3. package/lib/ApiExplorer.d.ts +2 -6
  4. package/lib/ApiExplorer.js +53 -74
  5. package/lib/ApiExplorer.js.map +1 -1
  6. package/lib/StandaloneApiExplorer.js +35 -47
  7. package/lib/StandaloneApiExplorer.js.map +1 -1
  8. package/lib/components/Banner/Banner.d.ts +8 -0
  9. package/lib/components/Banner/Banner.js +70 -0
  10. package/lib/components/Banner/Banner.js.map +1 -0
  11. package/lib/components/Banner/index.d.ts +1 -0
  12. package/lib/components/Banner/index.js +14 -0
  13. package/lib/components/Banner/index.js.map +1 -0
  14. package/lib/components/DocSDKs/DocSDKs.js +3 -3
  15. package/lib/components/DocSDKs/DocSDKs.js.map +1 -1
  16. package/lib/components/ExploreType/ExploreType.js +3 -5
  17. package/lib/components/ExploreType/ExploreType.js.map +1 -1
  18. package/lib/components/Header/Header.d.ts +2 -5
  19. package/lib/components/Header/Header.js +1 -5
  20. package/lib/components/Header/Header.js.map +1 -1
  21. package/lib/components/SelectorContainer/ApiSpecSelector.d.ts +2 -5
  22. package/lib/components/SelectorContainer/ApiSpecSelector.js +5 -5
  23. package/lib/components/SelectorContainer/ApiSpecSelector.js.map +1 -1
  24. package/lib/components/SelectorContainer/SelectorContainer.d.ts +2 -5
  25. package/lib/components/SelectorContainer/SelectorContainer.js +3 -7
  26. package/lib/components/SelectorContainer/SelectorContainer.js.map +1 -1
  27. package/lib/components/SideNav/SideNav.d.ts +2 -5
  28. package/lib/components/SideNav/SideNav.js.map +1 -1
  29. package/lib/components/index.d.ts +1 -0
  30. package/lib/components/index.js +8 -0
  31. package/lib/components/index.js.map +1 -1
  32. package/lib/esm/ApiExplorer.js +54 -74
  33. package/lib/esm/ApiExplorer.js.map +1 -1
  34. package/lib/esm/StandaloneApiExplorer.js +34 -48
  35. package/lib/esm/StandaloneApiExplorer.js.map +1 -1
  36. package/lib/esm/components/Banner/Banner.js +54 -0
  37. package/lib/esm/components/Banner/Banner.js.map +1 -0
  38. package/lib/esm/components/Banner/index.js +2 -0
  39. package/lib/esm/components/Banner/index.js.map +1 -0
  40. package/lib/esm/components/DocSDKs/DocSDKs.js +2 -2
  41. package/lib/esm/components/DocSDKs/DocSDKs.js.map +1 -1
  42. package/lib/esm/components/ExploreType/ExploreType.js +3 -4
  43. package/lib/esm/components/ExploreType/ExploreType.js.map +1 -1
  44. package/lib/esm/components/Header/Header.js +1 -5
  45. package/lib/esm/components/Header/Header.js.map +1 -1
  46. package/lib/esm/components/SelectorContainer/ApiSpecSelector.js +4 -5
  47. package/lib/esm/components/SelectorContainer/ApiSpecSelector.js.map +1 -1
  48. package/lib/esm/components/SelectorContainer/SelectorContainer.js +3 -7
  49. package/lib/esm/components/SelectorContainer/SelectorContainer.js.map +1 -1
  50. package/lib/esm/components/SideNav/SideNav.js.map +1 -1
  51. package/lib/esm/components/index.js +1 -0
  52. package/lib/esm/components/index.js.map +1 -1
  53. package/lib/esm/index.js +1 -0
  54. package/lib/esm/index.js.map +1 -1
  55. package/lib/esm/routes/AppRouter.js +3 -7
  56. package/lib/esm/routes/AppRouter.js.map +1 -1
  57. package/lib/esm/scenes/DiffScene/DiffScene.js +43 -99
  58. package/lib/esm/scenes/DiffScene/DiffScene.js.map +1 -1
  59. package/lib/esm/scenes/DiffScene/DocDiff/DiffItem.js +9 -13
  60. package/lib/esm/scenes/DiffScene/DocDiff/DiffItem.js.map +1 -1
  61. package/lib/esm/scenes/DiffScene/DocDiff/DocDiff.js +2 -2
  62. package/lib/esm/scenes/DiffScene/DocDiff/DocDiff.js.map +1 -1
  63. package/lib/esm/scenes/MethodScene/MethodScene.js +4 -5
  64. package/lib/esm/scenes/MethodScene/MethodScene.js.map +1 -1
  65. package/lib/esm/state/index.js +1 -0
  66. package/lib/esm/state/index.js.map +1 -1
  67. package/lib/esm/state/specs/index.js +3 -0
  68. package/lib/esm/state/specs/index.js.map +1 -0
  69. package/lib/esm/state/specs/sagas.js +58 -0
  70. package/lib/esm/state/specs/sagas.js.map +1 -0
  71. package/lib/esm/state/specs/selectors.js +8 -0
  72. package/lib/esm/state/specs/selectors.js.map +1 -0
  73. package/lib/esm/state/specs/slice.js +55 -0
  74. package/lib/esm/state/specs/slice.js.map +1 -0
  75. package/lib/esm/state/store.js +53 -2
  76. package/lib/esm/state/store.js.map +1 -1
  77. package/lib/esm/test-utils/redux.js +9 -5
  78. package/lib/esm/test-utils/redux.js.map +1 -1
  79. package/lib/esm/utils/adaptorUtils.js +101 -0
  80. package/lib/esm/utils/adaptorUtils.js.map +1 -0
  81. package/lib/esm/utils/apixAdaptor.js +48 -0
  82. package/lib/esm/utils/apixAdaptor.js.map +1 -0
  83. package/lib/esm/utils/index.js +3 -1
  84. package/lib/esm/utils/index.js.map +1 -1
  85. package/lib/esm/utils/path.js +27 -2
  86. package/lib/esm/utils/path.js.map +1 -1
  87. package/lib/index.d.ts +1 -0
  88. package/lib/index.js +13 -0
  89. package/lib/index.js.map +1 -1
  90. package/lib/routes/AppRouter.d.ts +1 -5
  91. package/lib/routes/AppRouter.js +3 -7
  92. package/lib/routes/AppRouter.js.map +1 -1
  93. package/lib/scenes/DiffScene/DiffScene.js +45 -100
  94. package/lib/scenes/DiffScene/DiffScene.js.map +1 -1
  95. package/lib/scenes/DiffScene/DocDiff/DiffItem.js +9 -13
  96. package/lib/scenes/DiffScene/DocDiff/DiffItem.js.map +1 -1
  97. package/lib/scenes/DiffScene/DocDiff/DocDiff.js +2 -2
  98. package/lib/scenes/DiffScene/DocDiff/DocDiff.js.map +1 -1
  99. package/lib/scenes/MethodScene/MethodScene.d.ts +0 -4
  100. package/lib/scenes/MethodScene/MethodScene.js +5 -5
  101. package/lib/scenes/MethodScene/MethodScene.js.map +1 -1
  102. package/lib/state/index.d.ts +1 -0
  103. package/lib/state/index.js +13 -0
  104. package/lib/state/index.js.map +1 -1
  105. package/lib/state/settings/selectors.d.ts +1 -1
  106. package/lib/state/settings/slice.d.ts +1 -1
  107. package/lib/state/specs/index.d.ts +2 -0
  108. package/lib/state/specs/index.js +32 -0
  109. package/lib/state/specs/index.js.map +1 -0
  110. package/lib/state/specs/sagas.d.ts +1 -0
  111. package/lib/state/specs/sagas.js +67 -0
  112. package/lib/state/specs/sagas.js.map +1 -0
  113. package/lib/state/specs/selectors.d.ts +4 -0
  114. package/lib/state/specs/selectors.js +20 -0
  115. package/lib/state/specs/selectors.js.map +1 -0
  116. package/lib/state/specs/slice.d.ts +49 -0
  117. package/lib/state/specs/slice.js +70 -0
  118. package/lib/state/specs/slice.js.map +1 -0
  119. package/lib/state/store.d.ts +3 -0
  120. package/lib/state/store.js +56 -2
  121. package/lib/state/store.js.map +1 -1
  122. package/lib/test-data/declarations.d.ts +2 -0
  123. package/lib/test-data/examples.d.ts +2 -0
  124. package/lib/test-data/index.d.ts +3 -0
  125. package/lib/test-data/index.js +12 -42
  126. package/lib/test-data/index.js.map +1 -1
  127. package/lib/test-data/specs.d.ts +10 -0
  128. package/lib/test-data/specs.js +6 -6
  129. package/lib/test-data/specs.js.map +1 -1
  130. package/lib/test-utils/redux.d.ts +2 -1
  131. package/lib/test-utils/redux.js +9 -4
  132. package/lib/test-utils/redux.js.map +1 -1
  133. package/lib/utils/adaptorUtils.d.ts +30 -0
  134. package/lib/utils/adaptorUtils.js +124 -0
  135. package/lib/utils/adaptorUtils.js.map +1 -0
  136. package/lib/utils/apixAdaptor.d.ts +15 -0
  137. package/lib/utils/apixAdaptor.js +67 -0
  138. package/lib/utils/apixAdaptor.js.map +1 -0
  139. package/lib/utils/index.d.ts +3 -1
  140. package/lib/utils/index.js +45 -30
  141. package/lib/utils/index.js.map +1 -1
  142. package/lib/utils/path.d.ts +3 -0
  143. package/lib/utils/path.js +32 -2
  144. package/lib/utils/path.js.map +1 -1
  145. package/package.json +10 -10
  146. package/src/ApiExplorer.tsx +47 -74
  147. package/src/StandaloneApiExplorer.tsx +37 -52
  148. package/src/components/Banner/Banner.spec.tsx +99 -0
  149. package/src/components/Banner/Banner.tsx +87 -0
  150. package/src/{reducers → components/Banner}/index.ts +1 -1
  151. package/src/components/DocSDKs/DocSDKs.tsx +4 -5
  152. package/src/components/ExploreType/ExploreType.spec.tsx +0 -23
  153. package/src/components/ExploreType/ExploreType.tsx +5 -6
  154. package/src/components/ExploreType/exploreUtils.spec.tsx +1 -1
  155. package/src/components/Header/Header.spec.tsx +9 -30
  156. package/src/components/Header/Header.tsx +3 -10
  157. package/src/components/SelectorContainer/ApiSpecSelector.spec.tsx +31 -44
  158. package/src/components/SelectorContainer/ApiSpecSelector.tsx +6 -12
  159. package/src/components/SelectorContainer/SelectorContainer.spec.tsx +7 -26
  160. package/src/components/SelectorContainer/SelectorContainer.tsx +4 -10
  161. package/src/components/SideNav/SideNav.spec.tsx +12 -45
  162. package/src/components/SideNav/SideNav.tsx +1 -7
  163. package/src/components/index.ts +1 -0
  164. package/src/index.ts +1 -0
  165. package/src/routes/AppRouter.tsx +25 -37
  166. package/src/scenes/DiffScene/DiffScene.tsx +47 -84
  167. package/src/scenes/DiffScene/DocDiff/DiffItem.spec.tsx +9 -16
  168. package/src/scenes/DiffScene/DocDiff/DiffItem.tsx +11 -12
  169. package/src/scenes/DiffScene/DocDiff/DocDiff.tsx +2 -2
  170. package/src/scenes/MethodScene/MethodScene.tsx +4 -10
  171. package/src/state/index.ts +1 -0
  172. package/src/{reducers/spec → state/specs}/index.ts +2 -3
  173. package/src/state/specs/sagas.spec.ts +135 -0
  174. package/src/state/specs/sagas.ts +81 -0
  175. package/src/{reducers/spec/actions.spec.ts → state/specs/selectors.ts} +12 -11
  176. package/src/state/specs/slice.ts +109 -0
  177. package/src/state/store.ts +58 -0
  178. package/src/test-data/index.ts +1 -8
  179. package/src/test-data/specs.ts +6 -6
  180. package/src/test-utils/redux.tsx +15 -4
  181. package/src/utils/adaptorUtils.ts +181 -0
  182. package/src/utils/apixAdaptor.ts +72 -0
  183. package/src/utils/index.ts +3 -7
  184. package/src/utils/path.ts +25 -2
  185. package/lib/esm/reducers/index.js +0 -2
  186. package/lib/esm/reducers/index.js.map +0 -1
  187. package/lib/esm/reducers/spec/actions.js +0 -19
  188. package/lib/esm/reducers/spec/actions.js.map +0 -1
  189. package/lib/esm/reducers/spec/index.js +0 -4
  190. package/lib/esm/reducers/spec/index.js.map +0 -1
  191. package/lib/esm/reducers/spec/reducer.js +0 -62
  192. package/lib/esm/reducers/spec/reducer.js.map +0 -1
  193. package/lib/esm/reducers/spec/utils.js +0 -74
  194. package/lib/esm/reducers/spec/utils.js.map +0 -1
  195. package/lib/reducers/index.d.ts +0 -1
  196. package/lib/reducers/index.js +0 -19
  197. package/lib/reducers/index.js.map +0 -1
  198. package/lib/reducers/spec/actions.d.ts +0 -20
  199. package/lib/reducers/spec/actions.js +0 -31
  200. package/lib/reducers/spec/actions.js.map +0 -1
  201. package/lib/reducers/spec/index.d.ts +0 -3
  202. package/lib/reducers/spec/index.js +0 -45
  203. package/lib/reducers/spec/index.js.map +0 -1
  204. package/lib/reducers/spec/reducer.d.ts +0 -7
  205. package/lib/reducers/spec/reducer.js +0 -73
  206. package/lib/reducers/spec/reducer.js.map +0 -1
  207. package/lib/reducers/spec/utils.d.ts +0 -7
  208. package/lib/reducers/spec/utils.js +0 -91
  209. package/lib/reducers/spec/utils.js.map +0 -1
  210. package/src/reducers/spec/actions.ts +0 -62
  211. package/src/reducers/spec/reducer.spec.ts +0 -44
  212. package/src/reducers/spec/reducer.ts +0 -69
  213. package/src/reducers/spec/utils.spec.ts +0 -138
  214. package/src/reducers/spec/utils.ts +0 -123
@@ -24,28 +24,23 @@
24
24
 
25
25
  */
26
26
 
27
- import type { FC, Dispatch } from 'react'
27
+ import type { FC } from 'react'
28
28
  import React from 'react'
29
29
  import { Select } from '@looker/components'
30
30
  import { useHistory, useLocation } from 'react-router-dom'
31
+ import type { SpecItem } from '@looker/sdk-codegen'
32
+ import { useSelector } from 'react-redux'
31
33
 
32
- import type { SpecList, SpecItem } from '@looker/sdk-codegen'
33
- import type { SpecAction } from '../../reducers'
34
- import { selectSpec } from '../../reducers'
34
+ import { selectSpecs } from '../../state'
35
35
 
36
36
  interface ApiSpecSelectorProps {
37
- specs: SpecList
38
37
  spec: SpecItem
39
- specDispatch: Dispatch<SpecAction>
40
38
  }
41
39
 
42
- export const ApiSpecSelector: FC<ApiSpecSelectorProps> = ({
43
- specs,
44
- spec,
45
- specDispatch,
46
- }) => {
40
+ export const ApiSpecSelector: FC<ApiSpecSelectorProps> = ({ spec }) => {
47
41
  const history = useHistory()
48
42
  const location = useLocation()
43
+ const specs = useSelector(selectSpecs)
49
44
  const options = Object.entries(specs).map(([key, spec]) => ({
50
45
  value: key,
51
46
  label: key,
@@ -53,7 +48,6 @@ export const ApiSpecSelector: FC<ApiSpecSelectorProps> = ({
53
48
  }))
54
49
 
55
50
  const handleChange = (specKey: string) => {
56
- specDispatch(selectSpec(specKey))
57
51
  const matchPath = location.pathname.replace(`/${spec.key}`, `/${specKey}`)
58
52
  history.push(matchPath)
59
53
  }
@@ -28,28 +28,21 @@ import { act, screen, waitFor } from '@testing-library/react'
28
28
  import { codeGenerators } from '@looker/sdk-codegen'
29
29
  import userEvent from '@testing-library/user-event'
30
30
 
31
- import { specs, specState } from '../../test-data'
31
+ import { getLoadedSpecs, specs } from '../../test-data'
32
32
  import { renderWithRouterAndReduxProvider } from '../../test-utils'
33
33
  import { defaultSettingsState } from '../../state'
34
34
  import { SelectorContainer } from './SelectorContainer'
35
35
 
36
36
  describe('SelectorContainer', () => {
37
- const specDispatch = jest.fn()
38
-
37
+ const spec = getLoadedSpecs()['4.0']
39
38
  beforeAll(() => {
40
39
  window.HTMLElement.prototype.scrollIntoView = jest.fn()
41
40
  })
42
41
 
43
42
  test('it renders a spec selector with the correct default value and options', async () => {
44
- renderWithRouterAndReduxProvider(
45
- <SelectorContainer
46
- specs={specs}
47
- spec={specState.spec}
48
- specDispatch={specDispatch}
49
- />
50
- )
43
+ renderWithRouterAndReduxProvider(<SelectorContainer spec={spec} />)
51
44
  const selector = screen.getByLabelText('spec selector')
52
- expect(selector).toHaveValue(`${specState.spec.key}`)
45
+ expect(selector).toHaveValue(`${spec.key}`)
53
46
  await act(async () => {
54
47
  await userEvent.click(selector)
55
48
  await waitFor(() => {
@@ -61,13 +54,7 @@ describe('SelectorContainer', () => {
61
54
  })
62
55
 
63
56
  test('it renders an sdk language selector with the correct value and options', async () => {
64
- renderWithRouterAndReduxProvider(
65
- <SelectorContainer
66
- specs={specs}
67
- spec={specState.spec}
68
- specDispatch={specDispatch}
69
- />
70
- )
57
+ renderWithRouterAndReduxProvider(<SelectorContainer spec={spec} />)
71
58
  const selector = screen.getByLabelText('sdk language selector')
72
59
  expect(selector).toHaveValue(defaultSettingsState.sdkLanguage)
73
60
  await act(async () => {
@@ -81,19 +68,13 @@ describe('SelectorContainer', () => {
81
68
  })
82
69
 
83
70
  test('it renders an icon button for the differ', () => {
84
- renderWithRouterAndReduxProvider(
85
- <SelectorContainer
86
- specs={specs}
87
- spec={specState.spec}
88
- specDispatch={specDispatch}
89
- />
90
- )
71
+ renderWithRouterAndReduxProvider(<SelectorContainer spec={spec} />)
91
72
  expect(
92
73
  screen
93
74
  .getByRole('button', {
94
75
  name: 'Compare Specifications',
95
76
  })
96
77
  .closest('a')
97
- ).toHaveAttribute('href', `/diff/${specState.spec.key}/`)
78
+ ).toHaveAttribute('href', `/diff/${spec.key}/`)
98
79
  })
99
80
  })
@@ -24,25 +24,21 @@
24
24
 
25
25
  */
26
26
 
27
- import type { FC, Dispatch } from 'react'
27
+ import type { FC } from 'react'
28
28
  import React from 'react'
29
29
  import type { SpaceHelperProps } from '@looker/components'
30
30
  import { Space, IconButton } from '@looker/components'
31
31
  import { ChangeHistory } from '@styled-icons/material/ChangeHistory'
32
- import type { SpecList, SpecItem } from '@looker/sdk-codegen'
32
+ import type { SpecItem } from '@looker/sdk-codegen'
33
+
33
34
  import { Link } from '../Link'
34
- import type { SpecAction } from '../../reducers'
35
35
  import { diffPath } from '../../utils'
36
36
  import { SdkLanguageSelector } from './SdkLanguageSelector'
37
37
  import { ApiSpecSelector } from './ApiSpecSelector'
38
38
 
39
39
  interface SelectorContainerProps extends SpaceHelperProps {
40
- /** Specs to choose from */
41
- specs: SpecList
42
40
  /** Current selected spec */
43
41
  spec: SpecItem
44
- /** Spec state setter */
45
- specDispatch: Dispatch<SpecAction>
46
42
  }
47
43
 
48
44
  export const HEADER_REM = 4
@@ -51,14 +47,12 @@ export const HEADER_REM = 4
51
47
  * Renders a container for selectors
52
48
  */
53
49
  export const SelectorContainer: FC<SelectorContainerProps> = ({
54
- specs,
55
50
  spec,
56
- specDispatch,
57
51
  ...spaceProps
58
52
  }) => (
59
53
  <Space width="auto" {...spaceProps}>
60
54
  <SdkLanguageSelector />
61
- <ApiSpecSelector specs={specs} spec={spec} specDispatch={specDispatch} />
55
+ <ApiSpecSelector spec={spec} />
62
56
  <Link to={`/${diffPath}/${spec.key}/`}>
63
57
  <IconButton
64
58
  toggle
@@ -28,15 +28,15 @@ import { criteriaToSet } from '@looker/sdk-codegen'
28
28
  import userEvent from '@testing-library/user-event'
29
29
  import { screen, waitFor } from '@testing-library/react'
30
30
 
31
- import { getLoadedSpecs, specState } from '../../test-data'
31
+ import { getLoadedSpecs } from '../../test-data'
32
32
  import { renderWithRouterAndReduxProvider } from '../../test-utils'
33
33
  import { defaultSettingsState } from '../../state'
34
34
  import { SideNav } from './SideNav'
35
35
  import { countMethods, countTypes } from './searchUtils'
36
36
 
37
+ const spec = getLoadedSpecs()['4.0']
38
+
37
39
  describe('SideNav', () => {
38
- const specs = getLoadedSpecs()
39
- const specDispatch = jest.fn()
40
40
  const allTagsPattern = /^(Auth|ApiAuth)$/
41
41
  const allTypesPattern = /^(WriteDashboard|WriteQuery)$/
42
42
 
@@ -55,13 +55,7 @@ describe('SideNav', () => {
55
55
  })
56
56
 
57
57
  test('it renders search, methods tab and types tab', () => {
58
- renderWithRouterAndReduxProvider(
59
- <SideNav
60
- specs={specs}
61
- spec={specState.spec}
62
- specDispatch={specDispatch}
63
- />
64
- )
58
+ renderWithRouterAndReduxProvider(<SideNav spec={spec} />)
65
59
  const search = screen.getByLabelText('Search')
66
60
  expect(search).toHaveProperty('placeholder', 'Search')
67
61
  const tabs = screen.getAllByRole('tab', {
@@ -69,23 +63,14 @@ describe('SideNav', () => {
69
63
  })
70
64
  expect(tabs).toHaveLength(2)
71
65
  expect(tabs[0]).toHaveTextContent(
72
- `Methods (${countMethods(specState.spec.api!.tags)})`
66
+ `Methods (${countMethods(spec.api!.tags)})`
73
67
  )
74
68
 
75
- expect(tabs[1]).toHaveTextContent(
76
- `Types (${countTypes(specState.spec.api!.types)})`
77
- )
69
+ expect(tabs[1]).toHaveTextContent(`Types (${countTypes(spec.api!.types)})`)
78
70
  })
79
71
 
80
72
  test('Methods tab is the default active tab', () => {
81
- renderWithRouterAndReduxProvider(
82
- <SideNav
83
- specs={specs}
84
- spec={specState.spec}
85
- specDispatch={specDispatch}
86
- />,
87
- ['/3.1/methods']
88
- )
73
+ renderWithRouterAndReduxProvider(<SideNav spec={spec} />, ['/3.1/methods'])
89
74
  expect(screen.getAllByText(allTagsPattern)).toHaveLength(2)
90
75
  expect(
91
76
  screen.queryAllByRole('link', { name: allTypesPattern })
@@ -97,47 +82,29 @@ describe('SideNav', () => {
97
82
  })
98
83
 
99
84
  test('url determines active tab', () => {
100
- renderWithRouterAndReduxProvider(
101
- <SideNav
102
- specs={specs}
103
- spec={specState.spec}
104
- specDispatch={specDispatch}
105
- />,
106
- ['/3.1/types']
107
- )
85
+ renderWithRouterAndReduxProvider(<SideNav spec={spec} />, ['/3.1/types'])
108
86
  // eslint-disable-next-line jest-dom/prefer-in-document
109
87
  expect(screen.queryAllByText(allTagsPattern)).toHaveLength(2)
110
88
  })
111
89
  })
112
90
 
113
91
  describe('Search', () => {
114
- const specs = getLoadedSpecs()
115
- const specDispatch = jest.fn()
116
-
117
92
  test('it filters methods and types on input', async () => {
118
- renderWithRouterAndReduxProvider(
119
- <SideNav
120
- specs={specs}
121
- spec={specState.spec}
122
- specDispatch={specDispatch}
123
- />
124
- )
93
+ renderWithRouterAndReduxProvider(<SideNav spec={spec} />)
125
94
  const searchPattern = 'embedsso'
126
95
  const input = screen.getByLabelText('Search')
127
- jest.spyOn(specState.spec.api!, 'search')
96
+ jest.spyOn(spec.api!, 'search')
128
97
  /** Pasting to avoid triggering search multiple times */
129
98
  await userEvent.paste(input, searchPattern)
130
99
  await waitFor(() => {
131
- expect(specState.spec.api!.search).toHaveBeenCalledWith(
100
+ expect(spec.api!.search).toHaveBeenCalledWith(
132
101
  searchPattern,
133
102
  criteriaToSet(defaultSettingsState.searchCriteria)
134
103
  )
135
104
  const methods = screen.getByRole('tab', { name: 'Methods (1)' })
136
105
  userEvent.click(methods)
137
106
  expect(
138
- screen.getByText(
139
- specState.spec.api!.tags.Auth.create_sso_embed_url.summary
140
- )
107
+ screen.getByText(spec.api!.tags.Auth.create_sso_embed_url.summary)
141
108
  ).toBeInTheDocument()
142
109
  const types = screen.getByRole('tab', { name: 'Types (1)' })
143
110
  userEvent.click(types)
@@ -24,7 +24,7 @@
24
24
 
25
25
  */
26
26
 
27
- import type { FC, Dispatch } from 'react'
27
+ import type { FC } from 'react'
28
28
  import React, { useEffect, useState } from 'react'
29
29
  import { useHistory, useLocation } from 'react-router-dom'
30
30
  import {
@@ -37,7 +37,6 @@ import {
37
37
  } from '@looker/components'
38
38
  import type {
39
39
  SpecItem,
40
- SpecList,
41
40
  ISearchResult,
42
41
  ApiModel,
43
42
  TagList,
@@ -46,7 +45,6 @@ import type {
46
45
  import { criteriaToSet, tagTypes } from '@looker/sdk-codegen'
47
46
  import { useSelector } from 'react-redux'
48
47
 
49
- import type { SpecAction } from '../../reducers'
50
48
  import { useWindowSize } from '../../utils'
51
49
  import { HEADER_REM } from '../Header'
52
50
  import { selectSearchCriteria, useSettingActions } from '../../state'
@@ -65,12 +63,8 @@ interface SideNavState {
65
63
 
66
64
  interface SideNavProps {
67
65
  headless?: boolean
68
- /** Specs to choose from */
69
- specs: SpecList
70
66
  /** Current selected spec */
71
67
  spec: SpecItem
72
- /** Spec state setter */
73
- specDispatch: Dispatch<SpecAction>
74
68
  }
75
69
 
76
70
  export const SideNav: FC<SideNavProps> = ({ headless = false, spec }) => {
@@ -45,3 +45,4 @@ export { DocTypeSummary } from './DocTypeSummary'
45
45
  export { Link } from './Link'
46
46
  export { ErrorBoundary } from './ErrorBoundary'
47
47
  export { SelectorContainer } from './SelectorContainer'
48
+ export { Banner } from './Banner'
package/src/index.ts CHANGED
@@ -27,3 +27,4 @@ export * from './ApiExplorer'
27
27
  export * from './StandaloneApiExplorer'
28
28
  export * from './components'
29
29
  export * from './state'
30
+ export * from './utils'
@@ -28,8 +28,6 @@ import type { FC } from 'react'
28
28
  import React from 'react'
29
29
  import { Redirect, Route, Switch } from 'react-router-dom'
30
30
  import type { ApiModel, SpecList } from '@looker/sdk-codegen'
31
- import type { RunItSetter } from '@looker/run-it'
32
- import type { IEnvironmentAdaptor } from '@looker/extension-utils'
33
31
 
34
32
  import {
35
33
  HomeScene,
@@ -42,47 +40,37 @@ import { DiffScene } from '../scenes/DiffScene'
42
40
  import { diffPath } from '../utils'
43
41
 
44
42
  interface AppRouterProps {
45
- api: ApiModel
46
43
  specKey: string
47
44
  specs: SpecList
45
+ api: ApiModel
48
46
  toggleNavigation: (target?: boolean) => void
49
- adaptor: IEnvironmentAdaptor
50
- setVersionsUrl: RunItSetter
51
47
  }
52
48
 
53
49
  export const AppRouter: FC<AppRouterProps> = ({
54
- specKey,
55
50
  api,
51
+ specKey,
56
52
  specs,
57
53
  toggleNavigation,
58
- adaptor,
59
- setVersionsUrl,
60
- }) => {
61
- return (
62
- <Switch>
63
- <Redirect from="/" to={`/${specKey}/`} exact />
64
- <Route path={`/${diffPath}/:l?/:r?`}>
65
- <DiffScene specs={specs} toggleNavigation={toggleNavigation} />
66
- </Route>
67
- <Route path="/:specKey/(methods|types)?" exact>
68
- <HomeScene api={api} />
69
- </Route>
70
- <Route path="/:specKey/methods/:methodTag" exact>
71
- <MethodTagScene api={api} />
72
- </Route>
73
- <Route path="/:specKey/methods/:methodTag/:methodName">
74
- <MethodScene
75
- api={api}
76
- adaptor={adaptor}
77
- setVersionsUrl={setVersionsUrl}
78
- />
79
- </Route>
80
- <Route path="/:specKey/types/:typeTag" exact>
81
- <TypeTagScene api={api} />
82
- </Route>
83
- <Route path="/:specKey/types/:typeTag/:typeName">
84
- <TypeScene api={api} />
85
- </Route>
86
- </Switch>
87
- )
88
- }
54
+ }) => (
55
+ <Switch>
56
+ <Redirect from="/" to={`/${specKey}/`} exact />
57
+ <Route path={`/${diffPath}/:l?/:r?`}>
58
+ <DiffScene specs={specs} toggleNavigation={toggleNavigation} />
59
+ </Route>
60
+ <Route path="/:specKey/(methods|types)?" exact>
61
+ <HomeScene api={api} />
62
+ </Route>
63
+ <Route path="/:specKey/methods/:methodTag" exact>
64
+ <MethodTagScene api={api} />
65
+ </Route>
66
+ <Route path="/:specKey/methods/:methodTag/:methodName">
67
+ <MethodScene api={api} />
68
+ </Route>
69
+ <Route path="/:specKey/types/:typeTag" exact>
70
+ <TypeTagScene api={api} />
71
+ </Route>
72
+ <Route path="/:specKey/types/:typeTag/:typeName">
73
+ <TypeScene api={api} />
74
+ </Route>
75
+ </Switch>
76
+ )
@@ -26,7 +26,7 @@
26
26
 
27
27
  import type { FC } from 'react'
28
28
  import React, { useState, useEffect } from 'react'
29
- import type { ApiModel, DiffRow, SpecList, SpecItem } from '@looker/sdk-codegen'
29
+ import type { ApiModel, DiffRow, SpecList } from '@looker/sdk-codegen'
30
30
  import { useHistory, useRouteMatch } from 'react-router-dom'
31
31
  import {
32
32
  Box,
@@ -38,35 +38,14 @@ import {
38
38
  SelectMulti,
39
39
  } from '@looker/components'
40
40
  import { SyncAlt } from '@styled-icons/material/SyncAlt'
41
- import { fallbackFetch, funFetch } from '@looker/run-it'
42
- import { getDefaultSpecKey } from '../../reducers/spec/utils'
43
- import { diffPath } from '../../utils'
41
+ import { useSelector } from 'react-redux'
42
+
44
43
  import { ApixSection } from '../../components'
44
+ import { selectCurrentSpec } from '../../state'
45
+ import { diffPath, getApixAdaptor } from '../../utils'
45
46
  import { diffSpecs, standardDiffToggles } from './diffUtils'
46
47
  import { DocDiff } from './DocDiff'
47
48
 
48
- /**
49
- * Pick the left key, or default spec
50
- * @param specs to pick from
51
- * @param leftKey spec key that may or may not have a value
52
- */
53
- const pickLeft = (specs: SpecList, leftKey: string) => {
54
- if (leftKey) return leftKey
55
- return getDefaultSpecKey(specs)
56
- }
57
-
58
- /**
59
- * Pick the right key, or "other" spec
60
- * @param specs to pick from
61
- * @param rightKey spec key from url path
62
- * @param leftKey spec key from url path
63
- */
64
- const pickRight = (specs: SpecList, rightKey: string, leftKey: string) => {
65
- if (rightKey) return rightKey
66
- if (!leftKey) leftKey = getDefaultSpecKey(specs)
67
- return Object.keys(specs).find((k) => k !== leftKey) || ''
68
- }
69
-
70
49
  const diffToggles = [
71
50
  {
72
51
  label: 'Missing',
@@ -104,7 +83,10 @@ const validateParam = (specs: SpecList, specKey = '') => {
104
83
  }
105
84
 
106
85
  export const DiffScene: FC<DiffSceneProps> = ({ specs, toggleNavigation }) => {
86
+ const adaptor = getApixAdaptor()
107
87
  const history = useHistory()
88
+ const spec = useSelector(selectCurrentSpec)
89
+ const currentSpecKey = spec.key
108
90
  const match = useRouteMatch<{ l: string; r: string }>(`/${diffPath}/:l?/:r?`)
109
91
  const l = validateParam(specs, match?.params.l)
110
92
  const r = validateParam(specs, match?.params.r)
@@ -114,83 +96,62 @@ export const DiffScene: FC<DiffSceneProps> = ({ specs, toggleNavigation }) => {
114
96
  label: `${key} (${spec.status})`,
115
97
  }))
116
98
 
117
- const [leftKey, setLeftKey] = useState<string>(pickLeft(specs, l))
118
- const [rightKey, setRightKey] = useState<string>(pickRight(specs, r, leftKey))
99
+ const [leftKey, setLeftKey] = useState<string>(l || currentSpecKey)
100
+ const [rightKey, setRightKey] = useState<string>(r || '')
119
101
  const [leftApi, setLeftApi] = useState<ApiModel>(specs[leftKey].api!)
120
- const [rightApi, setRightApi] = useState<ApiModel>(
102
+ const [rightApi, setRightApi] = useState<ApiModel>(() =>
121
103
  rightKey ? specs[rightKey].api! : specs[leftKey].api!
122
104
  )
123
105
  const [toggles, setToggles] = useState<string[]>(standardDiffToggles)
124
106
 
125
107
  useEffect(() => {
126
- toggleNavigation(false)
127
- }, [])
128
-
129
- const computeDelta = (left: string, right: string, toggles: string[]) => {
130
- if (left && right && specs[left].api && specs[right].api) {
131
- return diffSpecs(specs[left].api!, specs[right].api!, toggles)
108
+ if (r !== rightKey) {
109
+ setRightKey(r)
132
110
  }
133
- return []
134
- }
135
- const [delta, setDelta] = useState<DiffRow[]>(
136
- computeDelta(leftKey, rightKey, toggles)
137
- )
111
+ }, [r, rightKey])
138
112
 
139
- const loadSpec = async (
140
- specs: SpecList,
141
- key: string,
142
- setter: (spec: SpecItem) => void
143
- ) => {
144
- const spec = specs[key]
145
- if (!spec.api) {
146
- try {
147
- const newSpec = { ...spec }
148
- const api = await fallbackFetch(newSpec, funFetch)
149
- if (api) {
150
- spec.api = api
151
- setter(spec)
152
- }
153
- } catch (error) {
154
- console.error(error)
155
- }
113
+ useEffect(() => {
114
+ if (l !== leftKey) {
115
+ setLeftKey(l)
156
116
  }
157
- }
117
+ }, [l, leftKey])
158
118
 
159
- const compareKeys = async (left: string, right: string) => {
160
- if (left !== leftKey || right !== rightKey) {
161
- history.push(`/${diffPath}/${left}/${right}`)
162
- }
163
- if (!specs[left].api) {
164
- await loadSpec(specs, leftKey, (spec) => setLeftApi(spec.api!))
165
- }
166
- if (!specs[right].api) {
167
- await loadSpec(specs, rightKey, (spec) => setRightApi(spec.api!))
168
- }
169
- setDelta([...computeDelta(left, right, toggles)])
170
- }
119
+ useEffect(() => {
120
+ toggleNavigation(false)
121
+ }, [])
122
+
123
+ const [delta, setDelta] = useState<DiffRow[]>([])
171
124
 
172
125
  const handleLeftChange = (newLeft: string) => {
173
- setLeftKey(newLeft)
126
+ history.push(`/${diffPath}/${newLeft}/${rightKey}`)
127
+ }
128
+ const handleRightChange = (newRight: string) => {
129
+ history.push(`/${diffPath}/${leftKey}/${newRight}`)
174
130
  }
175
131
 
176
- const handleTogglesChange = (values?: string[]) => {
177
- const newToggles = values || []
178
- setToggles(newToggles)
179
- setDelta([...computeDelta(leftKey, rightKey, newToggles)])
132
+ const handleSwitch = () => {
133
+ history.push(`/${diffPath}/${rightKey}/${leftKey}`)
180
134
  }
181
135
 
182
136
  useEffect(() => {
183
- compareKeys(leftKey, rightKey)
184
- }, [leftKey, rightKey])
137
+ adaptor.fetchSpec(specs[leftKey]).then((spec) => setLeftApi(spec.api!))
138
+ }, [leftKey])
185
139
 
186
- const handleRightChange = (newRight: string) => {
187
- setRightKey(newRight)
188
- }
140
+ useEffect(() => {
141
+ if (rightKey in specs) {
142
+ adaptor.fetchSpec(specs[rightKey]).then((spec) => setRightApi(spec.api!))
143
+ }
144
+ }, [rightKey])
189
145
 
190
- const handleSwitch = () => {
191
- const currLeftKey = leftKey
192
- setLeftKey(rightKey)
193
- setRightKey(currLeftKey)
146
+ useEffect(() => {
147
+ if (leftApi && rightApi) {
148
+ setDelta([...diffSpecs(leftApi, rightApi, toggles)])
149
+ }
150
+ }, [leftApi, rightApi, toggles])
151
+
152
+ const handleTogglesChange = (values?: string[]) => {
153
+ const newToggles = values || []
154
+ setToggles(newToggles)
194
155
  }
195
156
 
196
157
  return (
@@ -211,6 +172,7 @@ export const DiffScene: FC<DiffSceneProps> = ({ specs, toggleNavigation }) => {
211
172
  <IconButton
212
173
  label="switch"
213
174
  size="small"
175
+ disabled={!leftKey || !rightKey}
214
176
  icon={<SyncAlt />}
215
177
  mt="medium"
216
178
  onClick={handleSwitch}
@@ -221,6 +183,7 @@ export const DiffScene: FC<DiffSceneProps> = ({ specs, toggleNavigation }) => {
221
183
  mt="xxsmall"
222
184
  id="compare"
223
185
  name="Right Version"
186
+ placeholder="Select a comparison..."
224
187
  value={rightKey}
225
188
  options={options}
226
189
  onChange={handleRightChange}
@@ -28,8 +28,7 @@ import { Router } from 'react-router'
28
28
  import type { MemoryHistory } from 'history'
29
29
  import { createMemoryHistory } from 'history'
30
30
  import { renderWithTheme } from '@looker/components-test-utils'
31
- import userEvent from '@testing-library/user-event'
32
- import { act, screen } from '@testing-library/react'
31
+ import { screen, fireEvent } from '@testing-library/react'
33
32
  import { api } from '../../../test-data'
34
33
  import { DiffMethodLink } from './DiffItem'
35
34
 
@@ -37,27 +36,24 @@ describe('DiffMethodLink', () => {
37
36
  const method = api.methods.create_dashboard
38
37
  const specKey = '4.0'
39
38
  let history: MemoryHistory
40
- let pushSpy: jasmine.Spy
41
39
 
42
40
  beforeEach(() => {
43
41
  history = createMemoryHistory()
44
- pushSpy = spyOn(history, 'push')
45
42
  })
46
43
 
47
44
  test('it renders method and navigates on click', () => {
45
+ const pushSpy = jest.spyOn(history, 'push')
48
46
  renderWithTheme(
49
47
  <Router history={history}>
50
48
  <DiffMethodLink method={method} specKey={specKey} />
51
49
  </Router>
52
50
  )
53
- const s = `${method.name} for ${specKey}`
54
- expect(screen.getByText(s)).toBeInTheDocument()
55
- userEvent.click(screen.getByText(s))
56
- act(() => {
57
- expect(pushSpy).toHaveBeenCalledWith(
58
- `/${specKey}/methods/${method.schema.tags[0]}/${method.name}`
59
- )
60
- })
51
+ const link = screen.getByRole('link')
52
+ expect(link).toHaveTextContent(`${method.name} for ${specKey}`)
53
+ fireEvent.click(link)
54
+ expect(pushSpy).toHaveBeenCalledWith(
55
+ `/${specKey}/methods/${method.schema.tags[0]}/${method.name}`
56
+ )
61
57
  })
62
58
 
63
59
  test('it renders missing method and does not navigate on click', () => {
@@ -68,9 +64,6 @@ describe('DiffMethodLink', () => {
68
64
  )
69
65
  const s = `Missing in ${specKey}`
70
66
  expect(screen.getByText(s)).toBeInTheDocument()
71
- userEvent.click(screen.getByText(s))
72
- act(() => {
73
- expect(pushSpy).not.toHaveBeenCalled()
74
- })
67
+ expect(screen.queryByRole('link')).not.toBeInTheDocument()
75
68
  })
76
69
  })