Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions apps/desktop/src/main/__tests__/account-auth-ui.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ describe('Account settings credential probe UI', () => {
);
assert.match(
page,
/const accountPageMountedRef = useRef\(false\);[\s\S]*useEffect\(\(\) => \{[\s\S]*accountPageMountedRef\.current = true;[\s\S]*return \(\) => \{[\s\S]*accountPageMountedRef\.current = false;[\s\S]*testingSlugRef\.current = null;/,
/const accountPageMountedRef = useMountedRef\(\);[\s\S]*useEffect\(\(\) => \{[\s\S]*return \(\) => \{[\s\S]*testingSlugRef\.current = null;/,
'Account page must release test ownership when Settings closes',
);
assert.match(
Expand All @@ -258,12 +258,12 @@ describe('Account settings credential probe UI', () => {

assert.match(
page,
/const accountPageMountedRef = useRef\(false\);/,
/const accountPageMountedRef = useMountedRef\(\);/,
'Account page must track mounted ownership for connection tests',
);
assert.match(
page,
/return \(\) => \{[\s\S]*accountPageMountedRef\.current = false;[\s\S]*testingSlugRef\.current = null;/,
/return \(\) => \{[\s\S]*testingSlugRef\.current = null;/,
'Account page cleanup must release an in-flight connection test owner',
);
assert.match(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('ArtifactPane async lifecycle contract', () => {
);
assert.match(
src,
/const artifactPaneMountedRef = useRef\(true\)/,
/const artifactPaneMountedRef = useMountedRef\(\)/,
'ArtifactPane must track whether async artifact work still owns a mounted surface',
);
assert.match(
Expand All @@ -39,7 +39,7 @@ describe('ArtifactPane async lifecycle contract', () => {
);
assert.match(
src,
/useEffect\(\(\) => \{[\s\S]*artifactPaneMountedRef\.current = true;[\s\S]*return \(\) => \{[\s\S]*artifactPaneMountedRef\.current = false;[\s\S]*artifactListRequestSeqRef\.current \+= 1;[\s\S]*pendingArtifactListRetryRef\.current = false;[\s\S]*pendingArtifactActionRef\.current = null;[\s\S]*\};[\s\S]*\}, \[\]\)/,
/useEffect\(\(\) => \{[\s\S]*return \(\) => \{[\s\S]*artifactListRequestSeqRef\.current \+= 1;[\s\S]*pendingArtifactListRetryRef\.current = false;[\s\S]*pendingArtifactActionRef\.current = null;[\s\S]*\};[\s\S]*\}, \[\]\)/,
'ArtifactPane unmount must invalidate list responses, release pending owners, and be StrictMode replay safe',
);
assert.match(
Expand Down Expand Up @@ -181,7 +181,7 @@ describe('ArtifactPane async lifecycle contract', () => {

assert.match(src, /const \[pendingArtifactAction, setPendingArtifactAction\] = useState<string \| null>\(null\)/);
assert.match(src, /const pendingArtifactActionRef = useRef<string \| null>\(null\)/);
assert.match(src, /const artifactPaneMountedRef = useRef\(true\)/);
assert.match(src, /const artifactPaneMountedRef = useMountedRef\(\)/);
assert.match(src, /const artifactActionBusy = pendingArtifactAction !== null/);
assert.match(
gateBlock,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,10 @@ describe('Bot settings UI contract', () => {
const refreshBlock = pageBlock.match(/async function refreshBotStatuses\(\)[\s\S]*?async function disconnectWechatLogin/)?.[0] ?? '';
const disconnectBlock = pageBlock.match(/async function disconnectWechatLogin\(\)[\s\S]*?const support =/)?.[0] ?? '';

assert.match(pageBlock, /const botPageMountedRef = useRef\(false\)/);
assert.match(pageBlock, /const botPageMountedRef = useMountedRef\(\)/);
assert.match(
pageBlock,
/useEffect\(\(\) => \{[\s\S]*botPageMountedRef\.current = true;[\s\S]*return \(\) => \{[\s\S]*botPageMountedRef\.current = false;[\s\S]*pendingBotActionRef\.current = null;/,
/useEffect\(\(\) => \{[\s\S]*return \(\) => \{[\s\S]*pendingBotActionRef\.current = null;/,
'Bot settings page cleanup must release owned async actions when Settings closes',
);
assert.match(
Expand Down Expand Up @@ -249,11 +249,11 @@ describe('Bot settings UI contract', () => {
assert.match(settings, /const fetchingQrRef = useRef\(false\)/, 'Direct WeChat scan-login refresh must keep a synchronous pending guard');
assert.match(settings, /const scanLoginPollingRef = useRef\(false\)/, 'Direct WeChat scan-login status polling must keep a synchronous in-flight guard');
assert.match(settings, /const scanLoginConfirmingRef = useRef\(false\)/, 'Direct WeChat scan-login confirmation must keep a synchronous owner guard');
assert.match(settings, /const scanLoginMountedRef = useRef\(false\)/, 'Direct WeChat scan-login modal must track mounted ownership');
assert.match(settings, /const scanLoginMountedRef = useMountedRef\(\)/, 'Direct WeChat scan-login modal must track mounted ownership');
assert.match(settings, /const scanLoginFetchTicketRef = useRef\(0\)/, 'Direct WeChat scan-login modal must invalidate stale QR fetches across remounts');
assert.match(
settings,
/useEffect\(\(\) => \{[\s\S]*scanLoginMountedRef\.current = true;[\s\S]*void fetchQr\(\);[\s\S]*return \(\) => \{[\s\S]*scanLoginMountedRef\.current = false;[\s\S]*scanLoginFetchTicketRef\.current \+= 1;[\s\S]*fetchingQrRef\.current = false;[\s\S]*scanLoginPollingRef\.current = false;[\s\S]*scanLoginConfirmingRef\.current = false;/,
/useEffect\(\(\) => \{[\s\S]*void fetchQr\(\);[\s\S]*return \(\) => \{[\s\S]*scanLoginFetchTicketRef\.current \+= 1;[\s\S]*fetchingQrRef\.current = false;[\s\S]*scanLoginPollingRef\.current = false;[\s\S]*scanLoginConfirmingRef\.current = false;/,
'Direct WeChat scan-login modal must release QR, poll, and confirmation ownership when closed',
);
assert.match(settings, /if \(fetchingQrRef\.current\) return;[\s\S]*fetchingQrRef\.current = true;[\s\S]*const ticket = \+\+scanLoginFetchTicketRef\.current;[\s\S]*setStatus\('fetching'\)/, 'Direct WeChat scan-login QR fetch must block rapid duplicate refreshes before React rerenders');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ describe('home composer new-chat model picker', () => {
const renderer = await readRendererShellSources([
'app-shell.tsx',
'app-shell-chat-actions.ts',
'use-shell-chat-model.ts',
]);

assert.match(
Expand Down Expand Up @@ -123,6 +124,7 @@ describe('home composer new-chat model picker', () => {
const renderer = await readRendererShellSources([
'app-shell.tsx',
'app-shell-chat-actions.ts',
'use-shell-chat-model.ts',
]);

assert.match(
Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/main/__tests__/composer-send-guard.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ describe('composer send guard', () => {
const composerBlock = source.match(/export const Composer = forwardRef[\s\S]*$/)?.[0] ?? '';
const sendCurrent = source.match(/async function sendCurrent\(\) \{[\s\S]*?\n \}/)?.[0] ?? '';

assert.match(composerBlock, /const composerMountedRef = useRef\(true\)/);
assert.match(composerBlock, /const composerMountedRef = useMountedRef\(\)/);
assert.match(
composerBlock,
/useEffect\(\(\) => \{\s*composerMountedRef\.current = true;[\s\S]*?return \(\) => \{\s*composerMountedRef\.current = false;\s*sendPendingRef\.current = false;\s*importActionOwnerRef\.current\?\.reset\(\);\s*\};\s*\}, \[\]\)/,
/useEffect\(\(\) => \{\s*return \(\) => \{\s*sendPendingRef\.current = false;\s*importActionOwnerRef\.current\?\.reset\(\);\s*\};\s*\}, \[\]\)/,
'Composer must release send/import pending owners when it unmounts or StrictMode replays cleanup',
);
assert.match(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,11 @@ describe('Daily Review copy feedback contract', () => {
assert.ok(gateBlock, 'runDailyReviewAction gate not found in DailyReviewPanel');

assert.match(panelBlock, /const \[pendingDailyReviewAction, setPendingDailyReviewAction\] = useState<string \| null>\(null\)/);
assert.match(panelBlock, /const dailyReviewMountedRef = useRef\(true\)/);
assert.match(panelBlock, /const dailyReviewMountedRef = useMountedRef\(\)/);
assert.match(panelBlock, /const pendingDailyReviewActionRef = useRef<string \| null>\(null\)/);
assert.match(
panelBlock,
/useEffect\(\(\) => \{\s*dailyReviewMountedRef\.current = true;[\s\S]*?return \(\) => \{\s*dailyReviewMountedRef\.current = false;\s*pendingDailyReviewActionRef\.current = null;\s*(?:archiveLoadRequestRef\.current \+= 1;\s*)?\};\s*\}, \[\]\)/,
/useEffect\(\(\) => \{\s*return \(\) => \{\s*pendingDailyReviewActionRef\.current = null;\s*(?:archiveLoadRequestRef\.current \+= 1;\s*)?\};\s*\}, \[\]\)/,
'Daily Review export pending ownership must be released when the main panel unmounts or StrictMode replays cleanup',
);
assert.match(panelBlock, /const dailyReviewActionBusy = pendingDailyReviewAction !== null/);
Expand Down Expand Up @@ -194,7 +194,7 @@ describe('Daily Review copy feedback contract', () => {
assert.match(panelBlock, /const archiveLoadRequestRef = useRef\(0\)/);
assert.match(
panelBlock,
/return \(\) => \{\s*dailyReviewMountedRef\.current = false;\s*pendingDailyReviewActionRef\.current = null;\s*archiveLoadRequestRef\.current \+= 1;\s*\};/,
/return \(\) => \{\s*pendingDailyReviewActionRef\.current = null;\s*archiveLoadRequestRef\.current \+= 1;\s*\};/,
'Daily Review archive loads must be invalidated when the panel unmounts',
);
assert.match(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe('FIRST_RUN_TASK_SUGGESTIONS', () => {
const gateBlock = readyBlock.match(/const runImportAction = useCallback[\s\S]*?const importActionBusy/)?.[0] ?? '';

assert.match(readyBlock, /const \[pendingImportAction, setPendingImportAction\] = useState<string \| null>\(null\)/);
assert.match(readyBlock, /const readyHeroMountedRef = useRef\(true\)/);
assert.match(readyBlock, /const readyHeroMountedRef = useMountedRef\(\)/);
assert.match(readyBlock, /const importActionOwnerRef = useRef<ChatInputActionOwner<string> \| null>\(null\)/);
assert.match(readyBlock, /importActionOwnerRef\.current = createChatInputActionOwner/);
assert.match(readyBlock, /const importActionBusy = pendingImportAction !== null/);
Expand Down Expand Up @@ -181,11 +181,11 @@ describe('FIRST_RUN_TASK_SUGGESTIONS', () => {
assert.match(refreshBlock, /workspaceInstructions\.getState\(\)\.then\([\s\S]*?\.catch\(\(error\) => \{[\s\S]*setWorkspaceInstructionCount\(null\);[\s\S]*handleProbeFailure\(error\)/);
assert.doesNotMatch(refreshBlock, /catch[\s\S]*setSettings\(null\)|catch[\s\S]*setPlanReminders\(\[\]\)|catch[\s\S]*setWorkspaceInstructionCount\(0\)/);
assert.match(source, /const \[statusRefreshPending, setStatusRefreshPending\] = useState\(false\)/);
assert.match(source, /const checklistMountedRef = useRef\(true\)/);
assert.match(source, /const checklistMountedRef = useMountedRef\(\)/);
assert.match(source, /const statusRefreshPendingRef = useRef\(false\)/);
assert.match(
source,
/useEffect\(\(\) => \{[\s\S]*checklistMountedRef\.current = true;[\s\S]*return \(\) => \{[\s\S]*checklistMountedRef\.current = false;[\s\S]*statusRefreshPendingRef\.current = false;[\s\S]*\};[\s\S]*\}, \[\]\)/,
/useEffect\(\(\) => \{[\s\S]*return \(\) => \{[\s\S]*statusRefreshPendingRef\.current = false;[\s\S]*\};[\s\S]*\}, \[\]\)/,
'first-run checklist must restore mounted state during StrictMode replay and release refresh ownership on unmount',
);
assert.match(source, /const isChecklistUnmounted = useCallback\(\(\) => !checklistMountedRef\.current, \[\]\)/);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO
assert.ok(reloadMatch, 'ProvidersPanel reload() must exist');
assert.match(
panel,
/const providersPanelMountedRef = useRef\(false\);[\s\S]*const providersReloadTicketRef = useRef\(0\);[\s\S]*const providerPageLifecycleRef = useRef\(0\);/,
/const providersPanelMountedRef = useMountedRef\(\);[\s\S]*const providersReloadTicketRef = useRef\(0\);[\s\S]*const providerPageLifecycleRef = useRef\(0\);/,
'ProvidersPanel reloads must track mounted state and latest request ownership',
);
assert.match(
Expand All @@ -100,7 +100,7 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO
);
assert.match(
panel,
/return \(\) => \{[\s\S]*providersPanelMountedRef\.current = false;[\s\S]*providersReloadTicketRef\.current \+= 1;[\s\S]*unsubscribe\?\.\(\);/,
/return \(\) => \{[\s\S]*providersReloadTicketRef\.current \+= 1;[\s\S]*unsubscribe\?\.\(\);/,
'ProvidersPanel cleanup must invalidate in-flight reloads and unsubscribe from connection events',
);
assert.match(
Expand Down Expand Up @@ -243,7 +243,7 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO
);
assert.match(
addForm,
/const addProviderMountedRef = useRef\(false\)[\s\S]*useEffect\(\(\) => \{[\s\S]*addProviderMountedRef\.current = true;[\s\S]*return \(\) => \{[\s\S]*addProviderMountedRef\.current = false;[\s\S]*busyRef\.current = false;[\s\S]*\};[\s\S]*\}, \[\]\);/,
/const addProviderMountedRef = useMountedRef\(\)[\s\S]*useEffect\(\(\) => \{[\s\S]*return \(\) => \{[\s\S]*busyRef\.current = false;[\s\S]*\};[\s\S]*\}, \[\]\);/,
'AddProviderForm must track its own sheet lifetime so pending create continuations cannot write after overlay close',
);
assert.match(
Expand Down Expand Up @@ -720,12 +720,12 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO

assert.match(
detail,
/const connectionDetailMountedRef = useRef\(false\);[\s\S]*const connectionDetailLifecycleRef = useRef\(0\);/,
/const connectionDetailMountedRef = useMountedRef\(\);[\s\S]*const connectionDetailLifecycleRef = useRef\(0\);/,
'ConnectionDetail must track mounted/lifecycle ownership',
);
assert.match(
detail,
/useEffect\(\(\) => \{[\s\S]*connectionDetailMountedRef\.current = true;[\s\S]*connectionDetailLifecycleRef\.current \+= 1;[\s\S]*return \(\) => \{[\s\S]*connectionDetailMountedRef\.current = false;[\s\S]*connectionDetailLifecycleRef\.current \+= 1;[\s\S]*busyRef\.current = false;[\s\S]*testingRef\.current = false;[\s\S]*fetchingModelsRef\.current = false;[\s\S]*settingDefaultRef\.current = false;[\s\S]*deletingRef\.current = false;[\s\S]*\};[\s\S]*\}, \[connection\.slug\]\);/,
/useEffect\(\(\) => \{[\s\S]*connectionDetailLifecycleRef\.current \+= 1;[\s\S]*return \(\) => \{[\s\S]*connectionDetailLifecycleRef\.current \+= 1;[\s\S]*busyRef\.current = false;[\s\S]*testingRef\.current = false;[\s\S]*fetchingModelsRef\.current = false;[\s\S]*settingDefaultRef\.current = false;[\s\S]*deletingRef\.current = false;[\s\S]*\};[\s\S]*\}, \[connection\.slug\]\);/,
'ConnectionDetail cleanup must release every pending action owner on close or provider switch',
);
assert.match(
Expand Down Expand Up @@ -938,7 +938,7 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO

assert.match(
section,
/const modelOAuthMountedRef = useRef\(false\);[\s\S]*const modelOAuthRefreshTicketRef = useRef\(0\);/,
/const modelOAuthMountedRef = useMountedRef\(\);[\s\S]*const modelOAuthRefreshTicketRef = useRef\(0\);/,
'ModelOAuthSection must keep mounted and latest-refresh ownership refs',
);
assert.match(
Expand All @@ -948,7 +948,7 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO
);
assert.match(
section,
/useEffect\(\(\) => \{[\s\S]*modelOAuthMountedRef\.current = true;[\s\S]*void refreshAllCards\(\);[\s\S]*return \(\) => \{[\s\S]*modelOAuthMountedRef\.current = false;[\s\S]*modelOAuthRefreshTicketRef\.current \+= 1;[\s\S]*\};[\s\S]*\}, \[\]\);/,
/useEffect\(\(\) => \{[\s\S]*void refreshAllCards\(\);[\s\S]*return \(\) => \{[\s\S]*modelOAuthRefreshTicketRef\.current \+= 1;[\s\S]*\};[\s\S]*\}, \[\]\);/,
'OAuth card refresh must invalidate in-flight requests on unmount',
);
assert.match(
Expand Down Expand Up @@ -1054,7 +1054,7 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO
);
assert.match(
hook,
/const oauthLoginFlowMountedRef = useRef\(false\)/,
/const oauthLoginFlowMountedRef = useMountedRef\(\)/,
'shared OAuth flow must own mounted state before writing async feedback',
);
assert.match(
Expand All @@ -1069,7 +1069,7 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO
);
assert.match(
hook,
/useEffect\(\(\) => \{[\s\S]*oauthLoginFlowMountedRef\.current = true;[\s\S]*void refresh\(\);[\s\S]*return \(\) => \{[\s\S]*oauthLoginFlowMountedRef\.current = false;[\s\S]*pendingGuard\.finish\(\);[\s\S]*teardownPendingAuthorization\(authRequestIdRef, \(id\) => void bridge\.cancelAuthorization\(id\)\);[\s\S]*\};[\s\S]*\}, \[\]\);/,
/useEffect\(\(\) => \{[\s\S]*void refresh\(\);[\s\S]*return \(\) => \{[\s\S]*pendingGuard\.finish\(\);[\s\S]*teardownPendingAuthorization\(authRequestIdRef, \(id\) => void bridge\.cancelAuthorization\(id\)\);[\s\S]*\};[\s\S]*\}, \[\]\);/,
'shared OAuth flow cleanup must invalidate async feedback and cancel pending authorization',
);
assert.match(
Expand Down Expand Up @@ -1178,7 +1178,7 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO
);
assert.match(
claudeCard,
/return \(\) => \{[\s\S]*claudeCardMountedRef\.current = false;[\s\S]*const pendingAuthRequestId = claudeAuthRequestIdRef\.current;[\s\S]*claudeAuthRequestIdRef\.current = null;[\s\S]*if \(pendingAuthRequestId\) void window\.maka\.claudeSubscription\.cancelAuthorization\(pendingAuthRequestId\);[\s\S]*\};/,
/return \(\) => \{[\s\S]*const pendingAuthRequestId = claudeAuthRequestIdRef\.current;[\s\S]*claudeAuthRequestIdRef\.current = null;[\s\S]*if \(pendingAuthRequestId\) void window\.maka\.claudeSubscription\.cancelAuthorization\(pendingAuthRequestId\);[\s\S]*\};/,
'closing the Claude OAuth modal mid-login must cancel the pending auth request',
);
assert.match(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ describe('Office document capability contract', () => {
assert.doesNotMatch(settings, /<div className="settingsCapabilityGuidanceActions" aria-label="Office 文档安装辅助">/);
assert.match(settings, /copyingOfficeCliInstallRef\.current/, 'OfficeCLI install copy action must have a ref-backed double-click guard');
assert.match(settings, /if \(copyingOfficeCliInstallRef\.current\) return;/);
assert.match(settings, /const capabilityRowMountedRef = useRef\(false\);/);
assert.match(settings, /const capabilityRowMountedRef = useMountedRef\(\);/);
assert.match(
settings,
/useEffect\(\(\) => \{[\s\S]*capabilityRowMountedRef\.current = true;[\s\S]*return \(\) => \{[\s\S]*capabilityRowMountedRef\.current = false;[\s\S]*copyingOfficeCliInstallRef\.current = false;/,
/useEffect\(\(\) => \{[\s\S]*return \(\) => \{[\s\S]*copyingOfficeCliInstallRef\.current = false;/,
'OfficeCLI install copy action must release ownership when its capability row unmounts',
);
assert.match(settings, /disabled=\{copyingOfficeCliInstall\}/);
Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/main/__tests__/onboarding-hero-copy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,10 +411,10 @@ describe('OnboardingHero Quick Chat draft lifecycle', () => {

assert.match(readyBlock, /const \[submitPending, setSubmitPending\] = useState\(false\)/);
assert.match(readyBlock, /const submitPendingRef = useRef\(false\)/);
assert.match(readyBlock, /const readyHeroMountedRef = useRef\(true\)/);
assert.match(readyBlock, /const readyHeroMountedRef = useMountedRef\(\)/);
assert.match(
readyBlock,
/useEffect\(\(\) => \{[\s\S]*readyHeroMountedRef\.current = true;[\s\S]*return \(\) => \{[\s\S]*readyHeroMountedRef\.current = false;[\s\S]*submitPendingRef\.current = false;[\s\S]*importActionOwnerRef\.current\?\.reset\(\);[\s\S]*\};[\s\S]*\}, \[\]\)/,
/useEffect\(\(\) => \{[\s\S]*return \(\) => \{[\s\S]*submitPendingRef\.current = false;[\s\S]*importActionOwnerRef\.current\?\.reset\(\);[\s\S]*\};[\s\S]*\}, \[\]\)/,
'ReadyEmptyHero must clear async pending owners on unmount and restore mounted state during StrictMode replay',
);
assert.match(readyBlock, /const quickChatBusy = props\.quickChatPending \|\| submitPending/);
Expand Down
Loading
Loading