Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ea2c2ec
feat: implement descriptive empty state UI for dashboard jobs list
vicajohn Aug 27, 2026
92aae61
feat: add DarkModeSwitcher base component for Storybook (closes #318)
SamuelStave Aug 28, 2026
32be981
feat: add Storybook stories for DarkModeSwitcher (closes #318)
SamuelStave Aug 28, 2026
0f77e29
test: add storybook verification tests (closes #318)
SamuelStave Aug 28, 2026
dc62fe7
Write React Testing Library assertions for wallet disconnect handler …
madisonsc52-del Aug 29, 2026
8463f9b
feat: add wallet_disconnect_handler component tests and fix lint error
madisonsc52-del Aug 30, 2026
ed5fb65
fix: move useMemo after activeTransactionXdr declaration
madisonsc52-del Aug 30, 2026
b1fc04f
fix(ci): resolve freighter-api ESM interop, fake XDR fixtures, and un…
Aug 30, 2026
fa08698
Merge branch 'main' into feat/dashboard-empty-state-ui
godamongstmen897 Aug 31, 2026
0023cd2
Merge branch 'main' into feat/dark-mode-storybook-318
godamongstmen897 Aug 31, 2026
0a8e90c
Merge branch 'main' into feat/dark-mode-storybook-318
godamongstmen897 Aug 31, 2026
b577cc5
fix: make Storybook null handling type-safe for type check
SamuelStave Aug 31, 2026
39c375b
Merge branch 'main' into Write-React-Testing-Library-assertions-for-w…
madisonsc52-del Aug 31, 2026
275bbc1
Merge branch 'main' into feat/dark-mode-storybook-318
godamongstmen897 Aug 31, 2026
077e977
Merge branch 'main' into Write-React-Testing-Library-assertions-for-w…
godamongstmen897 Aug 31, 2026
5717cc3
fix: remove @storybook/test import (module not found)
SamuelStave Aug 31, 2026
aecc8f8
fix: avoid JSX Story type error
SamuelStave Aug 31, 2026
bbbd845
fix: correct container mock for type check
SamuelStave Aug 31, 2026
4541d17
Merge branch 'main' into feat/dark-mode-storybook-318
godamongstmen897 Aug 31, 2026
e82bb02
Merge branch 'main' into Write-React-Testing-Library-assertions-for-w…
godamongstmen897 Aug 31, 2026
b725f38
fix: rewrite stories test to follow wallet-badge pattern (lasting sol…
SamuelStave Aug 31, 2026
ec9389f
feat(dashboard): add the EmptyStateCard this PR renders
godamongstmen897 Aug 31, 2026
1ac1f10
Merge branch 'main' into feat/dark-mode-storybook-318
godamongstmen897 Aug 31, 2026
859886f
Merge branch 'main' into Write-React-Testing-Library-assertions-for-w…
godamongstmen897 Aug 31, 2026
a18f3d0
Merge pull request #303 from vicajohn/feat/dashboard-empty-state-ui
godamongstmen897 Aug 31, 2026
98ff6d5
Merge pull request #346 from SamuelStave/feat/dark-mode-storybook-318
godamongstmen897 Aug 31, 2026
4c13459
Merge branch 'refs/heads/pr/364' into work-364
godamongstmen897 Aug 31, 2026
e26b7b8
Merge main into #364 and drop duplicated conflict residue
godamongstmen897 Aug 31, 2026
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
205 changes: 205 additions & 0 deletions WALLET_DISCONNECT_HANDLER_TESTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
# Wallet Disconnect Handler - Component Tests Implementation

## Summary

Successfully implemented comprehensive component tests for the `wallet_disconnect_handler` module to assert behavior under mocked wallet actions.

## Issue Description

**Problem & Goal**: Add component tests to assert the behavior of `wallet_disconnect_handler` under mocked wallet actions.

**Target Component**: `app/lib/wallet_disconnect_handler.ts`

## Implementation Details

### New Test File Created

**File**: `__tests__/wallet_disconnect_handler.component.test.ts`

**Total Tests Added**: 55 comprehensive test cases

### Test Coverage Breakdown

The new test file provides extensive coverage across multiple scenarios:

#### 1. **Successful Disconnect Scenarios** (5 tests)
- Disconnect completion for all wallet types (freighter, albedo, xbull, hana)
- Handling disconnect functions that return values
- Async operation completion verification

#### 2. **Failed Disconnect Scenarios with Error Objects** (5 tests)
- Error message capture for each wallet type
- Error handling with empty messages
- Proper error propagation through the handler

#### 3. **Failed Disconnect Scenarios with Non-Error Throws** (5 tests)
- String throws with fallback messages
- Number throws handling
- Object throws handling
- Null and undefined throws
- Graceful degradation for unexpected error types

#### 4. **Wallet Not Installed Scenarios** (5 tests)
- Fallback instructions for each wallet type
- Install URL provision
- Verification that disconnect function is not called
- Generic fallback for unknown wallets

#### 5. **Detector Throws Scenarios** (2 tests)
- Graceful handling when detector function throws
- Fallback to safe state with proper instructions

#### 6. **Concurrent and Sequential Disconnect Scenarios** (3 tests)
- Multiple sequential disconnects
- Concurrent disconnect attempts
- Mixed success and failure scenarios

#### 7. **Delayed and Async Disconnect Scenarios** (3 tests)
- Delayed disconnect operations
- Immediate promise resolution
- Immediate promise rejection

#### 8. **Logging Behavior Verification** (4 tests)
- Warning logs when wallet not installed
- Warning logs when disconnect fails
- No logs on successful disconnect
- Availability check failure logging

#### 9. **Result Structure Validation** (3 tests)
- Correct structure on success
- Correct structure when wallet not installed
- Correct structure on disconnect failure

#### 10. **Edge Cases** (4 tests)
- Synchronous throws in async context
- Empty wallet ID handling
- Very long error messages
- Multiple disconnect calls

#### 11. **Integration with Window Globals** (9 tests)
- Detection of freighter globals (freighterApi, freighter)
- Detection of albedo globals (albedo, albedoApi)
- Detection of xbull globals (xBullSDK)
- Detection of hana globals (hanaWallet, hana)
- Override behavior with detector callback

#### 12. **checkWalletAvailabilityById Detailed Scenarios** (7 tests)
- Complete result structure validation
- Wallet-specific setup instructions
- Install URL accuracy
- Generic instructions for unknown wallets
- Exception handling in detector

## Validation Results

### Test Execution

```bash
✓ __tests__/wallet_disconnect_handler.component.test.ts (55 tests)
✓ __tests__/wallet_disconnect_handler_availability.test.ts (34 tests)

Test Files 2 passed (2)
Tests 89 passed (89)
```

### TypeScript Type Check

```bash
✓ No type errors
```

### Build Verification

```bash
✓ Compiled successfully
✓ All pages generated successfully
✓ No conflicts with existing codebase
```

### Full Test Suite Results

- **Before**: 83 test files passed, 1289 tests passed
- **After**: 84 test files passed, 1344 tests passed
- **Improvement**: +1 test file, +55 tests

## Test Design Patterns

The implementation follows established patterns from the codebase:

1. **Vitest Framework**: Uses `describe`, `it`, `expect`, `vi` for mocking
2. **Console Spy Pattern**: Properly mocks and restores `console.warn` and `console.error`
3. **Cleanup Pattern**: Uses `afterEach` to restore spies and clean window globals
4. **Type Safety**: Includes proper TypeScript types with `WalletDisconnectResult`
5. **Comprehensive Mocking**: Uses `vi.fn()` for async disconnect function mocking
6. **Realistic Scenarios**: Tests actual wallet extension behaviors and edge cases

## Key Features Tested

### Core Functions Covered

1. **`disconnectWalletWithCheck`**
- Pre-checks wallet availability
- Executes disconnect function safely
- Returns structured results
- Handles errors gracefully
- Provides fallback instructions

2. **`detectWalletExtensionById`**
- Window global detection
- Detector override support
- Multi-global checking

3. **`checkWalletAvailabilityById`**
- Availability status reporting
- Setup instruction generation
- Install URL provision
- Error handling

### Wallet Types Supported

- ✅ Freighter
- ✅ Albedo
- ✅ xBull
- ✅ Hana
- ✅ Unknown/Generic wallets

## Files Modified/Created

### Created
- `__tests__/wallet_disconnect_handler.component.test.ts` (55 tests, ~700 lines)

### Unchanged (Source Code)
- `app/lib/wallet_disconnect_handler.ts` (no modifications needed - existing implementation was robust)

### Unchanged (Existing Tests)
- `__tests__/wallet_disconnect_handler_availability.test.ts` (34 tests - continues to pass)

## Confidence Level

**95% - 100%**

The implementation:
- ✅ Follows existing codebase patterns
- ✅ Passes all 55 new tests
- ✅ Maintains all 34 existing tests
- ✅ Passes TypeScript type checking
- ✅ Passes production build
- ✅ Does not break any existing functionality
- ✅ Provides comprehensive edge case coverage
- ✅ Documents all test scenarios clearly

## Testing Strategy

The tests validate the wallet disconnect handler's behavior across:

1. **Happy Paths**: Successful disconnects for all wallet types
2. **Error Paths**: Various failure modes and error types
3. **Edge Cases**: Unusual inputs and boundary conditions
4. **Integration**: Interaction with browser globals and detectors
5. **Concurrency**: Multiple simultaneous operations
6. **Logging**: Proper diagnostic output
7. **Type Safety**: Correct TypeScript usage throughout

## Conclusion

The wallet disconnect handler now has comprehensive component test coverage that validates its behavior under mocked wallet actions. The tests ensure robust error handling, proper fallback mechanisms, and reliable disconnect operations across all supported wallet types.
37 changes: 37 additions & 0 deletions __tests__/dark-mode-switcher-stories.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { describe, expect, it } from "vitest";
import { render, screen } from "@testing-library/react";
import DarkModeSwitcher, { DarkModeSwitcherEmptyState } from "@/app/components/DarkModeSwitcher";

describe("DarkModeSwitcher Storybook stories - rendering validation", () => {
it("renders Light state correctly", () => {
render(<DarkModeSwitcher isDarkMode={false} onToggle={() => {}} />);
expect(screen.getByRole("switch")).toBeInTheDocument();
expect(screen.getByRole("switch")).toHaveAttribute("aria-checked", "false");
});

it("renders Dark state correctly", () => {
render(<DarkModeSwitcher isDarkMode={true} onToggle={() => {}} />);
expect(screen.getByRole("switch")).toHaveAttribute("aria-checked", "true");
});

it("renders Disabled state correctly", () => {
render(<DarkModeSwitcher isDarkMode={false} disabled onToggle={() => {}} />);
expect(screen.getByRole("switch")).toHaveAttribute("aria-disabled", "true");
});

it("renders Loading state correctly", () => {
render(<DarkModeSwitcher isDarkMode={false} loading onToggle={() => {}} />);
expect(screen.getByText("Loading theme...")).toBeInTheDocument();
});

it("renders Empty state correctly", () => {
render(<DarkModeSwitcher isDarkMode={null} onToggle={() => {}} />);
expect(screen.getByTestId("dark-mode-switcher-empty-state")).toBeInTheDocument();
});

it("renders EmptyStateStandalone correctly", () => {
render(<DarkModeSwitcherEmptyState />);
expect(screen.getByTestId("dark-mode-switcher-empty-state")).toBeInTheDocument();
expect(screen.getByText("No theme preferences available")).toBeInTheDocument();
});
});
Loading
Loading