From d28c054c29d5c65c31c225cd2813d15d6fa09379 Mon Sep 17 00:00:00 2001 From: Aqil Aziz Date: Wed, 20 May 2026 06:51:13 +0700 Subject: [PATCH] fix(auth): point welcome legal links to docs (#2253) --- app/src/pages/Welcome.tsx | 29 ++++++++++++++++++++++++ app/src/pages/__tests__/Welcome.test.tsx | 21 +++++++++++++++++ app/src/utils/links.ts | 2 ++ 3 files changed, 52 insertions(+) diff --git a/app/src/pages/Welcome.tsx b/app/src/pages/Welcome.tsx index 2c3901937..2f426199e 100644 --- a/app/src/pages/Welcome.tsx +++ b/app/src/pages/Welcome.tsx @@ -13,6 +13,8 @@ import { useDeepLinkAuthState } from '../store/deepLinkAuthState'; import { useAppDispatch } from '../store/hooks'; import { clearAllAppData } from '../utils/clearAllAppData'; import { clearStoredCoreMode, clearStoredCoreToken, storeRpcUrl } from '../utils/configPersistence'; +import { PRIVACY_POLICY_URL, TERMS_OF_USE_URL } from '../utils/links'; +import { openUrl } from '../utils/openUrl'; const log = createDebug('app:welcome'); @@ -128,6 +130,33 @@ const Welcome = () => { /> ))} +

+ By continuing, you agree to the{' '} + { + event.preventDefault(); + void openUrl(TERMS_OF_USE_URL); + }} + className="font-medium text-stone-700 underline underline-offset-2 hover:text-stone-900 dark:text-neutral-300 dark:hover:text-neutral-100"> + Terms + {' '} + and{' '} + { + event.preventDefault(); + void openUrl(PRIVACY_POLICY_URL); + }} + className="font-medium text-stone-700 underline underline-offset-2 hover:text-stone-900 dark:text-neutral-300 dark:hover:text-neutral-100"> + Privacy Policy + + . +

)} diff --git a/app/src/pages/__tests__/Welcome.test.tsx b/app/src/pages/__tests__/Welcome.test.tsx index a238e3e82..5ab861f57 100644 --- a/app/src/pages/__tests__/Welcome.test.tsx +++ b/app/src/pages/__tests__/Welcome.test.tsx @@ -10,6 +10,8 @@ import { clearStoredCoreToken, storeRpcUrl, } from '../../utils/configPersistence'; +import { PRIVACY_POLICY_URL, TERMS_OF_USE_URL } from '../../utils/links'; +import { openUrl } from '../../utils/openUrl'; import Welcome from '../Welcome'; const oauthButtonSpy = vi.fn(); @@ -59,6 +61,8 @@ vi.mock('../../utils/clearAllAppData', () => ({ clearAllAppData: (...args: unknown[]) => mockClearAllAppData(...args), })); +vi.mock('../../utils/openUrl', () => ({ openUrl: vi.fn().mockResolvedValue(undefined) })); + vi.mock('../../services/coreRpcClient', () => ({ clearCoreRpcUrlCache: vi.fn(), clearCoreRpcTokenCache: vi.fn(), @@ -98,6 +102,7 @@ describe('Welcome auth entrypoint', () => { beforeEach(() => { oauthButtonSpy.mockReset(); oauthOverrideSpy.mockReset(); + vi.mocked(openUrl).mockClear(); vi.mocked(useDeepLinkAuthState).mockReturnValue({ isProcessing: false, errorMessage: null, @@ -116,6 +121,22 @@ describe('Welcome auth entrypoint', () => { expect(screen.queryByRole('button', { name: 'discord' })).not.toBeInTheDocument(); }); + it('renders legal links with valid targets and opens them externally', () => { + renderWithProviders(); + + const termsLink = screen.getByRole('link', { name: 'Terms' }); + const privacyLink = screen.getByRole('link', { name: 'Privacy Policy' }); + + expect(termsLink).toHaveAttribute('href', TERMS_OF_USE_URL); + expect(privacyLink).toHaveAttribute('href', PRIVACY_POLICY_URL); + + fireEvent.click(termsLink); + fireEvent.click(privacyLink); + + expect(openUrl).toHaveBeenNthCalledWith(1, TERMS_OF_USE_URL); + expect(openUrl).toHaveBeenNthCalledWith(2, PRIVACY_POLICY_URL); + }); + it('delegates OAuth clicks to OAuthProviderButton without an override', () => { renderWithProviders(); diff --git a/app/src/utils/links.ts b/app/src/utils/links.ts index 3aa1fa4f8..87e4e85bd 100644 --- a/app/src/utils/links.ts +++ b/app/src/utils/links.ts @@ -1,2 +1,4 @@ export const DISCORD_INVITE_URL = 'https://discord.tinyhumans.ai'; export const BILLING_DASHBOARD_URL = 'https://tinyhumans.ai/dashboard'; +export const PRIVACY_POLICY_URL = 'https://tinyhumans.gitbook.io/openhuman/legal/privacy-policy'; +export const TERMS_OF_USE_URL = 'https://tinyhumans.gitbook.io/openhuman/legal/terms-of-use';