🐛 fix(security): 完善密文升级导入覆盖与安全更新链路

- 完善连接恢复包与 legacy 导入覆盖语义及密文兼容处理

- 修复安全更新详情高亮反馈与相关前后端链路

- 补强 keyring 误判边界与安全更新回归测试
This commit is contained in:
tianqijiuyun-latiao
2026-04-11 16:53:03 +08:00
parent 070ff72ad8
commit 82e06bd94d
35 changed files with 2021 additions and 110 deletions

View File

@@ -1,8 +1,11 @@
import { describe, expect, it } from 'vitest';
import type { SavedConnection, SecurityUpdateIssue } from '../types';
import type { SavedConnection, SecurityUpdateIssue, SecurityUpdateStatus } from '../types';
import {
hasSecurityUpdateRecentResult,
resolveSecurityUpdateFocusState,
resolveSecurityUpdateRepairEntry,
resolveSecurityUpdateSettingsFocusTarget,
shouldReopenSecurityUpdateDetails,
shouldRetrySecurityUpdateAfterRepairSave,
} from './securityUpdateRepairFlow';
@@ -19,6 +22,19 @@ const createConnection = (id: string): SavedConnection => ({
},
});
const createStatus = (overrides: Partial<SecurityUpdateStatus> = {}): SecurityUpdateStatus => ({
overallStatus: 'needs_attention',
summary: {
total: 1,
updated: 0,
pending: 1,
skipped: 0,
failed: 0,
},
issues: [],
...overrides,
});
describe('securityUpdateRepairFlow', () => {
it('opens the matching connection and preserves the return source for security update repairs', () => {
const target = createConnection('conn-1');
@@ -63,6 +79,50 @@ describe('securityUpdateRepairFlow', () => {
});
});
it('routes view_details actions to the latest result section when a recent result exists', () => {
const status = createStatus({
backupPath: '/tmp/gonavi-backup.json',
lastError: '写入新密钥失败',
});
expect(hasSecurityUpdateRecentResult(status)).toBe(true);
expect(resolveSecurityUpdateSettingsFocusTarget(status)).toBe('recent_result');
expect(resolveSecurityUpdateRepairEntry({ id: 'details', action: 'view_details' }, [], status)).toEqual({
type: 'details',
focusTarget: 'recent_result',
});
});
it('falls back to the status section when no recent result is available yet', () => {
const status = createStatus();
expect(hasSecurityUpdateRecentResult(status)).toBe(false);
expect(resolveSecurityUpdateSettingsFocusTarget(status)).toBe('status');
expect(resolveSecurityUpdateRepairEntry({ id: 'details', action: 'view_details' }, [], status)).toEqual({
type: 'details',
focusTarget: 'status',
});
});
it('builds a fresh focus pulse for repeated details clicks and clears it when the modal closes', () => {
expect(resolveSecurityUpdateFocusState(true, 'status', 1)).toEqual({
target: 'status',
pulseKey: 'status:1',
});
expect(resolveSecurityUpdateFocusState(true, 'status', 2)).toEqual({
target: 'status',
pulseKey: 'status:2',
});
expect(resolveSecurityUpdateFocusState(false, 'status', 2)).toEqual({
target: null,
pulseKey: null,
});
expect(resolveSecurityUpdateFocusState(true, null, 3)).toEqual({
target: null,
pulseKey: null,
});
});
it('reopens security update details after closing a repair entry opened from that page', () => {
expect(shouldReopenSecurityUpdateDetails('connection')).toBe(true);
expect(shouldReopenSecurityUpdateDetails('proxy')).toBe(true);