From 1b7eb76d2180ec2bac7426cd588a4ef8857fd793 Mon Sep 17 00:00:00 2001 From: richardkeep Date: Sat, 31 Oct 2026 23:33:44 +0300 Subject: [PATCH 1/2] fix: keep the follow suggestions in place when syncing your profile from GitHub --- resources/js/components/edit-profile-menu.tsx | 1 + resources/js/pages/user-profile/edit.tsx | 5 +- tests/Unit/ProfileSync.test.tsx | 85 +++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 tests/Unit/ProfileSync.test.tsx diff --git a/resources/js/components/edit-profile-menu.tsx b/resources/js/components/edit-profile-menu.tsx index 491cff6465..7db85ef977 100644 --- a/resources/js/components/edit-profile-menu.tsx +++ b/resources/js/components/edit-profile-menu.tsx @@ -17,6 +17,7 @@ export function EditProfileMenu() { const sync = () => router.visit(UserProfileController.update(), { + except: ['suggestedUsers'], preserveScroll: true, onStart: () => setIsSyncing(true), onFinish: () => setIsSyncing(false), diff --git a/resources/js/pages/user-profile/edit.tsx b/resources/js/pages/user-profile/edit.tsx index b771cdfe27..308ca7f711 100644 --- a/resources/js/pages/user-profile/edit.tsx +++ b/resources/js/pages/user-profile/edit.tsx @@ -67,7 +67,10 @@ export default function Edit({
router.flushAll()} > {({ processing }) => ( diff --git a/tests/Unit/ProfileSync.test.tsx b/tests/Unit/ProfileSync.test.tsx new file mode 100644 index 0000000000..10ea98aa48 --- /dev/null +++ b/tests/Unit/ProfileSync.test.tsx @@ -0,0 +1,85 @@ +/// +import assert from 'node:assert/strict'; +import * as React from 'react'; +import type { ReactElement, ReactNode } from 'react'; +import { test, vi } from 'vite-plus/test'; + +type Props = Record & { children?: ReactNode }; +const visits: { except?: string[]; preserveScroll?: boolean }[] = []; + +vi.doMock('react', () => ({ + ...React, + useState: (initial: unknown) => [initial, () => {}], +})); +vi.doMock('@inertiajs/react', async () => ({ + ...(await vi.importActual('@inertiajs/react')), + router: { + visit: (_url: unknown, options: (typeof visits)[number]) => + visits.push(options), + }, +})); +vi.doMock('@/hooks/use-user', () => ({ + useUser: () => ({ user: { id: 'viewer', handle: 'viewer' } }), +})); +vi.doMock('@/hooks/use-now', () => ({ useNow: () => 0 })); + +const { EditProfileMenu } = + await import('../../resources/js/components/edit-profile-menu'); +const { default: Edit } = + await import('../../resources/js/pages/user-profile/edit'); + +function find( + node: ReactNode, + matches: (props: Props) => boolean, +): ReactElement | null { + if (Array.isArray(node)) { + for (const child of node) { + const found = find(child, matches); + + if (found) { + return found; + } + } + + return null; + } + + if (!React.isValidElement(node)) { + return null; + } + + return matches(node.props) ? node : find(node.props.children, matches); +} + +test('syncing from the profile menu keeps the loaded follow suggestions', () => { + const sync = find( + EditProfileMenu(), + (props) => props['data-test'] === 'sync-profile', + ); + assert.ok(sync); + + (sync.props.onSelect as () => void)(); + + assert.deepEqual(visits.at(-1)?.except, ['suggestedUsers']); + assert.equal(visits.at(-1)?.preserveScroll, true); +}); + +test('syncing from settings keeps the loaded follow suggestions', () => { + const form = find( + Edit({ + translationLanguage: null, + translationLanguages: [], + preferredLane: null, + automaticLane: 1, + githubSyncedAt: null, + activityGraphUrl: '/activity', + profileUrl: '/@viewer', + }), + (props) => 'options' in props && 'onSuccess' in props, + ); + assert.ok(form); + + const options = form.props.options as (typeof visits)[number]; + assert.deepEqual(options.except, ['suggestedUsers']); + assert.equal(options.preserveScroll, true); +}); From 995ac0f3c38802a1bd1f4fa53f97a70c5f6fb532 Mon Sep 17 00:00:00 2001 From: richardkeep Date: Sun, 1 Nov 2026 00:03:58 +0300 Subject: [PATCH 2/2] fix: reload missing suggestions and keep the profile feed when syncing --- package.json | 2 +- resources/js/components/edit-profile-menu.tsx | 10 +- resources/js/pages/user-profile/edit.tsx | 8 +- tests/Unit/ProfileSync.test.tsx | 113 +++++++++++++----- 4 files changed, 96 insertions(+), 37 deletions(-) diff --git a/package.json b/package.json index a95c6f84ee..b52d8969d7 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "lint": "NODE_OPTIONS='--experimental-strip-types' vp fmt resources/ && NODE_OPTIONS='--experimental-strip-types' vp lint --fix", "test:lint": "NODE_OPTIONS='--experimental-strip-types' vp fmt --check resources/ && NODE_OPTIONS='--experimental-strip-types' vp lint", "test:types": "tsc --noEmit && tsc --noEmit --project tests/tsconfig.json", - "test:unit": "php artisan wayfinder:generate --with-form && node --experimental-strip-types --test tests/Unit/*.test.ts" + "test:unit": "php artisan wayfinder:generate --with-form && node --experimental-strip-types --test tests/Unit/*.test.ts && vp test run tests/Unit/*.test.tsx" }, "dependencies": { "@daypicker/react": "^10.0.2", diff --git a/resources/js/components/edit-profile-menu.tsx b/resources/js/components/edit-profile-menu.tsx index 7db85ef977..e9480beb85 100644 --- a/resources/js/components/edit-profile-menu.tsx +++ b/resources/js/components/edit-profile-menu.tsx @@ -17,11 +17,17 @@ export function EditProfileMenu() { const sync = () => router.visit(UserProfileController.update(), { - except: ['suggestedUsers'], + except: ['suggestedUsers', 'commits'], preserveScroll: true, onStart: () => setIsSyncing(true), onFinish: () => setIsSyncing(false), - onSuccess: () => router.flushAll(), + onSuccess: (page) => { + router.flushAll(); + + if (page.props.suggestedUsers === undefined) { + router.reload({ only: ['suggestedUsers'] }); + } + }, }); return ( diff --git a/resources/js/pages/user-profile/edit.tsx b/resources/js/pages/user-profile/edit.tsx index 308ca7f711..c0d521a45c 100644 --- a/resources/js/pages/user-profile/edit.tsx +++ b/resources/js/pages/user-profile/edit.tsx @@ -71,7 +71,13 @@ export default function Edit({ except: ['suggestedUsers'], preserveScroll: true, }} - onSuccess={() => router.flushAll()} + onSuccess={(page) => { + router.flushAll(); + + if (page.props.suggestedUsers === undefined) { + router.reload({ only: ['suggestedUsers'] }); + } + }} > {({ processing }) => (