Fix TypePicker tests

Signed-off-by: Tim Hansen <timbonicus@gmail.com>
This commit is contained in:
Tim Hansen
2021-06-29 10:36:25 -06:00
parent 315deb8544
commit d31c048fab
4 changed files with 80 additions and 46 deletions
@@ -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}
/>
}