feature(plugins/home): Remove DoNotTrack functionality

Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com>
Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Renan Mendes Carvalho
2023-09-19 11:30:22 +02:00
committed by Camila Belo
parent 09a7f8f285
commit a84cac67ca
3 changed files with 11 additions and 162 deletions
-21
View File
@@ -14,14 +14,12 @@ import { CardSettings as CardSettings_2 } from '@backstage/plugin-home-react';
import { ComponentParts as ComponentParts_2 } from '@backstage/plugin-home-react';
import { ComponentRenderer as ComponentRenderer_2 } from '@backstage/plugin-home-react';
import { createCardExtension as createCardExtension_2 } from '@backstage/plugin-home-react';
import { Dispatch } from 'react';
import { JSX as JSX_2 } from 'react';
import { default as React_2 } from 'react';
import { ReactElement } from 'react';
import { ReactNode } from 'react';
import { RendererProps as RendererProps_2 } from '@backstage/plugin-home-react';
import { RouteRef } from '@backstage/core-plugin-api';
import { SetStateAction } from 'react';
// @public
export type Breakpoint = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
@@ -100,13 +98,6 @@ export type CustomHomepageGridProps = {
preventCollision?: boolean;
};
// @public
export const DoNotTrack: ({
children,
}: {
children?: ReactNode;
}) => JSX.Element;
// @public
export const getVisitName: (document: Document) => () => string;
@@ -204,9 +195,6 @@ export type ToolkitContentProps = {
tools: Tool[];
};
// @public
export const useVisitListener: () => VisitListenerContextValue;
// @public
export type Visit = {
id: string;
@@ -242,15 +230,6 @@ export const VisitListener: ({
visitName?: (({ pathname }: { pathname: string }) => string) | undefined;
}) => JSX.Element;
// @public (undocumented)
export const VisitListenerContext: React_2.Context<VisitListenerContextValue>;
// @public (undocumented)
export type VisitListenerContextValue = {
doNotTrack: boolean;
setDoNotTrack: Dispatch<SetStateAction<boolean>>;
};
// @public
export interface VisitsApi {
listUserVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>;
@@ -16,10 +16,8 @@
import React from 'react';
import { TestApiProvider, renderInTestApp } from '@backstage/test-utils';
import { Visit, visitsApiRef } from '../api';
import { DoNotTrack, VisitListener, useVisitListener } from './VisitListener';
import { VisitListener } from './VisitListener';
import { waitFor } from '@testing-library/react';
import { act, renderHook } from '@testing-library/react-hooks';
import { MemoryRouter } from 'react-router-dom';
const visits: Array<Visit> = [
{
@@ -139,65 +137,3 @@ describe('<VisitListener/>', () => {
);
});
});
describe('<DoNotTrack/>', () => {
afterEach(jest.resetAllMocks);
it("doesn't register a visit", async () => {
const requestAnimationFrameSpy = jest.spyOn(
window,
'requestAnimationFrame',
);
await renderInTestApp(
<TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}>
<VisitListener>
<DoNotTrack />
</VisitListener>
</TestApiProvider>,
);
await waitFor(() => expect(requestAnimationFrameSpy).toHaveBeenCalled());
expect(mockVisitsApi.saveVisit).not.toHaveBeenCalled();
});
it('renders its children', async () => {
const requestAnimationFrameSpy = jest.spyOn(
window,
'requestAnimationFrame',
);
const { getByTestId } = await renderInTestApp(
<TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}>
<VisitListener>
<DoNotTrack>
<div data-testid="child">child</div>
</DoNotTrack>
</VisitListener>
</TestApiProvider>,
);
await waitFor(() => expect(requestAnimationFrameSpy).toHaveBeenCalled());
expect(getByTestId('child')).toBeTruthy();
});
});
describe('useVisitListener()', () => {
it('returns the default context', () => {
const { result } = renderHook(() => useVisitListener());
expect(result.current.doNotTrack).toBeFalsy();
expect(result.current.setDoNotTrack).toBeInstanceOf(Function);
});
it('changes the doNotTrack flag', () => {
const { result } = renderHook(() => useVisitListener(), {
wrapper: ({ children }) => (
<MemoryRouter>
<TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}>
<VisitListener>{children}</VisitListener>
</TestApiProvider>
</MemoryRouter>
),
});
act(() => {
result.current.setDoNotTrack(true);
});
expect(result.current.doNotTrack).toBeTruthy();
});
});
+10 -76
View File
@@ -13,15 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, {
createContext,
useState,
useEffect,
useContext,
Dispatch,
SetStateAction,
ReactNode,
} from 'react';
import React, { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
@@ -29,22 +21,6 @@ import { visitsApiRef } from '../api';
import { useApi } from '@backstage/core-plugin-api';
import { stringifyEntityRef } from '@backstage/catalog-model';
/** @public */
export type VisitListenerContextValue = {
doNotTrack: boolean;
setDoNotTrack: Dispatch<SetStateAction<boolean>>;
};
const defaultVisitListenerContext: VisitListenerContextValue = {
doNotTrack: false,
setDoNotTrack: () => {},
};
/** @public */
export const VisitListenerContext = createContext<VisitListenerContextValue>(
defaultVisitListenerContext,
);
/**
* This function returns an implementation of toEntityRef which is responsible
* for receiving a pathname and maybe returning an entityRef compatible with the
@@ -97,66 +73,24 @@ export const VisitListener = ({
toEntityRef?: ({ pathname }: { pathname: string }) => string | undefined;
visitName?: ({ pathname }: { pathname: string }) => string;
}): JSX.Element => {
const [doNotTrack, setDoNotTrack] = useState<boolean>(
defaultVisitListenerContext.doNotTrack,
);
const visitsApi = useApi(visitsApiRef);
const { pathname } = useLocation();
const toEntityRefImpl = toEntityRef ?? getToEntityRef();
const visitNameImpl = visitName ?? getVisitName(document);
useEffect(() => {
// Wait for the browser to finish with paint with the assumption react
// has finished with dom reconciliation and the doNotTrack state update.
// has finished with dom reconciliation.
const requestId = requestAnimationFrame(() => {
if (!doNotTrack)
visitsApi.saveVisit({
visit: {
name: visitNameImpl({ pathname }),
pathname,
entityRef: toEntityRefImpl({ pathname }),
},
});
visitsApi.saveVisit({
visit: {
name: visitNameImpl({ pathname }),
pathname,
entityRef: toEntityRefImpl({ pathname }),
},
});
});
return () => cancelAnimationFrame(requestId);
}, [doNotTrack, visitsApi, pathname, toEntityRefImpl, visitNameImpl]);
return (
<VisitListenerContext.Provider value={{ doNotTrack, setDoNotTrack }}>
{children}
</VisitListenerContext.Provider>
);
};
/**
* @public
* Hook used to access visit listener context. Is able to control if tracking
* should be disabled.
*/
export const useVisitListener = () => {
const value = useContext(VisitListenerContext);
if (value === undefined)
throw new Error(
'useVisitListener found an undefined context, <VisitListener/> could be missing',
);
return value;
};
/**
* @public
* Use this component to warn VisitListener to disable tracking.
*/
export const DoNotTrack = ({
children,
}: {
children?: ReactNode;
}): JSX.Element => {
const { setDoNotTrack } = useVisitListener();
useEffect(() => {
setDoNotTrack(true);
return () => setDoNotTrack(false);
}, [setDoNotTrack]);
}, [visitsApi, pathname, toEntityRefImpl, visitNameImpl]);
return <>{children}</>;
};