Merge pull request #7149 from backstage/rugvip/entity-context
catalog-react: cross-version compatibility for entity context
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
---
|
||||
|
||||
Deprecated `Router` in favor of using the plugin extensions.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
---
|
||||
|
||||
Deprecated EntityContext in favor of using `useEntity`, `EntityProvider` and the new `AsyncEntityProvider` instead. This update also brings cross-version compatibility to `@backstage/catalog-react`, meaning that future versions can be used in parallel with this one.
|
||||
@@ -25,6 +25,29 @@ import { SystemEntity } from '@backstage/catalog-model';
|
||||
import { TableColumn } from '@backstage/core-components';
|
||||
import { UserEntity } from '@backstage/catalog-model';
|
||||
|
||||
// @public
|
||||
export const AsyncEntityProvider: ({
|
||||
children,
|
||||
entity,
|
||||
loading,
|
||||
error,
|
||||
refresh,
|
||||
}: AsyncEntityProviderProps) => JSX.Element;
|
||||
|
||||
// @public
|
||||
export interface AsyncEntityProviderProps {
|
||||
// (undocumented)
|
||||
children: ReactNode;
|
||||
// (undocumented)
|
||||
entity?: Entity;
|
||||
// (undocumented)
|
||||
error?: Error;
|
||||
// (undocumented)
|
||||
loading: boolean;
|
||||
// (undocumented)
|
||||
refresh?: VoidFunction;
|
||||
}
|
||||
|
||||
export { CATALOG_FILTER_EXISTS };
|
||||
|
||||
export { CatalogApi };
|
||||
@@ -109,9 +132,8 @@ export type DefaultEntityFilters = {
|
||||
};
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "EntityLoadingStatus" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "EntityContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const EntityContext: Context<EntityLoadingStatus>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "EntityFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
@@ -199,15 +221,20 @@ export class EntityOwnerFilter implements EntityFilter {
|
||||
// @public (undocumented)
|
||||
export const EntityOwnerPicker: () => JSX.Element | null;
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "EntityProviderProps" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "EntityProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const EntityProvider: ({
|
||||
entity,
|
||||
children,
|
||||
}: EntityProviderProps) => JSX.Element;
|
||||
|
||||
// @public
|
||||
export interface EntityProviderProps {
|
||||
// (undocumented)
|
||||
children: ReactNode;
|
||||
// (undocumented)
|
||||
entity?: Entity;
|
||||
}
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "EntityRefLinkProps" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "EntityRefLink" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
@@ -726,8 +753,6 @@ export const UnregisterEntityDialog: ({
|
||||
entity,
|
||||
}: Props_3) => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "useEntity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public
|
||||
export function useEntity<T extends Entity = Entity>(): {
|
||||
entity: T;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"@backstage/core-components": "^0.4.0",
|
||||
"@backstage/core-plugin-api": "^0.1.6",
|
||||
"@backstage/integration": "^0.6.3",
|
||||
"@backstage/version-bridge": "^0.1.0",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { EntityContext } from '../../hooks';
|
||||
|
||||
type EntityProviderProps = {
|
||||
entity: Entity;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export const EntityProvider = ({ entity, children }: EntityProviderProps) => (
|
||||
<EntityContext.Provider
|
||||
value={{
|
||||
entity,
|
||||
loading: !Boolean(entity),
|
||||
error: undefined,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</EntityContext.Provider>
|
||||
);
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export { EntityProvider } from './EntityProvider';
|
||||
@@ -16,7 +16,6 @@
|
||||
export * from './EntityKindPicker';
|
||||
export * from './EntityLifecyclePicker';
|
||||
export * from './EntityOwnerPicker';
|
||||
export * from './EntityProvider';
|
||||
export * from './EntityRefLink';
|
||||
export * from './EntitySearchBar';
|
||||
export * from './EntityTable';
|
||||
|
||||
@@ -13,7 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export { EntityContext, useEntity, useEntityFromUrl } from './useEntity';
|
||||
export {
|
||||
EntityContext,
|
||||
useEntity,
|
||||
useEntityFromUrl,
|
||||
EntityProvider,
|
||||
AsyncEntityProvider,
|
||||
} from './useEntity';
|
||||
export type {
|
||||
EntityProviderProps,
|
||||
AsyncEntityProviderProps,
|
||||
} from './useEntity';
|
||||
export { useEntityCompoundName } from './useEntityCompoundName';
|
||||
export {
|
||||
EntityListContext,
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import {
|
||||
useEntity,
|
||||
EntityProvider,
|
||||
AsyncEntityProvider,
|
||||
EntityContext,
|
||||
} from './useEntity';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
describe('EntityProvider', () => {
|
||||
it('should provide no entity', async () => {
|
||||
const { result } = renderHook(() => useEntity(), {
|
||||
wrapper: ({ children }) => <EntityProvider children={children} />,
|
||||
});
|
||||
|
||||
expect(result.current.entity).toBe(undefined);
|
||||
expect(result.current.loading).toBe(true);
|
||||
expect(result.current.error).toBe(undefined);
|
||||
expect(result.current.refresh).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should provide an entity', async () => {
|
||||
const entity = { kind: 'MyEntity' } as Entity;
|
||||
const { result } = renderHook(() => useEntity(), {
|
||||
wrapper: ({ children }) => (
|
||||
<EntityProvider entity={entity} children={children} />
|
||||
),
|
||||
});
|
||||
|
||||
expect(result.current.entity).toBe(entity);
|
||||
expect(result.current.loading).toBe(false);
|
||||
expect(result.current.error).toBe(undefined);
|
||||
expect(result.current.refresh).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('AsyncEntityProvider', () => {
|
||||
it('should provide no entity', async () => {
|
||||
const { result } = renderHook(() => useEntity(), {
|
||||
wrapper: ({ children }) => (
|
||||
<AsyncEntityProvider loading={false} children={children} />
|
||||
),
|
||||
});
|
||||
|
||||
expect(result.current.entity).toBe(undefined);
|
||||
expect(result.current.loading).toBe(false);
|
||||
expect(result.current.error).toBe(undefined);
|
||||
expect(result.current.refresh).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should provide an entity', async () => {
|
||||
const entity = { kind: 'MyEntity' } as Entity;
|
||||
const refresh = () => {};
|
||||
const { result } = renderHook(() => useEntity(), {
|
||||
wrapper: ({ children }) => (
|
||||
<AsyncEntityProvider
|
||||
loading={false}
|
||||
entity={entity}
|
||||
refresh={refresh}
|
||||
children={children}
|
||||
/>
|
||||
),
|
||||
});
|
||||
|
||||
expect(result.current.entity).toBe(entity);
|
||||
expect(result.current.loading).toBe(false);
|
||||
expect(result.current.error).toBe(undefined);
|
||||
expect(result.current.refresh).toBe(refresh);
|
||||
});
|
||||
|
||||
it('should provide an error', async () => {
|
||||
const error = new Error('oh no');
|
||||
const { result } = renderHook(() => useEntity(), {
|
||||
wrapper: ({ children }) => (
|
||||
<AsyncEntityProvider
|
||||
loading={false}
|
||||
error={error}
|
||||
children={children}
|
||||
/>
|
||||
),
|
||||
});
|
||||
|
||||
expect(result.current.entity).toBe(undefined);
|
||||
expect(result.current.loading).toBe(false);
|
||||
expect(result.current.error).toBe(error);
|
||||
expect(result.current.refresh).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('EntityContext.Provider', () => {
|
||||
it('should provide no entity', async () => {
|
||||
const { result } = renderHook(() => useEntity(), {
|
||||
wrapper: ({ children }) => (
|
||||
<EntityContext.Provider
|
||||
value={{ loading: false }}
|
||||
children={children}
|
||||
/>
|
||||
),
|
||||
});
|
||||
|
||||
expect(result.current.entity).toBe(undefined);
|
||||
expect(result.current.loading).toBe(false);
|
||||
expect(result.current.error).toBe(undefined);
|
||||
expect(result.current.refresh).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should provide an entity', async () => {
|
||||
const entity = { kind: 'MyEntity' } as Entity;
|
||||
const { result } = renderHook(() => useEntity(), {
|
||||
wrapper: ({ children }) => (
|
||||
<EntityContext.Provider
|
||||
value={{ entity, loading: false }}
|
||||
children={children}
|
||||
/>
|
||||
),
|
||||
});
|
||||
|
||||
expect(result.current.entity).toBe(entity);
|
||||
expect(result.current.loading).toBe(false);
|
||||
expect(result.current.error).toBe(undefined);
|
||||
expect(result.current.refresh).toBe(undefined);
|
||||
});
|
||||
});
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { errorApiRef, useApi } from '@backstage/core-plugin-api';
|
||||
import { createContext, useContext, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { useAsyncRetry } from 'react-use';
|
||||
import { catalogApiRef } from '../api';
|
||||
import { useEntityCompoundName } from './useEntityCompoundName';
|
||||
|
||||
type EntityLoadingStatus = {
|
||||
entity?: Entity;
|
||||
loading: boolean;
|
||||
error?: Error;
|
||||
refresh?: VoidFunction;
|
||||
};
|
||||
|
||||
export const EntityContext = createContext<EntityLoadingStatus>({
|
||||
entity: undefined,
|
||||
loading: true,
|
||||
error: undefined,
|
||||
refresh: () => {},
|
||||
});
|
||||
|
||||
export const useEntityFromUrl = (): EntityLoadingStatus => {
|
||||
const { kind, namespace, name } = useEntityCompoundName();
|
||||
const navigate = useNavigate();
|
||||
const errorApi = useApi(errorApiRef);
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
|
||||
const {
|
||||
value: entity,
|
||||
error,
|
||||
loading,
|
||||
retry: refresh,
|
||||
} = useAsyncRetry(
|
||||
() => catalogApi.getEntityByName({ kind, namespace, name }),
|
||||
[catalogApi, kind, namespace, name],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!name) {
|
||||
errorApi.post(new Error('No name provided!'));
|
||||
navigate('/');
|
||||
}
|
||||
}, [errorApi, navigate, error, loading, entity, name]);
|
||||
|
||||
return { entity, loading, error, refresh };
|
||||
};
|
||||
|
||||
/**
|
||||
* Grab the current entity from the context and its current loading state.
|
||||
*/
|
||||
export function useEntity<T extends Entity = Entity>() {
|
||||
const { entity, loading, error, refresh } = useContext(EntityContext);
|
||||
return { entity: entity as T, loading, error, refresh };
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { errorApiRef, useApi } from '@backstage/core-plugin-api';
|
||||
import {
|
||||
createVersionedContext,
|
||||
createVersionedValueMap,
|
||||
useVersionedContext,
|
||||
} from '@backstage/version-bridge';
|
||||
import React, {
|
||||
ReactNode,
|
||||
useEffect,
|
||||
createContext,
|
||||
Provider,
|
||||
Context,
|
||||
} from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { useAsyncRetry } from 'react-use';
|
||||
import { catalogApiRef } from '../api';
|
||||
import { useEntityCompoundName } from './useEntityCompoundName';
|
||||
|
||||
type EntityLoadingStatus = {
|
||||
entity?: Entity;
|
||||
loading: boolean;
|
||||
error?: Error;
|
||||
refresh?: VoidFunction;
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated use `useEntity` and `EntityProvider` or `AsyncEntityProvider` instead.
|
||||
*/
|
||||
export const EntityContext: Context<EntityLoadingStatus> =
|
||||
createContext<EntityLoadingStatus>({
|
||||
entity: undefined,
|
||||
loading: true,
|
||||
error: undefined,
|
||||
refresh: () => {},
|
||||
});
|
||||
// We grab this for use in the new provider, since we're overriding it later on
|
||||
const OldEntityProvider = EntityContext.Provider;
|
||||
|
||||
// This context has support for multiple concurrent versions of this package.
|
||||
// It is currently used in parallel with the old context in order to provide
|
||||
// a smooth transition, but will eventually be the only context we use.
|
||||
const NewEntityContext =
|
||||
createVersionedContext<{ 1: EntityLoadingStatus }>('entity-context');
|
||||
|
||||
/**
|
||||
* Properties for the AsyncEntityProvider component.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface AsyncEntityProviderProps {
|
||||
children: ReactNode;
|
||||
entity?: Entity;
|
||||
loading: boolean;
|
||||
error?: Error;
|
||||
refresh?: VoidFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a loaded entity to be picked up by the `useEntity` hook.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const AsyncEntityProvider = ({
|
||||
children,
|
||||
entity,
|
||||
loading,
|
||||
error,
|
||||
refresh,
|
||||
}: AsyncEntityProviderProps) => {
|
||||
const value = { entity, loading, error, refresh };
|
||||
// We provide both the old and the new context, since
|
||||
// consumers might be doing things like `useContext(EntityContext)`
|
||||
return (
|
||||
<OldEntityProvider value={value}>
|
||||
<NewEntityContext.Provider value={createVersionedValueMap({ 1: value })}>
|
||||
{children}
|
||||
</NewEntityContext.Provider>
|
||||
</OldEntityProvider>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Properties for the EntityProvider component.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface EntityProviderProps {
|
||||
children: ReactNode;
|
||||
entity?: Entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an entity to be picked up by the `useEntity` hook.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const EntityProvider = ({ entity, children }: EntityProviderProps) => (
|
||||
<AsyncEntityProvider
|
||||
entity={entity}
|
||||
loading={!Boolean(entity)}
|
||||
error={undefined}
|
||||
refresh={undefined}
|
||||
children={children}
|
||||
/>
|
||||
);
|
||||
|
||||
// This is used for forwards compatibility with the new entity context
|
||||
const CompatibilityProvider = ({
|
||||
value,
|
||||
children,
|
||||
}: {
|
||||
value: EntityLoadingStatus;
|
||||
children: ReactNode;
|
||||
}) => {
|
||||
return <AsyncEntityProvider {...value} children={children} />;
|
||||
};
|
||||
EntityContext.Provider = CompatibilityProvider as Provider<EntityLoadingStatus>;
|
||||
|
||||
export const useEntityFromUrl = (): EntityLoadingStatus => {
|
||||
const { kind, namespace, name } = useEntityCompoundName();
|
||||
const navigate = useNavigate();
|
||||
const errorApi = useApi(errorApiRef);
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
|
||||
const {
|
||||
value: entity,
|
||||
error,
|
||||
loading,
|
||||
retry: refresh,
|
||||
} = useAsyncRetry(
|
||||
() => catalogApi.getEntityByName({ kind, namespace, name }),
|
||||
[catalogApi, kind, namespace, name],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!name) {
|
||||
errorApi.post(new Error('No name provided!'));
|
||||
navigate('/');
|
||||
}
|
||||
}, [errorApi, navigate, error, loading, entity, name]);
|
||||
|
||||
return { entity, loading, error, refresh };
|
||||
};
|
||||
|
||||
/**
|
||||
* Grab the current entity from the context and its current loading state.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function useEntity<T extends Entity = Entity>() {
|
||||
const versionedHolder =
|
||||
useVersionedContext<{ 1: EntityLoadingStatus }>('entity-context');
|
||||
|
||||
if (!versionedHolder) {
|
||||
// TODO(Rugvip): Throw this once we fully migrate to the new context
|
||||
// throw new Error('Entity context is not available');
|
||||
|
||||
return {
|
||||
entity: undefined as unknown as T,
|
||||
loading: true,
|
||||
error: undefined,
|
||||
refresh: () => {},
|
||||
};
|
||||
}
|
||||
|
||||
const value = versionedHolder.atVersion(1);
|
||||
if (!value) {
|
||||
throw new Error('EntityContext v1 not available');
|
||||
}
|
||||
|
||||
const { entity, loading, error, refresh } = value;
|
||||
return { entity: entity as T, loading, error, refresh };
|
||||
}
|
||||
@@ -401,7 +401,7 @@ export const isOrphan: (entity: Entity) => boolean;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const Router: ({
|
||||
EntityPage,
|
||||
}: {
|
||||
|
||||
@@ -16,12 +16,13 @@
|
||||
|
||||
import React from 'react';
|
||||
import { Outlet } from 'react-router';
|
||||
import { EntityLoaderProvider } from '../EntityLoaderProvider';
|
||||
import {
|
||||
useEntityFromUrl,
|
||||
AsyncEntityProvider,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
|
||||
export const CatalogEntityPage = () => {
|
||||
return (
|
||||
<EntityLoaderProvider>
|
||||
<Outlet />
|
||||
</EntityLoaderProvider>
|
||||
);
|
||||
};
|
||||
export const CatalogEntityPage = () => (
|
||||
<AsyncEntityProvider {...useEntityFromUrl()}>
|
||||
<Outlet />
|
||||
</AsyncEntityProvider>
|
||||
);
|
||||
|
||||
@@ -15,7 +15,11 @@
|
||||
*/
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { catalogApiRef, EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import {
|
||||
catalogApiRef,
|
||||
EntityProvider,
|
||||
AsyncEntityProvider,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
@@ -26,16 +30,12 @@ import { EntityLayout } from './EntityLayout';
|
||||
import { AlertApi, alertApiRef } from '@backstage/core-plugin-api';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
|
||||
const mockEntityData = {
|
||||
loading: false,
|
||||
error: undefined,
|
||||
entity: {
|
||||
kind: 'MyKind',
|
||||
metadata: {
|
||||
name: 'my-entity',
|
||||
},
|
||||
} as Entity,
|
||||
};
|
||||
const mockEntity = {
|
||||
kind: 'MyKind',
|
||||
metadata: {
|
||||
name: 'my-entity',
|
||||
},
|
||||
} as Entity;
|
||||
|
||||
const mockApis = ApiRegistry.with(catalogApiRef, {} as CatalogApi).with(
|
||||
alertApiRef,
|
||||
@@ -46,13 +46,13 @@ describe('EntityLayout', () => {
|
||||
it('renders simplest case', async () => {
|
||||
const rendered = await renderInTestApp(
|
||||
<ApiProvider apis={mockApis}>
|
||||
<EntityContext.Provider value={mockEntityData}>
|
||||
<EntityProvider entity={mockEntity}>
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="tabbed-test-title">
|
||||
<div>tabbed-test-content</div>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
);
|
||||
|
||||
@@ -92,20 +92,15 @@ describe('EntityLayout', () => {
|
||||
});
|
||||
|
||||
it('renders error message when entity is not found', async () => {
|
||||
const noEntityData = {
|
||||
...mockEntityData,
|
||||
entity: undefined,
|
||||
};
|
||||
|
||||
const rendered = await renderInTestApp(
|
||||
<ApiProvider apis={mockApis}>
|
||||
<EntityContext.Provider value={noEntityData}>
|
||||
<AsyncEntityProvider loading={false}>
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="tabbed-test-title">
|
||||
<div>tabbed-test-content</div>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
</EntityContext.Provider>
|
||||
</AsyncEntityProvider>
|
||||
</ApiProvider>,
|
||||
);
|
||||
|
||||
@@ -122,7 +117,7 @@ describe('EntityLayout', () => {
|
||||
path="/*"
|
||||
element={
|
||||
<ApiProvider apis={mockApis}>
|
||||
<EntityContext.Provider value={mockEntityData}>
|
||||
<EntityProvider entity={mockEntity}>
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="tabbed-test-title">
|
||||
<div>tabbed-test-content</div>
|
||||
@@ -134,7 +129,7 @@ describe('EntityLayout', () => {
|
||||
<div>tabbed-test-content-2</div>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>
|
||||
}
|
||||
/>
|
||||
@@ -159,7 +154,7 @@ describe('EntityLayout', () => {
|
||||
|
||||
const rendered = await renderInTestApp(
|
||||
<ApiProvider apis={mockApis}>
|
||||
<EntityContext.Provider value={mockEntityData}>
|
||||
<EntityProvider entity={mockEntity}>
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="tabbed-test-title">
|
||||
<div>tabbed-test-content</div>
|
||||
@@ -179,7 +174,7 @@ describe('EntityLayout', () => {
|
||||
<div>tabbed-test-content-3</div>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { Entity, EntityLink } from '@backstage/catalog-model';
|
||||
import { EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
|
||||
import React from 'react';
|
||||
import { EntityLinksCard } from './EntityLinksCard';
|
||||
@@ -40,17 +40,12 @@ describe('EntityLinksCard', () => {
|
||||
|
||||
it('should render a link', async () => {
|
||||
const links: EntityLink[] = [createLink()];
|
||||
const entityContextValue = {
|
||||
entity: createEntity(links),
|
||||
loading: false,
|
||||
error: undefined,
|
||||
};
|
||||
|
||||
const { queryByText } = await renderWithEffects(
|
||||
wrapInTestApp(
|
||||
<EntityContext.Provider value={entityContextValue}>
|
||||
<EntityProvider entity={createEntity(links)}>
|
||||
<EntityLinksCard />
|
||||
</EntityContext.Provider>,
|
||||
</EntityProvider>,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -59,17 +54,11 @@ describe('EntityLinksCard', () => {
|
||||
});
|
||||
|
||||
it('should show empty state', async () => {
|
||||
const entityContextValue = {
|
||||
entity: createEntity([]),
|
||||
loading: false,
|
||||
error: undefined,
|
||||
};
|
||||
|
||||
const { queryByText } = await renderWithEffects(
|
||||
wrapInTestApp(
|
||||
<EntityContext.Provider value={entityContextValue}>
|
||||
<EntityProvider entity={createEntity([])}>
|
||||
<EntityLinksCard />
|
||||
</EntityContext.Provider>,
|
||||
</EntityProvider>,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {
|
||||
EntityContext,
|
||||
useEntityFromUrl,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import React, { ReactNode } from 'react';
|
||||
|
||||
export const EntityLoaderProvider = ({ children }: { children: ReactNode }) => {
|
||||
const { entity, loading, error, refresh } = useEntityFromUrl();
|
||||
|
||||
return (
|
||||
<EntityContext.Provider value={{ entity, loading, error, refresh }}>
|
||||
{children}
|
||||
</EntityContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export { EntityLoaderProvider } from './EntityLoaderProvider';
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { isKind } from './conditions';
|
||||
@@ -46,15 +46,9 @@ describe('EntitySwitch', () => {
|
||||
|
||||
const rendered = render(
|
||||
<Wrapper>
|
||||
<EntityContext.Provider
|
||||
value={{
|
||||
entity: { kind: 'component' } as Entity,
|
||||
loading: false,
|
||||
error: undefined,
|
||||
}}
|
||||
>
|
||||
<EntityProvider entity={{ kind: 'component' } as Entity}>
|
||||
{content}
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</Wrapper>,
|
||||
);
|
||||
|
||||
@@ -64,15 +58,9 @@ describe('EntitySwitch', () => {
|
||||
|
||||
rendered.rerender(
|
||||
<Wrapper>
|
||||
<EntityContext.Provider
|
||||
value={{
|
||||
entity: { kind: 'template' } as Entity,
|
||||
loading: false,
|
||||
error: undefined,
|
||||
}}
|
||||
>
|
||||
<EntityProvider entity={{ kind: 'template' } as Entity}>
|
||||
{content}
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</Wrapper>,
|
||||
);
|
||||
|
||||
@@ -82,15 +70,9 @@ describe('EntitySwitch', () => {
|
||||
|
||||
rendered.rerender(
|
||||
<Wrapper>
|
||||
<EntityContext.Provider
|
||||
value={{
|
||||
entity: { kind: 'derp' } as Entity,
|
||||
loading: false,
|
||||
error: undefined,
|
||||
}}
|
||||
>
|
||||
<EntityProvider entity={{ kind: 'derp' } as Entity}>
|
||||
{content}
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</Wrapper>,
|
||||
);
|
||||
|
||||
@@ -100,20 +82,16 @@ describe('EntitySwitch', () => {
|
||||
});
|
||||
|
||||
it('should switch child when filters switch', () => {
|
||||
const entityContextValue = {
|
||||
entity: { kind: 'component' } as Entity,
|
||||
loading: false,
|
||||
error: undefined,
|
||||
};
|
||||
const entity = { kind: 'component' } as Entity;
|
||||
|
||||
const rendered = render(
|
||||
<Wrapper>
|
||||
<EntityContext.Provider value={entityContextValue}>
|
||||
<EntityProvider entity={entity}>
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isKind('component')} children="A" />
|
||||
<EntitySwitch.Case children="B" />
|
||||
</EntitySwitch>
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</Wrapper>,
|
||||
);
|
||||
|
||||
@@ -122,12 +100,12 @@ describe('EntitySwitch', () => {
|
||||
|
||||
rendered.rerender(
|
||||
<Wrapper>
|
||||
<EntityContext.Provider value={entityContextValue}>
|
||||
<EntityProvider entity={entity}>
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isKind('template')} children="A" />
|
||||
<EntitySwitch.Case children="B" />
|
||||
</EntitySwitch>
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</Wrapper>,
|
||||
);
|
||||
|
||||
|
||||
@@ -15,15 +15,16 @@
|
||||
*/
|
||||
import { ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model';
|
||||
import {
|
||||
AsyncEntityProvider,
|
||||
entityRoute,
|
||||
rootRoute,
|
||||
useEntity,
|
||||
useEntityFromUrl,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { Link, Typography } from '@material-ui/core';
|
||||
import React, { ComponentType } from 'react';
|
||||
import React, { ComponentType, ReactNode } from 'react';
|
||||
import { Navigate, Route, Routes, useParams } from 'react-router';
|
||||
import { CatalogPage } from './CatalogPage';
|
||||
import { EntityLoaderProvider } from './EntityLoaderProvider';
|
||||
import { EntityNotFound } from './EntityNotFound';
|
||||
import { EntityPageLayout } from './EntityPageLayout';
|
||||
import { Content } from '@backstage/core-components';
|
||||
@@ -73,6 +74,13 @@ const OldEntityRouteRedirect = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const EntityLoader = (props: { children: ReactNode }) => (
|
||||
<AsyncEntityProvider {...useEntityFromUrl()} {...props} />
|
||||
);
|
||||
|
||||
/**
|
||||
* @deprecated Use plugin extensions instead
|
||||
* */
|
||||
export const Router = ({
|
||||
EntityPage = DefaultEntityPage,
|
||||
}: {
|
||||
@@ -83,9 +91,9 @@ export const Router = ({
|
||||
<Route
|
||||
path={`${entityRoute.path}`}
|
||||
element={
|
||||
<EntityLoaderProvider>
|
||||
<EntityLoader>
|
||||
<EntityPageSwitch EntityPage={EntityPage} />
|
||||
</EntityLoaderProvider>
|
||||
</EntityLoader>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
|
||||
+2
-6
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { useConsumerGroupsForEntity } from './useConsumerGroupsForEntity';
|
||||
@@ -23,11 +23,7 @@ describe('useConsumerGroupOffsets', () => {
|
||||
let entity: Entity;
|
||||
|
||||
const wrapper = ({ children }: PropsWithChildren<{}>) => {
|
||||
return (
|
||||
<EntityContext.Provider value={{ entity: entity, loading: false }}>
|
||||
{children}
|
||||
</EntityContext.Provider>
|
||||
);
|
||||
return <EntityProvider entity={entity}>{children}</EntityProvider>;
|
||||
};
|
||||
|
||||
const subject = () => renderHook(useConsumerGroupsForEntity, { wrapper });
|
||||
|
||||
+2
-4
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { when } from 'jest-when';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
@@ -65,9 +65,7 @@ describe('useConsumerGroupOffsets', () => {
|
||||
mockKafkaApi,
|
||||
)}
|
||||
>
|
||||
<EntityContext.Provider value={{ entity: entity, loading: false }}>
|
||||
{children}
|
||||
</EntityContext.Provider>
|
||||
<EntityProvider entity={entity}>{children}</EntityProvider>
|
||||
</ApiProvider>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { lightTheme } from '@backstage/theme';
|
||||
import { ThemeProvider } from '@material-ui/core';
|
||||
import { render } from '@testing-library/react';
|
||||
@@ -77,16 +77,14 @@ describe('<AuditListTableForEntity />', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const subject = (value = {}) =>
|
||||
const subject = () =>
|
||||
render(
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<MemoryRouter>
|
||||
<ApiProvider apis={apis}>
|
||||
<EntityContext.Provider
|
||||
value={{ entity: entity, loading: false, ...value }}
|
||||
>
|
||||
<EntityProvider entity={entity}>
|
||||
<AuditListForEntity />
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>
|
||||
</MemoryRouter>
|
||||
</ThemeProvider>,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { lightTheme } from '@backstage/theme';
|
||||
import { ThemeProvider } from '@material-ui/core';
|
||||
import { render } from '@testing-library/react';
|
||||
@@ -64,15 +64,13 @@ describe('<LastLighthouseAuditCard />', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const subject = (value = {}) =>
|
||||
const subject = () =>
|
||||
render(
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<MemoryRouter>
|
||||
<EntityContext.Provider
|
||||
value={{ entity: entity, loading: false, ...value }}
|
||||
>
|
||||
<EntityProvider entity={entity}>
|
||||
<LastLighthouseAuditCard />
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</MemoryRouter>
|
||||
</ThemeProvider>,
|
||||
);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { lighthouseApiRef, WebsiteListResponse } from '../api';
|
||||
@@ -61,9 +61,7 @@ describe('useWebsiteForEntity', () => {
|
||||
mockLighthouseApi,
|
||||
)}
|
||||
>
|
||||
<EntityContext.Provider value={{ entity: entity, loading: false }}>
|
||||
{children}
|
||||
</EntityContext.Provider>
|
||||
<EntityProvider entity={entity}>{children}</EntityProvider>
|
||||
</ApiProvider>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { GroupEntity } from '@backstage/catalog-model';
|
||||
import { EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { Grid } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
@@ -57,12 +57,12 @@ const defaultEntity: GroupEntity = {
|
||||
|
||||
export const Default = () => (
|
||||
<MemoryRouter>
|
||||
<EntityContext.Provider value={{ entity: defaultEntity, loading: false }}>
|
||||
<EntityProvider entity={defaultEntity}>
|
||||
<Grid container spacing={4}>
|
||||
<Grid item xs={12} md={4}>
|
||||
<GroupProfileCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { Entity, GroupEntity } from '@backstage/catalog-model';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
import { catalogApiRef, EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import { catalogApiRef, EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { Grid } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
@@ -105,13 +105,13 @@ const apiRegistry = (items: Entity[]) =>
|
||||
export const Default = () => (
|
||||
<MemoryRouter>
|
||||
<ApiProvider apis={apiRegistry([alice, bob])}>
|
||||
<EntityContext.Provider value={{ entity: defaultEntity, loading: false }}>
|
||||
<EntityProvider entity={defaultEntity}>
|
||||
<Grid container spacing={4}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<MembersListCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
@@ -119,13 +119,13 @@ export const Default = () => (
|
||||
export const Empty = () => (
|
||||
<MemoryRouter>
|
||||
<ApiProvider apis={apiRegistry([])}>
|
||||
<EntityContext.Provider value={{ entity: defaultEntity, loading: false }}>
|
||||
<EntityProvider entity={defaultEntity}>
|
||||
<Grid container spacing={4}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<MembersListCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
CatalogApi,
|
||||
catalogApiRef,
|
||||
catalogRouteRef,
|
||||
EntityContext,
|
||||
EntityProvider,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { wrapInTestApp } from '@backstage/test-utils';
|
||||
import {
|
||||
@@ -91,13 +91,13 @@ const apiRegistry = ApiRegistry.from([[catalogApiRef, catalogApi]]);
|
||||
export const Default = () =>
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apiRegistry}>
|
||||
<EntityContext.Provider value={{ entity: defaultEntity, loading: false }}>
|
||||
<EntityProvider entity={defaultEntity}>
|
||||
<Grid container spacing={4}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<OwnershipCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
{
|
||||
mountedRoutes: { '/catalog': catalogRouteRef },
|
||||
@@ -124,15 +124,13 @@ export const Themed = () =>
|
||||
wrapInTestApp(
|
||||
<ThemeProvider theme={monochromeTheme}>
|
||||
<ApiProvider apis={apiRegistry}>
|
||||
<EntityContext.Provider
|
||||
value={{ entity: defaultEntity, loading: false }}
|
||||
>
|
||||
<EntityProvider entity={defaultEntity}>
|
||||
<Grid container spacing={4}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<OwnershipCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>
|
||||
</ThemeProvider>,
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { UserEntity } from '@backstage/catalog-model';
|
||||
import { EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { Grid } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
@@ -55,13 +55,13 @@ const defaultEntity: UserEntity = {
|
||||
|
||||
export const Default = () => (
|
||||
<MemoryRouter>
|
||||
<EntityContext.Provider value={{ entity: defaultEntity, loading: false }}>
|
||||
<EntityProvider entity={defaultEntity}>
|
||||
<Grid container spacing={4}>
|
||||
<Grid item xs={12} md={4}>
|
||||
<UserProfileCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
@@ -83,12 +83,12 @@ const noImageEntity: UserEntity = {
|
||||
|
||||
export const NoImage = () => (
|
||||
<MemoryRouter>
|
||||
<EntityContext.Provider value={{ entity: noImageEntity, loading: false }}>
|
||||
<EntityProvider entity={noImageEntity}>
|
||||
<Grid container spacing={4}>
|
||||
<Grid item xs={12} md={4}>
|
||||
<UserProfileCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
import React from 'react';
|
||||
import { act, fireEvent, render, waitFor } from '@testing-library/react';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { wrapInTestApp } from '@backstage/test-utils';
|
||||
import {
|
||||
splunkOnCallApiRef,
|
||||
@@ -71,35 +71,27 @@ const apis = ApiRegistry.from([
|
||||
],
|
||||
]);
|
||||
|
||||
const mockEntityData = {
|
||||
loading: false,
|
||||
error: undefined,
|
||||
entity: {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'splunkoncall-test',
|
||||
annotations: {
|
||||
'splunk.com/on-call-team': 'test',
|
||||
},
|
||||
const mockEntity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'splunkoncall-test',
|
||||
annotations: {
|
||||
'splunk.com/on-call-team': 'test',
|
||||
},
|
||||
} as Entity,
|
||||
};
|
||||
},
|
||||
} as Entity;
|
||||
|
||||
const mockEntityDataNoIncidents = {
|
||||
loading: false,
|
||||
error: undefined,
|
||||
entity: {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'splunkoncall-test',
|
||||
annotations: {
|
||||
'splunk.com/on-call-team': 'test-noincidents',
|
||||
},
|
||||
const mockEntityNoIncidents = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'splunkoncall-test',
|
||||
annotations: {
|
||||
'splunk.com/on-call-team': 'test-noincidents',
|
||||
},
|
||||
} as Entity,
|
||||
};
|
||||
},
|
||||
} as Entity;
|
||||
|
||||
describe('SplunkOnCallCard', () => {
|
||||
it('Render splunkoncall', async () => {
|
||||
@@ -113,9 +105,9 @@ describe('SplunkOnCallCard', () => {
|
||||
const { getByText, queryByTestId } = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<EntityContext.Provider value={mockEntityDataNoIncidents}>
|
||||
<EntityProvider entity={mockEntityNoIncidents}>
|
||||
<EntitySplunkOnCallCard />
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
@@ -136,9 +128,9 @@ describe('SplunkOnCallCard', () => {
|
||||
const { getByText, queryByTestId } = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<EntityContext.Provider value={mockEntityData}>
|
||||
<EntityProvider entity={mockEntity}>
|
||||
<EntitySplunkOnCallCard />
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
@@ -155,9 +147,9 @@ describe('SplunkOnCallCard', () => {
|
||||
const { getByText, queryByTestId } = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<EntityContext.Provider value={mockEntityData}>
|
||||
<EntityProvider entity={mockEntity}>
|
||||
<EntitySplunkOnCallCard />
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
@@ -181,9 +173,9 @@ describe('SplunkOnCallCard', () => {
|
||||
const { getByText, queryByTestId } = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<EntityContext.Provider value={mockEntityData}>
|
||||
<EntityProvider entity={mockEntity}>
|
||||
<EntitySplunkOnCallCard />
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
@@ -204,9 +196,9 @@ describe('SplunkOnCallCard', () => {
|
||||
const { getByText, queryByTestId, getByRole } = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<EntityContext.Provider value={mockEntityData}>
|
||||
<EntityProvider entity={mockEntity}>
|
||||
<EntitySplunkOnCallCard />
|
||||
</EntityContext.Provider>
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user