feat: complete release preparation, 10+ ad mediation, CI/CD, and docker deployment
Some checks failed
CI Pipeline / Code Quality & Typecheck (push) Waiting to run
CI Pipeline / Test Suite (macos-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (ubuntu-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (windows-latest) (push) Blocked by required conditions
CI Pipeline / Build Validation (admin) (push) Blocked by required conditions
CI Pipeline / Build Validation (desktop) (push) Blocked by required conditions
Deploy Landing Page / deploy (push) Blocked by required conditions
Deploy Landing Page / build (push) Waiting to run
Release & Packaging Pipeline / Build & Publish Admin Docker Image (push) Failing after 8s
Release & Code Signing CA Pipeline / build-and-sign-windows (push) Failing after 1m51s
Build macOS / Build & Package (macOS) (push) Failing after 4s
Build macOS / Build & Package (macOS)-1 (push) Failing after 5s
Release & Code Signing CA Pipeline / build-and-sign-macos (push) Failing after 3s
Release & Packaging Pipeline / Package macOS Desktop App (push) Failing after 4s
Release & Packaging Pipeline / Package Windows Desktop App (push) Failing after 2m28s
Release & Packaging Pipeline / Publish Official GitHub Release (push) Has been skipped
Some checks failed
CI Pipeline / Code Quality & Typecheck (push) Waiting to run
CI Pipeline / Test Suite (macos-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (ubuntu-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (windows-latest) (push) Blocked by required conditions
CI Pipeline / Build Validation (admin) (push) Blocked by required conditions
CI Pipeline / Build Validation (desktop) (push) Blocked by required conditions
Deploy Landing Page / deploy (push) Blocked by required conditions
Deploy Landing Page / build (push) Waiting to run
Release & Packaging Pipeline / Build & Publish Admin Docker Image (push) Failing after 8s
Release & Code Signing CA Pipeline / build-and-sign-windows (push) Failing after 1m51s
Build macOS / Build & Package (macOS) (push) Failing after 4s
Build macOS / Build & Package (macOS)-1 (push) Failing after 5s
Release & Code Signing CA Pipeline / build-and-sign-macos (push) Failing after 3s
Release & Packaging Pipeline / Package macOS Desktop App (push) Failing after 4s
Release & Packaging Pipeline / Package Windows Desktop App (push) Failing after 2m28s
Release & Packaging Pipeline / Publish Official GitHub Release (push) Has been skipped
This commit is contained in:
parent
5cd1de6859
commit
708e20f747
406 changed files with 42464 additions and 6199 deletions
172
apps/desktop/tests/red/meeting.usecase.test.ts
Normal file
172
apps/desktop/tests/red/meeting.usecase.test.ts
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
import { describe, it, expect, vi } from 'vitest'
|
||||
import { D3ROError, ErrorCode } from '@d3ro/core/errors'
|
||||
import { getMeetingModeService } from '../../src/main/services/MeetingModeService'
|
||||
import { getMeetingSummaryService } from '../../src/main/services/MeetingSummaryService'
|
||||
import { getHistoryService } from '../../src/main/services/HistoryService'
|
||||
import { getDatabase } from '../../src/main/db'
|
||||
import { meetingSessions } from '../../src/main/db/schema'
|
||||
import { historyInput, useRedHarness } from './harness'
|
||||
import { USER_TEXT } from './fixtures'
|
||||
|
||||
useRedHarness()
|
||||
|
||||
function insertSession(id: string, overrides: Record<string, unknown> = {}): void {
|
||||
const now = Date.now()
|
||||
getDatabase()
|
||||
.insert(meetingSessions)
|
||||
.values({
|
||||
id,
|
||||
title: '세션',
|
||||
status: 'completed',
|
||||
startedAt: now,
|
||||
endedAt: now + 1000,
|
||||
durationMs: 1000,
|
||||
rawTranscript: USER_TEXT.KO,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
...overrides,
|
||||
})
|
||||
.run()
|
||||
}
|
||||
|
||||
describe('유스케이스: 회의 세션 CRUD / 메모 / 전사 수정 / 요약 실패', () => {
|
||||
it('초기 회의 상태는 idle 이다', () => {
|
||||
expect(getMeetingModeService().getState()).toBe('idle')
|
||||
expect(getMeetingModeService().getStateInfo().sessionId).toBeNull()
|
||||
})
|
||||
|
||||
it('녹음 중이 아닐 때 메모 추가는 MeetingNotRecording 이다', async () => {
|
||||
await expect(getMeetingModeService().addMemo('메모')).rejects.toMatchObject({
|
||||
code: ErrorCode.MeetingNotRecording,
|
||||
})
|
||||
})
|
||||
|
||||
it('녹음 중이 아닐 때 중지는 MeetingNotRecording 이다', async () => {
|
||||
await expect(getMeetingModeService().stopRecording()).rejects.toMatchObject({
|
||||
code: ErrorCode.MeetingNotRecording,
|
||||
})
|
||||
})
|
||||
|
||||
it('세션 목록은 처음에 비어 있다', () => {
|
||||
const page = getMeetingModeService().getSessions(1, 10)
|
||||
expect(page.total).toBe(0)
|
||||
expect(page.sessions).toEqual([])
|
||||
})
|
||||
|
||||
it('저장된 세션을 목록에서 본다', () => {
|
||||
insertSession('sess-1', { title: '주간회의' })
|
||||
const page = getMeetingModeService().getSessions(1, 10)
|
||||
expect(page.total).toBe(1)
|
||||
expect(page.sessions[0].title).toBe('주간회의')
|
||||
})
|
||||
|
||||
it('세션 상세를 연다', () => {
|
||||
insertSession('sess-2', { title: '상세' })
|
||||
const detail = getMeetingModeService().getSession('sess-2')
|
||||
expect(detail.id).toBe('sess-2')
|
||||
expect(detail.title).toBe('상세')
|
||||
})
|
||||
|
||||
it('없는 세션 조회는 MeetingSessionNotFound 다', () => {
|
||||
expect(() => getMeetingModeService().getSession('missing')).toThrow(D3ROError)
|
||||
try {
|
||||
getMeetingModeService().getSession('missing')
|
||||
} catch (err) {
|
||||
expect((err as D3ROError).code).toBe(ErrorCode.MeetingSessionNotFound)
|
||||
}
|
||||
})
|
||||
|
||||
it('세션 제목을 바꾼다', () => {
|
||||
insertSession('sess-3', { title: 'old' })
|
||||
getMeetingModeService().updateTitle('sess-3', 'new-title')
|
||||
expect(getMeetingModeService().getSession('sess-3').title).toBe('new-title')
|
||||
})
|
||||
|
||||
it('없는 세션 제목 변경은 MeetingSessionNotFound 다', () => {
|
||||
expect(() => getMeetingModeService().updateTitle('missing', 'x')).toThrow(D3ROError)
|
||||
})
|
||||
|
||||
it('세션을 삭제하면 목록에서 사라진다', () => {
|
||||
insertSession('sess-4')
|
||||
getMeetingModeService().deleteSession('sess-4')
|
||||
expect(getMeetingModeService().getSessions(1, 10).total).toBe(0)
|
||||
})
|
||||
|
||||
it('없는 세션 삭제는 MeetingSessionNotFound 다', () => {
|
||||
expect(() => getMeetingModeService().deleteSession('missing')).toThrow(D3ROError)
|
||||
})
|
||||
|
||||
it('전사를 수정하면 edited 텍스트가 남는다', () => {
|
||||
insertSession('sess-5')
|
||||
getMeetingModeService().updateTranscript('sess-5', USER_TEXT.EN)
|
||||
const detail = getMeetingModeService().getSession('sess-5')
|
||||
expect(detail.editedTranscript ?? detail.rawTranscript).toBeTruthy()
|
||||
})
|
||||
|
||||
it('없는 세션 전사 수정은 MeetingSessionNotFound 다', () => {
|
||||
expect(() => getMeetingModeService().updateTranscript('missing', 'x')).toThrow(D3ROError)
|
||||
})
|
||||
|
||||
it('빈 제목으로 바꾸면 빈 문자열이 저장되거나 거부된다', () => {
|
||||
insertSession('sess-6', { title: 'keep' })
|
||||
try {
|
||||
getMeetingModeService().updateTitle('sess-6', ' ')
|
||||
const title = getMeetingModeService().getSession('sess-6').title
|
||||
expect(title === 'keep' || title?.trim() === '').toBe(true)
|
||||
} catch (err) {
|
||||
expect(err).toBeInstanceOf(D3ROError)
|
||||
}
|
||||
})
|
||||
|
||||
it('없는 세션의 문서 목록은 빈 배열이다', () => {
|
||||
expect(getMeetingModeService().getDocuments('missing')).toEqual([])
|
||||
})
|
||||
|
||||
it('없는 문서 수정은 MeetingDocumentNotFound 다', () => {
|
||||
expect(() => getMeetingModeService().updateDocument('missing', 'x')).toThrow(D3ROError)
|
||||
})
|
||||
|
||||
it('없는 문서 삭제는 MeetingDocumentNotFound 다', () => {
|
||||
expect(() => getMeetingModeService().deleteDocument('missing')).toThrow(D3ROError)
|
||||
})
|
||||
|
||||
it('페이지네이션으로 세션을 나눈다', () => {
|
||||
insertSession('p-a', { title: 'A' })
|
||||
insertSession('p-b', { title: 'B' })
|
||||
insertSession('p-c', { title: 'C' })
|
||||
const p0 = getMeetingModeService().getSessions(1, 2)
|
||||
expect(p0.sessions.length).toBe(2)
|
||||
expect(p0.totalPages).toBe(2)
|
||||
})
|
||||
|
||||
it('요약할 히스토리가 없으면 HistoryNotFound 다', async () => {
|
||||
await expect(getMeetingSummaryService().summarize('missing')).rejects.toMatchObject({
|
||||
code: ErrorCode.HistoryNotFound,
|
||||
})
|
||||
})
|
||||
|
||||
it('빈 전사는 MeetingSummaryNoTranscript 다', async () => {
|
||||
const entry = getHistoryService().create(historyInput({ originalText: '' }))
|
||||
await expect(getMeetingSummaryService().summarize(entry.id)).rejects.toMatchObject({
|
||||
code: ErrorCode.MeetingSummaryNoTranscript,
|
||||
})
|
||||
})
|
||||
|
||||
it('LLM 이 없으면 요약 실패가 표면화된다 (빈 성공 금지)', async () => {
|
||||
const entry = getHistoryService().create(historyInput({ originalText: USER_TEXT.KO }))
|
||||
await expect(getMeetingSummaryService().summarize(entry.id)).rejects.toBeTruthy()
|
||||
expect(getHistoryService().getById(entry.id)?.summaryText ?? null).toBeNull()
|
||||
})
|
||||
|
||||
it('저장된 요약이 없으면 getSummary 는 null 이다', () => {
|
||||
const entry = getHistoryService().create(historyInput())
|
||||
expect(getMeetingSummaryService().getSummary(entry.id)).toBeNull()
|
||||
})
|
||||
|
||||
it('내보내기할 요약이 없으면 MeetingSummaryExportFailed 다', async () => {
|
||||
const entry = getHistoryService().create(historyInput())
|
||||
await expect(getMeetingSummaryService().exportMarkdown(entry.id)).rejects.toMatchObject({
|
||||
code: ErrorCode.MeetingSummaryExportFailed,
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue