mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-10-04 02:53:47 +08:00
183 lines
5.9 KiB
TypeScript
183 lines
5.9 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { APP_UPDATE_RELEASES_URL } from '../../src/shared/app-update'
|
|
|
|
const mocks = vi.hoisted(() => {
|
|
const listeners = new Map<string, Set<(...args: unknown[]) => void>>()
|
|
return {
|
|
listeners,
|
|
updater: {
|
|
autoDownload: true,
|
|
autoInstallOnAppQuit: false,
|
|
checkForUpdates: vi.fn(),
|
|
downloadUpdate: vi.fn(),
|
|
quitAndInstall: vi.fn(),
|
|
on: vi.fn((event: string, listener: (...args: unknown[]) => void) => {
|
|
const eventListeners = listeners.get(event) || new Set()
|
|
eventListeners.add(listener)
|
|
listeners.set(event, eventListeners)
|
|
})
|
|
},
|
|
shell: {
|
|
openExternal: vi.fn()
|
|
},
|
|
emit(event: string, ...args: unknown[]): void {
|
|
for (const listener of listeners.get(event) || []) listener(...args)
|
|
}
|
|
}
|
|
})
|
|
|
|
vi.mock('electron', () => ({
|
|
app: {
|
|
getVersion: () => '1.9.0',
|
|
isPackaged: false
|
|
},
|
|
BrowserWindow: {
|
|
getAllWindows: () => []
|
|
},
|
|
shell: mocks.shell
|
|
}))
|
|
|
|
vi.mock('electron-updater', () => ({ autoUpdater: mocks.updater }))
|
|
vi.mock('../../src/main/runtime-mode', () => ({ isPackagedRuntime: () => false }))
|
|
|
|
import { AppUpdateService } from '../../src/main/services/app-update-service'
|
|
|
|
describe('AppUpdateService', () => {
|
|
beforeEach(() => {
|
|
vi.useRealTimers()
|
|
vi.clearAllMocks()
|
|
mocks.listeners.clear()
|
|
})
|
|
|
|
it('keeps update-not-available as the final state when checkForUpdates returns metadata', async () => {
|
|
const service = new AppUpdateService({ packagedRuntime: () => true, platform: 'win32' })
|
|
mocks.updater.checkForUpdates.mockImplementationOnce(async () => {
|
|
mocks.emit('checking-for-update')
|
|
mocks.emit('update-not-available', { version: '1.9.0' })
|
|
return { updateInfo: { version: '1.9.0' } }
|
|
})
|
|
|
|
const result = await service.check('manual')
|
|
|
|
expect(result.success).toBe(true)
|
|
expect(result.state).toMatchObject({
|
|
status: 'up-to-date',
|
|
currentVersion: '1.9.0',
|
|
delivery: 'automatic',
|
|
source: 'manual'
|
|
})
|
|
})
|
|
|
|
it('simulates a realistic 2.0.0 download without invoking the real updater', async () => {
|
|
vi.useFakeTimers()
|
|
const states: ReturnType<AppUpdateService['getState']>[] = []
|
|
const service = new AppUpdateService({
|
|
simulationEnabled: true,
|
|
simulationDurationMs: 1_000,
|
|
currentVersion: () => '1.9.0'
|
|
})
|
|
service.handleState((state) => states.push(state))
|
|
|
|
const checkPromise = service.check('startup')
|
|
await vi.advanceTimersByTimeAsync(350)
|
|
const checkResult = await checkPromise
|
|
expect(checkResult.state).toMatchObject({
|
|
status: 'available',
|
|
version: '2.0.0',
|
|
source: 'startup',
|
|
isSimulation: true
|
|
})
|
|
|
|
const downloadPromise = service.download()
|
|
await vi.advanceTimersByTimeAsync(1_100)
|
|
const downloadResult = await downloadPromise
|
|
|
|
expect(downloadResult.state).toMatchObject({
|
|
status: 'downloaded',
|
|
version: '2.0.0',
|
|
percent: 100,
|
|
transferred: 60 * 1024 * 1024,
|
|
total: 60 * 1024 * 1024
|
|
})
|
|
expect(
|
|
states.filter((state) => state.status === 'downloading').map((state) => state.percent)
|
|
).toEqual([0, 5, 12, 21, 33, 46, 58, 69, 78, 86, 93, 97, 100])
|
|
expect(states.some((state) => (state.bytesPerSecond || 0) > 0)).toBe(true)
|
|
expect(mocks.updater.downloadUpdate).not.toHaveBeenCalled()
|
|
|
|
expect(service.install()).toEqual({
|
|
success: true,
|
|
simulated: true,
|
|
message: '开发模拟模式:更新安装动作已模拟,未实际退出应用。'
|
|
})
|
|
expect(mocks.updater.quitAndInstall).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('uses release-page delivery on unsigned macOS without downloading or installing', async () => {
|
|
const service = new AppUpdateService({
|
|
platform: 'darwin',
|
|
packagedRuntime: () => true,
|
|
currentVersion: () => '2.2.2',
|
|
macAutoUpdateEnabled: false
|
|
})
|
|
mocks.updater.checkForUpdates.mockImplementationOnce(async () => {
|
|
mocks.emit('checking-for-update')
|
|
mocks.emit('update-available', { version: '2.2.3' })
|
|
return { updateInfo: { version: '2.2.3' } }
|
|
})
|
|
|
|
const result = await service.check('manual')
|
|
expect(result.state).toMatchObject({
|
|
status: 'available',
|
|
delivery: 'release-page',
|
|
version: '2.2.3'
|
|
})
|
|
|
|
const download = await service.download()
|
|
expect(download.success).toBe(false)
|
|
expect(download.state.status).toBe('available')
|
|
expect(mocks.updater.downloadUpdate).not.toHaveBeenCalled()
|
|
expect(service.install()).toMatchObject({ success: false })
|
|
expect(mocks.updater.quitAndInstall).not.toHaveBeenCalled()
|
|
|
|
mocks.shell.openExternal.mockResolvedValue(undefined)
|
|
await expect(service.openDownloadPage()).resolves.toEqual({ success: true })
|
|
expect(mocks.shell.openExternal).toHaveBeenCalledWith(APP_UPDATE_RELEASES_URL)
|
|
})
|
|
|
|
it('keeps automatic download and quitAndInstall on Windows', async () => {
|
|
const service = new AppUpdateService({
|
|
platform: 'win32',
|
|
packagedRuntime: () => true,
|
|
currentVersion: () => '2.2.2'
|
|
})
|
|
mocks.updater.checkForUpdates.mockImplementationOnce(async () => {
|
|
mocks.emit('checking-for-update')
|
|
mocks.emit('update-available', { version: '2.2.3' })
|
|
return { updateInfo: { version: '2.2.3' } }
|
|
})
|
|
mocks.updater.downloadUpdate.mockImplementationOnce(async () => {
|
|
mocks.emit('download-progress', {
|
|
percent: 50,
|
|
transferred: 30,
|
|
total: 60,
|
|
bytesPerSecond: 10
|
|
})
|
|
mocks.emit('update-downloaded', { version: '2.2.3' })
|
|
})
|
|
|
|
await service.check('manual')
|
|
const download = await service.download()
|
|
expect(download.state).toMatchObject({
|
|
status: 'downloaded',
|
|
delivery: 'automatic',
|
|
version: '2.2.3',
|
|
percent: 100
|
|
})
|
|
expect(mocks.updater.downloadUpdate).toHaveBeenCalledOnce()
|
|
|
|
expect(service.install()).toEqual({ success: true })
|
|
expect(mocks.updater.quitAndInstall).toHaveBeenCalledOnce()
|
|
})
|
|
})
|