Skip to content
Merged
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
10 changes: 5 additions & 5 deletions fix.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[Frontend] Implement framer-motion animations for Multi-sig Approval Modal
[Frontend] Add unit tests for Multi-sig Approval Modal
Repo Avatar
emdevelopa/Stellar_Payment_API
Description
This task involves UX enhancement for the Multi-sig Approval Modal module.
The goal is to implement framer-motion animations for Multi-sig Approval Modal to improve the platform's styling, user interactions, and overall accessibility.
The goal is to add unit tests for Multi-sig Approval Modal to improve the platform's styling, user interactions, and overall accessibility.

Requirements and context

Expand All @@ -14,15 +14,15 @@ Specifically focused on frontend UX enhancement and responsiveness
Suggested execution

Fork the repo and create a branch
git checkout -b feature/fe-implement-framer-motion-animations-for-multi-sig-approval-modal
git checkout -b feature/fe-add-unit-tests-for-multi-sig-approval-modal
Implement changes

Review existing component in Multi-sig Approval Modal
Apply changes: Implement framer-motion animations for Multi-sig Approval Modal
Apply changes: Add unit tests for Multi-sig Approval Modal
Use clean CSS or tailwind variables for styling
Maintain state transitions and visual feedback
Test and commit

Test mobile responsiveness and interactive states
Check accessibility (a11y) using standard audits
Include screenshots or gifs in the PR
Include screenshots or gifs in the PR
Binary file modified frontend/package-lock.json
Binary file not shown.
135 changes: 135 additions & 0 deletions frontend/src/components/MultisigApprovalModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -520,4 +520,139 @@ describe("MultisigApprovalModal Component", () => {
expect(copyButtons.length).toBeGreaterThan(0);
});
});

describe("Edge Cases", () => {
it("handles empty signers list gracefully", () => {
const noSignersTransaction = {
...mockTransaction,
signers: [],
};
renderWithProvider({ transaction: noSignersTransaction });
expect(screen.getByText("Multi-Signature Approval")).toBeInTheDocument();
expect(screen.getByText(/Transaction must have at least one signer/i)).toBeInTheDocument();
});

it("handles single signer correctly", () => {
const singleSignerTransaction = {
...mockTransaction,
signers: [
{ id: "signer1", publicKey: "G123...", name: "Alice", weight: 1, hasSigned: false },
],
minSignatures: 1,
};
renderWithProvider({ transaction: singleSignerTransaction });

const signButtons = screen.getAllByText("Sign");
expect(signButtons).toHaveLength(1);
expect(screen.getByText("Signatures (0/1)")).toBeInTheDocument();
});

it("shows all signers as signed when pre-signed", () => {
const allSignedTransaction = {
...mockTransaction,
signers: [
{ id: "signer1", publicKey: "G123...", name: "Alice", weight: 1, hasSigned: true },
{ id: "signer2", publicKey: "G456...", name: "Bob", weight: 1, hasSigned: true },
],
};
renderWithProvider({ transaction: allSignedTransaction });

const signedButtons = screen.getAllByText("Signed");
expect(signedButtons).toHaveLength(2);
expect(screen.getByText("Submit Transaction")).toBeInTheDocument();
});
});

describe("Component Cleanup", () => {
it("restores body overflow on unmount", () => {
const { unmount } = renderWithProvider({ isOpen: true });
expect(document.body.style.overflow).toBe("hidden");
unmount();
expect(document.body.style.overflow).toBe("");
});
});

describe("Loading Interaction Guards", () => {
it("disables close button during loading", async () => {
renderWithProvider();

const signButtons = screen.getAllByText("Sign");
fireEvent.click(signButtons[0]);

const closeButton = screen.getByLabelText("Close modal");
expect(closeButton).toBeDisabled();

await waitFor(() => {
expect(closeButton).not.toBeDisabled();
}, { timeout: 2000 });
});

it("prevents backdrop close during loading", async () => {
const mockOnClose = jest.fn();
renderWithProvider({ onClose: mockOnClose });

const signButtons = screen.getAllByText("Sign");
fireEvent.click(signButtons[0]);

const backdrop = screen.getByText("Multi-Signature Approval")
.closest('[role="dialog"]')?.previousSibling as HTMLElement;
if (backdrop) {
fireEvent.click(backdrop);
}

expect(mockOnClose).not.toHaveBeenCalled();
});
});

describe("Render Boundary States", () => {
it("renders without crashing when transaction is null", () => {
renderWithProvider({ transaction: null });

expect(screen.getByText("Multi-Signature Approval")).toBeInTheDocument();
expect(screen.getByText("Review Transaction")).toBeInTheDocument();
expect(screen.queryByText("100 USDC")).not.toBeInTheDocument();
});

it("reopens correctly after being closed", () => {
const mockOnClose = jest.fn();
const { rerender } = render(
<MultisigProvider networkPassphrase="Test Network">
<MultisigApprovalModal
isOpen={true}
onClose={mockOnClose}
networkPassphrase="Test Network"
transaction={mockTransaction}
/>
</MultisigProvider>
);

expect(screen.getByText("Multi-Signature Approval")).toBeInTheDocument();

rerender(
<MultisigProvider networkPassphrase="Test Network">
<MultisigApprovalModal
isOpen={false}
onClose={mockOnClose}
networkPassphrase="Test Network"
transaction={mockTransaction}
/>
</MultisigProvider>
);

expect(screen.queryByText("Multi-Signature Approval")).not.toBeInTheDocument();

rerender(
<MultisigProvider networkPassphrase="Test Network">
<MultisigApprovalModal
isOpen={true}
onClose={mockOnClose}
networkPassphrase="Test Network"
transaction={mockTransaction}
/>
</MultisigProvider>
);

expect(screen.getByText("Multi-Signature Approval")).toBeInTheDocument();
});
});
});
Loading