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
56 changes: 55 additions & 1 deletion __tests__/wallet_selector_modal.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { fireEvent, render, screen } from "@testing-library/react";
import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
import WalletSelectorModal, {
detectAnyWalletExtension,
Expand Down Expand Up @@ -206,6 +206,60 @@ describe("WalletSelectorModal wallet availability (#103)", () => {
// Task 4 — Graceful handling of user signature rejection exceptions
// ---------------------------------------------------------------------------

describe("WalletSelectorModal design tokens", () => {
it("uses semantic design token classes for modal shell and alert surfaces", () => {
render(<WalletSelectorModal isOpen={true} onClose={vi.fn()} />);

const backdrop = screen.getByTestId("wallet-selector-modal");
expect(backdrop).toHaveClass("bg-surface-page/80");

const content = screen.getByTestId("wallet-selector-modal-content");
expect(content).toHaveClass(
"bg-surface-card",
"border",
"border-border-subtle",
"text-text-primary"
);

const title = screen.getByText("Select Wallet");
expect(title).toHaveClass("text-text-primary");

const warning = screen.getByTestId("wallet-selector-availability-warning");
expect(warning).toHaveClass(
"bg-warning-soft/10",
"border-warning-soft/40",
"text-warning-soft"
);

const errorMessage = screen.getByTestId("wallet-selector-error-message");
expect(errorMessage).toHaveClass(
"bg-danger/20",
"border-danger/40",
"text-danger-soft"
);
});

it("uses design-token classes for wallet rows and status badges", () => {
render(
<WalletSelectorModal
isOpen={true}
onClose={vi.fn()}
selectedWalletId="freighter"
/>
);

const selectedOption = screen.getByTestId("wallet-selector-option-freighter");
expect(selectedOption).toHaveClass(
"border-accent-soft",
"bg-accent/10",
"text-text-primary"
);

const connectedBadge = screen.getByTestId("wallet-selector-connected-badge");
expect(connectedBadge).toHaveClass("text-success-soft");
});
});

describe("WalletSelectorModal signature rejection handling (#105)", () => {
beforeEach(() => {
vi.clearAllMocks();
Expand Down
38 changes: 19 additions & 19 deletions app/components/WalletSelectorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,22 +224,22 @@ export default function WalletSelectorModal({
data-testid="wallet-selector-modal"
role="dialog"
aria-label="Select Wallet"
className={`fixed inset-0 z-50 flex items-center justify-center bg-black/60 ${className}`}
className={`fixed inset-0 z-50 flex items-center justify-center bg-surface-page/80 ${className}`}
>
<div
data-testid="wallet-selector-modal-content"
className="bg-surface rounded-xl shadow-xl max-w-md w-full mx-4 p-6"
className="bg-surface-card border border-border-subtle text-text-primary rounded-xl shadow-xl max-w-md w-full mx-4 p-6"
>
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-semibold text-primary">
<h2 className="text-lg font-semibold text-text-primary">
Select Wallet
</h2>
<button
type="button"
onClick={onClose}
data-testid="wallet-selector-modal-close"
aria-label="Close"
className="text-secondary hover:text-primary transition-colors"
className="text-text-secondary hover:text-text-primary transition-colors"
>
</button>
Expand All @@ -249,7 +249,7 @@ export default function WalletSelectorModal({
{networkMismatch.mismatched && mismatchMessage && (
<div
data-testid="wallet-selector-network-warning"
className="bg-warning/40 border border-warning rounded-lg px-4 py-3 mb-4 text-warning-soft text-sm"
className="bg-warning-soft/10 border border-warning-soft/40 rounded-lg px-4 py-3 mb-4 text-warning-soft text-sm"
role="alert"
>
{mismatchMessage}
Expand All @@ -261,7 +261,7 @@ export default function WalletSelectorModal({
<div
data-testid="wallet-selector-availability-warning"
role="alert"
className="bg-warning/40 border border-warning rounded-lg px-4 py-3 mb-4 text-warning-soft text-sm"
className="bg-warning-soft/10 border border-warning-soft/40 rounded-lg px-4 py-3 mb-4 text-warning-soft text-sm"
>
<p data-testid="wallet-selector-setup-instruction">
{availability.setupInstruction}
Expand All @@ -282,7 +282,7 @@ export default function WalletSelectorModal({
{errorMessage && (
<div
data-testid="wallet-selector-error-message"
className="bg-danger/20 border border-danger rounded-lg px-4 py-3 mb-4 text-danger-soft text-sm text-center"
className="bg-danger/20 border border-danger/40 rounded-lg px-4 py-3 mb-4 text-danger-soft text-sm text-center"
role="alert"
>
{errorMessage}
Expand All @@ -294,7 +294,7 @@ export default function WalletSelectorModal({
<div
data-testid="wallet-selector-rejection-warning"
role="alert"
className="bg-yellow-500/10 border border-yellow-500/30 rounded-lg px-4 py-3 mb-4 text-sm text-yellow-300"
className="bg-warning-soft/10 border border-warning-soft/40 rounded-lg px-4 py-3 mb-4 text-sm text-warning-soft"
>
Signature cancelled — you rejected the request in your wallet.
</div>
Expand All @@ -305,7 +305,7 @@ export default function WalletSelectorModal({
<div
data-testid="wallet-selector-error-warning"
role="alert"
className="bg-red-500/10 border border-red-500/30 rounded-lg px-4 py-3 mb-4 text-sm text-red-300"
className="bg-danger/10 border border-danger/30 rounded-lg px-4 py-3 mb-4 text-sm text-danger-soft"
>
Failed to connect wallet. Please try again.
</div>
Expand All @@ -315,11 +315,11 @@ export default function WalletSelectorModal({
{effectiveLoading && (
<div
data-testid="wallet-selector-spinner"
className="absolute inset-0 z-10 flex items-center justify-center bg-black/50 rounded-lg"
className="absolute inset-0 z-10 flex items-center justify-center bg-surface-page/60 rounded-lg"
>
<div className="flex flex-col items-center space-y-2">
<svg
className="h-8 w-8 text-indigo-500 animate-spin"
className="h-8 w-8 text-accent-soft animate-spin"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
Expand All @@ -339,7 +339,7 @@ export default function WalletSelectorModal({
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
/>
</svg>
<span className="text-sm text-gray-300">
<span className="text-sm text-text-secondary">
Wallet operation in progress…
</span>
</div>
Expand All @@ -350,19 +350,19 @@ export default function WalletSelectorModal({
{activeAddress && (
<div
data-testid="wallet-selector-active-info"
className="mb-4 p-3 border border-white/10 rounded-lg"
className="mb-4 p-3 border border-border-subtle rounded-lg bg-surface-field"
>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<span className="h-2 w-2 rounded-full bg-green-500 animate-pulse" />
<span className="text-sm text-gray-300 font-mono">
<span className="h-2 w-2 rounded-full bg-success-soft animate-pulse" />
<span className="text-sm text-text-secondary font-mono">
{activeAddress.slice(0, 4)}...{activeAddress.slice(-4)}
</span>
</div>
<button
onClick={handleDisconnect}
disabled={effectiveLoading}
className="text-sm text-red-400 hover:text-red-300 transition-colors disabled:opacity-50"
className="text-sm text-danger-soft hover:text-danger-soft-hover transition-colors disabled:opacity-50"
data-testid="wallet-selector-disconnect-btn"
>
Disconnect
Expand All @@ -389,8 +389,8 @@ export default function WalletSelectorModal({
data-connected={isConnected}
className={`w-full text-left px-4 py-3 rounded-lg border transition-colors disabled:opacity-50 disabled:cursor-not-allowed ${
isSelected
? "border-indigo-500 bg-indigo-600/20 text-white"
: "border-white/10 hover:border-white/20 hover:bg-white/5 text-primary"
? "border-accent-soft bg-accent/10 text-text-primary"
: "border-border-subtle hover:border-accent-soft/60 hover:bg-surface-field text-text-primary"
}`}
>
<div className="flex items-center justify-between">
Expand All @@ -400,7 +400,7 @@ export default function WalletSelectorModal({
{isConnected && (
<span
data-testid="wallet-selector-connected-badge"
className="text-xs text-green-400"
className="text-xs text-success-soft"
>
Connected
</span>
Expand Down