File tree Expand file tree Collapse file tree 3 files changed +159
-0
lines changed
src/HotChocolate/Fusion-vnext
src/Fusion.Execution/Execution/Nodes
test/Fusion.AspNetCore.Tests Expand file tree Collapse file tree 3 files changed +159
-0
lines changed Original file line number Diff line number Diff line change @@ -55,6 +55,57 @@ public OperationExecutionNode(
55
55
}
56
56
57
57
_variables = variables . ToArray ( ) ;
58
+
59
+ var selectionSet = GetSelectionSetNodeFromPath ( operation , source ) ;
60
+
61
+ _providingSelectionSet = selectionSet ?? throw new InvalidOperationException ( "Could not determine source selection set" ) ;
62
+ }
63
+
64
+ private readonly SelectionSetNode _providingSelectionSet ;
65
+
66
+ // TODO: Move
67
+ private static SelectionSetNode ? GetSelectionSetNodeFromPath ( OperationDefinitionNode operationDefinition , SelectionPath path )
68
+ {
69
+ var current = operationDefinition . SelectionSet ;
70
+
71
+ if ( path . IsRoot )
72
+ {
73
+ return current ;
74
+ }
75
+
76
+ for ( var i = path . Segments . Length - 1 ; i >= 0 ; i -- )
77
+ {
78
+ var segment = path . Segments [ i ] ;
79
+
80
+ if ( segment . Kind == SelectionPathSegmentKind . InlineFragment )
81
+ {
82
+ // TODO: Do we need to handle the case without a type condition?
83
+ var selection = current . Selections
84
+ . OfType < InlineFragmentNode > ( )
85
+ . FirstOrDefault ( s => s . TypeCondition ? . Name . Value == segment . Name ) ;
86
+
87
+ if ( selection is null )
88
+ {
89
+ return null ;
90
+ }
91
+
92
+ current = selection . SelectionSet ;
93
+ }
94
+ else if ( segment . Kind is SelectionPathSegmentKind . Field )
95
+ {
96
+ var selection = current . Selections
97
+ . OfType < FieldNode > ( )
98
+ . FirstOrDefault ( s => s . Alias ? . Value == segment . Name || s . Name . Value == segment . Name ) ;
99
+
100
+ if ( selection ? . SelectionSet is null )
101
+ {
102
+ return null ;
103
+ }
104
+ current = selection . SelectionSet ;
105
+ }
106
+ }
107
+
108
+ return current ;
58
109
}
59
110
60
111
public override int Id { get ; }
Original file line number Diff line number Diff line change @@ -304,6 +304,44 @@ public async Task No_Data_And_Error_With_Path_For_Lookup()
304
304
response . MatchSnapshot ( ) ;
305
305
}
306
306
307
+ [ Fact ]
308
+ public async Task No_Data_And_Error_With_Path_For_Lookup_Leaf ( )
309
+ {
310
+ // arrange
311
+ using var server1 = CreateSourceSchema (
312
+ "A" ,
313
+ b => b . AddQueryType < SourceSchema1 . Query > ( ) ) ;
314
+
315
+ using var server2 = CreateSourceSchema (
316
+ "B" ,
317
+ b => b . AddQueryType < SourceSchema6 . Query > ( ) ) ;
318
+
319
+ // act
320
+ using var gateway = await CreateCompositeSchemaAsync (
321
+ [
322
+ ( "A" , server1 ) ,
323
+ ( "B" , server2 ) ,
324
+ ] ) ;
325
+
326
+ // assert
327
+ using var client = GraphQLHttpClient . Create ( gateway . CreateClient ( ) ) ;
328
+
329
+ using var result = await client . PostAsync (
330
+ """
331
+ {
332
+ topProduct {
333
+ price
334
+ name
335
+ }
336
+ }
337
+ """ ,
338
+ new Uri ( "http://localhost:5000/graphql" ) ) ;
339
+
340
+ // act
341
+ using var response = await result . ReadAsResultAsync ( ) ;
342
+ response . MatchSnapshot ( ) ;
343
+ }
344
+
307
345
[ Fact ]
308
346
public async Task No_Data_And_Error_Without_Path_For_Lookup ( )
309
347
{
@@ -475,4 +513,22 @@ public record Product(int Id)
475
513
public string GetName ( ) => "Product " + Id ;
476
514
}
477
515
}
516
+
517
+ public static class SourceSchema6
518
+ {
519
+ public class Query
520
+ {
521
+ [ Lookup ]
522
+ public Product GetProductById ( int id ) => new ( id ) ;
523
+ }
524
+
525
+ public record Product ( int Id )
526
+ {
527
+ public string GetName ( IResolverContext context )
528
+ {
529
+ throw new GraphQLException ( ErrorBuilder . New ( ) . SetMessage ( "Could not resolve Product.name" )
530
+ . SetPath ( context . Path ) . Build ( ) ) ;
531
+ }
532
+ }
533
+ }
478
534
}
Original file line number Diff line number Diff line change
1
+ {
2
+ " data" : {
3
+ " topProduct" : {
4
+ " price" : 13.99 ,
5
+ " name" : null
6
+ }
7
+ },
8
+ " errors" : [
9
+ {
10
+ " message" : " Could not resolve Product.name" ,
11
+ " path" : [
12
+ " topProduct" ,
13
+ " name"
14
+ ]
15
+ }
16
+ ],
17
+ " extensions" : {
18
+ " fusion" : {
19
+ " operationPlan" : {
20
+ " operation" : {
21
+ " document" : " {\n topProduct {\n price\n name\n id @fusion__requirement\n }\n }" ,
22
+ " hash" : " e24d93b6245cedd878fff4452f5f16b9"
23
+ },
24
+ " nodes" : [
25
+ {
26
+ " id" : 1 ,
27
+ " type" : " Operation" ,
28
+ " schema" : " A" ,
29
+ " operation" : " query Op_e24d93b6_1 {\n topProduct {\n price\n id\n }\n }"
30
+ },
31
+ {
32
+ " id" : 2 ,
33
+ " type" : " Operation" ,
34
+ " schema" : " B" ,
35
+ " operation" : " query Op_e24d93b6_2(\n $__fusion_1_id: Int!\n ) {\n productById(id: $__fusion_1_id) {\n name\n }\n }" ,
36
+ " source" : " $.productById" ,
37
+ " target" : " $.topProduct" ,
38
+ " requirements" : [
39
+ {
40
+ " name" : " __fusion_1_id" ,
41
+ " selectionMap" : " id"
42
+ }
43
+ ],
44
+ " dependencies" : [
45
+ 1
46
+ ]
47
+ }
48
+ ]
49
+ }
50
+ }
51
+ }
52
+ }
You can’t perform that action at this time.
0 commit comments