@@ -123,7 +123,7 @@ describe('<EntityTypePicker/>', () => {
|
||||
fireEvent.click(rendered.getByText('Service'));
|
||||
|
||||
expect(updateFilters).toHaveBeenLastCalledWith({
|
||||
type: new EntityTypeFilter('service'),
|
||||
type: new EntityTypeFilter(['service']),
|
||||
});
|
||||
|
||||
fireEvent.click(input);
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import React, { PropsWithChildren, useCallback, useState } from 'react';
|
||||
import {
|
||||
DefaultEntityFilters,
|
||||
EntityListContext,
|
||||
EntityListContextProps,
|
||||
} from '../hooks/useEntityListProvider';
|
||||
@@ -23,17 +24,47 @@ import {
|
||||
export const MockEntityListContextProvider = ({
|
||||
children,
|
||||
value,
|
||||
}: PropsWithChildren<{ value: Partial<EntityListContextProps> }>) => {
|
||||
}: PropsWithChildren<{
|
||||
value: Partial<EntityListContextProps>;
|
||||
}>) => {
|
||||
// Provides a default implementation that stores filter state, for testing components that
|
||||
// reflect filter state.
|
||||
const [filters, setFilters] = useState<DefaultEntityFilters>(
|
||||
value.filters ?? {},
|
||||
);
|
||||
const updateFilters = useCallback(
|
||||
(
|
||||
update:
|
||||
| Partial<DefaultEntityFilters>
|
||||
| ((
|
||||
prevFilters: DefaultEntityFilters,
|
||||
) => Partial<DefaultEntityFilters>),
|
||||
) => {
|
||||
setFilters(prevFilters => {
|
||||
const newFilters =
|
||||
typeof update === 'function' ? update(prevFilters) : update;
|
||||
return { ...prevFilters, ...newFilters };
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const defaultContext: EntityListContextProps = {
|
||||
entities: [],
|
||||
backendEntities: [],
|
||||
updateFilters: jest.fn(),
|
||||
filters: {},
|
||||
updateFilters: updateFilters,
|
||||
filters: filters,
|
||||
loading: false,
|
||||
};
|
||||
|
||||
// Extract value.filters to avoid overwriting it; some tests exercise filter updates. The value
|
||||
// provided is used as the initial seed in useState above.
|
||||
const { filters: _, ...otherContextFields } = value;
|
||||
|
||||
return (
|
||||
<EntityListContext.Provider value={{ ...defaultContext, ...value }}>
|
||||
<EntityListContext.Provider
|
||||
value={{ ...defaultContext, ...otherContextFields }}
|
||||
>
|
||||
{children}
|
||||
</EntityListContext.Provider>
|
||||
);
|
||||
|
||||
@@ -15,24 +15,26 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { fireEvent, render, waitFor } from '@testing-library/react';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import { capitalize } from 'lodash';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityTypePicker } from './EntityTypePicker';
|
||||
import { MockEntityListContextProvider } from '../../testUtils/providers';
|
||||
import { catalogApiRef } from '../../api';
|
||||
import { EntityKindFilter, EntityTypeFilter } from '../../filters';
|
||||
|
||||
import { TemplateTypePicker } from './TemplateTypePicker';
|
||||
import {
|
||||
catalogApiRef,
|
||||
EntityKindFilter,
|
||||
MockEntityListContextProvider,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { AlertApi, alertApiRef } from '@backstage/core-plugin-api';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
import { renderWithEffects } from '../../../../../packages/test-utils-core/src';
|
||||
|
||||
const entities: Entity[] = [
|
||||
{
|
||||
apiVersion: '1',
|
||||
kind: 'Component',
|
||||
kind: 'Template',
|
||||
metadata: {
|
||||
name: 'component-1',
|
||||
name: 'template-1',
|
||||
},
|
||||
spec: {
|
||||
type: 'service',
|
||||
@@ -40,9 +42,9 @@ const entities: Entity[] = [
|
||||
},
|
||||
{
|
||||
apiVersion: '1',
|
||||
kind: 'Component',
|
||||
kind: 'Template',
|
||||
metadata: {
|
||||
name: 'component-2',
|
||||
name: 'template-2',
|
||||
},
|
||||
spec: {
|
||||
type: 'website',
|
||||
@@ -50,9 +52,9 @@ const entities: Entity[] = [
|
||||
},
|
||||
{
|
||||
apiVersion: '1',
|
||||
kind: 'Component',
|
||||
kind: 'Template',
|
||||
metadata: {
|
||||
name: 'component-3',
|
||||
name: 'template-3',
|
||||
},
|
||||
spec: {
|
||||
type: 'library',
|
||||
@@ -77,58 +79,60 @@ const apis = ApiRegistry.from([
|
||||
],
|
||||
]);
|
||||
|
||||
describe('<EntityTypePicker/>', () => {
|
||||
describe('<TemplateTypePicker/>', () => {
|
||||
it('renders available entity types', async () => {
|
||||
const rendered = render(
|
||||
const rendered = await renderWithEffects(
|
||||
<ApiProvider apis={apis}>
|
||||
<MockEntityListContextProvider
|
||||
value={{ filters: { kind: new EntityKindFilter('component') } }}
|
||||
value={{
|
||||
filters: { kind: new EntityKindFilter('template') },
|
||||
backendEntities: entities,
|
||||
}}
|
||||
>
|
||||
<EntityTypePicker />
|
||||
<TemplateTypePicker />
|
||||
</MockEntityListContextProvider>
|
||||
</ApiProvider>,
|
||||
);
|
||||
expect(rendered.getByText('Type')).toBeInTheDocument();
|
||||
|
||||
const input = rendered.getByTestId('select');
|
||||
fireEvent.click(input);
|
||||
|
||||
await waitFor(() => rendered.getByText('Service'));
|
||||
expect(rendered.getByText('Categories')).toBeInTheDocument();
|
||||
|
||||
entities.forEach(entity => {
|
||||
expect(
|
||||
rendered.getByText(capitalize(entity.spec!.type as string)),
|
||||
rendered.getByLabelText(capitalize(entity.spec!.type as string)),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('sets the selected type filter', async () => {
|
||||
const updateFilters = jest.fn();
|
||||
const rendered = render(
|
||||
it('sets the selected type filters', async () => {
|
||||
const rendered = await renderWithEffects(
|
||||
<ApiProvider apis={apis}>
|
||||
<MockEntityListContextProvider
|
||||
value={{
|
||||
filters: { kind: new EntityKindFilter('component') },
|
||||
updateFilters,
|
||||
filters: { kind: new EntityKindFilter('template') },
|
||||
backendEntities: entities,
|
||||
}}
|
||||
>
|
||||
<EntityTypePicker />
|
||||
<TemplateTypePicker />
|
||||
</MockEntityListContextProvider>
|
||||
</ApiProvider>,
|
||||
);
|
||||
const input = rendered.getByTestId('select');
|
||||
fireEvent.click(input);
|
||||
|
||||
await waitFor(() => rendered.getByText('Service'));
|
||||
fireEvent.click(rendered.getByText('Service'));
|
||||
expect(rendered.getByLabelText('Service')).not.toBeChecked();
|
||||
expect(rendered.getByLabelText('Website')).not.toBeChecked();
|
||||
|
||||
expect(updateFilters).toHaveBeenLastCalledWith({
|
||||
type: new EntityTypeFilter('service'),
|
||||
});
|
||||
fireEvent.click(rendered.getByLabelText('Service'));
|
||||
expect(rendered.getByLabelText('Service')).toBeChecked();
|
||||
expect(rendered.getByLabelText('Website')).not.toBeChecked();
|
||||
|
||||
fireEvent.click(input);
|
||||
fireEvent.click(rendered.getByText('All'));
|
||||
fireEvent.click(rendered.getByLabelText('Website'));
|
||||
expect(rendered.getByLabelText('Service')).toBeChecked();
|
||||
expect(rendered.getByLabelText('Website')).toBeChecked();
|
||||
|
||||
expect(updateFilters).toHaveBeenLastCalledWith({ type: undefined });
|
||||
fireEvent.click(rendered.getByLabelText('Service'));
|
||||
expect(rendered.getByLabelText('Service')).not.toBeChecked();
|
||||
expect(rendered.getByLabelText('Website')).toBeChecked();
|
||||
|
||||
fireEvent.click(rendered.getByLabelText('Website'));
|
||||
expect(rendered.getByLabelText('Service')).not.toBeChecked();
|
||||
expect(rendered.getByLabelText('Website')).not.toBeChecked();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -76,7 +76,6 @@ export const TemplateTypePicker = () => {
|
||||
<Checkbox
|
||||
checked={selectedTypes.includes(type)}
|
||||
onChange={() => toggleSelection(type)}
|
||||
name={`entity-type-option-${type}`}
|
||||
className={classes.checkbox}
|
||||
/>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user