import { describe, expect, test } from 'vitest'; import { buildMobileShellUrlFromDeepLink } from './mobileShellDeepLink'; const options = { platform: 'ios' as const, hostVersion: '0.1.0', capabilities: ['host.getRuntime' as const], }; describe('buildMobileShellUrlFromDeepLink', () => { test('把原生 scheme deep link 映射成同源 H5 目标页', () => { const url = new URL( buildMobileShellUrlFromDeepLink( 'genarrative://open/works/detail?work=PZ-1', 'https://app.genarrative.world/', options, ), ); expect(url.origin).toBe('https://app.genarrative.world'); expect(url.pathname).toBe('/works/detail'); expect(url.searchParams.get('work')).toBe('PZ-1'); expect(url.searchParams.get('clientRuntime')).toBe('native_app'); expect(url.searchParams.get('hostShell')).toBe('expo_mobile'); }); test('把同源 universal link 映射成带宿主上下文的 H5 URL', () => { const url = new URL( buildMobileShellUrlFromDeepLink( 'https://app.genarrative.world/creation/puzzle#draft', 'https://app.genarrative.world/', options, ), ); expect(url.pathname).toBe('/creation/puzzle'); expect(url.hash).toBe('#draft'); expect(url.searchParams.get('hostCapabilities')).toBe('host.getRuntime'); }); test('外域和危险协议回退到默认首页', () => { const external = new URL( buildMobileShellUrlFromDeepLink( 'https://example.com/works/detail?work=PZ-1', 'https://app.genarrative.world/', options, ), ); const unsafe = new URL( buildMobileShellUrlFromDeepLink( 'javascript:alert(1)', 'https://app.genarrative.world/', options, ), ); expect(external.origin).toBe('https://app.genarrative.world'); expect(external.pathname).toBe('/'); expect(unsafe.origin).toBe('https://app.genarrative.world'); expect(unsafe.pathname).toBe('/'); }); test('协议相对外域 URL 不会被装进移动壳 WebView', () => { const url = new URL( buildMobileShellUrlFromDeepLink( '//example.com/works/detail?work=PZ-1', 'https://app.genarrative.world/', options, ), ); expect(url.origin).toBe('https://app.genarrative.world'); expect(url.pathname).toBe('/'); }); });