Skip to content

Commit adbb9b6

Browse files
authored
fix(fireflies): handle nullable transcript metadata (#7129)
1 parent 1b597b0 commit adbb9b6

2 files changed

Lines changed: 253 additions & 65 deletions

File tree

apps/sim/connectors/fireflies/fireflies.test.ts

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,78 @@ describe('fireflies listDocuments', () => {
224224
)
225225
})
226226

227+
it('accepts documented nullable transcript metadata without aborting the listing', async () => {
228+
mockGraphQL([
229+
{
230+
body: {
231+
data: {
232+
transcripts: [
233+
transcript('nullable', {
234+
title: null,
235+
date: null,
236+
duration: null,
237+
host_email: null,
238+
organizer_email: null,
239+
participants: [null],
240+
transcript_url: null,
241+
speakers: [null, { name: null }],
242+
is_live: null,
243+
meeting_info: null,
244+
}),
245+
],
246+
},
247+
},
248+
},
249+
])
250+
251+
const result = await firefliesConnector.listDocuments('key', {}, undefined, {})
252+
253+
expect(result.documents).toEqual([
254+
expect.objectContaining({
255+
externalId: 'nullable',
256+
title: 'Untitled Meeting',
257+
sourceUrl: undefined,
258+
metadata: {
259+
hostEmail: undefined,
260+
duration: null,
261+
meetingDate: undefined,
262+
participants: [],
263+
speakers: [],
264+
},
265+
}),
266+
])
267+
})
268+
269+
it('accepts a transcript when optional metadata fields are omitted', async () => {
270+
mockGraphQL([{ body: { data: { transcripts: [{ id: 'minimal' }] } } }])
271+
272+
const result = await firefliesConnector.listDocuments('key', {}, undefined, {})
273+
274+
expect(result.documents[0]).toMatchObject({
275+
externalId: 'minimal',
276+
title: 'Untitled Meeting',
277+
metadata: {
278+
participants: [],
279+
speakers: [],
280+
},
281+
})
282+
})
283+
284+
it.each([
285+
['title', { title: 42 }],
286+
['date', { date: '2024-07-08' }],
287+
['duration', { duration: '45' }],
288+
['participants', { participants: {} }],
289+
['speakers', { speakers: [42] }],
290+
['meeting_info', { meeting_info: 'processed' }],
291+
])('rejects a malformed non-null %s value', async (_field, extra) => {
292+
mockGraphQL([{ body: { data: { transcripts: [transcript('t0', extra)] } } }])
293+
294+
await expect(firefliesConnector.listDocuments('key', {}, undefined, {})).rejects.toThrow(
295+
'Fireflies API returned malformed transcript metadata'
296+
)
297+
})
298+
227299
it('retries one malformed page without discarding the sync', async () => {
228300
vi.useFakeTimers()
229301
mockGraphQL([{ body: {} }, page(2)])
@@ -427,6 +499,71 @@ describe('fireflies getDocument', () => {
427499
expect(full?.content).toContain('An overview')
428500
})
429501

502+
it('normalizes documented nullable nested transcript fields during hydration', async () => {
503+
mockGraphQL([
504+
{
505+
body: {
506+
data: {
507+
transcript: transcript('nullable', {
508+
title: null,
509+
date: null,
510+
duration: null,
511+
host_email: null,
512+
organizer_email: null,
513+
participants: [null, 'participant@example.test'],
514+
transcript_url: null,
515+
speakers: [null, { name: null }, { name: 'Ada' }],
516+
is_live: null,
517+
meeting_info: { summary_status: null },
518+
sentences: [
519+
null,
520+
{ speaker_name: null, text: 'Hello' },
521+
{ speaker_name: 'Ada', text: null },
522+
],
523+
summary: {
524+
keywords: null,
525+
action_items: null,
526+
overview: null,
527+
short_summary: null,
528+
},
529+
}),
530+
},
531+
},
532+
},
533+
])
534+
535+
const result = await firefliesConnector.getDocument('key', {}, 'nullable')
536+
537+
expect(result).toMatchObject({
538+
externalId: 'nullable',
539+
title: 'Untitled Meeting',
540+
sourceUrl: undefined,
541+
contentDeferred: false,
542+
metadata: {
543+
hostEmail: undefined,
544+
duration: null,
545+
meetingDate: undefined,
546+
participants: ['participant@example.test'],
547+
speakers: ['Ada'],
548+
keywords: null,
549+
},
550+
})
551+
expect(result?.content).toContain('Unknown speaker: Hello')
552+
expect(result?.content).not.toContain('Ada: null')
553+
})
554+
555+
it.each([
556+
['sentences', { sentences: [42] }],
557+
['summary', { summary: { overview: 42 } }],
558+
['summary keywords', { summary: { keywords: [42] } }],
559+
])('rejects malformed non-null hydrated %s metadata', async (_field, extra) => {
560+
mockGraphQL([{ body: { data: { transcript: transcript('t0', extra) } } }])
561+
562+
await expect(firefliesConnector.getDocument('key', {}, 't0')).rejects.toThrow(
563+
'Fireflies API returned malformed transcript metadata'
564+
)
565+
})
566+
430567
it('renders duration as minutes, not seconds', async () => {
431568
mockGraphQL([{ body: { data: { transcript: transcript('t0', { duration: 45 }) } } }])
432569

0 commit comments

Comments
 (0)