From 505e8f022024aacdc100c6a47b45ea733fa4e3be Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 27 Oct 2026 16:00:02 -0700 Subject: [PATCH] fix(v2): link Terms and Privacy from the footer and signup /terms and /privacy shipped with no link reaching them. The landing footer's Legal column gains Terms and Privacy, and signup gains one line under the form naming both pages. en and zh-CN together. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MDs9DS3E4dzoHKdxtgQqyz --- frontend/src/i18n/locales/en.json | 3 ++ frontend/src/i18n/locales/zh-CN.json | 3 ++ frontend/src/v2/__tests__/V2Register.test.tsx | 13 +++++++ frontend/src/v2/components/V2Register.tsx | 10 ++++++ frontend/src/v2/landing/V2LandingPage.tsx | 2 ++ .../__tests__/landingLegalLinks.test.tsx | 34 +++++++++++++++++++ 6 files changed, 65 insertions(+) create mode 100644 frontend/src/v2/landing/__tests__/landingLegalLinks.test.tsx diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index 727cc96eb0..863de44485 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -355,6 +355,7 @@ "submit": "Create account", "creating": "Creating account...", "alreadyHaveAccount": "Already have an account?", + "legal": "By creating an account you agree to the Terms and Privacy policy.", "errors": { "failed": "Registration failed." }, @@ -1039,6 +1040,8 @@ "twitter": "X / Twitter", "legal": "Legal", "license": "License (Apache-2.0)", + "terms": "Terms", + "privacy": "Privacy", "copyright": "© {{year}} Commonly. Code licensed under Apache-2.0; the Commonly name and logo are trademarks of the Commonly project." } }, diff --git a/frontend/src/i18n/locales/zh-CN.json b/frontend/src/i18n/locales/zh-CN.json index e9260fe305..eca298ed86 100644 --- a/frontend/src/i18n/locales/zh-CN.json +++ b/frontend/src/i18n/locales/zh-CN.json @@ -355,6 +355,7 @@ "submit": "注册", "creating": "正在注册…", "alreadyHaveAccount": "已有账号?", + "legal": "创建账号即表示你同意服务条款和隐私政策。", "errors": { "failed": "注册失败。" }, @@ -1038,6 +1039,8 @@ "twitter": "X / Twitter", "legal": "法律信息", "license": "许可证(Apache-2.0)", + "terms": "服务条款", + "privacy": "隐私政策", "copyright": "© {{year}} Commonly。代码采用 Apache-2.0 许可;Commonly 名称和标志是 Commonly 项目的商标。" } }, diff --git a/frontend/src/v2/__tests__/V2Register.test.tsx b/frontend/src/v2/__tests__/V2Register.test.tsx index 6c303f46d1..b69b22cc9a 100644 --- a/frontend/src/v2/__tests__/V2Register.test.tsx +++ b/frontend/src/v2/__tests__/V2Register.test.tsx @@ -316,3 +316,16 @@ describe('V2Register invite code handoff', () => { expect(body.invitationCode).toBe('CM-KEPT'); }); }); + +// Launch row 2: signup links the Terms and Privacy pages it asks people to agree to. +describe('V2Register legal links', () => { + beforeEach(() => { + axios.get.mockResolvedValue({ data: { inviteOnly: false, providers: [] } }); + }); + + it('links Terms and Privacy under the form', async () => { + renderRegister(); + expect(await screen.findByRole('link', { name: 'Terms' })).toHaveAttribute('href', '/terms'); + expect(screen.getByRole('link', { name: 'Privacy' })).toHaveAttribute('href', '/privacy'); + }); +}); diff --git a/frontend/src/v2/components/V2Register.tsx b/frontend/src/v2/components/V2Register.tsx index ba14429a24..9a0918b69f 100644 --- a/frontend/src/v2/components/V2Register.tsx +++ b/frontend/src/v2/components/V2Register.tsx @@ -239,6 +239,16 @@ const V2Register: React.FC = () => { +
+ , + privacy: , + }} + /> +
+
{t('auth.register.alreadyHaveAccount')} {' '} diff --git a/frontend/src/v2/landing/V2LandingPage.tsx b/frontend/src/v2/landing/V2LandingPage.tsx index eaa8b11ea1..280d4a4967 100644 --- a/frontend/src/v2/landing/V2LandingPage.tsx +++ b/frontend/src/v2/landing/V2LandingPage.tsx @@ -965,6 +965,8 @@ const V2LandingPage: React.FC = () => {
{t('landing.footer.legal')}
{t('landing.footer.license')} + {t('landing.footer.terms')} + {t('landing.footer.privacy')}
{/* Copyright is retained under Apache-2.0 — the license grants diff --git a/frontend/src/v2/landing/__tests__/landingLegalLinks.test.tsx b/frontend/src/v2/landing/__tests__/landingLegalLinks.test.tsx new file mode 100644 index 0000000000..9399821292 --- /dev/null +++ b/frontend/src/v2/landing/__tests__/landingLegalLinks.test.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { render, screen, within } from '@testing-library/react'; +import { MemoryRouter } from 'react-router-dom'; +import axios from 'axios'; +import i18n from '../../../i18n'; +import { useAuth } from '../../../context/AuthContext'; +import V2LandingPage from '../V2LandingPage'; + +/** + * Launch row 2. /terms and /privacy shipped with no link reaching them; the + * footer's Legal column is where a visitor looks for both. + */ + +jest.mock('axios'); +jest.mock('../../../context/AuthContext', () => ({ + useAuth: jest.fn(), +})); + +describe('V2LandingPage legal links', () => { + beforeEach(async () => { + (axios.get as jest.Mock).mockResolvedValue({ data: {} }); + (useAuth as jest.Mock).mockReturnValue({ isAuthenticated: false }); + await i18n.changeLanguage('en'); + }); + + afterEach(() => jest.clearAllMocks()); + + it('links Terms and Privacy from the footer', () => { + const { container } = render(); + const footer = container.querySelector('footer') as HTMLElement; + expect(within(footer).getByRole('link', { name: 'Terms' })).toHaveAttribute('href', '/terms'); + expect(within(footer).getByRole('link', { name: 'Privacy' })).toHaveAttribute('href', '/privacy'); + }); +});