@@ -41,6 +41,190 @@ public UpdatingRelationshipsTests(TestFixture<TestStartup> fixture)
4141
4242 }
4343
44+ [ Fact ]
45+ public async Task Can_Update_Cyclic_ToMany_Relationship_By_Patching_Resource ( )
46+ {
47+ // Arrange
48+ var todoItem = _todoItemFaker . Generate ( ) ;
49+ var strayTodoItem = _todoItemFaker . Generate ( ) ;
50+ _context . TodoItems . Add ( todoItem ) ;
51+ _context . TodoItems . Add ( strayTodoItem ) ;
52+ _context . SaveChanges ( ) ;
53+
54+
55+ var builder = new WebHostBuilder ( )
56+ . UseStartup < Startup > ( ) ;
57+
58+ var server = new TestServer ( builder ) ;
59+ var client = server . CreateClient ( ) ;
60+
61+ // Act
62+ var content = new
63+ {
64+ data = new
65+ {
66+ type = "todo-items" ,
67+ id = todoItem . Id ,
68+ relationships = new Dictionary < string , object >
69+ {
70+ { "children-todos" , new
71+ {
72+ data = new object [ ]
73+ {
74+ new { type = "todo-items" , id = $ "{ todoItem . Id } " } ,
75+ new { type = "todo-items" , id = $ "{ strayTodoItem . Id } " }
76+ }
77+
78+ }
79+ }
80+ }
81+ }
82+ } ;
83+
84+ var httpMethod = new HttpMethod ( "PATCH" ) ;
85+ var route = $ "/api/v1/todo-items/{ todoItem . Id } ";
86+ var request = new HttpRequestMessage ( httpMethod , route ) ;
87+
88+ string serializedContent = JsonConvert . SerializeObject ( content ) ;
89+ request . Content = new StringContent ( serializedContent ) ;
90+ request . Content . Headers . ContentType = new MediaTypeHeaderValue ( "application/vnd.api+json" ) ;
91+
92+
93+ // Act
94+ var response = await client . SendAsync ( request ) ;
95+ var body = await response . Content . ReadAsStringAsync ( ) ;
96+ _context = _fixture . GetService < AppDbContext > ( ) ;
97+
98+ var updatedTodoItem = _context . TodoItems . AsNoTracking ( )
99+ . Where ( ti => ti . Id == todoItem . Id )
100+ . Include ( ti => ti . ChildrenTodoItems ) . First ( ) ;
101+
102+ updatedTodoItem . ChildrenTodoItems . Any ( ( ti ) => ti . Id == todoItem . Id ) ;
103+ Assert . Contains ( updatedTodoItem . ChildrenTodoItems , ( ti ) => ti . Id == todoItem . Id ) ;
104+ }
105+
106+ [ Fact ]
107+ public async Task Can_Update_Cyclic_ToOne_Relationship_By_Patching_Resource ( )
108+ {
109+ // Arrange
110+ var todoItem = _todoItemFaker . Generate ( ) ;
111+ var strayTodoItem = _todoItemFaker . Generate ( ) ;
112+ _context . TodoItems . Add ( todoItem ) ;
113+ _context . SaveChanges ( ) ;
114+
115+
116+ var builder = new WebHostBuilder ( )
117+ . UseStartup < Startup > ( ) ;
118+
119+ var server = new TestServer ( builder ) ;
120+ var client = server . CreateClient ( ) ;
121+
122+ // Act
123+ var content = new
124+ {
125+ data = new
126+ {
127+ type = "todo-items" ,
128+ id = todoItem . Id ,
129+ relationships = new Dictionary < string , object >
130+ {
131+ { "dependent-on-todo" , new
132+ {
133+ data = new { type = "todo-items" , id = $ "{ todoItem . Id } " }
134+ }
135+ }
136+ }
137+ }
138+ } ;
139+
140+ var httpMethod = new HttpMethod ( "PATCH" ) ;
141+ var route = $ "/api/v1/todo-items/{ todoItem . Id } ";
142+ var request = new HttpRequestMessage ( httpMethod , route ) ;
143+
144+ string serializedContent = JsonConvert . SerializeObject ( content ) ;
145+ request . Content = new StringContent ( serializedContent ) ;
146+ request . Content . Headers . ContentType = new MediaTypeHeaderValue ( "application/vnd.api+json" ) ;
147+
148+
149+ // Act
150+ var response = await client . SendAsync ( request ) ;
151+ var body = await response . Content . ReadAsStringAsync ( ) ;
152+ _context = _fixture . GetService < AppDbContext > ( ) ;
153+
154+
155+ var updatedTodoItem = _context . TodoItems . AsNoTracking ( )
156+ . Where ( ti => ti . Id == todoItem . Id )
157+ . Include ( ti => ti . DependentTodoItem ) . First ( ) ;
158+
159+ Assert . Equal ( todoItem . Id , updatedTodoItem . DependentTodoItemId ) ;
160+ }
161+
162+ [ Fact ]
163+ public async Task Can_Update_Both_Cyclic_ToOne_And_ToMany_Relationship_By_Patching_Resource ( )
164+ {
165+ // Arrange
166+ var todoItem = _todoItemFaker . Generate ( ) ;
167+ var strayTodoItem = _todoItemFaker . Generate ( ) ;
168+ _context . TodoItems . Add ( todoItem ) ;
169+ _context . TodoItems . Add ( strayTodoItem ) ;
170+ _context . SaveChanges ( ) ;
171+
172+
173+ var builder = new WebHostBuilder ( )
174+ . UseStartup < Startup > ( ) ;
175+
176+ var server = new TestServer ( builder ) ;
177+ var client = server . CreateClient ( ) ;
178+
179+ // Act
180+ var content = new
181+ {
182+ data = new
183+ {
184+ type = "todo-items" ,
185+ id = todoItem . Id ,
186+ relationships = new Dictionary < string , object >
187+ {
188+ { "dependent-on-todo" , new
189+ {
190+ data = new { type = "todo-items" , id = $ "{ todoItem . Id } " }
191+ }
192+ } ,
193+ { "children-todos" , new
194+ {
195+ data = new object [ ]
196+ {
197+ new { type = "todo-items" , id = $ "{ todoItem . Id } " } ,
198+ new { type = "todo-items" , id = $ "{ strayTodoItem . Id } " }
199+ }
200+ }
201+ }
202+ }
203+ }
204+ } ;
205+
206+ var httpMethod = new HttpMethod ( "PATCH" ) ;
207+ var route = $ "/api/v1/todo-items/{ todoItem . Id } ";
208+ var request = new HttpRequestMessage ( httpMethod , route ) ;
209+
210+ string serializedContent = JsonConvert . SerializeObject ( content ) ;
211+ request . Content = new StringContent ( serializedContent ) ;
212+ request . Content . Headers . ContentType = new MediaTypeHeaderValue ( "application/vnd.api+json" ) ;
213+
214+
215+ // Act
216+ var response = await client . SendAsync ( request ) ;
217+ var body = await response . Content . ReadAsStringAsync ( ) ;
218+ _context = _fixture . GetService < AppDbContext > ( ) ;
219+
220+
221+ var updatedTodoItem = _context . TodoItems . AsNoTracking ( )
222+ . Where ( ti => ti . Id == todoItem . Id )
223+ . Include ( ti => ti . ParentTodoItem ) . First ( ) ;
224+
225+ Assert . Equal ( todoItem . Id , updatedTodoItem . ParentTodoItemId ) ;
226+ }
227+
44228 [ Fact ]
45229 public async Task Can_Update_ToMany_Relationship_By_Patching_Resource ( )
46230 {
0 commit comments