Introduce initial TemplateTypePicker component in scaffolder
Co-authored-by: Tim Hansen <timbonicus@gmail.com> Co-authored-by: Chase Rutherford-Jenkins <chaseajen@users.noreply.github.com> Co-authored-by: Himanshu Mishra <himanshum@spotify.com> Co-authored-by: Joe Porpeglia <josephp@spotify.com> Signed-off-by: Mike Lewis <mtlewis@users.noreply.github.com>
This commit is contained in:
@@ -51,6 +51,7 @@
|
||||
"humanize-duration": "^3.25.1",
|
||||
"immer": "^9.0.1",
|
||||
"json-schema": "^0.3.0",
|
||||
"lodash": "^4.17.21",
|
||||
"luxon": "^1.25.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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 { fireEvent, render, waitFor } 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 { AlertApi, alertApiRef } from '@backstage/core-plugin-api';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
|
||||
const entities: Entity[] = [
|
||||
{
|
||||
apiVersion: '1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'component-1',
|
||||
},
|
||||
spec: {
|
||||
type: 'service',
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: '1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'component-2',
|
||||
},
|
||||
spec: {
|
||||
type: 'website',
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: '1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'component-3',
|
||||
},
|
||||
spec: {
|
||||
type: 'library',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const apis = ApiRegistry.from([
|
||||
[
|
||||
catalogApiRef,
|
||||
({
|
||||
getEntities: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve({ items: entities })),
|
||||
} as unknown) as CatalogApi,
|
||||
],
|
||||
[
|
||||
alertApiRef,
|
||||
({
|
||||
post: jest.fn(),
|
||||
} as unknown) as AlertApi,
|
||||
],
|
||||
]);
|
||||
|
||||
describe('<EntityTypePicker/>', () => {
|
||||
it('renders available entity types', async () => {
|
||||
const rendered = render(
|
||||
<ApiProvider apis={apis}>
|
||||
<MockEntityListContextProvider
|
||||
value={{ filters: { kind: new EntityKindFilter('component') } }}
|
||||
>
|
||||
<EntityTypePicker />
|
||||
</MockEntityListContextProvider>
|
||||
</ApiProvider>,
|
||||
);
|
||||
expect(rendered.getByText('Type')).toBeInTheDocument();
|
||||
|
||||
const input = rendered.getByTestId('select');
|
||||
fireEvent.click(input);
|
||||
|
||||
await waitFor(() => rendered.getByText('Service'));
|
||||
|
||||
entities.forEach(entity => {
|
||||
expect(
|
||||
rendered.getByText(capitalize(entity.spec!.type as string)),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('sets the selected type filter', async () => {
|
||||
const updateFilters = jest.fn();
|
||||
const rendered = render(
|
||||
<ApiProvider apis={apis}>
|
||||
<MockEntityListContextProvider
|
||||
value={{
|
||||
filters: { kind: new EntityKindFilter('component') },
|
||||
updateFilters,
|
||||
}}
|
||||
>
|
||||
<EntityTypePicker />
|
||||
</MockEntityListContextProvider>
|
||||
</ApiProvider>,
|
||||
);
|
||||
const input = rendered.getByTestId('select');
|
||||
fireEvent.click(input);
|
||||
|
||||
await waitFor(() => rendered.getByText('Service'));
|
||||
fireEvent.click(rendered.getByText('Service'));
|
||||
|
||||
expect(updateFilters).toHaveBeenLastCalledWith({
|
||||
type: new EntityTypeFilter('service'),
|
||||
});
|
||||
|
||||
fireEvent.click(input);
|
||||
fireEvent.click(rendered.getByText('All'));
|
||||
|
||||
expect(updateFilters).toHaveBeenLastCalledWith({ type: undefined });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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 {
|
||||
Typography,
|
||||
List,
|
||||
ListItem,
|
||||
makeStyles,
|
||||
Theme,
|
||||
Checkbox,
|
||||
ListItemText,
|
||||
} from '@material-ui/core';
|
||||
import { useEntityTypeFilter } from '@backstage/plugin-catalog-react';
|
||||
import { alertApiRef, useApi } from '@backstage/core-plugin-api';
|
||||
|
||||
const useStyles = makeStyles<Theme>(theme => ({
|
||||
checkbox: {
|
||||
padding: theme.spacing(0, 1, 0, 1),
|
||||
},
|
||||
}));
|
||||
|
||||
export const TemplateTypePicker = () => {
|
||||
const classes = useStyles();
|
||||
const alertApi = useApi(alertApiRef);
|
||||
// TODO(timbonicus): Use new setTypes returned from the hook
|
||||
const { error, types, selectedType } = useEntityTypeFilter();
|
||||
|
||||
if (!types) return null;
|
||||
|
||||
if (error) {
|
||||
alertApi.post({
|
||||
message: `Failed to load entity types`,
|
||||
severity: 'error',
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography variant="button">Categories</Typography>
|
||||
<List disablePadding dense>
|
||||
{types.map(type => {
|
||||
const labelId = `checkbox-list-label-${type}`;
|
||||
return (
|
||||
<ListItem
|
||||
key={type}
|
||||
dense
|
||||
button
|
||||
onClick={() => {}}
|
||||
// TODO(timbonicus): Update to use setTypes
|
||||
// setSelectedCategories(
|
||||
// selectedCategories.includes(type)
|
||||
// ? selectedCategories.filter(
|
||||
// selectedCategory => selectedCategory !== type,
|
||||
// )
|
||||
// : [...selectedCategories, type],
|
||||
// )
|
||||
// }
|
||||
>
|
||||
<Checkbox
|
||||
edge="start"
|
||||
color="primary"
|
||||
// TODO: Fix me
|
||||
// checked={selectedTypes.includes(type)}
|
||||
checked={type === selectedType}
|
||||
tabIndex={-1}
|
||||
disableRipple
|
||||
className={classes.checkbox}
|
||||
inputProps={{ 'aria-labelledby': labelId }}
|
||||
/>
|
||||
<ListItemText
|
||||
id={labelId}
|
||||
primary={
|
||||
type.charAt(0).toLocaleUpperCase('en-US') + type.slice(1)
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { TemplateTypePicker } from './TemplateTypePicker';
|
||||
Reference in New Issue
Block a user