88import { beforeEach , describe , expect , it , vi } from 'vitest'
99import { AuthType } from '@/lib/auth/hybrid'
1010import { clearLargeValueCacheForTests } from '@/lib/execution/payloads/cache'
11- import { isLargeArrayManifest } from '@/lib/execution/payloads/large-array-manifest-metadata'
12- import { isLargeValueRef } from '@/lib/execution/payloads/large-value-ref'
1311import { compactExecutionPayload } from '@/lib/execution/payloads/serializer'
12+ import { EXECUTION_RESOURCE_LIMIT_CODE } from '@/lib/execution/resource-errors'
1413import type { ExecutionResult } from '@/lib/workflows/types'
1514import { createHttpResponseFromBlock , workflowHasResponseBlock } from '@/lib/workflows/utils'
1615
1716const { mockUploadFile } = vi . hoisted ( ( ) => ( {
1817 mockUploadFile : vi . fn ( ) ,
1918} ) )
2019
20+ const MATERIALIZATION_CONTEXT = {
21+ workspaceId : 'workspace-1' ,
22+ workflowId : 'workflow-1' ,
23+ executionId : 'execution-1' ,
24+ userId : 'user-1' ,
25+ }
26+
2127vi . mock ( '@/lib/uploads' , ( ) => ( {
2228 StorageService : {
2329 uploadFile : mockUploadFile ,
@@ -92,14 +98,14 @@ describe('Response block gating by auth type', () => {
9298 expect ( shouldFormatAsResponseBlock ) . toBe ( false )
9399 } )
94100
95- it ( 'should apply Response block formatting for API key callers' , ( ) => {
101+ it ( 'should apply Response block formatting for API key callers' , async ( ) => {
96102 const authType = AuthType . API_KEY
97103 const hasResponseBlock = workflowHasResponseBlock ( resultWithResponseBlock )
98104
99105 const shouldFormatAsResponseBlock = authType !== AuthType . INTERNAL_JWT && hasResponseBlock
100106 expect ( shouldFormatAsResponseBlock ) . toBe ( true )
101107
102- const response = createHttpResponseFromBlock ( resultWithResponseBlock )
108+ const response = await createHttpResponseFromBlock ( resultWithResponseBlock )
103109 expect ( response . status ) . toBe ( 200 )
104110 } )
105111
@@ -112,7 +118,7 @@ describe('Response block gating by auth type', () => {
112118 } )
113119
114120 it ( 'should return raw user data via createHttpResponseFromBlock' , async ( ) => {
115- const response = createHttpResponseFromBlock ( resultWithResponseBlock )
121+ const response = await createHttpResponseFromBlock ( resultWithResponseBlock )
116122 const body = await response . json ( )
117123
118124 // Response block returns the user-defined data directly (no success/executionId wrapper)
@@ -121,66 +127,88 @@ describe('Response block gating by auth type', () => {
121127 expect ( body . executionId ) . toBeUndefined ( )
122128 } )
123129
124- it ( 'should respect custom status codes from Response block' , ( ) => {
130+ it ( 'should respect custom status codes from Response block' , async ( ) => {
125131 const result = buildExecutionResult ( {
126132 output : { data : { error : 'Not found' } , status : 404 , headers : { } } ,
127133 } )
128134
129- const response = createHttpResponseFromBlock ( result )
135+ const response = await createHttpResponseFromBlock ( result )
130136 expect ( response . status ) . toBe ( 404 )
131137 } )
132138
133- it ( 'should return manifest metadata directly for Response block data' , async ( ) => {
139+ it ( 'should materialize manifest data for Response block HTTP output' , async ( ) => {
140+ const rows = Array . from ( { length : 100 } , ( _ , index ) => ( {
141+ key : `SIM-${ index } ` ,
142+ payload : 'x' . repeat ( 100 ) ,
143+ } ) )
134144 const output = await compactExecutionPayload (
135145 {
136- data : {
137- rows : Array . from ( { length : 120_000 } , ( _ , index ) => ( {
138- key : `SIM-${ index } ` ,
139- payload : 'x' . repeat ( 100 ) ,
140- } ) ) ,
141- } ,
146+ data : { rows } ,
142147 status : 200 ,
143148 headers : { } ,
144149 } ,
145150 {
146- workspaceId : 'workspace-1' ,
147- workflowId : 'workflow-1' ,
148- executionId : 'execution-1' ,
149- userId : 'user-1' ,
151+ ...MATERIALIZATION_CONTEXT ,
150152 requireDurable : true ,
151153 preserveRoot : true ,
154+ thresholdBytes : 1024 ,
152155 }
153156 )
154- const response = createHttpResponseFromBlock ( buildExecutionResult ( { output } ) )
157+ const response = await createHttpResponseFromBlock (
158+ buildExecutionResult ( { output } ) ,
159+ MATERIALIZATION_CONTEXT
160+ )
155161 const body = await response . json ( )
156162
157163 expect ( response . status ) . toBe ( 200 )
158- expect ( isLargeArrayManifest ( body . rows ) ) . toBe ( true )
164+ expect ( body . rows ) . toEqual ( rows )
159165 expect ( body . success ) . toBeUndefined ( )
160166 } )
161167
162- it ( 'should keep large string Response block data bounded as a generic ref' , async ( ) => {
168+ it ( 'should materialize large string refs for Response block HTTP output' , async ( ) => {
169+ const text = 'x' . repeat ( 9 * 1024 * 1024 )
163170 const output = await compactExecutionPayload (
164171 {
165- data : {
166- text : 'x' . repeat ( 9 * 1024 * 1024 ) ,
167- } ,
172+ data : { text } ,
168173 status : 200 ,
169174 headers : { } ,
170175 } ,
171176 {
172- workspaceId : 'workspace-1' ,
173- workflowId : 'workflow-1' ,
174- executionId : 'execution-1' ,
175- userId : 'user-1' ,
177+ ...MATERIALIZATION_CONTEXT ,
176178 requireDurable : true ,
177179 preserveRoot : true ,
178180 }
179181 )
180- const response = createHttpResponseFromBlock ( buildExecutionResult ( { output } ) )
182+ const response = await createHttpResponseFromBlock (
183+ buildExecutionResult ( { output } ) ,
184+ MATERIALIZATION_CONTEXT
185+ )
181186 const body = await response . json ( )
182187
183188 expect ( response . status ) . toBe ( 200 )
184- expect ( isLargeValueRef ( body . text ) ) . toBe ( true )
189+ expect ( body . text ) . toBe ( text )
190+ } )
191+
192+ it ( 'should reject Response block HTTP output that is too large to inline' , async ( ) => {
193+ const output = await compactExecutionPayload (
194+ {
195+ data : {
196+ text : 'x' . repeat ( 17 * 1024 * 1024 ) ,
197+ } ,
198+ status : 200 ,
199+ headers : { } ,
200+ } ,
201+ {
202+ ...MATERIALIZATION_CONTEXT ,
203+ requireDurable : true ,
204+ preserveRoot : true ,
205+ }
206+ )
207+
208+ await expect (
209+ createHttpResponseFromBlock ( buildExecutionResult ( { output } ) , MATERIALIZATION_CONTEXT )
210+ ) . rejects . toMatchObject ( {
211+ code : EXECUTION_RESOURCE_LIMIT_CODE ,
212+ } )
185213 } )
186214} )
0 commit comments