1- using JsonApiDotNetCore . Builders ;
1+ using System . Collections . Generic ;
2+ using System . Linq ;
3+ using System . Text . RegularExpressions ;
4+ using JsonApiDotNetCore . Builders ;
25using JsonApiDotNetCore . Configuration ;
6+ using JsonApiDotNetCore . Extensions ;
37using JsonApiDotNetCore . Internal ;
48using JsonApiDotNetCore . Models ;
9+ using JsonApiDotNetCore . Request ;
510using JsonApiDotNetCore . Serialization ;
611using JsonApiDotNetCore . Services ;
12+ using Microsoft . Extensions . DependencyInjection ;
713using Moq ;
814using Xunit ;
915
@@ -17,19 +23,9 @@ public void Can_Serialize_Complex_Types()
1723 // arrange
1824 var contextGraphBuilder = new ContextGraphBuilder ( ) ;
1925 contextGraphBuilder . AddResource < TestResource > ( "test-resource" ) ;
20- var contextGraph = contextGraphBuilder . Build ( ) ;
21-
22- var jsonApiContextMock = new Mock < IJsonApiContext > ( ) ;
23- jsonApiContextMock . SetupAllProperties ( ) ;
24- jsonApiContextMock . Setup ( m => m . ContextGraph ) . Returns ( contextGraph ) ;
25- jsonApiContextMock . Setup ( m => m . Options ) . Returns ( new JsonApiOptions ( ) ) ;
26- jsonApiContextMock . Setup ( m => m . RequestEntity )
27- . Returns ( contextGraph . GetContextEntity ( "test-resource" ) ) ;
28- jsonApiContextMock . Setup ( m => m . MetaBuilder ) . Returns ( new MetaBuilder ( ) ) ;
29- jsonApiContextMock . Setup ( m => m . PageManager ) . Returns ( new PageManager ( ) ) ;
26+
27+ var serializer = GetSerializer ( contextGraphBuilder ) ;
3028
31- var documentBuilder = new DocumentBuilder ( jsonApiContextMock . Object ) ;
32- var serializer = new JsonApiSerializer ( jsonApiContextMock . Object , documentBuilder ) ;
3329 var resource = new TestResource
3430 {
3531 ComplexMember = new ComplexType
@@ -43,18 +39,235 @@ public void Can_Serialize_Complex_Types()
4339
4440 // assert
4541 Assert . NotNull ( result ) ;
46- Assert . Equal ( "{\" data\" :{\" attributes\" :{\" complex-member\" :{\" compound-name\" :\" testname\" }},\" type\" :\" test-resource\" ,\" id\" :\" \" }}" , result ) ;
42+
43+ var expectedFormatted =
44+ @"{
45+ ""data"": {
46+ ""attributes"": {
47+ ""complex-member"": {
48+ ""compound-name"": ""testname""
49+ }
50+ },
51+ ""relationships"": {
52+ ""children"": {
53+ ""links"": {
54+ ""self"": ""/test-resource//relationships/children"",
55+ ""related"": ""/test-resource//children""
56+ }
57+ }
58+ },
59+ ""type"": ""test-resource"",
60+ ""id"": """"
61+ }
62+ }" ;
63+ var expected = Regex . Replace ( expectedFormatted , @"\s+" , "" ) ;
64+
65+ Assert . Equal ( expected , result ) ;
66+ }
67+
68+ [ Fact ]
69+ public void Can_Serialize_Deeply_Nested_Relationships ( )
70+ {
71+ // arrange
72+ var contextGraphBuilder = new ContextGraphBuilder ( ) ;
73+ contextGraphBuilder . AddResource < TestResource > ( "test-resource" ) ;
74+ contextGraphBuilder . AddResource < ChildResource > ( "children" ) ;
75+ contextGraphBuilder . AddResource < InfectionResource > ( "infections" ) ;
76+
77+ var serializer = GetSerializer (
78+ contextGraphBuilder ,
79+ included : new List < string > { "children.infections" }
80+ ) ;
81+
82+ var resource = new TestResource
83+ {
84+ Id = 1 ,
85+ Children = new List < ChildResource > {
86+ new ChildResource {
87+ Id = 2 ,
88+ Infections = new List < InfectionResource > {
89+ new InfectionResource { Id = 4 } ,
90+ new InfectionResource { Id = 5 } ,
91+ }
92+ } ,
93+ new ChildResource {
94+ Id = 3
95+ }
96+ }
97+ } ;
98+
99+ // act
100+ var result = serializer . Serialize ( resource ) ;
101+
102+ // assert
103+ Assert . NotNull ( result ) ;
104+
105+ var expectedFormatted =
106+ @"{
107+ ""data"": {
108+ ""attributes"": {
109+ ""complex-member"": null
110+ },
111+ ""relationships"": {
112+ ""children"": {
113+ ""links"": {
114+ ""self"": ""/test-resource/1/relationships/children"",
115+ ""related"": ""/test-resource/1/children""
116+ },
117+ ""data"": [{
118+ ""type"": ""children"",
119+ ""id"": ""2""
120+ }, {
121+ ""type"": ""children"",
122+ ""id"": ""3""
123+ }]
124+ }
125+ },
126+ ""type"": ""test-resource"",
127+ ""id"": ""1""
128+ },
129+ ""included"": [
130+ {
131+ ""attributes"": {},
132+ ""relationships"": {
133+ ""infections"": {
134+ ""links"": {
135+ ""self"": ""/children/2/relationships/infections"",
136+ ""related"": ""/children/2/infections""
137+ },
138+ ""data"": [{
139+ ""type"": ""infections"",
140+ ""id"": ""4""
141+ }, {
142+ ""type"": ""infections"",
143+ ""id"": ""5""
144+ }]
145+ },
146+ ""parent"": {
147+ ""links"": {
148+ ""self"": ""/children/2/relationships/parent"",
149+ ""related"": ""/children/2/parent""
150+ }
151+ }
152+ },
153+ ""type"": ""children"",
154+ ""id"": ""2""
155+ },
156+ {
157+ ""attributes"": {},
158+ ""relationships"": {
159+ ""infected"": {
160+ ""links"": {
161+ ""self"": ""/infections/4/relationships/infected"",
162+ ""related"": ""/infections/4/infected""
163+ }
164+ }
165+ },
166+ ""type"": ""infections"",
167+ ""id"": ""4""
168+ },
169+ {
170+ ""attributes"": {},
171+ ""relationships"": {
172+ ""infected"": {
173+ ""links"": {
174+ ""self"": ""/infections/5/relationships/infected"",
175+ ""related"": ""/infections/5/infected""
176+ }
177+ }
178+ },
179+ ""type"": ""infections"",
180+ ""id"": ""5""
181+ },
182+ {
183+ ""attributes"": {},
184+ ""relationships"": {
185+ ""infections"": {
186+ ""links"": {
187+ ""self"": ""/children/3/relationships/infections"",
188+ ""related"": ""/children/3/infections""
189+ }
190+ },
191+ ""parent"": {
192+ ""links"": {
193+ ""self"": ""/children/3/relationships/parent"",
194+ ""related"": ""/children/3/parent""
195+ }
196+ }
197+ },
198+ ""type"": ""children"",
199+ ""id"": ""3""
200+ }
201+ ]
202+ }" ;
203+ var expected = Regex . Replace ( expectedFormatted , @"\s+" , "" ) ;
204+
205+ Assert . Equal ( expected , result ) ;
206+ }
207+
208+ private JsonApiSerializer GetSerializer (
209+ ContextGraphBuilder contextGraphBuilder ,
210+ List < string > included = null )
211+ {
212+ var contextGraph = contextGraphBuilder . Build ( ) ;
213+
214+ var jsonApiContextMock = new Mock < IJsonApiContext > ( ) ;
215+ jsonApiContextMock . SetupAllProperties ( ) ;
216+ jsonApiContextMock . Setup ( m => m . ContextGraph ) . Returns ( contextGraph ) ;
217+ jsonApiContextMock . Setup ( m => m . Options ) . Returns ( new JsonApiOptions ( ) ) ;
218+ jsonApiContextMock . Setup ( m => m . RequestEntity ) . Returns ( contextGraph . GetContextEntity ( "test-resource" ) ) ;
219+ // jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
220+ // jsonApiContextMock.Setup(m => m.RelationshipsToUpdate).Returns(new Dictionary<RelationshipAttribute, object>());
221+ // jsonApiContextMock.Setup(m => m.HasManyRelationshipPointers).Returns(new HasManyRelationshipPointers());
222+ // jsonApiContextMock.Setup(m => m.HasOneRelationshipPointers).Returns(new HasOneRelationshipPointers());
223+ jsonApiContextMock . Setup ( m => m . MetaBuilder ) . Returns ( new MetaBuilder ( ) ) ;
224+ jsonApiContextMock . Setup ( m => m . PageManager ) . Returns ( new PageManager ( ) ) ;
225+
226+ if ( included != null )
227+ jsonApiContextMock . Setup ( m => m . IncludedRelationships ) . Returns ( included ) ;
228+
229+ var jsonApiOptions = new JsonApiOptions ( ) ;
230+ jsonApiContextMock . Setup ( m => m . Options ) . Returns ( jsonApiOptions ) ;
231+
232+ var services = new ServiceCollection ( ) ;
233+
234+ var mvcBuilder = services . AddMvcCore ( ) ;
235+
236+ services
237+ . AddJsonApiInternals ( jsonApiOptions ) ;
238+
239+ var provider = services . BuildServiceProvider ( ) ;
240+ var scoped = new TestScopedServiceProvider ( provider ) ;
241+
242+ var documentBuilder = new DocumentBuilder ( jsonApiContextMock . Object , scopedServiceProvider : scoped ) ;
243+ var serializer = new JsonApiSerializer ( jsonApiContextMock . Object , documentBuilder ) ;
244+
245+ return serializer ;
47246 }
48247
49248 private class TestResource : Identifiable
50249 {
51250 [ Attr ( "complex-member" ) ]
52251 public ComplexType ComplexMember { get ; set ; }
252+
253+ [ HasMany ( "children" ) ] public List < ChildResource > Children { get ; set ; }
53254 }
54255
55256 private class ComplexType
56257 {
57258 public string CompoundName { get ; set ; }
58259 }
260+
261+ private class ChildResource : Identifiable
262+ {
263+ [ HasMany ( "infections" ) ] public List < InfectionResource > Infections { get ; set ; }
264+
265+ [ HasOne ( "parent" ) ] public TestResource Parent { get ; set ; }
266+ }
267+
268+ private class InfectionResource : Identifiable
269+ {
270+ [ HasOne ( "infected" ) ] public ChildResource Infected { get ; set ; }
271+ }
59272 }
60273}
0 commit comments