diff --git a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx index fa74b34717..fccf985f4f 100644 --- a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx @@ -123,7 +123,7 @@ describe('', () => { fireEvent.click(rendered.getByText('Service')); expect(updateFilters).toHaveBeenLastCalledWith({ - type: new EntityTypeFilter('service'), + type: new EntityTypeFilter(['service']), }); fireEvent.click(input); diff --git a/plugins/catalog-react/src/testUtils/providers.tsx b/plugins/catalog-react/src/testUtils/providers.tsx index 8678ae659c..5429e87ebd 100644 --- a/plugins/catalog-react/src/testUtils/providers.tsx +++ b/plugins/catalog-react/src/testUtils/providers.tsx @@ -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 }>) => { +}: PropsWithChildren<{ + value: Partial; +}>) => { + // Provides a default implementation that stores filter state, for testing components that + // reflect filter state. + const [filters, setFilters] = useState( + value.filters ?? {}, + ); + const updateFilters = useCallback( + ( + update: + | Partial + | (( + prevFilters: DefaultEntityFilters, + ) => Partial), + ) => { + 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 ( - + {children} ); diff --git a/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx b/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx index fa74b34717..baeefc7d99 100644 --- a/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx +++ b/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx @@ -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('', () => { +describe('', () => { it('renders available entity types', async () => { - const rendered = render( + const rendered = await renderWithEffects( - + , ); - 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( - + , ); - 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(); }); }); diff --git a/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.tsx b/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.tsx index d2658c0c1e..b547af6143 100644 --- a/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.tsx +++ b/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.tsx @@ -76,7 +76,6 @@ export const TemplateTypePicker = () => { toggleSelection(type)} - name={`entity-type-option-${type}`} className={classes.checkbox} /> }