mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-10-06 13:54:10 +08:00
Merge pull request #41 from Wxw-Gu/codex/develop-xkey-4-1-13
Codex/develop xkey 4 1 13
This commit is contained in:
@@ -78,6 +78,43 @@ function renderPage(
|
||||
}
|
||||
|
||||
describe('DatabaseConnectionPage', () => {
|
||||
it('guides Apple Silicon users to log in while key capture is active', async () => {
|
||||
const onAutoGetKey = vi.fn()
|
||||
const { props, rerender } = renderPage({
|
||||
platform: 'darwin',
|
||||
mode: 'automatic',
|
||||
guideStep: 3,
|
||||
onAutoGetKey,
|
||||
environment: {
|
||||
platform: 'darwin',
|
||||
architecture: 'arm64',
|
||||
osVersion: 'macOS fixture',
|
||||
appVersion: 'v2.3.0',
|
||||
wechatVersion: '4.1.13',
|
||||
dataStructureVersion: '微信 4.x(WCDB)',
|
||||
dataDirectoryDetected: true,
|
||||
diagnosticSummary: 'fixture',
|
||||
autoDetectSupported: true,
|
||||
wechatRunning: true,
|
||||
accountIdentified: true,
|
||||
dbConnected: false,
|
||||
encryptionAvailable: true
|
||||
}
|
||||
})
|
||||
|
||||
await userEvent.click(screen.getByRole('button', { name: '开始获取密钥' }))
|
||||
expect(onAutoGetKey).toHaveBeenCalledOnce()
|
||||
|
||||
rerender(
|
||||
<TooltipProvider>
|
||||
<DatabaseConnectionPage {...props} mode="automatic" guideStep={4} isFetching />
|
||||
</TooltipProvider>
|
||||
)
|
||||
expect(screen.getByText('正在监听 macOS 登录密钥')).toBeVisible()
|
||||
expect(screen.getByText(/立即回到微信点击登录/)).toBeVisible()
|
||||
expect(screen.getByRole('button', { name: '正在获取密钥…' })).toBeDisabled()
|
||||
})
|
||||
|
||||
it('uses the automatic Intel Mac flow without exposing implementation details', () => {
|
||||
renderPage({
|
||||
platform: 'darwin',
|
||||
|
||||
@@ -31,6 +31,34 @@ const state: DatabaseKeyState = {
|
||||
}
|
||||
|
||||
describe('database key controls', () => {
|
||||
it('offers login-time key capture on Apple Silicon macOS', async () => {
|
||||
const user = userEvent.setup()
|
||||
const onDetect = vi.fn()
|
||||
render(
|
||||
<DatabaseKeyAutoDetect
|
||||
state={{
|
||||
...state,
|
||||
environment: {
|
||||
...state.environment!,
|
||||
platform: 'darwin',
|
||||
architecture: 'arm64',
|
||||
osVersion: 'macOS fixture',
|
||||
wechatVersion: '4.1.13',
|
||||
autoDetectSupported: true
|
||||
}
|
||||
}}
|
||||
disabled={false}
|
||||
onDetect={onDetect}
|
||||
onRefresh={vi.fn()}
|
||||
/>
|
||||
)
|
||||
|
||||
expect(screen.getByText('macOS 自动获取')).toBeVisible()
|
||||
expect(screen.getByText(/通常不需要扫码/)).toBeVisible()
|
||||
await user.click(screen.getByRole('button', { name: '自动获取密钥' }))
|
||||
expect(onDetect).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('offers automatic key detection on Intel Mac without exposing implementation details', async () => {
|
||||
const user = userEvent.setup()
|
||||
const onDetect = vi.fn()
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
vi.mock('electron', () => ({
|
||||
app: {
|
||||
getPath: vi.fn(() => '/tmp/tracememo-key-service-test')
|
||||
}
|
||||
}))
|
||||
|
||||
import {
|
||||
buildAppleSiliconXkeyInvocation,
|
||||
buildXkeyHelperArguments,
|
||||
mapXkeyHelperFailure,
|
||||
parseXkeyHelperOutput,
|
||||
resolveXkeyHelperMode
|
||||
} from '../../src/main/key-service-mac'
|
||||
|
||||
describe('parseXkeyHelperOutput', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('returns a valid helper key without exposing progress output', () => {
|
||||
const key = 'ab'.repeat(32)
|
||||
expect(
|
||||
parseXkeyHelperOutput(`progress line\n${JSON.stringify({ success: true, key })}`)
|
||||
).toEqual({ success: true, key })
|
||||
})
|
||||
|
||||
it('maps a login-time capture timeout to an actionable message', () => {
|
||||
const result = parseXkeyHelperOutput(
|
||||
JSON.stringify({
|
||||
success: false,
|
||||
result:
|
||||
'sink found at 0x1234\nsoftware breakpoint unavailable\nhardware breakpoint armed\ntimeout waiting for breakpoint hit'
|
||||
})
|
||||
)
|
||||
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
code: 'CAPTURE_TIMEOUT',
|
||||
error:
|
||||
'已完成管理员授权,但监听期间微信没有触发账号密钥派生。请先停留在微信登录界面,在 TraceMemo 点击“自动获取密钥”,授权后点击微信“登录”;已有登录凭据时通常不需要扫码。'
|
||||
})
|
||||
})
|
||||
|
||||
it('does not expose raw helper diagnostics for an unknown failure', () => {
|
||||
const result = parseXkeyHelperOutput(
|
||||
JSON.stringify({
|
||||
success: false,
|
||||
result: 'private diagnostic /Users/example/source/xkey.mm:123'
|
||||
})
|
||||
)
|
||||
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
code: 'HELPER_RESULT_INVALID',
|
||||
error: '密钥工具未返回有效密钥,请确认微信仍在运行后重试。'
|
||||
})
|
||||
expect(result.error).not.toContain('/Users/example')
|
||||
})
|
||||
|
||||
it('sanitizes diagnostics returned through an AppleScript command error', () => {
|
||||
const result = mapXkeyHelperFailure(
|
||||
'sink found at 0x1234\nhardware breakpoint armed on 81/81 threads\nWAIT_FAILED:no_breakpoint_hit',
|
||||
'OSASCRIPT_1'
|
||||
)
|
||||
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
code: 'CAPTURE_TIMEOUT',
|
||||
error:
|
||||
'已完成管理员授权,但监听期间微信没有触发账号密钥派生。请先停留在微信登录界面,在 TraceMemo 点击“自动获取密钥”,授权后点击微信“登录”;已有登录凭据时通常不需要扫码。'
|
||||
})
|
||||
})
|
||||
|
||||
it.each([
|
||||
['4.1.8', 'legacy'],
|
||||
['4.1.9.57', 'legacy'],
|
||||
['4.1.10', 'legacy'],
|
||||
['4.1.13', 'wechat-4.1.13'],
|
||||
['4.1.13.91', 'wechat-4.1.13'],
|
||||
['4.1.130', 'legacy'],
|
||||
['未检测到', 'legacy']
|
||||
])('selects the helper mode for WeChat %s', (version, mode) => {
|
||||
expect(resolveXkeyHelperMode(version)).toBe(mode)
|
||||
})
|
||||
|
||||
it('builds the verified 4.1.13 account-key capture contract', () => {
|
||||
expect(buildXkeyHelperArguments(60037, 120_000)).toEqual([
|
||||
'60037',
|
||||
'120000',
|
||||
'--profile',
|
||||
'wechat-4.1.13',
|
||||
'--account'
|
||||
])
|
||||
})
|
||||
|
||||
it('uses the new helper only for WeChat 4.1.13', () => {
|
||||
expect(buildAppleSiliconXkeyInvocation('4.1.13.91', 60037, 60_000)).toEqual({
|
||||
mode: 'wechat-4.1.13',
|
||||
resourceName: 'xkey_helper_4_1_13',
|
||||
args: ['60037', '120000', '--profile', 'wechat-4.1.13', '--account'],
|
||||
waitMs: 120_000,
|
||||
timeoutSeconds: 130,
|
||||
execTimeoutMs: 135_000
|
||||
})
|
||||
})
|
||||
|
||||
it.each(['4.1.8', '4.1.9.57', '4.1.10', '未检测到'])(
|
||||
'preserves the legacy helper invocation for WeChat %s',
|
||||
(version) => {
|
||||
expect(buildAppleSiliconXkeyInvocation(version, 60037, 60_000)).toEqual({
|
||||
mode: 'legacy',
|
||||
resourceName: 'xkey_helper',
|
||||
args: ['60037', '60000'],
|
||||
waitMs: 60_000,
|
||||
timeoutSeconds: 90,
|
||||
execTimeoutMs: 80_000
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
it('extracts a helper error embedded in AppleScript diagnostics', () => {
|
||||
expect(
|
||||
mapXkeyHelperFailure(
|
||||
'hardware breakpoint armed\n{"success":false,"result":"ERROR:HOOK_FAILED:ptrace"}',
|
||||
'OSASCRIPT_1'
|
||||
)
|
||||
).toEqual({
|
||||
success: false,
|
||||
code: 'HOOK_FAILED',
|
||||
error: '密钥工具执行未完成(HOOK_FAILED),请确认微信仍在运行后重试。'
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -25,6 +25,8 @@ describe('database key validation', () => {
|
||||
|
||||
it('maps automatic detection progress into stable phases', () => {
|
||||
expect(mapAutoDetectPhase('正在查找微信进程')).toBeGreaterThan(0)
|
||||
expect(mapAutoDetectPhase('正在请求管理员授权')).toBe(2)
|
||||
expect(mapAutoDetectPhase('授权后请在微信登录界面点击“登录”')).toBe(3)
|
||||
expect(mapAutoDetectPhase('已获取数据库密钥')).toBe(5)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user