Skip to content

Commit f45972f

Browse files
committed
tests: implicit remove through create tests
1 parent c1d472d commit f45972f

File tree

2 files changed

+121
-6
lines changed

2 files changed

+121
-6
lines changed

src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,10 @@ private void LoadInverseRelationships(object trackedRelationshipValue, Relations
195195
}
196196
}
197197

198-
private bool IsHasOneRelationship(string inverseNavigation, Type type)
198+
199+
private bool IsHasOneRelationship(string internalRelationshipName, Type type)
199200
{
200-
var relationshipAttr = _jsonApiContext.ResourceGraph.GetContextEntity(type).Relationships.Single(r => r.InternalRelationshipName == inverseNavigation);
201+
var relationshipAttr = _jsonApiContext.ResourceGraph.GetContextEntity(type).Relationships.Single(r => r.InternalRelationshipName == internalRelationshipName);
201202
if (relationshipAttr is HasOneAttribute) return true;
202203
return false;
203204
}
@@ -455,7 +456,7 @@ protected void LoadCurrentRelationships(TEntity oldEntity, RelationshipAttribute
455456
/// retrieve from the context WHICH relationships to update, but the actual
456457
/// values should not come from the context.
457458
/// </summary>
458-
protected void AssignRelationshipValue(TEntity oldEntity, object relationshipValue, RelationshipAttribute relationshipAttribute)
459+
private void AssignRelationshipValue(TEntity oldEntity, object relationshipValue, RelationshipAttribute relationshipAttribute)
459460
{
460461
if (relationshipAttribute is HasManyThroughAttribute throughAttribute)
461462
{
@@ -493,7 +494,7 @@ private void AssignHasManyThrough(TEntity entity, HasManyThroughAttribute hasMan
493494
/// A helper method that gets the relationship value in the case of
494495
/// entity resource separation.
495496
/// </summary>
496-
IIdentifiable GetEntityResourceSeparationValue(TEntity entity, HasOneAttribute attribute)
497+
private IIdentifiable GetEntityResourceSeparationValue(TEntity entity, HasOneAttribute attribute)
497498
{
498499
if (attribute.EntityPropertyName == null)
499500
{
@@ -506,7 +507,7 @@ IIdentifiable GetEntityResourceSeparationValue(TEntity entity, HasOneAttribute a
506507
/// A helper method that gets the relationship value in the case of
507508
/// entity resource separation.
508509
/// </summary>
509-
IEnumerable<IIdentifiable> GetEntityResourceSeparationValue(TEntity entity, HasManyAttribute attribute)
510+
private IEnumerable<IIdentifiable> GetEntityResourceSeparationValue(TEntity entity, HasManyAttribute attribute)
510511
{
511512
if (attribute.EntityPropertyName == null)
512513
{
@@ -522,7 +523,7 @@ IEnumerable<IIdentifiable> GetEntityResourceSeparationValue(TEntity entity, HasM
522523
///
523524
/// useful article: https://stackoverflow.com/questions/30987806/dbset-attachentity-vs-dbcontext-entryentity-state-entitystate-modified
524525
/// </summary>
525-
IIdentifiable AttachOrGetTracked(IIdentifiable relationshipValue)
526+
private IIdentifiable AttachOrGetTracked(IIdentifiable relationshipValue)
526527
{
527528
var trackedEntity = _context.GetTrackedEntity(relationshipValue);
528529

test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using Microsoft.EntityFrameworkCore;
1818
using Newtonsoft.Json;
1919
using Xunit;
20+
using Person = JsonApiDotNetCoreExample.Models.Person;
2021

2122
namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
2223
{
@@ -26,6 +27,7 @@ public class CreatingDataTests
2627
private TestFixture<TestStartup> _fixture;
2728
private IJsonApiContext _jsonApiContext;
2829
private Faker<TodoItem> _todoItemFaker;
30+
private Faker<Person> _personFaker;
2931

3032
public CreatingDataTests(TestFixture<TestStartup> fixture)
3133
{
@@ -35,6 +37,10 @@ public CreatingDataTests(TestFixture<TestStartup> fixture)
3537
.RuleFor(t => t.Description, f => f.Lorem.Sentence())
3638
.RuleFor(t => t.Ordinal, f => f.Random.Number())
3739
.RuleFor(t => t.CreatedDate, f => f.Date.Past());
40+
_personFaker = new Faker<Person>()
41+
.RuleFor(t => t.FirstName, f => f.Name.FirstName())
42+
.RuleFor(t => t.LastName, f => f.Name.LastName());
43+
3844
}
3945

4046
[Fact]
@@ -586,5 +592,113 @@ public async Task Respond_409_ToIncorrectEntityType()
586592
// assert
587593
Assert.Equal(HttpStatusCode.Conflict, response.StatusCode);
588594
}
595+
596+
[Fact]
597+
public async Task Create_With_ToOne_Relationship_With_Implicit_Remove()
598+
{
599+
// Arrange
600+
var context = _fixture.GetService<AppDbContext>();
601+
var passport = new Passport();
602+
var person1 = _personFaker.Generate();
603+
person1.Passport = passport;
604+
context.People.AddRange(new List<Person>() { person1 });
605+
await context.SaveChangesAsync();
606+
var passportId = person1.PassportId;
607+
var content = new
608+
{
609+
data = new
610+
{
611+
type = "people",
612+
attributes = new Dictionary<string, string>() { { "first-name", "Joe" } },
613+
relationships = new Dictionary<string, object>
614+
{
615+
{ "passport", new
616+
{
617+
data = new { type = "passports", id = $"{passportId}" }
618+
}
619+
}
620+
}
621+
}
622+
};
623+
624+
var httpMethod = new HttpMethod("POST");
625+
var route = $"/api/v1/people";
626+
var request = new HttpRequestMessage(httpMethod, route);
627+
628+
string serializedContent = JsonConvert.SerializeObject(content);
629+
request.Content = new StringContent(serializedContent);
630+
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
631+
632+
// Act
633+
var response = await _fixture.Client.SendAsync(request);
634+
var body = await response.Content.ReadAsStringAsync();
635+
var personResult = _fixture.GetService<IJsonApiDeSerializer>().Deserialize<Person>(body);
636+
637+
// Assert
638+
639+
Assert.True(HttpStatusCode.Created == response.StatusCode, $"{route} returned {response.StatusCode} status code with payload: {body}");
640+
var dbPerson = context.People.AsNoTracking().Where(p => p.Id == personResult.Id).Include("Passport").FirstOrDefault();
641+
Assert.Equal(passportId, dbPerson.Passport.Id);
642+
}
643+
644+
[Fact]
645+
public async Task Create_With_ToMany_Relationship_With_Implicit_Remove()
646+
{
647+
// Arrange
648+
var context = _fixture.GetService<AppDbContext>();
649+
var person1 = _personFaker.Generate();
650+
person1.TodoItems = _todoItemFaker.Generate(3).ToList();
651+
context.People.AddRange(new List<Person>() { person1 });
652+
await context.SaveChangesAsync();
653+
var todoItem1Id = person1.TodoItems[0].Id;
654+
var todoItem2Id = person1.TodoItems[1].Id;
655+
656+
var content = new
657+
{
658+
data = new
659+
{
660+
type = "people",
661+
attributes = new Dictionary<string, string>() { { "first-name", "Joe" } },
662+
relationships = new Dictionary<string, object>
663+
{
664+
{ "todo-items", new
665+
{
666+
data = new List<object>
667+
{
668+
new {
669+
type = "todo-items",
670+
id = $"{todoItem1Id}"
671+
},
672+
new {
673+
type = "todo-items",
674+
id = $"{todoItem2Id}"
675+
}
676+
}
677+
}
678+
}
679+
}
680+
}
681+
};
682+
683+
var httpMethod = new HttpMethod("POST");
684+
var route = $"/api/v1/people";
685+
var request = new HttpRequestMessage(httpMethod, route);
686+
687+
string serializedContent = JsonConvert.SerializeObject(content);
688+
request.Content = new StringContent(serializedContent);
689+
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
690+
691+
// Act
692+
var response = await _fixture.Client.SendAsync(request);
693+
var body = await response.Content.ReadAsStringAsync();
694+
var personResult = _fixture.GetService<IJsonApiDeSerializer>().Deserialize<Person>(body);
695+
696+
// Assert
697+
Assert.True(HttpStatusCode.Created == response.StatusCode, $"{route} returned {response.StatusCode} status code with payload: {body}");
698+
var dbPerson = context.People.AsNoTracking().Where(p => p.Id == personResult.Id).Include("TodoItems").FirstOrDefault();
699+
Assert.Equal(2, dbPerson.TodoItems.Count);
700+
Assert.NotNull(dbPerson.TodoItems.SingleOrDefault(ti => ti.Id == todoItem1Id));
701+
Assert.NotNull(dbPerson.TodoItems.SingleOrDefault(ti => ti.Id == todoItem2Id));
702+
}
589703
}
590704
}

0 commit comments

Comments
 (0)