From 2e76e5f9a88b9ff5c6d4b1590ca3620d49b7e052 Mon Sep 17 00:00:00 2001 From: Joseph Axisa Date: Thu, 28 Oct 2021 15:58:21 +0000 Subject: [PATCH 1/3] move lodes into redux --- packages/api-explorer/src/ApiExplorer.tsx | 185 +++++++++--------- .../DocSdkUsage/DocSdkUsage.spec.tsx | 4 +- .../components/DocSdkUsage/DocSdkUsage.tsx | 10 +- .../src/components/DocSource/DocSource.tsx | 7 +- .../SdkLanguageSelector.spec.tsx | 4 +- .../SelectorContainer/SdkLanguageSelector.tsx | 4 +- .../src/components/SideNav/SideNav.tsx | 4 +- packages/api-explorer/src/state/index.ts | 1 + .../src/{context => state/lodes}/index.ts | 3 +- .../api-explorer/src/state/lodes/sagas.ts | 52 +++++ .../index.ts => state/lodes/selectors.ts} | 10 +- .../lodes/slice.ts} | 74 +++---- .../src/state/settings/sagas.spec.ts | 36 ++-- .../api-explorer/src/state/settings/sagas.ts | 13 +- .../src/state/settings/selectors.ts | 10 +- .../api-explorer/src/state/settings/slice.ts | 19 +- packages/api-explorer/src/state/store.ts | 9 +- packages/api-explorer/src/test-utils/index.ts | 5 +- .../LodeContext.ts => test-utils/lode.tsx} | 27 +-- .../api-explorer/src/test-utils/redux.tsx | 18 +- packages/api-explorer/src/utils/lodeUtils.ts | 10 +- 21 files changed, 293 insertions(+), 212 deletions(-) rename packages/api-explorer/src/{context => state/lodes}/index.ts (94%) create mode 100644 packages/api-explorer/src/state/lodes/sagas.ts rename packages/api-explorer/src/{context/lode/index.ts => state/lodes/selectors.ts} (79%) rename packages/api-explorer/src/{test-utils/render_with_lode.tsx => state/lodes/slice.ts} (50%) rename packages/api-explorer/src/{context/lode/LodeContext.ts => test-utils/lode.tsx} (68%) diff --git a/packages/api-explorer/src/ApiExplorer.tsx b/packages/api-explorer/src/ApiExplorer.tsx index dd46842c2..58f81d775 100644 --- a/packages/api-explorer/src/ApiExplorer.tsx +++ b/packages/api-explorer/src/ApiExplorer.tsx @@ -44,14 +44,8 @@ import { funFetch, fallbackFetch, OAuthScene } from '@looker/run-it' import { FirstPage } from '@styled-icons/material/FirstPage' import { LastPage } from '@styled-icons/material/LastPage' -import { LodeContext, defaultLodeContextValue } from './context' import type { IApixEnvAdaptor } from './utils' -import { - getLoded, - oAuthPath, - registerEnvAdaptor, - unregisterEnvAdaptor, -} from './utils' +import { oAuthPath, registerEnvAdaptor, unregisterEnvAdaptor } from './utils' import { Header, SideNav, @@ -63,13 +57,17 @@ import { import { specReducer, initDefaultSpecState, updateSpecApi } from './reducers' import { AppRouter } from './routes' import { apixFilesHost } from './utils/lodeUtils' -import { useActions, useSettingsStoreState } from './state' - +import { + useSettingActions, + useSettingStoreState, + useLodeActions, + useLodeState, +} from './state' export interface ApiExplorerProps { specs: SpecList envAdaptor: IApixEnvAdaptor setVersionsUrl: RunItSetter - exampleLodeUrl?: string + examplesLodeUrl?: string declarationsLodeUrl?: string headless?: boolean } @@ -80,12 +78,14 @@ const ApiExplorer: FC = ({ specs, envAdaptor, setVersionsUrl, - exampleLodeUrl = 'https://raw.githubusercontent.com/looker-open-source/sdk-codegen/main/examplesIndex.json', + examplesLodeUrl = 'https://raw.githubusercontent.com/looker-open-source/sdk-codegen/main/examplesIndex.json', declarationsLodeUrl = `${apixFilesHost}/declarationsIndex.json`, headless = false, }) => { - const { initialized } = useSettingsStoreState() - const { initAction } = useActions() + const { initialized } = useSettingStoreState() + useLodeState() + const { initLodeAction } = useLodeActions() + const { initSettingsAction } = useSettingActions() const location = useLocation() const oauthReturn = location.pathname === `/${oAuthPath}` const [specState, specDispatch] = useReducer( @@ -94,8 +94,6 @@ const ApiExplorer: FC = ({ ) const { spec } = specState - const [lode, setLode] = useState(defaultLodeContextValue) - const [hasNavigation, setHasNavigation] = useState(true) const toggleNavigation = (target?: boolean) => setHasNavigation(target || !hasNavigation) @@ -108,7 +106,7 @@ const ApiExplorer: FC = ({ useEffect(() => { registerEnvAdaptor(envAdaptor) - initAction() + initSettingsAction() return () => unregisterEnvAdaptor() }, []) @@ -145,8 +143,9 @@ const ApiExplorer: FC = ({ }, [spec, location]) useEffect(() => { - getLoded(exampleLodeUrl, declarationsLodeUrl).then((resp) => setLode(resp)) - }, [exampleLodeUrl, declarationsLodeUrl]) + console.log(examplesLodeUrl) + initLodeAction({ examplesLodeUrl, declarationsLodeUrl }) + }, [examplesLodeUrl, declarationsLodeUrl]) const themeOverrides = envAdaptor.themeOverrides() @@ -160,87 +159,85 @@ const ApiExplorer: FC = ({ ) : ( - - - {!headless && ( -
- )} - - - {headless && ( - <> - - {hasNavigation && ( - - API DOCUMENTATION - - )} - : } - label={HEADER_TOGGLE_LABEL} - onClick={() => toggleNavigation()} - /> - + + {!headless && ( +
+ )} + + + {headless && ( + <> + {hasNavigation && ( - <> - - - + + API DOCUMENTATION + )} - - )} - {hasNavigation && ( - - )} - - {oauthReturn && } - {!oauthReturn && spec.api && ( - : } + label={HEADER_TOGGLE_LABEL} + onClick={() => toggleNavigation()} + /> + + {hasNavigation && ( + <> + + + + )} + + )} + {hasNavigation && ( + )} - - - + + {oauthReturn && } + {!oauthReturn && spec.api && ( + + )} + + )} diff --git a/packages/api-explorer/src/components/DocSdkUsage/DocSdkUsage.spec.tsx b/packages/api-explorer/src/components/DocSdkUsage/DocSdkUsage.spec.tsx index 16d3c11c3..ebc828b88 100644 --- a/packages/api-explorer/src/components/DocSdkUsage/DocSdkUsage.spec.tsx +++ b/packages/api-explorer/src/components/DocSdkUsage/DocSdkUsage.spec.tsx @@ -27,7 +27,7 @@ import React from 'react' import { screen } from '@testing-library/react' import { findExampleLanguages } from '@looker/sdk-codegen' -import { renderWithReduxProviderAndLode } from '../../test-utils' +import { renderWithLode } from '../../test-utils' import { api, examples } from '../../test-data' import { DocSdkUsage } from './DocSdkUsage' import { @@ -47,7 +47,7 @@ describe('DocSdkUsage', () => { method.operationId, 1 ) - renderWithReduxProviderAndLode(, examples) + renderWithLode(, examples) expect(screen.getAllByRole('link')).toHaveLength(PER_PAGE_COUNT) expect( diff --git a/packages/api-explorer/src/components/DocSdkUsage/DocSdkUsage.tsx b/packages/api-explorer/src/components/DocSdkUsage/DocSdkUsage.tsx index 781de20e4..1ad1fd199 100644 --- a/packages/api-explorer/src/components/DocSdkUsage/DocSdkUsage.tsx +++ b/packages/api-explorer/src/components/DocSdkUsage/DocSdkUsage.tsx @@ -24,7 +24,7 @@ */ import type { FC } from 'react' -import React, { useContext, useState, useEffect } from 'react' +import React, { useState, useEffect } from 'react' import { Box, Card, @@ -41,8 +41,7 @@ import { CollapserCard } from '@looker/run-it' import { InsertDriveFile } from '@styled-icons/material-outlined/InsertDriveFile' import { useSelector } from 'react-redux' -import { selectSdkLanguage } from '../../state' -import { LodeContext } from '../../context' +import { selectSdkLanguage, selectExamplesLode } from '../../state' import { exampleColumns, EMPTY_STRING, @@ -61,15 +60,16 @@ interface DocSdkUsageProps { * links to the source files */ export const DocSdkUsage: FC = ({ method }) => { - const { examples } = useContext(LodeContext) + const examples = useSelector(selectExamplesLode) const sdkLanguage = useSelector(selectSdkLanguage) - let languages = findExampleLanguages(examples, method.name) const [page, setPage] = useState(1) useEffect(() => { setPage(1) }, [method]) + if (!examples) return <> + let languages = findExampleLanguages(examples, method.name) if (languages.length === 0) return <> languages = sortLanguagesByPreference(languages, sdkLanguage) diff --git a/packages/api-explorer/src/components/DocSource/DocSource.tsx b/packages/api-explorer/src/components/DocSource/DocSource.tsx index 64a607c54..562b97019 100644 --- a/packages/api-explorer/src/components/DocSource/DocSource.tsx +++ b/packages/api-explorer/src/components/DocSource/DocSource.tsx @@ -24,13 +24,14 @@ */ import type { FC } from 'react' -import React, { useContext } from 'react' +import React from 'react' import type { IMethod, IType } from '@looker/sdk-codegen' import { findDeclaration } from '@looker/sdk-codegen' import { Icon, Link, Tooltip } from '@looker/components' import { IdeFileDocument } from '@looker/icons' +import { useSelector } from 'react-redux' -import { LodeContext } from '../../context' +import { selectDeclarationsLode } from '../../state' interface DocSourceProps { method?: IMethod @@ -38,7 +39,7 @@ interface DocSourceProps { } export const DocSource: FC = ({ method, type }) => { - const { declarations } = useContext(LodeContext) + const declarations = useSelector(selectDeclarationsLode) let sourceLink let declaration if (declarations) { diff --git a/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.spec.tsx b/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.spec.tsx index 051045181..2ca860a9b 100644 --- a/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.spec.tsx +++ b/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.spec.tsx @@ -29,7 +29,7 @@ import userEvent from '@testing-library/user-event' import { codeGenerators } from '@looker/sdk-codegen' import * as reactRedux from 'react-redux' -import { defaultSettingsState, slice as settingsSlice } from '../../state' +import { defaultSettingsState, settingSlice } from '../../state' import { registerTestEnvAdaptor, renderWithReduxProvider, @@ -77,7 +77,7 @@ describe('SdkLanguageSelector', () => { await userEvent.click(screen.getByRole('option', { name: 'TypeScript' })) await waitFor(async () => { expect(mockDispatch).toHaveBeenLastCalledWith( - settingsSlice.actions.setSdkLanguageAction({ + settingSlice.actions.setSdkLanguageAction({ sdkLanguage: 'TypeScript', }) ) diff --git a/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.tsx b/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.tsx index 136f006cb..ba42bb350 100644 --- a/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.tsx +++ b/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.tsx @@ -30,13 +30,13 @@ import { Select } from '@looker/components' import { useSelector } from 'react-redux' import type { SelectOptionProps } from '@looker/components' -import { useActions, selectSdkLanguage } from '../../state' +import { useSettingActions, selectSdkLanguage } from '../../state' /** * Allows the user to select their preferred SDK language */ export const SdkLanguageSelector: FC = () => { - const { setSdkLanguageAction } = useActions() + const { setSdkLanguageAction } = useSettingActions() const selectedSdkLanguage = useSelector(selectSdkLanguage) const allSdkLanguages: SelectOptionProps[] = codeGenerators.map((gen) => ({ diff --git a/packages/api-explorer/src/components/SideNav/SideNav.tsx b/packages/api-explorer/src/components/SideNav/SideNav.tsx index d60b7165c..a9781b8c5 100644 --- a/packages/api-explorer/src/components/SideNav/SideNav.tsx +++ b/packages/api-explorer/src/components/SideNav/SideNav.tsx @@ -49,7 +49,7 @@ import { useSelector } from 'react-redux' import type { SpecAction } from '../../reducers' import { useWindowSize } from '../../utils' import { HEADER_REM } from '../Header' -import { selectSearchCriteria, useActions } from '../../state' +import { selectSearchCriteria, useSettingActions } from '../../state' import { SideNavMethodTags } from './SideNavMethodTags' import { SideNavTypeTags } from './SideNavTypeTags' import { useDebounce, countMethods, countTypes } from './searchUtils' @@ -100,7 +100,7 @@ export const SideNav: FC = ({ headless = false, spec }) => { } const tabs = useTabs({ defaultIndex, onChange: onTabChange }) const searchCriteria = useSelector(selectSearchCriteria) - const { setSearchPatternAction } = useActions() + const { setSearchPatternAction } = useSettingActions() const [pattern, setSearchPattern] = useState('') const debouncedPattern = useDebounce(pattern, 250) diff --git a/packages/api-explorer/src/state/index.ts b/packages/api-explorer/src/state/index.ts index 584e4bcfd..dcb854d53 100644 --- a/packages/api-explorer/src/state/index.ts +++ b/packages/api-explorer/src/state/index.ts @@ -25,3 +25,4 @@ */ export * from './store' export * from './settings' +export * from './lodes' diff --git a/packages/api-explorer/src/context/index.ts b/packages/api-explorer/src/state/lodes/index.ts similarity index 94% rename from packages/api-explorer/src/context/index.ts rename to packages/api-explorer/src/state/lodes/index.ts index 66b0f791d..a06152c6f 100644 --- a/packages/api-explorer/src/context/index.ts +++ b/packages/api-explorer/src/state/lodes/index.ts @@ -23,4 +23,5 @@ SOFTWARE. */ -export { LodeContext, defaultLodeContextValue } from './lode' +export * from './selectors' +export * from './slice' diff --git a/packages/api-explorer/src/state/lodes/sagas.ts b/packages/api-explorer/src/state/lodes/sagas.ts new file mode 100644 index 000000000..58863edc2 --- /dev/null +++ b/packages/api-explorer/src/state/lodes/sagas.ts @@ -0,0 +1,52 @@ +/* + + 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 { call, put, takeEvery } from 'typed-redux-saga' +import type { PayloadAction } from '@reduxjs/toolkit' + +import { getLoded } from '../../utils' +import type { InitPayload } from './slice' +import { lodeActions } from './slice' + +function* initSaga(action: PayloadAction) { + const { initLodeSuccessAction, initLodeFailureAction } = lodeActions + try { + console.log('in lode saga') + const lode = yield* call( + getLoded, + action.payload.examplesLodeUrl, + action.payload.declarationsLodeUrl + ) + yield* put(initLodeSuccessAction(lode)) + } catch (error: any) { + yield* put(initLodeFailureAction(error)) + } +} + +export function* saga() { + const { initLodeAction } = lodeActions + + yield* takeEvery(initLodeAction, initSaga) +} diff --git a/packages/api-explorer/src/context/lode/index.ts b/packages/api-explorer/src/state/lodes/selectors.ts similarity index 79% rename from packages/api-explorer/src/context/lode/index.ts rename to packages/api-explorer/src/state/lodes/selectors.ts index 596362f9a..e3ee00878 100644 --- a/packages/api-explorer/src/context/lode/index.ts +++ b/packages/api-explorer/src/state/lodes/selectors.ts @@ -23,4 +23,12 @@ SOFTWARE. */ -export { defaultLodeContextValue, LodeContext } from './LodeContext' +import type { RootState } from '../store' + +const selectLodeState = (state: RootState) => state.lode + +export const selectExamplesLode = (state: RootState) => + selectLodeState(state).examples + +export const selectDeclarationsLode = (state: RootState) => + selectLodeState(state).declarations diff --git a/packages/api-explorer/src/test-utils/render_with_lode.tsx b/packages/api-explorer/src/state/lodes/slice.ts similarity index 50% rename from packages/api-explorer/src/test-utils/render_with_lode.tsx rename to packages/api-explorer/src/state/lodes/slice.ts index 440364352..8acd6c9d0 100644 --- a/packages/api-explorer/src/test-utils/render_with_lode.tsx +++ b/packages/api-explorer/src/state/lodes/slice.ts @@ -23,47 +23,47 @@ SOFTWARE. */ - -import type { ReactElement } from 'react' -import React from 'react' -import type { RenderOptions } from '@testing-library/react' -import type { Store } from 'redux' - -import { renderWithTheme } from '@looker/components-test-utils' +import { createSliceHooks } from '@looker/redux' import type { IDeclarationMine, IExampleMine } from '@looker/sdk-codegen' -import { LodeContext } from '../context' -import type { RootState } from '../state' -import { withReduxProvider } from './redux' +import type { PayloadAction } from '@reduxjs/toolkit' +import { createSlice } from '@reduxjs/toolkit' -const withLode = ( - consumer: ReactElement, - examples: IExampleMine, +import { saga } from './sagas' + +export interface LodeState { + examples?: IExampleMine declarations?: IDeclarationMine -) => { - return ( - - {consumer} - - ) + error?: Error } -export const renderWithLode = ( - component: ReactElement, - examples: IExampleMine, - declarations?: IDeclarationMine, - options?: Omit -) => { - return renderWithTheme(withLode(component, examples, declarations), options) +export const defaultLodeState: LodeState = { + examples: undefined, + declarations: undefined, } -export const renderWithReduxProviderAndLode = ( - component: ReactElement, - examples: IExampleMine, - declarations?: IDeclarationMine, - store?: Store, - options?: Omit -) => - renderWithTheme( - withReduxProvider(withLode(component, examples, declarations), store), - options - ) +export interface InitPayload { + examplesLodeUrl?: string + declarationsLodeUrl?: string +} + +interface InitSuccessAction extends LodeState {} + +export const lodeSlice = createSlice({ + name: 'lode', + initialState: defaultLodeState, + reducers: { + // eslint-disable-next-line @typescript-eslint/no-empty-function + initLodeAction(_state, _action: PayloadAction) {}, + initLodeSuccessAction(state, action: PayloadAction) { + state.examples = action.payload.examples + state.declarations = action.payload.declarations + }, + initLodeFailureAction(state, action: PayloadAction) { + state.error = action.payload + }, + }, +}) + +export const lodeActions = lodeSlice.actions +export const { useActions: useLodeActions, useStoreState: useLodeState } = + createSliceHooks(lodeSlice, saga) diff --git a/packages/api-explorer/src/state/settings/sagas.spec.ts b/packages/api-explorer/src/state/settings/sagas.spec.ts index 75c1d413a..ed6cc9d12 100644 --- a/packages/api-explorer/src/state/settings/sagas.spec.ts +++ b/packages/api-explorer/src/state/settings/sagas.spec.ts @@ -28,7 +28,7 @@ import { registerTestEnvAdaptor } from '../../test-utils' import { EnvAdaptorConstants, getEnvAdaptor } from '../../utils' import * as sagas from './sagas' -import { actions, defaultSettings, slice } from './slice' +import { settingActions, defaultSettings, settingSlice } from './slice' describe('Settings Sagas', () => { let sagaTester: ReduxSagaTester @@ -39,7 +39,7 @@ describe('Settings Sagas', () => { sagaTester = new ReduxSagaTester({ initialState: { settings: { sdkLanguage: 'Go' } }, reducers: { - settings: slice.reducer, + settings: settingSlice.reducer, }, }) localStorage.clear() @@ -47,7 +47,7 @@ describe('Settings Sagas', () => { }) describe('setSdkLanguageSaga', () => { - const setSdkLanguageAction = actions.setSdkLanguageAction + const setSdkLanguageAction = settingActions.setSdkLanguageAction test('persists value sdkLanguage in localstorage', async () => { sagaTester.dispatch(setSdkLanguageAction({ sdkLanguage: 'Kotlin' })) @@ -67,16 +67,20 @@ describe('Settings Sagas', () => { }) describe('initSaga', () => { - const { initAction, initSuccessAction, initFailureAction } = actions + const { + initSettingsAction, + initSettingsSuccessAction, + initSettingsFailureAction, + } = settingActions test('sends initSuccess action with defaults on success if no persisted settings are found', async () => { - sagaTester.dispatch(initAction()) - await sagaTester.waitFor('settings/initSuccessAction') + sagaTester.dispatch(initSettingsAction()) + await sagaTester.waitFor('settings/initSettingsSuccessAction') const calledActions = sagaTester.getCalledActions() expect(calledActions).toHaveLength(2) - expect(calledActions[0]).toEqual(initAction()) + expect(calledActions[0]).toEqual(initSettingsAction()) expect(calledActions[1]).toEqual( - initSuccessAction({ + initSettingsSuccessAction({ ...defaultSettings, }) ) @@ -87,13 +91,13 @@ describe('Settings Sagas', () => { .spyOn(getEnvAdaptor(), 'localStorageGetItem') .mockResolvedValueOnce(JSON.stringify({ sdkLanguage: 'Go' })) - sagaTester.dispatch(initAction()) - await sagaTester.waitFor('settings/initSuccessAction') + sagaTester.dispatch(initSettingsAction()) + await sagaTester.waitFor('settings/initSettingsSuccessAction') const calledActions = sagaTester.getCalledActions() expect(calledActions).toHaveLength(2) - expect(calledActions[0]).toEqual(initAction()) + expect(calledActions[0]).toEqual(initSettingsAction()) expect(calledActions[1]).toEqual( - initSuccessAction({ + initSettingsSuccessAction({ ...defaultSettings, sdkLanguage: 'Go', }) @@ -106,12 +110,12 @@ describe('Settings Sagas', () => { .spyOn(getEnvAdaptor(), 'localStorageGetItem') .mockRejectedValueOnce(error) - sagaTester.dispatch(initAction()) - await sagaTester.waitFor('settings/initFailureAction') + sagaTester.dispatch(initSettingsAction()) + await sagaTester.waitFor('settings/initSettingsFailureAction') const calledActions = sagaTester.getCalledActions() expect(calledActions).toHaveLength(2) - expect(calledActions[0]).toEqual(initAction()) - expect(calledActions[1]).toEqual(initFailureAction(error)) + expect(calledActions[0]).toEqual(initSettingsAction()) + expect(calledActions[1]).toEqual(initSettingsFailureAction(error)) }) }) }) diff --git a/packages/api-explorer/src/state/settings/sagas.ts b/packages/api-explorer/src/state/settings/sagas.ts index bcf470320..9777f4a3d 100644 --- a/packages/api-explorer/src/state/settings/sagas.ts +++ b/packages/api-explorer/src/state/settings/sagas.ts @@ -27,7 +27,7 @@ import { takeEvery, call, put, select } from 'typed-redux-saga' import { EnvAdaptorConstants, getEnvAdaptor } from '../../utils' import type { RootState } from '../store' -import { actions, defaultSettings } from './slice' +import { settingActions, defaultSettings } from './slice' /** * Serializes state to local storage @@ -62,18 +62,19 @@ function* deserializeLocalStorage() { * Initializes the store with default settings and existing persisted settings */ function* initSaga() { - const { initSuccessAction, initFailureAction } = actions + const { initSettingsSuccessAction, initSettingsFailureAction } = + settingActions try { const settings = yield* call(deserializeLocalStorage) - yield* put(initSuccessAction(settings)) + yield* put(initSettingsSuccessAction(settings)) } catch (error: any) { - yield* put(initFailureAction(error)) + yield* put(initSettingsFailureAction(error)) } } export function* saga() { - const { initAction, setSdkLanguageAction } = actions + const { initSettingsAction, setSdkLanguageAction } = settingActions - yield* takeEvery(initAction, initSaga) + yield* takeEvery(initSettingsAction, initSaga) yield* takeEvery(setSdkLanguageAction, serializeToLocalStorageSaga) } diff --git a/packages/api-explorer/src/state/settings/selectors.ts b/packages/api-explorer/src/state/settings/selectors.ts index 096ca1cd5..7ba09d3d7 100644 --- a/packages/api-explorer/src/state/settings/selectors.ts +++ b/packages/api-explorer/src/state/settings/selectors.ts @@ -25,16 +25,16 @@ */ import type { RootState } from '../store' -const getSettingsState = (state: RootState) => state.settings +const selectSettingsState = (state: RootState) => state.settings export const selectSdkLanguage = (state: RootState) => - getSettingsState(state).sdkLanguage + selectSettingsState(state).sdkLanguage export const selectSearchPattern = (state: RootState) => - getSettingsState(state).searchPattern + selectSettingsState(state).searchPattern export const selectSearchCriteria = (state: RootState) => - getSettingsState(state).searchCriteria + selectSettingsState(state).searchCriteria export const isInitialized = (state: RootState) => - getSettingsState(state).initialized + selectSettingsState(state).initialized diff --git a/packages/api-explorer/src/state/settings/slice.ts b/packages/api-explorer/src/state/settings/slice.ts index 61a095444..cee912f50 100644 --- a/packages/api-explorer/src/state/settings/slice.ts +++ b/packages/api-explorer/src/state/settings/slice.ts @@ -58,17 +58,20 @@ type SetSdkLanguageAction = Pick export type InitSuccessPayload = UserDefinedSettings -export const slice = createSlice({ +export const settingSlice = createSlice({ name: 'settings', initialState: defaultSettingsState, reducers: { // eslint-disable-next-line @typescript-eslint/no-empty-function - initAction() {}, - initSuccessAction(state, action: PayloadAction) { + initSettingsAction() {}, + initSettingsSuccessAction( + state, + action: PayloadAction + ) { state.sdkLanguage = action.payload.sdkLanguage state.initialized = true }, - initFailureAction(state, action: PayloadAction) { + initSettingsFailureAction(state, action: PayloadAction) { state.error = action.payload state.initialized = false }, @@ -84,6 +87,8 @@ export const slice = createSlice({ }, }) -export const actions = slice.actions -export const { useActions, useStoreState: useSettingsStoreState } = - createSliceHooks(slice, saga) +export const settingActions = settingSlice.actions +export const { + useActions: useSettingActions, + useStoreState: useSettingStoreState, +} = createSliceHooks(settingSlice, saga) diff --git a/packages/api-explorer/src/state/store.ts b/packages/api-explorer/src/state/store.ts index f930bebef..c8013fa89 100644 --- a/packages/api-explorer/src/state/store.ts +++ b/packages/api-explorer/src/state/store.ts @@ -26,17 +26,22 @@ import { createStore } from '@looker/redux' import type { SettingState } from './settings' -import { defaultSettingsState, slice } from './settings' +import { defaultSettingsState, settingSlice } from './settings' +import type { LodeState } from './lodes' +import { lodeSlice, defaultLodeState } from './lodes' export const store = createStore({ preloadedState: { settings: defaultSettingsState, + lode: defaultLodeState, }, reducer: { - settings: slice.reducer, + settings: settingSlice.reducer, + lode: lodeSlice.reducer, }, }) export interface RootState { settings: SettingState + lode: LodeState } diff --git a/packages/api-explorer/src/test-utils/index.ts b/packages/api-explorer/src/test-utils/index.ts index e487dbfac..bc6038b12 100644 --- a/packages/api-explorer/src/test-utils/index.ts +++ b/packages/api-explorer/src/test-utils/index.ts @@ -23,10 +23,7 @@ SOFTWARE. */ -export { - renderWithLode, - renderWithReduxProviderAndLode, -} from './render_with_lode' +export * from './lode' export * from './router' export * from './redux' export { registerTestEnvAdaptor } from './envAdaptor' diff --git a/packages/api-explorer/src/context/lode/LodeContext.ts b/packages/api-explorer/src/test-utils/lode.tsx similarity index 68% rename from packages/api-explorer/src/context/lode/LodeContext.ts rename to packages/api-explorer/src/test-utils/lode.tsx index e21429469..7956db304 100644 --- a/packages/api-explorer/src/context/lode/LodeContext.ts +++ b/packages/api-explorer/src/test-utils/lode.tsx @@ -23,18 +23,19 @@ SOFTWARE. */ -import { createContext } from 'react' import type { IDeclarationMine, IExampleMine } from '@looker/sdk-codegen' - -interface LodeContextProps { - examples: IExampleMine - declarations?: IDeclarationMine -} - -export const defaultLodeContextValue: LodeContextProps = { - examples: { commitHash: '', remoteOrigin: '', nuggets: {}, summaries: {} }, +import type { ReactElement } from 'react' +import type { RenderOptions } from '@testing-library/react' +import { renderWithTheme } from '@looker/components-test-utils' + +import { createTestStore, withReduxProvider } from './redux' + +export const renderWithLode = ( + consumers: ReactElement, + examples: IExampleMine, + declarations?: IDeclarationMine, + options?: Omit +) => { + const store = createTestStore({ lode: { examples, declarations } }) + return renderWithTheme(withReduxProvider(consumers, store), options) } - -export const LodeContext = createContext( - defaultLodeContextValue -) diff --git a/packages/api-explorer/src/test-utils/redux.tsx b/packages/api-explorer/src/test-utils/redux.tsx index 6b8eeac87..681b5ccf0 100644 --- a/packages/api-explorer/src/test-utils/redux.tsx +++ b/packages/api-explorer/src/test-utils/redux.tsx @@ -31,9 +31,14 @@ import { renderWithTheme } from '@looker/components-test-utils' import type { RenderOptions } from '@testing-library/react' import { createStore } from '@looker/redux' -import type { RootState, SettingState } from '../state' -import { defaultSettingsState, store as defaultStore } from '../state' -import { slice as settingsSlice } from '../state/settings' +import type { LodeState, RootState, SettingState } from '../state' +import { + settingSlice, + defaultLodeState, + defaultSettingsState, + store as defaultStore, + lodeSlice, +} from '../state' import { registerEnvAdaptor, StandaloneEnvAdaptor } from '../utils' import { renderWithRouter } from './router' @@ -61,6 +66,7 @@ export const renderWithRouterAndReduxProvider = ( const preloadedState: RootState = { settings: defaultSettingsState, + lode: defaultLodeState, } type DeepPartial = { @@ -74,6 +80,10 @@ export const createTestStore = (overrides?: DeepPartial) => ...preloadedState.settings, ...overrides?.settings, } as SettingState, + lode: { + ...defaultLodeState, + ...overrides?.lode, + } as LodeState, }, - reducer: { settings: settingsSlice.reducer }, + reducer: { settings: settingSlice.reducer, lode: lodeSlice.reducer }, }) diff --git a/packages/api-explorer/src/utils/lodeUtils.ts b/packages/api-explorer/src/utils/lodeUtils.ts index 3e3ac90e3..4f8e0f703 100644 --- a/packages/api-explorer/src/utils/lodeUtils.ts +++ b/packages/api-explorer/src/utils/lodeUtils.ts @@ -38,17 +38,17 @@ const fetchLode = async (lodeUrl: string) => { } interface FullLode { - examples: IExampleMine + examples?: IExampleMine declarations?: IDeclarationMine } export const getLoded = async ( - examplesLodeUrl: string, + examplesLodeUrl?: string, declarationsLodeUrl?: string ): Promise => { // First try to load from the apix-files server let examples = await fetchLode(`${apixFilesHost}/examplesIndex.json`) - if (!examples) { + if (!examples && examplesLodeUrl) { examples = await fetchLode(examplesLodeUrl) } @@ -57,9 +57,7 @@ export const getLoded = async ( declarations = await fetchLode(declarationsLodeUrl) } - const lode: FullLode = { - examples: { commitHash: '', nuggets: {}, remoteOrigin: '', summaries: {} }, - } + const lode: FullLode = { examples: undefined, declarations: undefined } if (examples) { lode.examples = JSON.parse(examples) } From bb215dea79a889585560208bcdb3ddfb3129e360 Mon Sep 17 00:00:00 2001 From: Joseph Axisa Date: Fri, 29 Oct 2021 11:04:35 +0000 Subject: [PATCH 2/3] tests, utils and naming improvements --- packages/api-explorer/src/ApiExplorer.tsx | 8 +- .../SdkLanguageSelector.spec.tsx | 4 +- .../src/state/lodes/sagas.spec.ts | 92 +++++++++++++++++++ .../api-explorer/src/state/lodes/sagas.ts | 11 +-- .../src/state/lodes/selectors.spec.ts | 42 +++++++++ .../api-explorer/src/state/lodes/selectors.ts | 2 +- .../api-explorer/src/state/lodes/slice.ts | 22 ++--- .../src/state/settings/sagas.spec.ts | 8 +- .../src/state/settings/selectors.spec.ts | 6 +- .../api-explorer/src/state/settings/slice.ts | 6 +- packages/api-explorer/src/state/store.ts | 14 +-- .../src/test-data/declarations.ts | 43 +++++++++ packages/api-explorer/src/test-data/index.ts | 1 + packages/api-explorer/src/test-utils/index.ts | 2 +- .../src/test-utils/{lode.tsx => lodes.tsx} | 2 +- .../api-explorer/src/test-utils/redux.tsx | 22 ++--- 16 files changed, 227 insertions(+), 58 deletions(-) create mode 100644 packages/api-explorer/src/state/lodes/sagas.spec.ts create mode 100644 packages/api-explorer/src/state/lodes/selectors.spec.ts create mode 100644 packages/api-explorer/src/test-data/declarations.ts rename packages/api-explorer/src/test-utils/{lode.tsx => lodes.tsx} (95%) diff --git a/packages/api-explorer/src/ApiExplorer.tsx b/packages/api-explorer/src/ApiExplorer.tsx index 58f81d775..e1450c33b 100644 --- a/packages/api-explorer/src/ApiExplorer.tsx +++ b/packages/api-explorer/src/ApiExplorer.tsx @@ -84,7 +84,7 @@ const ApiExplorer: FC = ({ }) => { const { initialized } = useSettingStoreState() useLodeState() - const { initLodeAction } = useLodeActions() + const { initLodesAction } = useLodeActions() const { initSettingsAction } = useSettingActions() const location = useLocation() const oauthReturn = location.pathname === `/${oAuthPath}` @@ -107,6 +107,7 @@ const ApiExplorer: FC = ({ useEffect(() => { registerEnvAdaptor(envAdaptor) initSettingsAction() + initLodesAction({ examplesLodeUrl, declarationsLodeUrl }) return () => unregisterEnvAdaptor() }, []) @@ -142,11 +143,6 @@ const ApiExplorer: FC = ({ } }, [spec, location]) - useEffect(() => { - console.log(examplesLodeUrl) - initLodeAction({ examplesLodeUrl, declarationsLodeUrl }) - }, [examplesLodeUrl, declarationsLodeUrl]) - const themeOverrides = envAdaptor.themeOverrides() return ( diff --git a/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.spec.tsx b/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.spec.tsx index 2ca860a9b..1d494ea88 100644 --- a/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.spec.tsx +++ b/packages/api-explorer/src/components/SelectorContainer/SdkLanguageSelector.spec.tsx @@ -29,7 +29,7 @@ import userEvent from '@testing-library/user-event' import { codeGenerators } from '@looker/sdk-codegen' import * as reactRedux from 'react-redux' -import { defaultSettingsState, settingSlice } from '../../state' +import { defaultSettingsState, settingsSlice } from '../../state' import { registerTestEnvAdaptor, renderWithReduxProvider, @@ -77,7 +77,7 @@ describe('SdkLanguageSelector', () => { await userEvent.click(screen.getByRole('option', { name: 'TypeScript' })) await waitFor(async () => { expect(mockDispatch).toHaveBeenLastCalledWith( - settingSlice.actions.setSdkLanguageAction({ + settingsSlice.actions.setSdkLanguageAction({ sdkLanguage: 'TypeScript', }) ) diff --git a/packages/api-explorer/src/state/lodes/sagas.spec.ts b/packages/api-explorer/src/state/lodes/sagas.spec.ts new file mode 100644 index 000000000..071586686 --- /dev/null +++ b/packages/api-explorer/src/state/lodes/sagas.spec.ts @@ -0,0 +1,92 @@ +/* + + 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 ReduxSagaTester from 'redux-saga-tester' +import { examples, declarations } from '../../test-data' +import * as lodeUtils from '../../utils/lodeUtils' +import * as sagas from './sagas' +import { lodeActions, lodesSlice } from './slice' + +describe('Lode sagas', () => { + let sagaTester: ReduxSagaTester + + beforeEach(() => { + jest.resetAllMocks() + sagaTester = new ReduxSagaTester({ + initialState: { lodes: { examples, declarations } }, + reducers: { + lodes: lodesSlice.reducer, + }, + }) + sagaTester.start(sagas.saga) + }) + + describe('initSaga', () => { + const { initLodesAction, initLodesSuccessAction, initLodesFailureAction } = + lodeActions + const examplesLodeUrl = 'https://foo.com/examples.json' + const declarationsLodeUrl = 'https://foo.com/declarations.json' + + test('sends initLodesSuccessAction with examples and declarations on success', async () => { + jest + .spyOn(lodeUtils, 'getLoded') + .mockResolvedValueOnce({ examples, declarations }) + + sagaTester.dispatch( + initLodesAction({ examplesLodeUrl, declarationsLodeUrl }) + ) + + await sagaTester.waitFor('lodes/initLodesSuccessAction') + const calledActions = sagaTester.getCalledActions() + expect(calledActions).toHaveLength(2) + expect(calledActions[0]).toEqual( + initLodesAction({ examplesLodeUrl, declarationsLodeUrl }) + ) + expect(calledActions[1]).toEqual( + initLodesSuccessAction({ + examples, + declarations, + }) + ) + }) + + test('sends initLodesFailureAction on error', async () => { + const error = new Error('boom') + jest.spyOn(lodeUtils, 'getLoded').mockRejectedValueOnce(error) + + sagaTester.dispatch( + initLodesAction({ examplesLodeUrl, declarationsLodeUrl }) + ) + + await sagaTester.waitFor('lodes/initLodesFailureAction') + const calledActions = sagaTester.getCalledActions() + expect(calledActions).toHaveLength(2) + expect(calledActions[0]).toEqual( + initLodesAction({ examplesLodeUrl, declarationsLodeUrl }) + ) + expect(calledActions[1]).toEqual(initLodesFailureAction(error)) + }) + }) +}) diff --git a/packages/api-explorer/src/state/lodes/sagas.ts b/packages/api-explorer/src/state/lodes/sagas.ts index 58863edc2..1dc37a908 100644 --- a/packages/api-explorer/src/state/lodes/sagas.ts +++ b/packages/api-explorer/src/state/lodes/sagas.ts @@ -31,22 +31,21 @@ import type { InitPayload } from './slice' import { lodeActions } from './slice' function* initSaga(action: PayloadAction) { - const { initLodeSuccessAction, initLodeFailureAction } = lodeActions + const { initLodesSuccessAction, initLodesFailureAction } = lodeActions try { - console.log('in lode saga') const lode = yield* call( getLoded, action.payload.examplesLodeUrl, action.payload.declarationsLodeUrl ) - yield* put(initLodeSuccessAction(lode)) + yield* put(initLodesSuccessAction(lode)) } catch (error: any) { - yield* put(initLodeFailureAction(error)) + yield* put(initLodesFailureAction(error)) } } export function* saga() { - const { initLodeAction } = lodeActions + const { initLodesAction } = lodeActions - yield* takeEvery(initLodeAction, initSaga) + yield* takeEvery(initLodesAction, initSaga) } diff --git a/packages/api-explorer/src/state/lodes/selectors.spec.ts b/packages/api-explorer/src/state/lodes/selectors.spec.ts new file mode 100644 index 000000000..b69d1f23e --- /dev/null +++ b/packages/api-explorer/src/state/lodes/selectors.spec.ts @@ -0,0 +1,42 @@ +/* + + 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 { createTestStore } from '../../test-utils' +import { declarations, examples } from '../../test-data' +import { selectDeclarationsLode, selectExamplesLode } from './selectors' + +const testStore = createTestStore({ lodes: { examples, declarations } }) + +describe('Lode selectors', () => { + const state = testStore.getState() + + test('selectExamplesLode selects', () => { + expect(selectExamplesLode(state)).toEqual(examples) + }) + + test('selectDeclarationsLode selects', () => { + expect(selectDeclarationsLode(state)).toEqual(declarations) + }) +}) diff --git a/packages/api-explorer/src/state/lodes/selectors.ts b/packages/api-explorer/src/state/lodes/selectors.ts index e3ee00878..5784b182f 100644 --- a/packages/api-explorer/src/state/lodes/selectors.ts +++ b/packages/api-explorer/src/state/lodes/selectors.ts @@ -25,7 +25,7 @@ */ import type { RootState } from '../store' -const selectLodeState = (state: RootState) => state.lode +const selectLodeState = (state: RootState) => state.lodes export const selectExamplesLode = (state: RootState) => selectLodeState(state).examples diff --git a/packages/api-explorer/src/state/lodes/slice.ts b/packages/api-explorer/src/state/lodes/slice.ts index 8acd6c9d0..03481ffe6 100644 --- a/packages/api-explorer/src/state/lodes/slice.ts +++ b/packages/api-explorer/src/state/lodes/slice.ts @@ -30,13 +30,13 @@ import { createSlice } from '@reduxjs/toolkit' import { saga } from './sagas' -export interface LodeState { +export interface LodesState { examples?: IExampleMine declarations?: IDeclarationMine error?: Error } -export const defaultLodeState: LodeState = { +export const defaultLodesState: LodesState = { examples: undefined, declarations: undefined, } @@ -46,24 +46,24 @@ export interface InitPayload { declarationsLodeUrl?: string } -interface InitSuccessAction extends LodeState {} +type InitSuccessAction = LodesState -export const lodeSlice = createSlice({ - name: 'lode', - initialState: defaultLodeState, +export const lodesSlice = createSlice({ + name: 'lodes', + initialState: defaultLodesState, reducers: { // eslint-disable-next-line @typescript-eslint/no-empty-function - initLodeAction(_state, _action: PayloadAction) {}, - initLodeSuccessAction(state, action: PayloadAction) { + initLodesAction(_state, _action: PayloadAction) {}, + initLodesSuccessAction(state, action: PayloadAction) { state.examples = action.payload.examples state.declarations = action.payload.declarations }, - initLodeFailureAction(state, action: PayloadAction) { + initLodesFailureAction(state, action: PayloadAction) { state.error = action.payload }, }, }) -export const lodeActions = lodeSlice.actions +export const lodeActions = lodesSlice.actions export const { useActions: useLodeActions, useStoreState: useLodeState } = - createSliceHooks(lodeSlice, saga) + createSliceHooks(lodesSlice, saga) diff --git a/packages/api-explorer/src/state/settings/sagas.spec.ts b/packages/api-explorer/src/state/settings/sagas.spec.ts index ed6cc9d12..10b6df3f2 100644 --- a/packages/api-explorer/src/state/settings/sagas.spec.ts +++ b/packages/api-explorer/src/state/settings/sagas.spec.ts @@ -28,7 +28,7 @@ import { registerTestEnvAdaptor } from '../../test-utils' import { EnvAdaptorConstants, getEnvAdaptor } from '../../utils' import * as sagas from './sagas' -import { settingActions, defaultSettings, settingSlice } from './slice' +import { settingActions, defaultSettings, settingsSlice } from './slice' describe('Settings Sagas', () => { let sagaTester: ReduxSagaTester @@ -39,7 +39,7 @@ describe('Settings Sagas', () => { sagaTester = new ReduxSagaTester({ initialState: { settings: { sdkLanguage: 'Go' } }, reducers: { - settings: settingSlice.reducer, + settings: settingsSlice.reducer, }, }) localStorage.clear() @@ -86,7 +86,7 @@ describe('Settings Sagas', () => { ) }) - test('sends initSuccess action with persisted language on success', async () => { + test('sends initSettingsSuccessAction with persisted language on success', async () => { jest .spyOn(getEnvAdaptor(), 'localStorageGetItem') .mockResolvedValueOnce(JSON.stringify({ sdkLanguage: 'Go' })) @@ -104,7 +104,7 @@ describe('Settings Sagas', () => { ) }) - test('sends initFailure action on error', async () => { + test('sends initSettingsFailureAction on error', async () => { const error = new Error('boom') jest .spyOn(getEnvAdaptor(), 'localStorageGetItem') diff --git a/packages/api-explorer/src/state/settings/selectors.spec.ts b/packages/api-explorer/src/state/settings/selectors.spec.ts index fd7c6f5bd..38c81a636 100644 --- a/packages/api-explorer/src/state/settings/selectors.spec.ts +++ b/packages/api-explorer/src/state/settings/selectors.spec.ts @@ -23,13 +23,9 @@ SOFTWARE. */ -import { createTestStore } from '../../test-utils' +import { createTestStore, preloadedState } from '../../test-utils' import { selectSdkLanguage, isInitialized } from './selectors' -const preloadedState = { - settings: { initialized: false, sdkLanguage: 'Python' }, -} - const testStore = createTestStore() describe('Settings selectors', () => { diff --git a/packages/api-explorer/src/state/settings/slice.ts b/packages/api-explorer/src/state/settings/slice.ts index cee912f50..c6373d9d0 100644 --- a/packages/api-explorer/src/state/settings/slice.ts +++ b/packages/api-explorer/src/state/settings/slice.ts @@ -58,7 +58,7 @@ type SetSdkLanguageAction = Pick export type InitSuccessPayload = UserDefinedSettings -export const settingSlice = createSlice({ +export const settingsSlice = createSlice({ name: 'settings', initialState: defaultSettingsState, reducers: { @@ -87,8 +87,8 @@ export const settingSlice = createSlice({ }, }) -export const settingActions = settingSlice.actions +export const settingActions = settingsSlice.actions export const { useActions: useSettingActions, useStoreState: useSettingStoreState, -} = createSliceHooks(settingSlice, saga) +} = createSliceHooks(settingsSlice, saga) diff --git a/packages/api-explorer/src/state/store.ts b/packages/api-explorer/src/state/store.ts index c8013fa89..ed0b437a1 100644 --- a/packages/api-explorer/src/state/store.ts +++ b/packages/api-explorer/src/state/store.ts @@ -26,22 +26,22 @@ import { createStore } from '@looker/redux' import type { SettingState } from './settings' -import { defaultSettingsState, settingSlice } from './settings' -import type { LodeState } from './lodes' -import { lodeSlice, defaultLodeState } from './lodes' +import { defaultSettingsState, settingsSlice } from './settings' +import type { LodesState } from './lodes' +import { lodesSlice, defaultLodesState } from './lodes' export const store = createStore({ preloadedState: { settings: defaultSettingsState, - lode: defaultLodeState, + lodes: defaultLodesState, }, reducer: { - settings: settingSlice.reducer, - lode: lodeSlice.reducer, + settings: settingsSlice.reducer, + lodes: lodesSlice.reducer, }, }) export interface RootState { settings: SettingState - lode: LodeState + lodes: LodesState } diff --git a/packages/api-explorer/src/test-data/declarations.ts b/packages/api-explorer/src/test-data/declarations.ts new file mode 100644 index 000000000..55c4511c3 --- /dev/null +++ b/packages/api-explorer/src/test-data/declarations.ts @@ -0,0 +1,43 @@ +/* + + 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 type { IDeclarationMine } from '@looker/sdk-codegen' + +export const declarations: IDeclarationMine = { + commitHash: '1e9348b797c2f3760d03c1f94c60f18e534e8298', + remoteOrigin: 'https://github.com/looker-open-source/sdk-codegen', + types: { + FullLode: { + line: 40, + sourceFile: 'packages/api-explorer/src/utils/lodeUtils.ts', + }, + }, + methods: { + getLoded: { + line: 45, + sourceFile: 'packages/api-explorer/src/utils/lodeUtils.ts', + }, + }, +} diff --git a/packages/api-explorer/src/test-data/index.ts b/packages/api-explorer/src/test-data/index.ts index bb4c8c744..0fdf9e13a 100644 --- a/packages/api-explorer/src/test-data/index.ts +++ b/packages/api-explorer/src/test-data/index.ts @@ -32,3 +32,4 @@ export { getLoadedSpecState, } from './specs' export { examples } from './examples' +export * from './declarations' diff --git a/packages/api-explorer/src/test-utils/index.ts b/packages/api-explorer/src/test-utils/index.ts index bc6038b12..870a334ed 100644 --- a/packages/api-explorer/src/test-utils/index.ts +++ b/packages/api-explorer/src/test-utils/index.ts @@ -23,7 +23,7 @@ SOFTWARE. */ -export * from './lode' +export * from './lodes' export * from './router' export * from './redux' export { registerTestEnvAdaptor } from './envAdaptor' diff --git a/packages/api-explorer/src/test-utils/lode.tsx b/packages/api-explorer/src/test-utils/lodes.tsx similarity index 95% rename from packages/api-explorer/src/test-utils/lode.tsx rename to packages/api-explorer/src/test-utils/lodes.tsx index 7956db304..9568a12fd 100644 --- a/packages/api-explorer/src/test-utils/lode.tsx +++ b/packages/api-explorer/src/test-utils/lodes.tsx @@ -36,6 +36,6 @@ export const renderWithLode = ( declarations?: IDeclarationMine, options?: Omit ) => { - const store = createTestStore({ lode: { examples, declarations } }) + const store = createTestStore({ lodes: { examples, declarations } }) return renderWithTheme(withReduxProvider(consumers, store), options) } diff --git a/packages/api-explorer/src/test-utils/redux.tsx b/packages/api-explorer/src/test-utils/redux.tsx index 681b5ccf0..e85729b66 100644 --- a/packages/api-explorer/src/test-utils/redux.tsx +++ b/packages/api-explorer/src/test-utils/redux.tsx @@ -31,13 +31,13 @@ import { renderWithTheme } from '@looker/components-test-utils' import type { RenderOptions } from '@testing-library/react' import { createStore } from '@looker/redux' -import type { LodeState, RootState, SettingState } from '../state' +import type { LodesState, RootState, SettingState } from '../state' import { - settingSlice, - defaultLodeState, + settingsSlice, + defaultLodesState, defaultSettingsState, store as defaultStore, - lodeSlice, + lodesSlice, } from '../state' import { registerEnvAdaptor, StandaloneEnvAdaptor } from '../utils' import { renderWithRouter } from './router' @@ -64,9 +64,9 @@ export const renderWithRouterAndReduxProvider = ( ) => renderWithRouter(withReduxProvider(consumers, store), initialEntries, options) -const preloadedState: RootState = { +export const preloadedState: RootState = { settings: defaultSettingsState, - lode: defaultLodeState, + lodes: defaultLodesState, } type DeepPartial = { @@ -80,10 +80,10 @@ export const createTestStore = (overrides?: DeepPartial) => ...preloadedState.settings, ...overrides?.settings, } as SettingState, - lode: { - ...defaultLodeState, - ...overrides?.lode, - } as LodeState, + lodes: { + ...defaultLodesState, + ...overrides?.lodes, + } as LodesState, }, - reducer: { settings: settingSlice.reducer, lode: lodeSlice.reducer }, + reducer: { settings: settingsSlice.reducer, lodes: lodesSlice.reducer }, }) From 6288014b4980a5aeaeeb66e38b7f1ee5ce277aab Mon Sep 17 00:00:00 2001 From: Joseph Axisa Date: Fri, 29 Oct 2021 12:36:05 +0000 Subject: [PATCH 3/3] naming convention --- packages/api-explorer/src/ApiExplorer.tsx | 4 ++-- packages/api-explorer/src/state/lodes/slice.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/api-explorer/src/ApiExplorer.tsx b/packages/api-explorer/src/ApiExplorer.tsx index e1450c33b..8f5e827a0 100644 --- a/packages/api-explorer/src/ApiExplorer.tsx +++ b/packages/api-explorer/src/ApiExplorer.tsx @@ -61,7 +61,7 @@ import { useSettingActions, useSettingStoreState, useLodeActions, - useLodeState, + useLodesStoreState, } from './state' export interface ApiExplorerProps { specs: SpecList @@ -83,7 +83,7 @@ const ApiExplorer: FC = ({ headless = false, }) => { const { initialized } = useSettingStoreState() - useLodeState() + useLodesStoreState() const { initLodesAction } = useLodeActions() const { initSettingsAction } = useSettingActions() const location = useLocation() diff --git a/packages/api-explorer/src/state/lodes/slice.ts b/packages/api-explorer/src/state/lodes/slice.ts index 03481ffe6..a5b43fae8 100644 --- a/packages/api-explorer/src/state/lodes/slice.ts +++ b/packages/api-explorer/src/state/lodes/slice.ts @@ -65,5 +65,5 @@ export const lodesSlice = createSlice({ }) export const lodeActions = lodesSlice.actions -export const { useActions: useLodeActions, useStoreState: useLodeState } = +export const { useActions: useLodeActions, useStoreState: useLodesStoreState } = createSliceHooks(lodesSlice, saga)