diff --git a/packages/api-explorer/src/ApiExplorer.tsx b/packages/api-explorer/src/ApiExplorer.tsx index 35b3be517..272e50ce9 100644 --- a/packages/api-explorer/src/ApiExplorer.tsx +++ b/packages/api-explorer/src/ApiExplorer.tsx @@ -32,14 +32,15 @@ import { Aside, ComponentsProvider, Layout, Page } from '@looker/components' import type { SpecList } from '@looker/sdk-codegen' import type { RunItSetter } from '@looker/run-it' import { funFetch, fallbackFetch, OAuthScene } from '@looker/run-it' -import { - SearchContext, - LodeContext, - defaultLodeContextValue, - EnvAdaptorContext, -} from './context' +import { SearchContext, LodeContext, defaultLodeContextValue } from './context' import type { IApixEnvAdaptor } from './utils' -import { EnvAdaptorConstants, getLoded, oAuthPath } from './utils' +import { + EnvAdaptorConstants, + getLoded, + oAuthPath, + registerEnvAdaptor, + unregisterEnvAdaptor, +} from './utils' import { Header, SideNav, ErrorBoundary } from './components' import { specReducer, @@ -71,10 +72,10 @@ const ApiExplorer: FC = ({ declarationsLodeUrl = `${apixFilesHost}/declarationsIndex.json`, headless = false, }) => { + registerEnvAdaptor(envAdaptor) const location = useLocation() const { setSdkLanguageAction } = useActions() const oauthReturn = location.pathname === `/${oAuthPath}` - const [specState, specDispatch] = useReducer( specReducer, initDefaultSpecState(specs, location) @@ -97,6 +98,10 @@ const ApiExplorer: FC = ({ } }, []) + useEffect(() => { + return () => unregisterEnvAdaptor() + }, []) + useEffect(() => { if (headless) { window.addEventListener('message', hasNavigationToggle) @@ -153,47 +158,45 @@ const ApiExplorer: FC = ({ themeCustomizations={themeCustomizations} > - - - - - {!headless && ( -
+ + + {!headless && ( +
+ )} + + {hasNavigation && ( + + + + )} + {oauthReturn && } + {!oauthReturn && spec.api && ( + )} - - {hasNavigation && ( - - - - )} - {oauthReturn && } - {!oauthReturn && spec.api && ( - - )} - - - - - + + + + {!headless && } diff --git a/packages/api-explorer/src/components/DocMarkdown/DocMarkdown.spec.tsx b/packages/api-explorer/src/components/DocMarkdown/DocMarkdown.spec.tsx index 62e6905c2..db6364f4d 100644 --- a/packages/api-explorer/src/components/DocMarkdown/DocMarkdown.spec.tsx +++ b/packages/api-explorer/src/components/DocMarkdown/DocMarkdown.spec.tsx @@ -28,10 +28,13 @@ import React from 'react' import { screen } from '@testing-library/react' import { renderWithTheme } from '@looker/components-test-utils' -import { renderWithSearch } from '../../test-utils' +import { renderWithSearch, registerTestEnvAdaptor } from '../../test-utils' import { DocMarkdown } from './DocMarkdown' describe('DocMarkdown', () => { + beforeEach(() => { + registerTestEnvAdaptor() + }) test('it renders markdown', () => { renderWithSearch( = ({ source, specKey }) => { - const { envAdaptor } = useContext(EnvAdaptorContext) + const envAdaptor = getEnvAdaptor() const { searchSettings: { pattern }, } = useContext(SearchContext) diff --git a/packages/api-explorer/src/components/Header/Header.spec.tsx b/packages/api-explorer/src/components/Header/Header.spec.tsx index 0c664a812..cb63d994f 100644 --- a/packages/api-explorer/src/components/Header/Header.spec.tsx +++ b/packages/api-explorer/src/components/Header/Header.spec.tsx @@ -29,7 +29,11 @@ import { codeGenerators } from '@looker/sdk-codegen' import userEvent from '@testing-library/user-event' import { specs, specState } from '../../test-data' -import { renderWithRouter, withReduxProvider } from '../../test-utils' +import { + renderWithRouter, + withReduxProvider, + registerTestEnvAdaptor, +} from '../../test-utils' import { defaultSettingsState } from '../../state' import { Header } from './Header' @@ -40,6 +44,7 @@ describe('Header', () => { beforeAll(() => { window.HTMLElement.prototype.scrollIntoView = jest.fn() + registerTestEnvAdaptor() }) test('it renders a title', () => { diff --git a/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.spec.tsx b/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.spec.tsx index 07975cd09..d215a8d42 100644 --- a/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.spec.tsx +++ b/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.spec.tsx @@ -29,7 +29,10 @@ import userEvent from '@testing-library/user-event' import { codeGenerators } from '@looker/sdk-codegen' import { defaultSettingsState } from '../../state' -import { renderWithReduxProvider } from '../../test-utils' +import { + registerTestEnvAdaptor, + renderWithReduxProvider, +} from '../../test-utils' import { EnvAdaptorConstants } from '../../utils' import { SdkLanguageSelector } from './SdkLanguageSelector' @@ -38,6 +41,7 @@ describe('SdkLanguageSelector', () => { beforeEach(() => { localStorage.clear() + registerTestEnvAdaptor() }) test('it has the correct default language selected', () => { diff --git a/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.tsx b/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.tsx index 96e6ece1a..07cde8efc 100644 --- a/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.tsx +++ b/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.tsx @@ -24,7 +24,7 @@ */ import type { FC } from 'react' -import React, { useContext } from 'react' +import React from 'react' import { codeGenerators } from '@looker/sdk-codegen' import { Select } from '@looker/components' import { useSelector } from 'react-redux' @@ -32,8 +32,7 @@ import type { SelectOptionProps } from '@looker/components' import { useActions } from '../../hooks' import { getSelectedSdkLanguage } from '../../state' -import { EnvAdaptorContext } from '../../context' -import { EnvAdaptorConstants } from '../../utils' +import { EnvAdaptorConstants, getEnvAdaptor } from '../../utils' /** * Allows the user to select their preferred SDK language @@ -41,7 +40,7 @@ import { EnvAdaptorConstants } from '../../utils' export const SdkLanguageSelector: FC = () => { const { setSdkLanguageAction } = useActions() const selectedSdkLanguage = useSelector(getSelectedSdkLanguage) - const { envAdaptor } = useContext(EnvAdaptorContext) + const envAdaptor = getEnvAdaptor() const allSdkLanguages: SelectOptionProps[] = codeGenerators.map((gen) => ({ value: gen.language, diff --git a/packages/api-explorer/src/components/SelectorContainer/SelectorContainer.spec.tsx b/packages/api-explorer/src/components/SelectorContainer/SelectorContainer.spec.tsx index bc0a34ec7..d560ddf2a 100644 --- a/packages/api-explorer/src/components/SelectorContainer/SelectorContainer.spec.tsx +++ b/packages/api-explorer/src/components/SelectorContainer/SelectorContainer.spec.tsx @@ -29,7 +29,11 @@ import { codeGenerators } from '@looker/sdk-codegen' import userEvent from '@testing-library/user-event' import { specs, specState } from '../../test-data' -import { renderWithRouter, withReduxProvider } from '../../test-utils' +import { + registerTestEnvAdaptor, + renderWithRouter, + withReduxProvider, +} from '../../test-utils' import { defaultSettingsState } from '../../state' import { SelectorContainer } from './SelectorContainer' @@ -38,6 +42,7 @@ describe('SelectorContainer', () => { beforeAll(() => { window.HTMLElement.prototype.scrollIntoView = jest.fn() + registerTestEnvAdaptor() }) test('it renders a spec selector with the correct default value and options', async () => { diff --git a/packages/api-explorer/src/context/envAdaptor/EnvAdaptorContext.ts b/packages/api-explorer/src/context/envAdaptor/EnvAdaptorContext.ts deleted file mode 100644 index c98694cee..000000000 --- a/packages/api-explorer/src/context/envAdaptor/EnvAdaptorContext.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - - MIT License - - Copyright (c) 2021 Looker Data Sciences, Inc. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - - */ -import { createContext } from 'react' -import type { IApixEnvAdaptor } from '../../utils' -import { StandaloneEnvAdaptor } from '../../utils' - -export interface EnvAdaptorContextProps { - envAdaptor: IApixEnvAdaptor -} - -export const defaultEnvAdaptorContextValue: EnvAdaptorContextProps = { - envAdaptor: new StandaloneEnvAdaptor(), -} -export const EnvAdaptorContext = createContext( - defaultEnvAdaptorContextValue -) diff --git a/packages/api-explorer/src/context/index.ts b/packages/api-explorer/src/context/index.ts index 10d7b6d2d..781c60f44 100644 --- a/packages/api-explorer/src/context/index.ts +++ b/packages/api-explorer/src/context/index.ts @@ -25,4 +25,3 @@ */ export { LodeContext, defaultLodeContextValue } from './lode' export { SearchContext, defaultSearchContextValue } from './search' -export { EnvAdaptorContext, defaultEnvAdaptorContextValue } from './envAdaptor' diff --git a/packages/api-explorer/src/context/envAdaptor/index.ts b/packages/api-explorer/src/test-utils/envAdaptor.tsx similarity index 81% rename from packages/api-explorer/src/context/envAdaptor/index.ts rename to packages/api-explorer/src/test-utils/envAdaptor.tsx index f09791dba..fe1972faf 100644 --- a/packages/api-explorer/src/context/envAdaptor/index.ts +++ b/packages/api-explorer/src/test-utils/envAdaptor.tsx @@ -23,7 +23,9 @@ SOFTWARE. */ -export { - defaultEnvAdaptorContextValue, - EnvAdaptorContext, -} from './EnvAdaptorContext' +import type { IApixEnvAdaptor } from '../utils' +import { registerEnvAdaptor, StandaloneEnvAdaptor } from '../utils' + +export const registerTestEnvAdaptor = (envAdaptor?: IApixEnvAdaptor) => { + registerEnvAdaptor(envAdaptor || new StandaloneEnvAdaptor()) +} diff --git a/packages/api-explorer/src/test-utils/index.ts b/packages/api-explorer/src/test-utils/index.ts index 0a0870450..8ba3a5821 100644 --- a/packages/api-explorer/src/test-utils/index.ts +++ b/packages/api-explorer/src/test-utils/index.ts @@ -37,3 +37,4 @@ export { renderWithReduxProvider, withReduxProvider, } from './redux' +export { registerTestEnvAdaptor } from './envAdaptor' diff --git a/packages/api-explorer/src/test-utils/redux.tsx b/packages/api-explorer/src/test-utils/redux.tsx index 28090b3f9..18cff161a 100644 --- a/packages/api-explorer/src/test-utils/redux.tsx +++ b/packages/api-explorer/src/test-utils/redux.tsx @@ -32,43 +32,27 @@ import type { RenderOptions } from '@testing-library/react' import type { RootState } from '../state' import { configureStore } from '../state' -import type { IApixEnvAdaptor } from '../utils' -import { StandaloneEnvAdaptor } from '../utils' -import { EnvAdaptorContext } from '../context' import { renderWithRouter } from '.' const defaultStore = configureStore() export const withReduxProvider = ( consumers: ReactElement, - store: Store = defaultStore, - envAdaptor: IApixEnvAdaptor = new StandaloneEnvAdaptor() + store: Store = defaultStore ) => { - return ( - - - {consumers} - - - ) + return {consumers} } export const renderWithReduxProvider = ( consumers: ReactElement, store?: Store, - envAdaptor?: IApixEnvAdaptor, options?: Omit -) => renderWithTheme(withReduxProvider(consumers, store, envAdaptor), options) +) => renderWithTheme(withReduxProvider(consumers, store), options) export const renderWithRouterAndReduxProvider = ( consumers: ReactElement, initialEntries: string[] = ['/'], store?: Store, - envAdaptor?: IApixEnvAdaptor, options?: Omit ) => - renderWithRouter( - withReduxProvider(consumers, store, envAdaptor), - initialEntries, - options - ) + renderWithRouter(withReduxProvider(consumers, store), initialEntries, options) diff --git a/packages/api-explorer/src/utils/envAdaptor.ts b/packages/api-explorer/src/utils/envAdaptor.ts index 0137b7709..29f159d2f 100644 --- a/packages/api-explorer/src/utils/envAdaptor.ts +++ b/packages/api-explorer/src/utils/envAdaptor.ts @@ -118,3 +118,29 @@ export class StandaloneEnvAdaptor implements IApixEnvAdaptor { export enum EnvAdaptorConstants { LOCALSTORAGE_SDK_LANGUAGE_KEY = 'sdkLanguage', } + +let envAdaptor: IApixEnvAdaptor | undefined + +/** + * Register the environment adaptor. The API Explorer will automatically call this. + */ +export const registerEnvAdaptor = (adaptor: IApixEnvAdaptor) => { + envAdaptor = adaptor +} + +/** + * Unregister the envAdaptor. The ApiExplorer will automatically call this when it is unmounted. + */ +export const unregisterEnvAdaptor = () => { + envAdaptor = undefined +} + +/** + * Global access to the envAdaptor. An error will be thrown if accessed prematurely. + */ +export const getEnvAdaptor = () => { + if (!envAdaptor) { + throw new Error('Environment adaptor not initialized.') + } + return envAdaptor +}