@@ -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