diff --git a/.changeset/kind-jobs-remain.md b/.changeset/kind-jobs-remain.md new file mode 100644 index 0000000000..f41da42de8 --- /dev/null +++ b/.changeset/kind-jobs-remain.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +Added test coverage selectors to TemplateCard and its sub-components diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/CardLink.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/CardLink.tsx index 263a1356b7..4aa63e4555 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/CardLink.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/CardLink.tsx @@ -19,7 +19,7 @@ import { Link } from '@backstage/core-components'; import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; -interface CardLinkProps { +export interface CardLinkProps { icon: IconComponent; text: string; url: string; diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx index 5d2c8aa7fe..d8057b9867 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx @@ -15,67 +15,26 @@ */ import { RELATION_OWNED_BY } from '@backstage/catalog-model'; -import { MarkdownContent, UserIcon } from '@backstage/core-components'; -import { - IconComponent, - useAnalytics, - useApp, -} from '@backstage/core-plugin-api'; -import { - EntityRefLinks, - getEntityRelations, -} from '@backstage/plugin-catalog-react'; +import { IconComponent, useAnalytics } from '@backstage/core-plugin-api'; +import { getEntityRelations } from '@backstage/plugin-catalog-react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; -import Box from '@material-ui/core/Box'; import Card from '@material-ui/core/Card'; import CardActions from '@material-ui/core/CardActions'; import CardContent from '@material-ui/core/CardContent'; -import Chip from '@material-ui/core/Chip'; import Divider from '@material-ui/core/Divider'; -import Button from '@material-ui/core/Button'; import Grid from '@material-ui/core/Grid'; import { makeStyles, Theme } from '@material-ui/core/styles'; -import LanguageIcon from '@material-ui/icons/Language'; import React, { useCallback } from 'react'; import { CardHeader } from './CardHeader'; -import { CardLink } from './CardLink'; import { usePermission } from '@backstage/plugin-permission-react'; import { taskCreatePermission } from '@backstage/plugin-scaffolder-common/alpha'; +import { TemplateCardContent } from './TemplateCardContent'; +import { TemplateCardTags } from './TemplateCardTags'; +import { TemplateCardLinks } from './TemplateCardLinks'; +import { TemplateCardActions } from './TemplateCardActions'; -const useStyles = makeStyles(theme => ({ - box: { - overflow: 'hidden', - textOverflow: 'ellipsis', - display: '-webkit-box', - '-webkit-line-clamp': 10, - '-webkit-box-orient': 'vertical', - }, - markdown: { - /** to make the styles for React Markdown not leak into the description */ - '& :first-child': { - margin: 0, - }, - }, - label: { - color: theme.palette.text.secondary, - textTransform: 'uppercase', - fontWeight: 'bold', - letterSpacing: 0.5, - lineHeight: 1, - fontSize: '0.75rem', - }, - footer: { - display: 'flex', - justifyContent: 'space-between', - flex: 1, - alignItems: 'center', - }, - ownedBy: { - display: 'flex', - alignItems: 'center', - flex: 1, - color: theme.palette.link, - }, +const useStyles = makeStyles(() => ({ + actionContainer: { padding: '16px', flex: 1, alignItems: 'flex-end' }, })); /** @@ -89,7 +48,6 @@ export interface TemplateCardProps { text: string; url: string; }[]; - onSelected?: (template: TemplateEntityV1beta3) => void; } @@ -98,16 +56,13 @@ export interface TemplateCardProps { * @alpha */ export const TemplateCard = (props: TemplateCardProps) => { - const { onSelected, template } = props; + const { additionalLinks, onSelected, template } = props; const styles = useStyles(); const analytics = useAnalytics(); const ownedByRelations = getEntityRelations(template, RELATION_OWNED_BY); - const app = useApp(); - const iconResolver = (key?: string): IconComponent => - key ? app.getSystemIcon(key) ?? LanguageIcon : LanguageIcon; const hasTags = !!template.metadata.tags?.length; const hasLinks = - !!props.additionalLinks?.length || !!template.metadata.links?.length; + !!additionalLinks?.length || !!template.metadata.links?.length; const displayDefaultDivider = !hasTags && !hasLinks; const { allowed: canCreateTask } = usePermission({ @@ -120,98 +75,33 @@ export const TemplateCard = (props: TemplateCardProps) => { return ( - + - - - - - - + + {displayDefaultDivider && ( )} - {hasTags && ( - <> - - - - - - {template.metadata.tags?.map(tag => ( - - - - ))} - - - - )} + {hasTags && } {hasLinks && ( - <> - - - - - - {props.additionalLinks?.map(({ icon, text, url }, index) => ( - - - - ))} - {template.metadata.links?.map( - ({ url, icon, title }, index) => ( - - - - ), - )} - - - + )} - -
-
- {ownedByRelations.length > 0 && ( - <> - - - - )} -
- {canCreateTask ? ( - - ) : null} -
+ +
); diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCardActions.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCardActions.tsx new file mode 100644 index 0000000000..e8a84487df --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCardActions.tsx @@ -0,0 +1,86 @@ +/* + * Copyright 2022 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 { UserIcon } from '@backstage/core-components'; +import { EntityRefLinks } from '@backstage/plugin-catalog-react'; +import Button from '@material-ui/core/Button'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import React from 'react'; + +const useStyles = makeStyles(theme => ({ + footer: { + display: 'flex', + justifyContent: 'space-between', + flex: 1, + alignItems: 'center', + }, + ownedBy: { + display: 'flex', + alignItems: 'center', + flex: 1, + color: theme.palette.link, + }, + actionContainer: { padding: '16px', flex: 1, alignItems: 'flex-end' }, +})); + +/** + * The Props for the {@link TemplateCardActions} component + * @alpha + */ +export interface TemplateCardActionsProps { + ownedByRelations: any; + canCreateTask: boolean; + handleChoose: () => void; +} +export const TemplateCardActions = ({ + canCreateTask, + handleChoose, + ownedByRelations, +}: TemplateCardActionsProps) => { + const styles = useStyles(); + + return ( +
+
+ {ownedByRelations.length > 0 && ( + <> + + + + )} +
+ {canCreateTask ? ( + + ) : null} +
+ ); +}; diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCardContent.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCardContent.tsx new file mode 100644 index 0000000000..fad5c85474 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCardContent.tsx @@ -0,0 +1,59 @@ +/* + * Copyright 2022 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 { MarkdownContent } from '@backstage/core-components'; +import type { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { makeStyles } from '@material-ui/core/styles'; +import Box from '@material-ui/core/Box'; +import Grid from '@material-ui/core/Grid'; +import React from 'react'; + +const useStyles = makeStyles(() => ({ + box: { + overflow: 'hidden', + textOverflow: 'ellipsis', + display: '-webkit-box', + '-webkit-line-clamp': 10, + '-webkit-box-orient': 'vertical', + }, + markdown: { + /** to make the styles for React Markdown not leak into the description */ + '& :first-child': { + margin: 0, + }, + }, +})); + +/** + * The Props for the {@link TemplateCardContent} component + * @alpha + */ +export interface TemplateCardContentProps { + template: TemplateEntityV1beta3; +} +export const TemplateCardContent = ({ template }: TemplateCardContentProps) => { + const styles = useStyles(); + return ( + + + + + + ); +}; diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCardLinks.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCardLinks.tsx new file mode 100644 index 0000000000..f626875818 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCardLinks.tsx @@ -0,0 +1,85 @@ +/* + * Copyright 2022 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 { IconComponent, useApp } from '@backstage/core-plugin-api'; +import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import Divider from '@material-ui/core/Divider'; +import Grid from '@material-ui/core/Grid'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import LanguageIcon from '@material-ui/icons/Language'; +import React from 'react'; +import { CardLink } from './CardLink'; + +const useStyles = makeStyles({}); + +/** + * The Props for the {@link TemplateCardLinks} component + * @alpha + */ +export interface TemplateCardLinksProps { + template: TemplateEntityV1beta3; + additionalLinks?: { + icon: IconComponent; + text: string; + url: string; + }[]; +} +export const TemplateCardLinks = ({ + template, + additionalLinks, +}: TemplateCardLinksProps) => { + const styles = useStyles(); + const app = useApp(); + const iconResolver = (key?: string): IconComponent => + key ? app.getSystemIcon(key) ?? LanguageIcon : LanguageIcon; + return ( + <> + + + + + + {additionalLinks?.map(({ icon, text, url }, index) => ( + + + + ))} + {template.metadata.links?.map(({ url, icon, title }, index) => ( + + + + ))} + + + + ); +}; diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCardTags.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCardTags.tsx new file mode 100644 index 0000000000..88550e2104 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCardTags.tsx @@ -0,0 +1,55 @@ +/* + * Copyright 2022 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 type { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import Chip from '@material-ui/core/Chip'; +import Divider from '@material-ui/core/Divider'; +import Grid from '@material-ui/core/Grid'; +import React from 'react'; + +/** + * The Props for the {@link TemplateCardTags} component + * @alpha + */ +export interface TemplateCardTagsProps { + template: TemplateEntityV1beta3; +} +export const TemplateCardTags = ({ template }: TemplateCardTagsProps) => ( + <> + + + + + + {template.metadata.tags?.map(tag => ( + + + + ))} + + + +);