@@ -53,6 +53,7 @@ vi.mock('@nextcloud/dialogs', () => ({
5353} ) )
5454vi . mock ( '@nextcloud/router' , ( ) => ( {
5555 generateOcsUrl : vi . fn ( ( path ) => `/ocs${ path } ` ) ,
56+ generateUrl : vi . fn ( ( path , params ) => path . replace ( '{uuid}' , params ?. uuid ?? '' ) ) ,
5657} ) )
5758
5859vi . mock ( '@libresign/pdf-elements' , ( ) => ( {
@@ -126,6 +127,7 @@ describe('VisibleElements Component - Business Rules', () => {
126127
127128 let wrapper : VisibleElementsWrapper
128129 let filesStore : ReturnType < typeof useFilesStoreType >
130+ let fetchMock : ReturnType < typeof vi . fn >
129131
130132 function createWrapper ( ) : VisibleElementsWrapper {
131133 return mount ( VisibleElements , {
@@ -147,6 +149,14 @@ describe('VisibleElements Component - Business Rules', () => {
147149 setActivePinia ( createPinia ( ) )
148150 const { useFilesStore } = await import ( '../../../store/files.js' )
149151 filesStore = useFilesStore ( )
152+ fetchMock = vi . fn ( ) . mockResolvedValue ( {
153+ ok : true ,
154+ headers : {
155+ get : vi . fn ( ( ) => 'application/pdf' ) ,
156+ } ,
157+ blob : vi . fn ( async ( ) => new Blob ( [ 'pdf' ] , { type : 'application/pdf' } ) ) ,
158+ } )
159+ vi . stubGlobal ( 'fetch' , fetchMock )
150160
151161 filesStore . files [ 1 ] = {
152162 id : 1 ,
@@ -222,6 +232,7 @@ describe('VisibleElements Component - Business Rules', () => {
222232 {
223233 id : 10 ,
224234 name : 'doc1.pdf' ,
235+ file : '/path/to/doc1.pdf' ,
225236 metadata : { p : 3 } ,
226237 } ,
227238 ]
@@ -250,9 +261,9 @@ describe('VisibleElements Component - Business Rules', () => {
250261
251262 it ( 'maps multiple files pages sequentially' , ( ) => {
252263 filesStore . files [ 1 ] . files = [
253- { id : 10 , name : 'doc1.pdf' , metadata : { p : 2 } } ,
254- { id : 20 , name : 'doc2.pdf' , metadata : { p : 3 } } ,
255- { id : 30 , name : 'doc3.pdf' , metadata : { p : 1 } } ,
264+ { id : 10 , name : 'doc1.pdf' , file : '/path/to/doc1.pdf' , metadata : { p : 2 } } ,
265+ { id : 20 , name : 'doc2.pdf' , file : '/path/to/doc2.pdf' , metadata : { p : 3 } } ,
266+ { id : 30 , name : 'doc3.pdf' , file : '/path/to/doc3.pdf' , metadata : { p : 1 } } ,
256267 ]
257268
258269 wrapper . vm . buildFilePagesMap ( )
@@ -273,8 +284,8 @@ describe('VisibleElements Component - Business Rules', () => {
273284
274285 it ( 'handles files with zero pages' , ( ) => {
275286 filesStore . files [ 1 ] . files = [
276- { id : 10 , name : 'doc1.pdf' , metadata : { p : 0 } } ,
277- { id : 20 , name : 'doc2.pdf' , metadata : { p : 2 } } ,
287+ { id : 10 , name : 'doc1.pdf' , file : '/path/to/doc1.pdf' , metadata : { p : 0 } } ,
288+ { id : 20 , name : 'doc2.pdf' , file : '/path/to/doc2.pdf' , metadata : { p : 2 } } ,
278289 ]
279290
280291 wrapper . vm . buildFilePagesMap ( )
@@ -356,24 +367,24 @@ describe('VisibleElements Component - Business Rules', () => {
356367 describe ( 'RULE: PDF file name generation' , ( ) => {
357368 it ( 'generates file names with extension' , ( ) => {
358369 filesStore . files [ 1 ] . files = [
359- { name : 'doc1' , metadata : { extension : 'pdf' } } ,
360- { name : 'doc2' , metadata : { extension : 'docx' } } ,
370+ { name : 'doc1' , file : '/path/to/doc1.pdf' , metadata : { extension : 'pdf' } } ,
371+ { name : 'doc2' , file : '/path/to/doc2.docx' , metadata : { extension : 'docx' } } ,
361372 ]
362373
363374 expect ( wrapper . vm . pdfFileNames ) . toEqual ( [ 'doc1.pdf' , 'doc2.docx' ] )
364375 } )
365376
366377 it ( 'defaults to pdf extension when not specified' , ( ) => {
367378 filesStore . files [ 1 ] . files = [
368- { name : 'doc1' , metadata : { } } ,
379+ { name : 'doc1' , file : '/path/to/doc1.pdf' , metadata : { } } ,
369380 ]
370381
371382 expect ( wrapper . vm . pdfFileNames ) . toEqual ( [ 'doc1.pdf' ] )
372383 } )
373384
374385 it ( 'handles missing metadata' , ( ) => {
375386 filesStore . files [ 1 ] . files = [
376- { name : 'doc1' } ,
387+ { name : 'doc1' , file : '/path/to/doc1.pdf' } ,
377388 ]
378389
379390 expect ( wrapper . vm . pdfFileNames ) . toEqual ( [ 'doc1.pdf' ] )
@@ -411,6 +422,48 @@ describe('VisibleElements Component - Business Rules', () => {
411422 expect ( wrapper . vm . pdfFiles ) . toEqual ( [ ] )
412423 } )
413424
425+ it ( 'falls back to the current document file when there are no child files' , ( ) => {
426+ filesStore . files [ 1 ] . files = [ ]
427+ filesStore . files [ 1 ] . name = 'test'
428+ filesStore . files [ 1 ] . file = '/path/to/single-file.pdf'
429+ filesStore . files [ 1 ] . metadata = { extension : 'pdf' , p : 1 }
430+
431+ expect ( wrapper . vm . pdfFiles ) . toEqual ( [ '/path/to/single-file.pdf' ] )
432+ expect ( wrapper . vm . pdfFileNames ) . toEqual ( [ 'test.pdf' ] )
433+ } )
434+
435+ it ( 'supports current document file objects with nested URLs' , ( ) => {
436+ filesStore . files [ 1 ] . files = [ ]
437+ filesStore . files [ 1 ] . name = 'test'
438+ filesStore . files [ 1 ] . file = { url : '/path/to/single-file.pdf' }
439+ filesStore . files [ 1 ] . metadata = { extension : 'pdf' , p : 1 }
440+
441+ expect ( wrapper . vm . pdfFiles ) . toEqual ( [ '/path/to/single-file.pdf' ] )
442+ expect ( wrapper . vm . pdfFileNames ) . toEqual ( [ 'test.pdf' ] )
443+ } )
444+
445+ it ( 'falls back to the document uuid when no direct file URL is present' , ( ) => {
446+ wrapper . vm . document . files = [ ]
447+ wrapper . vm . document . file = null
448+ wrapper . vm . document . uuid = 'uuid-123'
449+ wrapper . vm . document . name = 'draft-document'
450+ wrapper . vm . document . metadata = { extension : 'pdf' , p : 1 }
451+
452+ expect ( wrapper . vm . pdfFiles ) . toEqual ( [ '/apps/libresign/p/pdf/uuid-123' ] )
453+ expect ( wrapper . vm . pdfFileNames ) . toEqual ( [ 'draft-document.pdf' ] )
454+ } )
455+
456+ it ( 'ignores placeholder document files without a renderable PDF URL' , ( ) => {
457+ wrapper . vm . document . files = [ { id : 10 , name : 'placeholder.pdf' , file : null , metadata : { extension : 'pdf' , p : 1 } } ]
458+ wrapper . vm . document . file = null
459+ wrapper . vm . document . uuid = 'uuid-123'
460+ wrapper . vm . document . name = 'draft-document'
461+ wrapper . vm . document . metadata = { extension : 'pdf' , p : 1 }
462+
463+ expect ( wrapper . vm . pdfFiles ) . toEqual ( [ '/apps/libresign/p/pdf/uuid-123' ] )
464+ expect ( wrapper . vm . pdfFileNames ) . toEqual ( [ 'draft-document.pdf' ] )
465+ } )
466+
414467 it ( 'extracts file objects from nested files array payload' , ( ) => {
415468 const file1 = '/path/to/file1.pdf'
416469 const file2 = '/path/to/file2.pdf'
@@ -422,13 +475,26 @@ describe('VisibleElements Component - Business Rules', () => {
422475
423476 expect ( wrapper . vm . pdfFiles ) . toEqual ( [ file1 , file2 ] )
424477 } )
478+
479+ it ( 'extracts file URLs from nested file objects' , ( ) => {
480+ const file1 = '/path/to/file1.pdf'
481+ const file2 = '/path/to/file2.pdf'
482+
483+ filesStore . files [ 1 ] . files = [
484+ { id : 10 , file : { url : file1 } } ,
485+ { id : 20 , file : { url : file2 } } ,
486+ ]
487+
488+ expect ( wrapper . vm . pdfFiles ) . toEqual ( [ file1 , file2 ] )
489+ } )
425490 } )
426491
427492 describe ( 'RULE: page height retrieval' , ( ) => {
428493 it ( 'retrieves correct page height from file metadata' , ( ) => {
429494 filesStore . files [ 1 ] . files = [
430495 {
431496 id : 10 ,
497+ file : '/path/to/doc1.pdf' ,
432498 metadata : {
433499 d : [
434500 { w : 595.28 , h : 841.89 } ,
@@ -446,15 +512,15 @@ describe('VisibleElements Component - Business Rules', () => {
446512
447513 it ( 'returns undefined for non-existent file' , ( ) => {
448514 filesStore . files [ 1 ] . files = [
449- { id : 10 , metadata : { d : [ { w : 595.28 , h : 841.89 } ] } } ,
515+ { id : 10 , file : '/path/to/doc1.pdf' , metadata : { d : [ { w : 595.28 , h : 841.89 } ] } } ,
450516 ]
451517
452518 expect ( wrapper . vm . getPageHeightForFile ( 999 , 1 ) ) . toBeUndefined ( )
453519 } )
454520
455521 it ( 'returns undefined for non-existent page' , ( ) => {
456522 filesStore . files [ 1 ] . files = [
457- { id : 10 , metadata : { d : [ { w : 595.28 , h : 841.89 } ] } } ,
523+ { id : 10 , file : '/path/to/doc1.pdf' , metadata : { d : [ { w : 595.28 , h : 841.89 } ] } } ,
458524 ]
459525
460526 expect ( wrapper . vm . getPageHeightForFile ( 10 , 5 ) ) . toBeUndefined ( )
@@ -567,7 +633,7 @@ describe('VisibleElements Component - Business Rules', () => {
567633 } ,
568634 } ) as unknown as VisibleElementsWrapper
569635
570- wrapperWithPdfEditorEvent . vm . modal = true
636+ await wrapperWithPdfEditorEvent . vm . showModal ( )
571637 wrapperWithPdfEditorEvent . vm . signerSelected = filesStore . files [ 1 ] . signers ?. [ 0 ] ?? null
572638 await wrapperWithPdfEditorEvent . vm . $nextTick ( )
573639
@@ -695,6 +761,41 @@ describe('VisibleElements Component - Business Rules', () => {
695761 expect ( filesStore . loading ) . toBe ( false )
696762 expect ( filesStore . files [ 1 ] . files ) . toHaveLength ( 1 )
697763 } )
764+
765+ it ( 'uses the current document PDF without fetching child files' , async ( ) => {
766+ wrapper . vm . document . files = [ ]
767+ wrapper . vm . document . file = null
768+ wrapper . vm . document . uuid = 'uuid-123'
769+ wrapper . vm . document . metadata = { extension : 'pdf' , p : 1 }
770+ ; ( vi . mocked ( axios ) . get as ReturnType < typeof vi . fn > ) . mockClear ( )
771+ fetchMock . mockClear ( )
772+ await wrapper . vm . $nextTick ( )
773+
774+ await wrapper . vm . showModal ( )
775+
776+ expect ( wrapper . vm . modal ) . toBe ( true )
777+ expect ( filesStore . loading ) . toBe ( false )
778+ expect ( vi . mocked ( axios ) . get ) . not . toHaveBeenCalled ( )
779+ expect ( fetchMock ) . toHaveBeenCalledWith ( '/apps/libresign/p/pdf/uuid-123' )
780+ expect ( wrapper . vm . pdfFiles ) . toEqual ( [ '/apps/libresign/p/pdf/uuid-123' ] )
781+ } )
782+
783+ it ( 'uses nested file URLs from the current document without fetching child files' , async ( ) => {
784+ wrapper . vm . document . files = [ ]
785+ wrapper . vm . document . file = { url : '/path/to/current-document.pdf' }
786+ wrapper . vm . document . metadata = { extension : 'pdf' , p : 1 }
787+ ; ( vi . mocked ( axios ) . get as ReturnType < typeof vi . fn > ) . mockClear ( )
788+ fetchMock . mockClear ( )
789+ await wrapper . vm . $nextTick ( )
790+
791+ await wrapper . vm . showModal ( )
792+
793+ expect ( wrapper . vm . modal ) . toBe ( true )
794+ expect ( filesStore . loading ) . toBe ( false )
795+ expect ( vi . mocked ( axios ) . get ) . not . toHaveBeenCalled ( )
796+ expect ( fetchMock ) . toHaveBeenCalledWith ( '/path/to/current-document.pdf' )
797+ expect ( wrapper . vm . pdfFiles ) . toEqual ( [ '/path/to/current-document.pdf' ] )
798+ } )
698799 } )
699800
700801 describe ( 'RULE: signer selection requires pdf editor' , ( ) => {
@@ -748,6 +849,7 @@ describe('VisibleElements Component - Business Rules', () => {
748849 {
749850 id : 10 ,
750851 name : 'doc1' ,
852+ file : '/path/to/doc1.pdf' ,
751853 metadata : { p : 2 , d : [ { w : 80 , h : 100 } , { w : 80 , h : 100 } ] } ,
752854 signers : [
753855 { signRequestId : 101 , identifyMethods : [ { method : 'email' , value : 'a' , mandatory : 0 } ] } ,
@@ -756,6 +858,7 @@ describe('VisibleElements Component - Business Rules', () => {
756858 {
757859 id : 20 ,
758860 name : 'doc2' ,
861+ file : '/path/to/doc2.pdf' ,
759862 metadata : { p : 1 , d : [ { w : 160 , h : 200 } ] } ,
760863 signers : [
761864 { signRequestId : 202 , identifyMethods : [ { method : 'email' , value : 'b' , mandatory : 0 } ] } ,
0 commit comments