Provide a deprecation path for affected sidebar contexts.

Signed-off-by: Eric Peterson <ericpeterson@spotify.com>
This commit is contained in:
Eric Peterson
2022-05-20 17:28:14 +02:00
parent bff65e6958
commit a907d620fa
6 changed files with 128 additions and 40 deletions
+6
View File
@@ -902,6 +902,9 @@ export const sidebarConfig: {
mobileSidebarHeight: number;
};
// @public @deprecated
export const SidebarContext: React_2.Context<SidebarContextType>;
// @public
export const SidebarContextProvider: ({
children,
@@ -1005,6 +1008,9 @@ export type SidebarPageProps = {
children?: React_2.ReactNode;
};
// @public @deprecated
export const SidebarPinStateContext: React_2.Context<SidebarPinStateContextType>;
// @public
export const SidebarPinStateContextProvider: ({
children,
@@ -13,21 +13,45 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { ReactNode } from 'react';
import { renderInTestApp } from '@backstage/test-utils';
import { screen, waitFor } from '@testing-library/react';
import React, { ReactNode, useContext } from 'react';
import { renderWithEffects } from '@backstage/test-utils';
import { waitFor } from '@testing-library/react';
import { renderHook, act } from '@testing-library/react-hooks';
import { SidebarContextProvider, useSidebar } from './SidebarContext';
import {
LegacySidebarContext,
SidebarContextProvider,
useSidebar,
} from './SidebarContext';
describe('SidebarContext', () => {
describe('SidebarContextProvider', () => {
it('should render children', async () => {
await renderInTestApp(
const { findByText } = await renderWithEffects(
<SidebarContextProvider value={{ isOpen: false, setOpen: () => {} }}>
Child
</SidebarContextProvider>,
);
expect(await screen.findByText('Child')).toBeInTheDocument();
expect(await findByText('Child')).toBeInTheDocument();
});
it('should provide the legacy context as well, for now', async () => {
const LegacyContextSpy = () => {
const { isOpen } = useContext(LegacySidebarContext);
return <>{String(isOpen)}</>;
};
const { findByText } = await renderWithEffects(
<SidebarContextProvider
value={{
isOpen: true,
setOpen: () => {},
}}
>
<LegacyContextSpy />
</SidebarContextProvider>,
);
expect(await findByText('true')).toBeInTheDocument();
});
});
@@ -52,15 +76,16 @@ describe('SidebarContext', () => {
{children}
</SidebarContextProvider>
);
const { result } = renderHook(() => useSidebar(), { wrapper });
const { result, rerender } = renderHook(() => useSidebar(), { wrapper });
expect(result.current.isOpen).toBe(true);
act(() => {
result.current.setOpen(false);
rerender();
});
waitFor(() => {
await waitFor(() => {
expect(result.current.isOpen).toBe(false);
});
});
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import React, { ReactNode, useContext } from 'react';
import React, { createContext, ReactNode, useContext } from 'react';
import {
createVersionedContext,
createVersionedValueMap,
@@ -30,6 +30,21 @@ export type SidebarContextType = {
setOpen: (open: boolean) => void;
};
const defaultSidebarContext = {
isOpen: false,
setOpen: () => {},
};
/**
* Context whether the `Sidebar` is open
*
* @public @deprecated
* Use `<SidebarContextProvider>` + `useSidebar()` instead.
*/
export const LegacySidebarContext = createContext<SidebarContextType>(
defaultSidebarContext,
);
const VersionedSidebarContext = createVersionedContext<{
1: SidebarContextType;
}>('sidebar-context');
@@ -46,11 +61,13 @@ export const SidebarContextProvider = ({
children: ReactNode;
value: SidebarContextType;
}) => (
<VersionedSidebarContext.Provider
value={createVersionedValueMap({ 1: value })}
>
{children}
</VersionedSidebarContext.Provider>
<LegacySidebarContext.Provider value={value}>
<VersionedSidebarContext.Provider
value={createVersionedValueMap({ 1: value })}
>
{children}
</VersionedSidebarContext.Provider>
</LegacySidebarContext.Provider>
);
/**
@@ -63,10 +80,7 @@ export const useSidebar = (): SidebarContextType => {
// Invoked from outside a SidbarContextProvider, return a default value.
if (versionedSidebarContext === undefined) {
return {
isOpen: false,
setOpen: () => {},
};
return defaultSidebarContext;
}
const sidebarContext = versionedSidebarContext.atVersion(1);
@@ -13,19 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { ReactNode } from 'react';
import { renderInTestApp } from '@backstage/test-utils';
import { screen, waitFor } from '@testing-library/react';
import React, { ReactNode, useContext } from 'react';
import { renderWithEffects } from '@backstage/test-utils';
import { waitFor } from '@testing-library/react';
import { renderHook, act } from '@testing-library/react-hooks';
import {
LegacySidebarPinStateContext,
SidebarPinStateContextProvider,
useSidebarPinState,
} from './SidebarPinStateContext';
describe('SidebarContext', () => {
describe('SidebarContextProvider', () => {
describe('SidebarPinStateContext', () => {
describe('SidebarPinStateContextProvider', () => {
it('should render children', async () => {
await renderInTestApp(
const { findByText } = await renderWithEffects(
<SidebarPinStateContextProvider
value={{
isPinned: true,
@@ -36,11 +37,32 @@ describe('SidebarContext', () => {
Child
</SidebarPinStateContextProvider>,
);
expect(await screen.findByText('Child')).toBeInTheDocument();
expect(await findByText('Child')).toBeInTheDocument();
});
it('should provide the legacy context as well, for now', async () => {
const LegacyContextSpy = () => {
const { isMobile } = useContext(LegacySidebarPinStateContext);
return <>{String(isMobile)}</>;
};
const { findByText } = await renderWithEffects(
<SidebarPinStateContextProvider
value={{
isPinned: true,
isMobile: true,
toggleSidebarPinState: () => {},
}}
>
<LegacyContextSpy />
</SidebarPinStateContextProvider>,
);
expect(await findByText('true')).toBeInTheDocument();
});
});
describe('useSidebar', () => {
describe('useSidebarPinState', () => {
it('does not need to be invoked within provider', () => {
const { result } = renderHook(() => useSidebarPinState());
expect(result.current.isPinned).toBe(true);
@@ -63,15 +85,18 @@ describe('SidebarContext', () => {
{children}
</SidebarPinStateContextProvider>
);
const { result } = renderHook(() => useSidebarPinState(), { wrapper });
const { result, rerender } = renderHook(() => useSidebarPinState(), {
wrapper,
});
expect(result.current.isPinned).toBe(true);
act(() => {
result.current.toggleSidebarPinState();
rerender();
});
waitFor(() => {
await waitFor(() => {
expect(result.current.isPinned).toBe(false);
});
});
@@ -17,7 +17,7 @@ import {
createVersionedContext,
createVersionedValueMap,
} from '@backstage/version-bridge';
import React, { ReactNode, useContext } from 'react';
import React, { createContext, ReactNode, useContext } from 'react';
/**
* Type of `SidebarPinStateContext`
@@ -30,6 +30,21 @@ export type SidebarPinStateContextType = {
isMobile?: boolean;
};
const defaultSidebarPinStateContext = {
isPinned: true,
toggleSidebarPinState: () => {},
isMobile: false,
};
/**
* Contains the state on how the `Sidebar` is rendered
*
* @public @deprecated
* Use `<SidebarPinStateContextProvider>` + `useSidebarPinState()` instead.
*/
export const LegacySidebarPinStateContext =
createContext<SidebarPinStateContextType>(defaultSidebarPinStateContext);
const VersionedSidebarPinStateContext = createVersionedContext<{
1: SidebarPinStateContextType;
}>('sidebar-pin-state-context');
@@ -46,11 +61,13 @@ export const SidebarPinStateContextProvider = ({
children: ReactNode;
value: SidebarPinStateContextType;
}) => (
<VersionedSidebarPinStateContext.Provider
value={createVersionedValueMap({ 1: value })}
>
{children}
</VersionedSidebarPinStateContext.Provider>
<LegacySidebarPinStateContext.Provider value={value}>
<VersionedSidebarPinStateContext.Provider
value={createVersionedValueMap({ 1: value })}
>
{children}
</VersionedSidebarPinStateContext.Provider>
</LegacySidebarPinStateContext.Provider>
);
/**
@@ -63,11 +80,7 @@ export const useSidebarPinState = (): SidebarPinStateContextType => {
// Invoked from outside a SidebarPinStateContextProvider: default value.
if (versionedSidebarContext === undefined) {
return {
isPinned: true,
toggleSidebarPinState: () => {},
isMobile: false,
};
return defaultSidebarPinStateContext;
}
const sidebarContext = versionedSidebarContext.atVersion(1);
@@ -48,9 +48,14 @@ export { IntroCard, SidebarIntro } from './Intro';
export type { SidebarIntroClassKey } from './Intro';
export { SIDEBAR_INTRO_LOCAL_STORAGE, sidebarConfig } from './config';
export type { SidebarOptions, SubmenuOptions } from './config';
export { SidebarContextProvider, useSidebar } from './SidebarContext';
export {
LegacySidebarContext as SidebarContext,
SidebarContextProvider,
useSidebar,
} from './SidebarContext';
export type { SidebarContextType } from './SidebarContext';
export {
LegacySidebarPinStateContext as SidebarPinStateContext,
SidebarPinStateContextProvider,
useSidebarPinState,
} from './SidebarPinStateContext';