@@ -220,6 +220,7 @@ type _executionTestOptions struct {
220220 apolloRouterCompatibilitySubrequestHTTPError bool
221221 propagateFetchReasons bool
222222 validateRequiredExternalFields bool
223+ streamingResponse bool
223224}
224225
225226type executionTestOptions func (* _executionTestOptions )
@@ -244,6 +245,12 @@ func validateRequiredExternalFields() executionTestOptions {
244245 }
245246}
246247
248+ func withStreamingResponse () executionTestOptions {
249+ return func (options * _executionTestOptions ) {
250+ options .streamingResponse = true
251+ }
252+ }
253+
247254func TestExecutionEngine_Execute (t * testing.T ) {
248255 run := func (testCase ExecutionEngineTestCase , withError bool , expectedErrorMessage string , options ... executionTestOptions ) func (t * testing.T ) {
249256 t .Helper ()
@@ -289,6 +296,14 @@ func TestExecutionEngine_Execute(t *testing.T) {
289296
290297 operation := testCase .operation (t )
291298 resultWriter := graphql .NewEngineResultWriter ()
299+
300+ streamingBuf := bytes .NewBuffer (nil )
301+ if opts .streamingResponse {
302+ resultWriter .SetFlushCallback (func (data []byte ) {
303+ streamingBuf .Write (data )
304+ })
305+ }
306+
292307 execCtx , execCtxCancel := context .WithCancel (context .Background ())
293308 defer execCtxCancel ()
294309 err = engine .Execute (execCtx , & operation , & resultWriter , testCase .engineOptions ... )
@@ -311,7 +326,12 @@ func TestExecutionEngine_Execute(t *testing.T) {
311326 }
312327
313328 if testCase .expectedResponse != "" {
314- assert .Equal (t , testCase .expectedResponse , actualResponse )
329+ if opts .streamingResponse {
330+ streamingResponse := streamingBuf .String ()
331+ assert .Equal (t , testCase .expectedResponse , streamingResponse )
332+ } else {
333+ assert .Equal (t , testCase .expectedResponse , actualResponse )
334+ }
315335 }
316336
317337 if withError {
@@ -5603,6 +5623,100 @@ func TestExecutionEngine_Execute(t *testing.T) {
56035623 }, withFetchReasons (), validateRequiredExternalFields ()))
56045624 })
56055625 })
5626+
5627+ t .Run ("defer" , func (t * testing.T ) {
5628+ t .Run ("simple" , func (t * testing.T ) {
5629+
5630+ definition := `
5631+ type User {
5632+ id: ID!
5633+ name: String!
5634+ title: String!
5635+ }
5636+
5637+ type Query {
5638+ user: User!
5639+ }
5640+ `
5641+
5642+ makeDataSource := func (t * testing.T , expectFetchReasons bool ) []plan.DataSource {
5643+ return []plan.DataSource {
5644+ mustGraphqlDataSourceConfiguration (t ,
5645+ "id-1" ,
5646+ mustFactory (t ,
5647+ testConditionalNetHttpClient (t , conditionalTestCase {
5648+ expectedHost : "first" ,
5649+ expectedPath : "/" ,
5650+ responses : map [string ]sendResponse {
5651+ `{"query":"{user {name}}"}` : {
5652+ statusCode : 200 ,
5653+ body : `{"data":{"user":{"name":"Black"}}}` ,
5654+ },
5655+ `{"query":"{user {title}}"}` : {
5656+ statusCode : 200 ,
5657+ body : `{"data":{"user":{"title":"Sabbat"}}}` ,
5658+ },
5659+ },
5660+ }),
5661+ ),
5662+ & plan.DataSourceMetadata {
5663+ RootNodes : []plan.TypeField {
5664+ {
5665+ TypeName : "Query" ,
5666+ FieldNames : []string {"user" },
5667+ },
5668+ },
5669+ ChildNodes : []plan.TypeField {
5670+ {
5671+ TypeName : "User" ,
5672+ FieldNames : []string {"id" , "title" , "name" },
5673+ },
5674+ },
5675+ },
5676+ mustConfiguration (t , graphql_datasource.ConfigurationInput {
5677+ Fetch : & graphql_datasource.FetchConfiguration {
5678+ URL : "https://first/" ,
5679+ Method : "POST" ,
5680+ },
5681+ SchemaConfiguration : mustSchemaConfig (
5682+ t ,
5683+ & graphql_datasource.FederationConfiguration {
5684+ Enabled : true ,
5685+ ServiceSDL : definition ,
5686+ },
5687+ definition ,
5688+ ),
5689+ }),
5690+ ),
5691+ }
5692+ }
5693+
5694+ t .Run ("run" , runWithoutError (ExecutionEngineTestCase {
5695+ schema : func (t * testing.T ) * graphql.Schema {
5696+ t .Helper ()
5697+ parseSchema , err := graphql .NewSchemaFromString (definition )
5698+ require .NoError (t , err )
5699+ return parseSchema
5700+ }(t ),
5701+ operation : func (t * testing.T ) graphql.Request {
5702+ return graphql.Request {
5703+ OperationName : "DeferUserTitle" ,
5704+ Query : `
5705+ query DeferUserTitle {
5706+ user {
5707+ name
5708+ ... @defer {
5709+ title
5710+ }
5711+ }
5712+ }` ,
5713+ }
5714+ },
5715+ dataSources : makeDataSource (t , false ),
5716+ expectedResponse : `{"data":{"user":{"name":"Black"}}}{"name":"Black"}{"data":{{"name":"Black"}}}` ,
5717+ }, withStreamingResponse ()))
5718+ })
5719+ })
56065720}
56075721
56085722func testNetHttpClient (t * testing.T , testCase roundTripperTestCase ) * http.Client {
0 commit comments