Some checks failed
ci / 정본·보안·린트·타입·테스트 (push) Successful in 51s
ci / 모바일 린트·타입·Jest (push) Successful in 37s
ci / Supabase Edge Functions + Cloudflare Worker (push) Successful in 26s
ci / .NET API 서버 테스트 (push) Successful in 14s
deploy-site / deploy (push) Failing after 15s
ci / 워크스페이스 빌드 검증 (push) Failing after 11m7s
With the embedding server unavailable every chunk failed, yet the document was stored as indexed=true with 0 chunks, so the knowledge base listed it as searchable while queries could never match it. The red use-case test caught this; it had been written off as an environment failure. Now a run with zero embedded chunks leaves indexed=false and throws RAGEmbeddingFailed (surfaced by reindex, logged by addDocument). Tests that only hold on the Windows developer machine now declare it: the bundled SoX binary and PowerShell device discovery run on win32 only, and the sidecar venv test runs only when sidecar/.venv exists. The Linux Forgejo runner skips them instead of failing.
99 lines
3.5 KiB
TypeScript
99 lines
3.5 KiB
TypeScript
// tests/main/utils/paths.test.ts
|
|
// dev/packaged 경로 해석 테스트.
|
|
//
|
|
// 회귀 배경: electron-vite dev에서 app.getAppPath()가 `out/main`을 가리켜
|
|
// sidecar/SoX가 존재하지 않는 경로로 잡혔고, 결과적으로 로컬 전사와 녹음이
|
|
// 모두 실패했다(시스템 python/PATH 폴백). 여기서 그 해석을 고정한다.
|
|
|
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
|
import { existsSync } from 'node:fs'
|
|
import path from 'node:path'
|
|
import { app } from 'electron'
|
|
import {
|
|
getAppRoot,
|
|
getSidecarCommand,
|
|
getSidecarBaseUrl,
|
|
getSoxPath,
|
|
resetPathCache,
|
|
} from '../../../src/main/utils/paths'
|
|
|
|
const desktopDir = path.resolve(__dirname, '..', '..', '..')
|
|
|
|
describe('paths (dev)', () => {
|
|
beforeEach(() => {
|
|
resetPathCache()
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
resetPathCache()
|
|
})
|
|
|
|
it('resolves the app root a level above the vite out/main bundle', () => {
|
|
// dev에서 app.getAppPath() = <desktop>/out/main 이다.
|
|
vi.mocked(app.getAppPath).mockReturnValue(path.join(desktopDir, 'out', 'main'))
|
|
resetPathCache()
|
|
|
|
expect(getAppRoot()).toBe(desktopDir)
|
|
})
|
|
|
|
// resources/sox 에는 Windows용 sox.exe 만 커밋돼 있다(앱은 Windows 배포). 다른 OS에서는 PATH 의 sox 를 쓴다.
|
|
it.skipIf(process.platform !== 'win32')('prefers the bundled SoX binary over the system PATH', () => {
|
|
expect(getSoxPath()).toContain(path.join('resources', 'sox', 'sox'))
|
|
expect(existsSync(getSoxPath())).toBe(true)
|
|
expect(getSoxPath()).not.toBe('sox')
|
|
})
|
|
|
|
// 로컬 개발 환경에만 있는 sidecar/.venv 가 있을 때의 동작이다. CI 에는 venv 가 없다.
|
|
it.skipIf(!existsSync(path.join(desktopDir, 'sidecar', '.venv')))('uses the sidecar virtualenv python when it exists', () => {
|
|
const launch = getSidecarCommand()
|
|
|
|
expect(launch.source).toBe('venv')
|
|
expect(launch.command).toContain('.venv')
|
|
expect(launch.args[0]).toBe(path.join(desktopDir, 'sidecar', 'main.py'))
|
|
expect(existsSync(launch.command)).toBe(true)
|
|
})
|
|
|
|
it('builds the sidecar base URL on the IPv4 loopback', () => {
|
|
expect(getSidecarBaseUrl(18765)).toBe('http://127.0.0.1:18765')
|
|
})
|
|
})
|
|
|
|
describe('paths (packaged)', () => {
|
|
beforeEach(() => {
|
|
resetPathCache()
|
|
Object.defineProperty(app, 'isPackaged', { value: true, configurable: true })
|
|
})
|
|
|
|
afterEach(() => {
|
|
Object.defineProperty(app, 'isPackaged', { value: false, configurable: true })
|
|
vi.restoreAllMocks()
|
|
resetPathCache()
|
|
})
|
|
|
|
it('fails loudly when the packaged sidecar bundle is missing', () => {
|
|
Object.defineProperty(process, 'resourcesPath', {
|
|
value: path.join(desktopDir, 'definitely-not-bundled'),
|
|
configurable: true,
|
|
})
|
|
|
|
expect(() => getSidecarCommand()).toThrowError(/로컬 음성 엔진이 아직 설치되지 않았습니다/)
|
|
})
|
|
|
|
it('uses the packaged sidecar executable when present', () => {
|
|
Object.defineProperty(process, 'resourcesPath', {
|
|
value: path.join(desktopDir, 'resources'),
|
|
configurable: true,
|
|
})
|
|
|
|
// resources/sox 는 커밋되어 있으므로 resources/sidecar/sidecar(.exe)도
|
|
// 같은 방식으로 배치된다. 존재하지 않는 플랫폼이면 번들 실패로 처리된다.
|
|
const exeSuffix = process.platform === 'win32' ? '.exe' : ''
|
|
const bundled = path.join(desktopDir, 'resources', 'sidecar', `sidecar${exeSuffix}`)
|
|
if (existsSync(bundled)) {
|
|
expect(getSidecarCommand().source).toBe('bundled')
|
|
} else {
|
|
expect(() => getSidecarCommand()).toThrow()
|
|
}
|
|
})
|
|
})
|