-
Notifications
You must be signed in to change notification settings - Fork 7
feat: wallet card test #1275
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
feat: wallet card test #1275
Changes from 5 commits
5860bc5
2330c48
baf824a
e503a4a
0d1e3ad
05d2f1b
b1128d0
ccc0b40
3836af5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import CardsWallet from "@/components/cards/wallet"; | ||
import "@testing-library/jest-dom"; | ||
import { mockWallet } from "../../../__mocks__/fixtures/wallet"; | ||
import { screen } from "@testing-library/react"; | ||
import { renderWithRedux } from "@__mocks__/renderWithRedux"; | ||
|
||
// use the actual component when it is done tested | ||
jest.mock("../../../src/components/sections/profile/modals/EditAddress/index.tsx", () => { | ||
return <h1>hello</h1>; | ||
}); | ||
|
||
jest.mock("@/hooks/useTypedDispatch.ts", () => ({ | ||
useDispatch: jest.fn(), | ||
})); | ||
|
||
describe("Wallet card component", () => { | ||
it("renders the wallet component with all the children", () => { | ||
renderWithRedux(<CardsWallet wallet={mockWallet} disabled={false} />); | ||
expect(screen.getByTestId("cardWalletId")).toBeInTheDocument(); | ||
expect(screen.getByTestId("overviewId")).toBeInTheDocument(); | ||
expect(screen.getByTestId("cashoutAddressId")).toBeInTheDocument(); | ||
expect(screen.queryByText("profile.wallet.payout.text")).not.toBeNull(); | ||
}); | ||
}); |
This file was deleted.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,96 @@ | ||||||
import ArrowButton from "@/components/ui/button/Arrow"; | ||||||
import { useTranslation } from "next-i18next"; | ||||||
import { useDispatch } from "@/hooks/useTypedDispatch"; | ||||||
import { setCurrentWallet } from "@/store/feature/user/wallets.slice"; | ||||||
import { toggleBodyScrolling } from "@/store/feature/ui.slice"; | ||||||
import { useSelector } from "@/hooks/useTypedSelector"; | ||||||
import { openVerificationModal } from "@/store/feature/kyc.slice"; | ||||||
import { Wallet } from "@/types/wallet"; | ||||||
import { useCallback, useMemo } from "react"; | ||||||
|
||||||
interface CashoutAddressProps { | ||||||
wallet: Wallet; | ||||||
setShowEditModal: (show: boolean) => void; | ||||||
disabled: boolean; | ||||||
setShowPayoutModal: (show: boolean) => void; | ||||||
testId?:string | ||||||
} | ||||||
|
||||||
export default function CashoutAddress({ wallet, setShowEditModal, disabled, setShowPayoutModal, testId='cashoutAddressId' }: CashoutAddressProps) { | ||||||
const { t } = useTranslation(); | ||||||
const dispatch = useDispatch(); | ||||||
const user = useSelector((state) => state.user.data); | ||||||
const isKycVerified = user?.kycStatus === "VERIFIED"; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would you move this in a useMemo? |
||||||
const address = useMemo(() => (wallet.address ? wallet.address.match(/.{1,4}/g) : null), [wallet.address]); | ||||||
const cashable = useMemo(() => String(wallet.token).toUpperCase() !== "DAC", [wallet.token]); | ||||||
|
||||||
|
||||||
const triggerEditAddress = useCallback(() => { | ||||||
dispatch(setCurrentWallet(wallet)); | ||||||
setShowEditModal(true); | ||||||
dispatch(toggleBodyScrolling(true)); | ||||||
}, [dispatch, setShowEditModal, wallet]); | ||||||
|
||||||
const triggerCashout = useCallback(() => { | ||||||
setShowPayoutModal(true); | ||||||
dispatch(toggleBodyScrolling(true)); | ||||||
}, [setShowPayoutModal, dispatch]); | ||||||
|
||||||
const triggerKYCVerification = useCallback(() => { | ||||||
dispatch( | ||||||
openVerificationModal({ | ||||||
description: t("kyc.payout.reason"), | ||||||
completedActionText: t("kyc.payout.button.completed"), | ||||||
completedAction: () => { | ||||||
triggerCashout(); | ||||||
}, | ||||||
}) | ||||||
); | ||||||
}, [dispatch, t, triggerCashout]); | ||||||
const cashout = () => { | ||||||
if (!isKycVerified) return triggerKYCVerification(); | ||||||
triggerCashout(); | ||||||
}; | ||||||
return ( | ||||||
<div className="px-7 pt-6 flex-1 pb-24 lg:pb-24" data-testId={testId}> | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix typo in The - <div className="px-7 pt-6 flex-1 pb-24 lg:pb-24" data-testId={testId}>
+ <div className="px-7 pt-6 flex-1 pb-24 lg:pb-24" data-testid={testId}> Committable suggestion
Suggested change
|
||||||
{cashable ? ( | ||||||
<div className="text-sm text-gray-700"> | ||||||
{address ? ( | ||||||
<p className="leading-5 text-sm flex gap-x-2 gap-y-1 flex-wrap font-mono font-normal"> | ||||||
{address.map((part, k) => ( | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
<span key={`address-${k}`} className="mr-2"> | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
{part} | ||||||
</span> | ||||||
))} | ||||||
</p> | ||||||
) : ( | ||||||
<p>{wallet.description}</p> | ||||||
)} | ||||||
<div className="text-gray-700 text-sm mt-3"> | ||||||
<span className="cursor-pointer hover:underline" onClick={triggerEditAddress}> | ||||||
{address ? t("profile.wallets.address-change") : t("profile.wallets.address-set")} | ||||||
</span> | ||||||
</div> | ||||||
</div> | ||||||
) : ( | ||||||
<div className="prose"> | ||||||
<p | ||||||
dangerouslySetInnerHTML={{ | ||||||
__html: t("profile.wallets.uncashable", { | ||||||
token: `${wallet.title}`, | ||||||
link: "https://discord.gg/5yDZvVnpQQ", | ||||||
}), | ||||||
}} | ||||||
/> | ||||||
</div> | ||||||
Comment on lines
+76
to
+85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid using Using - <p
- dangerouslySetInnerHTML={{
- __html: t("profile.wallets.uncashable", {
- token: `${wallet.title}`,
- link: "https://discord.gg/5yDZvVnpQQ",
- }),
- }}
- />
+ <p>
+ {t("profile.wallets.uncashable", {
+ token: `${wallet.title}`,
+ link: <a href="https://discord.gg/5yDZvVnpQQ">https://discord.gg/5yDZvVnpQQ</a>,
+ })}
+ </p>
ToolsBiome
|
||||||
)} | ||||||
{cashable && ( | ||||||
<div className="right-2 absolute bottom-2 mt-5"> | ||||||
<ArrowButton disabled={!wallet.balance || !wallet.address || disabled} variant="outline-primary" minWidthClass="min-w-40" onClick={cashout}> | ||||||
{t("profile.wallets.cash-out")} | ||||||
</ArrowButton> | ||||||
</div> | ||||||
)} | ||||||
</div> | ||||||
); | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import Coin from "@/components/ui/Coin"; | ||
import Tag from "@/components/ui/Tag"; | ||
import Currency from "@/components/ui/Currency"; | ||
import { Wallet } from "@/types/wallet"; | ||
import { useTranslation } from "next-i18next"; | ||
|
||
interface OverviewProps { | ||
wallet: Wallet; | ||
testId?: string | ||
} | ||
|
||
export default function Overview({ wallet, testId='overviewId' }: OverviewProps) { | ||
const { t } = useTranslation(); | ||
return ( | ||
<div className="bg-secondary lg:w-60 md:w-60 sm:w-60 rounded-3.5xl" data-testid={testId}> | ||
<div className="p-6"> | ||
<div className="border-b border-dotted border-gray-900"> | ||
<h1 className="text-2xl">{wallet.title}</h1> | ||
<Tag value={wallet.token} /> | ||
<div className="text-right mb-4"> | ||
<Coin size="medium" token={wallet.token} /> | ||
</div> | ||
</div> | ||
<div className="flex"> | ||
<div className="w-1/2 pt-5 text-sm"> | ||
<h1>{t("profile.wallets.balance")}</h1> | ||
</div> | ||
<div className="w-1/2 pt-3.5 text-right text-2xl font-medium"> | ||
<h1> | ||
<Currency value={wallet.balance} /> | ||
</h1> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { Wallet } from "@/types/wallet"; | ||
import Currency from "@/components/ui/Currency"; | ||
import Hint from "@/components/ui/Hint"; | ||
import { useTranslation } from "next-i18next"; | ||
|
||
interface HintProps { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we use type for components props There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are using interface in all components, I think we can stick to same approach |
||
wallet: Wallet; | ||
} | ||
Comment on lines
+6
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add prop types validation. Consider adding prop types validation to ensure that the import PropTypes from 'prop-types';
interface HintProps {
wallet: Wallet;
}
WalletHint.propTypes = {
wallet: PropTypes.shape({
payouts: PropTypes.arrayOf(
PropTypes.shape({
amount: PropTypes.number.isRequired,
token: PropTypes.string.isRequired,
})
).isRequired,
}).isRequired,
}; |
||
export default function WalletHint({ wallet }: HintProps) { | ||
const { t } = useTranslation(); | ||
return ( | ||
<> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no need of fragements There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we need them to return single JSX |
||
{wallet.payouts.map((payout, i) => ( | ||
<Hint key={`wallet-payout-${i}`} className="mt-2"> | ||
<span className="font-medium"> | ||
<Currency value={payout.amount} token={payout.token} /> | ||
</span>{" "} | ||
{t("profile.wallet.payout.text")} | ||
</Hint> | ||
))} | ||
</> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you refactor this component in way that we have less of if else
? : ? : ? :
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't have any
if else
, we are using aternary operator
to avoid many if conditions