1
- using JsonApiDotNetCore . Builders ;
1
+ using System . Collections . Generic ;
2
+ using System . Linq ;
3
+ using System . Text . RegularExpressions ;
4
+ using JsonApiDotNetCore . Builders ;
2
5
using JsonApiDotNetCore . Configuration ;
6
+ using JsonApiDotNetCore . Extensions ;
3
7
using JsonApiDotNetCore . Internal ;
4
8
using JsonApiDotNetCore . Models ;
9
+ using JsonApiDotNetCore . Request ;
5
10
using JsonApiDotNetCore . Serialization ;
6
11
using JsonApiDotNetCore . Services ;
12
+ using Microsoft . Extensions . DependencyInjection ;
7
13
using Moq ;
8
14
using Xunit ;
9
15
@@ -17,19 +23,9 @@ public void Can_Serialize_Complex_Types()
17
23
// arrange
18
24
var contextGraphBuilder = new ContextGraphBuilder ( ) ;
19
25
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 ) ;
30
28
31
- var documentBuilder = new DocumentBuilder ( jsonApiContextMock . Object ) ;
32
- var serializer = new JsonApiSerializer ( jsonApiContextMock . Object , documentBuilder ) ;
33
29
var resource = new TestResource
34
30
{
35
31
ComplexMember = new ComplexType
@@ -43,18 +39,235 @@ public void Can_Serialize_Complex_Types()
43
39
44
40
// assert
45
41
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 ;
47
246
}
48
247
49
248
private class TestResource : Identifiable
50
249
{
51
250
[ Attr ( "complex-member" ) ]
52
251
public ComplexType ComplexMember { get ; set ; }
252
+
253
+ [ HasMany ( "children" ) ] public List < ChildResource > Children { get ; set ; }
53
254
}
54
255
55
256
private class ComplexType
56
257
{
57
258
public string CompoundName { get ; set ; }
58
259
}
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
+ }
59
272
}
60
273
}
0 commit comments