diff --git a/frontend/src/components/checklist/RecordingModals.test.js b/frontend/src/components/checklist/RecordingModals.test.js index 874f63b..ec0ac47 100644 --- a/frontend/src/components/checklist/RecordingModals.test.js +++ b/frontend/src/components/checklist/RecordingModals.test.js @@ -46,7 +46,7 @@ describe('RecordingTextModal', () => { [{ isLoading: true }, '녹음 내용을 불러오고 있어요.'], [{ errorMessage: '조회 실패' }, '조회 실패'], [{ text: '' }, '변환된 녹음 텍스트가 아직 없어요.'], - [{ text: '첫 줄\n둘째 줄' }, '첫 줄\n둘째 줄'], + [{ text: '화자 정보 없는 녹음' }, '화자 정보 없는 녹음'], ])('조회 상태에 맞는 본문을 표시한다', (state, message) => { const wrapper = mount(RecordingTextModal, { props: { open: true, ...state }, @@ -55,6 +55,23 @@ describe('RecordingTextModal', () => { expect(wrapper.text()).toContain(message); }); + test('백엔드 화자 번호를 A와 B로 바꾸고 화자마다 별도 줄로 표시한다', () => { + const wrapper = mount(RecordingTextModal, { + props: { + open: true, + text: '화자 1: 첫 번째 발화 이어지는 발화\n화자 2: 두 번째 발화\n화자 1: 다시 첫 번째 화자', + }, + }); + + expect( + wrapper.findAll('.recording-text-modal__speaker-line').map((line) => line.text()), + ).toEqual([ + 'A: 첫 번째 발화 이어지는 발화', + 'B: 두 번째 발화', + 'A: 다시 첫 번째 화자', + ]); + }); + test('모달 shell 닫힘을 상위로 전달한다', async () => { const wrapper = mount(RecordingTextModal, { props: { open: true } }); await wrapper.get('.shell-close').trigger('click'); diff --git a/frontend/src/components/checklist/RecordingTextModal.vue b/frontend/src/components/checklist/RecordingTextModal.vue index ec5f794..a40a1aa 100644 --- a/frontend/src/components/checklist/RecordingTextModal.vue +++ b/frontend/src/components/checklist/RecordingTextModal.vue @@ -10,7 +10,28 @@ const props = defineProps({ errorMessage: { type: String, default: '' }, }); const emit = defineEmits(['close']); -const hasText = computed(() => Boolean(props.text.trim())); +const transcriptLines = computed(() => { + const speakerAliases = new Map(); + + return props.text + .split(/\r?\n/) + .map((line) => line.trim()) + .filter(Boolean) + .map((line) => { + const speakerLine = line.match(/^화자\s+([^:]+):\s*(.*)$/); + if (!speakerLine) return line; + + const [, speaker, content] = speakerLine; + if (!speakerAliases.has(speaker)) { + speakerAliases.set( + speaker, + String.fromCharCode(65 + speakerAliases.size), + ); + } + return `${speakerAliases.get(speaker)}: ${content}`; + }); +}); +const hasText = computed(() => transcriptLines.value.length > 0);