@@ -135,6 +135,64 @@ describe('POST /api/tools/quickbooks/upload-attachment', () => {
135135 )
136136 } )
137137
138+ it ( 'normalizes linked entity names before building attachment metadata' , async ( ) => {
139+ const response = await POST (
140+ createMockRequest ( 'POST' , {
141+ ...baseBody ,
142+ entity : 'purchaseorder' ,
143+ } )
144+ )
145+ expect ( response . status ) . toBe ( 200 )
146+
147+ const [ , init ] = mockFetch . mock . calls [ 0 ] as [ string , RequestInit ]
148+ const metadata = ( init . body as FormData ) . get ( 'file_metadata_01' )
149+ expect ( metadata ) . toBeInstanceOf ( Blob )
150+ await expect ( ( metadata as Blob ) . text ( ) ) . resolves . toContain (
151+ '"EntityRef":{"type":"PurchaseOrder","value":"17"}'
152+ )
153+ } )
154+
155+ it ( 'rejects nested QuickBooks upload faults returned with HTTP 200' , async ( ) => {
156+ mockFetch . mockResolvedValueOnce (
157+ new Response (
158+ JSON . stringify ( {
159+ AttachableResponse : [
160+ {
161+ Fault : {
162+ Error : [ { Message : 'ValidationFault' , Detail : 'Unsupported entity reference' } ] ,
163+ } ,
164+ } ,
165+ ] ,
166+ time : '2026-07-29T23:00:00Z' ,
167+ } ) ,
168+ { headers : { 'content-type' : 'application/json' } , status : 200 }
169+ )
170+ )
171+
172+ const response = await POST ( createMockRequest ( 'POST' , baseBody ) )
173+ expect ( response . status ) . toBe ( 500 )
174+ await expect ( response . json ( ) ) . resolves . toEqual ( {
175+ success : false ,
176+ error : 'QuickBooks API error (200): Unsupported entity reference' ,
177+ } )
178+ } )
179+
180+ it ( 'rejects timestamp-only QuickBooks upload responses' , async ( ) => {
181+ mockFetch . mockResolvedValueOnce (
182+ new Response ( JSON . stringify ( { time : '2026-07-29T23:00:00Z' } ) , {
183+ headers : { 'content-type' : 'application/json' } ,
184+ status : 200 ,
185+ } )
186+ )
187+
188+ const response = await POST ( createMockRequest ( 'POST' , baseBody ) )
189+ expect ( response . status ) . toBe ( 500 )
190+ await expect ( response . json ( ) ) . resolves . toEqual ( {
191+ success : false ,
192+ error : 'QuickBooks attachment upload returned no attachment' ,
193+ } )
194+ } )
195+
138196 it ( 'rejects files over the QuickBooks 100 MB attachment limit' , async ( ) => {
139197 mockProcessFilesToUserFiles . mockReturnValueOnce ( [
140198 { ...baseBody . file , size : 100 * 1024 * 1024 + 1 } ,
0 commit comments