From 5623a502ebf88c35d27452ada396d26ebd3dcc93 Mon Sep 17 00:00:00 2001
From: Connie Liu <139280159+coliu-akamai@users.noreply.github.com>
Date: Tue, 5 Dec 2023 16:36:40 -0500
Subject: [PATCH] refactor: [M3-7532] - Payment Method Row Storybook v7 Story
(#9958)
* props and export cleanup
* add tests, start story
* starting story
* stories for storybook
* update comments
* Added changeset: Payment Method Row V7 story migration
* address feedback
* update key
* feedback
---
.../pr-9958-tech-stories-1701721635562.md | 5 +
.../DeletePaymentMethodDialog.test.tsx | 46 +++++++
.../DeletePaymentMethodDialog.tsx | 14 +-
.../PaymentMethodRow.stories.mdx | 130 ------------------
.../PaymentMethodRow.stories.tsx | 78 +++++++++++
.../PaymentMethodRow.test.tsx | 2 +-
.../PaymentMethodRow/PaymentMethodRow.tsx | 16 ++-
.../ThirdPartyPayment.test.tsx | 2 +-
.../PaymentMethodRow/ThirdPartyPayment.tsx | 23 ++--
.../src/components/PaymentMethodRow/index.ts | 1 -
.../PaymentInfoPanel/PaymentInformation.tsx | 2 +-
.../PaymentInfoPanel/PaymentMethods.tsx | 2 +-
12 files changed, 163 insertions(+), 158 deletions(-)
create mode 100644 packages/manager/.changeset/pr-9958-tech-stories-1701721635562.md
create mode 100644 packages/manager/src/components/PaymentMethodRow/DeletePaymentMethodDialog.test.tsx
delete mode 100644 packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.stories.mdx
create mode 100644 packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.stories.tsx
delete mode 100644 packages/manager/src/components/PaymentMethodRow/index.ts
diff --git a/packages/manager/.changeset/pr-9958-tech-stories-1701721635562.md b/packages/manager/.changeset/pr-9958-tech-stories-1701721635562.md
new file mode 100644
index 00000000000..fc782cdad4e
--- /dev/null
+++ b/packages/manager/.changeset/pr-9958-tech-stories-1701721635562.md
@@ -0,0 +1,5 @@
+---
+"@linode/manager": Tech Stories
+---
+
+Payment Method Row V7 story migration ([#9958](https://github.com/linode/manager/pull/9958))
diff --git a/packages/manager/src/components/PaymentMethodRow/DeletePaymentMethodDialog.test.tsx b/packages/manager/src/components/PaymentMethodRow/DeletePaymentMethodDialog.test.tsx
new file mode 100644
index 00000000000..8d9f0cc9d47
--- /dev/null
+++ b/packages/manager/src/components/PaymentMethodRow/DeletePaymentMethodDialog.test.tsx
@@ -0,0 +1,46 @@
+import { fireEvent } from '@testing-library/react';
+import * as React from 'react';
+
+import { renderWithTheme } from 'src/utilities/testHelpers';
+
+import { DeletePaymentMethodDialog } from './DeletePaymentMethodDialog';
+
+const props = {
+ error: 'some error',
+ loading: false,
+ onClose: vi.fn(),
+ onDelete: vi.fn(),
+ open: true,
+ paymentMethod: undefined,
+};
+
+describe('Delete Payment Method Dialog', () => {
+ it('renders the delete payment method dialog', () => {
+ const screen = renderWithTheme();
+
+ const headerText = screen.getByText('Delete Payment Method');
+ expect(headerText).toBeVisible();
+
+ const deleteText = screen.getByText(
+ 'Are you sure you want to delete this payment method?'
+ );
+ expect(deleteText).toBeVisible();
+
+ const buttons = screen.getAllByRole('button');
+ expect(buttons?.length).toBe(3);
+ });
+
+ it('calls the corresponding functions when buttons are clicked', () => {
+ const screen = renderWithTheme();
+
+ const deleteButton = screen.getByText('Delete');
+ expect(deleteButton).toBeVisible();
+ fireEvent.click(deleteButton);
+ expect(props.onDelete).toHaveBeenCalled();
+
+ const cancelButton = screen.getByText('Cancel');
+ expect(cancelButton).toBeVisible();
+ fireEvent.click(cancelButton);
+ expect(props.onClose).toHaveBeenCalled();
+ });
+});
diff --git a/packages/manager/src/components/PaymentMethodRow/DeletePaymentMethodDialog.tsx b/packages/manager/src/components/PaymentMethodRow/DeletePaymentMethodDialog.tsx
index 8b60bd420a9..204e2050e3a 100644
--- a/packages/manager/src/components/PaymentMethodRow/DeletePaymentMethodDialog.tsx
+++ b/packages/manager/src/components/PaymentMethodRow/DeletePaymentMethodDialog.tsx
@@ -1,16 +1,16 @@
import { PaymentMethod } from '@linode/api-v4/lib/account/types';
import { Theme } from '@mui/material/styles';
-import { makeStyles } from '@mui/styles';
import * as React from 'react';
+import { makeStyles } from 'tss-react/mui';
import { ConfirmationDialog } from 'src/components/ConfirmationDialog/ConfirmationDialog';
import CreditCard from 'src/features/Billing/BillingPanels/BillingSummary/PaymentDrawer/CreditCard';
import { ActionsPanel } from '../ActionsPanel/ActionsPanel';
import { Grid } from '../Grid';
-import ThirdPartyPayment from './ThirdPartyPayment';
+import { ThirdPartyPayment } from './ThirdPartyPayment';
-export const useStyles = makeStyles((theme: Theme) => ({
+export const useStyles = makeStyles()((theme: Theme) => ({
container: {
flexWrap: 'nowrap',
marginTop: theme.spacing(1),
@@ -30,9 +30,9 @@ interface Props {
paymentMethod: PaymentMethod | undefined;
}
-export const DeletePaymentMethodDialog: React.FC = (props) => {
+export const DeletePaymentMethodDialog = React.memo((props: Props) => {
const { error, loading, onClose, onDelete, open, paymentMethod } = props;
- const classes = useStyles();
+ const { classes } = useStyles();
const actions = (
= (props) => {
);
-};
-
-export default React.memo(DeletePaymentMethodDialog);
+});
diff --git a/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.stories.mdx b/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.stories.mdx
deleted file mode 100644
index 2a17e4de74c..00000000000
--- a/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.stories.mdx
+++ /dev/null
@@ -1,130 +0,0 @@
-import { ArgsTable, Canvas, Meta, Story } from '@storybook/addon-docs';
-import PaymentMethodRow from 'src/components/PaymentMethodRow/PaymentMethodRow';
-import { paymentMethodFactory } from 'src/factories';
-
-
-
-export const onDelete = () => {};
-
-export const supportedCreditCards = [
- 'Visa',
- 'MasterCard',
- 'American Express',
- 'Discover',
- 'JCB',
- 'Other',
-];
-
-export const CreditCards = () =>
- supportedCreditCards.map((creditCard) => (
-
- ));
-
-export const Template = (args) => ;
-
-# Payment Method Row
-
-## Credit Cards
-
-
-
-## Google Pay
-
-
-
-
-
-## PayPal
-
-
-
-
-
-## Component API
-
-
-
-
diff --git a/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.stories.tsx b/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.stories.tsx
new file mode 100644
index 00000000000..55195da6b58
--- /dev/null
+++ b/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.stories.tsx
@@ -0,0 +1,78 @@
+import { CardType } from '@linode/api-v4';
+import { action } from '@storybook/addon-actions';
+import React from 'react';
+
+import { paymentMethodFactory } from 'src/factories';
+
+import { PaymentMethodRow } from './PaymentMethodRow';
+
+import type { Meta, StoryObj } from '@storybook/react';
+
+type Story = StoryObj;
+
+const onDelete = action('onDelete');
+
+const supportedCreditCards: (CardType | undefined)[] = [
+ 'Visa',
+ 'MasterCard',
+ 'American Express',
+ 'Discover',
+ 'JCB',
+ undefined,
+];
+
+const CreditCardExamples = () => {
+ const paymentMethods = supportedCreditCards.map((creditCard) => (
+
+ ));
+
+ return <>{paymentMethods}>;
+};
+
+export const CreditCards: Story = {
+ render: () => ,
+};
+
+export const GooglePay: Story = {
+ render: (args) => ,
+};
+
+export const PayPal: Story = {
+ render: (args) => (
+
+ ),
+};
+
+const meta: Meta = {
+ args: {
+ onDelete,
+ paymentMethod: paymentMethodFactory.build({
+ data: {
+ card_type: 'Visa',
+ },
+ type: 'google_pay',
+ }),
+ },
+ component: PaymentMethodRow,
+ title: 'Components/Payment Method Row',
+};
+
+export default meta;
diff --git a/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.test.tsx b/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.test.tsx
index 50f7917bff6..486d083a4ac 100644
--- a/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.test.tsx
+++ b/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.test.tsx
@@ -8,7 +8,7 @@ import { paymentMethodFactory } from 'src/factories';
import BillingSummary from 'src/features/Billing/BillingPanels/BillingSummary';
import { renderWithTheme } from 'src/utilities/testHelpers';
-import PaymentMethodRow from './PaymentMethodRow';
+import { PaymentMethodRow } from './PaymentMethodRow';
vi.mock('@linode/api-v4/lib/account', async () => {
const actual = await vi.importActual('@linode/api-v4/lib/account');
diff --git a/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.tsx b/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.tsx
index 6b3f8201470..fe28b09b3dc 100644
--- a/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.tsx
+++ b/packages/manager/src/components/PaymentMethodRow/PaymentMethodRow.tsx
@@ -13,14 +13,24 @@ import { Paper } from 'src/components/Paper';
import CreditCard from 'src/features/Billing/BillingPanels/BillingSummary/PaymentDrawer/CreditCard';
import { queryKey } from 'src/queries/accountPayment';
-import ThirdPartyPayment from './ThirdPartyPayment';
+import { ThirdPartyPayment } from './ThirdPartyPayment';
interface Props {
+ /**
+ * Function called when the delete button in the Action Menu is pressed.
+ */
onDelete: () => void;
+ /**
+ * Payment method type and data.
+ */
paymentMethod: PaymentMethod;
}
-const PaymentMethodRow = (props: Props) => {
+/**
+ * The `PaymentMethodRow` displays the given payment method and supports various actions for each payment method. It can be used
+ * for credit cards, Google Pay, and PayPal.
+ */
+export const PaymentMethodRow = (props: Props) => {
const theme = useTheme();
const { onDelete, paymentMethod } = props;
const { is_default, type } = paymentMethod;
@@ -125,5 +135,3 @@ const PaymentMethodRow = (props: Props) => {
);
};
-
-export default PaymentMethodRow;
diff --git a/packages/manager/src/components/PaymentMethodRow/ThirdPartyPayment.test.tsx b/packages/manager/src/components/PaymentMethodRow/ThirdPartyPayment.test.tsx
index 00da257b2b8..592bb6a2bca 100644
--- a/packages/manager/src/components/PaymentMethodRow/ThirdPartyPayment.test.tsx
+++ b/packages/manager/src/components/PaymentMethodRow/ThirdPartyPayment.test.tsx
@@ -3,7 +3,7 @@ import * as React from 'react';
import { paymentMethodFactory } from 'src/factories';
import { renderWithTheme } from 'src/utilities/testHelpers';
-import ThirdPartyPayment from './ThirdPartyPayment';
+import { ThirdPartyPayment } from './ThirdPartyPayment';
it('Displays credit card type and last four digits when payment method is Google Pay', () => {
const googlePayPaymentMethod = paymentMethodFactory.build({
diff --git a/packages/manager/src/components/PaymentMethodRow/ThirdPartyPayment.tsx b/packages/manager/src/components/PaymentMethodRow/ThirdPartyPayment.tsx
index ab78f6318ec..a705ea605be 100644
--- a/packages/manager/src/components/PaymentMethodRow/ThirdPartyPayment.tsx
+++ b/packages/manager/src/components/PaymentMethodRow/ThirdPartyPayment.tsx
@@ -1,16 +1,19 @@
-import { PaymentMethod, ThirdPartyPayment } from '@linode/api-v4/lib/account';
-import { Box } from 'src/components/Box';
-import { Theme } from '@mui/material/styles';
+import {
+ ThirdPartyPayment as _ThirdPartyPayment,
+ PaymentMethod,
+} from '@linode/api-v4/lib/account';
+import { Theme, useTheme } from '@mui/material/styles';
import useMediaQuery from '@mui/material/useMediaQuery';
-import { makeStyles, useTheme } from '@mui/styles';
import * as React from 'react';
+import { makeStyles } from 'tss-react/mui';
import GooglePayIcon from 'src/assets/icons/payment/googlePay.svg';
import PayPalIcon from 'src/assets/icons/payment/payPal.svg';
+import { Box } from 'src/components/Box';
import { Typography } from 'src/components/Typography';
import CreditCard from 'src/features/Billing/BillingPanels/BillingSummary/PaymentDrawer/CreditCard';
-const useStyles = makeStyles((theme: Theme) => ({
+const useStyles = makeStyles()((theme: Theme) => ({
icon: {
// https://stackoverflow.com/questions/57516373/image-stretching-in-flexbox-in-safari
alignItems: 'center',
@@ -62,18 +65,18 @@ export const renderThirdPartyPaymentBody = (paymentMethod: PaymentMethod) => {
}
};
-export const getIcon = (paymentMethod: ThirdPartyPayment) => {
+export const getIcon = (paymentMethod: _ThirdPartyPayment) => {
return thirdPartyPaymentMap[paymentMethod].icon;
};
-export const TPP: React.FC = (props) => {
+export const ThirdPartyPayment = (props: Props) => {
const { paymentMethod } = props;
- const classes = useStyles();
+ const { classes } = useStyles();
const theme = useTheme();
const matchesSmDown = useMediaQuery(theme.breakpoints.down('md'));
- const Icon = getIcon(paymentMethod.type as ThirdPartyPayment);
+ const Icon = getIcon(paymentMethod.type as _ThirdPartyPayment);
return (
<>
@@ -91,5 +94,3 @@ export const TPP: React.FC = (props) => {
>
);
};
-
-export default TPP;
diff --git a/packages/manager/src/components/PaymentMethodRow/index.ts b/packages/manager/src/components/PaymentMethodRow/index.ts
deleted file mode 100644
index f71c3bc8339..00000000000
--- a/packages/manager/src/components/PaymentMethodRow/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './PaymentMethodRow';
diff --git a/packages/manager/src/features/Billing/BillingPanels/PaymentInfoPanel/PaymentInformation.tsx b/packages/manager/src/features/Billing/BillingPanels/PaymentInfoPanel/PaymentInformation.tsx
index 624daa8efa5..80212410af1 100644
--- a/packages/manager/src/features/Billing/BillingPanels/PaymentInfoPanel/PaymentInformation.tsx
+++ b/packages/manager/src/features/Billing/BillingPanels/PaymentInfoPanel/PaymentInformation.tsx
@@ -5,7 +5,7 @@ import * as React from 'react';
import { useQueryClient } from 'react-query';
import { useHistory, useRouteMatch } from 'react-router-dom';
-import DeletePaymentMethodDialog from 'src/components/PaymentMethodRow/DeletePaymentMethodDialog';
+import { DeletePaymentMethodDialog } from 'src/components/PaymentMethodRow/DeletePaymentMethodDialog';
import { Typography } from 'src/components/Typography';
import { PaymentMethods } from 'src/features/Billing/BillingPanels/PaymentInfoPanel/PaymentMethods';
import { queryKey } from 'src/queries/accountPayment';
diff --git a/packages/manager/src/features/Billing/BillingPanels/PaymentInfoPanel/PaymentMethods.tsx b/packages/manager/src/features/Billing/BillingPanels/PaymentInfoPanel/PaymentMethods.tsx
index aa10e9aa856..515b654bfa2 100644
--- a/packages/manager/src/features/Billing/BillingPanels/PaymentInfoPanel/PaymentMethods.tsx
+++ b/packages/manager/src/features/Billing/BillingPanels/PaymentInfoPanel/PaymentMethods.tsx
@@ -4,7 +4,7 @@ import Grid from '@mui/material/Unstable_Grid2';
import * as React from 'react';
import { CircleProgress } from 'src/components/CircleProgress';
-import PaymentMethodRow from 'src/components/PaymentMethodRow';
+import { PaymentMethodRow } from 'src/components/PaymentMethodRow/PaymentMethodRow';
import { Typography } from 'src/components/Typography';
import { getAPIErrorOrDefault } from 'src/utilities/errorUtils';