UNPKG

@reown/appkit-scaffold-ui

Version:

#### 🔗 [Website](https://reown.com/appkit)

389 lines • 17.6 kB
import { beforeEach, describe, expect, it, vi } from 'vitest'; import { ConstantsUtil } from '@reown/appkit-common'; import { ApiController, ConnectionController, CoreHelperUtil, OptionsController } from '@reown/appkit-controllers'; import { ConnectorUtil } from '../../src/utils/ConnectorUtil'; const INJECTED = { id: 'injected' }; const RECENT = { id: 'recent' }; const FEATURED = { id: 'featured' }; const CUSTOM = { id: 'custom' }; const EXTERNAL = { id: 'external' }; const MULTI_CHAIN = { id: 'multiChain' }; const INJECTED_CONNECTOR = { id: 'injected', type: 'INJECTED', info: { rdns: 'browser.wallet' }, name: 'Browser Wallet', chain: { id: 'eip155:1' } }; const ANNOUNCED_CONNECTOR = { id: 'announced', type: 'ANNOUNCED', info: { rdns: 'announced.wallet' }, name: 'Announced Wallet', chain: { id: 'eip155:1' } }; describe('ConnectorUtil', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('getConnectorTypeOrder', () => { it('should return connector positions in order of overriddenConnectors first then enabled connectors', () => { vi.spyOn(ConnectorUtil, 'getIsConnectedWithWC').mockReturnValue(false); vi.spyOn(OptionsController, 'state', 'get').mockReturnValue({ ...OptionsController.state, enableWalletConnect: true, features: { connectorTypeOrder: ['injected', 'walletConnect'] } }); const result = ConnectorUtil.getConnectorTypeOrder({ recommended: [], featured: [FEATURED], custom: [CUSTOM], recent: [RECENT], announced: [INJECTED], injected: [INJECTED], multiChain: [MULTI_CHAIN], external: [EXTERNAL], overriddenConnectors: ['featured', 'walletConnect', 'injected'] }); expect(result).toEqual([ 'featured', 'walletConnect', 'injected', 'recent', 'custom', 'external' ]); }); it('should use default connectorPosition from OptionsController when overriddenConnectors not provided', () => { vi.spyOn(ConnectorUtil, 'getIsConnectedWithWC').mockReturnValue(false); vi.spyOn(OptionsController, 'state', 'get').mockReturnValue({ ...OptionsController.state, enableWalletConnect: true, features: { connectorTypeOrder: ['injected', 'walletConnect'] } }); const result = ConnectorUtil.getConnectorTypeOrder({ recommended: [], featured: [FEATURED], custom: [CUSTOM], recent: [RECENT], announced: [INJECTED], injected: [INJECTED], multiChain: [MULTI_CHAIN], external: [EXTERNAL] }); expect(result).toEqual([ 'injected', 'walletConnect', 'recent', 'featured', 'custom', 'external' ]); }); it('should only include enabled connectors', () => { vi.spyOn(ConnectorUtil, 'getIsConnectedWithWC').mockReturnValue(false); vi.spyOn(OptionsController, 'state', 'get').mockReturnValue({ ...OptionsController.state, enableWalletConnect: true, features: { connectorTypeOrder: ['injected', 'recommended'] } }); const result = ConnectorUtil.getConnectorTypeOrder({ recommended: [], featured: [FEATURED], custom: [CUSTOM], recent: [RECENT], announced: [], injected: [], multiChain: [], external: [EXTERNAL] }); expect(result).toEqual(['walletConnect', 'recent', 'featured', 'custom', 'external']); expect(result).not.toContain('injected'); }); it('should handle disabled walletConnect connector properly', () => { vi.spyOn(ConnectorUtil, 'getIsConnectedWithWC').mockReturnValue(false); vi.spyOn(OptionsController, 'state', 'get').mockReturnValue({ ...OptionsController.state, enableWalletConnect: false, features: { connectorTypeOrder: ['walletConnect', 'injected'] } }); const result = ConnectorUtil.getConnectorTypeOrder({ recommended: [], featured: [], custom: [], recent: [], announced: [], injected: [INJECTED], multiChain: [], external: [] }); expect(result).toEqual(['injected']); expect(result).not.toContain('walletConnect'); }); it('should handle already connected walletConnect properly', () => { vi.spyOn(ConnectorUtil, 'getIsConnectedWithWC').mockReturnValue(true); vi.spyOn(OptionsController, 'state', 'get').mockReturnValue({ ...OptionsController.state, enableWalletConnect: true, features: { connectorTypeOrder: ['walletConnect', 'injected'] } }); const result = ConnectorUtil.getConnectorTypeOrder({ recommended: [], featured: [], custom: [], recent: [], announced: [], injected: [INJECTED], multiChain: [INJECTED], external: [] }); expect(result).toEqual(['injected']); expect(result).not.toContain('walletConnect'); }); }); describe('showConnector', () => { beforeEach(() => { vi.clearAllMocks(); }); it('should hide browser wallet on desktop', () => { vi.spyOn(CoreHelperUtil, 'isMobile').mockReturnValue(false); expect(ConnectorUtil.showConnector(INJECTED_CONNECTOR)).toBe(false); }); it('should show browser wallet on mobile', () => { vi.spyOn(CoreHelperUtil, 'isMobile').mockReturnValue(true); vi.spyOn(ConnectionController, 'checkInstalled').mockReturnValue(true); expect(ConnectorUtil.showConnector(INJECTED_CONNECTOR)).toBe(true); }); it('should hide injected connector when not installed and no rdns', () => { vi.spyOn(ConnectionController, 'checkInstalled').mockReturnValue(false); expect(ConnectorUtil.showConnector({ ...INJECTED_CONNECTOR, info: undefined })).toBe(false); }); it('should hide connector when rdns is excluded', () => { vi.spyOn(ApiController.state, 'excludedWallets', 'get').mockReturnValue([ { rdns: 'browser.wallet', name: 'Test Wallet' } ]); expect(ConnectorUtil.showConnector(INJECTED_CONNECTOR)).toBe(false); }); it('should hide connector when name is excluded', () => { vi.spyOn(ApiController.state, 'excludedWallets', 'get').mockReturnValue([ { name: 'Browser Wallet', rdns: 'test.wallet' } ]); expect(ConnectorUtil.showConnector(INJECTED_CONNECTOR)).toBe(false); }); it('should hide announced connector when excluded with rdns', () => { vi.spyOn(ApiController.state, 'excludedWallets', 'get').mockReturnValue([ { rdns: 'announced.wallet', name: 'Announced Wallet' } ]); expect(ConnectorUtil.showConnector(ANNOUNCED_CONNECTOR)).toBe(false); }); it('should hide announced connector when excluded with name', () => { vi.spyOn(ApiController.state, 'excludedWallets', 'get').mockReturnValue([ { name: 'Announced Wallet', rdns: 'announced' } ]); expect(ConnectorUtil.showConnector(ANNOUNCED_CONNECTOR)).toBe(false); }); it('should show injected connector when not excluded', () => { vi.spyOn(ApiController.state, 'excludedWallets', 'get').mockReturnValue([]); expect(ConnectorUtil.showConnector(INJECTED_CONNECTOR)).toBe(true); }); it('should show announced connector when not excluded', () => { vi.spyOn(ApiController.state, 'excludedWallets', 'get').mockReturnValue([]); expect(ConnectorUtil.showConnector(ANNOUNCED_CONNECTOR)).toBe(true); }); }); describe('getAuthName', () => { it('should return socialUsername when provided and not discord ending with 0', () => { const result = ConnectorUtil.getAuthName({ email: 'test@example.com', socialUsername: 'john_doe', socialProvider: 'github' }); expect(result).toBe('john_doe'); }); it('should return socialUsername without last character when discord provider and ends with 0', () => { const result = ConnectorUtil.getAuthName({ email: 'test@example.com', socialUsername: 'john_doe0', socialProvider: 'discord' }); expect(result).toBe('john_doe'); }); it('should return socialUsername as-is when discord provider but does not end with 0', () => { const result = ConnectorUtil.getAuthName({ email: 'test@example.com', socialUsername: 'john_doe1', socialProvider: 'discord' }); expect(result).toBe('john_doe1'); }); it('should return socialUsername when provided and socialProvider is null', () => { const result = ConnectorUtil.getAuthName({ email: 'test@example.com', socialUsername: 'john_doe', socialProvider: null }); expect(result).toBe('john_doe'); }); it('should return email when socialUsername is not provided', () => { const result = ConnectorUtil.getAuthName({ email: 'test@example.com' }); expect(result).toBe('test@example.com'); }); it('should return email when socialUsername is null', () => { const result = ConnectorUtil.getAuthName({ email: 'test@example.com', socialUsername: null }); expect(result).toBe('test@example.com'); }); it('should return email when socialUsername is empty string', () => { const result = ConnectorUtil.getAuthName({ email: 'test@example.com', socialUsername: '' }); expect(result).toBe('test@example.com'); }); it('should truncate email when longer than 30 characters', () => { const longEmail = 'verylongemailaddress@verylongdomain.com'; const result = ConnectorUtil.getAuthName({ email: longEmail }); expect(result).toBe(`${longEmail.slice(0, -3)}...`); expect(result).toBe('verylongemailaddress@verylongdomain....'); }); it('should return full email when exactly 30 characters', () => { const email = 'test12345@example12345678.com'; const result = ConnectorUtil.getAuthName({ email }); expect(result).toBe(email); }); it('should return full email when less than 30 characters', () => { const shortEmail = 'short@test.com'; const result = ConnectorUtil.getAuthName({ email: shortEmail }); expect(result).toBe(shortEmail); }); }); describe('fetchProviderData', () => { const mockProvider = { request: vi.fn() }; const mockConnector = { name: 'Test Wallet', id: 'test-connector', provider: mockProvider }; beforeEach(() => { vi.clearAllMocks(); mockProvider.request.mockClear(); }); it('should return empty data for Browser Wallet on desktop', async () => { vi.spyOn(CoreHelperUtil, 'isMobile').mockReturnValue(false); const browserWalletConnector = { ...mockConnector, name: 'Browser Wallet' }; const result = await ConnectorUtil.fetchProviderData(browserWalletConnector); expect(result).toEqual({ accounts: [], chainId: undefined }); expect(mockProvider.request).not.toHaveBeenCalled(); }); it('should return empty data for AUTH connector', async () => { const authConnector = { ...mockConnector, id: ConstantsUtil.CONNECTOR_ID.AUTH }; const result = await ConnectorUtil.fetchProviderData(authConnector); expect(result).toEqual({ accounts: [], chainId: undefined }); expect(mockProvider.request).not.toHaveBeenCalled(); }); it('should fetch accounts and chainId successfully', async () => { const mockAccounts = ['0x123', '0x456']; const mockChainId = '0x1'; mockProvider.request.mockResolvedValueOnce(mockAccounts).mockResolvedValueOnce(mockChainId); const result = await ConnectorUtil.fetchProviderData(mockConnector); expect(result).toEqual({ accounts: mockAccounts, chainId: 1 }); expect(mockProvider.request).toHaveBeenCalledTimes(2); expect(mockProvider.request).toHaveBeenNthCalledWith(1, { method: 'eth_accounts' }); expect(mockProvider.request).toHaveBeenNthCalledWith(2, { method: 'eth_chainId' }); }); it('should return empty data when provider is undefined', async () => { const connectorWithoutProvider = { ...mockConnector, provider: undefined }; const result = await ConnectorUtil.fetchProviderData(connectorWithoutProvider); expect(result).toEqual({ accounts: undefined, chainId: undefined }); }); it('should handle eth_accounts request failure gracefully', async () => { mockProvider.request .mockRejectedValueOnce(new Error('eth_accounts failed')) .mockResolvedValueOnce('0x1'); const result = await ConnectorUtil.fetchProviderData(mockConnector); expect(result).toEqual({ accounts: [], chainId: undefined }); }); it('should handle eth_chainId request failure gracefully', async () => { mockProvider.request .mockResolvedValueOnce(['0x123']) .mockRejectedValueOnce(new Error('eth_chainId failed')); const result = await ConnectorUtil.fetchProviderData(mockConnector); expect(result).toEqual({ accounts: [], chainId: undefined }); }); it('should handle both requests failing gracefully', async () => { mockProvider.request .mockRejectedValueOnce(new Error('eth_accounts failed')) .mockRejectedValueOnce(new Error('eth_chainId failed')); const result = await ConnectorUtil.fetchProviderData(mockConnector); expect(result).toEqual({ accounts: [], chainId: undefined }); }); it('should convert various hex chainId formats correctly', async () => { const testCases = [ { hex: '0x1', expected: 1 }, { hex: '0xa', expected: 10 }, { hex: '0x38', expected: 56 }, { hex: '0x89', expected: 137 }, { hex: '0xa4b1', expected: 42161 } ]; for (const { hex, expected } of testCases) { mockProvider.request.mockClear(); mockProvider.request.mockResolvedValueOnce(['0x123']).mockResolvedValueOnce(hex); const result = await ConnectorUtil.fetchProviderData(mockConnector); expect(result.chainId).toBe(expected); } }); it('should handle Browser Wallet on mobile correctly', async () => { vi.spyOn(CoreHelperUtil, 'isMobile').mockReturnValue(true); const browserWalletConnector = { ...mockConnector, name: 'Browser Wallet' }; const mockAccounts = ['0x789']; const mockChainId = '0x1'; mockProvider.request.mockResolvedValueOnce(mockAccounts).mockResolvedValueOnce(mockChainId); const result = await ConnectorUtil.fetchProviderData(browserWalletConnector); expect(result).toEqual({ accounts: mockAccounts, chainId: 1 }); expect(mockProvider.request).toHaveBeenCalledTimes(2); expect(mockProvider.request).toHaveBeenNthCalledWith(1, { method: 'eth_accounts' }); expect(mockProvider.request).toHaveBeenNthCalledWith(2, { method: 'eth_chainId' }); }); }); }); //# sourceMappingURL=ConnectorUtil.test.js.map