diff --git a/website/src/__tests__/public-marketing-pages.test.tsx b/website/src/__tests__/public-marketing-pages.test.tsx index e916205..7585e3d 100644 --- a/website/src/__tests__/public-marketing-pages.test.tsx +++ b/website/src/__tests__/public-marketing-pages.test.tsx @@ -508,6 +508,62 @@ describe('public marketing pages', () => { errors: [], }, }) + mockGetReleaseManifest.mockResolvedValue({ + ok: true, + manifest: { + generated_at: '2026-06-22T12:00:00.000Z', + support_email: 'hello@hypertwist.app', + public_docs_url: 'https://docs.hypertwist.app', + release_notes_url: 'https://notes.hypertwist.app', + corresponding_source_url: 'https://hypertwist.app/open-source/source.zip', + open_source_repo_url: 'https://github.com/hypertwist/hypertwist', + viewer: { + authenticated: false, + canDownload: false, + plan: null, + role: null, + accessStatus: null, + }, + platforms: [ + { + platform_key: 'windows', + platform: 'Windows', + subtitle: 'Primary shipping lane', + details: 'Current packaged validation is strongest on the Windows Unreal lane.', + configured: true, + channel: 'candidate', + version: '1.0.0', + build_id: 'win64-1000', + published_at: '2026-06-22T00:00:00.000Z', + file_name: 'HyperTwist-Windows.zip', + file_size_bytes: 1048576, + checksum_sha256: 'abc123', + download_url: null, + download_available: false, + validation_summary: { + lane: 'Windows Unreal packaged validation', + result: 'passed', + generated_at: '2026-06-22T01:43:08.7625247Z', + configuration: 'Development', + skip_build: true, + smoke_map_count: 2, + smoke_maps: [ + { + map_url: '/Game/HyperTwistTraining/Maps/L_HyperTwist_Magic120CellTraining', + label: 'Magic120Cell dedicated-family training map', + result: 'passed', + }, + { + map_url: '/Game/HyperTwistTraining/Maps/L_HyperTwist_MagicCube5DTraining', + label: 'MagicCube5D dedicated-family training map', + result: 'passed', + }, + ], + }, + }, + ], + }, + }) renderWithProviders(, ['/features']) @@ -521,6 +577,8 @@ describe('public marketing pages', () => { expect(screen.getAllByText('Selectable immersive and family-specific settings').length).toBeGreaterThan(0) expect(screen.getByText('Current public rollout posture')).toBeTruthy() expect(screen.getByText('Public feature and launch posture')).toBeTruthy() + expect(screen.getByText('Current packaged desktop proof')).toBeTruthy() + expect(screen.getByText('Packaged validation passed')).toBeTruthy() expect(document.title).toBe('HyperTwist features | HyperTwist') expect(document.head.querySelector('meta[property="og:url"]')?.getAttribute('content')).toBe('https://hypertwist.app/features') }) diff --git a/website/src/pages/public-pages-features.tsx b/website/src/pages/public-pages-features.tsx index b325e7e..30ecfb1 100644 --- a/website/src/pages/public-pages-features.tsx +++ b/website/src/pages/public-pages-features.tsx @@ -1,8 +1,13 @@ +import { useMemo } from 'react' +import { useQuery } from '@tanstack/react-query' import { Link } from 'react-router-dom' +import { getReleaseManifest } from '../auth/auth-api' import { MarketingShell } from '../components/layout/MarketingShell' import { SiteMetadata } from '../components/seo/SiteMetadata' import { PublicLaunchStatus } from '../components/ui/PublicLaunchStatus' import { ProductSurfaceMatrix } from '../components/ui/ProductSurfaceMatrix' +import { ReleaseValidationSummary } from '../components/ui/ReleaseValidationSummary' +import { resolveReleaseManifestView } from '../release-manifest' import { controlProfileRosterCards, deploymentReadinessTracks, @@ -14,9 +19,23 @@ import { releaseStoryCards, roadmapHonestyCards, } from '../site-data' -import { Section } from './public-page-helpers' +import { buildPublicReleaseManifestFallback, Section } from './public-page-helpers' export function FeaturesPage() { + const releaseManifestQuery = useQuery({ + queryKey: ['release-manifest', 'public-features'], + queryFn: getReleaseManifest, + retry: false, + }) + const releaseManifest = useMemo( + () => resolveReleaseManifestView(releaseManifestQuery.data?.manifest, buildPublicReleaseManifestFallback()), + [releaseManifestQuery.data?.manifest], + ) + const windowsValidationPlatform = useMemo( + () => releaseManifest.platforms.find((platform) => platform.platform_key === 'windows' && platform.validation_summary) ?? null, + [releaseManifest], + ) + return ( <> + {windowsValidationPlatform ? ( +
+ +
+ + Open download center + + + Open public manual + +
+
+ ) : null} +