diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/TagsController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/TagsController.cs new file mode 100644 index 0000000000..a9536f009b --- /dev/null +++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/TagsController.cs @@ -0,0 +1,16 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Services; +using JsonApiDotNetCoreExample.Models; +using Microsoft.Extensions.Logging; + +namespace JsonApiDotNetCoreExample.Controllers +{ + public sealed class TagsController : JsonApiController + { + public TagsController(IJsonApiOptions options, ILoggerFactory loggerFactory, IResourceService resourceService) + : base(options, loggerFactory, resourceService) + { + } + } +} diff --git a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs index ae3d13d553..9cb18cf548 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs @@ -10,10 +10,6 @@ namespace JsonApiDotNetCoreExample.Data public sealed class AppDbContext : DbContext { public DbSet TodoItems { get; set; } - public DbSet People { get; set; } - public DbSet
Articles { get; set; } - public DbSet AuthorDifferentDbContextName { get; set; } - public DbSet Users { get; set; } public AppDbContext(DbContextOptions options) : base(options) @@ -22,47 +18,26 @@ public AppDbContext(DbContextOptions options) protected override void OnModelCreating(ModelBuilder builder) { - builder.Entity() - .HasOne(todoItem => todoItem.Assignee) - .WithMany(person => person.AssignedTodoItems); - - builder.Entity() - .HasOne(todoItem => todoItem.Owner) - .WithMany(person => person.TodoItems); - - builder.Entity() - .HasKey(bc => new - { - bc.ArticleId, - bc.TagId - }); - - builder.Entity() - .HasKey(bc => new + builder.Entity() + .HasKey(todoItemTag => new { - bc.ArticleId, - bc.TagId + todoItemTag.TodoItemId, + todoItemTag.TagId }); + // When deleting a person, un-assign him/her from existing todo items. builder.Entity() - .HasOne(person => person.StakeHolderTodoItem) - .WithMany(todoItem => todoItem.StakeHolders) - .OnDelete(DeleteBehavior.Cascade); - - builder.Entity() - .HasMany(todoItem => todoItem.ChildTodoItems) - .WithOne(todoItem => todoItem.ParentTodo); - - builder.Entity() - .HasOne(passport => passport.Person) - .WithOne(person => person.Passport) - .HasForeignKey("PassportKey") + .HasMany(person => person.AssignedTodoItems) + .WithOne(todoItem => todoItem.Assignee) + .IsRequired(false) .OnDelete(DeleteBehavior.SetNull); + // When deleting a person, the todo items he/she owns are deleted too. builder.Entity() - .HasOne(todoItem => todoItem.OneToOnePerson) - .WithOne(person => person.OneToOneTodoItem) - .HasForeignKey("OneToOnePersonKey"); + .HasOne(todoItem => todoItem.Owner) + .WithMany() + .IsRequired() + .OnDelete(DeleteBehavior.Cascade); } } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Definitions/TodoItemDefinition.cs b/src/Examples/JsonApiDotNetCoreExample/Definitions/TodoItemDefinition.cs new file mode 100644 index 0000000000..43b57b98e5 --- /dev/null +++ b/src/Examples/JsonApiDotNetCoreExample/Definitions/TodoItemDefinition.cs @@ -0,0 +1,53 @@ +using System.ComponentModel; +using System.Threading; +using System.Threading.Tasks; +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Queries.Expressions; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCoreExample.Models; +using Microsoft.AspNetCore.Authentication; + +namespace JsonApiDotNetCoreExample.Definitions +{ + [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] + public sealed class TodoItemDefinition : JsonApiResourceDefinition + { + private readonly ISystemClock _systemClock; + + public TodoItemDefinition(IResourceGraph resourceGraph, ISystemClock systemClock) + : base(resourceGraph) + { + _systemClock = systemClock; + } + + public override SortExpression OnApplySort(SortExpression existingSort) + { + return existingSort ?? GetDefaultSortOrder(); + } + + private SortExpression GetDefaultSortOrder() + { + return CreateSortExpressionFromLambda(new PropertySortOrder + { + (todoItem => todoItem.Priority, ListSortDirection.Descending), + (todoItem => todoItem.LastModifiedAt, ListSortDirection.Descending) + }); + } + + public override Task OnWritingAsync(TodoItem resource, OperationKind operationKind, CancellationToken cancellationToken) + { + if (operationKind == OperationKind.CreateResource) + { + resource.CreatedAt = _systemClock.UtcNow; + } + else if (operationKind == OperationKind.UpdateResource) + { + resource.LastModifiedAt = _systemClock.UtcNow; + } + + return Task.CompletedTask; + } + } +} diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs index 45015c437f..0f30ab3bf6 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs @@ -6,29 +6,15 @@ namespace JsonApiDotNetCoreExample.Models { [UsedImplicitly(ImplicitUseTargetFlags.Members)] - public sealed class Person : Identifiable, IIsLockable + public sealed class Person : Identifiable { - public bool IsLocked { get; set; } - [Attr] public string FirstName { get; set; } [Attr] public string LastName { get; set; } - [HasMany] - public ISet TodoItems { get; set; } - [HasMany] public ISet AssignedTodoItems { get; set; } - - [HasOne] - public TodoItem OneToOneTodoItem { get; set; } - - [HasOne] - public TodoItem StakeHolderTodoItem { get; set; } - - [HasOne] - public Passport Passport { get; set; } } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Tag.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Tag.cs index b1b446d7f2..cd6e73552f 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/Tag.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/Tag.cs @@ -1,3 +1,4 @@ +using System.ComponentModel.DataAnnotations; using JetBrains.Annotations; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; @@ -7,6 +8,8 @@ namespace JsonApiDotNetCoreExample.Models [UsedImplicitly(ImplicitUseTargetFlags.Members)] public sealed class Tag : Identifiable { + [Required] + [MinLength(1)] [Attr] public string Name { get; set; } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs index b9f0277b61..95643e61a3 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; using JetBrains.Annotations; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; @@ -6,30 +8,30 @@ namespace JsonApiDotNetCoreExample.Models { [UsedImplicitly(ImplicitUseTargetFlags.Members)] - public sealed class TodoItem : Identifiable, IIsLockable + public sealed class TodoItem : Identifiable { - public bool IsLocked { get; set; } - [Attr] public string Description { get; set; } + [Attr] + public TodoItemPriority Priority { get; set; } + + [Attr(Capabilities = AttrCapabilities.AllowFilter | AttrCapabilities.AllowSort | AttrCapabilities.AllowView)] + public DateTimeOffset CreatedAt { get; set; } + + [Attr(PublicName = "modifiedAt", Capabilities = AttrCapabilities.AllowFilter | AttrCapabilities.AllowSort | AttrCapabilities.AllowView)] + public DateTimeOffset? LastModifiedAt { get; set; } + [HasOne] public Person Owner { get; set; } [HasOne] public Person Assignee { get; set; } - [HasOne] - public Person OneToOnePerson { get; set; } - - [HasMany] - public ISet StakeHolders { get; set; } - - // cyclical to-many structure - [HasOne] - public TodoItem ParentTodo { get; set; } + [NotMapped] + [HasManyThrough(nameof(TodoItemTags))] + public ISet Tags { get; set; } - [HasMany] - public IList ChildTodoItems { get; set; } + public ISet TodoItemTags { get; set; } } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemPriority.cs b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemPriority.cs new file mode 100644 index 0000000000..5f8687a064 --- /dev/null +++ b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemPriority.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; + +namespace JsonApiDotNetCoreExample.Models +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public enum TodoItemPriority + { + Low, + Medium, + High + } +} diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemTag.cs b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemTag.cs new file mode 100644 index 0000000000..8d1ef42d42 --- /dev/null +++ b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemTag.cs @@ -0,0 +1,14 @@ +using JetBrains.Annotations; + +namespace JsonApiDotNetCoreExample.Models +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public sealed class TodoItemTag + { + public int TodoItemId { get; set; } + public TodoItem TodoItem { get; set; } + + public int TagId { get; set; } + public Tag Tag { get; set; } + } +} diff --git a/src/Examples/JsonApiDotNetCoreExample/Startups/Startup.cs b/src/Examples/JsonApiDotNetCoreExample/Startups/Startup.cs index c8bd15bffa..84ddf4a4de 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Startups/Startup.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Startups/Startup.cs @@ -27,20 +27,27 @@ public override void ConfigureServices(IServiceCollection services) { services.AddSingleton(); - services.AddDbContext(options => options.UseNpgsql(_connectionString)); - - services.AddJsonApi(ConfigureJsonApiOptions, discovery => discovery.AddCurrentAssembly()); - } + services.AddDbContext(options => + { + options.UseNpgsql(_connectionString); +#if DEBUG + options.EnableSensitiveDataLogging(); + options.EnableDetailedErrors(); +#endif + }); - private void ConfigureJsonApiOptions(JsonApiOptions options) - { - options.IncludeExceptionStackTraceInErrors = true; - options.Namespace = "api/v1"; - options.DefaultPageSize = new PageSize(5); - options.IncludeTotalResourceCount = true; - options.ValidateModelState = true; - options.SerializerSettings.Formatting = Formatting.Indented; - options.SerializerSettings.Converters.Add(new StringEnumConverter()); + services.AddJsonApi(options => + { + options.Namespace = "api/v1"; + options.UseRelativeLinks = true; + options.ValidateModelState = true; + options.IncludeTotalResourceCount = true; + options.SerializerSettings.Formatting = Formatting.Indented; + options.SerializerSettings.Converters.Add(new StringEnumConverter()); +#if DEBUG + options.IncludeExceptionStackTraceInErrors = true; +#endif + }, discovery => discovery.AddCurrentAssembly()); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/test/DiscoveryTests/ServiceDiscoveryFacadeTests.cs b/test/DiscoveryTests/ServiceDiscoveryFacadeTests.cs index d5a101cd11..a13c6340f5 100644 --- a/test/DiscoveryTests/ServiceDiscoveryFacadeTests.cs +++ b/test/DiscoveryTests/ServiceDiscoveryFacadeTests.cs @@ -59,11 +59,11 @@ public void Can_add_resources_from_assembly_to_graph() // Assert IResourceGraph resourceGraph = _resourceGraphBuilder.Build(); - ResourceContext personResource = resourceGraph.GetResourceContext(typeof(Person)); - personResource.Should().NotBeNull(); + ResourceContext personContext = resourceGraph.GetResourceContext(typeof(Person)); + personContext.Should().NotBeNull(); - ResourceContext articleResource = resourceGraph.GetResourceContext(typeof(Article)); - articleResource.Should().NotBeNull(); + ResourceContext todoItemContext = resourceGraph.GetResourceContext(typeof(TodoItem)); + todoItemContext.Should().NotBeNull(); } [Fact] @@ -79,8 +79,8 @@ public void Can_add_resource_from_current_assembly_to_graph() // Assert IResourceGraph resourceGraph = _resourceGraphBuilder.Build(); - ResourceContext resource = resourceGraph.GetResourceContext(typeof(TestResource)); - resource.Should().NotBeNull(); + ResourceContext testContext = resourceGraph.GetResourceContext(typeof(TestResource)); + testContext.Should().NotBeNull(); } [Fact] diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/ArticlesController.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/ArticlesController.cs similarity index 73% rename from src/Examples/JsonApiDotNetCoreExample/Controllers/ArticlesController.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/ArticlesController.cs index 0735952114..34f6c30abf 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/ArticlesController.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/ArticlesController.cs @@ -1,10 +1,10 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Services; -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; using Microsoft.Extensions.Logging; -namespace JsonApiDotNetCoreExample.Controllers +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Controllers { public sealed class ArticlesController : JsonApiController
{ diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/AuthorsController.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/AuthorsController.cs similarity index 73% rename from src/Examples/JsonApiDotNetCoreExample/Controllers/AuthorsController.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/AuthorsController.cs index 963e85e996..ec06d74d15 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/AuthorsController.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/AuthorsController.cs @@ -1,10 +1,10 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Services; -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; using Microsoft.Extensions.Logging; -namespace JsonApiDotNetCoreExample.Controllers +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Controllers { public sealed class AuthorsController : JsonApiController { diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/PassportsController.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/PassportsController.cs similarity index 74% rename from src/Examples/JsonApiDotNetCoreExample/Controllers/PassportsController.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/PassportsController.cs index 0a737184b7..04d3b67d05 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/PassportsController.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/PassportsController.cs @@ -1,10 +1,10 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Services; -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; using Microsoft.Extensions.Logging; -namespace JsonApiDotNetCoreExample.Controllers +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Controllers { public sealed class PassportsController : JsonApiController { diff --git a/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/PeopleController.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/PeopleController.cs new file mode 100644 index 0000000000..b7ffdacd19 --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/PeopleController.cs @@ -0,0 +1,16 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Services; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; +using Microsoft.Extensions.Logging; + +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Controllers +{ + public sealed class PeopleController : JsonApiController + { + public PeopleController(IJsonApiOptions options, ILoggerFactory loggerFactory, IResourceService resourceService) + : base(options, loggerFactory, resourceService) + { + } + } +} diff --git a/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/TodoItemsController.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/TodoItemsController.cs new file mode 100644 index 0000000000..94e965d69c --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/TodoItemsController.cs @@ -0,0 +1,16 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Services; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; +using Microsoft.Extensions.Logging; + +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Controllers +{ + public sealed class TodoItemsController : JsonApiController + { + public TodoItemsController(IJsonApiOptions options, ILoggerFactory loggerFactory, IResourceService resourceService) + : base(options, loggerFactory, resourceService) + { + } + } +} diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/UsersController.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/UsersController.cs similarity index 73% rename from src/Examples/JsonApiDotNetCoreExample/Controllers/UsersController.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/UsersController.cs index 11a742ced4..d426354956 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/UsersController.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Controllers/UsersController.cs @@ -1,10 +1,10 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Services; -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; using Microsoft.Extensions.Logging; -namespace JsonApiDotNetCoreExample.Controllers +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Controllers { public sealed class UsersController : JsonApiController { diff --git a/src/Examples/JsonApiDotNetCoreExample/Definitions/ArticleHooksDefinition.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/ArticleHooksDefinition.cs similarity index 88% rename from src/Examples/JsonApiDotNetCoreExample/Definitions/ArticleHooksDefinition.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/ArticleHooksDefinition.cs index cef9af0a74..11956bc85f 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Definitions/ArticleHooksDefinition.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/ArticleHooksDefinition.cs @@ -7,9 +7,9 @@ using JsonApiDotNetCore.Hooks.Internal.Execution; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Serialization.Objects; -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; -namespace JsonApiDotNetCoreExample.Definitions +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Definitions { [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] public sealed class ArticleHooksDefinition : ResourceHooksDefinition
diff --git a/src/Examples/JsonApiDotNetCoreExample/Definitions/LockableHooksDefinition.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/LockableHooksDefinition.cs similarity index 88% rename from src/Examples/JsonApiDotNetCoreExample/Definitions/LockableHooksDefinition.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/LockableHooksDefinition.cs index 54e20746c7..81ae8a2e3c 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Definitions/LockableHooksDefinition.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/LockableHooksDefinition.cs @@ -5,9 +5,9 @@ using JsonApiDotNetCore.Errors; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Serialization.Objects; -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; -namespace JsonApiDotNetCoreExample.Definitions +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Definitions { public abstract class LockableHooksDefinition : ResourceHooksDefinition where T : class, IIsLockable, IIdentifiable diff --git a/src/Examples/JsonApiDotNetCoreExample/Definitions/PassportHooksDefinition.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/PassportHooksDefinition.cs similarity index 90% rename from src/Examples/JsonApiDotNetCoreExample/Definitions/PassportHooksDefinition.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/PassportHooksDefinition.cs index b2a5eb7775..26c1cfdbc3 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Definitions/PassportHooksDefinition.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/PassportHooksDefinition.cs @@ -6,9 +6,9 @@ using JsonApiDotNetCore.Errors; using JsonApiDotNetCore.Hooks.Internal.Execution; using JsonApiDotNetCore.Serialization.Objects; -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; -namespace JsonApiDotNetCoreExample.Definitions +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Definitions { [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] public sealed class PassportHooksDefinition : LockableHooksDefinition diff --git a/src/Examples/JsonApiDotNetCoreExample/Definitions/PersonHooksDefinition.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/PersonHooksDefinition.cs similarity index 87% rename from src/Examples/JsonApiDotNetCoreExample/Definitions/PersonHooksDefinition.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/PersonHooksDefinition.cs index 473817b0e8..bf30f5594c 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Definitions/PersonHooksDefinition.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/PersonHooksDefinition.cs @@ -3,9 +3,9 @@ using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; -namespace JsonApiDotNetCoreExample.Definitions +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Definitions { [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] public sealed class PersonHooksDefinition : LockableHooksDefinition diff --git a/src/Examples/JsonApiDotNetCoreExample/Definitions/TagHooksDefinition.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/TagHooksDefinition.cs similarity index 81% rename from src/Examples/JsonApiDotNetCoreExample/Definitions/TagHooksDefinition.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/TagHooksDefinition.cs index 891959e00c..0ea050e3d7 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Definitions/TagHooksDefinition.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/TagHooksDefinition.cs @@ -4,9 +4,9 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Hooks.Internal.Execution; using JsonApiDotNetCore.Resources; -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; -namespace JsonApiDotNetCoreExample.Definitions +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Definitions { [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] public sealed class TagHooksDefinition : ResourceHooksDefinition diff --git a/src/Examples/JsonApiDotNetCoreExample/Definitions/TodoItemHooksDefinition.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/TodoItemHooksDefinition.cs similarity index 90% rename from src/Examples/JsonApiDotNetCoreExample/Definitions/TodoItemHooksDefinition.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/TodoItemHooksDefinition.cs index bb912e3a82..09be6b9491 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Definitions/TodoItemHooksDefinition.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Definitions/TodoItemHooksDefinition.cs @@ -6,9 +6,9 @@ using JsonApiDotNetCore.Errors; using JsonApiDotNetCore.Hooks.Internal.Execution; using JsonApiDotNetCore.Serialization.Objects; -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; -namespace JsonApiDotNetCoreExample.Definitions +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Definitions { [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] public sealed class TodoItemHooksDefinition : LockableHooksDefinition diff --git a/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/HooksDbContext.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/HooksDbContext.cs new file mode 100644 index 0000000000..a20c9a4f8f --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/HooksDbContext.cs @@ -0,0 +1,44 @@ +using JetBrains.Annotations; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; +using Microsoft.EntityFrameworkCore; + +// @formatter:wrap_chained_method_calls chop_always + +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public sealed class HooksDbContext : DbContext + { + public DbSet TodoItems { get; set; } + public DbSet People { get; set; } + public DbSet
Articles { get; set; } + public DbSet AuthorDifferentDbContextName { get; set; } + public DbSet Users { get; set; } + + public HooksDbContext(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.Entity() + .HasKey(bc => new + { + bc.ArticleId, + bc.TagId + }); + + builder.Entity() + .HasOne(person => person.StakeholderTodoItem) + .WithMany(todoItem => todoItem.Stakeholders) + .OnDelete(DeleteBehavior.Cascade); + + builder.Entity() + .HasOne(passport => passport.Person) + .WithOne(person => person.Passport) + .HasForeignKey("PassportKey") + .OnDelete(DeleteBehavior.SetNull); + } + } +} diff --git a/test/JsonApiDotNetCoreExampleTests/ExampleFakers.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/HooksFakers.cs similarity index 79% rename from test/JsonApiDotNetCoreExampleTests/ExampleFakers.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/HooksFakers.cs index 106eb8fe40..165068309d 100644 --- a/test/JsonApiDotNetCoreExampleTests/ExampleFakers.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/HooksFakers.cs @@ -1,21 +1,20 @@ using System; using Bogus; -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; using TestBuildingBlocks; -using Person = JsonApiDotNetCoreExample.Models.Person; +using Person = JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models.Person; // @formatter:wrap_chained_method_calls chop_always // @formatter:keep_existing_linebreaks true -namespace JsonApiDotNetCoreExampleTests +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks { - internal sealed class ExampleFakers : FakerContainer + internal sealed class HooksFakers : FakerContainer { private readonly Lazy> _lazyAuthorFaker = new Lazy>(() => new Faker() .UseSeed(GetFakerSeed()) - .RuleFor(author => author.FirstName, faker => faker.Person.FirstName) - .RuleFor(author => author.LastName, faker => faker.Person.LastName)); + .RuleFor(author => author.Name, faker => faker.Person.FullName)); private readonly Lazy> _lazyArticleFaker = new Lazy>(() => new Faker
() @@ -37,8 +36,7 @@ internal sealed class ExampleFakers : FakerContainer private readonly Lazy> _lazyPersonFaker = new Lazy>(() => new Faker() .UseSeed(GetFakerSeed()) - .RuleFor(person => person.FirstName, faker => faker.Person.FirstName) - .RuleFor(person => person.LastName, faker => faker.Person.LastName)); + .RuleFor(person => person.Name, faker => faker.Person.FullName)); private readonly Lazy> _lazyTagFaker = new Lazy>(() => new Faker() diff --git a/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Article.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Article.cs new file mode 100644 index 0000000000..00391a69ba --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Article.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public sealed class Article : Identifiable + { + [Attr] + public string Caption { get; set; } + + [Attr] + public string Url { get; set; } + + [NotMapped] + [HasManyThrough(nameof(ArticleTags))] + public ISet Tags { get; set; } + + public ISet ArticleTags { get; set; } + } +} diff --git a/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/ArticleTag.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/ArticleTag.cs new file mode 100644 index 0000000000..291b751342 --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/ArticleTag.cs @@ -0,0 +1,14 @@ +using JetBrains.Annotations; + +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public sealed class ArticleTag + { + public int ArticleId { get; set; } + public Article Article { get; set; } + + public int TagId { get; set; } + public Tag Tag { get; set; } + } +} diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Author.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Author.cs similarity index 70% rename from src/Examples/JsonApiDotNetCoreExample/Models/Author.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Author.cs index 0b5b1d1acd..4bc2f0f781 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/Author.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Author.cs @@ -3,16 +3,13 @@ using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; -namespace JsonApiDotNetCoreExample.Models +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models { [UsedImplicitly(ImplicitUseTargetFlags.Members)] public sealed class Author : Identifiable { [Attr] - public string FirstName { get; set; } - - [Attr] - public string LastName { get; set; } + public string Name { get; set; } [HasMany] public IList
Articles { get; set; } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/IIsLockable.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/IIsLockable.cs similarity index 50% rename from src/Examples/JsonApiDotNetCoreExample/Models/IIsLockable.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/IIsLockable.cs index d59f5b8f4d..08923b91cd 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/IIsLockable.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/IIsLockable.cs @@ -1,4 +1,4 @@ -namespace JsonApiDotNetCoreExample.Models +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models { public interface IIsLockable { diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Passport.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Passport.cs similarity index 82% rename from src/Examples/JsonApiDotNetCoreExample/Models/Passport.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Passport.cs index 23d4012dd9..673d1e0d8b 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/Passport.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Passport.cs @@ -2,7 +2,7 @@ using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; -namespace JsonApiDotNetCoreExample.Models +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models { [UsedImplicitly(ImplicitUseTargetFlags.Members)] public sealed class Passport : Identifiable, IIsLockable diff --git a/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Person.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Person.cs new file mode 100644 index 0000000000..fe7d26d92e --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Person.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public sealed class Person : Identifiable, IIsLockable + { + public bool IsLocked { get; set; } + + [Attr] + public string Name { get; set; } + + [HasMany] + public ISet TodoItems { get; set; } + + [HasOne] + public TodoItem StakeholderTodoItem { get; set; } + + [HasOne] + public Passport Passport { get; set; } + } +} diff --git a/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Tag.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Tag.cs new file mode 100644 index 0000000000..b70a7779bc --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/Tag.cs @@ -0,0 +1,13 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public sealed class Tag : Identifiable + { + [Attr] + public string Name { get; set; } + } +} diff --git a/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/TodoItem.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/TodoItem.cs new file mode 100644 index 0000000000..ee2273c8b2 --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/TodoItem.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public sealed class TodoItem : Identifiable, IIsLockable + { + public bool IsLocked { get; set; } + + [Attr] + public string Description { get; set; } + + [HasMany] + public ISet Stakeholders { get; set; } + } +} diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/User.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/User.cs similarity index 84% rename from src/Examples/JsonApiDotNetCoreExample/Models/User.cs rename to test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/User.cs index fd7852ec3b..56fa0dcec5 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/User.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/Models/User.cs @@ -2,7 +2,7 @@ using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; -namespace JsonApiDotNetCoreExample.Models +namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models { [UsedImplicitly(ImplicitUseTargetFlags.Members)] public sealed class User : Identifiable diff --git a/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/ResourceHookTests.cs b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/ResourceHookTests.cs index 374ab674eb..610d5d279f 100644 --- a/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/ResourceHookTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/IntegrationTests/ResourceHooks/ResourceHookTests.cs @@ -10,10 +10,9 @@ using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Serialization.Client.Internal; using JsonApiDotNetCore.Serialization.Objects; -using JsonApiDotNetCoreExample.Controllers; -using JsonApiDotNetCoreExample.Data; -using JsonApiDotNetCoreExample.Definitions; -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Controllers; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Definitions; +using JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks.Models; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using TestBuildingBlocks; @@ -21,12 +20,12 @@ namespace JsonApiDotNetCoreExampleTests.IntegrationTests.ResourceHooks { - public sealed class ResourceHookTests : IClassFixture, AppDbContext>> + public sealed class ResourceHookTests : IClassFixture, HooksDbContext>> { - private readonly ExampleIntegrationTestContext, AppDbContext> _testContext; - private readonly ExampleFakers _fakers = new ExampleFakers(); + private readonly ExampleIntegrationTestContext, HooksDbContext> _testContext; + private readonly HooksFakers _fakers = new HooksFakers(); - public ResourceHookTests(ExampleIntegrationTestContext, AppDbContext> testContext) + public ResourceHookTests(ExampleIntegrationTestContext, HooksDbContext> testContext) { _testContext = testContext; @@ -543,7 +542,7 @@ public async Task Can_block_creating_ToMany_relationship_using_BeforeUpdateRelat List persons = _fakers.Person.Generate(2); TodoItem lockedTodo = _fakers.TodoItem.Generate(); lockedTodo.IsLocked = true; - lockedTodo.StakeHolders = persons.ToHashSet(); + lockedTodo.Stakeholders = persons.ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -558,7 +557,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => type = "todoItems", relationships = new { - stakeHolders = new + stakeholders = new { data = new[] { @@ -602,7 +601,7 @@ public async Task Can_block_replacing_ToMany_relationship_using_BeforeImplicitUp TodoItem lockedTodo = _fakers.TodoItem.Generate(); lockedTodo.IsLocked = true; - lockedTodo.StakeHolders = persons.ToHashSet(); + lockedTodo.Stakeholders = persons.ToHashSet(); TodoItem unlockedTodo = _fakers.TodoItem.Generate(); @@ -620,7 +619,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => id = unlockedTodo.Id, relationships = new { - stakeHolders = new + stakeholders = new { data = new[] { @@ -663,7 +662,7 @@ public async Task Can_block_clearing_ToMany_relationship_using_BeforeImplicitUpd List persons = _fakers.Person.Generate(2); TodoItem lockedTodo = _fakers.TodoItem.Generate(); lockedTodo.IsLocked = true; - lockedTodo.StakeHolders = persons.ToHashSet(); + lockedTodo.Stakeholders = persons.ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/UnitTests/Extensions/ServiceCollectionExtensionsTests.cs b/test/UnitTests/Extensions/ServiceCollectionExtensionsTests.cs index 603ac39aa3..7bb63532a5 100644 --- a/test/UnitTests/Extensions/ServiceCollectionExtensionsTests.cs +++ b/test/UnitTests/Extensions/ServiceCollectionExtensionsTests.cs @@ -74,10 +74,10 @@ public void RegisterResource_DeviatingDbContextPropertyName_RegistersCorrectly() services.AddScoped(); ServiceProvider provider = services.BuildServiceProvider(); var graph = provider.GetRequiredService(); - ResourceContext resourceContext = graph.GetResourceContext(); + ResourceContext resourceContext = graph.GetResourceContext(); // Assert - Assert.Equal("authors", resourceContext.PublicName); + Assert.Equal("people", resourceContext.PublicName); } [Fact] diff --git a/test/UnitTests/Middleware/JsonApiRequestTests.cs b/test/UnitTests/Middleware/JsonApiRequestTests.cs index 5e2baeadaa..4ac64a62e5 100644 --- a/test/UnitTests/Middleware/JsonApiRequestTests.cs +++ b/test/UnitTests/Middleware/JsonApiRequestTests.cs @@ -18,25 +18,25 @@ namespace UnitTests.Middleware public sealed class JsonApiRequestTests { [Theory] - [InlineData("HEAD", "/articles", true, EndpointKind.Primary, true)] - [InlineData("HEAD", "/articles/1", false, EndpointKind.Primary, true)] - [InlineData("HEAD", "/articles/1/author", false, EndpointKind.Secondary, true)] - [InlineData("HEAD", "/articles/1/tags", true, EndpointKind.Secondary, true)] - [InlineData("HEAD", "/articles/1/relationships/author", false, EndpointKind.Relationship, true)] - [InlineData("HEAD", "/articles/1/relationships/tags", true, EndpointKind.Relationship, true)] - [InlineData("GET", "/articles", true, EndpointKind.Primary, true)] - [InlineData("GET", "/articles/1", false, EndpointKind.Primary, true)] - [InlineData("GET", "/articles/1/author", false, EndpointKind.Secondary, true)] - [InlineData("GET", "/articles/1/tags", true, EndpointKind.Secondary, true)] - [InlineData("GET", "/articles/1/relationships/author", false, EndpointKind.Relationship, true)] - [InlineData("GET", "/articles/1/relationships/tags", true, EndpointKind.Relationship, true)] - [InlineData("POST", "/articles", false, EndpointKind.Primary, false)] - [InlineData("POST", "/articles/1/relationships/tags", true, EndpointKind.Relationship, false)] - [InlineData("PATCH", "/articles/1", false, EndpointKind.Primary, false)] - [InlineData("PATCH", "/articles/1/relationships/author", false, EndpointKind.Relationship, false)] - [InlineData("PATCH", "/articles/1/relationships/tags", true, EndpointKind.Relationship, false)] - [InlineData("DELETE", "/articles/1", false, EndpointKind.Primary, false)] - [InlineData("DELETE", "/articles/1/relationships/tags", true, EndpointKind.Relationship, false)] + [InlineData("HEAD", "/todoItems", true, EndpointKind.Primary, true)] + [InlineData("HEAD", "/todoItems/1", false, EndpointKind.Primary, true)] + [InlineData("HEAD", "/todoItems/1/owner", false, EndpointKind.Secondary, true)] + [InlineData("HEAD", "/todoItems/1/tags", true, EndpointKind.Secondary, true)] + [InlineData("HEAD", "/todoItems/1/relationships/owner", false, EndpointKind.Relationship, true)] + [InlineData("HEAD", "/todoItems/1/relationships/tags", true, EndpointKind.Relationship, true)] + [InlineData("GET", "/todoItems", true, EndpointKind.Primary, true)] + [InlineData("GET", "/todoItems/1", false, EndpointKind.Primary, true)] + [InlineData("GET", "/todoItems/1/owner", false, EndpointKind.Secondary, true)] + [InlineData("GET", "/todoItems/1/tags", true, EndpointKind.Secondary, true)] + [InlineData("GET", "/todoItems/1/relationships/owner", false, EndpointKind.Relationship, true)] + [InlineData("GET", "/todoItems/1/relationships/tags", true, EndpointKind.Relationship, true)] + [InlineData("POST", "/todoItems", false, EndpointKind.Primary, false)] + [InlineData("POST", "/todoItems/1/relationships/tags", true, EndpointKind.Relationship, false)] + [InlineData("PATCH", "/todoItems/1", false, EndpointKind.Primary, false)] + [InlineData("PATCH", "/todoItems/1/relationships/owner", false, EndpointKind.Relationship, false)] + [InlineData("PATCH", "/todoItems/1/relationships/tags", true, EndpointKind.Relationship, false)] + [InlineData("DELETE", "/todoItems/1", false, EndpointKind.Primary, false)] + [InlineData("DELETE", "/todoItems/1/relationships/tags", true, EndpointKind.Relationship, false)] public async Task Sets_request_properties_correctly(string requestMethod, string requestPath, bool expectIsCollection, EndpointKind expectKind, bool expectIsReadOnly) { @@ -47,14 +47,14 @@ public async Task Sets_request_properties_correctly(string requestMethod, string }; var graphBuilder = new ResourceGraphBuilder(options, NullLoggerFactory.Instance); - graphBuilder.Add
(); - graphBuilder.Add(); + graphBuilder.Add(); + graphBuilder.Add(); IResourceGraph resourceGraph = graphBuilder.Build(); var controllerResourceMappingMock = new Mock(); - controllerResourceMappingMock.Setup(mapping => mapping.GetResourceTypeForController(It.IsAny())).Returns(typeof(Article)); + controllerResourceMappingMock.Setup(mapping => mapping.GetResourceTypeForController(It.IsAny())).Returns(typeof(TodoItem)); var httpContext = new DefaultHttpContext(); SetupRoutes(httpContext, requestMethod, requestPath); @@ -72,7 +72,7 @@ public async Task Sets_request_properties_correctly(string requestMethod, string request.IsReadOnly.Should().Be(expectIsReadOnly); request.BasePath.Should().BeEmpty(); request.PrimaryResource.Should().NotBeNull(); - request.PrimaryResource.PublicName.Should().Be("articles"); + request.PrimaryResource.PublicName.Should().Be("todoItems"); } private static void SetupRoutes(HttpContext httpContext, string requestMethod, string requestPath) diff --git a/test/UnitTests/ResourceHooks/Executor/Create/AfterCreateTests.cs b/test/UnitTests/ResourceHooks/Executor/Create/AfterCreateTests.cs index 52a60846a6..407d953361 100644 --- a/test/UnitTests/ResourceHooks/Executor/Create/AfterCreateTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/Create/AfterCreateTests.cs @@ -2,8 +2,8 @@ using JsonApiDotNetCore.Hooks.Internal; using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor.Create diff --git a/test/UnitTests/ResourceHooks/Executor/Create/BeforeCreateTests.cs b/test/UnitTests/ResourceHooks/Executor/Create/BeforeCreateTests.cs index 56427939c7..4d09fa64de 100644 --- a/test/UnitTests/ResourceHooks/Executor/Create/BeforeCreateTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/Create/BeforeCreateTests.cs @@ -2,8 +2,8 @@ using JsonApiDotNetCore.Hooks.Internal; using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor.Create diff --git a/test/UnitTests/ResourceHooks/Executor/Create/BeforeCreateWithDbValuesTests.cs b/test/UnitTests/ResourceHooks/Executor/Create/BeforeCreateWithDbValuesTests.cs index ac9e4f7278..deb4e3040f 100644 --- a/test/UnitTests/ResourceHooks/Executor/Create/BeforeCreateWithDbValuesTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/Create/BeforeCreateWithDbValuesTests.cs @@ -3,10 +3,9 @@ using JsonApiDotNetCore.Hooks.Internal; using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Data; -using JsonApiDotNetCoreExample.Models; using Microsoft.EntityFrameworkCore; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor.Create @@ -14,7 +13,7 @@ namespace UnitTests.ResourceHooks.Executor.Create public sealed class BeforeCreateWithDbValuesTests : HooksTestsSetup { private const string Description = "DESCRIPTION"; - private const string LastName = "NAME"; + private const string Name = "NAME"; private readonly ResourceHook[] _targetHooks = { @@ -31,7 +30,7 @@ public sealed class BeforeCreateWithDbValuesTests : HooksTestsSetup private readonly string _personId; private readonly IList _todoList; - private readonly DbContextOptions _options; + private readonly DbContextOptions _options; public BeforeCreateWithDbValuesTests() { @@ -40,7 +39,7 @@ public BeforeCreateWithDbValuesTests() _todoList[0].Id = 0; _todoList[0].Description = Description; Person person = _todoList[0].OneToOnePerson; - person.LastName = LastName; + person.Name = Name; _personId = person.Id.ToString(); TodoItem implicitTodo = TodoFaker.Generate(); implicitTodo.Id += 1000; diff --git a/test/UnitTests/ResourceHooks/Executor/Delete/AfterDeleteTests.cs b/test/UnitTests/ResourceHooks/Executor/Delete/AfterDeleteTests.cs index 815776709d..0cf0611b50 100644 --- a/test/UnitTests/ResourceHooks/Executor/Delete/AfterDeleteTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/Delete/AfterDeleteTests.cs @@ -2,8 +2,8 @@ using JsonApiDotNetCore.Hooks.Internal; using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor.Delete diff --git a/test/UnitTests/ResourceHooks/Executor/Delete/BeforeDeleteTests.cs b/test/UnitTests/ResourceHooks/Executor/Delete/BeforeDeleteTests.cs index 57da7dcc98..9b2eee151e 100644 --- a/test/UnitTests/ResourceHooks/Executor/Delete/BeforeDeleteTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/Delete/BeforeDeleteTests.cs @@ -2,8 +2,8 @@ using JsonApiDotNetCore.Hooks.Internal; using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor.Delete diff --git a/test/UnitTests/ResourceHooks/Executor/Delete/BeforeDeleteWithDbValuesTests.cs b/test/UnitTests/ResourceHooks/Executor/Delete/BeforeDeleteWithDbValuesTests.cs index 045aa4ef2d..8c6aaf9ceb 100644 --- a/test/UnitTests/ResourceHooks/Executor/Delete/BeforeDeleteWithDbValuesTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/Delete/BeforeDeleteWithDbValuesTests.cs @@ -5,10 +5,9 @@ using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; using JsonApiDotNetCore.Resources.Annotations; -using JsonApiDotNetCoreExample.Data; -using JsonApiDotNetCoreExample.Models; using Microsoft.EntityFrameworkCore; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor.Delete @@ -22,7 +21,7 @@ public sealed class BeforeDeleteWithDbValuesTests : HooksTestsSetup ResourceHook.BeforeUpdateRelationship }; - private readonly DbContextOptions _options; + private readonly DbContextOptions _options; private readonly Person _person; public BeforeDeleteWithDbValuesTests() @@ -39,7 +38,7 @@ public BeforeDeleteWithDbValuesTests() todo1 }; - _person.StakeHolderTodoItem = todo2; + _person.StakeholderTodoItem = todo2; _options = InitInMemoryDb(context => { diff --git a/test/UnitTests/ResourceHooks/Executor/IdentifiableManyToManyOnReturnTests.cs b/test/UnitTests/ResourceHooks/Executor/IdentifiableManyToManyOnReturnTests.cs index 1692604aee..866e0e3d2e 100644 --- a/test/UnitTests/ResourceHooks/Executor/IdentifiableManyToManyOnReturnTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/IdentifiableManyToManyOnReturnTests.cs @@ -3,8 +3,8 @@ using JsonApiDotNetCore.Hooks.Internal; using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor diff --git a/test/UnitTests/ResourceHooks/Executor/ManyToManyOnReturnTests.cs b/test/UnitTests/ResourceHooks/Executor/ManyToManyOnReturnTests.cs index 06d2bd876f..098a99123a 100644 --- a/test/UnitTests/ResourceHooks/Executor/ManyToManyOnReturnTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/ManyToManyOnReturnTests.cs @@ -4,8 +4,8 @@ using JsonApiDotNetCore.Hooks.Internal; using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor diff --git a/test/UnitTests/ResourceHooks/Executor/Read/BeforeReadTests.cs b/test/UnitTests/ResourceHooks/Executor/Read/BeforeReadTests.cs index ed30041ad9..f2e078e4dc 100644 --- a/test/UnitTests/ResourceHooks/Executor/Read/BeforeReadTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/Read/BeforeReadTests.cs @@ -3,8 +3,8 @@ using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; using JsonApiDotNetCore.Queries; -using JsonApiDotNetCoreExample.Models; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor.Read @@ -42,7 +42,7 @@ public void BeforeReadWithInclusion() Mock> todoResourceMock, Mock> ownerResourceMock) = CreateTestObjects(todoDiscovery, personDiscovery); - IEnumerable constraintProviders = Wrap(ToIncludeExpression("owner", "assignee", "stakeHolders")); + IEnumerable constraintProviders = Wrap(ToIncludeExpression("owner", "assignee", "stakeholders")); constraintsMock.Setup(providers => providers.GetEnumerator()).Returns(constraintProviders.GetEnumerator()); // Act @@ -66,7 +66,7 @@ public void BeforeReadWithNestedInclusion() Mock> todoResourceMock, Mock> ownerResourceMock, Mock> passportResourceMock) = CreateTestObjectsC(todoDiscovery, personDiscovery, passportDiscovery); - IEnumerable constraintProviders = Wrap(ToIncludeExpression("owner.passport", "assignee", "stakeHolders")); + IEnumerable constraintProviders = Wrap(ToIncludeExpression("owner.passport", "assignee", "stakeholders")); constraintsMock.Setup(providers => providers.GetEnumerator()).Returns(constraintProviders.GetEnumerator()); // Act @@ -91,7 +91,7 @@ public void BeforeReadWithNestedInclusion_No_Parent_Hook_Implemented() Mock> todoResourceMock, Mock> ownerResourceMock, Mock> passportResourceMock) = CreateTestObjectsC(todoDiscovery, personDiscovery, passportDiscovery); - IEnumerable constraintProviders = Wrap(ToIncludeExpression("owner.passport", "assignee", "stakeHolders")); + IEnumerable constraintProviders = Wrap(ToIncludeExpression("owner.passport", "assignee", "stakeholders")); constraintsMock.Setup(providers => providers.GetEnumerator()).Returns(constraintProviders.GetEnumerator()); // Act @@ -115,7 +115,7 @@ public void BeforeReadWithNestedInclusion_No_Child_Hook_Implemented() Mock> todoResourceMock, Mock> ownerResourceMock, Mock> passportResourceMock) = CreateTestObjectsC(todoDiscovery, personDiscovery, passportDiscovery); - IEnumerable constraintProviders = Wrap(ToIncludeExpression("owner.passport", "assignee", "stakeHolders")); + IEnumerable constraintProviders = Wrap(ToIncludeExpression("owner.passport", "assignee", "stakeholders")); constraintsMock.Setup(providers => providers.GetEnumerator()).Returns(constraintProviders.GetEnumerator()); // Act @@ -139,7 +139,7 @@ public void BeforeReadWithNestedInclusion_No_Grandchild_Hook_Implemented() Mock> todoResourceMock, Mock> ownerResourceMock, Mock> passportResourceMock) = CreateTestObjectsC(todoDiscovery, personDiscovery, passportDiscovery); - IEnumerable constraintProviders = Wrap(ToIncludeExpression("owner.passport", "assignee", "stakeHolders")); + IEnumerable constraintProviders = Wrap(ToIncludeExpression("owner.passport", "assignee", "stakeholders")); constraintsMock.Setup(providers => providers.GetEnumerator()).Returns(constraintProviders.GetEnumerator()); // Act @@ -163,7 +163,7 @@ public void BeforeReadWithNestedInclusion_Without_Any_Hook_Implemented() Mock> todoResourceMock, Mock> ownerResourceMock, Mock> passportResourceMock) = CreateTestObjectsC(todoDiscovery, personDiscovery, passportDiscovery); - IEnumerable constraintProviders = Wrap(ToIncludeExpression("owner.passport", "assignee", "stakeHolders")); + IEnumerable constraintProviders = Wrap(ToIncludeExpression("owner.passport", "assignee", "stakeholders")); constraintsMock.Setup(providers => providers.GetEnumerator()).Returns(constraintProviders.GetEnumerator()); // Act diff --git a/test/UnitTests/ResourceHooks/Executor/Read/IdentifiableManyToManyAfterReadTests.cs b/test/UnitTests/ResourceHooks/Executor/Read/IdentifiableManyToManyAfterReadTests.cs index ecba51349d..a10ab13452 100644 --- a/test/UnitTests/ResourceHooks/Executor/Read/IdentifiableManyToManyAfterReadTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/Read/IdentifiableManyToManyAfterReadTests.cs @@ -3,8 +3,8 @@ using JsonApiDotNetCore.Hooks.Internal; using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor.Read diff --git a/test/UnitTests/ResourceHooks/Executor/Read/ManyToManyAfterReadTests.cs b/test/UnitTests/ResourceHooks/Executor/Read/ManyToManyAfterReadTests.cs index 410cb1e3d0..d43f862c36 100644 --- a/test/UnitTests/ResourceHooks/Executor/Read/ManyToManyAfterReadTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/Read/ManyToManyAfterReadTests.cs @@ -3,8 +3,8 @@ using JsonApiDotNetCore.Hooks.Internal; using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor.Read diff --git a/test/UnitTests/ResourceHooks/Executor/SameResourceTypeTests.cs b/test/UnitTests/ResourceHooks/Executor/SameResourceTypeTests.cs index da65de87a7..22f49d141a 100644 --- a/test/UnitTests/ResourceHooks/Executor/SameResourceTypeTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/SameResourceTypeTests.cs @@ -3,8 +3,8 @@ using JsonApiDotNetCore.Hooks.Internal; using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor @@ -45,10 +45,10 @@ public void Resource_Has_Multiple_Relations_To_Same_Type() var person3 = new Person { - StakeHolderTodoItem = todo + StakeholderTodoItem = todo }; - todo.StakeHolders = new HashSet + todo.Stakeholders = new HashSet { person3 }; diff --git a/test/UnitTests/ResourceHooks/Executor/Update/AfterUpdateTests.cs b/test/UnitTests/ResourceHooks/Executor/Update/AfterUpdateTests.cs index 0a36b06fdd..5551d364ca 100644 --- a/test/UnitTests/ResourceHooks/Executor/Update/AfterUpdateTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/Update/AfterUpdateTests.cs @@ -2,8 +2,8 @@ using JsonApiDotNetCore.Hooks.Internal; using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor.Update diff --git a/test/UnitTests/ResourceHooks/Executor/Update/BeforeUpdateTests.cs b/test/UnitTests/ResourceHooks/Executor/Update/BeforeUpdateTests.cs index a45938c467..6afd2ce32f 100644 --- a/test/UnitTests/ResourceHooks/Executor/Update/BeforeUpdateTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/Update/BeforeUpdateTests.cs @@ -2,8 +2,8 @@ using JsonApiDotNetCore.Hooks.Internal; using JsonApiDotNetCore.Hooks.Internal.Discovery; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor.Update diff --git a/test/UnitTests/ResourceHooks/Executor/Update/BeforeUpdateWithDbValuesTests.cs b/test/UnitTests/ResourceHooks/Executor/Update/BeforeUpdateWithDbValuesTests.cs index 310d4a23a4..528d61a0e1 100644 --- a/test/UnitTests/ResourceHooks/Executor/Update/BeforeUpdateWithDbValuesTests.cs +++ b/test/UnitTests/ResourceHooks/Executor/Update/BeforeUpdateWithDbValuesTests.cs @@ -5,10 +5,9 @@ using JsonApiDotNetCore.Hooks.Internal.Execution; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; -using JsonApiDotNetCoreExample.Data; -using JsonApiDotNetCoreExample.Models; using Microsoft.EntityFrameworkCore; using Moq; +using UnitTests.ResourceHooks.Models; using Xunit; namespace UnitTests.ResourceHooks.Executor.Update @@ -16,7 +15,7 @@ namespace UnitTests.ResourceHooks.Executor.Update public sealed class BeforeUpdateWithDbValuesTests : HooksTestsSetup { private const string Description = "DESCRIPTION"; - private const string LastName = "NAME"; + private const string Name = "NAME"; private readonly ResourceHook[] _targetHooks = { @@ -33,7 +32,7 @@ public sealed class BeforeUpdateWithDbValuesTests : HooksTestsSetup private readonly string _personId; private readonly IList _todoList; - private readonly DbContextOptions _options; + private readonly DbContextOptions _options; public BeforeUpdateWithDbValuesTests() { @@ -50,7 +49,7 @@ public BeforeUpdateWithDbValuesTests() implicitTodo.OneToOnePerson = new Person { Id = personId, - LastName = LastName + Name = Name }; implicitTodo.Description = Description + Description; @@ -63,7 +62,7 @@ public BeforeUpdateWithDbValuesTests() OneToOnePerson = new Person { Id = implicitPersonId, - LastName = LastName + LastName + Name = Name + Name }, Description = Description }); @@ -93,11 +92,11 @@ public void BeforeUpdate() ownerResourceMock.Verify( rd => rd.BeforeUpdateRelationship(It.Is>(ids => PersonIdCheck(ids, _personId)), - It.Is>(rh => PersonCheck(LastName, rh)), ResourcePipeline.Patch), Times.Once()); + It.Is>(rh => PersonCheck(Name, rh)), ResourcePipeline.Patch), Times.Once()); ownerResourceMock.Verify( - rd => rd.BeforeImplicitUpdateRelationship(It.Is>(rh => PersonCheck(LastName + LastName, rh)), - ResourcePipeline.Patch), Times.Once()); + rd => rd.BeforeImplicitUpdateRelationship(It.Is>(rh => PersonCheck(Name + Name, rh)), ResourcePipeline.Patch), + Times.Once()); todoResourceMock.Verify( rd => rd.BeforeImplicitUpdateRelationship(It.Is>(rh => TodoCheck(rh, Description + Description)), @@ -136,8 +135,8 @@ public void BeforeUpdate_Deleting_Relationship() Times.Once()); ownerResourceMock.Verify( - rd => rd.BeforeImplicitUpdateRelationship(It.Is>(rh => PersonCheck(LastName + LastName, rh)), - ResourcePipeline.Patch), Times.Once()); + rd => rd.BeforeImplicitUpdateRelationship(It.Is>(rh => PersonCheck(Name + Name, rh)), ResourcePipeline.Patch), + Times.Once()); VerifyNoOtherCalls(todoResourceMock, ownerResourceMock); } @@ -158,11 +157,11 @@ public void BeforeUpdate_Without_Parent_Hook_Implemented() // Assert ownerResourceMock.Verify( rd => rd.BeforeUpdateRelationship(It.Is>(ids => PersonIdCheck(ids, _personId)), - It.Is>(rh => PersonCheck(LastName, rh)), ResourcePipeline.Patch), Times.Once()); + It.Is>(rh => PersonCheck(Name, rh)), ResourcePipeline.Patch), Times.Once()); ownerResourceMock.Verify( - rd => rd.BeforeImplicitUpdateRelationship(It.Is>(rh => PersonCheck(LastName + LastName, rh)), - ResourcePipeline.Patch), Times.Once()); + rd => rd.BeforeImplicitUpdateRelationship(It.Is>(rh => PersonCheck(Name + Name, rh)), ResourcePipeline.Patch), + Times.Once()); VerifyNoOtherCalls(todoResourceMock, ownerResourceMock); } @@ -233,7 +232,7 @@ public void BeforeUpdate_NoImplicit_Without_Parent_Hook_Implemented() // Assert ownerResourceMock.Verify( rd => rd.BeforeUpdateRelationship(It.Is>(ids => PersonIdCheck(ids, _personId)), - It.Is>(rh => PersonCheck(LastName, rh)), ResourcePipeline.Patch), Times.Once()); + It.Is>(rh => PersonCheck(Name, rh)), ResourcePipeline.Patch), Times.Once()); VerifyNoOtherCalls(todoResourceMock, ownerResourceMock); } @@ -286,7 +285,7 @@ private bool PersonIdCheck(IEnumerable ids, string checksum) private bool PersonCheck(string checksum, IRelationshipsDictionary helper) { IDictionary> entries = helper.GetByRelationship(); - return entries.Single().Value.Single().LastName == checksum; + return entries.Single().Value.Single().Name == checksum; } } } diff --git a/test/UnitTests/ResourceHooks/HooksDbContext.cs b/test/UnitTests/ResourceHooks/HooksDbContext.cs new file mode 100644 index 0000000000..5b5a8e0dcc --- /dev/null +++ b/test/UnitTests/ResourceHooks/HooksDbContext.cs @@ -0,0 +1,66 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using UnitTests.ResourceHooks.Models; + +// @formatter:wrap_chained_method_calls chop_always + +namespace UnitTests.ResourceHooks +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public sealed class HooksDbContext : DbContext + { + public DbSet TodoItems { get; set; } + public DbSet People { get; set; } + public DbSet
Articles { get; set; } + + public HooksDbContext(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.Entity() + .HasOne(todoItem => todoItem.Assignee) + .WithMany(person => person.AssignedTodoItems); + + builder.Entity() + .HasOne(todoItem => todoItem.Owner) + .WithMany(person => person.TodoItems); + + builder.Entity() + .HasKey(bc => new + { + bc.ArticleId, + bc.TagId + }); + + builder.Entity() + .HasKey(bc => new + { + bc.ArticleId, + bc.TagId + }); + + builder.Entity() + .HasOne(person => person.StakeholderTodoItem) + .WithMany(todoItem => todoItem.Stakeholders) + .OnDelete(DeleteBehavior.Cascade); + + builder.Entity() + .HasMany(todoItem => todoItem.ChildTodoItems) + .WithOne(todoItem => todoItem.ParentTodo); + + builder.Entity() + .HasOne(passport => passport.Person) + .WithOne(person => person.Passport) + .HasForeignKey("PassportKey") + .OnDelete(DeleteBehavior.SetNull); + + builder.Entity() + .HasOne(todoItem => todoItem.OneToOnePerson) + .WithOne(person => person.OneToOneTodoItem) + .HasForeignKey("OneToOnePersonKey"); + } + } +} diff --git a/test/UnitTests/ResourceHooks/HooksDummyData.cs b/test/UnitTests/ResourceHooks/HooksDummyData.cs index b95b45dacc..161a07f48f 100644 --- a/test/UnitTests/ResourceHooks/HooksDummyData.cs +++ b/test/UnitTests/ResourceHooks/HooksDummyData.cs @@ -4,9 +4,9 @@ using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Hooks.Internal.Execution; -using JsonApiDotNetCoreExample.Models; using Microsoft.Extensions.Logging.Abstractions; -using Person = JsonApiDotNetCoreExample.Models.Person; +using UnitTests.ResourceHooks.Models; +using Person = UnitTests.ResourceHooks.Models.Person; namespace UnitTests.ResourceHooks { diff --git a/test/UnitTests/ResourceHooks/HooksTestsSetup.cs b/test/UnitTests/ResourceHooks/HooksTestsSetup.cs index d9f288b9a2..27b22d3cda 100644 --- a/test/UnitTests/ResourceHooks/HooksTestsSetup.cs +++ b/test/UnitTests/ResourceHooks/HooksTestsSetup.cs @@ -12,11 +12,10 @@ using JsonApiDotNetCore.Repositories; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; -using JsonApiDotNetCoreExample.Data; -using JsonApiDotNetCoreExample.Models; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging.Abstractions; using Moq; +using UnitTests.ResourceHooks.Models; namespace UnitTests.ResourceHooks { @@ -61,7 +60,7 @@ protected TestObjectsA CreateTestObjects(IHooksDiscovery CreateTestObjects(IHooksDiscovery primaryDiscovery = null, - IHooksDiscovery secondaryDiscovery = null, DbContextOptions repoDbContextOptions = null) + IHooksDiscovery secondaryDiscovery = null, DbContextOptions repoDbContextOptions = null) where TPrimary : class, IIdentifiable where TSecondary : class, IIdentifiable { @@ -73,7 +72,7 @@ protected TestObjectsB CreateTestObjects ufMock, Mock> constraintsMock, Mock gpfMock, IJsonApiOptions options) = CreateMocks(); - AppDbContext dbContext = repoDbContextOptions != null ? new AppDbContext(repoDbContextOptions) : null; + HooksDbContext dbContext = repoDbContextOptions != null ? new HooksDbContext(repoDbContextOptions) : null; IResourceGraph resourceGraph = new ResourceGraphBuilder(new JsonApiOptions(), NullLoggerFactory.Instance).Add().Add().Build(); @@ -89,7 +88,7 @@ protected TestObjectsB CreateTestObjects CreateTestObjectsC( IHooksDiscovery primaryDiscovery = null, IHooksDiscovery firstSecondaryDiscovery = null, - IHooksDiscovery secondSecondaryDiscovery = null, DbContextOptions repoDbContextOptions = null) + IHooksDiscovery secondSecondaryDiscovery = null, DbContextOptions repoDbContextOptions = null) where TPrimary : class, IIdentifiable where TFirstSecondary : class, IIdentifiable where TSecondSecondary : class, IIdentifiable @@ -103,7 +102,7 @@ protected TestObjectsC CreateTestOb (Mock ufMock, Mock> constraintsMock, Mock gpfMock, IJsonApiOptions options) = CreateMocks(); - AppDbContext dbContext = repoDbContextOptions != null ? new AppDbContext(repoDbContextOptions) : null; + HooksDbContext dbContext = repoDbContextOptions != null ? new HooksDbContext(repoDbContextOptions) : null; IResourceGraph resourceGraph = new ResourceGraphBuilder(new JsonApiOptions(), NullLoggerFactory.Instance).Add().Add() .Add().Build(); @@ -145,11 +144,11 @@ protected void VerifyNoOtherCalls(params dynamic[] resourceMocks) } } - protected DbContextOptions InitInMemoryDb(Action seeder) + protected DbContextOptions InitInMemoryDb(Action seeder) { - DbContextOptions options = new DbContextOptionsBuilder().UseInMemoryDatabase("repository_mock").Options; + DbContextOptions options = new DbContextOptionsBuilder().UseInMemoryDatabase("repository_mock").Options; - using var context = new AppDbContext(options); + using var context = new HooksDbContext(options); seeder(context); ResolveInverseRelationships(context); @@ -189,7 +188,8 @@ private void MockHooks(Mock> resourceDefi } private void SetupProcessorFactoryForResourceDefinition(Mock processorFactory, - IResourceHookContainer modelResource, IHooksDiscovery discovery, AppDbContext dbContext = null, IResourceGraph resourceGraph = null) + IResourceHookContainer modelResource, IHooksDiscovery discovery, HooksDbContext dbContext = null, + IResourceGraph resourceGraph = null) where TModel : class, IIdentifiable { processorFactory.Setup(factory => factory.Get(typeof(ResourceHooksDefinition<>), typeof(TModel))).Returns(modelResource); @@ -214,7 +214,7 @@ private void SetupProcessorFactoryForResourceDefinition(Mock CreateTestRepository(AppDbContext dbContext, IResourceGraph resourceGraph) + private IResourceReadRepository CreateTestRepository(HooksDbContext dbContext, IResourceGraph resourceGraph) where TModel : class, IIdentifiable { var resourceFactory = new TestResourceFactory(); @@ -225,16 +225,16 @@ private IResourceReadRepository CreateTestRepository(AppDbC Enumerable.Empty(), NullLoggerFactory.Instance); } - private IDbContextResolver CreateTestDbResolver(AppDbContext dbContext) + private IDbContextResolver CreateTestDbResolver(HooksDbContext dbContext) { var mock = new Mock(); mock.Setup(resolver => resolver.GetContext()).Returns(dbContext); return mock.Object; } - private void ResolveInverseRelationships(AppDbContext context) + private void ResolveInverseRelationships(HooksDbContext context) { - IEnumerable> dbContextResolvers = new DbContextResolver(context).AsEnumerable(); + IEnumerable> dbContextResolvers = new DbContextResolver(context).AsEnumerable(); var inverseRelationships = new InverseNavigationResolver(ResourceGraph, dbContextResolvers); inverseRelationships.Resolve(); } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Article.cs b/test/UnitTests/ResourceHooks/Models/Article.cs similarity index 81% rename from src/Examples/JsonApiDotNetCoreExample/Models/Article.cs rename to test/UnitTests/ResourceHooks/Models/Article.cs index df1adfdbcd..037e29075b 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/Article.cs +++ b/test/UnitTests/ResourceHooks/Models/Article.cs @@ -4,17 +4,11 @@ using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; -namespace JsonApiDotNetCoreExample.Models +namespace UnitTests.ResourceHooks.Models { [UsedImplicitly(ImplicitUseTargetFlags.Members)] public sealed class Article : Identifiable { - [Attr] - public string Caption { get; set; } - - [Attr] - public string Url { get; set; } - [NotMapped] [HasManyThrough(nameof(ArticleTags))] public ISet Tags { get; set; } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/ArticleTag.cs b/test/UnitTests/ResourceHooks/Models/ArticleTag.cs similarity index 87% rename from src/Examples/JsonApiDotNetCoreExample/Models/ArticleTag.cs rename to test/UnitTests/ResourceHooks/Models/ArticleTag.cs index 7edc32ef75..2c113589c7 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/ArticleTag.cs +++ b/test/UnitTests/ResourceHooks/Models/ArticleTag.cs @@ -1,6 +1,6 @@ using JetBrains.Annotations; -namespace JsonApiDotNetCoreExample.Models +namespace UnitTests.ResourceHooks.Models { [UsedImplicitly(ImplicitUseTargetFlags.Members)] public sealed class ArticleTag diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/IdentifiableArticleTag.cs b/test/UnitTests/ResourceHooks/Models/IdentifiableArticleTag.cs similarity index 91% rename from src/Examples/JsonApiDotNetCoreExample/Models/IdentifiableArticleTag.cs rename to test/UnitTests/ResourceHooks/Models/IdentifiableArticleTag.cs index d8cbab1366..452e6767a9 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/IdentifiableArticleTag.cs +++ b/test/UnitTests/ResourceHooks/Models/IdentifiableArticleTag.cs @@ -2,7 +2,7 @@ using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; -namespace JsonApiDotNetCoreExample.Models +namespace UnitTests.ResourceHooks.Models { [UsedImplicitly(ImplicitUseTargetFlags.Members)] public sealed class IdentifiableArticleTag : Identifiable diff --git a/test/UnitTests/ResourceHooks/Models/Passport.cs b/test/UnitTests/ResourceHooks/Models/Passport.cs new file mode 100644 index 0000000000..ca001feb66 --- /dev/null +++ b/test/UnitTests/ResourceHooks/Models/Passport.cs @@ -0,0 +1,13 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace UnitTests.ResourceHooks.Models +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public sealed class Passport : Identifiable + { + [HasOne] + public Person Person { get; set; } + } +} diff --git a/test/UnitTests/ResourceHooks/Models/Person.cs b/test/UnitTests/ResourceHooks/Models/Person.cs new file mode 100644 index 0000000000..55ee5ea8ae --- /dev/null +++ b/test/UnitTests/ResourceHooks/Models/Person.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace UnitTests.ResourceHooks.Models +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public sealed class Person : Identifiable + { + [Attr] + public string Name { get; set; } + + [HasMany] + public ISet TodoItems { get; set; } + + [HasMany] + public ISet AssignedTodoItems { get; set; } + + [HasOne] + public TodoItem OneToOneTodoItem { get; set; } + + [HasOne] + public TodoItem StakeholderTodoItem { get; set; } + + [HasOne] + public Passport Passport { get; set; } + } +} diff --git a/test/UnitTests/ResourceHooks/Models/Tag.cs b/test/UnitTests/ResourceHooks/Models/Tag.cs new file mode 100644 index 0000000000..f56e084a23 --- /dev/null +++ b/test/UnitTests/ResourceHooks/Models/Tag.cs @@ -0,0 +1,13 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace UnitTests.ResourceHooks.Models +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public sealed class Tag : Identifiable + { + [Attr] + public string Name { get; set; } + } +} diff --git a/test/UnitTests/ResourceHooks/Models/TodoItem.cs b/test/UnitTests/ResourceHooks/Models/TodoItem.cs new file mode 100644 index 0000000000..0b7764bff6 --- /dev/null +++ b/test/UnitTests/ResourceHooks/Models/TodoItem.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace UnitTests.ResourceHooks.Models +{ + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public sealed class TodoItem : Identifiable + { + [Attr] + public string Description { get; set; } + + [HasOne] + public Person Owner { get; set; } + + [HasOne] + public Person Assignee { get; set; } + + [HasOne] + public Person OneToOnePerson { get; set; } + + [HasMany] + public ISet Stakeholders { get; set; } + + // cyclical to-many structure + [HasOne] + public TodoItem ParentTodo { get; set; } + + [HasMany] + public IList ChildTodoItems { get; set; } + } +}