import {renderHook} from '@testing-library/react' import {describe, expect, it, vi, beforeEach, afterEach} from 'vitest' import {useDeeplink} from './useDeeplink' vi.mock('../../utils/parseUrl', () => ({ parseUrl: vi.fn(), })) const {parseUrl} = await import('../../utils/parseUrl') describe('useDeeplink', () => { const originalMinisParams = (window as any).minisParams beforeEach(() => { vi.clearAllMocks() }) afterEach(() => { ;(window as any).minisParams = originalMinisParams }) describe('Without initialUrl', () => { beforeEach(() => { ;(window as any).minisParams = { initialUrl: undefined, handle: 'test-mini', } }) it('returns undefined values when initialUrl is not provided', () => { const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: undefined, queryParams: undefined, hash: undefined, }) expect(parseUrl).not.toHaveBeenCalled() }) }) describe('With initialUrl', () => { beforeEach(() => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/products?category=clothing', handle: 'test-mini', } }) it('parses URL and strips mini handle prefix from pathname', () => { vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/products', query: {category: 'clothing'}, hash: '', } as any) const {result} = renderHook(() => useDeeplink()) expect(parseUrl).toHaveBeenCalledWith( 'https://shop.app/mini/test-mini/products?category=clothing' ) expect(result.current).toEqual({ path: '/products', queryParams: {category: 'clothing'}, hash: '', }) }) it('returns pathname as-is when it does not contain mini handle prefix', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/some-other-path', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/some-other-path', query: {}, hash: '', } as any) const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: '/some-other-path', queryParams: {}, hash: '', }) }) it('handles URL with multiple query parameters', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/search?q=shoes&page=2&sort=price', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/search', query: {q: 'shoes', page: '2', sort: 'price'}, hash: '', } as any) const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: '/search', queryParams: {q: 'shoes', page: '2', sort: 'price'}, hash: '', }) }) it('handles URL with hash', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/page#section-2', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/page', query: {}, hash: '#section-2', } as any) const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: '/page', queryParams: {}, hash: '#section-2', }) }) it('handles URL with both query params and hash', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/products?filter=sale#top', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/products', query: {filter: 'sale'}, hash: '#top', } as any) const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: '/products', queryParams: {filter: 'sale'}, hash: '#top', }) }) it('handles root path after stripping prefix', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini', query: {}, hash: '', } as any) const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: '', queryParams: {}, hash: '', }) }) it('handles root path with trailing slash', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/', query: {}, hash: '', } as any) const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: '/', queryParams: {}, hash: '', }) }) it('handles nested paths', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/category/shoes/product/123', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/category/shoes/product/123', query: {}, hash: '', } as any) const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: '/category/shoes/product/123', queryParams: {}, hash: '', }) }) it('handles different mini handle', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/another-mini/dashboard', handle: 'another-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/another-mini/dashboard', query: {}, hash: '', } as any) const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: '/dashboard', queryParams: {}, hash: '', }) }) }) describe('Memoization', () => { it('returns same reference when dependencies do not change', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/products', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/products', query: {}, hash: '', } as any) const {result, rerender} = renderHook(() => useDeeplink()) const firstResult = result.current rerender() expect(result.current).toBe(firstResult) expect(parseUrl).toHaveBeenCalledTimes(1) }) it('recomputes when initialUrl changes', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/products', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/products', query: {}, hash: '', } as any) const {result, rerender} = renderHook(() => useDeeplink()) const firstResult = result.current // Change initialUrl ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/cart', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/cart', query: {}, hash: '', } as any) rerender() expect(result.current).not.toBe(firstResult) expect(result.current.path).toBe('/cart') expect(parseUrl).toHaveBeenCalledTimes(2) }) it('recomputes when handle changes', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/products', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/products', query: {}, hash: '', } as any) const {result, rerender} = renderHook(() => useDeeplink()) const firstResult = result.current // Change handle ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/products', handle: 'different-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/products', query: {}, hash: '', } as any) rerender() expect(result.current).not.toBe(firstResult) expect(parseUrl).toHaveBeenCalledTimes(2) }) }) describe('Edge Cases', () => { it('handles empty initialUrl string', () => { ;(window as any).minisParams = { initialUrl: '', handle: 'test-mini', } const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: undefined, queryParams: undefined, hash: undefined, }) expect(parseUrl).not.toHaveBeenCalled() }) it('handles null initialUrl', () => { ;(window as any).minisParams = { initialUrl: null, handle: 'test-mini', } const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: undefined, queryParams: undefined, hash: undefined, }) expect(parseUrl).not.toHaveBeenCalled() }) it('handles query params with undefined values', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/search?q=&page=1', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/search', query: {q: undefined, page: '1'}, hash: '', } as any) const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: '/search', queryParams: {q: undefined, page: '1'}, hash: '', }) }) it('handles pathname with special characters', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini/search?q=%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini/search', query: {q: 'S�kao'}, hash: '', } as any) const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: '/search', queryParams: {q: 'S�kao'}, hash: '', }) }) it('handles case where pathname is just the prefix', () => { ;(window as any).minisParams = { initialUrl: 'https://shop.app/mini/test-mini', handle: 'test-mini', } vi.mocked(parseUrl).mockReturnValue({ pathname: '/mini/test-mini', query: {}, hash: '', } as any) const {result} = renderHook(() => useDeeplink()) expect(result.current).toEqual({ path: '', queryParams: {}, hash: '', }) }) }) })