Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions test/OpenApiTests/Capabilities/Article.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using JetBrains.Annotations;
using JsonApiDotNetCore.Resources;
using JsonApiDotNetCore.Resources.Annotations;

namespace OpenApiTests.Capabilities;

[UsedImplicitly(ImplicitUseTargetFlags.Members)]
[Resource(ControllerNamespace = "OpenApiTests.Capabilities")]
public sealed class Article : Identifiable<long>
{
[Attr]
public string Headline { get; set; } = null!;

[HasOne(Capabilities = HasOneCapabilities.AllowSet)]
public Writer? Writer { get; set; }

[HasMany(Capabilities = HasManyCapabilities.AllowView)]
public ISet<Category> Categories { get; set; } = new HashSet<Category>();

[HasMany(Capabilities = HasManyCapabilities.AllowAdd)]
public ISet<Tag> Tags { get; set; } = new HashSet<Tag>();

[HasMany(Capabilities = HasManyCapabilities.AllowRemove)]
public ISet<Comment> Comments { get; set; } = new HashSet<Comment>();
}
192 changes: 192 additions & 0 deletions test/OpenApiTests/Capabilities/AttributeCapabilitiesTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
using System.Text.Json;
using TestBuildingBlocks;
using Xunit;
using Xunit.Abstractions;

namespace OpenApiTests.Capabilities;

public sealed class AttributeCapabilitiesTests : IClassFixture<OpenApiTestContext<OpenApiStartup<CapabilitiesDbContext>, CapabilitiesDbContext>>
{
private readonly OpenApiTestContext<OpenApiStartup<CapabilitiesDbContext>, CapabilitiesDbContext> _testContext;

public AttributeCapabilitiesTests(OpenApiTestContext<OpenApiStartup<CapabilitiesDbContext>, CapabilitiesDbContext> testContext, ITestOutputHelper testOutputHelper)
{
_testContext = testContext;

testContext.UseController<BooksController>();

testContext.SetTestOutputHelper(testOutputHelper);
testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger";
}

[Theory]
[InlineData("title")]
[InlineData("isbn")]
[InlineData("publishedOn")]
[InlineData("hasEmptyTitle")]
public async Task Attribute_with_AllowView_capability_appears_in_response_schema(string attributeName)
{
// Act
JsonElement document = await _testContext.GetSwaggerDocumentAsync();

// Assert
document.Should().ContainPath("components.schemas.attributesInBookResponse.allOf[1].properties").With(properties =>
{
properties.Should().ContainProperty(attributeName);
});
}

[Theory]
[InlineData("draftContent")]
[InlineData("internalNotes")]
[InlineData("secretCode")]
[InlineData("isDeleted")]
public async Task Attribute_without_AllowView_capability_does_not_appear_in_response_schema(string attributeName)
{
// Act
JsonElement document = await _testContext.GetSwaggerDocumentAsync();

// Assert
document.Should().ContainPath("components.schemas.attributesInBookResponse.allOf[1].properties").With(properties =>
{
properties.Should().NotContainPath(attributeName);
});
}

[Theory]
[InlineData("draftContent")]
[InlineData("isDeleted")]
public async Task Attribute_with_AllowCreate_capability_appears_in_create_request_schema(string attributeName)
{
// Act
JsonElement document = await _testContext.GetSwaggerDocumentAsync();

// Assert
document.Should().ContainPath("components.schemas.attributesInCreateBookRequest.allOf[1].properties").With(properties =>
{
properties.Should().ContainProperty(attributeName);
});
}

[Theory]
[InlineData("title")]
[InlineData("isbn")]
[InlineData("publishedOn")]
[InlineData("internalNotes")]
[InlineData("secretCode")]
[InlineData("hasEmptyTitle")]
public async Task Attribute_without_AllowCreate_capability_does_not_appear_in_create_request_schema(string attributeName)
{
// Act
JsonElement document = await _testContext.GetSwaggerDocumentAsync();

// Assert
document.Should().ContainPath("components.schemas.attributesInCreateBookRequest.allOf[1].properties").With(properties =>
{
properties.Should().NotContainPath(attributeName);
});
}

[Theory]
[InlineData("title")]
[InlineData("internalNotes")]
[InlineData("isDeleted")]
public async Task Attribute_with_AllowChange_capability_appears_in_update_request_schema(string attributeName)
{
// Act
JsonElement document = await _testContext.GetSwaggerDocumentAsync();

// Assert
document.Should().ContainPath("components.schemas.attributesInUpdateBookRequest.allOf[1].properties").With(properties =>
{
properties.Should().ContainProperty(attributeName);
});
}

[Theory]
[InlineData("isbn")]
[InlineData("publishedOn")]
[InlineData("draftContent")]
[InlineData("secretCode")]
[InlineData("hasEmptyTitle")]
public async Task Attribute_without_AllowChange_capability_does_not_appear_in_update_request_schema(string attributeName)
{
// Act
JsonElement document = await _testContext.GetSwaggerDocumentAsync();

// Assert
document.Should().ContainPath("components.schemas.attributesInUpdateBookRequest.allOf[1].properties").With(properties =>
{
properties.Should().NotContainPath(attributeName);
});
}

[Fact]
public async Task Attribute_with_None_capability_does_not_appear_in_any_schema()
{
// Act
JsonElement document = await _testContext.GetSwaggerDocumentAsync();

// Assert
document.Should().ContainPath("components.schemas.attributesInBookResponse.allOf[1].properties").With(properties =>
{
properties.Should().NotContainPath("secretCode");
});

document.Should().ContainPath("components.schemas.attributesInCreateBookRequest.allOf[1].properties").With(properties =>
{
properties.Should().NotContainPath("secretCode");
});

document.Should().ContainPath("components.schemas.attributesInUpdateBookRequest.allOf[1].properties").With(properties =>
{
properties.Should().NotContainPath("secretCode");
});
}

[Fact]
public async Task Get_only_property_only_appears_in_response_schema()
{
// Act
JsonElement document = await _testContext.GetSwaggerDocumentAsync();

// Assert
document.Should().ContainPath("components.schemas.attributesInBookResponse.allOf[1].properties").With(properties =>
{
properties.Should().ContainProperty("hasEmptyTitle");
});

document.Should().ContainPath("components.schemas.attributesInCreateBookRequest.allOf[1].properties").With(properties =>
{
properties.Should().NotContainPath("hasEmptyTitle");
});

document.Should().ContainPath("components.schemas.attributesInUpdateBookRequest.allOf[1].properties").With(properties =>
{
properties.Should().NotContainPath("hasEmptyTitle");
});
}

[Fact]
public async Task Set_only_property_only_appears_in_request_schemas()
{
// Act
JsonElement document = await _testContext.GetSwaggerDocumentAsync();

// Assert
document.Should().ContainPath("components.schemas.attributesInBookResponse.allOf[1].properties").With(properties =>
{
properties.Should().NotContainPath("isDeleted");
});

document.Should().ContainPath("components.schemas.attributesInCreateBookRequest.allOf[1].properties").With(properties =>
{
properties.Should().ContainProperty("isDeleted");
});

document.Should().ContainPath("components.schemas.attributesInUpdateBookRequest.allOf[1].properties").With(properties =>
{
properties.Should().ContainProperty("isDeleted");
});
}
}
13 changes: 13 additions & 0 deletions test/OpenApiTests/Capabilities/Author.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using JetBrains.Annotations;
using JsonApiDotNetCore.Resources;
using JsonApiDotNetCore.Resources.Annotations;

namespace OpenApiTests.Capabilities;

[UsedImplicitly(ImplicitUseTargetFlags.Members)]
[Resource(ControllerNamespace = "OpenApiTests.Capabilities")]
public sealed class Author : Identifiable<long>
{
[Attr]
public string Name { get; set; } = null!;
}
40 changes: 40 additions & 0 deletions test/OpenApiTests/Capabilities/Book.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using JetBrains.Annotations;
using JsonApiDotNetCore.Resources;
using JsonApiDotNetCore.Resources.Annotations;

namespace OpenApiTests.Capabilities;

[UsedImplicitly(ImplicitUseTargetFlags.Members)]
[Resource(ControllerNamespace = "OpenApiTests.Capabilities")]
public sealed class Book : Identifiable<long>
{
[Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowChange)]
public string Title { get; set; } = null!;

[Attr(Capabilities = AttrCapabilities.AllowView)]
public string Isbn { get; set; } = null!;

[Attr(Capabilities = AttrCapabilities.AllowView)]
public DateOnly PublishedOn { get; set; }

[Attr(Capabilities = AttrCapabilities.AllowCreate)]
public string DraftContent { get; set; } = null!;

[Attr(Capabilities = AttrCapabilities.AllowChange)]
public string InternalNotes { get; set; } = null!;

[Attr(Capabilities = AttrCapabilities.None)]
public string SecretCode { get; set; } = null!;

[Attr]
public bool HasEmptyTitle => string.IsNullOrEmpty(Title);

[Attr]
public bool IsDeleted { set => _ = value; }

[HasOne(Capabilities = HasOneCapabilities.AllowView)]
public Author? Author { get; set; }

[HasMany(Capabilities = HasManyCapabilities.AllowSet)]
public ISet<Review> Reviews { get; set; } = new HashSet<Review>();
}
19 changes: 19 additions & 0 deletions test/OpenApiTests/Capabilities/CapabilitiesDbContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using TestBuildingBlocks;

namespace OpenApiTests.Capabilities;

[UsedImplicitly(ImplicitUseTargetFlags.Members)]
public sealed class CapabilitiesDbContext(DbContextOptions<CapabilitiesDbContext> options)
: TestableDbContext(options)
{
public DbSet<Book> Books => Set<Book>();
public DbSet<Author> Authors => Set<Author>();
public DbSet<Review> Reviews => Set<Review>();
public DbSet<Article> Articles => Set<Article>();
public DbSet<Writer> Writers => Set<Writer>();
public DbSet<Category> Categories => Set<Category>();
public DbSet<Tag> Tags => Set<Tag>();
public DbSet<Comment> Comments => Set<Comment>();
}
13 changes: 13 additions & 0 deletions test/OpenApiTests/Capabilities/Category.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using JetBrains.Annotations;
using JsonApiDotNetCore.Resources;
using JsonApiDotNetCore.Resources.Annotations;

namespace OpenApiTests.Capabilities;

[UsedImplicitly(ImplicitUseTargetFlags.Members)]
[Resource(ControllerNamespace = "OpenApiTests.Capabilities")]
public sealed class Category : Identifiable<long>
{
[Attr]
public string Name { get; set; } = null!;
}
13 changes: 13 additions & 0 deletions test/OpenApiTests/Capabilities/Comment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using JetBrains.Annotations;
using JsonApiDotNetCore.Resources;
using JsonApiDotNetCore.Resources.Annotations;

namespace OpenApiTests.Capabilities;

[UsedImplicitly(ImplicitUseTargetFlags.Members)]
[Resource(ControllerNamespace = "OpenApiTests.Capabilities")]
public sealed class Comment : Identifiable<long>
{
[Attr]
public string Text { get; set; } = null!;
}
Loading
Loading