Skip to content

Commit a8031c6

Browse files
authored
Merge pull request #389 from NullVoxPopuli/feature/#39-implementation
Feature/#39 - Acceptance Tests
2 parents 8847403 + daa61ab commit a8031c6

File tree

2 files changed

+289
-0
lines changed

2 files changed

+289
-0
lines changed

Diff for: test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeeplyNestedInclusionTests.cs

+259
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
using System.Collections.Generic;
12
using System.Net;
23
using System.Net.Http;
34
using System.Threading.Tasks;
45
using Bogus;
6+
using JsonApiDotNetCore.Models;
57
using JsonApiDotNetCoreExample;
68
using JsonApiDotNetCoreExample.Data;
79
using JsonApiDotNetCoreExample.Models;
10+
using JsonApiDotNetCoreExampleTests.Helpers.Extensions;
811
using Microsoft.AspNetCore.Hosting;
912
using Newtonsoft.Json;
1013
using Xunit;
@@ -22,6 +25,14 @@ public DeeplyNestedInclusionTests(TestFixture<TestStartup> fixture)
2225
_fixture = fixture;
2326
}
2427

28+
private void ResetContext(AppDbContext context)
29+
{
30+
context.TodoItems.RemoveRange(context.TodoItems);
31+
context.TodoItemCollections.RemoveRange(context.TodoItemCollections);
32+
context.People.RemoveRange(context.People);
33+
context.PersonRoles.RemoveRange(context.PersonRoles);
34+
}
35+
2536
[Fact]
2637
public async Task Can_Include_Nested_Relationships()
2738
{
@@ -53,5 +64,253 @@ public async Task Can_Include_Nested_Relationships()
5364
Assert.NotNull(responseTodoItem.Collection);
5465
Assert.NotNull(responseTodoItem.Collection.Owner);
5566
}
67+
68+
[Fact]
69+
public async Task Can_Include_Nested_HasMany_Relationships()
70+
{
71+
// arrange
72+
const string route = "/api/v1/todo-items?include=collection.todo-items";
73+
74+
var todoItem = new TodoItem {
75+
Collection = new TodoItemCollection {
76+
Owner = new Person(),
77+
TodoItems = new List<TodoItem> {
78+
new TodoItem(),
79+
new TodoItem()
80+
}
81+
}
82+
};
83+
84+
85+
var context = _fixture.GetService<AppDbContext>();
86+
ResetContext(context);
87+
88+
context.TodoItems.Add(todoItem);
89+
await context.SaveChangesAsync();
90+
91+
// act
92+
var response = await _fixture.Client.GetAsync(route);
93+
94+
// assert
95+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
96+
97+
var body = await response.Content.ReadAsStringAsync();
98+
var documents = JsonConvert.DeserializeObject<Documents>(body);
99+
var included = documents.Included;
100+
101+
Assert.Equal(4, included.Count);
102+
103+
Assert.Equal(3, included.CountOfType("todo-items"));
104+
Assert.Equal(1, included.CountOfType("todo-collections"));
105+
}
106+
107+
[Fact]
108+
public async Task Can_Include_Nested_HasMany_Relationships_BelongsTo()
109+
{
110+
// arrange
111+
const string route = "/api/v1/todo-items?include=collection.todo-items.owner";
112+
113+
var todoItem = new TodoItem {
114+
Collection = new TodoItemCollection {
115+
Owner = new Person(),
116+
TodoItems = new List<TodoItem> {
117+
new TodoItem {
118+
Owner = new Person()
119+
},
120+
new TodoItem()
121+
}
122+
}
123+
};
124+
125+
var context = _fixture.GetService<AppDbContext>();
126+
ResetContext(context);
127+
128+
context.TodoItems.Add(todoItem);
129+
await context.SaveChangesAsync();
130+
131+
// act
132+
var response = await _fixture.Client.GetAsync(route);
133+
134+
// assert
135+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
136+
137+
var body = await response.Content.ReadAsStringAsync();
138+
var documents = JsonConvert.DeserializeObject<Documents>(body);
139+
var included = documents.Included;
140+
141+
Assert.Equal(5, included.Count);
142+
143+
Assert.Equal(3, included.CountOfType("todo-items"));
144+
Assert.Equal(1, included.CountOfType("people"));
145+
Assert.Equal(1, included.CountOfType("todo-collections"));
146+
}
147+
148+
[Fact]
149+
public async Task Can_Include_Nested_Relationships_With_Multiple_Paths()
150+
{
151+
// arrange
152+
const string route = "/api/v1/todo-items?include=collection.owner.role,collection.todo-items.owner";
153+
154+
var todoItem = new TodoItem {
155+
Collection = new TodoItemCollection {
156+
Owner = new Person {
157+
Role = new PersonRole()
158+
},
159+
TodoItems = new List<TodoItem> {
160+
new TodoItem {
161+
Owner = new Person()
162+
},
163+
new TodoItem()
164+
}
165+
}
166+
};
167+
168+
var context = _fixture.GetService<AppDbContext>();
169+
ResetContext(context);
170+
171+
context.TodoItems.Add(todoItem);
172+
await context.SaveChangesAsync();
173+
174+
// act
175+
var response = await _fixture.Client.GetAsync(route);
176+
177+
// assert
178+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
179+
180+
var body = await response.Content.ReadAsStringAsync();
181+
var documents = JsonConvert.DeserializeObject<Documents>(body);
182+
var included = documents.Included;
183+
184+
Assert.Equal(7, included.Count);
185+
186+
Assert.Equal(3, included.CountOfType("todo-items"));
187+
Assert.Equal(2, included.CountOfType("people"));
188+
Assert.Equal(1, included.CountOfType("person-roles"));
189+
Assert.Equal(1, included.CountOfType("todo-collections"));
190+
}
191+
192+
[Fact]
193+
public async Task Included_Resources_Are_Correct()
194+
{
195+
// arrange
196+
var role = new PersonRole();
197+
var assignee = new Person { Role = role };
198+
var collectionOwner = new Person();
199+
var someOtherOwner = new Person();
200+
var collection = new TodoItemCollection { Owner = collectionOwner };
201+
var todoItem1 = new TodoItem { Collection = collection, Assignee = assignee };
202+
var todoItem2 = new TodoItem { Collection = collection, Assignee = assignee };
203+
var todoItem3 = new TodoItem { Collection = collection, Owner = someOtherOwner };
204+
var todoItem4 = new TodoItem { Collection = collection, Owner = assignee };
205+
206+
var context = _fixture.GetService<AppDbContext>();
207+
ResetContext(context);
208+
209+
context.TodoItems.Add(todoItem1);
210+
context.TodoItems.Add(todoItem2);
211+
context.TodoItems.Add(todoItem3);
212+
context.TodoItems.Add(todoItem4);
213+
context.PersonRoles.Add(role);
214+
context.People.Add(assignee);
215+
context.People.Add(collectionOwner);
216+
context.People.Add(someOtherOwner);
217+
context.TodoItemCollections.Add(collection);
218+
219+
220+
await context.SaveChangesAsync();
221+
222+
string route =
223+
"/api/v1/todo-items/" + todoItem1.Id + "?include=" +
224+
"collection.owner," +
225+
"assignee.role," +
226+
"assignee.assigned-todo-items";
227+
228+
// act
229+
var response = await _fixture.Client.GetAsync(route);
230+
231+
// assert
232+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
233+
234+
var body = await response.Content.ReadAsStringAsync();
235+
var documents = JsonConvert.DeserializeObject<Document>(body);
236+
var included = documents.Included;
237+
238+
// 1 collection, 1 owner,
239+
// 1 assignee, 1 assignee role,
240+
// 2 assigned todo items (including the primary resource)
241+
Assert.Equal(6, included.Count);
242+
243+
var collectionDocument = included.FindResource("todo-collections", collection.Id);
244+
var ownerDocument = included.FindResource("people", collectionOwner.Id);
245+
var assigneeDocument = included.FindResource("people", assignee.Id);
246+
var roleDocument = included.FindResource("person-roles", role.Id);
247+
var assignedTodo1 = included.FindResource("todo-items", todoItem1.Id);
248+
var assignedTodo2 = included.FindResource("todo-items", todoItem2.Id);
249+
250+
Assert.NotNull(assignedTodo1);
251+
Assert.Equal(todoItem1.Id.ToString(), assignedTodo1.Id);
252+
253+
Assert.NotNull(assignedTodo2);
254+
Assert.Equal(todoItem2.Id.ToString(), assignedTodo2.Id);
255+
256+
Assert.NotNull(collectionDocument);
257+
Assert.Equal(collection.Id.ToString(), collectionDocument.Id);
258+
259+
Assert.NotNull(ownerDocument);
260+
Assert.Equal(collectionOwner.Id.ToString(), ownerDocument.Id);
261+
262+
Assert.NotNull(assigneeDocument);
263+
Assert.Equal(assignee.Id.ToString(), assigneeDocument.Id);
264+
265+
Assert.NotNull(roleDocument);
266+
Assert.Equal(role.Id.ToString(), roleDocument.Id);
267+
}
268+
269+
[Fact]
270+
public async Task Can_Include_Doubly_HasMany_Relationships()
271+
{
272+
// arrange
273+
var person = new Person {
274+
TodoItemCollections = new List<TodoItemCollection> {
275+
new TodoItemCollection {
276+
TodoItems = new List<TodoItem> {
277+
new TodoItem(),
278+
new TodoItem()
279+
}
280+
},
281+
new TodoItemCollection {
282+
TodoItems = new List<TodoItem> {
283+
new TodoItem(),
284+
new TodoItem(),
285+
new TodoItem()
286+
}
287+
}
288+
}
289+
};
290+
291+
var context = _fixture.GetService<AppDbContext>();
292+
ResetContext(context);
293+
294+
context.People.Add(person);
295+
296+
await context.SaveChangesAsync();
297+
298+
string route = "/api/v1/people/" + person.Id + "?include=todo-collections.todo-items";
299+
300+
// act
301+
var response = await _fixture.Client.GetAsync(route);
302+
303+
// assert
304+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
305+
306+
var body = await response.Content.ReadAsStringAsync();
307+
var documents = JsonConvert.DeserializeObject<Document>(body);
308+
var included = documents.Included;
309+
310+
Assert.Equal(7, included.Count);
311+
312+
Assert.Equal(5, included.CountOfType("todo-items"));
313+
Assert.Equal(2, included.CountOfType("todo-collections"));
314+
}
56315
}
57316
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using JsonApiDotNetCore.Models;
6+
using Microsoft.EntityFrameworkCore.Internal;
7+
using Microsoft.EntityFrameworkCore.Query;
8+
using Microsoft.EntityFrameworkCore.Query.Internal;
9+
using Microsoft.EntityFrameworkCore.Storage;
10+
using Database = Microsoft.EntityFrameworkCore.Storage.Database;
11+
12+
namespace JsonApiDotNetCoreExampleTests.Helpers.Extensions
13+
{
14+
public static class DocumentExtensions
15+
{
16+
public static DocumentData FindResource<TId>(this List<DocumentData> included, string type, TId id)
17+
{
18+
var document = included.Where(documentData => (
19+
documentData.Type == type
20+
&& documentData.Id == id.ToString()
21+
)).FirstOrDefault();
22+
23+
return document;
24+
}
25+
26+
public static int CountOfType(this List<DocumentData> included, string type) {
27+
return included.Where(documentData => documentData.Type == type).Count();
28+
}
29+
}
30+
}

0 commit comments

Comments
 (0)