Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-toast": "^1.2.1",
"@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.1.2",
"@safe-global/api-kit": "^2.5.6",
"@safe-global/protocol-kit": "^5.1.1",
Expand Down
6 changes: 6 additions & 0 deletions src/components/dashboard/refreshes/RefreshesPanel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const mocks = vi.hoisted(() => ({
mockUseStateWaitMsg: vi.fn(),
mockUseProposeRKHTransaction: vi.fn(),
mockUseGovernanceReview: vi.fn(),
mockUseGetVerifierDataCap: vi.fn(),
}));

vi.mock('@/hooks/useAccount', () => ({
Expand All @@ -32,6 +33,11 @@ vi.mock('@/hooks', () => ({
mutateAsync: vi.fn(),
reset: vi.fn(),
}),
useGetVerifierDataCap: mocks.mockUseGetVerifierDataCap.mockReturnValue({
data: null,
isLoading: false,
error: null,
}),
}));

describe('RefreshesPanel', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const mocks = vi.hoisted(() => ({
mockUseMetaAllocatorTransaction: vi.fn(),
mockUseGovernanceReview: vi.fn(),
mockUseMetaAllocatorReject: vi.fn(),
mockUseGetVerifierDataCap: vi.fn(),
}));

vi.mock('@/hooks', () => ({
Expand Down Expand Up @@ -42,12 +43,18 @@ vi.mock('@/hooks', () => ({
mutateAsync: vi.fn(),
reset: vi.fn(),
}),
useGetVerifierDataCap: mocks.mockUseGetVerifierDataCap.mockReturnValue({
data: null,
isLoading: false,
error: null,
}),
}));

describe('RefreshTableActions', () => {
const createMockRow = (refresh: Partial<Refresh>): Row<Refresh> =>
({
original: {
actorId: 100,
githubIssueId: 1,
title: 'Test Refresh',
creator: { userId: 1, name: 'Test User' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const RefreshTableActions = ({ row }: { row: Row<Refresh> }) => {
<RkhSignTransactionButton
dataCap={row.original.dataCap}
address={row.original.msigAddress}
actorId={row.original.actorId}
/>
);

Expand Down
9 changes: 9 additions & 0 deletions src/components/refresh/RkhSignTransactionButton.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ import { createWrapper } from '@/test-utils';

const mocks = vi.hoisted(() => ({
mockUseAccount: vi.fn(),
mockUseGetVerifierDataCap: vi.fn(),
}));

vi.mock('@/hooks/useAccount', () => ({
useAccount: mocks.mockUseAccount,
useGetVerifierDataCap: mocks.mockUseGetVerifierDataCap,
}));

describe('RkhSignTransactionButton', () => {
const wrapper = createWrapper();
const defaultProps = {
address: 'f1abc',
dataCap: 1024,
actorId: 'f1abc',
};

beforeEach(() => {
Expand All @@ -25,6 +28,12 @@ describe('RkhSignTransactionButton', () => {
mocks.mockUseAccount.mockReturnValue({
account: null,
});

mocks.mockUseGetVerifierDataCap.mockReturnValue({
data: {
datacap: 50,
},
});
});

it('renders the button label', () => {
Expand Down
8 changes: 7 additions & 1 deletion src/components/refresh/RkhSignTransactionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ import RkhSignTransactionDialog from '@/components/refresh/dialogs/RkhSignTransa

interface RkhSignTransactionButtonProps {
address: string;
actorId: string;
dataCap: number;
}

export function RkhSignTransactionButton({ address, dataCap }: RkhSignTransactionButtonProps) {
export function RkhSignTransactionButton({
address,
actorId,
dataCap,
}: RkhSignTransactionButtonProps) {
const [isDialogOpen, setIsDialogOpen] = useState(false);

return (
Expand All @@ -17,6 +22,7 @@ export function RkhSignTransactionButton({ address, dataCap }: RkhSignTransactio
</Button>
<RkhSignTransactionDialog
address={address}
actorId={actorId}
dataCap={dataCap}
open={isDialogOpen}
onOpenChange={setIsDialogOpen}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ describe('MetaAllocatorSignTransactionDialog Integration Tests', () => {
});
});

it('should go through complete success flow', async () => {
it('should go through complete success flow and addAllowance', async () => {
const user = userEvent.setup();
render(<MetaAllocatorSignTransactionDialog {...mockProps} />, { wrapper });

Expand All @@ -144,6 +144,24 @@ describe('MetaAllocatorSignTransactionDialog Integration Tests', () => {
expect(blockNumberSection).toHaveTextContent('Block number123');
});

it('should go through complete success flow and setAllowance', async () => {
const user = userEvent.setup();
render(<MetaAllocatorSignTransactionDialog {...mockProps} />, { wrapper });

await user.type(screen.getByRole('spinbutton', { name: /datacap/i }), '1000');
await user.click(screen.getByRole('radio', { name: /set/i }));
await user.click(screen.getByRole('button', { name: /approve/i }));

const successHeader = await screen.findByTestId('success-header');
expect(successHeader).toHaveTextContent('Success!');

const transactionIdSection = screen.getByTestId('transaction-id-section');
expect(transactionIdSection).toHaveTextContent('Transaction ID0xabcdef123456789');

const blockNumberSection = screen.getByTestId('block-number-section');
expect(blockNumberSection).toHaveTextContent('Block number123');
});

it('should close dialog from success step', async () => {
const user = userEvent.setup();
render(<MetaAllocatorSignTransactionDialog {...mockProps} />, { wrapper });
Expand Down Expand Up @@ -407,7 +425,7 @@ describe('MetaAllocatorSignTransactionDialog Integration Tests', () => {
expect(screen.queryByTestId('error-message')).not.toBeInTheDocument();
});

it('should call onSubmit with correct parameters', async () => {
it('should call onSubmit with correct parameters for addAllowance', async () => {
const user = userEvent.setup();
render(<MetaAllocatorSignTransactionDialog {...mockProps} />, { wrapper });

Expand All @@ -422,6 +440,23 @@ describe('MetaAllocatorSignTransactionDialog Integration Tests', () => {
});
});
});

it('should call onSubmit with correct parameters for setAllowance', async () => {
const user = userEvent.setup();
render(<MetaAllocatorSignTransactionDialog {...mockProps} />, { wrapper });

await user.type(screen.getByRole('spinbutton', { name: /datacap/i }), '1000');
await user.click(screen.getByRole('radio', { name: /set/i }));
await user.click(screen.getByRole('button', { name: /approve/i }));

await waitFor(() => {
expect(mocks.mockEncodeFunctionData).toHaveBeenCalledWith({
abi: expect.any(Array),
functionName: 'setAllowance',
args: [mockProps.address, BigInt(1000 * 1_125_899_906_842_624)],
});
});
});
});

describe('Address conversion scenarios', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import {
DialogSuccessCard,
} from '@/components/ui/dialog';
import { useCallback, useEffect, useState } from 'react';
import { RefreshAllocatorSuccessStep, SetDatacapFormStep } from '@/components/refresh/steps';
import { RefreshAllocatorSuccessStep, ChangeDatacapFormStep } from '@/components/refresh/steps';
import { MetaAllocatorSignSteps } from '@/components/refresh/steps/constants';
import { useMetaAllocatorTransaction, useMetaAllocatorReject } from '@/hooks';
import { MetapathwayType } from '@/types/refresh';
import { withFormProvider } from '@/lib/hocs/withFormProvider';
import { SetDatacapFormValues } from '@/components/refresh/steps/SetDatacapFormStep';
import { ChangeDatacapFormValues } from '@/components/refresh/steps/ChangeDatacapFormStep';
import { SignatureType } from '@/types/governance-review';
import { toast } from '@/components/ui/use-toast';

Expand Down Expand Up @@ -104,14 +104,15 @@ const MetaAllocatorSignTransactionDialog = ({
});

const onMetaAllocatorSubmit = useCallback(
async ({ dataCap }: SetDatacapFormValues) => {
async ({ dataCap, method }: ChangeDatacapFormValues) => {
if (Number(dataCap) === 0) {
setStep(MetaAllocatorSignSteps.REJECTION_CONFIRMATION);
} else {
submitSafeTransaction({
address,
datacap: dataCap,
metaAllocatorContractAddress: maAddress,
method,
});
}
},
Expand Down Expand Up @@ -145,7 +146,7 @@ const MetaAllocatorSignTransactionDialog = ({

const stepsConfig = {
[MetaAllocatorSignSteps.FORM]: (
<SetDatacapFormStep
<ChangeDatacapFormStep
rejectable
metapathwayType={metapathwayType}
dataCap={dataCap}
Expand Down
41 changes: 40 additions & 1 deletion src/components/refresh/dialogs/RkhSignTransactionDialog.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ApiStateWaitMsgResponse } from '@/types/filecoin-client';

const mocks = vi.hoisted(() => ({
mockUseAccount: vi.fn(),
mockUseGetVerifierDataCap: vi.fn(),
mockProposeAddVerifier: vi.fn(),
mockGetStateWaitMsg: vi.fn(),
mockUseToast: vi.fn(),
Expand All @@ -21,6 +22,10 @@ vi.mock('@/hooks/useAccount', () => ({
useAccount: mocks.mockUseAccount,
}));

vi.mock('@/hooks/useGetVerifierDataCap', () => ({
useGetVerifierDataCap: mocks.mockUseGetVerifierDataCap,
}));

vi.mock('@/components/ui/use-toast', () => ({
useToast: mocks.mockUseToast,
}));
Expand All @@ -31,6 +36,7 @@ describe('RkhSignTransactionDialog Integration Tests', () => {
open: true,
address: 'f1234567890abcdef',
onOpenChange: vi.fn(),
actorId: 'f012345',
};
const mockStateWaitResponse: ApiStateWaitMsgResponse = {
data: {
Expand All @@ -53,6 +59,8 @@ describe('RkhSignTransactionDialog Integration Tests', () => {
success: true,
};

const mockDataCap = 10n ** 18n;

beforeEach(() => {
vi.clearAllMocks();

Expand All @@ -63,6 +71,13 @@ describe('RkhSignTransactionDialog Integration Tests', () => {
mocks.mockUseToast.mockReturnValue({
toast: mocks.mockToast,
});

mocks.mockUseGetVerifierDataCap.mockReturnValue({
data: { datacap: mockDataCap, verifier: 'f012345' },
isLoading: false,
isError: false,
error: null,
});
});

it('should render dialog with correct title and description', () => {
Expand All @@ -85,11 +100,35 @@ describe('RkhSignTransactionDialog Integration Tests', () => {
mocks.mockGetStateWaitMsg.mockResolvedValue(mockStateWaitResponse);
});

it('should go through complete success flow', async () => {
it('should go through complete success flow and add datacap', async () => {
const user = userEvent.setup();
render(<RkhSignTransactionDialog {...mockProps} />, { wrapper });

await user.type(screen.getByRole('spinbutton', { name: /datacap/i }), '1000');
await user.click(screen.getByRole('button', { name: /approve/i }));

expect(mocks.mockProposeAddVerifier).toHaveBeenCalledWith(
mockProps.address,
'1000',
mockDataCap,
);

const successHeader = await screen.findByTestId('success-header');
expect(successHeader).toHaveTextContent('Success!');

const transactionIdSection = screen.getByTestId('transaction-id-section');
expect(transactionIdSection).toHaveTextContent('Transaction IDmessage-id-123');

const blockNumberSection = screen.getByTestId('block-number-section');
expect(blockNumberSection).toHaveTextContent('Block number12345');
});

it('should go through complete success flow and set datacap', async () => {
const user = userEvent.setup();
render(<RkhSignTransactionDialog {...mockProps} />, { wrapper });

await user.type(screen.getByRole('spinbutton', { name: /datacap/i }), '1000');
await user.click(screen.getByRole('radio', { name: /set/i }));
await user.click(screen.getByRole('button', { name: /approve/i }));

expect(mocks.mockProposeAddVerifier).toHaveBeenCalledWith(mockProps.address, '1000');
Expand Down
Loading
Loading