你的姓名 acb288aa51 fix(ci): repair server/adapter/desktop-native PR checks
- ci: install adapter deps in server-checks job so the server route's
  static import of @whiskeysockets/baileys (via whatsapp adapter) resolves,
  fixing the 34 fail + 7 errors A-group in server-checks
- adapters(ws-bridge): keep a no-op 'error' listener when detaching a
  discarded socket so a pending socket's async ECONNREFUSED can't surface
  as an unhandled exception (was 9 "errors" -> exit 1 in adapter-checks)
- desktop(electron): share one electron module mock across tray/menu tests
  so bun's single-process, last-registered-wins vi.mock('electron') no
  longer leaves tray with menu's mock (missing nativeImage/Tray)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 10:03:50 +08:00

86 lines
3.0 KiB
TypeScript

import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
import path from 'node:path'
import { tmpdir } from 'node:os'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { installTray, resolveTrayIconPath, shouldInstallTray } from './tray'
import { buildElectronModuleMock, getElectronServiceMocks, resetElectronServiceMocks } from './__electronMock'
vi.mock('electron', () => buildElectronModuleMock())
describe('Electron tray service', () => {
afterEach(() => {
resetElectronServiceMocks()
})
it('uses the existing desktop icon assets for the tray icon', () => {
const root = mkdtempSync(path.join(tmpdir(), 'electron-tray-'))
try {
const iconPath = path.join(root, 'src-tauri', 'icons', 'icon.png')
mkdirSync(path.dirname(iconPath), { recursive: true })
writeFileSync(iconPath, 'png')
expect(resolveTrayIconPath(root)).toBe(iconPath)
} finally {
rmSync(root, { recursive: true, force: true })
}
})
it('fails clearly when no tray icon exists', () => {
const root = mkdtempSync(path.join(tmpdir(), 'electron-tray-missing-'))
try {
expect(() => resolveTrayIconPath(root)).toThrow('Electron tray icon not found')
} finally {
rmSync(root, { recursive: true, force: true })
}
})
it('skips the status-bar tray on macOS and keeps it on Windows and Linux', () => {
expect(shouldInstallTray('darwin')).toBe(false)
expect(shouldInstallTray('win32')).toBe(true)
expect(shouldInstallTray('linux')).toBe(true)
})
it('installs tray handlers that show the app, quit explicitly, and dispose cleanly', async () => {
const root = mkdtempSync(path.join(tmpdir(), 'electron-tray-install-'))
try {
const trayMocks = getElectronServiceMocks()
const iconPath = path.join(root, 'src-tauri', 'icons', 'icon.png')
mkdirSync(path.dirname(iconPath), { recursive: true })
writeFileSync(iconPath, 'png')
const show = vi.fn()
const quit = vi.fn()
const controller = await installTray({
app: { name: 'Claude Code Haha' } as never,
desktopRoot: root,
show,
quit,
})
expect(trayMocks.createFromPath).toHaveBeenCalledWith(iconPath)
expect(trayMocks.Tray).toHaveBeenCalledTimes(1)
expect(trayMocks.tray.setToolTip).toHaveBeenCalledWith('Claude Code Haha')
expect(trayMocks.buildFromTemplate).toHaveBeenCalledTimes(1)
const template = trayMocks.buildFromTemplate.mock.calls[0]?.[0] as Array<{ label?: string, click?: () => void, type?: string }>
expect(template.map(item => item.label ?? item.type)).toEqual([
'Show Claude Code Haha',
'separator',
'Quit Claude Code Haha',
])
template[0]?.click?.()
template[2]?.click?.()
trayMocks.handlers.get('click')?.()
expect(show).toHaveBeenCalledTimes(2)
expect(quit).toHaveBeenCalledTimes(1)
controller.dispose()
expect(trayMocks.tray.destroy).toHaveBeenCalledTimes(1)
} finally {
rmSync(root, { recursive: true, force: true })
}
})
})