From 47f10d2496f0c2f0d7434be9435629265ba1d449 Mon Sep 17 00:00:00 2001 From: Titani Date: Wed, 31 Jan 2024 18:38:56 -0500 Subject: [PATCH 1/2] feat(Card): Consume penta tokens --- .../react-core/src/components/Card/Card.tsx | 79 +-------- .../src/components/Card/CardHeader.tsx | 8 +- .../components/Card/__tests__/Card.test.tsx | 128 +-------------- .../src/components/Card/examples/Card.md | 51 ++---- .../Card/examples/CardClickable.tsx | 106 +++++++----- .../Card/examples/CardClickableSelectable.tsx | 152 +++++++++++------- .../examples/CardDeprecatedSelectable.tsx | 127 --------------- .../CardDeprecatedSelectableA11yHighlight.tsx | 61 ------- .../Card/examples/CardExpandableWithIcon.tsx | 2 +- .../Card/examples/CardSecondary.tsx | 10 ++ .../Card/examples/CardSelectable.tsx | 107 ++++++------ .../Card/examples/CardSingleSelectable.tsx | 6 +- .../Card/examples/CardWithDividers.tsx | 14 ++ .../Card/examples/CardWithImageAndActions.tsx | 36 ++--- .../Card/examples/CardWithModifiers.tsx | 1 - .../examples/Card/CardHorizontalSplit.tsx | 2 +- .../examples/Tabs/NestedUnindentedTabs.tsx | 6 +- .../cypress/integration/card.spec.ts | 11 -- .../components/demos/CardDemo/CardDemo.tsx | 15 +- 19 files changed, 299 insertions(+), 623 deletions(-) delete mode 100644 packages/react-core/src/components/Card/examples/CardDeprecatedSelectable.tsx delete mode 100644 packages/react-core/src/components/Card/examples/CardDeprecatedSelectableA11yHighlight.tsx create mode 100644 packages/react-core/src/components/Card/examples/CardSecondary.tsx create mode 100644 packages/react-core/src/components/Card/examples/CardWithDividers.tsx diff --git a/packages/react-core/src/components/Card/Card.tsx b/packages/react-core/src/components/Card/Card.tsx index dcf4ba2580d..000b77cfa15 100644 --- a/packages/react-core/src/components/Card/Card.tsx +++ b/packages/react-core/src/components/Card/Card.tsx @@ -16,20 +16,12 @@ export interface CardProps extends React.HTMLProps, OUIAProps { isCompact?: boolean; /** Modifies the card to include selectable styling */ isSelectable?: boolean; - /** @deprecated Specifies the card is selectable, and applies raised styling on hover and select */ - isSelectableRaised?: boolean; /** Modifies the card to include selected styling */ isSelected?: boolean; /** Modifies the card to include clickable styling */ isClickable?: boolean; /** Modifies a clickable or selectable card to have disabled styling. */ isDisabled?: boolean; - /** @deprecated Modifies a raised selectable card to have disabled styling */ - isDisabledRaised?: boolean; - /** Modifies the card to include flat styling */ - isFlat?: boolean; - /** Modifies the card to include rounded styling */ - isRounded?: boolean; /** Modifies the card to be large. Should not be used with isCompact. */ isLarge?: boolean; /** Cause component to consume the available height of its container */ @@ -38,12 +30,8 @@ export interface CardProps extends React.HTMLProps, OUIAProps { isPlain?: boolean; /** Flag indicating if a card is expanded. Modifies the card to be expandable. */ isExpanded?: boolean; - /** @deprecated Flag indicating that the card should render a hidden input to make it selectable */ - hasSelectableInput?: boolean; - /** @deprecated Aria label to apply to the selectable input if one is rendered */ - selectableInputAriaLabel?: string; - /** @deprecated Callback that executes when the selectable input is changed */ - onSelectableInputChange?: (event: React.FormEvent, labelledBy: string) => void; + /** Card background color variant */ + variant?: 'default' | 'secondary'; /** Value to overwrite the randomly generated data-ouia-component-id.*/ ouiaId?: number | string; /** Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false. */ @@ -57,13 +45,6 @@ interface CardContextProps { isClickable: boolean; isSelectable: boolean; isDisabled: boolean; - // TODO: Remove hasSelectableInput when deprecated prop is removed - hasSelectableInput: boolean; -} - -interface AriaProps { - 'aria-label'?: string; - 'aria-labelledby'?: string; } export const CardContext = React.createContext>({ @@ -84,28 +65,19 @@ export const Card: React.FunctionComponent = ({ isSelectable = false, isClickable = false, isDisabled = false, - isSelectableRaised = false, isSelected = false, - isDisabledRaised = false, - // TODO: Update with issue #9991 - // isFlat = false, isExpanded = false, - // TODO: Update with issue #9991 - // isRounded = false, isLarge = false, isFullHeight = false, isPlain = false, + variant = 'default', ouiaId, ouiaSafe = true, - hasSelectableInput = false, - selectableInputAriaLabel, - onSelectableInputChange = () => {}, + ...props }: CardProps) => { const Component = component as any; const ouiaProps = useOUIAProps(Card.displayName, ouiaId, ouiaSafe); - const [titleId, setTitleId] = React.useState(''); - const [ariaProps, setAriaProps] = React.useState(); if (isCompact && isLarge) { // eslint-disable-next-line no-console @@ -114,13 +86,6 @@ export const Card: React.FunctionComponent = ({ } const getSelectableModifiers = () => { - // TODO: Update with issue #9991 - // if (isDisabledRaised) { - // return css(styles.modifiers.nonSelectableRaised); - // } - // if (isSelectableRaised) { - // return css(styles.modifiers.selectableRaised, isSelected && styles.modifiers.selectedRaised); - // } if (isSelectable && isClickable) { return css(styles.modifiers.selectable, styles.modifiers.clickable, isSelected && styles.modifiers.current); } @@ -139,24 +104,9 @@ export const Card: React.FunctionComponent = ({ const containsCardTitleChildRef = React.useRef(false); const registerTitleId = (id: string) => { - setTitleId(id); containsCardTitleChildRef.current = !!id; }; - React.useEffect(() => { - if (selectableInputAriaLabel) { - setAriaProps({ 'aria-label': selectableInputAriaLabel }); - } else if (titleId) { - setAriaProps({ 'aria-labelledby': titleId }); - } else if (hasSelectableInput && !containsCardTitleChildRef.current) { - setAriaProps({}); - // eslint-disable-next-line no-console - console.warn( - 'If no CardTitle component is passed as a child of Card the selectableInputAriaLabel prop must be passed' - ); - } - }, [hasSelectableInput, selectableInputAriaLabel, titleId]); - return ( = ({ isExpanded, isClickable, isSelectable, - isDisabled, - // TODO: Remove hasSelectableInput when deprecated prop is removed - hasSelectableInput + isDisabled }} > - {hasSelectableInput && ( - onSelectableInputChange(event, id)} - disabled={isDisabledRaised} - tabIndex={-1} - /> - )} diff --git a/packages/react-core/src/components/Card/CardHeader.tsx b/packages/react-core/src/components/Card/CardHeader.tsx index c8b34353b34..3eaada1d828 100644 --- a/packages/react-core/src/components/Card/CardHeader.tsx +++ b/packages/react-core/src/components/Card/CardHeader.tsx @@ -79,8 +79,7 @@ export const CardHeader: React.FunctionComponent = ({ ...props }: CardHeaderProps) => ( - {/* TODO: Remove hasSelectableInput when deprecated props are removed */} - {({ cardId, isClickable, isSelectable, isDisabled: isCardDisabled, hasSelectableInput }) => { + {({ cardId, isClickable, isSelectable, isDisabled: isCardDisabled }) => { const cardHeaderToggle = (
- - - This card performs an action upon clicking the card title and is selectable. - - - - Second Card - - - This card is selectable and has a link in the card body that navigates to{' '} - - . - - - - - - - - - This card is clickable and selectable, but disabled. - - + <> + toggleVariant(checked)} + aria-label="add secondary styling" + id="toggle-variant-clickable-selectable" + name="toggle-variant" + /> +
+ + + + + + + + This card performs an action upon clicking the card title and is selectable. + + + + Second Card + + + This card is selectable and has a link in the card body that navigates to{' '} + + . + + + + + + + + + This card is clickable and selectable, but disabled. + + +
+ ); }; diff --git a/packages/react-core/src/components/Card/examples/CardDeprecatedSelectable.tsx b/packages/react-core/src/components/Card/examples/CardDeprecatedSelectable.tsx deleted file mode 100644 index a3c9083a3c5..00000000000 --- a/packages/react-core/src/components/Card/examples/CardDeprecatedSelectable.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import React from 'react'; -import { - Card, - CardHeader, - CardTitle, - CardBody, - Dropdown, - DropdownList, - DropdownItem, - MenuToggle, - MenuToggleElement, - Divider -} from '@patternfly/react-core'; -import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; - -export const CardLegacySelectable: React.FunctionComponent = () => { - const [selected, setSelected] = React.useState(''); - const [isKebabOpen, setIsKebabOpen] = React.useState(false); - - const onKeyDown = (event: React.KeyboardEvent) => { - if (event.target !== event.currentTarget) { - return; - } - if (['Enter', ' '].includes(event.key)) { - event.preventDefault(); - const newSelected = event.currentTarget.id === selected ? '' : event.currentTarget.id; - setSelected(newSelected); - } - }; - - const onClick = (event: React.MouseEvent) => { - const newSelected = event.currentTarget.id === selected ? '' : event.currentTarget.id; - setSelected(newSelected); - }; - - const onChange = (_event: React.FormEvent, labelledById: string) => { - const newSelected = labelledById === selected ? '' : labelledById; - setSelected(newSelected); - }; - - const onToggle = (event: React.MouseEvent) => { - event?.stopPropagation(); - setIsKebabOpen(!isKebabOpen); - }; - - const onSelect = (event: React.MouseEvent | undefined) => { - event?.stopPropagation(); - setIsKebabOpen(!isKebabOpen); - }; - - const dropdownItems = ( - <> - Action - {/* Prevent default onClick functionality for example purposes */} - event.preventDefault()}> - Link - - - Disabled Action - - event.preventDefault()}> - Disabled Link - - - Separated Action - event.preventDefault()}> - Separated Link - - - ); - - const headerActions = ( - <> - ) => ( - - - )} - isOpen={isKebabOpen} - onOpenChange={(isOpen: boolean) => setIsKebabOpen(isOpen)} - > - {dropdownItems} - - - ); - - return ( - <> - - - First legacy selectable card - This is a selectable card. Click me to select me. Click again to deselect me. - -
- - Second legacy selectable card - This is a selectable card. Click me to select me. Click again to deselect me. - - - ); -}; diff --git a/packages/react-core/src/components/Card/examples/CardDeprecatedSelectableA11yHighlight.tsx b/packages/react-core/src/components/Card/examples/CardDeprecatedSelectableA11yHighlight.tsx deleted file mode 100644 index 5ed107335e9..00000000000 --- a/packages/react-core/src/components/Card/examples/CardDeprecatedSelectableA11yHighlight.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import React from 'react'; -import { Card, CardTitle, CardBody } from '@patternfly/react-core'; - -export const CardLegacySelectableA11yHighlight: React.FunctionComponent = () => { - const [selected, setSelected] = React.useState(''); - - const onKeyDown = (event: React.KeyboardEvent) => { - if (event.target !== event.currentTarget) { - return; - } - if ([' ', 'Enter'].includes(event.key)) { - event.preventDefault(); - const newSelected = event.currentTarget.id === selected ? '' : event.currentTarget.id; - setSelected(newSelected); - } - }; - - const onClick = (event: React.MouseEvent) => { - const newSelected = event.currentTarget.id === selected ? '' : event.currentTarget.id; - setSelected(newSelected); - }; - - const onChange = (_event: React.FormEvent, labelledById: string) => { - const newSelected = labelledById === selected ? '' : labelledById; - setSelected(newSelected); - }; - - return ( - - - Selectable card with proper accessibility considerations - - When using a screen reader a checkbox will become navigable that indicates this card is selectable and - communicate if it is currently selected. - - -
- - Selectable card without proper accessibility considerations - - When using a screen reader there are no indications that this card is selectable or if it is currently - selected. - - -
- ); -}; diff --git a/packages/react-core/src/components/Card/examples/CardExpandableWithIcon.tsx b/packages/react-core/src/components/Card/examples/CardExpandableWithIcon.tsx index 2d19f70010d..691282989f3 100644 --- a/packages/react-core/src/components/Card/examples/CardExpandableWithIcon.tsx +++ b/packages/react-core/src/components/Card/examples/CardExpandableWithIcon.tsx @@ -13,7 +13,7 @@ import { MenuToggle, MenuToggleElement } from '@patternfly/react-core'; -import pfLogoSmall from '../../assets/pf-c-brand--logo-on-sm.svg'; +import pfLogoSmall from '../../PF-IconLogo.svg'; import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; export const CardExpandableWithIcon: React.FunctionComponent = () => { diff --git a/packages/react-core/src/components/Card/examples/CardSecondary.tsx b/packages/react-core/src/components/Card/examples/CardSecondary.tsx new file mode 100644 index 00000000000..7efa4fd9c2e --- /dev/null +++ b/packages/react-core/src/components/Card/examples/CardSecondary.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { Card, CardTitle, CardBody, CardFooter } from '@patternfly/react-core'; + +export const CardSecondary: React.FunctionComponent = () => ( + + Title + Body + Footer + +); diff --git a/packages/react-core/src/components/Card/examples/CardSelectable.tsx b/packages/react-core/src/components/Card/examples/CardSelectable.tsx index a9de63b669d..413977da3de 100644 --- a/packages/react-core/src/components/Card/examples/CardSelectable.tsx +++ b/packages/react-core/src/components/Card/examples/CardSelectable.tsx @@ -1,10 +1,11 @@ import React from 'react'; -import { Card, CardHeader, CardTitle, CardBody } from '@patternfly/react-core'; +import { Card, CardHeader, CardTitle, CardBody, Checkbox, Gallery } from '@patternfly/react-core'; export const SelectableCard: React.FunctionComponent = () => { const [isChecked1, setIsChecked1] = React.useState(false); const [isChecked2, setIsChecked2] = React.useState(false); const [isChecked3, setIsChecked3] = React.useState(false); + const [isSecondary, setIsSecondary] = React.useState(false); const id1 = 'selectable-card-input-1'; const id2 = 'selectable-card-input-2'; @@ -26,50 +27,66 @@ export const SelectableCard: React.FunctionComponent = () => { } }; + const toggleVariant = (checked: boolean) => { + setIsSecondary(checked); + }; + return ( - - - - First card - - This card is selectable. - - - - Second card - - This card is selectable. - - - - Third card - - This card is selectable but disabled. - - + <> + toggleVariant(checked)} + aria-label="add secondary styling" + id="toggle-variant-selectable" + name="toggle-variant" + /> +
+ + + + First card + + This card is selectable. + + + + Second card + + This card is selectable. + + + + Third card + + This card is selectable but disabled. + + +
+ ); }; diff --git a/packages/react-core/src/components/Card/examples/CardSingleSelectable.tsx b/packages/react-core/src/components/Card/examples/CardSingleSelectable.tsx index 6279ac1f6d3..18854d98d4f 100644 --- a/packages/react-core/src/components/Card/examples/CardSingleSelectable.tsx +++ b/packages/react-core/src/components/Card/examples/CardSingleSelectable.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Card, CardHeader, CardTitle, CardBody } from '@patternfly/react-core'; +import { Card, CardHeader, CardTitle, CardBody, Gallery } from '@patternfly/react-core'; export const SingleSelectableCard: React.FunctionComponent = () => { const id1 = 'single-selectable-card-input-1'; @@ -7,7 +7,7 @@ export const SingleSelectableCard: React.FunctionComponent = () => { const id3 = 'single-selectable-card-input-3'; return ( - + { This card is single selectable but disabled. - + ); }; diff --git a/packages/react-core/src/components/Card/examples/CardWithDividers.tsx b/packages/react-core/src/components/Card/examples/CardWithDividers.tsx new file mode 100644 index 00000000000..4d15e87dd44 --- /dev/null +++ b/packages/react-core/src/components/Card/examples/CardWithDividers.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { Card, CardTitle, CardBody, CardFooter, Divider } from '@patternfly/react-core'; + +export const CardWithDividers: React.FunctionComponent = () => ( + + Title + + Body + + Body + + Footer + +); diff --git a/packages/react-core/src/components/Card/examples/CardWithImageAndActions.tsx b/packages/react-core/src/components/Card/examples/CardWithImageAndActions.tsx index bc7e7e54012..867d0310b38 100644 --- a/packages/react-core/src/components/Card/examples/CardWithImageAndActions.tsx +++ b/packages/react-core/src/components/Card/examples/CardWithImageAndActions.tsx @@ -15,7 +15,7 @@ import { Divider } from '@patternfly/react-core'; import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; -import pfLogo from '../../assets/pfLogo.svg'; +import pfLogo from '../../assets/PF-HorizontalLogo-Color.svg'; export const CardWithImageAndActions: React.FunctionComponent = () => { const [isOpen, setIsOpen] = React.useState(false); @@ -85,23 +85,23 @@ export const CardWithImageAndActions: React.FunctionComponent = () => { return ( <> - - - - - Title - Body - Footer - -
- toggleOffset(checked)} - aria-label="remove actions offset" - id="toggle-actions-offset" - name="toggle-actions-offset" - /> + toggleOffset(checked)} + aria-label="remove actions offset" + id="toggle-actions-offset" + name="toggle-actions-offset" + /> +
+ + + + + Title + Body + Footer +
); diff --git a/packages/react-core/src/components/Card/examples/CardWithModifiers.tsx b/packages/react-core/src/components/Card/examples/CardWithModifiers.tsx index 051166695ae..7332ace1036 100644 --- a/packages/react-core/src/components/Card/examples/CardWithModifiers.tsx +++ b/packages/react-core/src/components/Card/examples/CardWithModifiers.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { Card, CardTitle, CardBody, CardFooter, Checkbox } from '@patternfly/react-core'; export const CardWithModifiers: React.FunctionComponent = () => { - // TODO: Update with issue #9991 removed isFlat and isRounded const mods = ['isCompact', 'isLarge', 'isFullHeight', 'isPlain']; const [modifiers, setModifiers] = React.useState({}); diff --git a/packages/react-core/src/demos/examples/Card/CardHorizontalSplit.tsx b/packages/react-core/src/demos/examples/Card/CardHorizontalSplit.tsx index 51a2e773089..23496e5ecf5 100644 --- a/packages/react-core/src/demos/examples/Card/CardHorizontalSplit.tsx +++ b/packages/react-core/src/demos/examples/Card/CardHorizontalSplit.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { Card, CardTitle, CardBody, CardFooter, Grid, GridItem, Button } from '@patternfly/react-core'; export const CardHorizontalSplitDemo: React.FunctionComponent = () => ( - + { - + Check system requirements Your physical or virtual machine should meet the system requirement. - + Download an installation ISO image {' '} Download the binary DVD ISO. - + Create a bootable installation media {' '} diff --git a/packages/react-integration/cypress/integration/card.spec.ts b/packages/react-integration/cypress/integration/card.spec.ts index d554a39a1dd..26fda00fc81 100644 --- a/packages/react-integration/cypress/integration/card.spec.ts +++ b/packages/react-integration/cypress/integration/card.spec.ts @@ -23,17 +23,6 @@ describe('Card Demo Test', () => { cy.focused().should('not.have.class', 'pf-m-selected'); }); - // TODO: update it issue #9991 - xit('Verify that selectableRaised card can be selected and unselected with keyboard input', () => { - cy.get('#selectableCardRaised').focus(); - cy.focused().should('have.class', 'pf-m-selectable-raised'); - cy.focused().should('not.have.class', 'pf-m-selected-raised'); - cy.focused().type('{enter}'); - cy.focused().should('have.class', 'pf-m-selected-raised'); - cy.focused().type('{enter}'); - cy.focused().should('not.have.class', 'pf-m-selected-raised'); - }); - it('Verify card is expandable', () => { cy.get('#expand-card').should('not.have.class', 'pf-m-expanded'); cy.get('#expand-card .pf-v5-c-card__header').should('have.class', 'pf-m-toggle-right'); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/CardDemo/CardDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/CardDemo/CardDemo.tsx index 8fe5068157e..717c7c42b96 100644 --- a/packages/react-integration/demo-app-ts/src/components/demos/CardDemo/CardDemo.tsx +++ b/packages/react-integration/demo-app-ts/src/components/demos/CardDemo/CardDemo.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Component } from 'react'; import { Brand, Button, @@ -32,7 +32,7 @@ interface CardDemoState { selectaleClickableDrawerIsExpanded: boolean; } -export class CardDemo extends React.Component { +export class CardDemo extends Component { static displayName = 'CardDemo'; state: CardDemoState = { @@ -168,17 +168,6 @@ export class CardDemo extends React.Component { Footer

- - Header - Body - Footer - -

Header From 22d9dd3abbe5d16409007af5bf6f1655c02feb94 Mon Sep 17 00:00:00 2001 From: Titani Date: Tue, 13 Feb 2024 09:30:32 -0500 Subject: [PATCH 2/2] removed registerTitleId --- packages/react-core/src/components/Card/Card.tsx | 9 --------- .../react-core/src/components/Card/CardTitle.tsx | 8 +------- .../components/Card/__tests__/CardTitle.test.tsx | 13 ------------- 3 files changed, 1 insertion(+), 29 deletions(-) diff --git a/packages/react-core/src/components/Card/Card.tsx b/packages/react-core/src/components/Card/Card.tsx index 000b77cfa15..08ec332a5a0 100644 --- a/packages/react-core/src/components/Card/Card.tsx +++ b/packages/react-core/src/components/Card/Card.tsx @@ -40,7 +40,6 @@ export interface CardProps extends React.HTMLProps, OUIAProps { interface CardContextProps { cardId: string; - registerTitleId: (id: string) => void; isExpanded: boolean; isClickable: boolean; isSelectable: boolean; @@ -49,7 +48,6 @@ interface CardContextProps { export const CardContext = React.createContext>({ cardId: '', - registerTitleId: () => {}, isExpanded: false, isClickable: false, isSelectable: false, @@ -101,17 +99,10 @@ export const Card: React.FunctionComponent = ({ return ''; }; - const containsCardTitleChildRef = React.useRef(false); - - const registerTitleId = (id: string) => { - containsCardTitleChildRef.current = !!id; - }; - return ( = ({ component = 'div', ...props }: CardTitleProps) => { - const { cardId, registerTitleId } = React.useContext(CardContext); + const { cardId } = React.useContext(CardContext); const Component = component as any; const titleId = cardId ? `${cardId}-title` : ''; - React.useEffect(() => { - registerTitleId(titleId); - - return () => registerTitleId(''); - }, [registerTitleId, titleId]); - return (
diff --git a/packages/react-core/src/components/Card/__tests__/CardTitle.test.tsx b/packages/react-core/src/components/Card/__tests__/CardTitle.test.tsx index 2b7f43ec8da..0aa55985b51 100644 --- a/packages/react-core/src/components/Card/__tests__/CardTitle.test.tsx +++ b/packages/react-core/src/components/Card/__tests__/CardTitle.test.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import { CardTitle } from '../CardTitle'; -import { CardContext } from '../Card'; describe('CardTitle', () => { test('renders with PatternFly Core styles', () => { @@ -20,16 +19,4 @@ describe('CardTitle', () => { render(); expect(screen.getByTestId(testId)).toBeInTheDocument(); }); - - test('calls the registerTitleId function provided by the CardContext with the generated title id', () => { - const mockRegisterTitleId = jest.fn(); - - render( - - text - - ); - - expect(mockRegisterTitleId).toHaveBeenCalledWith('card-title'); - }); });