From af3c656f4992af931c7eef5f27d8d61d50d09a1c Mon Sep 17 00:00:00 2001 From: Sergey Litvinov Date: Mon, 24 Sep 2018 19:45:00 +0300 Subject: [PATCH 1/2] added LinkType.Top enum, so we can specify only top level links --- Saule/LinkType.cs | 5 +++++ Saule/Serialization/ResourceSerializer.cs | 5 ++++- Tests/Models/PersonOnlyTopLinksResource.cs | 23 +++++++++++++++++++++ Tests/Serialization/UrlConstructionTests.cs | 15 ++++++++++++++ Tests/Tests.csproj | 1 + 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 Tests/Models/PersonOnlyTopLinksResource.cs diff --git a/Saule/LinkType.cs b/Saule/LinkType.cs index 2851253..2c5d6a4 100644 --- a/Saule/LinkType.cs +++ b/Saule/LinkType.cs @@ -23,6 +23,11 @@ public enum LinkType /// Related = 2, + /// + /// Only top section links + /// + Top = 4, + /// /// Generate all possible links /// diff --git a/Saule/Serialization/ResourceSerializer.cs b/Saule/Serialization/ResourceSerializer.cs index 51086ad..36b2b88 100644 --- a/Saule/Serialization/ResourceSerializer.cs +++ b/Saule/Serialization/ResourceSerializer.cs @@ -130,7 +130,10 @@ private JToken CreateTopLevelLinks(int count) { var result = new JObject(); - if (_resource.LinkType.HasFlag(LinkType.Self)) + // if resource has Top only and not Self, then we render it. + // otherwise to preserve back compatibility if Self is enabled, then we also render it + if ((_resource.LinkType.HasFlag(LinkType.Top) && !_resource.LinkType.HasFlag(LinkType.Self)) + || _resource.LinkType.HasFlag(LinkType.Self)) { result.Add("self", _baseUrl); } diff --git a/Tests/Models/PersonOnlyTopLinksResource.cs b/Tests/Models/PersonOnlyTopLinksResource.cs new file mode 100644 index 0000000..3ba8ede --- /dev/null +++ b/Tests/Models/PersonOnlyTopLinksResource.cs @@ -0,0 +1,23 @@ +using Saule; + +namespace Tests.Models +{ + public class PersonOnlyTopLinksResource : ApiResource + { + public PersonOnlyTopLinksResource() + { + WithId(nameof(Person.Identifier)); + WithLinks(LinkType.Top); + + Attribute(nameof(Person.FirstName)); + Attribute(nameof(Person.LastName)); + Attribute(nameof(Person.Age)); + Attribute(nameof(Person.Address)); + + BelongsTo(nameof(Person.Job), "/employer"); + BelongsTo(nameof(Person.Car)); + HasMany(nameof(Person.Friends)); + HasMany( nameof( Person.FamilyMembers)); + } + } +} \ No newline at end of file diff --git a/Tests/Serialization/UrlConstructionTests.cs b/Tests/Serialization/UrlConstructionTests.cs index 87f4ce8..8e23b54 100644 --- a/Tests/Serialization/UrlConstructionTests.cs +++ b/Tests/Serialization/UrlConstructionTests.cs @@ -85,6 +85,21 @@ public void SelfLink() Assert.Equal("/api/people/123", selfLink); } + [Fact(DisplayName = "Adds top level self link if only LinkType.Top is specified")] + public void TopLinkOnlyLink() + { + var target = new ResourceSerializer(Get.Person(), new PersonOnlyTopLinksResource(), + GetUri("123"), DefaultPathBuilder, null, null, null); + var result = target.Serialize(); + _output.WriteLine(result.ToString()); + + var selfLink = result["links"].Value("self").AbsolutePath; + + Assert.Equal("/api/people/123", selfLink); + + Assert.Null(result["data"]["links"]); + } + [Fact(DisplayName = "Omits top level links if so requested")] public void NoTopLevelLinks() { diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 299b067..06b608f 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -140,6 +140,7 @@ + From b8943f8d09f2de0668f95b9070543107ec7ab6f5 Mon Sep 17 00:00:00 2001 From: Sergey Litvinov Date: Tue, 25 Sep 2018 17:52:54 +0300 Subject: [PATCH 2/2] Renamed LinkType.Top to LinkType.TopSelf --- Saule/LinkType.cs | 4 ++-- Saule/Serialization/ResourceSerializer.cs | 6 ++---- Tests/Models/PersonOnlyTopLinksResource.cs | 2 +- Tests/Serialization/UrlConstructionTests.cs | 6 +++--- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Saule/LinkType.cs b/Saule/LinkType.cs index 2c5d6a4..a950de6 100644 --- a/Saule/LinkType.cs +++ b/Saule/LinkType.cs @@ -24,9 +24,9 @@ public enum LinkType Related = 2, /// - /// Only top section links + /// Only self links in the top section /// - Top = 4, + TopSelf = 4, /// /// Generate all possible links diff --git a/Saule/Serialization/ResourceSerializer.cs b/Saule/Serialization/ResourceSerializer.cs index 36b2b88..7dabe26 100644 --- a/Saule/Serialization/ResourceSerializer.cs +++ b/Saule/Serialization/ResourceSerializer.cs @@ -130,10 +130,8 @@ private JToken CreateTopLevelLinks(int count) { var result = new JObject(); - // if resource has Top only and not Self, then we render it. - // otherwise to preserve back compatibility if Self is enabled, then we also render it - if ((_resource.LinkType.HasFlag(LinkType.Top) && !_resource.LinkType.HasFlag(LinkType.Self)) - || _resource.LinkType.HasFlag(LinkType.Self)) + // to preserve back compatibility if Self is enabled, then we also render it. Or if TopSelf is enabled + if (_resource.LinkType.HasFlag(LinkType.TopSelf) || _resource.LinkType.HasFlag(LinkType.Self)) { result.Add("self", _baseUrl); } diff --git a/Tests/Models/PersonOnlyTopLinksResource.cs b/Tests/Models/PersonOnlyTopLinksResource.cs index 3ba8ede..6ea7cd7 100644 --- a/Tests/Models/PersonOnlyTopLinksResource.cs +++ b/Tests/Models/PersonOnlyTopLinksResource.cs @@ -7,7 +7,7 @@ public class PersonOnlyTopLinksResource : ApiResource public PersonOnlyTopLinksResource() { WithId(nameof(Person.Identifier)); - WithLinks(LinkType.Top); + WithLinks(LinkType.TopSelf); Attribute(nameof(Person.FirstName)); Attribute(nameof(Person.LastName)); diff --git a/Tests/Serialization/UrlConstructionTests.cs b/Tests/Serialization/UrlConstructionTests.cs index 8e23b54..ee01c40 100644 --- a/Tests/Serialization/UrlConstructionTests.cs +++ b/Tests/Serialization/UrlConstructionTests.cs @@ -85,10 +85,10 @@ public void SelfLink() Assert.Equal("/api/people/123", selfLink); } - [Fact(DisplayName = "Adds top level self link if only LinkType.Top is specified")] + [Fact(DisplayName = "Adds top level self link if only LinkType.TopSelf is specified")] public void TopLinkOnlyLink() { - var target = new ResourceSerializer(Get.Person(), new PersonOnlyTopLinksResource(), + var target = new ResourceSerializer(Get.People(1), new PersonOnlyTopLinksResource(), GetUri("123"), DefaultPathBuilder, null, null, null); var result = target.Serialize(); _output.WriteLine(result.ToString()); @@ -97,7 +97,7 @@ public void TopLinkOnlyLink() Assert.Equal("/api/people/123", selfLink); - Assert.Null(result["data"]["links"]); + Assert.Null(result["data"][0]["links"]); } [Fact(DisplayName = "Omits top level links if so requested")]