mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-10-04 03:01:42 +08:00
feat: 增加windows发送能力
抽离功能到设置页面 抽离文字转语音功能
This commit is contained in:
@@ -4,6 +4,13 @@ import type React from 'react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { PersonalWechatSendDialog } from '../../src/renderer/src/components/chat/PersonalWechatSendDialog'
|
||||
|
||||
vi.mock('../../src/renderer/src/utils/runtime-environment', () => ({
|
||||
isMac: true,
|
||||
isWindows: false,
|
||||
runtimePlatform: 'darwin',
|
||||
supportsPersonalWechatSend: true
|
||||
}))
|
||||
|
||||
const getStatus = vi.fn()
|
||||
const getRuntimeStatus = vi.fn()
|
||||
const downloadRuntime = vi.fn()
|
||||
@@ -73,9 +80,12 @@ function renderDialog(
|
||||
}
|
||||
|
||||
async function startComposer(): Promise<void> {
|
||||
const bind = await screen.findByRole('button', { name: '绑定微信' })
|
||||
fireEvent.click(bind)
|
||||
await screen.findByText('✓ 微信已绑定')
|
||||
await screen.findByText('绑定个人微信')
|
||||
const bind = screen.queryByRole('button', { name: '绑定微信' })
|
||||
if (bind) {
|
||||
fireEvent.click(bind)
|
||||
await screen.findByText('✓ 微信已绑定')
|
||||
}
|
||||
const detect = await screen.findByRole('button', { name: '重新检测' })
|
||||
fireEvent.click(detect)
|
||||
const start = await screen.findByRole('button', { name: '开始发送' })
|
||||
@@ -170,8 +180,8 @@ describe('PersonalWechatSendDialog', () => {
|
||||
message: '尚未绑定当前微信'
|
||||
})
|
||||
renderDialog()
|
||||
expect(await screen.findByText('准备语音模型')).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: '下载模型' })).toBeEnabled()
|
||||
expect(await screen.findByText('准备 OneBot 运行时')).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: '下载运行时' })).toBeEnabled()
|
||||
expect(screen.getByText('绑定个人微信')).toBeInTheDocument()
|
||||
expect(screen.getByText('验证消息能力')).toBeInTheDocument()
|
||||
expect(screen.getByText('能力检测')).toBeInTheDocument()
|
||||
@@ -250,7 +260,7 @@ describe('PersonalWechatSendDialog', () => {
|
||||
})
|
||||
fireEvent.click(screen.getByRole('button', { name: '生成语音' }))
|
||||
await waitFor(() => expect(screen.getByText('语音已生成')).toBeInTheDocument())
|
||||
fireEvent.click(screen.getByRole('button', { name: '发送2' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: '空白语音?重新处理' }))
|
||||
await waitFor(() =>
|
||||
expect(sendMessage).toHaveBeenCalledWith({
|
||||
type: 'voice',
|
||||
@@ -286,8 +296,8 @@ describe('PersonalWechatSendDialog', () => {
|
||||
canSendVoice: false
|
||||
})
|
||||
renderDialog()
|
||||
await screen.findByRole('button', { name: '下载模型' })
|
||||
fireEvent.click(screen.getByRole('button', { name: '下载模型' }))
|
||||
await screen.findByRole('button', { name: '下载运行时' })
|
||||
fireEvent.click(screen.getByRole('button', { name: '下载运行时' }))
|
||||
await waitFor(() => expect(downloadRuntime).toHaveBeenCalledOnce())
|
||||
fireEvent.click(screen.getByRole('button', { name: '绑定微信' }))
|
||||
await waitFor(() => expect(rebind).toHaveBeenCalledOnce())
|
||||
@@ -320,8 +330,11 @@ describe('PersonalWechatSendDialog', () => {
|
||||
})
|
||||
renderDialog()
|
||||
expect(await screen.findByText('图片和语音消息')).toBeInTheDocument()
|
||||
fireEvent.click(screen.getByRole('button', { name: '绑定微信' }))
|
||||
await screen.findByText('✓ 微信已绑定')
|
||||
const bind = screen.queryByRole('button', { name: '绑定微信' })
|
||||
if (bind) {
|
||||
fireEvent.click(bind)
|
||||
await screen.findByText('✓ 微信已绑定')
|
||||
}
|
||||
fireEvent.click(await screen.findByRole('button', { name: '重新检测' }))
|
||||
expect(screen.getByText('微信消息发送已配置完成')).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: '开始发送' })).toBeEnabled()
|
||||
@@ -340,8 +353,12 @@ describe('PersonalWechatSendDialog', () => {
|
||||
message: '等待消息初始化'
|
||||
})
|
||||
renderDialog()
|
||||
fireEvent.click(await screen.findByRole('button', { name: '绑定微信' }))
|
||||
await screen.findByText('✓ 微信已绑定')
|
||||
await screen.findByText('绑定个人微信')
|
||||
const bind = screen.queryByRole('button', { name: '绑定微信' })
|
||||
if (bind) {
|
||||
fireEvent.click(bind)
|
||||
await screen.findByText('✓ 微信已绑定')
|
||||
}
|
||||
const detect = await screen.findByRole('button', { name: '重新检测' })
|
||||
expect(detect).toBeEnabled()
|
||||
fireEvent.click(detect)
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { PersonalWechatSendPage } from '../../src/renderer/src/features/settings/pages/PersonalWechatSendPage'
|
||||
|
||||
vi.mock('../../src/renderer/src/utils/runtime-environment', () => ({
|
||||
isMac: true,
|
||||
isWindows: false,
|
||||
runtimePlatform: 'darwin',
|
||||
supportsPersonalWechatSend: true
|
||||
}))
|
||||
|
||||
const getCapability = vi.fn()
|
||||
const getSenderStatus = vi.fn()
|
||||
const getRuntimeStatus = vi.fn()
|
||||
const onRuntimeProgress = vi.fn(() => vi.fn())
|
||||
const downloadRuntime = vi.fn()
|
||||
const cancelRuntimeDownload = vi.fn()
|
||||
const removeRuntime = vi.fn()
|
||||
const openRuntimeDirectory = vi.fn()
|
||||
const rebindSender = vi.fn()
|
||||
|
||||
const senderStatus = {
|
||||
state: 'online' as const,
|
||||
platform: 'darwin',
|
||||
arch: 'arm64',
|
||||
sipDisabled: true,
|
||||
wechatRunning: true,
|
||||
wechatPid: 4668,
|
||||
boundWechatPid: 4668,
|
||||
oneBotPid: 5401,
|
||||
endpoint: '127.0.0.1:58080',
|
||||
endpointReady: true,
|
||||
wechatVersion: '4.1.11.53',
|
||||
runtimeReady: true,
|
||||
attachReady: true,
|
||||
baseAddress: '0x114ef8000',
|
||||
baseAddressReady: true,
|
||||
textHookInstalled: true,
|
||||
textHookReady: true,
|
||||
imageHookInstalled: true,
|
||||
imageHookReady: true,
|
||||
messageListenerReady: true,
|
||||
canSend: true,
|
||||
canSendText: true,
|
||||
canSendImage: true,
|
||||
canSendVoice: true,
|
||||
message: '个人微信已绑定'
|
||||
}
|
||||
|
||||
const readyRuntime = {
|
||||
version: 'v0.0.18',
|
||||
state: 'ready' as const,
|
||||
downloadedBytes: 66_599_785,
|
||||
totalBytes: 66_599_785,
|
||||
progress: 1,
|
||||
platform: 'darwin' as NodeJS.Platform,
|
||||
architecture: 'arm64',
|
||||
supported: true,
|
||||
removable: true,
|
||||
directory: '/tmp/personal-wechat-runtime'
|
||||
}
|
||||
|
||||
const capability = {
|
||||
supported: true,
|
||||
ready: true,
|
||||
status: 'ready' as const,
|
||||
capabilities: { text: true, image: true, voice: true },
|
||||
senderStatus,
|
||||
message: '个人微信发送能力已就绪'
|
||||
}
|
||||
|
||||
describe('PersonalWechatSendPage on macOS', () => {
|
||||
beforeEach(() => {
|
||||
getCapability.mockReset().mockResolvedValue(capability)
|
||||
getSenderStatus.mockReset().mockResolvedValue(senderStatus)
|
||||
getRuntimeStatus.mockReset().mockResolvedValue(readyRuntime)
|
||||
onRuntimeProgress.mockReset().mockReturnValue(vi.fn())
|
||||
downloadRuntime.mockReset().mockResolvedValue({ success: true, status: readyRuntime })
|
||||
cancelRuntimeDownload.mockReset().mockResolvedValue({ success: true })
|
||||
removeRuntime.mockReset().mockResolvedValue({
|
||||
...readyRuntime,
|
||||
state: 'missing',
|
||||
downloadedBytes: 0,
|
||||
progress: 0,
|
||||
removable: false,
|
||||
directory: undefined
|
||||
})
|
||||
openRuntimeDirectory.mockReset().mockResolvedValue({ success: true })
|
||||
rebindSender.mockReset().mockResolvedValue(senderStatus)
|
||||
vi.spyOn(window, 'confirm').mockReturnValue(true)
|
||||
Object.defineProperty(window, 'api', {
|
||||
configurable: true,
|
||||
value: {
|
||||
getPersonalWechatSendCapability: getCapability,
|
||||
getPersonalWechatSenderStatus: getSenderStatus,
|
||||
getPersonalWechatRuntimeStatus: getRuntimeStatus,
|
||||
onPersonalWechatRuntimeProgress: onRuntimeProgress,
|
||||
downloadPersonalWechatRuntime: downloadRuntime,
|
||||
cancelPersonalWechatRuntimeDownload: cancelRuntimeDownload,
|
||||
removePersonalWechatRuntime: removeRuntime,
|
||||
openPersonalWechatRuntimeDirectory: openRuntimeDirectory,
|
||||
rebindPersonalWechatSender: rebindSender
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('keeps OneBot runtime management on the WeChat send page', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(<PersonalWechatSendPage onNotice={vi.fn()} />)
|
||||
|
||||
expect(await screen.findByText('OneBot v0.0.18')).toBeVisible()
|
||||
expect(screen.getAllByText('已就绪')).not.toHaveLength(0)
|
||||
await user.click(screen.getByRole('button', { name: '打开目录' }))
|
||||
expect(openRuntimeDirectory).toHaveBeenCalledOnce()
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '卸载组件' }))
|
||||
await waitFor(() => expect(removeRuntime).toHaveBeenCalledOnce())
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '支持版本' }))
|
||||
const versionsDialog = screen.getByRole('dialog', { name: '支持的微信版本' })
|
||||
expect(versionsDialog).toBeVisible()
|
||||
expect(versionsDialog).toHaveTextContent('4.1.11.53')
|
||||
})
|
||||
|
||||
it('downloads a missing macOS runtime from the send page', async () => {
|
||||
getRuntimeStatus.mockResolvedValue({
|
||||
...readyRuntime,
|
||||
state: 'missing',
|
||||
downloadedBytes: 0,
|
||||
progress: 0,
|
||||
removable: false,
|
||||
directory: undefined
|
||||
})
|
||||
const onNotice = vi.fn()
|
||||
render(<PersonalWechatSendPage onNotice={onNotice} />)
|
||||
|
||||
await userEvent.setup().click(await screen.findByRole('button', { name: '下载组件' }))
|
||||
await waitFor(() => expect(downloadRuntime).toHaveBeenCalledOnce())
|
||||
expect(onNotice).toHaveBeenCalledWith('微信发送组件已准备好')
|
||||
})
|
||||
})
|
||||
@@ -609,6 +609,8 @@ describe('daily report controls', () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: '发送到当前群聊' }))
|
||||
|
||||
expect(await screen.findByRole('dialog', { name: '测试群' })).toBeVisible()
|
||||
const detect = screen.queryByRole('button', { name: '重新检测' })
|
||||
if (detect) fireEvent.click(detect)
|
||||
expect(screen.getByRole('radio', { name: '图片' })).toHaveAttribute('aria-checked', 'true')
|
||||
expect(screen.getByText('测试群日报.png')).toBeVisible()
|
||||
expect(screen.getByText('/Users/fixture/测试群日报.png')).toBeVisible()
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { PersonalWechatSendDialog } from '../../src/renderer/src/components/chat/PersonalWechatSendDialog'
|
||||
import { PersonalWechatSendPage } from '../../src/renderer/src/features/settings/pages/PersonalWechatSendPage'
|
||||
import { TextToSpeechPage } from '../../src/renderer/src/features/settings/pages/TextToSpeechPage'
|
||||
|
||||
vi.mock('../../src/renderer/src/utils/runtime-environment', () => ({
|
||||
isMac: false,
|
||||
isWindows: true,
|
||||
runtimePlatform: 'win32',
|
||||
supportsPersonalWechatSend: true
|
||||
}))
|
||||
|
||||
const getTextToSpeechSettings = vi.fn()
|
||||
const listTextToSpeechVoices = vi.fn()
|
||||
const openFishAudioApiKeys = vi.fn()
|
||||
const getSettings = vi.fn()
|
||||
const setSettings = vi.fn()
|
||||
const getPersonalWechatSenderStatus = vi.fn()
|
||||
const getPersonalWechatRuntimeStatus = vi.fn()
|
||||
const checkPersonalWechatSenderStatus = vi.fn()
|
||||
|
||||
const textToSpeechSettings = {
|
||||
success: true,
|
||||
settings: {
|
||||
provider: 'fish-audio' as const,
|
||||
hasApiKey: false,
|
||||
hasStoredApiKey: false,
|
||||
hasEnvironmentApiKey: false,
|
||||
keySource: 'none' as const,
|
||||
encryptionAvailable: true,
|
||||
selectedVoiceId: '',
|
||||
outputFormat: 'mp3' as const,
|
||||
model: 's2.1-pro-free' as const,
|
||||
phase: 'idle' as const
|
||||
},
|
||||
voices: []
|
||||
}
|
||||
|
||||
const windowsStatus = {
|
||||
state: 'online' as const,
|
||||
platform: 'win32',
|
||||
arch: 'x64',
|
||||
sipDisabled: true,
|
||||
wechatRunning: true,
|
||||
runtimeReady: true,
|
||||
endpoint: '127.0.0.1:4567',
|
||||
endpointReady: true,
|
||||
attachReady: true,
|
||||
baseAddressReady: true,
|
||||
textHookInstalled: false,
|
||||
textHookReady: false,
|
||||
imageHookInstalled: false,
|
||||
imageHookReady: false,
|
||||
messageListenerReady: false,
|
||||
canSend: true,
|
||||
canSendText: true,
|
||||
canSendImage: true,
|
||||
canSendVoice: true,
|
||||
message: 'Windows 微信发送能力已连接,可以发送消息'
|
||||
}
|
||||
|
||||
describe('PersonalWechatSendPage on Windows', () => {
|
||||
beforeEach(() => {
|
||||
getTextToSpeechSettings.mockReset().mockResolvedValue(textToSpeechSettings)
|
||||
listTextToSpeechVoices.mockReset()
|
||||
openFishAudioApiKeys.mockReset().mockResolvedValue({ success: true })
|
||||
getSettings.mockReset().mockResolvedValue({ settings: { windowsWechatPort: '' } })
|
||||
setSettings.mockReset().mockResolvedValue({
|
||||
settings: { windowsWechatPort: '4567' }
|
||||
})
|
||||
getPersonalWechatSenderStatus.mockReset()
|
||||
getPersonalWechatRuntimeStatus.mockReset().mockResolvedValue(null)
|
||||
checkPersonalWechatSenderStatus.mockReset().mockResolvedValue(windowsStatus)
|
||||
Object.defineProperty(window, 'api', {
|
||||
configurable: true,
|
||||
value: {
|
||||
getTextToSpeechSettings,
|
||||
listTextToSpeechVoices,
|
||||
openFishAudioApiKeys,
|
||||
getSettings,
|
||||
setSettings,
|
||||
getPersonalWechatSenderStatus,
|
||||
getPersonalWechatRuntimeStatus,
|
||||
checkPersonalWechatSenderStatus
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('keeps an unconfigured port empty and saves it only after a successful check', async () => {
|
||||
const onNotice = vi.fn()
|
||||
render(<PersonalWechatSendPage onNotice={onNotice} />)
|
||||
|
||||
const portInput = await screen.findByRole('spinbutton', { name: '微信发送能力端口' })
|
||||
expect(portInput).toHaveValue(null)
|
||||
expect(screen.getByRole('button', { name: '检测' })).toBeEnabled()
|
||||
expect(getPersonalWechatSenderStatus).not.toHaveBeenCalled()
|
||||
|
||||
fireEvent.change(portInput, { target: { value: '4567' } })
|
||||
fireEvent.click(screen.getByRole('button', { name: '检测' }))
|
||||
|
||||
await waitFor(() => expect(checkPersonalWechatSenderStatus).toHaveBeenCalledWith('4567'))
|
||||
expect(screen.getByRole('button', { name: '保存' })).toBeEnabled()
|
||||
expect(portInput).toHaveValue(4567)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '保存' }))
|
||||
await waitFor(() => expect(setSettings).toHaveBeenCalledWith({ windowsWechatPort: '4567' }))
|
||||
expect(screen.getByRole('button', { name: '检测' })).toBeEnabled()
|
||||
expect(onNotice).toHaveBeenCalledWith('微信发送能力端口已保存')
|
||||
})
|
||||
|
||||
it('clears a saved port and resets the connection state', async () => {
|
||||
getSettings.mockResolvedValue({ settings: { windowsWechatPort: '4567' } })
|
||||
getPersonalWechatSenderStatus.mockResolvedValue(windowsStatus)
|
||||
const onNotice = vi.fn()
|
||||
render(<PersonalWechatSendPage onNotice={onNotice} />)
|
||||
|
||||
const portInput = await screen.findByRole('spinbutton', { name: '微信发送能力端口' })
|
||||
expect(portInput).toHaveValue(4567)
|
||||
expect(screen.getByRole('button', { name: '清除端口' })).toBeEnabled()
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '清除端口' }))
|
||||
|
||||
await waitFor(() => expect(setSettings).toHaveBeenCalledWith({ windowsWechatPort: '' }))
|
||||
expect(portInput).toHaveValue(null)
|
||||
expect(screen.getByRole('button', { name: '清除端口' })).toBeDisabled()
|
||||
expect(screen.getByRole('button', { name: '检测' })).toBeEnabled()
|
||||
expect(onNotice).toHaveBeenCalledWith('微信发送能力端口已清除')
|
||||
})
|
||||
|
||||
it('keeps the Windows send dialog free of macOS OneBot controls', async () => {
|
||||
getPersonalWechatSenderStatus.mockResolvedValue({
|
||||
...windowsStatus,
|
||||
state: 'error',
|
||||
canSend: false,
|
||||
canSendText: false,
|
||||
canSendImage: false,
|
||||
canSendVoice: false,
|
||||
message: '未检测到 Windows 微信发送能力,请先启动并登录微信'
|
||||
})
|
||||
|
||||
render(
|
||||
<PersonalWechatSendDialog
|
||||
contact={{
|
||||
m_nsUsrName: 'fixture-user',
|
||||
m_nsNickName: '文件传输助手',
|
||||
md5: 'fixture-md5',
|
||||
type: 'user'
|
||||
}}
|
||||
isGroupChat={false}
|
||||
onClose={vi.fn()}
|
||||
onOpenPersonalWechatSettings={vi.fn()}
|
||||
/>
|
||||
)
|
||||
|
||||
expect(
|
||||
await screen.findByText('未检测到 Windows 微信发送能力,请先启动并登录微信')
|
||||
).toBeVisible()
|
||||
expect(getPersonalWechatRuntimeStatus).not.toHaveBeenCalled()
|
||||
expect(screen.queryByText(/OneBot/i)).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('switch', { name: '保留 OneBot 进程' })).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('button', { name: '语音发送诊断' })).not.toBeInTheDocument()
|
||||
expect(screen.getByRole('heading', { name: '个人微信发送' })).toBeVisible()
|
||||
expect(screen.getByRole('region', { name: '发送消息' })).toBeVisible()
|
||||
})
|
||||
|
||||
it('opens the Windows send dialog in text mode by default', async () => {
|
||||
getPersonalWechatSenderStatus.mockResolvedValue(windowsStatus)
|
||||
|
||||
render(
|
||||
<PersonalWechatSendDialog
|
||||
contact={{
|
||||
m_nsUsrName: 'fixture-user',
|
||||
m_nsNickName: '文件传输助手',
|
||||
md5: 'fixture-md5',
|
||||
type: 'user'
|
||||
}}
|
||||
isGroupChat={false}
|
||||
onClose={vi.fn()}
|
||||
/>
|
||||
)
|
||||
|
||||
expect(await screen.findByRole('radio', { name: '文字' })).toHaveAttribute(
|
||||
'data-state',
|
||||
'checked'
|
||||
)
|
||||
expect(screen.getByRole('textbox', { name: '消息内容' })).toBeVisible()
|
||||
})
|
||||
|
||||
it('keeps the Windows voice page focused on speech settings', async () => {
|
||||
render(<TextToSpeechPage onNotice={vi.fn()} />)
|
||||
|
||||
expect(await screen.findByText('API 设置')).toBeVisible()
|
||||
expect(screen.queryByText(/OneBot/i)).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('微信发送组件')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
@@ -14,10 +14,6 @@ const getSettings = vi.fn()
|
||||
const saveSettings = vi.fn()
|
||||
const listVoices = vi.fn()
|
||||
const openApiKeys = vi.fn()
|
||||
const getRuntimeStatus = vi.fn()
|
||||
const onRuntimeProgress = vi.fn(() => vi.fn())
|
||||
const openRuntimeDirectory = vi.fn()
|
||||
const removeRuntime = vi.fn()
|
||||
|
||||
const response = {
|
||||
success: true,
|
||||
@@ -55,7 +51,6 @@ const response = {
|
||||
|
||||
describe('TextToSpeechPage', () => {
|
||||
beforeEach(() => {
|
||||
sessionStorage.clear()
|
||||
getSettings.mockReset().mockResolvedValue(response)
|
||||
listVoices.mockReset().mockResolvedValue({
|
||||
success: true,
|
||||
@@ -75,42 +70,13 @@ describe('TextToSpeechPage', () => {
|
||||
}
|
||||
}))
|
||||
openApiKeys.mockReset().mockResolvedValue({ success: true })
|
||||
getRuntimeStatus.mockReset().mockResolvedValue({
|
||||
version: 'v0.0.18',
|
||||
state: 'ready',
|
||||
downloadedBytes: 100,
|
||||
totalBytes: 100,
|
||||
progress: 1,
|
||||
platform: 'darwin',
|
||||
architecture: 'arm64',
|
||||
supported: true,
|
||||
removable: true,
|
||||
directory: '/tmp/personal-wechat-runtime'
|
||||
})
|
||||
onRuntimeProgress.mockReset().mockReturnValue(vi.fn())
|
||||
openRuntimeDirectory.mockReset().mockResolvedValue({ success: true })
|
||||
removeRuntime.mockReset().mockResolvedValue({
|
||||
version: 'v0.0.18',
|
||||
state: 'missing',
|
||||
downloadedBytes: 0,
|
||||
totalBytes: 100,
|
||||
progress: 0,
|
||||
platform: 'darwin',
|
||||
architecture: 'arm64',
|
||||
supported: true,
|
||||
removable: false
|
||||
})
|
||||
Object.defineProperty(window, 'api', {
|
||||
configurable: true,
|
||||
value: {
|
||||
getTextToSpeechSettings: getSettings,
|
||||
saveTextToSpeechSettings: saveSettings,
|
||||
listTextToSpeechVoices: listVoices,
|
||||
openFishAudioApiKeys: openApiKeys,
|
||||
getPersonalWechatRuntimeStatus: getRuntimeStatus,
|
||||
onPersonalWechatRuntimeProgress: onRuntimeProgress,
|
||||
openPersonalWechatRuntimeDirectory: openRuntimeDirectory,
|
||||
removePersonalWechatRuntime: removeRuntime
|
||||
openFishAudioApiKeys: openApiKeys
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -148,7 +114,7 @@ describe('TextToSpeechPage', () => {
|
||||
|
||||
it('opens the official Fish Audio API key page through the main process', async () => {
|
||||
render(<TextToSpeechPage onNotice={vi.fn()} />)
|
||||
await screen.findByText('微信发送组件')
|
||||
await screen.findByText('API 设置')
|
||||
fireEvent.click(screen.getByRole('button', { name: '前往 api.fish.audio 获取 Key' }))
|
||||
await waitFor(() => expect(openApiKeys).toHaveBeenCalledTimes(1))
|
||||
})
|
||||
@@ -170,49 +136,11 @@ describe('TextToSpeechPage', () => {
|
||||
await waitFor(() => expect(saveSettings).toHaveBeenCalledWith({ clearApiKey: true }))
|
||||
})
|
||||
|
||||
it('keeps runtime directory and refresh actions wired to the existing API', async () => {
|
||||
const user = userEvent.setup()
|
||||
it('keeps the speech page free of personal WeChat runtime controls', async () => {
|
||||
render(<TextToSpeechPage onNotice={vi.fn()} />)
|
||||
|
||||
await user.click(await screen.findByRole('button', { name: '打开目录' }))
|
||||
expect(openRuntimeDirectory).toHaveBeenCalledOnce()
|
||||
await user.click(screen.getByRole('button', { name: '重新检测' }))
|
||||
expect(getRuntimeStatus).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it('opens supported versions from both triggers and restores focus after closing', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(<TextToSpeechPage onNotice={vi.fn()} />)
|
||||
|
||||
const guideTrigger = await screen.findByRole('button', { name: '查看支持版本' })
|
||||
await user.click(guideTrigger)
|
||||
expect(screen.getByRole('dialog', { name: '支持的微信版本' })).toBeVisible()
|
||||
expect(screen.getByText('请安装下列完整版本之一。')).toBeVisible()
|
||||
expect(screen.getByRole('link', { name: /下载微信历史版本/ })).toHaveAttribute(
|
||||
'href',
|
||||
'https://github.com/zsbai/wechat-versions/releases'
|
||||
)
|
||||
expect(screen.getByText('4.1.6.12')).toBeVisible()
|
||||
expect(screen.getByText('4.1.11.53')).toBeVisible()
|
||||
|
||||
await user.keyboard('{Escape}')
|
||||
expect(screen.queryByRole('dialog', { name: '支持的微信版本' })).not.toBeInTheDocument()
|
||||
expect(guideTrigger).toHaveFocus()
|
||||
|
||||
const runtimeTrigger = screen.getByRole('button', { name: '支持版本' })
|
||||
await user.click(runtimeTrigger)
|
||||
const dialog = screen.getByRole('dialog', { name: '支持的微信版本' })
|
||||
expect(dialog).toBeVisible()
|
||||
await user.click(dialog.previousElementSibling as HTMLElement)
|
||||
expect(screen.queryByRole('dialog', { name: '支持的微信版本' })).not.toBeInTheDocument()
|
||||
expect(runtimeTrigger).toHaveFocus()
|
||||
})
|
||||
|
||||
it('keeps the session handoff that opens supported versions automatically', async () => {
|
||||
sessionStorage.setItem('wxe:show-supported-wechat-versions', '1')
|
||||
render(<TextToSpeechPage onNotice={vi.fn()} />)
|
||||
|
||||
expect(await screen.findByRole('dialog', { name: '支持的微信版本' })).toBeVisible()
|
||||
expect(sessionStorage.getItem('wxe:show-supported-wechat-versions')).toBeNull()
|
||||
expect(await screen.findByText('API 设置')).toBeVisible()
|
||||
expect(screen.queryByText(/微信|OneBot/i)).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('支持的微信版本')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user