@@ -224,6 +224,7 @@ type _executionTestOptions struct {
224224 validateRequiredExternalFields bool
225225 computeStaticCost bool
226226 relaxFieldSelectionMergingNullability bool
227+ streamingResponse bool
227228}
228229
229230type executionTestOptions func (* _executionTestOptions )
@@ -257,6 +258,11 @@ func computeStaticCost() executionTestOptions {
257258func relaxFieldSelectionMergingNullability () executionTestOptions {
258259 return func (options * _executionTestOptions ) {
259260 options .relaxFieldSelectionMergingNullability = true
261+ }
262+
263+ func withStreamingResponse () executionTestOptions {
264+ return func (options * _executionTestOptions ) {
265+ options .streamingResponse = true
260266 }
261267}
262268
@@ -309,6 +315,14 @@ func TestExecutionEngine_Execute(t *testing.T) {
309315
310316 operation := testCase .operation (t )
311317 resultWriter := graphql .NewEngineResultWriter ()
318+
319+ streamingBuf := bytes .NewBuffer (nil )
320+ if opts .streamingResponse {
321+ resultWriter .SetFlushCallback (func (data []byte ) {
322+ streamingBuf .Write (data )
323+ })
324+ }
325+
312326 execCtx , execCtxCancel := context .WithCancel (context .Background ())
313327 defer execCtxCancel ()
314328 err = engine .Execute (execCtx , & operation , & resultWriter , testCase .engineOptions ... )
@@ -340,7 +354,12 @@ func TestExecutionEngine_Execute(t *testing.T) {
340354 }
341355
342356 if testCase .expectedResponse != "" {
343- assert .Equal (t , testCase .expectedResponse , actualResponse )
357+ if opts .streamingResponse {
358+ streamingResponse := streamingBuf .String ()
359+ assert .Equal (t , testCase .expectedResponse , streamingResponse )
360+ } else {
361+ assert .Equal (t , testCase .expectedResponse , actualResponse )
362+ }
344363 }
345364
346365 if testCase .expectedStaticCost != 0 {
@@ -7024,6 +7043,100 @@ func TestExecutionEngine_Execute(t *testing.T) {
70247043 relaxFieldSelectionMergingNullability (),
70257044 ))
70267045 })
7046+
7047+ t .Run ("defer" , func (t * testing.T ) {
7048+ t .Run ("simple" , func (t * testing.T ) {
7049+
7050+ definition := `
7051+ type User {
7052+ id: ID!
7053+ name: String!
7054+ title: String!
7055+ }
7056+
7057+ type Query {
7058+ user: User!
7059+ }
7060+ `
7061+
7062+ makeDataSource := func (t * testing.T , expectFetchReasons bool ) []plan.DataSource {
7063+ return []plan.DataSource {
7064+ mustGraphqlDataSourceConfiguration (t ,
7065+ "id-1" ,
7066+ mustFactory (t ,
7067+ testConditionalNetHttpClient (t , conditionalTestCase {
7068+ expectedHost : "first" ,
7069+ expectedPath : "/" ,
7070+ responses : map [string ]sendResponse {
7071+ `{"query":"{user {name}}"}` : {
7072+ statusCode : 200 ,
7073+ body : `{"data":{"user":{"name":"Black"}}}` ,
7074+ },
7075+ `{"query":"{user {title}}"}` : {
7076+ statusCode : 200 ,
7077+ body : `{"data":{"user":{"title":"Sabbat"}}}` ,
7078+ },
7079+ },
7080+ }),
7081+ ),
7082+ & plan.DataSourceMetadata {
7083+ RootNodes : []plan.TypeField {
7084+ {
7085+ TypeName : "Query" ,
7086+ FieldNames : []string {"user" },
7087+ },
7088+ },
7089+ ChildNodes : []plan.TypeField {
7090+ {
7091+ TypeName : "User" ,
7092+ FieldNames : []string {"id" , "title" , "name" },
7093+ },
7094+ },
7095+ },
7096+ mustConfiguration (t , graphql_datasource.ConfigurationInput {
7097+ Fetch : & graphql_datasource.FetchConfiguration {
7098+ URL : "https://first/" ,
7099+ Method : "POST" ,
7100+ },
7101+ SchemaConfiguration : mustSchemaConfig (
7102+ t ,
7103+ & graphql_datasource.FederationConfiguration {
7104+ Enabled : true ,
7105+ ServiceSDL : definition ,
7106+ },
7107+ definition ,
7108+ ),
7109+ }),
7110+ ),
7111+ }
7112+ }
7113+
7114+ t .Run ("run" , runWithoutError (ExecutionEngineTestCase {
7115+ schema : func (t * testing.T ) * graphql.Schema {
7116+ t .Helper ()
7117+ parseSchema , err := graphql .NewSchemaFromString (definition )
7118+ require .NoError (t , err )
7119+ return parseSchema
7120+ }(t ),
7121+ operation : func (t * testing.T ) graphql.Request {
7122+ return graphql.Request {
7123+ OperationName : "DeferUserTitle" ,
7124+ Query : `
7125+ query DeferUserTitle {
7126+ user {
7127+ name
7128+ ... @defer {
7129+ title
7130+ }
7131+ }
7132+ }` ,
7133+ }
7134+ },
7135+ dataSources : makeDataSource (t , false ),
7136+ expectedResponse : `{"data":{"user":{"name":"Black"}}}{"name":"Black"}{"data":{{"name":"Black"}}}` ,
7137+ }, withStreamingResponse ()))
7138+ })
7139+ })
70277140}
70287141
70297142func testNetHttpClient (t * testing.T , testCase roundTripperTestCase ) * http.Client {
0 commit comments