Skip to content

Commit 8d93ee9

Browse files
committed
Adds tests for validating attribute visibility on schema generation based on relationship capabilities (#1056)
1 parent 41340c2 commit 8d93ee9

7 files changed

Lines changed: 120 additions & 6 deletions

File tree

test/OpenApiTests/AttributeTypes/AttributeCapabilitiesTests.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
using TestBuildingBlocks;
44
using Xunit;
55
using Xunit.Abstractions;
6+
using RequestType = OpenApiTests.AttributeTypes.CapabilitiesUtils.RequestType;
67

78
namespace OpenApiTests.AttributeTypes;
89

910
public sealed class AttributeCapabilitiesTests : IClassFixture<OpenApiTestContext<AttributeTypesStartup, AttributeTypesDbContext>>
1011
{
11-
private enum RequestType{ Response, Create, Update }
12-
1312
private static readonly Dictionary<RequestType, AttrCapabilities> CapabilitiesByRequestType = new()
1413
{
1514
{ RequestType.Response, AttrCapabilities.AllowView },
@@ -26,10 +25,21 @@ private enum RequestType{ Response, Create, Update }
2625

2726
private static readonly Dictionary<AttrCapabilities, List<string>> BookModelAttrsByCapability = new()
2827
{
29-
{ AttrCapabilities.AllowView, ["title", "isbn", "publishedOn"] },
30-
{ AttrCapabilities.AllowChange, ["title", "internalNotes"] },
28+
{
29+
AttrCapabilities.AllowView, [
30+
"title",
31+
"isbn",
32+
"publishedOn"
33+
]
34+
},
35+
{
36+
AttrCapabilities.AllowChange, [
37+
"title",
38+
"internalNotes"
39+
]
40+
},
3141
{ AttrCapabilities.AllowCreate, ["draftContent"] },
32-
{ AttrCapabilities.None, ["secretCode"] }
42+
{ AttrCapabilities.None, ["secretCode"] }
3343
};
3444

3545
private readonly OpenApiTestContext<AttributeTypesStartup, AttributeTypesDbContext> _testContext;
@@ -55,6 +65,7 @@ private async Task Generated_Schema_Includes_Only_Expected_Attrs_For_Request_Typ
5565
JsonElement attrs = document.Should().ContainPath(path);
5666

5767
IList<string> bookExpectedAttrs = BookModelAttrsByCapability[CapabilitiesByRequestType[requestType]];
68+
5869
IList<string> bookUnexpectedAttrs = BookModelAttrsByCapability.SelectMany(kvPair => kvPair.Value)
5970
.Except(bookExpectedAttrs).ToList();
6071

@@ -63,6 +74,7 @@ private async Task Generated_Schema_Includes_Only_Expected_Attrs_For_Request_Typ
6374
{
6475
attrs.Should().ContainProperty(attrName);
6576
}
77+
6678
foreach (string attrName in bookUnexpectedAttrs)
6779
{
6880
attrs.Should().NotContainPath($"properties.{attrName}");

test/OpenApiTests/AttributeTypes/AttributeTypesDbContext.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ namespace OpenApiTests.AttributeTypes;
1414
public sealed class AttributeTypesDbContext(DbContextOptions<AttributeTypesDbContext> options)
1515
: TestableDbContext(options)
1616
{
17+
public DbSet<Author> Authors => Set<Author>();
1718
public DbSet<Book> Books => Set<Book>();
19+
public DbSet<Review> Reviews => Set<Review>();
1820
public DbSet<TypeContainer> TypeContainers => Set<TypeContainer>();
1921

2022
protected override void ConfigureConventions(ModelConfigurationBuilder builder)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
using JsonApiDotNetCore.Resources;
2+
3+
namespace OpenApiTests.AttributeTypes;
4+
5+
public sealed class Author : Identifiable<int>
6+
{
7+
}

test/OpenApiTests/AttributeTypes/Book.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public sealed class Book : Identifiable<int>
1414

1515
// Only visible in GET
1616
[Attr(Capabilities = AttrCapabilities.AllowView)]
17-
public string ISBN { get; set; } = null!;
17+
public string Isbn { get; set; } = null!;
1818

1919
// Only visible in GET
2020
[Attr(Capabilities = AttrCapabilities.AllowView)]
@@ -31,4 +31,10 @@ public sealed class Book : Identifiable<int>
3131
// No visibility or modifiers whatsoever
3232
[Attr(Capabilities = AttrCapabilities.None)]
3333
public string SecretCode { get; set; } = null!;
34+
35+
[HasOne(Capabilities = HasOneCapabilities.AllowView)]
36+
public Author? Author { get; set; }
37+
38+
[HasMany(Capabilities = HasManyCapabilities.AllowSet)]
39+
public ISet<Review> Reviews { get; set; } = new HashSet<Review>();
3440
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace OpenApiTests.AttributeTypes;
2+
3+
public static class CapabilitiesUtils
4+
{
5+
public enum RequestType
6+
{
7+
Response,
8+
Create,
9+
Update
10+
}
11+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using System.Text.Json;
2+
using TestBuildingBlocks;
3+
using Xunit;
4+
using Xunit.Abstractions;
5+
using RequestType = OpenApiTests.AttributeTypes.CapabilitiesUtils.RequestType;
6+
7+
namespace OpenApiTests.AttributeTypes;
8+
9+
public sealed class RelationshipCapabilitiesTests : IClassFixture<OpenApiTestContext<AttributeTypesStartup, AttributeTypesDbContext>>
10+
{
11+
private static readonly Dictionary<RequestType, string> SchemaPathByRequestType = new()
12+
{
13+
{ RequestType.Response, "components.schemas.relationshipsInBookResponse.allOf[1].properties" },
14+
{ RequestType.Create, "components.schemas.relationshipsInCreateBookRequest.allOf[1].properties" },
15+
{ RequestType.Update, "components.schemas.relationshipsInUpdateBookRequest.allOf[1].properties" }
16+
};
17+
18+
private static readonly Dictionary<string, List<string>> BookModelRelsByCapability = new()
19+
{
20+
{ "AllowView", ["author"] },
21+
{ "AllowSet", ["reviews"] }
22+
};
23+
24+
private static readonly Dictionary<RequestType, string> CapabilitiesByRequestType = new()
25+
{
26+
{ RequestType.Response, "AllowView" },
27+
{ RequestType.Create, "AllowSet" },
28+
{ RequestType.Update, "AllowSet" }
29+
};
30+
31+
private readonly OpenApiTestContext<AttributeTypesStartup, AttributeTypesDbContext> _testContext;
32+
33+
public RelationshipCapabilitiesTests(
34+
OpenApiTestContext<AttributeTypesStartup, AttributeTypesDbContext> testContext,
35+
ITestOutputHelper output)
36+
{
37+
_testContext = testContext;
38+
_testContext.UseController<BooksController>();
39+
_testContext.SetTestOutputHelper(output);
40+
}
41+
42+
[Theory]
43+
[InlineData(RequestType.Response)]
44+
[InlineData(RequestType.Create)]
45+
[InlineData(RequestType.Update)]
46+
public async Task Generated_Schema_Includes_Only_Expected_Relationships_For_Request_Type_Async(RequestType requestType)
47+
{
48+
// Arrange
49+
JsonElement document = await _testContext.GetSwaggerDocumentAsync();
50+
JsonElement properties = document.Should().ContainPath(SchemaPathByRequestType[requestType]);
51+
string selectedCapability = CapabilitiesByRequestType[requestType];
52+
53+
IList<string> expected = BookModelRelsByCapability[selectedCapability];
54+
55+
IList<string> unexpected = BookModelRelsByCapability.SelectMany(kvp => kvp.Value)
56+
.Except(expected).ToList();
57+
58+
// Assert
59+
foreach (string relName in expected)
60+
{
61+
properties.Should().ContainProperty(relName);
62+
}
63+
64+
foreach (string relName in unexpected)
65+
{
66+
properties.Should().NotContainPath($"properties.{relName}");
67+
}
68+
}
69+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
using JsonApiDotNetCore.Resources;
2+
3+
namespace OpenApiTests.AttributeTypes;
4+
5+
public sealed class Review : Identifiable<int>
6+
{
7+
}

0 commit comments

Comments
 (0)