Skip to content

Commit

Permalink
Empty resource list (#1)
Browse files Browse the repository at this point in the history
* engine is able to respond with empty resource collection

* unit test for resource list
  • Loading branch information
kirsar committed Nov 27, 2018
1 parent 1ba66f7 commit 1acdc0f
Show file tree
Hide file tree
Showing 8 changed files with 279 additions and 103 deletions.
83 changes: 69 additions & 14 deletions WebApi.Hal.Tests/HalResourceMixedContentTest.cs
Expand Up @@ -26,13 +26,13 @@ public HalResourceMixedContentTest()
{
resource = new OrganisationWithPeopleDetailRepresentation(1, "Org Name")
{
Boss = new Boss(2, "Eunice PHB", 1, true)
};
resource.People = new List<Person>
{
new Person(3, "Dilbert", 1),
new Person(4, "Wally", 1),
new Person(5, "Alice", 1)
Boss = new Boss(2, "Eunice PHB", 1, true),
People = new List<Person>
{
new Person(3, "Dilbert", 1),
new Person(4, "Wally", 1),
new Person(5, "Alice", 1)
}
};
}

Expand All @@ -55,6 +55,61 @@ public void peopledetail_get_json_test()
}
}

[Fact]
public void peopledetail_non_empty_resource_list_get_json_test()
{
// arrange
var resourceWithResourceList = new OrganisationWithPeopleDetailRepresentation(1, "Org Name")
{
Boss = new Boss(2, "Eunice PHB", 1, true),
People = new ResourceList<Person>("person")
{
new Person(3, "Dilbert", 1),
new Person(4, "Wally", 1),
new Person(5, "Alice", 1)
}
};

var mediaFormatter = new JsonHalMediaTypeOutputFormatter(
new JsonSerializerSettings { Formatting = Formatting.Indented }, ArrayPool<char>.Shared);

// act
using (var stream = new StringWriter())
{
mediaFormatter.WriteObject(stream, resourceWithResourceList);

var serializedResult = stream.ToString();

// assert
this.Assent(serializedResult);
}
}

[Fact]
public void peopledetail_empty_resource_list_get_json_test()
{
// arrange
var emptyResource = new OrganisationWithPeopleDetailRepresentation(1, "Org Name")
{
Boss = new Boss(2, "Eunice PHB", 1, true),
People = new ResourceList<Person>("person")
};

var mediaFormatter = new JsonHalMediaTypeOutputFormatter(
new JsonSerializerSettings { Formatting = Formatting.Indented }, ArrayPool<char>.Shared);

// act
using (var stream = new StringWriter())
{
mediaFormatter.WriteObject(stream, emptyResource);

var serializedResult = stream.ToString();

// assert
this.Assent(serializedResult);
}
}

[Fact]
public void peopledetail_get_xml_test()
{
Expand Down Expand Up @@ -102,7 +157,7 @@ public async Task peopledetail_post_json_props_test()
var obj = await mediaFormatter.ReadAsync(new Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext(
context,
type.ToString(),
new Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary(),
new ModelStateDictionary(),
CreateDefaultProvider().GetMetadataForType(type),
(s, encoding) => new StreamReader(s, encoding)
));
Expand Down Expand Up @@ -154,7 +209,7 @@ public async Task peopledetail_post_json_links_test()
var obj = await mediaFormatter.ReadAsync(new Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext(
context,
type.ToString(),
new Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary(),
new ModelStateDictionary(),
CreateDefaultProvider().GetMetadataForType(type),
(s, encoding) => new StreamReader(s, encoding)
));
Expand Down Expand Up @@ -214,7 +269,7 @@ public async Task peopledetail_post_json_embedded_singles_test()
var obj = await mediaFormatter.ReadAsync(new Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext(
context,
type.ToString(),
new Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary(),
new ModelStateDictionary(),
CreateDefaultProvider().GetMetadataForType(type),
(s, encoding) => new StreamReader(s, encoding)
));
Expand All @@ -224,7 +279,7 @@ public async Task peopledetail_post_json_embedded_singles_test()
var org = obj.Model as OrganisationWithPeopleDetailRepresentation;
Assert.NotNull(org);
Assert.NotNull(org.Boss);
Assert.Equal(1, org.People.Count);
Assert.Single(org.People);
Assert.Equal(1, org.Boss.Links.Count);
}
}
Expand Down Expand Up @@ -269,7 +324,7 @@ public async Task peopledetail_post_json_embedded_arrays_test()
var obj = await mediaFormatter.ReadAsync(new Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext(
context,
type.ToString(),
new Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary(),
new ModelStateDictionary(),
CreateDefaultProvider().GetMetadataForType(type),
(s, encoding) => new StreamReader(s, encoding)
));
Expand Down Expand Up @@ -314,7 +369,7 @@ public async Task peopledetail_post_json_embedded_null_test()
var obj = await mediaFormatter.ReadAsync(new Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext(
context,
type.ToString(),
new Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary(),
new ModelStateDictionary(),
CreateDefaultProvider().GetMetadataForType(type),
(s, encoding) => new StreamReader(s, encoding)
));
Expand Down Expand Up @@ -373,7 +428,7 @@ public async Task simplelist_post_json_test()
var obj = await mediaFormatter.ReadAsync(new Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext(
context,
type.ToString(),
new Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary(),
new ModelStateDictionary(),
CreateDefaultProvider().GetMetadataForType(type),
(s, encoding) => new StreamReader(s, encoding)
));
Expand Down
@@ -0,0 +1,29 @@
{
"Id": 1,
"Name": "Org Name",
"_links": {
"self": {
"href": "/api/organisations/1"
},
"people": {
"href": "/api/organisations/1/people"
},
"boss": {
"href": "/api/organisations/1/boss"
}
},
"_embedded": {
"person": [],
"boss": {
"HasPointyHair": true,
"Id": 2,
"Name": "Eunice PHB",
"OrganisationId": 1,
"_links": {
"self": {
"href": "/api/organisations/1/boss"
}
}
}
}
}
@@ -0,0 +1,71 @@
{
"Id": 1,
"Name": "Org Name",
"_links": {
"self": {
"href": "/api/organisations/1"
},
"people": {
"href": "/api/organisations/1/people"
},
"person": [
{
"href": "/api/organisations/1/people/3"
},
{
"href": "/api/organisations/1/people/4"
},
{
"href": "/api/organisations/1/people/5"
}
],
"boss": {
"href": "/api/organisations/1/boss"
}
},
"_embedded": {
"person": [
{
"Id": 3,
"Name": "Dilbert",
"OrganisationId": 1,
"_links": {
"self": {
"href": "/api/organisations/1/people/3"
}
}
},
{
"Id": 4,
"Name": "Wally",
"OrganisationId": 1,
"_links": {
"self": {
"href": "/api/organisations/1/people/4"
}
}
},
{
"Id": 5,
"Name": "Alice",
"OrganisationId": 1,
"_links": {
"self": {
"href": "/api/organisations/1/people/5"
}
}
}
],
"boss": {
"HasPointyHair": true,
"Id": 2,
"Name": "Eunice PHB",
"OrganisationId": 1,
"_links": {
"self": {
"href": "/api/organisations/1/boss"
}
}
}
}
}
1 change: 1 addition & 0 deletions WebApi.Hal/EmbeddedResource.cs
Expand Up @@ -7,5 +7,6 @@ internal class EmbeddedResource
{
public bool IsSourceAnArray { get; set; }
public IList<IResource> Resources { get; private set; } = new List<IResource>();
public string RelationName { get; set; }
}
}
9 changes: 9 additions & 0 deletions WebApi.Hal/IResourceList.cs
@@ -0,0 +1,9 @@
using System.Collections;

namespace WebApi.Hal
{
public interface IResourceList : IEnumerable
{
string RelationName { get; }
}
}
17 changes: 7 additions & 10 deletions WebApi.Hal/JsonConverters/EmbeddedResourceConverter.cs
@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using Newtonsoft.Json;
using WebApi.Hal.Interfaces;

namespace WebApi.Hal.JsonConverters
{
Expand All @@ -11,13 +10,12 @@ public class EmbeddedResourceConverter : JsonConverter
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var resourceList = (IList<EmbeddedResource>)value;
if (resourceList.Count == 0) return;


writer.WriteStartObject();

foreach (var rel in resourceList)
{
writer.WritePropertyName(NormalizeRel(rel.Resources[0]));
writer.WritePropertyName(NormalizeRel(rel));
if (rel.IsSourceAnArray)
writer.WriteStartArray();
foreach (var res in rel.Resources)
Expand All @@ -28,11 +26,10 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
writer.WriteEndObject();
}

private static string NormalizeRel(IResource res)
{
if (!string.IsNullOrEmpty(res.Rel)) return res.Rel;
return "unknownRel-" + res.GetType().Name;
}
private static string NormalizeRel(EmbeddedResource relation) =>
!string.IsNullOrEmpty(relation.RelationName)
? relation.RelationName
: $"unknownRel-{relation.Resources.FirstOrDefault()?.GetType().Name ?? string.Empty}";

public override bool CanRead => false;

Expand Down

0 comments on commit 1acdc0f

Please sign in to comment.