diff --git a/benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs b/benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs index a2487052d8..2dff692a31 100644 --- a/benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs +++ b/benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs @@ -58,7 +58,7 @@ public JsonApideserializer_Benchmarks() { public object DeserializeSimpleObject() => _jsonApideserializer.Deserialize(Content); private class SimpleType : Identifiable { - [Attr("name")] + [Attr] public string Name { get; set; } } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/CamelCasedModelsController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/CamelCasedModelsController.cs index ee98b7f23d..01db4c2720 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/CamelCasedModelsController.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/CamelCasedModelsController.cs @@ -6,11 +6,11 @@ namespace JsonApiDotNetCoreExample.Controllers { - public class CamelCasedModelsController : JsonApiController + public class KebabCasedModelsController : JsonApiController { - public CamelCasedModelsController( + public KebabCasedModelsController( IJsonApiOptions jsonApiOptions, - IResourceService resourceService, + IResourceService resourceService, ILoggerFactory loggerFactory) : base(jsonApiOptions, resourceService, loggerFactory) { } diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs index c4913689e4..19e16c26ea 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs @@ -10,7 +10,7 @@ namespace JsonApiDotNetCoreExample.Controllers { - [DisableRoutingConvention, Route("custom/route/todo-items")] + [DisableRoutingConvention, Route("custom/route/todoItems")] public class TodoItemsCustomController : CustomJsonApiController { public TodoItemsCustomController( diff --git a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs index 9411f48a4f..17815f9778 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs @@ -9,7 +9,7 @@ public class AppDbContext : DbContext public DbSet Passports { get; set; } public DbSet People { get; set; } public DbSet TodoItemCollections { get; set; } - public DbSet CamelCasedModels { get; set; } + public DbSet KebabCasedModels { get; set; } public DbSet
Articles { get; set; } public DbSet AuthorDifferentDbContextName { get; set; } public DbSet NonJsonApiResources { get; set; } @@ -46,18 +46,18 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasKey(bc => new { bc.ArticleId, bc.TagId }); modelBuilder.Entity() - .HasOne(t => t.StakeHolderTodo) + .HasOne(t => t.StakeHolderTodoItem) .WithMany(t => t.StakeHolders) - .HasForeignKey(t => t.StakeHolderTodoId) + .HasForeignKey(t => t.StakeHolderTodoItemId) .OnDelete(DeleteBehavior.Cascade); modelBuilder.Entity() - .HasOne(t => t.DependentTodoItem); + .HasOne(t => t.DependentOnTodo); modelBuilder.Entity() - .HasMany(t => t.ChildrenTodoItems) - .WithOne(t => t.ParentTodoItem) - .HasForeignKey(t => t.ParentTodoItemId); + .HasMany(t => t.ChildrenTodos) + .WithOne(t => t.ParentTodo) + .HasForeignKey(t => t.ParentTodoId); modelBuilder.Entity() .HasOne(p => p.Person) @@ -66,14 +66,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.SetNull); modelBuilder.Entity() - .HasOne(p => p.ToOnePerson) - .WithOne(p => p.ToOneTodoItem) - .HasForeignKey(p => p.ToOnePersonId); + .HasOne(p => p.OneToOnePerson) + .WithOne(p => p.OneToOneTodoItem) + .HasForeignKey(p => p.OneToOnePersonId); modelBuilder.Entity() - .HasOne(p => p.ToOneTodoItem) - .WithOne(p => p.ToOnePerson) - .HasForeignKey(p => p.ToOnePersonId); + .HasOne(p => p.OneToOneTodoItem) + .WithOne(p => p.OneToOnePerson) + .HasForeignKey(p => p.OneToOnePersonId); } } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Article.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Article.cs index 6b4648e8d2..d8fd68c886 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/Article.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/Article.cs @@ -6,10 +6,10 @@ namespace JsonApiDotNetCoreExample.Models { public class Article : Identifiable { - [Attr("name")] + [Attr] public string Name { get; set; } - [HasOne("author")] + [HasOne] public Author Author { get; set; } public int AuthorId { get; set; } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/ArticleTag.cs b/src/Examples/JsonApiDotNetCoreExample/Models/ArticleTag.cs index 8b180cc203..22a63459c7 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/ArticleTag.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/ArticleTag.cs @@ -15,11 +15,11 @@ public class ArticleTag public class IdentifiableArticleTag : Identifiable { public int ArticleId { get; set; } - [HasOne("article")] + [HasOne] public Article Article { get; set; } public int TagId { get; set; } - [HasOne("Tag")] + [HasOne] public Tag Tag { get; set; } public string SomeMetaData { get; set; } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Author.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Author.cs index 246118a53b..fce4e7f9c3 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/Author.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/Author.cs @@ -5,10 +5,10 @@ namespace JsonApiDotNetCoreExample.Models { public class Author : Identifiable { - [Attr("name")] + [Attr] public string Name { get; set; } - [HasMany("articles")] + [HasMany] public List
Articles { get; set; } } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/CamelCasedModel.cs b/src/Examples/JsonApiDotNetCoreExample/Models/KebabCasedModel.cs similarity index 55% rename from src/Examples/JsonApiDotNetCoreExample/Models/CamelCasedModel.cs rename to src/Examples/JsonApiDotNetCoreExample/Models/KebabCasedModel.cs index 43d5a43272..ad36d928f3 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/CamelCasedModel.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/KebabCasedModel.cs @@ -2,10 +2,9 @@ namespace JsonApiDotNetCoreExample.Models { - [Resource("camelCasedModels")] - public class CamelCasedModel : Identifiable + public class KebabCasedModel : Identifiable { - [Attr("compoundAttr")] + [Attr] public string CompoundAttr { get; set; } } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Passport.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Passport.cs index ebcfb8b09f..8775ecbab5 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/Passport.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/Passport.cs @@ -5,9 +5,9 @@ namespace JsonApiDotNetCoreExample.Models public class Passport : Identifiable { public virtual int? SocialSecurityNumber { get; set; } - public virtual bool IsLocked { get; set; } + public virtual bool IsLocked { get; set; } - [HasOne("person")] + [HasOne] public virtual Person Person { get; set; } } } \ No newline at end of file diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs index 3e18bb5feb..c5182aeb9d 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs @@ -6,7 +6,7 @@ namespace JsonApiDotNetCoreExample.Models { public class PersonRole : Identifiable { - [HasOne("person")] + [HasOne] public Person Person { get; set; } } @@ -14,43 +14,40 @@ public class Person : Identifiable, IIsLockable { public bool IsLocked { get; set; } - [Attr("first-name")] + [Attr] public string FirstName { get; set; } - [Attr("last-name")] + [Attr] public string LastName { get; set; } - [Attr("age")] + [Attr] public int Age { get; set; } - [HasMany("todo-items")] + [HasMany] public virtual List TodoItems { get; set; } - [HasMany("assigned-todo-items")] + [HasMany] public virtual List AssignedTodoItems { get; set; } - [HasMany("todo-collections")] - public virtual List TodoItemCollections { get; set; } + [HasMany] + public virtual List todoCollections { get; set; } - [HasOne("role")] + [HasOne] public virtual PersonRole Role { get; set; } public int? PersonRoleId { get; set; } - [HasOne("one-to-one-todo-item")] - public virtual TodoItem ToOneTodoItem { get; set; } + [HasOne] + public virtual TodoItem OneToOneTodoItem { get; set; } + [HasOne] + public virtual TodoItem StakeHolderTodoItem { get; set; } + public virtual int? StakeHolderTodoItemId { get; set; } - [HasOne("stake-holder-todo-item")] - public virtual TodoItem StakeHolderTodo { get; set; } - public virtual int? StakeHolderTodoId { get; set; } - - [HasOne("unincludeable-item", links: Link.All, canInclude: false)] + [HasOne(links: Link.All, canInclude: false)] public virtual TodoItem UnIncludeableItem { get; set; } - public int? PassportId { get; set; } - - [HasOne("passport")] + [HasOne] public virtual Passport Passport { get; set; } - + public int? PassportId { get; set; } } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs index 4576595d91..a8a88c0cda 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs @@ -13,66 +13,60 @@ public TodoItem() public bool IsLocked { get; set; } - [Attr("description")] + [Attr] public string Description { get; set; } - [Attr("ordinal")] + [Attr] public long Ordinal { get; set; } - [Attr("guid-property")] + [Attr] public Guid GuidProperty { get; set; } - [Attr("created-date")] + [Attr] public DateTime CreatedDate { get; set; } - [Attr("achieved-date", isFilterable: false, isSortable: false)] + [Attr(isFilterable: false, isSortable: false)] public DateTime? AchievedDate { get; set; } - [Attr("updated-date")] + [Attr] public DateTime? UpdatedDate { get; set; } - [Attr("calculated-value", isImmutable: true)] - public string CalculatedValue - { - get => "joe"; - } + [Attr(isImmutable: true)] + public string CalculatedValue { get => "calculated"; } - [Attr("offset-date")] + [Attr] public DateTimeOffset? OffsetDate { get; set; } public int? OwnerId { get; set; } public int? AssigneeId { get; set; } public Guid? CollectionId { get; set; } - [HasOne("owner")] + [HasOne] public virtual Person Owner { get; set; } - [HasOne("assignee")] + [HasOne] public virtual Person Assignee { get; set; } - [HasOne("one-to-one-person")] - public virtual Person ToOnePerson { get; set; } - public virtual int? ToOnePersonId { get; set; } - + [HasOne] + public virtual Person OneToOnePerson { get; set; } + public virtual int? OneToOnePersonId { get; set; } - [HasMany("stake-holders")] + [HasMany] public virtual List StakeHolders { get; set; } - [HasOne("collection")] + [HasOne] public virtual TodoItemCollection Collection { get; set; } - // cyclical to-one structure - public virtual int? DependentTodoItemId { get; set; } - [HasOne("dependent-on-todo")] - public virtual TodoItem DependentTodoItem { get; set; } - + public virtual int? DependentOnTodoId { get; set; } + [HasOne] + public virtual TodoItem DependentOnTodo { get; set; } // cyclical to-many structure - public virtual int? ParentTodoItemId {get; set;} - [HasOne("parent-todo")] - public virtual TodoItem ParentTodoItem { get; set; } - [HasMany("children-todos")] - public virtual List ChildrenTodoItems { get; set; } + public virtual int? ParentTodoId {get; set;} + [HasOne] + public virtual TodoItem ParentTodo { get; set; } + [HasMany] + public virtual List ChildrenTodos { get; set; } } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemCollection.cs b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemCollection.cs index fa17134680..2a251581d4 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemCollection.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemCollection.cs @@ -4,16 +4,16 @@ namespace JsonApiDotNetCoreExample.Models { - [Resource("todo-collections")] + [Resource("todoCollections")] public class TodoItemCollection : Identifiable { - [Attr("name")] + [Attr] public string Name { get; set; } - [HasMany("todo-items")] + [HasMany] public virtual List TodoItems { get; set; } - [HasOne("owner")] + [HasOne] public virtual Person Owner { get; set; } public int? OwnerId { get; set; } diff --git a/src/Examples/JsonApiDotNetCoreExample/Resources/UserResource.cs b/src/Examples/JsonApiDotNetCoreExample/Resources/UserResource.cs index 9aa8d8397f..aa4552cae6 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Resources/UserResource.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Resources/UserResource.cs @@ -18,7 +18,7 @@ public override QueryFilters GetQueryFilters() { return new QueryFilters { - { "first-character", (users, queryFilter) => FirstCharacterFilter(users, queryFilter) } + { "firstCharacter", (users, queryFilter) => FirstCharacterFilter(users, queryFilter) } }; } diff --git a/src/Examples/JsonApiDotNetCoreExample/Startups/ClientGeneratedIdsStartup.cs b/src/Examples/JsonApiDotNetCoreExample/Startups/ClientGeneratedIdsStartup.cs deleted file mode 100644 index 665096060c..0000000000 --- a/src/Examples/JsonApiDotNetCoreExample/Startups/ClientGeneratedIdsStartup.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using JsonApiDotNetCoreExample.Data; -using Microsoft.EntityFrameworkCore; -using JsonApiDotNetCore.Extensions; -using System.Reflection; - -namespace JsonApiDotNetCoreExample -{ - /// - /// This should be in JsonApiDotNetCoreExampleTests project but changes in .net core 3.0 - /// do no longer allow that. See https://github.com/aspnet/AspNetCore/issues/15373. - /// - public class ClientGeneratedIdsStartup : Startup - { - public ClientGeneratedIdsStartup(IWebHostEnvironment env) - : base(env) - { } - - public override void ConfigureServices(IServiceCollection services) - { - var loggerFactory = new LoggerFactory(); - var mvcBuilder = services.AddMvcCore(); - services - .AddSingleton(loggerFactory) - .AddLogging(builder => - { - builder.AddConsole(); - }) - .AddDbContext(options => options.UseNpgsql(GetDbConnectionString()), ServiceLifetime.Transient) - .AddJsonApi(options => { - options.Namespace = "api/v1"; - options.DefaultPageSize = 5; - options.IncludeTotalRecordCount = true; - options.EnableResourceHooks = true; - options.LoadDatabaseValues = true; - options.AllowClientGeneratedIds = true; - }, - discovery => discovery.AddAssembly(Assembly.Load(nameof(JsonApiDotNetCoreExample))), - mvcBuilder: mvcBuilder); - } - } -} \ No newline at end of file diff --git a/src/Examples/JsonApiDotNetCoreExample/Startups/MetaStartup.cs b/src/Examples/JsonApiDotNetCoreExample/Startups/MetaStartup.cs index 32accb087a..6cc0dd1e81 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Startups/MetaStartup.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Startups/MetaStartup.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using JsonApiDotNetCore.Services; using System.Collections.Generic; +using Microsoft.Extensions.Configuration; namespace JsonApiDotNetCoreExample { @@ -11,9 +12,7 @@ namespace JsonApiDotNetCoreExample /// public class MetaStartup : Startup { - public MetaStartup(IWebHostEnvironment env) - : base (env) - { } + public MetaStartup(IWebHostEnvironment env) : base(env) { } public override void ConfigureServices(IServiceCollection services) { diff --git a/src/Examples/JsonApiDotNetCoreExample/Startups/NoDefaultPageSizeStartup.cs b/src/Examples/JsonApiDotNetCoreExample/Startups/NoDefaultPageSizeStartup.cs index f0ee0a6acb..489385f76d 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Startups/NoDefaultPageSizeStartup.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Startups/NoDefaultPageSizeStartup.cs @@ -14,9 +14,7 @@ namespace JsonApiDotNetCoreExample /// public class NoDefaultPageSizeStartup : Startup { - public NoDefaultPageSizeStartup(IWebHostEnvironment env) - : base(env) - { } + public NoDefaultPageSizeStartup(IWebHostEnvironment env) : base(env) { } public override void ConfigureServices(IServiceCollection services) { @@ -32,7 +30,6 @@ public override void ConfigureServices(IServiceCollection services) .AddJsonApi(options => { options.Namespace = "api/v1"; options.IncludeTotalRecordCount = true; - options.EnableResourceHooks = true; options.LoadDatabaseValues = true; options.AllowClientGeneratedIds = true; }, diff --git a/src/Examples/JsonApiDotNetCoreExample/Startups/Startup.cs b/src/Examples/JsonApiDotNetCoreExample/Startups/Startup.cs index 387287a243..a2d11f06f5 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Startups/Startup.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Startups/Startup.cs @@ -7,7 +7,6 @@ using Microsoft.EntityFrameworkCore; using JsonApiDotNetCore.Extensions; using System; -using Microsoft.Extensions.Logging.Console; using Microsoft.Extensions.Logging.Debug; namespace JsonApiDotNetCoreExample @@ -26,7 +25,6 @@ public Startup(IWebHostEnvironment env) Config = builder.Build(); } - public virtual void ConfigureServices(IServiceCollection services) { var loggerFactory = new LoggerFactory(); @@ -48,19 +46,17 @@ public virtual void ConfigureServices(IServiceCollection services) options.Namespace = "api/v1"; options.DefaultPageSize = 5; options.IncludeTotalRecordCount = true; - options.EnableResourceHooks = true; options.LoadDatabaseValues = true; }, discovery => discovery.AddCurrentAssembly()); - services.AddClientSerialization(); + // once all tests have been moved to WebApplicationFactory format we can get rid of this line below + services.AddClientSerialization(); } public virtual void Configure( IApplicationBuilder app, - ILoggerFactory loggerFactory, AppDbContext context) { - context.Database.EnsureCreated(); app.UseJsonApi(); } diff --git a/src/Examples/NoEntityFrameworkExample/Models/TodoItem.cs b/src/Examples/NoEntityFrameworkExample/Models/TodoItem.cs index b1021d18f5..d380b0d018 100644 --- a/src/Examples/NoEntityFrameworkExample/Models/TodoItem.cs +++ b/src/Examples/NoEntityFrameworkExample/Models/TodoItem.cs @@ -12,25 +12,25 @@ public TodoItem() public bool IsLocked { get; set; } - [Attr("description")] + [Attr] public string Description { get; set; } - [Attr("ordinal")] + [Attr] public long Ordinal { get; set; } - [Attr("guid-property")] + [Attr] public Guid GuidProperty { get; set; } - [Attr("created-date")] + [Attr] public DateTime CreatedDate { get; set; } - [Attr("achieved-date", isFilterable: false, isSortable: false)] + [Attr(isFilterable: false, isSortable: false)] public DateTime? AchievedDate { get; set; } - [Attr("updated-date")] + [Attr] public DateTime? UpdatedDate { get; set; } - [Attr("offset-date")] + [Attr] public DateTimeOffset? OffsetDate { get; set; } } } diff --git a/src/Examples/NoEntityFrameworkExample/Startup.cs b/src/Examples/NoEntityFrameworkExample/Startup.cs index 1d6aef07c5..f21f59c7ba 100644 --- a/src/Examples/NoEntityFrameworkExample/Startup.cs +++ b/src/Examples/NoEntityFrameworkExample/Startup.cs @@ -37,7 +37,7 @@ public virtual void ConfigureServices(IServiceCollection services) builder.AddConsole(); }).AddJsonApi( options => options.Namespace = "api/v1", - resources: resources => resources.AddResource("todo-items"), + resources: resources => resources.AddResource("todoItems"), mvcBuilder: mvcBuilder ); services.AddScoped, TodoItemService>(); diff --git a/src/Examples/ReportsExample/Models/Report.cs b/src/Examples/ReportsExample/Models/Report.cs index 39c07aca3d..241221cdaa 100644 --- a/src/Examples/ReportsExample/Models/Report.cs +++ b/src/Examples/ReportsExample/Models/Report.cs @@ -2,10 +2,10 @@ public class Report : Identifiable { - [Attr("title")] + [Attr] public string Title { get; set; } - [Attr("complex-type")] + [Attr] public ComplexType ComplexType { get; set; } } diff --git a/src/Examples/ReportsExample/Startup.cs b/src/Examples/ReportsExample/Startup.cs index 480f2a0f62..bafa6f7689 100644 --- a/src/Examples/ReportsExample/Startup.cs +++ b/src/Examples/ReportsExample/Startup.cs @@ -1,9 +1,7 @@ using JsonApiDotNetCore.Extensions; -using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; namespace ReportsExample { diff --git a/src/JsonApiDotNetCore/Builders/JsonApiApplicationBuilder.cs b/src/JsonApiDotNetCore/Builders/JsonApiApplicationBuilder.cs index 0d5bf08e12..d7b070f33a 100644 --- a/src/JsonApiDotNetCore/Builders/JsonApiApplicationBuilder.cs +++ b/src/JsonApiDotNetCore/Builders/JsonApiApplicationBuilder.cs @@ -78,7 +78,7 @@ public void ConfigureMvc() } /// - /// Executes autodiscovery of JADNC services. + /// Executes auto-discovery of JADNC services. /// public void AutoDiscover(Action autoDiscover) { @@ -206,7 +206,7 @@ private void AddServerSerialization() private void RegisterJsonApiStartupServices() { _services.AddSingleton(JsonApiOptions); - _services.TryAddSingleton(new KebabCaseFormatter()); + _services.TryAddSingleton(new CamelCaseFormatter()); _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(sp => new ServiceDiscoveryFacade(_services, sp.GetRequiredService())); diff --git a/src/JsonApiDotNetCore/Builders/ResourceGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ResourceGraphBuilder.cs index 05d4a6a8c5..8b0ad0e348 100644 --- a/src/JsonApiDotNetCore/Builders/ResourceGraphBuilder.cs +++ b/src/JsonApiDotNetCore/Builders/ResourceGraphBuilder.cs @@ -18,7 +18,7 @@ public class ResourceGraphBuilder : IResourceGraphBuilder { private List _resources { get; set; } = new List(); private List _validationResults { get; set; } = new List(); - private IResourceNameFormatter _formatter { get; set; } = new KebabCaseFormatter(); + private IResourceNameFormatter _formatter { get; set; } = new CamelCaseFormatter(); public ResourceGraphBuilder() { } diff --git a/src/JsonApiDotNetCore/Data/IResourceReadRepository.cs b/src/JsonApiDotNetCore/Data/IResourceReadRepository.cs index d2d8946d2d..63867c6bea 100644 --- a/src/JsonApiDotNetCore/Data/IResourceReadRepository.cs +++ b/src/JsonApiDotNetCore/Data/IResourceReadRepository.cs @@ -32,7 +32,7 @@ public interface IResourceReadRepository /// /// /// - /// _todoItemsRepository.GetAndIncludeAsync(1, "achieved-date"); + /// _todoItemsRepository.GetAndIncludeAsync(1, "achievedDate"); /// /// IQueryable Include(IQueryable entities, IEnumerable inclusionChain); diff --git a/src/JsonApiDotNetCore/Graph/ResourceNameFormatters/CamelCaseFormatter.cs b/src/JsonApiDotNetCore/Graph/ResourceNameFormatters/CamelCaseFormatter.cs index 7e9a4d1e27..17a94cdcde 100644 --- a/src/JsonApiDotNetCore/Graph/ResourceNameFormatters/CamelCaseFormatter.cs +++ b/src/JsonApiDotNetCore/Graph/ResourceNameFormatters/CamelCaseFormatter.cs @@ -3,7 +3,7 @@ namespace JsonApiDotNetCore.Graph { /// - /// Uses kebab-case as formatting options in the route and request/response body. + /// Uses camelCase as formatting options in the route and request/response body. /// /// /// diff --git a/src/JsonApiDotNetCore/Graph/ResourceNameFormatters/KebabCaseFormatter.cs b/src/JsonApiDotNetCore/Graph/ResourceNameFormatters/KebabCaseFormatter.cs index 22144a4769..42a48a8572 100644 --- a/src/JsonApiDotNetCore/Graph/ResourceNameFormatters/KebabCaseFormatter.cs +++ b/src/JsonApiDotNetCore/Graph/ResourceNameFormatters/KebabCaseFormatter.cs @@ -8,7 +8,7 @@ namespace JsonApiDotNetCore.Graph /// /// /// _default.FormatResourceName(typeof(TodoItem)).Dump(); - /// // > "todo-items" + /// // > "todoItems" /// /// /// @@ -25,7 +25,7 @@ namespace JsonApiDotNetCore.Graph /// /// /// _default.ApplyCasingConvention("TodoItems"); - /// // > "todo-items" + /// // > "todoItems" /// /// _default.ApplyCasingConvention("TodoItem"); /// // > "todo-item" diff --git a/src/JsonApiDotNetCore/Graph/ResourceNameFormatters/ResourceNameFormatterBase.cs b/src/JsonApiDotNetCore/Graph/ResourceNameFormatters/ResourceNameFormatterBase.cs index 319824041d..6c6fc86f36 100644 --- a/src/JsonApiDotNetCore/Graph/ResourceNameFormatters/ResourceNameFormatterBase.cs +++ b/src/JsonApiDotNetCore/Graph/ResourceNameFormatters/ResourceNameFormatterBase.cs @@ -35,7 +35,7 @@ public string FormatResourceName(Type type) /// /// Uses the internal PropertyInfo to determine the external resource name. - /// By default the name will be formatted to kebab-case. + /// By default the name will be formatted to camelCase. /// public string FormatPropertyName(PropertyInfo property) => ApplyCasingConvention(property.Name); } diff --git a/src/JsonApiDotNetCore/Graph/ServiceDiscoveryFacade.cs b/src/JsonApiDotNetCore/Graph/ServiceDiscoveryFacade.cs index 074914faa3..ac5cdd79fa 100644 --- a/src/JsonApiDotNetCore/Graph/ServiceDiscoveryFacade.cs +++ b/src/JsonApiDotNetCore/Graph/ServiceDiscoveryFacade.cs @@ -140,13 +140,9 @@ private void RegisterResourceDefinition(Assembly assembly, ResourceDescriptor id private void AddResourceToGraph(ResourceDescriptor identifiable) { - var resourceName = FormatResourceName(identifiable.ResourceType); - _resourceGraphBuilder.AddResource(identifiable.ResourceType, identifiable.IdType, resourceName); + _resourceGraphBuilder.AddResource(identifiable.ResourceType, identifiable.IdType); } - private string FormatResourceName(Type resourceType) - => new KebabCaseFormatter().FormatResourceName(resourceType); - /// /// Add implementations to container. /// diff --git a/src/JsonApiDotNetCore/Internal/DefaultRoutingConvention.cs b/src/JsonApiDotNetCore/Internal/DefaultRoutingConvention.cs index f694d95010..ca84b60a47 100644 --- a/src/JsonApiDotNetCore/Internal/DefaultRoutingConvention.cs +++ b/src/JsonApiDotNetCore/Internal/DefaultRoutingConvention.cs @@ -15,23 +15,23 @@ namespace JsonApiDotNetCore.Internal /// /// The default routing convention registers the name of the resource as the route /// using the that is registered. The default for this is - /// a kebab-case formatter. If the controller directly inherits from JsonApiMixin and there is no + /// a camelCase formatter. If the controller directly inherits from JsonApiMixin and there is no /// resource directly associated, it used the name of the controller instead of the name of the type. /// /// /// public class SomeResourceController: JsonApiController{SomeResource} { } - /// // => /some-resources/relationship/related-resource + /// // => /someResources/relationship/relatedResource /// /// public class RandomNameController{SomeResource} : JsonApiController{SomeResource} { } - /// // => /some-resources/relationship/related-resource + /// // => /someResources/relationship/relatedResource /// - /// // when using the camelCase formatter: + /// // when using the kebab-case formatter: /// public class SomeResourceController{SomeResource} : JsonApiController{SomeResource} { } - /// // => /someResources/relationship/relatedResource + /// // => /some-resources/relationship/related-resource /// - /// // when inheriting from JsonApiMixin formatter: + /// // when inheriting from JsonApiMixin controller: /// public class SomeVeryCustomController{SomeResource} : JsonApiMixin { } - /// // => /some-very-customs/relationship/related-resource + /// // => /someVeryCustoms/relationship/relatedResource /// public class DefaultRoutingConvention : IJsonApiRoutingConvention, IControllerResourceMapping { @@ -58,7 +58,7 @@ public void Apply(ApplicationModel application) foreach (var controller in application.Controllers) { var resourceType = GetResourceTypeFromController(controller.ControllerType); - + if (resourceType != null) _registeredResources.Add(controller.ControllerName, resourceType); diff --git a/src/JsonApiDotNetCore/Models/Annotation/AttrAttribute.cs b/src/JsonApiDotNetCore/Models/Annotation/AttrAttribute.cs index da3a9d4631..4c44acf8b6 100644 --- a/src/JsonApiDotNetCore/Models/Annotation/AttrAttribute.cs +++ b/src/JsonApiDotNetCore/Models/Annotation/AttrAttribute.cs @@ -20,7 +20,7 @@ public class AttrAttribute : Attribute, IResourceField /// /// public class Author : Identifiable /// { - /// [Attr("name")] + /// [Attr] /// public string Name { get; set; } /// } /// diff --git a/src/JsonApiDotNetCore/QueryParameterServices/SparseFieldsService.cs b/src/JsonApiDotNetCore/QueryParameterServices/SparseFieldsService.cs index 83b5fcdff3..28b9312962 100644 --- a/src/JsonApiDotNetCore/QueryParameterServices/SparseFieldsService.cs +++ b/src/JsonApiDotNetCore/QueryParameterServices/SparseFieldsService.cs @@ -79,7 +79,7 @@ public virtual void Parse(KeyValuePair queryParameter) } /// - /// Registers field selection queries of the form articles?fields[author]=first-name + /// Registers field selection queries of the form articles?fields[author]=firstName /// private void RegisterRelatedResourceField(string field, RelationshipAttribute relationship) { diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs deleted file mode 100644 index a9b827ebc5..0000000000 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs +++ /dev/null @@ -1,171 +0,0 @@ -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading.Tasks; -using Bogus; -using JsonApiDotNetCoreExample; -using JsonApiDotNetCoreExample.Data; -using JsonApiDotNetCoreExample.Models; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Newtonsoft.Json; -using Xunit; - -namespace JsonApiDotNetCoreExampleTests.Acceptance -{ - [Collection("WebHostCollection")] - public class CamelCasedModelsControllerTests - { - private TestFixture _fixture; - private AppDbContext _context; - private Faker _faker; - - public CamelCasedModelsControllerTests(TestFixture fixture) - { - _fixture = fixture; - _context = fixture.GetService(); - _faker = new Faker() - .RuleFor(m => m.CompoundAttr, f => f.Lorem.Sentence()); - } - - [Fact] - public async Task Can_Get_CamelCasedModels() - { - // Arrange - var model = _faker.Generate(); - _context.CamelCasedModels.Add(model); - _context.SaveChanges(); - - var httpMethod = new HttpMethod("GET"); - var route = "api/v1/camelCasedModels"; - var builder = new WebHostBuilder() - .UseStartup(); - var server = new TestServer(builder); - var client = server.CreateClient(); - var request = new HttpRequestMessage(httpMethod, route); - - // Act - var response = await client.SendAsync(request); - var body = await response.Content.ReadAsStringAsync(); - var deserializedBody = _fixture.GetDeserializer().DeserializeList(body).Data; - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotEmpty(deserializedBody); - Assert.True(deserializedBody.Count > 0); - } - - [Fact] - public async Task Can_Get_CamelCasedModels_ById() - { - // Arrange - var model = _faker.Generate(); - _context.CamelCasedModels.Add(model); - _context.SaveChanges(); - - var httpMethod = new HttpMethod("GET"); - var route = $"api/v1/camelCasedModels/{model.Id}"; - var request = new HttpRequestMessage(httpMethod, route); - - // unnecessary, will fix in 4.1 - var builder = new WebHostBuilder() - .UseStartup(); - var server = new TestServer(builder); - var client = server.CreateClient(); - - // Act - var response = await client.SendAsync(request); - var body = await response.Content.ReadAsStringAsync(); - var deserializedBody = _fixture.GetDeserializer().DeserializeSingle(body).Data; - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(deserializedBody); - Assert.Equal(model.Id, deserializedBody.Id); - } - - [Fact] - public async Task Can_Post_CamelCasedModels() - { - // Arrange - var model = _faker.Generate(); - var content = new - { - data = new - { - type = "camelCasedModels", - attributes = new Dictionary() - { - { "compoundAttr", model.CompoundAttr } - } - } - }; - var httpMethod = new HttpMethod("POST"); - var route = $"api/v1/camelCasedModels"; - var builder = new WebHostBuilder() - .UseStartup(); - var server = new TestServer(builder); - var client = server.CreateClient(); - var request = new HttpRequestMessage(httpMethod, route); - request.Content = new StringContent(JsonConvert.SerializeObject(content)); - request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json"); - - // Act - var response = await client.SendAsync(request); - var body = await response.Content.ReadAsStringAsync(); - - // Assert - Assert.Equal(HttpStatusCode.Created, response.StatusCode); - Assert.NotNull(body); - Assert.NotEmpty(body); - - var deserializedBody = _fixture.GetDeserializer().DeserializeSingle(body).Data; - Assert.Equal(model.CompoundAttr, deserializedBody.CompoundAttr); - } - - [Fact] - public async Task RoutingPatch_RouteIsCamelcased_ResponseOKAndCompoundAttrIsAvailable() - { - // Arrange - var model = _faker.Generate(); - _context.CamelCasedModels.Add(model); - _context.SaveChanges(); - - var newModel = _faker.Generate(); - var content = new - { - data = new - { - type = "camelCasedModels", - id = model.Id, - attributes = new Dictionary() - { - { "compoundAttr", newModel.CompoundAttr } - } - } - }; - var httpMethod = HttpMethod.Patch; - var route = $"api/v1/camelCasedModels/{model.Id}"; - var builder = new WebHostBuilder().UseStartup(); - - using var server = new TestServer(builder); - var client = server.CreateClient(); - var request = new HttpRequestMessage(httpMethod, route); - request.Content = new StringContent(JsonConvert.SerializeObject(content)); - request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json"); - - // Act - var response = await client.SendAsync(request); - var body = await response.Content.ReadAsStringAsync(); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotNull(body); - Assert.NotEmpty(body); - - var deserializedBody = _fixture.GetDeserializer().DeserializeSingle(body).Data; - Assert.Equal(newModel.CompoundAttr, deserializedBody.CompoundAttr); - } - } -} diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomControllerTests.cs index 4a23da42ac..4797732c6b 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomControllerTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomControllerTests.cs @@ -59,7 +59,7 @@ public async Task CustomRouteControllers_Uses_Dasherized_Collection_Route() var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/custom/route/todo-items"; + var route = $"/custom/route/todoItems"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -86,7 +86,7 @@ public async Task CustomRouteControllers_Uses_Dasherized_Item_Route() var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/custom/route/todo-items/{todoItem.Id}"; + var route = $"/custom/route/todoItems/{todoItem.Id}"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -112,7 +112,7 @@ public async Task CustomRouteControllers_Creates_Proper_Relationship_Links() var builder = new WebHostBuilder().UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/custom/route/todo-items/{todoItem.Id}"; + var route = $"/custom/route/todoItems/{todoItem.Id}"; var server = new TestServer(builder); var client = server.CreateClient(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs index 9081dac41e..baeb5deef7 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs @@ -84,7 +84,7 @@ public async Task CheckNullBehaviorCombination(bool? omitNullValuedAttributes, b var queryString = allowClientOverride.HasValue ? $"&omitNull={clientOverride}" : ""; - var route = $"/api/v1/todo-items/{_todoItem.Id}?include=owner{queryString}"; + var route = $"/api/v1/todoItems/{_todoItem.Id}?include=owner{queryString}"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -94,7 +94,7 @@ public async Task CheckNullBehaviorCombination(bool? omitNullValuedAttributes, b // Assert: does response contain a null valued attribute? Assert.Equal(omitsNulls, !deserializeBody.SingleData.Attributes.ContainsKey("description")); - Assert.Equal(omitsNulls, !deserializeBody.Included[0].Attributes.ContainsKey("last-name")); + Assert.Equal(omitsNulls, !deserializeBody.Included[0].Attributes.ContainsKey("lastName")); } } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/KebabCaseFormatterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/KebabCaseFormatterTests.cs new file mode 100644 index 0000000000..842e533d36 --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/KebabCaseFormatterTests.cs @@ -0,0 +1,90 @@ +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Bogus; +using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.Acceptance.Spec; +using Xunit; + +namespace JsonApiDotNetCoreExampleTests.Acceptance +{ + public class KebabCaseFormatterTests : FunctionalTestCollection + { + private readonly Faker _faker; + + public KebabCaseFormatterTests(KebabCaseApplicationFactory factory) : base(factory) + { + _faker = new Faker().RuleFor(m => m.CompoundAttr, f => f.Lorem.Sentence()); + } + + [Fact] + public async Task KebabCaseFormatter_GetAll_IsReturned() + { + /// Arrange + var model = _faker.Generate(); + _dbContext.KebabCasedModels.Add(model); + _dbContext.SaveChanges(); + + /// Act + var (body, response) = await Get("api/v1/kebab-cased-models"); + + /// Assert + AssertEqualStatusCode(HttpStatusCode.OK, response); + var responseItem = _deserializer.DeserializeList(body).Data; + Assert.True(responseItem.Count > 0); + } + + [Fact] + public async Task KebabCaseFormatter_GetSingle_IsReturned() + { + /// Arrange + var model = _faker.Generate(); + _dbContext.KebabCasedModels.Add(model); + _dbContext.SaveChanges(); + + /// Act + var (body, response) = await Get($"api/v1/kebab-cased-models/{model.Id}"); + + /// Assert + AssertEqualStatusCode(HttpStatusCode.OK, response); + var responseItem = _deserializer.DeserializeSingle(body).Data; + Assert.Equal(model.Id, responseItem.Id); + } + + [Fact] + public async Task KebabCaseFormatter_Create_IsCreated() + { + /// Arrange + var model = _faker.Generate(); + var serializer = GetSerializer(kcm => new { kcm.CompoundAttr }); + + /// Act + var (body, response) = await Post($"api/v1/kebab-cased-models", serializer.Serialize(model)); + + /// Assert + AssertEqualStatusCode(HttpStatusCode.Created, response); + var responseItem = _deserializer.DeserializeSingle(body).Data; + var x = _dbContext.KebabCasedModels.Where(kcm => kcm.Id.Equals(responseItem.Id)).Single(); + Assert.Equal(model.CompoundAttr, responseItem.CompoundAttr); + } + + [Fact] + public async Task KebabCaseFormatter_Update_IsUpdated() + { + /// Arrange + var model = _faker.Generate(); + _dbContext.KebabCasedModels.Add(model); + _dbContext.SaveChanges(); + model.CompoundAttr = _faker.Generate().CompoundAttr; + var serializer = GetSerializer(kcm => new { kcm.CompoundAttr }); + + /// Act + var (body, response) = await Patch($"api/v1/kebab-cased-models/{model.Id}", serializer.Serialize(model)); + + /// Assert + AssertEqualStatusCode(HttpStatusCode.OK, response); + var responseItem = _deserializer.DeserializeSingle(body).Data; + Assert.Equal(model.CompoundAttr, responseItem.CompoundAttr); + } + } +} diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/ResourceDefinitions/QueryFiltersTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/ResourceDefinitions/QueryFiltersTests.cs index 6c3c23b125..1f4c426b55 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/ResourceDefinitions/QueryFiltersTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/ResourceDefinitions/QueryFiltersTests.cs @@ -38,7 +38,7 @@ public async Task FiltersWithCustomQueryFiltersEquals() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/users?filter[first-character]=eq:{firstUsernameCharacter}"; + var route = $"/api/v1/users?filter[firstCharacter]=eq:{firstUsernameCharacter}"; var request = new HttpRequestMessage(httpMethod, route); // @TODO - Use fixture @@ -71,7 +71,7 @@ public async Task FiltersWithCustomQueryFiltersLessThan() var median = 'h'; var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/users?filter[first-character]=lt:{median}"; + var route = $"/api/v1/users?filter[firstCharacter]=lt:{median}"; var request = new HttpRequestMessage(httpMethod, route); // @TODO - Use fixture diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/ResourceDefinitions/ResourceDefinitionTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/ResourceDefinitions/ResourceDefinitionTests.cs index a29ece9344..e5a2ba0a8e 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/ResourceDefinitions/ResourceDefinitionTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/ResourceDefinitions/ResourceDefinitionTests.cs @@ -139,7 +139,7 @@ public async Task Can_Update_User_Password() public async Task Unauthorized_TodoItem() { // Arrange - var route = $"/api/v1/todo-items/1337"; + var route = $"/api/v1/todoItems/1337"; var httpMethod = new HttpMethod("GET"); var request = new HttpRequestMessage(httpMethod, route); @@ -452,10 +452,10 @@ public async Task Cascade_Permission_Error__Create_ToMany_Relationship() { data = new { - type = "todo-items", + type = "todoItems", relationships = new Dictionary { - { "stake-holders", new + { "stakeHolders", new { data = new object[] { @@ -470,7 +470,7 @@ public async Task Cascade_Permission_Error__Create_ToMany_Relationship() }; var httpMethod = new HttpMethod("POST"); - var route = $"/api/v1/todo-items"; + var route = $"/api/v1/todoItems"; var request = new HttpRequestMessage(httpMethod, route); string serializedContent = JsonConvert.SerializeObject(content); @@ -503,11 +503,11 @@ public async Task Cascade_Permission_Error__Updating_ToMany_Relationship() { data = new { - type = "todo-items", + type = "todoItems", id = unlockedTodo.Id, relationships = new Dictionary { - { "stake-holders", new + { "stakeHolders", new { data = new object[] { @@ -522,7 +522,7 @@ public async Task Cascade_Permission_Error__Updating_ToMany_Relationship() }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-items/{unlockedTodo.Id}"; + var route = $"/api/v1/todoItems/{unlockedTodo.Id}"; var request = new HttpRequestMessage(httpMethod, route); string serializedContent = JsonConvert.SerializeObject(content); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs index 25fd53c6f3..49472014f1 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs @@ -45,7 +45,7 @@ public async Task Can_Filter_On_Guid_Properties() await context.SaveChangesAsync(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?filter[guid-property]={todoItem.GuidProperty}"; + var route = $"/api/v1/todoItems?filter[guidProperty]={todoItem.GuidProperty}"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -74,7 +74,7 @@ public async Task Can_Filter_On_Related_Attrs() await context.SaveChangesAsync(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?include=owner&filter[owner.first-name]={person.FirstName}"; + var route = $"/api/v1/todoItems?include=owner&filter[owner.firstName]={person.FirstName}"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -93,7 +93,7 @@ public async Task Cannot_Filter_If_Explicitly_Forbidden() { // Arrange var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?include=owner&filter[achieved-date]={DateTime.UtcNow.Date}"; + var route = $"/api/v1/todoItems?include=owner&filter[achievedDate]={DateTime.UtcNow.Date}"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -114,7 +114,7 @@ public async Task Can_Filter_On_Not_Equal_Values() var totalCount = context.TodoItems.Count(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?page[size]={totalCount}&filter[ordinal]=ne:{todoItem.Ordinal}"; + var route = $"/api/v1/todoItems?page[size]={totalCount}&filter[ordinal]=ne:{todoItem.Ordinal}"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -148,7 +148,7 @@ public async Task Can_Filter_On_In_Array_Values() var totalCount = context.TodoItems.Count(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?filter[guid-property]=in:{string.Join(",", guids)}"; + var route = $"/api/v1/todoItems?filter[guidProperty]=in:{string.Join(",", guids)}"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -185,7 +185,7 @@ public async Task Can_Filter_On_Related_In_Array_Values() context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?include=owner&filter[owner.first-name]=in:{string.Join(",", ownerFirstNames)}"; + var route = $"/api/v1/todoItems?include=owner&filter[owner.firstName]=in:{string.Join(",", ownerFirstNames)}"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -200,7 +200,7 @@ public async Task Can_Filter_On_Related_In_Array_Values() Assert.NotNull(included); Assert.NotEmpty(included); foreach (var item in included) - Assert.Contains(item.Attributes["first-name"], ownerFirstNames); + Assert.Contains(item.Attributes["firstName"], ownerFirstNames); } @@ -227,7 +227,7 @@ public async Task Can_Filter_On_Not_In_Array_Values() var totalCount = context.TodoItems.Count(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?page[size]={totalCount}&filter[guid-property]=nin:{string.Join(",", notInGuids)}"; + var route = $"/api/v1/todoItems?page[size]={totalCount}&filter[guidProperty]=nin:{string.Join(",", notInGuids)}"; var request = new HttpRequestMessage(httpMethod, route); // Act diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs index 4b81073a48..6b387fed64 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs @@ -21,7 +21,7 @@ public async Task Cannot_Sort_If_Explicitly_Forbidden() { // Arrange var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?include=owner&sort=achieved-date"; + var route = $"/api/v1/todoItems?include=owner&sort=achievedDate"; var request = new HttpRequestMessage(httpMethod, route); // Act diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/ContentNegotiation.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/ContentNegotiation.cs index 9397af4dce..bccb8ebf83 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/ContentNegotiation.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/ContentNegotiation.cs @@ -25,7 +25,7 @@ public async Task Server_Sends_Correct_ContentType_Header() var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = "/api/v1/todo-items"; + var route = "/api/v1/todoItems"; var server = new TestServer(builder); var client = server.CreateClient(); var request = new HttpRequestMessage(httpMethod, route); @@ -45,7 +45,7 @@ public async Task Server_Responds_415_With_MediaType_Parameters() var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = "/api/v1/todo-items"; + var route = "/api/v1/todoItems"; var server = new TestServer(builder); var client = server.CreateClient(); var request = new HttpRequestMessage(httpMethod, route); @@ -67,7 +67,7 @@ public async Task ServerResponds_406_If_RequestAcceptHeader_Contains_MediaTypePa var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = "/api/v1/todo-items"; + var route = "/api/v1/todoItems"; var server = new TestServer(builder); var client = server.CreateClient(); var acceptHeader = new MediaTypeWithQualityHeaderValue("application/vnd.api+json"); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs index 982dfdd100..51f10bf1d8 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs @@ -6,8 +6,6 @@ using Bogus; using JsonApiDotNetCore.Builders; using JsonApiDotNetCore.Serialization.Client; -using JsonApiDotNetCoreExample; -using JsonApiDotNetCoreExample.Data; using JsonApiDotNetCoreExample.Models; using JsonApiDotNetCoreExampleTests.Helpers.Models; using Microsoft.EntityFrameworkCore; @@ -16,57 +14,50 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec { - - [Collection("WebHostCollection")] - public class CreatingDataTests : EndToEndTest + public class CreatingDataTests : FunctionalTestCollection { private readonly Faker _todoItemFaker; private readonly Faker _personFaker; - public CreatingDataTests(TestFixture fixture) : base(fixture) + public CreatingDataTests(StandardApplicationFactory factory) : base(factory) { - _fixture = fixture; _todoItemFaker = new Faker() - .RuleFor(t => t.Description, f => f.Lorem.Sentence()) - .RuleFor(t => t.Ordinal, f => f.Random.Number()) - .RuleFor(t => t.CreatedDate, f => f.Date.Past()); + .RuleFor(t => t.Description, f => f.Lorem.Sentence()) + .RuleFor(t => t.Ordinal, f => f.Random.Number()) + .RuleFor(t => t.CreatedDate, f => f.Date.Past()); _personFaker = new Faker() .RuleFor(t => t.FirstName, f => f.Name.FirstName()) .RuleFor(t => t.LastName, f => f.Name.LastName()); - } [Fact] public async Task CreateResource_ModelWithEntityFrameworkInHeritance_IsCreated() { // Arrange - var dbContext = PrepareTest(); var serializer = GetSerializer(e => new { e.SecurityLevel, e.Username, e.Password }); var superUser = new SuperUser { SecurityLevel = 1337, Username = "Super", Password = "User" }; // Act - var (body, response) = await Post("/api/v1/super-users", serializer.Serialize(superUser)); + var (body, response) = await Post("/api/v1/superUsers", serializer.Serialize(superUser)); // Assert AssertEqualStatusCode(HttpStatusCode.Created, response); var createdSuperUser = _deserializer.DeserializeSingle(body).Data; - var created = dbContext.SuperUsers.Where(e => e.Id.Equals(createdSuperUser.Id)).First(); + var created = _dbContext.SuperUsers.Where(e => e.Id.Equals(createdSuperUser.Id)).First(); } [Fact] public async Task CreateResource_GuidResource_IsCreated() { // Arrange - var dbContext = PrepareTest(); var serializer = GetSerializer(e => new { }, e => new { e.Owner }); - var owner = new Person(); - dbContext.People.Add(owner); - dbContext.SaveChanges(); + _dbContext.People.Add(owner); + _dbContext.SaveChanges(); var todoItemCollection = new TodoItemCollection { Owner = owner }; // Act - var (body, response) = await Post("/api/v1/todo-collections", serializer.Serialize(todoItemCollection)); + var (body, response) = await Post("/api/v1/todoCollections", serializer.Serialize(todoItemCollection)); // Assert AssertEqualStatusCode(HttpStatusCode.Created, response); @@ -76,86 +67,39 @@ public async Task CreateResource_GuidResource_IsCreated() public async Task ClientGeneratedId_IntegerIdAndNotEnabled_IsForbidden() { // Arrange - var dbContext = PrepareTest(); var serializer = GetSerializer(e => new { e.Description, e.Ordinal, e.CreatedDate }); - var todoItem = _todoItemFaker.Generate(); const int clientDefinedId = 9999; todoItem.Id = clientDefinedId; // Act - var (body, response) = await Post("/api/v1/todo-items", serializer.Serialize(todoItem)); + var (body, response) = await Post("/api/v1/todoItems", serializer.Serialize(todoItem)); // Assert AssertEqualStatusCode(HttpStatusCode.Forbidden, response); } - - [Fact] - public async Task ClientGeneratedId_IntegerIdAndEnabled_IsCreated() - { - // Arrange - var dbContext = PrepareTest(); - var serializer = GetSerializer(e => new { e.Description, e.Ordinal, e.CreatedDate }); - - var todoItem = _todoItemFaker.Generate(); - const int clientDefinedId = 9999; - todoItem.Id = clientDefinedId; - - // Act - var (body, response) = await Post("/api/v1/todo-items", serializer.Serialize(todoItem)); - var responseItem = _deserializer.DeserializeSingle(body).Data; - - // Assert - AssertEqualStatusCode(HttpStatusCode.Created, response); - Assert.Equal(clientDefinedId, responseItem.Id); - } - - [Fact] - public async Task ClientGeneratedId_GuidIdAndEnabled_IsCreated() - { - // Arrange - var dbContext = PrepareTest(); - var serializer = GetSerializer(e => new { }, e => new { e.Owner }); - - var owner = new Person(); - dbContext.People.Add(owner); - await dbContext.SaveChangesAsync(); - var clientDefinedId = Guid.NewGuid(); - var todoItemCollection = new TodoItemCollection { Owner = owner, OwnerId = owner.Id, Id = clientDefinedId }; - - // Act - var (body, response) = await Post("/api/v1/todo-collections", serializer.Serialize(todoItemCollection)); - var responseItem = _deserializer.DeserializeSingle(body).Data; - - // Assert - AssertEqualStatusCode(HttpStatusCode.Created, response); - Assert.Equal(clientDefinedId, responseItem.Id); - } - [Fact] public async Task CreateWithRelationship_HasMany_IsCreated() { // Arrange - var dbContext = PrepareTest(); var serializer = GetSerializer(e => new { }, e => new { e.TodoItems }); - var todoItem = _todoItemFaker.Generate(); - dbContext.TodoItems.Add(todoItem); - dbContext.SaveChanges(); + _dbContext.TodoItems.Add(todoItem); + _dbContext.SaveChanges(); var todoCollection = new TodoItemCollection { TodoItems = new List { todoItem } }; // Act - var (body, response) = await Post("/api/v1/todo-collections", serializer.Serialize(todoCollection)); - var responseItem = _deserializer.DeserializeSingle(body).Data; + var (body, response) = await Post("/api/v1/todoCollections", serializer.Serialize(todoCollection)); // Assert + AssertEqualStatusCode(HttpStatusCode.Created, response); + var responseItem = _deserializer.DeserializeSingle(body).Data; var contextCollection = GetDbContext().TodoItemCollections.AsNoTracking() .Include(c => c.Owner) .Include(c => c.TodoItems) .SingleOrDefault(c => c.Id == responseItem.Id); - AssertEqualStatusCode(HttpStatusCode.Created, response); Assert.NotEmpty(contextCollection.TodoItems); Assert.Equal(todoItem.Id, contextCollection.TodoItems.First().Id); } @@ -164,27 +108,20 @@ public async Task CreateWithRelationship_HasMany_IsCreated() public async Task CreateWithRelationship_HasManyAndInclude_IsCreatedAndIncludes() { // Arrange - var dbContext = PrepareTest(); var serializer = GetSerializer(e => new { }, e => new { e.TodoItems, e.Owner }); - var owner = new Person(); - var todoItem = new TodoItem - { - Owner = owner, - Description = "Description" - }; - dbContext.People.Add(owner); - dbContext.TodoItems.Add(todoItem); - dbContext.SaveChanges(); + var todoItem = new TodoItem { Owner = owner, Description = "Description" }; + _dbContext.People.Add(owner); + _dbContext.TodoItems.Add(todoItem); + _dbContext.SaveChanges(); var todoCollection = new TodoItemCollection { Owner = owner, TodoItems = new List { todoItem } }; // Act - var (body, response) = await Post("/api/v1/todo-collections?include=todo-items", serializer.Serialize(todoCollection)); - var responseItem = _deserializer.DeserializeSingle(body).Data; + var (body, response) = await Post("/api/v1/todoCollections?include=todoItems", serializer.Serialize(todoCollection)); // Assert AssertEqualStatusCode(HttpStatusCode.Created, response); - + var responseItem = _deserializer.DeserializeSingle(body).Data; Assert.NotNull(responseItem); Assert.NotEmpty(responseItem.TodoItems); Assert.Equal(todoItem.Description, responseItem.TodoItems.Single().Description); @@ -194,24 +131,22 @@ public async Task CreateWithRelationship_HasManyAndInclude_IsCreatedAndIncludes( public async Task CreateWithRelationship_HasOne_IsCreated() { // Arrange - var dbContext = PrepareTest(); var serializer = GetSerializer(attributes: ti => new { }, relationships: ti => new { ti.Owner }); - var todoItem = new TodoItem(); var owner = new Person(); - dbContext.People.Add(owner); - await dbContext.SaveChangesAsync(); + _dbContext.People.Add(owner); + _dbContext.SaveChanges(); todoItem.Owner = owner; // Act - var (body, response) = await Post("/api/v1/todo-items", serializer.Serialize(todoItem)); - var responseItem = _deserializer.DeserializeSingle(body).Data; + var (body, response) = await Post("/api/v1/todoItems", serializer.Serialize(todoItem)); // Assert + AssertEqualStatusCode(HttpStatusCode.Created, response); + var responseItem = _deserializer.DeserializeSingle(body).Data; var todoItemResult = GetDbContext().TodoItems.AsNoTracking() .Include(c => c.Owner) .SingleOrDefault(c => c.Id == responseItem.Id); - AssertEqualStatusCode(HttpStatusCode.Created, response); Assert.Equal(owner.Id, todoItemResult.OwnerId); } @@ -219,21 +154,19 @@ public async Task CreateWithRelationship_HasOne_IsCreated() public async Task CreateWithRelationship_HasOneAndInclude_IsCreatedAndIncludes() { // Arrange - var dbContext = PrepareTest(); var serializer = GetSerializer(attributes: ti => new { }, relationships: ti => new { ti.Owner }); - var todoItem = new TodoItem(); var owner = new Person { FirstName = "Alice" }; - dbContext.People.Add(owner); - dbContext.SaveChanges(); + _dbContext.People.Add(owner); + _dbContext.SaveChanges(); todoItem.Owner = owner; // Act - var (body, response) = await Post("/api/v1/todo-items?include=owner", serializer.Serialize(todoItem)); - var responseItem = _deserializer.DeserializeSingle(body).Data; + var (body, response) = await Post("/api/v1/todoItems?include=owner", serializer.Serialize(todoItem)); // Assert AssertEqualStatusCode(HttpStatusCode.Created, response); + var responseItem = _deserializer.DeserializeSingle(body).Data; Assert.NotNull(responseItem); Assert.NotNull(responseItem.Owner); Assert.Equal(owner.FirstName, responseItem.Owner.FirstName); @@ -243,23 +176,21 @@ public async Task CreateWithRelationship_HasOneAndInclude_IsCreatedAndIncludes() public async Task CreateWithRelationship_HasOneFromIndependentSide_IsCreated() { // Arrange - var dbContext = PrepareTest(); var serializer = GetSerializer(pr => new { }, pr => new { pr.Person }); - var person = new Person(); - dbContext.People.Add(person); - dbContext.SaveChanges(); + _dbContext.People.Add(person); + _dbContext.SaveChanges(); var personRole = new PersonRole { Person = person }; // Act - var (body, response) = await Post("/api/v1/person-roles", serializer.Serialize(personRole)); - var responseItem = _deserializer.DeserializeSingle(body).Data; + var (body, response) = await Post("/api/v1/personRoles", serializer.Serialize(personRole)); // Assert - var personRoleResult = dbContext.PersonRoles.AsNoTracking() + AssertEqualStatusCode(HttpStatusCode.Created, response); + var responseItem = _deserializer.DeserializeSingle(body).Data; + var personRoleResult = _dbContext.PersonRoles.AsNoTracking() .Include(c => c.Person) .SingleOrDefault(c => c.Id == responseItem.Id); - AssertEqualStatusCode(HttpStatusCode.Created, response); Assert.NotEqual(0, responseItem.Id); Assert.Equal(person.Id, personRoleResult.Person.Id); } @@ -268,33 +199,29 @@ public async Task CreateWithRelationship_HasOneFromIndependentSide_IsCreated() public async Task CreateResource_SimpleResource_HeaderLocationsAreCorrect() { // Arrange - var dbContext = PrepareTest(); var serializer = GetSerializer(ti => new { ti.CreatedDate, ti.Description, ti.Ordinal }); - var todoItem = _todoItemFaker.Generate(); // Act - var (body, response) = await Post("/api/v1/todo-items", serializer.Serialize(todoItem)); + var (body, response) = await Post("/api/v1/todoItems", serializer.Serialize(todoItem)); var responseItem = _deserializer.DeserializeSingle(body).Data; // Assert AssertEqualStatusCode(HttpStatusCode.Created, response); - Assert.Equal($"/api/v1/todo-items/{responseItem.Id}", response.Headers.Location.ToString()); + Assert.Equal($"/api/v1/todoItems/{responseItem.Id}", response.Headers.Location.ToString()); } [Fact] public async Task CreateResource_EntityTypeMismatch_IsConflict() { // Arrange - var dbContext = PrepareTest(); var serializer = GetSerializer(e => new { }, e => new { e.Owner }); - var resourceGraph = new ResourceGraphBuilder().AddResource("todo-items").AddResource().AddResource().Build(); + var resourceGraph = new ResourceGraphBuilder().AddResource("todoItems").AddResource().AddResource().Build(); var _deserializer = new ResponseDeserializer(resourceGraph); - - var content = serializer.Serialize(_todoItemFaker.Generate()).Replace("todo-items", "people"); + var content = serializer.Serialize(_todoItemFaker.Generate()).Replace("todoItems", "people"); // Act - var (body, response) = await Post("/api/v1/todo-items", content); + var (body, response) = await Post("/api/v1/todoItems", content); // Assert AssertEqualStatusCode(HttpStatusCode.Conflict, response); @@ -304,24 +231,22 @@ public async Task CreateResource_EntityTypeMismatch_IsConflict() public async Task CreateRelationship_ToOneWithImplicitRemove_IsCreated() { // Arrange - var dbContext = PrepareTest(); var serializer = GetSerializer(e => new { e.FirstName }, e => new { e.Passport }); - var passport = new Passport(); var currentPerson = _personFaker.Generate(); currentPerson.Passport = passport; - dbContext.People.Add(currentPerson); - dbContext.SaveChanges(); + _dbContext.People.Add(currentPerson); + _dbContext.SaveChanges(); var newPerson = _personFaker.Generate(); newPerson.Passport = passport; // Act var (body, response) = await Post("/api/v1/people", serializer.Serialize(newPerson)); - var responseItem = _deserializer.DeserializeSingle(body).Data; // Assert AssertEqualStatusCode(HttpStatusCode.Created, response); - var newPersonDb = dbContext.People.AsNoTracking().Where(p => p.Id == responseItem.Id).Include(e => e.Passport).Single(); + var responseItem = _deserializer.DeserializeSingle(body).Data; + var newPersonDb = _dbContext.People.AsNoTracking().Where(p => p.Id == responseItem.Id).Include(e => e.Passport).Single(); Assert.NotNull(newPersonDb.Passport); Assert.Equal(passport.Id, newPersonDb.Passport.Id); } @@ -330,15 +255,12 @@ public async Task CreateRelationship_ToOneWithImplicitRemove_IsCreated() public async Task CreateRelationship_ToManyWithImplicitRemove_IsCreated() { // Arrange - var dbContext = PrepareTest(); var serializer = GetSerializer(e => new { e.FirstName }, e => new { e.TodoItems }); - - var context = _fixture.GetService(); var currentPerson = _personFaker.Generate(); var todoItems = _todoItemFaker.Generate(3).ToList(); currentPerson.TodoItems = todoItems; - dbContext.Add(currentPerson); - dbContext.SaveChanges(); + _dbContext.Add(currentPerson); + _dbContext.SaveChanges(); var firstTd = currentPerson.TodoItems[0]; var secondTd = currentPerson.TodoItems[1]; var thirdTd = currentPerson.TodoItems[2]; @@ -348,12 +270,12 @@ public async Task CreateRelationship_ToManyWithImplicitRemove_IsCreated() // Act var (body, response) = await Post("/api/v1/people", serializer.Serialize(newPerson)); - var responseItem = _deserializer.DeserializeSingle(body).Data; // Assert - var newPersonDb = dbContext.People.AsNoTracking().Where(p => p.Id == responseItem.Id).Include(e => e.TodoItems).Single(); - var oldPersonDb = dbContext.People.AsNoTracking().Where(p => p.Id == currentPerson.Id).Include(e => e.TodoItems).Single(); AssertEqualStatusCode(HttpStatusCode.Created, response); + var responseItem = _deserializer.DeserializeSingle(body).Data; + var newPersonDb = _dbContext.People.AsNoTracking().Where(p => p.Id == responseItem.Id).Include(e => e.TodoItems).Single(); + var oldPersonDb = _dbContext.People.AsNoTracking().Where(p => p.Id == currentPerson.Id).Include(e => e.TodoItems).Single(); Assert.Equal(2, newPersonDb.TodoItems.Count); Assert.Single(oldPersonDb.TodoItems); Assert.NotNull(newPersonDb.TodoItems.SingleOrDefault(ti => ti.Id == firstTd.Id)); @@ -361,4 +283,56 @@ public async Task CreateRelationship_ToManyWithImplicitRemove_IsCreated() Assert.NotNull(oldPersonDb.TodoItems.SingleOrDefault(ti => ti.Id == thirdTd.Id)); } } + + + public class CreatingDataWithClientEnabledIdTests : FunctionalTestCollection + { + private readonly Faker _todoItemFaker; + + public CreatingDataWithClientEnabledIdTests(ClientEnabledIdsApplicationFactory factory) : base(factory) + { + _todoItemFaker = new Faker() + .RuleFor(t => t.Description, f => f.Lorem.Sentence()) + .RuleFor(t => t.Ordinal, f => f.Random.Number()) + .RuleFor(t => t.CreatedDate, f => f.Date.Past()); + } + + [Fact] + public async Task ClientGeneratedId_IntegerIdAndEnabled_IsCreated() + { + // Arrange + var serializer = GetSerializer(e => new { e.Description, e.Ordinal, e.CreatedDate }); + var todoItem = _todoItemFaker.Generate(); + const int clientDefinedId = 9999; + todoItem.Id = clientDefinedId; + + // Act + var (body, response) = await Post("/api/v1/todoItems", serializer.Serialize(todoItem)); + + // Assert + AssertEqualStatusCode(HttpStatusCode.Created, response); + var responseItem = _deserializer.DeserializeSingle(body).Data; + Assert.Equal(clientDefinedId, responseItem.Id); + } + + [Fact] + public async Task ClientGeneratedId_GuidIdAndEnabled_IsCreated() + { + // Arrange + var serializer = GetSerializer(e => new { }, e => new { e.Owner }); + var owner = new Person(); + _dbContext.People.Add(owner); + await _dbContext.SaveChangesAsync(); + var clientDefinedId = Guid.NewGuid(); + var todoItemCollection = new TodoItemCollection { Owner = owner, OwnerId = owner.Id, Id = clientDefinedId }; + + // Act + var (body, response) = await Post("/api/v1/todoCollections", serializer.Serialize(todoItemCollection)); + + // Assert + AssertEqualStatusCode(HttpStatusCode.Created, response); + var responseItem = _deserializer.DeserializeSingle(body).Data; + Assert.Equal(clientDefinedId, responseItem.Id); + } + } } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeeplyNestedInclusionTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeeplyNestedInclusionTests.cs index 2299ee2ba2..6130e81e45 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeeplyNestedInclusionTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeeplyNestedInclusionTests.cs @@ -38,8 +38,8 @@ private void ResetContext(AppDbContext context) public async Task Can_Include_Nested_Relationships() { // Arrange - const string route = "/api/v1/todo-items?include=collection.owner"; - var resourceGraph = new ResourceGraphBuilder().AddResource("todo-items").AddResource().AddResource().Build(); + const string route = "/api/v1/todoItems?include=collection.owner"; + var resourceGraph = new ResourceGraphBuilder().AddResource("todoItems").AddResource().AddResource().Build(); var deserializer = new ResponseDeserializer(resourceGraph); var todoItem = new TodoItem { @@ -74,7 +74,7 @@ public async Task Can_Include_Nested_Relationships() public async Task Can_Include_Nested_HasMany_Relationships() { // Arrange - const string route = "/api/v1/todo-items?include=collection.todo-items"; + const string route = "/api/v1/todoItems?include=collection.todoItems"; var todoItem = new TodoItem { @@ -107,15 +107,15 @@ public async Task Can_Include_Nested_HasMany_Relationships() Assert.Equal(4, included.Count); - Assert.Equal(3, included.CountOfType("todo-items")); - Assert.Equal(1, included.CountOfType("todo-collections")); + Assert.Equal(3, included.CountOfType("todoItems")); + Assert.Equal(1, included.CountOfType("todoCollections")); } [Fact] public async Task Can_Include_Nested_HasMany_Relationships_BelongsTo() { // Arrange - const string route = "/api/v1/todo-items?include=collection.todo-items.owner"; + const string route = "/api/v1/todoItems?include=collection.todoItems.owner"; var todoItem = new TodoItem { @@ -149,16 +149,16 @@ public async Task Can_Include_Nested_HasMany_Relationships_BelongsTo() Assert.Equal(5, included.Count); - Assert.Equal(3, included.CountOfType("todo-items")); + Assert.Equal(3, included.CountOfType("todoItems")); Assert.Equal(1, included.CountOfType("people")); - Assert.Equal(1, included.CountOfType("todo-collections")); + Assert.Equal(1, included.CountOfType("todoCollections")); } [Fact] public async Task Can_Include_Nested_Relationships_With_Multiple_Paths() { // Arrange - const string route = "/api/v1/todo-items?include=collection.owner.role,collection.todo-items.owner"; + const string route = "/api/v1/todoItems?include=collection.owner.role,collection.todoItems.owner"; var todoItem = new TodoItem { @@ -195,10 +195,10 @@ public async Task Can_Include_Nested_Relationships_With_Multiple_Paths() Assert.Equal(7, included.Count); - Assert.Equal(3, included.CountOfType("todo-items")); + Assert.Equal(3, included.CountOfType("todoItems")); Assert.Equal(2, included.CountOfType("people")); - Assert.Equal(1, included.CountOfType("person-roles")); - Assert.Equal(1, included.CountOfType("todo-collections")); + Assert.Equal(1, included.CountOfType("personRoles")); + Assert.Equal(1, included.CountOfType("todoCollections")); } [Fact] @@ -232,10 +232,10 @@ public async Task Included_Resources_Are_Correct() await context.SaveChangesAsync(); string route = - "/api/v1/todo-items/" + todoItem1.Id + "?include=" + + "/api/v1/todoItems/" + todoItem1.Id + "?include=" + "collection.owner," + "assignee.role," + - "assignee.assigned-todo-items"; + "assignee.assignedTodoItems"; // Act var response = await _fixture.Client.GetAsync(route); @@ -252,12 +252,12 @@ public async Task Included_Resources_Are_Correct() // 2 assigned todo items (including the primary resource) Assert.Equal(6, included.Count); - var collectionDocument = included.FindResource("todo-collections", collection.Id); + var collectionDocument = included.FindResource("todoCollections", collection.Id); var ownerDocument = included.FindResource("people", collectionOwner.Id); var assigneeDocument = included.FindResource("people", assignee.Id); - var roleDocument = included.FindResource("person-roles", role.Id); - var assignedTodo1 = included.FindResource("todo-items", todoItem1.Id); - var assignedTodo2 = included.FindResource("todo-items", todoItem2.Id); + var roleDocument = included.FindResource("personRoles", role.Id); + var assignedTodo1 = included.FindResource("todoItems", todoItem1.Id); + var assignedTodo2 = included.FindResource("todoItems", todoItem2.Id); Assert.NotNull(assignedTodo1); Assert.Equal(todoItem1.Id.ToString(), assignedTodo1.Id); @@ -283,7 +283,7 @@ public async Task Can_Include_Doubly_HasMany_Relationships() { // Arrange var person = new Person { - TodoItemCollections = new List { + todoCollections = new List { new TodoItemCollection { TodoItems = new List { new TodoItem(), @@ -307,7 +307,7 @@ public async Task Can_Include_Doubly_HasMany_Relationships() await context.SaveChangesAsync(); - string route = "/api/v1/people/" + person.Id + "?include=todo-collections.todo-items"; + string route = "/api/v1/people/" + person.Id + "?include=todoCollections.todoItems"; // Act var response = await _fixture.Client.GetAsync(route); @@ -321,8 +321,8 @@ public async Task Can_Include_Doubly_HasMany_Relationships() Assert.Equal(7, included.Count); - Assert.Equal(5, included.CountOfType("todo-items")); - Assert.Equal(2, included.CountOfType("todo-collections")); + Assert.Equal(5, included.CountOfType("todoItems")); + Assert.Equal(2, included.CountOfType("todoCollections")); } } } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeletingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeletingDataTests.cs index 00abbdec85..099128e71c 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeletingDataTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeletingDataTests.cs @@ -44,7 +44,7 @@ public async Task Respond_404_If_EntityDoesNotExist() var client = server.CreateClient(); var httpMethod = new HttpMethod("DELETE"); - var route = $"/api/v1/todo-items/{lastTodoId + 100}"; + var route = $"/api/v1/todoItems/{lastTodoId + 100}"; var request = new HttpRequestMessage(httpMethod, route); // Act diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs index 1471b0410b..ac73ca9c4f 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs @@ -54,7 +54,7 @@ public async Task GET_Included_Contains_SideloadeData_ForManyToOne() var builder = new WebHostBuilder().UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?include=owner"; + var route = $"/api/v1/todoItems?include=owner"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -66,7 +66,7 @@ public async Task GET_Included_Contains_SideloadeData_ForManyToOne() // Assert var json = await response.Content.ReadAsStringAsync(); var documents = JsonConvert.DeserializeObject(json); - // we only care about counting the todo-items that have owners + // we only care about counting the todoItems that have owners var expectedCount = documents.ManyData.Count(d => d.Relationships["owner"].SingleData != null); Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -93,7 +93,7 @@ public async Task GET_ById_Included_Contains_SideloadeData_ForManyToOne() var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items/{todoItem.Id}?include=owner"; + var route = $"/api/v1/todoItems/{todoItem.Id}?include=owner"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -108,8 +108,8 @@ public async Task GET_ById_Included_Contains_SideloadeData_ForManyToOne() Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotEmpty(document.Included); Assert.Equal(person.Id.ToString(), document.Included[0].Id); - Assert.Equal(person.FirstName, document.Included[0].Attributes["first-name"]); - Assert.Equal(person.LastName, document.Included[0].Attributes["last-name"]); + Assert.Equal(person.FirstName, document.Included[0].Attributes["firstName"]); + Assert.Equal(person.LastName, document.Included[0].Attributes["lastName"]); server.Dispose(); request.Dispose(); @@ -120,7 +120,7 @@ public async Task GET_ById_Included_Contains_SideloadeData_ForManyToOne() public async Task GET_Included_Contains_SideloadeData_OneToMany() { // Arrange - _context.People.RemoveRange(_context.People); // ensure all people have todo-items + _context.People.RemoveRange(_context.People); // ensure all people have todoItems _context.TodoItems.RemoveRange(_context.TodoItems); var person = _personFaker.Generate(); var todoItem = _todoItemFaker.Generate(); @@ -132,7 +132,7 @@ public async Task GET_Included_Contains_SideloadeData_OneToMany() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/people?include=todo-items"; + var route = $"/api/v1/people?include=todoItems"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -158,7 +158,7 @@ public async Task GET_Included_DoesNot_Duplicate_Records_ForMultipleRelationship // Arrange _context.RemoveRange(_context.TodoItems); _context.RemoveRange(_context.TodoItemCollections); - _context.RemoveRange(_context.People); // ensure all people have todo-items + _context.RemoveRange(_context.People); // ensure all people have todoItems _context.SaveChanges(); var person = _personFaker.Generate(); var todoItem = _todoItemFaker.Generate(); @@ -171,7 +171,7 @@ public async Task GET_Included_DoesNot_Duplicate_Records_ForMultipleRelationship .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items/{todoItem.Id}?include=owner&include=assignee"; + var route = $"/api/v1/todoItems/{todoItem.Id}?include=owner&include=assignee"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -196,7 +196,7 @@ public async Task GET_Included_DoesNot_Duplicate_Records_If_HasOne_Exists_Twice( { // Arrange _context.TodoItemCollections.RemoveRange(_context.TodoItemCollections); - _context.People.RemoveRange(_context.People); // ensure all people have todo-items + _context.People.RemoveRange(_context.People); // ensure all people have todoItems _context.TodoItems.RemoveRange(_context.TodoItems); var person = _personFaker.Generate(); var todoItem1 = _todoItemFaker.Generate(); @@ -210,7 +210,7 @@ public async Task GET_Included_DoesNot_Duplicate_Records_If_HasOne_Exists_Twice( .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?include=owner"; + var route = $"/api/v1/todoItems?include=owner"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -249,7 +249,7 @@ public async Task GET_ById_Included_Contains_SideloadeData_ForOneToMany() var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/people/{person.Id}?include=todo-items"; + var route = $"/api/v1/people/{person.Id}?include=todoItems"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -293,7 +293,7 @@ public async Task Can_Include_MultipleRelationships() var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/people/{person.Id}?include=todo-items,todo-collections"; + var route = $"/api/v1/people/{person.Id}?include=todoItems,todoCollections"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -325,7 +325,7 @@ public async Task Request_ToIncludeUnknownRelationship_Returns_400() var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/people/{person.Id}?include=non-existent-relationship"; + var route = $"/api/v1/people/{person.Id}?include=nonExistentRelationship"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -381,7 +381,7 @@ public async Task Request_ToIncludeRelationshipMarkedCanIncludeFalse_Returns_400 var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/people/{person.Id}?include=unincludeable-item"; + var route = $"/api/v1/people/{person.Id}?include=unincludeableItem"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -419,7 +419,7 @@ public async Task Can_Ignore_Null_Parent_In_Nested_Include() var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?sort=-created-date&page[size]=2&include=owner.role"; // last two todo-items + var route = $"/api/v1/todoItems?sort=-createdDate&page[size]=2&include=owner.role"; // last two todoItems var server = new TestServer(builder); var client = server.CreateClient(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs index b1e4b33017..59928ffccd 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs @@ -37,7 +37,7 @@ public async Task Total_Record_Count_Included() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items"; + var route = $"/api/v1/todoItems"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -64,7 +64,7 @@ public async Task Total_Record_Count_Included_When_None() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items"; + var route = $"/api/v1/todoItems"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -91,7 +91,7 @@ public async Task Total_Record_Count_Not_Included_In_POST_Response() .UseStartup(); var httpMethod = new HttpMethod("POST"); - var route = $"/api/v1/todo-items"; + var route = $"/api/v1/todoItems"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -100,7 +100,7 @@ public async Task Total_Record_Count_Not_Included_In_POST_Response() { data = new { - type = "todo-items", + type = "todoItems", attributes = new { description = "New Description", @@ -133,7 +133,7 @@ public async Task Total_Record_Count_Not_Included_In_PATCH_Response() .UseStartup(); var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -142,7 +142,7 @@ public async Task Total_Record_Count_Not_Included_In_PATCH_Response() { data = new { - type = "todo-items", + type = "todoItems", id = todoItem.Id, attributes = new { diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs index a15c92a38d..e34e63179e 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs @@ -49,7 +49,7 @@ public async Task Server_IncludesPagination_Links() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?page[number]=2"; + var route = $"/api/v1/todoItems?page[number]=2"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -66,10 +66,10 @@ public async Task Server_IncludesPagination_Links() Assert.NotEmpty(links.Next); Assert.NotEmpty(links.Last); - Assert.Equal($"http://localhost/api/v1/todo-items?page[size]={pageSize}&page[number]={startPageNumber+1}", links.Next); - Assert.Equal($"http://localhost/api/v1/todo-items?page[size]={pageSize}&page[number]={startPageNumber-1}", links.Prev); - Assert.Equal($"http://localhost/api/v1/todo-items?page[size]={pageSize}&page[number]={numberOfPages}", links.Last); - Assert.Equal($"http://localhost/api/v1/todo-items?page[size]={pageSize}&page[number]=1", links.First); + Assert.Equal($"http://localhost/api/v1/todoItems?page[size]={pageSize}&page[number]={startPageNumber+1}", links.Next); + Assert.Equal($"http://localhost/api/v1/todoItems?page[size]={pageSize}&page[number]={startPageNumber-1}", links.Prev); + Assert.Equal($"http://localhost/api/v1/todoItems?page[size]={pageSize}&page[number]={numberOfPages}", links.Last); + Assert.Equal($"http://localhost/api/v1/todoItems?page[size]={pageSize}&page[number]=1", links.First); } } } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Relationships.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Relationships.cs index 50c0848956..3d1097a3be 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Relationships.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Relationships.cs @@ -43,7 +43,7 @@ public async Task Correct_RelationshipObjects_For_ManyToOne_Relationships() await _context.SaveChangesAsync(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -53,8 +53,8 @@ public async Task Correct_RelationshipObjects_For_ManyToOne_Relationships() var response = await client.SendAsync(request); var document = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); var data = document.SingleData; - var expectedOwnerSelfLink = $"http://localhost/api/v1/todo-items/{data.Id}/relationships/owner"; - var expectedOwnerRelatedLink = $"http://localhost/api/v1/todo-items/{data.Id}/owner"; + var expectedOwnerSelfLink = $"http://localhost/api/v1/todoItems/{data.Id}/relationships/owner"; + var expectedOwnerRelatedLink = $"http://localhost/api/v1/todoItems/{data.Id}/owner"; // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -74,7 +74,7 @@ public async Task Correct_RelationshipObjects_For_ManyToOne_Relationships_ById() await _context.SaveChangesAsync(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var server = new TestServer(builder); var client = server.CreateClient(); @@ -84,8 +84,8 @@ public async Task Correct_RelationshipObjects_For_ManyToOne_Relationships_ById() var response = await client.SendAsync(request); var responseString = await response.Content.ReadAsStringAsync(); var data = JsonConvert.DeserializeObject(responseString).SingleData; - var expectedOwnerSelfLink = $"http://localhost/api/v1/todo-items/{todoItem.Id}/relationships/owner"; - var expectedOwnerRelatedLink = $"http://localhost/api/v1/todo-items/{todoItem.Id}/owner"; + var expectedOwnerSelfLink = $"http://localhost/api/v1/todoItems/{todoItem.Id}/relationships/owner"; + var expectedOwnerRelatedLink = $"http://localhost/api/v1/todoItems/{todoItem.Id}/owner"; // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -111,13 +111,13 @@ public async Task Correct_RelationshipObjects_For_OneToMany_Relationships() var response = await client.SendAsync(request); var documents = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); var data = documents.ManyData.First(); - var expectedOwnerSelfLink = $"http://localhost/api/v1/people/{data.Id}/relationships/todo-items"; - var expectedOwnerRelatedLink = $"http://localhost/api/v1/people/{data.Id}/todo-items"; + var expectedOwnerSelfLink = $"http://localhost/api/v1/people/{data.Id}/relationships/todoItems"; + var expectedOwnerRelatedLink = $"http://localhost/api/v1/people/{data.Id}/todoItems"; // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(expectedOwnerSelfLink, data.Relationships["todo-items"].Links.Self); - Assert.Equal(expectedOwnerRelatedLink, data.Relationships["todo-items"].Links.Related); + Assert.Equal(expectedOwnerSelfLink, data.Relationships["todoItems"].Links.Self); + Assert.Equal(expectedOwnerRelatedLink, data.Relationships["todoItems"].Links.Related); } [Fact] @@ -140,13 +140,13 @@ public async Task Correct_RelationshipObjects_For_OneToMany_Relationships_ById() var response = await client.SendAsync(request); var responseString = await response.Content.ReadAsStringAsync(); var data = JsonConvert.DeserializeObject(responseString).SingleData; - var expectedOwnerSelfLink = $"http://localhost/api/v1/people/{personId}/relationships/todo-items"; - var expectedOwnerRelatedLink = $"http://localhost/api/v1/people/{personId}/todo-items"; + var expectedOwnerSelfLink = $"http://localhost/api/v1/people/{personId}/relationships/todoItems"; + var expectedOwnerRelatedLink = $"http://localhost/api/v1/people/{personId}/todoItems"; // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(expectedOwnerSelfLink, data.Relationships["todo-items"].Links?.Self); - Assert.Equal(expectedOwnerRelatedLink, data.Relationships["todo-items"].Links.Related); + Assert.Equal(expectedOwnerSelfLink, data.Relationships["todoItems"].Links?.Self); + Assert.Equal(expectedOwnerRelatedLink, data.Relationships["todoItems"].Links.Related); } } } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/EndToEndTest.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/EndToEndTest.cs index ee5451c542..e3cb86dd9d 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/EndToEndTest.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/EndToEndTest.cs @@ -4,14 +4,127 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; +using JsonApiDotNetCore.Builders; +using JsonApiDotNetCore.Graph; +using JsonApiDotNetCore.Internal.Contracts; using JsonApiDotNetCore.Models; using JsonApiDotNetCore.Serialization.Client; using JsonApiDotNetCoreExample; using JsonApiDotNetCoreExample.Data; +using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExampleTests.Helpers.Models; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using Xunit; +namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec +{ + public class FunctionalTestCollection : IClassFixture where TFactory : class, IApplicationFactory + { + public static MediaTypeHeaderValue JsonApiContentType = new MediaTypeHeaderValue("application/vnd.api+json"); + protected readonly TFactory _factory; + protected readonly HttpClient _client; + protected readonly AppDbContext _dbContext; + protected IResponseDeserializer _deserializer; + + public FunctionalTestCollection(TFactory factory) + { + _factory = factory; + _client = _factory.CreateClient(); + _dbContext = _factory.GetService(); + _deserializer = GetDeserializer(); + ClearDbContext(); + } + + protected Task<(string, HttpResponseMessage)> Get(string route) + { + return SendRequest("GET", route); + } + + protected Task<(string, HttpResponseMessage)> Post(string route, string content) + { + return SendRequest("POST", route, content); + } + + protected Task<(string, HttpResponseMessage)> Patch(string route, string content) + { + return SendRequest("PATCH", route, content); + } + + protected Task<(string, HttpResponseMessage)> Delete(string route) + { + return SendRequest("DELETE", route); + } + + protected IRequestSerializer GetSerializer(Expression> attributes = null, Expression> relationships = null) where TResource : class, IIdentifiable + { + var serializer = GetService(); + var graph = GetService(); + if (attributes != null) + { + serializer.AttributesToSerialize = graph.GetAttributes(attributes); + } + if (relationships != null) + { + serializer.RelationshipsToSerialize = graph.GetRelationships(relationships); + } + return serializer; + } + + protected IResponseDeserializer GetDeserializer() + { + var formatter = GetService(); + var resourcesContexts = GetService().GetResourceContexts(); + var builder = new ResourceGraphBuilder(formatter); + foreach (var rc in resourcesContexts) + { + if (rc.ResourceType == typeof(TodoItem) || rc.ResourceType == typeof(TodoItemCollection)) + { + continue; + } + builder.AddResource(rc.ResourceType, rc.IdentityType, rc.ResourceName); + } + builder.AddResource(formatter.FormatResourceName(typeof(TodoItem))); + builder.AddResource(formatter.FormatResourceName(typeof(TodoItemCollection))); + return new ResponseDeserializer(builder.Build()); + } + + protected AppDbContext GetDbContext() => GetService(); + + protected T GetService() => _factory.GetService(); + + protected void AssertEqualStatusCode(HttpStatusCode expected, HttpResponseMessage response) + { + var content = response.Content.ReadAsStringAsync(); + content.Wait(); + Assert.True(expected == response.StatusCode, $"Got {response.StatusCode} status code with payload instead of {expected}. Payload: {content.Result}"); + } + + protected void ClearDbContext() + { + _dbContext.RemoveRange(_dbContext.TodoItems); + _dbContext.RemoveRange(_dbContext.TodoItemCollections); + _dbContext.RemoveRange(_dbContext.PersonRoles); + _dbContext.RemoveRange(_dbContext.People); + _dbContext.SaveChanges(); + } + + private async Task<(string, HttpResponseMessage)> SendRequest(string method, string route, string content = null) + { + var request = new HttpRequestMessage(new HttpMethod(method), route); + if (content != null) + { + request.Content = new StringContent(content); + request.Content.Headers.ContentType = JsonApiContentType; + } + var response = await _client.SendAsync(request); + var body = await response.Content?.ReadAsStringAsync(); + return (body, response); + } + } +} + + namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec { public class EndToEndTest @@ -46,17 +159,25 @@ public AppDbContext GetDbContext() return _fixture.GetService(); } - public async Task<(string, HttpResponseMessage)> SendRequest(string method, string route, string content) + public async Task<(string, HttpResponseMessage)> SendRequest(string method, string route, string content = null) { var request = new HttpRequestMessage(new HttpMethod(method), route); - request.Content = new StringContent(content); - request.Content.Headers.ContentType = JsonApiContentType; + if (content != null) + { + request.Content = new StringContent(content); + request.Content.Headers.ContentType = JsonApiContentType; + } var response = await _client.SendAsync(request); var body = await response.Content?.ReadAsStringAsync(); return (body, response); } + public Task<(string, HttpResponseMessage)> Get(string route) + { + return SendRequest("GET", route); + } + public Task<(string, HttpResponseMessage)> Post(string route, string content) { return SendRequest("POST", route, content); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs index 40d82b8888..e863104596 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs @@ -45,7 +45,7 @@ public async Task Request_ForEmptyCollection_Returns_EmptyDataCollection() var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = "/api/v1/todo-items"; + var route = "/api/v1/todoItems"; var server = new TestServer(builder); var client = server.CreateClient(); var request = new HttpRequestMessage(httpMethod, route); @@ -79,7 +79,7 @@ public async Task Included_Records_Contain_Relationship_Links() var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items/{todoItem.Id}?include=owner"; + var route = $"/api/v1/todoItems/{todoItem.Id}?include=owner"; var server = new TestServer(builder); var client = server.CreateClient(); var request = new HttpRequestMessage(httpMethod, route); @@ -93,8 +93,8 @@ public async Task Included_Records_Contain_Relationship_Links() Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(person.StringId, deserializedBody.Included[0].Id); Assert.NotNull(deserializedBody.Included[0].Relationships); - Assert.Equal($"http://localhost/api/v1/people/{person.Id}/todo-items", deserializedBody.Included[0].Relationships["todo-items"].Links.Related); - Assert.Equal($"http://localhost/api/v1/people/{person.Id}/relationships/todo-items", deserializedBody.Included[0].Relationships["todo-items"].Links.Self); + Assert.Equal($"http://localhost/api/v1/people/{person.Id}/todoItems", deserializedBody.Included[0].Relationships["todoItems"].Links.Related); + Assert.Equal($"http://localhost/api/v1/people/{person.Id}/relationships/todoItems", deserializedBody.Included[0].Relationships["todoItems"].Links.Self); context.Dispose(); } @@ -110,7 +110,7 @@ public async Task GetResources_NoDefaultPageSize_ReturnsResources() var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items"; + var route = $"/api/v1/todoItems"; var server = new TestServer(builder); var client = server.CreateClient(); var request = new HttpRequestMessage(httpMethod, route); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs index 0380d13487..f5a8921a02 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs @@ -39,7 +39,7 @@ public async Task Request_UnsetRelationship_Returns_Null_DataObject() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items/{todoItem.Id}/owner"; + var route = $"/api/v1/todoItems/{todoItem.Id}/owner"; var server = new TestServer(builder); var client = server.CreateClient(); var request = new HttpRequestMessage(httpMethod, route); @@ -75,7 +75,7 @@ public async Task Request_ForRelationshipLink_ThatDoesNotExist_Returns_404() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items/{todoItemId}/owner"; + var route = $"/api/v1/todoItems/{todoItemId}/owner"; var server = new TestServer(builder); var client = server.CreateClient(); var request = new HttpRequestMessage(httpMethod, route); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs index e404b605d4..ea50bf8201 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs @@ -42,7 +42,7 @@ public async Task Can_Paginate_TodoItems() Context.TodoItems.AddRange(todoItems); Context.SaveChanges(); - var route = $"/api/v1/todo-items?page[size]={expectedEntitiesPerPage}"; + var route = $"/api/v1/todoItems?page[size]={expectedEntitiesPerPage}"; // Act var response = await Client.GetAsync(route); @@ -73,7 +73,7 @@ public async Task Can_Paginate_TodoItems_From_Start() Context.TodoItems.AddRange(todoItems); Context.SaveChanges(); - var route = $"/api/v1/todo-items?page[size]={expectedEntitiesPerPage}&page[number]=1"; + var route = $"/api/v1/todoItems?page[size]={expectedEntitiesPerPage}&page[number]=1"; // Act var response = await Client.GetAsync(route); @@ -102,7 +102,7 @@ public async Task Can_Paginate_TodoItems_From_End() Context.TodoItems.RemoveRange(Context.TodoItems); Context.TodoItems.AddRange(todoItems); Context.SaveChanges(); - var route = $"/api/v1/todo-items?page[size]={expectedEntitiesPerPage}&page[number]=-1"; + var route = $"/api/v1/todoItems?page[size]={expectedEntitiesPerPage}&page[number]=-1"; // Act var response = await Client.GetAsync(route); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs index 4a7a8cfdcf..1c64f41dab 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs @@ -28,7 +28,7 @@ public async Task Server_Returns_400_ForUnknownQueryParam() var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?{queryKey}={queryValue}"; + var route = $"/api/v1/todoItems?{queryKey}={queryValue}"; var server = new TestServer(builder); var client = server.CreateClient(); var request = new HttpRequestMessage(httpMethod, route); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs index b39dcdb012..4c85d5bd99 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs @@ -101,7 +101,7 @@ public async Task Fields_Query_Selects_Sparse_Field_Sets() using var server = new TestServer(builder); var client = server.CreateClient(); - var route = $"/api/v1/todo-items/{todoItem.Id}?fields=description,created-date"; + var route = $"/api/v1/todoItems/{todoItem.Id}?fields=description,createdDate"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -113,7 +113,7 @@ public async Task Fields_Query_Selects_Sparse_Field_Sets() Assert.Equal(todoItem.StringId, deserializeBody.SingleData.Id); Assert.Equal(2, deserializeBody.SingleData.Attributes.Count); Assert.Equal(todoItem.Description, deserializeBody.SingleData.Attributes["description"]); - Assert.Equal(todoItem.CreatedDate.ToString("G"), ((DateTime)deserializeBody.SingleData.Attributes["created-date"]).ToString("G")); + Assert.Equal(todoItem.CreatedDate.ToString("G"), ((DateTime)deserializeBody.SingleData.Attributes["createdDate"]).ToString("G")); } [Fact] @@ -134,7 +134,7 @@ public async Task Fields_Query_Selects_Sparse_Field_Sets_With_Type_As_Navigation var httpMethod = new HttpMethod("GET"); using var server = new TestServer(builder); var client = server.CreateClient(); - var route = $"/api/v1/todo-items/{todoItem.Id}?fields[todo-items]=description,created-date"; + var route = $"/api/v1/todoItems/{todoItem.Id}?fields[todoItems]=description,createdDate"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -170,9 +170,9 @@ public async Task Fields_Query_Selects_All_Fieldset_With_HasOne() using var server = new TestServer(builder); var client = server.CreateClient(); - var route = $"/api/v1/todo-items?include=owner&fields[owner]=first-name,age"; + var route = $"/api/v1/todoItems?include=owner&fields[owner]=firstName,age"; var request = new HttpRequestMessage(httpMethod, route); - var resourceGraph = new ResourceGraphBuilder().AddResource().AddResource("todo-items").Build(); + var resourceGraph = new ResourceGraphBuilder().AddResource().AddResource("todoItems").Build(); var deserializer = new ResponseDeserializer(resourceGraph); // Act var response = await client.SendAsync(request); @@ -212,7 +212,7 @@ public async Task Fields_Query_Selects_Fieldset_With_HasOne() using var server = new TestServer(builder); var client = server.CreateClient(); - var route = $"/api/v1/todo-items/{todoItem.Id}?include=owner&fields[owner]=first-name,age"; + var route = $"/api/v1/todoItems/{todoItem.Id}?include=owner&fields[owner]=firstName,age"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -226,9 +226,9 @@ public async Task Fields_Query_Selects_Fieldset_With_HasOne() // Assert - check owner attributes var included = deserializeBody.Included.First(); Assert.Equal(owner.StringId, included.Id); - Assert.Equal(owner.FirstName, included.Attributes["first-name"]); + Assert.Equal(owner.FirstName, included.Attributes["firstName"]); Assert.Equal((long)owner.Age, included.Attributes["age"]); - Assert.DoesNotContain("last-name", included.Attributes.Keys); + Assert.DoesNotContain("lastName", included.Attributes.Keys); } [Fact] @@ -249,7 +249,7 @@ public async Task Fields_Query_Selects_Fieldset_With_HasMany() using var server = new TestServer(builder); var client = server.CreateClient(); - var route = $"/api/v1/people/{owner.Id}?include=todo-items&fields[todo-items]=description"; + var route = $"/api/v1/people/{owner.Id}?include=todoItems&fields[todoItems]=description"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -267,7 +267,7 @@ public async Task Fields_Query_Selects_Fieldset_With_HasMany() Assert.NotNull(todoItem); Assert.Equal(todoItem.Description, includedItem.Attributes["description"]); Assert.DoesNotContain("ordinal", includedItem.Attributes.Keys); - Assert.DoesNotContain("created-date", includedItem.Attributes.Keys); + Assert.DoesNotContain("createdDate", includedItem.Attributes.Keys); } } } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs index 9d58f4d75c..1e9a3d1643 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs @@ -53,7 +53,7 @@ public async Task PatchResource_ModelWithEntityFrameworkInHeritance_IsPatched() var su = new SuperUser { Id = superUser.Id, SecurityLevel = 2674 }; // Act - var (body, response) = await Patch($"/api/v1/super-users/{su.Id}", serializer.Serialize(su)); + var (body, response) = await Patch($"/api/v1/superUsers/{su.Id}", serializer.Serialize(su)); // Assert AssertEqualStatusCode(HttpStatusCode.OK, response); @@ -75,7 +75,7 @@ public async Task Response400IfUpdatingNotSettableAttribute() var serializer = _fixture.GetSerializer(ti => new { ti.CalculatedValue }); var content = serializer.Serialize(todoItem); - var request = PrepareRequest("PATCH", $"/api/v1/todo-items/{todoItem.Id}", content); + var request = PrepareRequest("PATCH", $"/api/v1/todoItems/{todoItem.Id}", content); // Act var response = await client.SendAsync(request); @@ -101,7 +101,7 @@ public async Task Respond_404_If_EntityDoesNotExist() var serializer = _fixture.GetSerializer(ti => new { ti.Description, ti.Ordinal, ti.CreatedDate }); var content = serializer.Serialize(todoItem); - var request = PrepareRequest("PATCH", $"/api/v1/todo-items/{maxPersonId + 100}", content); + var request = PrepareRequest("PATCH", $"/api/v1/todoItems/{maxPersonId + 100}", content); // Act var response = await client.SendAsync(request); @@ -124,7 +124,7 @@ public async Task Respond_422_If_IdNotInAttributeList() var client = server.CreateClient(); var serializer = _fixture.GetSerializer(ti => new { ti.Description, ti.Ordinal, ti.CreatedDate }); var content = serializer.Serialize(todoItem); - var request = PrepareRequest("PATCH", $"/api/v1/todo-items/{maxPersonId}", content); + var request = PrepareRequest("PATCH", $"/api/v1/todoItems/{maxPersonId}", content); // Act var response = await client.SendAsync(request); @@ -156,7 +156,7 @@ public async Task Can_Patch_Entity() var client = server.CreateClient(); var serializer = _fixture.GetSerializer(p => new { p.Description, p.Ordinal }); - var request = PrepareRequest("PATCH", $"/api/v1/todo-items/{todoItem.Id}", serializer.Serialize(newTodoItem)); + var request = PrepareRequest("PATCH", $"/api/v1/todoItems/{todoItem.Id}", serializer.Serialize(newTodoItem)); // Act var response = await client.SendAsync(request); @@ -211,10 +211,10 @@ public async Task Patch_Entity_With_HasMany_Does_Not_Included_Relationships() Assert.NotNull(document); Assert.NotNull(document.Data); Assert.NotNull(document.SingleData.Attributes); - Assert.Equal(newPerson.LastName, document.SingleData.Attributes["last-name"]); - Assert.Equal(newPerson.FirstName, document.SingleData.Attributes["first-name"]); - Assert.True(document.SingleData.Relationships.ContainsKey("todo-items")); - Assert.Null(document.SingleData.Relationships["todo-items"].Data); + Assert.Equal(newPerson.LastName, document.SingleData.Attributes["lastName"]); + Assert.Equal(newPerson.FirstName, document.SingleData.Attributes["firstName"]); + Assert.True(document.SingleData.Relationships.ContainsKey("todoItems")); + Assert.Null(document.SingleData.Relationships["todoItems"].Data); } [Fact] @@ -235,7 +235,7 @@ public async Task Can_Patch_Entity_And_HasOne_Relationships() var client = server.CreateClient(); var serializer = _fixture.GetSerializer(ti => new { ti.Description, ti.Ordinal, ti.CreatedDate }, ti => new { ti.Owner }); var content = serializer.Serialize(todoItem); - var request = PrepareRequest("PATCH", $"/api/v1/todo-items/{todoItem.Id}", content); + var request = PrepareRequest("PATCH", $"/api/v1/todoItems/{todoItem.Id}", content); // Act var response = await client.SendAsync(request); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs index 6dd6744210..c21e8f3b0c 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs @@ -66,16 +66,16 @@ public async Task Can_Update_Cyclic_ToMany_Relationship_By_Patching_Resource() { data = new { - type = "todo-items", + type = "todoItems", id = todoItem.Id, relationships = new Dictionary { - { "children-todos", new + { "childrenTodos", new { data = new object[] { - new { type = "todo-items", id = $"{todoItem.Id}" }, - new { type = "todo-items", id = $"{strayTodoItem.Id}" } + new { type = "todoItems", id = $"{todoItem.Id}" }, + new { type = "todoItems", id = $"{strayTodoItem.Id}" } } } @@ -85,7 +85,7 @@ public async Task Can_Update_Cyclic_ToMany_Relationship_By_Patching_Resource() }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var request = new HttpRequestMessage(httpMethod, route); string serializedContent = JsonConvert.SerializeObject(content); @@ -100,10 +100,10 @@ public async Task Can_Update_Cyclic_ToMany_Relationship_By_Patching_Resource() var updatedTodoItem = _context.TodoItems.AsNoTracking() .Where(ti => ti.Id == todoItem.Id) - .Include(ti => ti.ChildrenTodoItems).First(); + .Include(ti => ti.ChildrenTodos).First(); - updatedTodoItem.ChildrenTodoItems.Any((ti) => ti.Id == todoItem.Id); - Assert.Contains(updatedTodoItem.ChildrenTodoItems, (ti) => ti.Id == todoItem.Id); + updatedTodoItem.ChildrenTodos.Any((ti) => ti.Id == todoItem.Id); + Assert.Contains(updatedTodoItem.ChildrenTodos, (ti) => ti.Id == todoItem.Id); } [Fact] @@ -127,13 +127,13 @@ public async Task Can_Update_Cyclic_ToOne_Relationship_By_Patching_Resource() { data = new { - type = "todo-items", + type = "todoItems", id = todoItem.Id, relationships = new Dictionary { - { "dependent-on-todo", new + { "dependentOnTodo", new { - data = new { type = "todo-items", id = $"{todoItem.Id}" } + data = new { type = "todoItems", id = $"{todoItem.Id}" } } } } @@ -141,7 +141,7 @@ public async Task Can_Update_Cyclic_ToOne_Relationship_By_Patching_Resource() }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var request = new HttpRequestMessage(httpMethod, route); string serializedContent = JsonConvert.SerializeObject(content); @@ -157,9 +157,9 @@ public async Task Can_Update_Cyclic_ToOne_Relationship_By_Patching_Resource() var updatedTodoItem = _context.TodoItems.AsNoTracking() .Where(ti => ti.Id == todoItem.Id) - .Include(ti => ti.DependentTodoItem).First(); + .Include(ti => ti.DependentOnTodo).First(); - Assert.Equal(todoItem.Id, updatedTodoItem.DependentTodoItemId); + Assert.Equal(todoItem.Id, updatedTodoItem.DependentOnTodoId); } [Fact] @@ -184,21 +184,21 @@ public async Task Can_Update_Both_Cyclic_ToOne_And_ToMany_Relationship_By_Patchi { data = new { - type = "todo-items", + type = "todoItems", id = todoItem.Id, relationships = new Dictionary { - { "dependent-on-todo", new + { "dependentOnTodo", new { - data = new { type = "todo-items", id = $"{todoItem.Id}" } + data = new { type = "todoItems", id = $"{todoItem.Id}" } } }, - { "children-todos", new + { "childrenTodos", new { data = new object[] { - new { type = "todo-items", id = $"{todoItem.Id}" }, - new { type = "todo-items", id = $"{strayTodoItem.Id}" } + new { type = "todoItems", id = $"{todoItem.Id}" }, + new { type = "todoItems", id = $"{strayTodoItem.Id}" } } } } @@ -207,7 +207,7 @@ public async Task Can_Update_Both_Cyclic_ToOne_And_ToMany_Relationship_By_Patchi }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var request = new HttpRequestMessage(httpMethod, route); string serializedContent = JsonConvert.SerializeObject(content); @@ -223,9 +223,9 @@ public async Task Can_Update_Both_Cyclic_ToOne_And_ToMany_Relationship_By_Patchi var updatedTodoItem = _context.TodoItems.AsNoTracking() .Where(ti => ti.Id == todoItem.Id) - .Include(ti => ti.ParentTodoItem).First(); + .Include(ti => ti.ParentTodo).First(); - Assert.Equal(todoItem.Id, updatedTodoItem.ParentTodoItemId); + Assert.Equal(todoItem.Id, updatedTodoItem.ParentTodoId); } [Fact] @@ -256,16 +256,16 @@ public async Task Can_Update_ToMany_Relationship_By_Patching_Resource() { data = new { - type = "todo-collections", + type = "todoCollections", id = todoCollection.Id, relationships = new Dictionary { - { "todo-items", new + { "todoItems", new { data = new object[] { - new { type = "todo-items", id = $"{newTodoItem1.Id}" }, - new { type = "todo-items", id = $"{newTodoItem2.Id}" } + new { type = "todoItems", id = $"{newTodoItem1.Id}" }, + new { type = "todoItems", id = $"{newTodoItem2.Id}" } } } @@ -275,7 +275,7 @@ public async Task Can_Update_ToMany_Relationship_By_Patching_Resource() }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-collections/{todoCollection.Id}"; + var route = $"/api/v1/todoCollections/{todoCollection.Id}"; var request = new HttpRequestMessage(httpMethod, route); string serializedContent = JsonConvert.SerializeObject(content); @@ -331,7 +331,7 @@ public async Task Can_Update_ToMany_Relationship_By_Patching_Resource_When_Targe { data = new { - type = "todo-collections", + type = "todoCollections", id = todoCollection.Id, attributes = new { @@ -339,12 +339,12 @@ public async Task Can_Update_ToMany_Relationship_By_Patching_Resource_When_Targe }, relationships = new Dictionary { - { "todo-items", new + { "todoItems", new { data = new object[] { - new { type = "todo-items", id = $"{newTodoItem1.Id}" }, - new { type = "todo-items", id = $"{newTodoItem2.Id}" } + new { type = "todoItems", id = $"{newTodoItem1.Id}" }, + new { type = "todoItems", id = $"{newTodoItem2.Id}" } } } @@ -354,7 +354,7 @@ public async Task Can_Update_ToMany_Relationship_By_Patching_Resource_When_Targe }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-collections/{todoCollection.Id}"; + var route = $"/api/v1/todoCollections/{todoCollection.Id}"; var request = new HttpRequestMessage(httpMethod, route); string serializedContent = JsonConvert.SerializeObject(content); @@ -401,16 +401,16 @@ public async Task Can_Update_ToMany_Relationship_By_Patching_Resource_With_Overl { data = new { - type = "todo-collections", + type = "todoCollections", id = todoCollection.Id, relationships = new Dictionary { - { "todo-items", new + { "todoItems", new { data = new object[] { - new { type = "todo-items", id = $"{todoItem1.Id}" }, - new { type = "todo-items", id = $"{todoItem2.Id}" } + new { type = "todoItems", id = $"{todoItem1.Id}" }, + new { type = "todoItems", id = $"{todoItem2.Id}" } } } @@ -420,7 +420,7 @@ public async Task Can_Update_ToMany_Relationship_By_Patching_Resource_With_Overl }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-collections/{todoCollection.Id}"; + var route = $"/api/v1/todoCollections/{todoCollection.Id}"; var request = new HttpRequestMessage(httpMethod, route); string serializedContent = JsonConvert.SerializeObject(content); @@ -464,14 +464,14 @@ public async Task Can_Update_ToMany_Relationship_ThroughLink() data = new List { new { - type = "todo-items", + type = "todoItems", id = $"{todoItem.Id}" } } }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/people/{person.Id}/relationships/todo-items"; + var route = $"/api/v1/people/{person.Id}/relationships/todoItems"; var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(JsonConvert.SerializeObject(content)); @@ -509,7 +509,7 @@ public async Task Can_Update_ToOne_Relationship_ThroughLink() var content = serializer.Serialize(person); var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-items/{todoItem.Id}/relationships/owner"; + var route = $"/api/v1/todoItems/{todoItem.Id}/relationships/owner"; var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(content); @@ -547,7 +547,7 @@ public async Task Can_Delete_ToOne_Relationship_By_Patching_Resource() data = new { id = todoItem.Id, - type = "todo-items", + type = "todoItems", relationships = new { owner = new @@ -559,7 +559,7 @@ public async Task Can_Delete_ToOne_Relationship_By_Patching_Resource() }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(JsonConvert.SerializeObject(content)); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json"); @@ -602,7 +602,7 @@ public async Task Can_Delete_ToMany_Relationship_By_Patching_Resource() type = "people", relationships = new Dictionary { - { "todo-items", new + { "todoItems", new { data = new List { @@ -659,7 +659,7 @@ public async Task Can_Delete_Relationship_By_Patching_Relationship() }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-items/{todoItem.Id}/relationships/owner"; + var route = $"/api/v1/todoItems/{todoItem.Id}/relationships/owner"; var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(JsonConvert.SerializeObject(content)); @@ -748,16 +748,16 @@ public async Task Updating_ToMany_Relationship_With_Implicit_Remove() id = person2.Id, relationships = new Dictionary { - { "todo-items", new + { "todoItems", new { data = new List { new { - type = "todo-items", + type = "todoItems", id = $"{todoItem1Id}" }, new { - type = "todo-items", + type = "todoItems", id = $"{todoItem2Id}" } } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs index 420f04f4a4..79a19c8c9a 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs @@ -36,8 +36,8 @@ public TestFixture() public IRequestSerializer GetSerializer(Expression> attributes = null, Expression> relationships = null) where TResource : class, IIdentifiable { - var serializer = GetService(); - var graph = GetService(); + var serializer = GetService(); + var graph = GetService(); if (attributes != null) serializer.AttributesToSerialize = graph.GetAttributes(attributes); if (relationships != null) @@ -50,19 +50,19 @@ public IResponseDeserializer GetDeserializer() .AddResource() .AddResource
() .AddResource() - .AddResource() + .AddResource() .AddResource() .AddResource() .AddResource() .AddResource() .AddResource() - .AddResource("todo-items") + .AddResource("todoItems") .AddResource().Build(); return new ResponseDeserializer(resourceGraph); } public T GetService() => (T)_services.GetService(typeof(T)); - + public void ReloadDbContext() { Context = new AppDbContext(GetService>()); @@ -88,4 +88,4 @@ public void Dispose() Dispose(true); } } -} +} \ No newline at end of file diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs index a69ae3a70a..a58e394fd0 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs @@ -61,7 +61,7 @@ public async Task Can_Get_TodoItems_Paginate_Check() } var httpMethod = new HttpMethod("GET"); - var route = "/api/v1/todo-items"; + var route = "/api/v1/todoItems"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -84,7 +84,7 @@ public async Task Can_Filter_By_Resource_Id() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?filter[id]={todoItem.Id}"; + var route = $"/api/v1/todoItems?filter[id]={todoItem.Id}"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -109,7 +109,7 @@ public async Task Can_Filter_By_Relationship_Id() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?filter[owner.id]={person.Id}"; + var route = $"/api/v1/todoItems?filter[owner.id]={person.Id}"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -135,7 +135,7 @@ public async Task Can_Filter_TodoItems() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?filter[ordinal]={todoItem.Ordinal}"; + var route = $"/api/v1/todoItems?filter[ordinal]={todoItem.Ordinal}"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -165,7 +165,7 @@ public async Task Can_Filter_TodoItems_Using_IsNotNull_Operator() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?filter[updated-date]=isnotnull:"; + var route = $"/api/v1/todoItems?filter[updatedDate]=isnotnull:"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -196,7 +196,7 @@ public async Task Can_Filter_TodoItems_ByParent_Using_IsNotNull_Operator() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?filter[assignee.id]=isnotnull:"; + var route = $"/api/v1/todoItems?filter[assignee.id]=isnotnull:"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -224,7 +224,7 @@ public async Task Can_Filter_TodoItems_Using_IsNull_Operator() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?filter[updated-date]=isnull:"; + var route = $"/api/v1/todoItems?filter[updatedDate]=isnull:"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -254,7 +254,7 @@ public async Task Can_Filter_TodoItems_ByParent_Using_IsNull_Operator() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?filter[assignee.id]=isnull:"; + var route = $"/api/v1/todoItems?filter[assignee.id]=isnull:"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -281,7 +281,7 @@ public async Task Can_Filter_TodoItems_Using_Like_Operator() var substring = todoItem.Description.Substring(1, todoItem.Description.Length - 2); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?filter[description]=like:{substring}"; + var route = $"/api/v1/todoItems?filter[description]=like:{substring}"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -316,7 +316,7 @@ public async Task Can_Sort_TodoItems_By_Ordinal_Ascending() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?sort=ordinal"; + var route = $"/api/v1/todoItems?sort=ordinal"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -354,7 +354,7 @@ public async Task Can_Sort_TodoItems_By_Nested_Attribute_Ascending() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?page[size]={numberOfItems}&include=owner&sort=owner.age"; + var route = $"/api/v1/todoItems?page[size]={numberOfItems}&include=owner&sort=owner.age"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -392,7 +392,7 @@ public async Task Can_Sort_TodoItems_By_Nested_Attribute_Descending() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?page[size]={numberOfItems}&include=owner&sort=-owner.age"; + var route = $"/api/v1/todoItems?page[size]={numberOfItems}&include=owner&sort=-owner.age"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -431,7 +431,7 @@ public async Task Can_Sort_TodoItems_By_Ordinal_Descending() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?sort=-ordinal"; + var route = $"/api/v1/todoItems?sort=-ordinal"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -462,7 +462,7 @@ public async Task Can_Get_TodoItem_ById() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -490,7 +490,7 @@ public async Task Can_Get_TodoItem_WithOwner() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items/{todoItem.Id}?include=owner"; + var route = $"/api/v1/todoItems/{todoItem.Id}?include=owner"; var request = new HttpRequestMessage(httpMethod, route); // Act @@ -524,7 +524,7 @@ public async Task Can_Post_TodoItem() todoItem.OffsetDate = nowOffset; var httpMethod = new HttpMethod("POST"); - var route = $"/api/v1/todo-items"; + var route = $"/api/v1/todoItems"; var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(serializer.Serialize(todoItem)); @@ -560,12 +560,12 @@ public async Task Can_Post_TodoItem_With_Different_Owner_And_Assignee() { data = new { - type = "todo-items", + type = "todoItems", attributes = new Dictionary() { { "description", todoItem.Description }, { "ordinal", todoItem.Ordinal }, - { "created-date", todoItem.CreatedDate } + { "createdDate", todoItem.CreatedDate } }, relationships = new { @@ -590,7 +590,7 @@ public async Task Can_Post_TodoItem_With_Different_Owner_And_Assignee() }; var httpMethod = new HttpMethod("POST"); - var route = $"/api/v1/todo-items"; + var route = $"/api/v1/todoItems"; var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(JsonConvert.SerializeObject(content)); @@ -632,18 +632,18 @@ public async Task Can_Patch_TodoItem() data = new { id = todoItem.Id, - type = "todo-items", + type = "todoItems", attributes = new Dictionary() { { "description", newTodoItem.Description }, { "ordinal", newTodoItem.Ordinal }, - { "created-date", newTodoItem.CreatedDate } + { "createdDate", newTodoItem.CreatedDate } } } }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(JsonConvert.SerializeObject(content)); @@ -684,19 +684,19 @@ public async Task Can_Patch_TodoItemWithNullable() data = new { id = todoItem.Id, - type = "todo-items", + type = "todoItems", attributes = new Dictionary() { { "description", newTodoItem.Description }, { "ordinal", newTodoItem.Ordinal }, - { "created-date", newTodoItem.CreatedDate }, - { "achieved-date", newTodoItem.AchievedDate } + { "createdDate", newTodoItem.CreatedDate }, + { "achievedDate", newTodoItem.AchievedDate } } } }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(JsonConvert.SerializeObject(content)); @@ -736,19 +736,19 @@ public async Task Can_Patch_TodoItemWithNullValue() data = new { id = todoItem.Id, - type = "todo-items", + type = "todoItems", attributes = new Dictionary() { { "description", newTodoItem.Description }, { "ordinal", newTodoItem.Ordinal }, - { "created-date", newTodoItem.CreatedDate }, - { "achieved-date", null } + { "createdDate", newTodoItem.CreatedDate }, + { "achievedDate", null } } } }; var httpMethod = new HttpMethod("PATCH"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(JsonConvert.SerializeObject(content)); @@ -781,7 +781,7 @@ public async Task Can_Delete_TodoItem() _context.SaveChanges(); var httpMethod = new HttpMethod("DELETE"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(string.Empty); diff --git a/test/JsonApiDotNetCoreExampleTests/CamelCaseTestStartup.cs b/test/JsonApiDotNetCoreExampleTests/CamelCaseTestStartup.cs deleted file mode 100644 index f801c593a7..0000000000 --- a/test/JsonApiDotNetCoreExampleTests/CamelCaseTestStartup.cs +++ /dev/null @@ -1,25 +0,0 @@ -using JsonApiDotNetCore.Extensions; -using JsonApiDotNetCore.Graph; -using JsonApiDotNetCore.Services; -using JsonApiDotNetCoreExample; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using System; -using UnitTests; - -namespace JsonApiDotNetCoreExampleTests -{ - public class CamelCaseTestStartup : Startup - { - public CamelCaseTestStartup(IWebHostEnvironment env) : base(env) - { } - - public override void ConfigureServices(IServiceCollection services) - { - services.AddSingleton(); - base.ConfigureServices(services); - services.AddClientSerialization(); - services.AddScoped(); - } - } -} diff --git a/test/JsonApiDotNetCoreExampleTests/Factories/ClientEnabledIdsApplicationFactory.cs b/test/JsonApiDotNetCoreExampleTests/Factories/ClientEnabledIdsApplicationFactory.cs new file mode 100644 index 0000000000..91d832e062 --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/Factories/ClientEnabledIdsApplicationFactory.cs @@ -0,0 +1,31 @@ +using JsonApiDotNetCore.Extensions; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using System.Reflection; + +namespace JsonApiDotNetCoreExampleTests +{ + public class ClientEnabledIdsApplicationFactory : CustomApplicationFactoryBase + { + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + builder.ConfigureServices(services => + { + services.AddClientSerialization(); + }); + + builder.ConfigureTestServices(services => + { + services.AddJsonApi(options => + { + options.Namespace = "api/v1"; + options.DefaultPageSize = 5; + options.IncludeTotalRecordCount = true; + options.LoadDatabaseValues = true; + options.AllowClientGeneratedIds = true; + }, + discovery => discovery.AddAssembly(Assembly.Load(nameof(JsonApiDotNetCoreExample)))); + }); + } + } +} diff --git a/test/JsonApiDotNetCoreExampleTests/Factories/CustomApplicationFactoryBase.cs b/test/JsonApiDotNetCoreExampleTests/Factories/CustomApplicationFactoryBase.cs new file mode 100644 index 0000000000..d94b8f001b --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/Factories/CustomApplicationFactoryBase.cs @@ -0,0 +1,27 @@ +using JsonApiDotNetCoreExample; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Extensions.DependencyInjection; +using System.Net.Http; + +namespace JsonApiDotNetCoreExampleTests +{ + public class CustomApplicationFactoryBase : WebApplicationFactory, IApplicationFactory + { + public readonly HttpClient Client; + private readonly IServiceScope _scope; + + public CustomApplicationFactoryBase() + { + Client = CreateClient(); + _scope = Services.CreateScope(); + } + + public T GetService() => (T)_scope.ServiceProvider.GetService(typeof(T)); + } + + public interface IApplicationFactory + { + T GetService(); + HttpClient CreateClient(); + } +} diff --git a/test/JsonApiDotNetCoreExampleTests/Factories/KebabCaseApplicationFactory.cs b/test/JsonApiDotNetCoreExampleTests/Factories/KebabCaseApplicationFactory.cs new file mode 100644 index 0000000000..a51dfde0b0 --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/Factories/KebabCaseApplicationFactory.cs @@ -0,0 +1,19 @@ +using JsonApiDotNetCore.Extensions; +using JsonApiDotNetCore.Graph; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; + +namespace JsonApiDotNetCoreExampleTests +{ + public class KebabCaseApplicationFactory : CustomApplicationFactoryBase + { + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + builder.ConfigureServices(services => + { + services.AddSingleton(); + services.AddClientSerialization(); + }); + } + } +} diff --git a/test/JsonApiDotNetCoreExampleTests/Factories/StandardApplicationFactory.cs b/test/JsonApiDotNetCoreExampleTests/Factories/StandardApplicationFactory.cs new file mode 100644 index 0000000000..26222b8602 --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/Factories/StandardApplicationFactory.cs @@ -0,0 +1,16 @@ +using JsonApiDotNetCore.Extensions; +using Microsoft.AspNetCore.Hosting; + +namespace JsonApiDotNetCoreExampleTests +{ + public class StandardApplicationFactory : CustomApplicationFactoryBase + { + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + builder.ConfigureServices(services => + { + services.AddClientSerialization(); + }); + } + } +} diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Models/TodoItemClient.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Models/TodoItemClient.cs index 77e928358f..ae15c5d7b2 100644 --- a/test/JsonApiDotNetCoreExampleTests/Helpers/Models/TodoItemClient.cs +++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Models/TodoItemClient.cs @@ -13,28 +13,21 @@ namespace JsonApiDotNetCoreExampleTests.Helpers.Models /// public class TodoItemClient : TodoItem { - [Attr("calculated-value")] + [Attr] public new string CalculatedValue { get; set; } } - //[Resource("todo-collections")] - //public class TodoItemCollectionClient : TodoItemCollection - //{ - // [HasMany("todo-items")] - // public new List TodoItems { get; set; } - //} - - [Resource("todo-collections")] + [Resource("todoCollections")] public class TodoItemCollectionClient : Identifiable { - [Attr("name")] + [Attr] public string Name { get; set; } public int OwnerId { get; set; } - [HasMany("todo-items")] + [HasMany] public virtual List TodoItems { get; set; } - [HasOne("owner")] + [HasOne] public virtual Person Owner { get; set; } } } diff --git a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj index 7a099cdf48..d68923e892 100644 --- a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj +++ b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj @@ -26,11 +26,13 @@ + + diff --git a/test/JsonApiDotNetCoreExampleTests/TestStartup.cs b/test/JsonApiDotNetCoreExampleTests/TestStartup.cs deleted file mode 100644 index 73cc900b51..0000000000 --- a/test/JsonApiDotNetCoreExampleTests/TestStartup.cs +++ /dev/null @@ -1,22 +0,0 @@ -using JsonApiDotNetCore.Extensions; -using JsonApiDotNetCore.Services; -using JsonApiDotNetCoreExample; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using UnitTests; - -namespace JsonApiDotNetCoreExampleTests -{ - public class TestStartup : Startup - { - public TestStartup(IWebHostEnvironment env) : base(env) - { } - - public override void ConfigureServices(IServiceCollection services) - { - base.ConfigureServices(services); - services.AddClientSerialization(); - services.AddScoped(); - } - } -} diff --git a/test/NoEntityFrameworkTests/Acceptance/Extensibility/NoEntityFrameworkTests.cs b/test/NoEntityFrameworkTests/Acceptance/Extensibility/NoEntityFrameworkTests.cs index 06dd96a854..dc6506afdc 100644 --- a/test/NoEntityFrameworkTests/Acceptance/Extensibility/NoEntityFrameworkTests.cs +++ b/test/NoEntityFrameworkTests/Acceptance/Extensibility/NoEntityFrameworkTests.cs @@ -31,7 +31,7 @@ public async Task Can_Get_TodoItems() var client = _fixture.Server.CreateClient(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items"; + var route = $"/api/v1/todoItems"; var request = new HttpRequestMessage(httpMethod, route); @@ -57,7 +57,7 @@ public async Task Can_Get_TodoItems_By_Id() var client = _fixture.Server.CreateClient(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items/{todoItem.Id}"; + var route = $"/api/v1/todoItems/{todoItem.Id}"; var request = new HttpRequestMessage(httpMethod, route); @@ -78,12 +78,12 @@ public async Task Can_Create_TodoItems() // Arrange var description = Guid.NewGuid().ToString(); var httpMethod = new HttpMethod("POST"); - var route = $"/api/v1/todo-items/"; + var route = $"/api/v1/todoItems/"; var content = new { data = new { - type = "todo-items", + type = "todoItems", attributes = new { description, diff --git a/test/NoEntityFrameworkTests/TestFixture.cs b/test/NoEntityFrameworkTests/TestFixture.cs index c76e37e9bb..6a5f294a94 100644 --- a/test/NoEntityFrameworkTests/TestFixture.cs +++ b/test/NoEntityFrameworkTests/TestFixture.cs @@ -39,7 +39,7 @@ public IRequestSerializer GetSerializer(Expression("todo-items").Build(); + var resourceGraph = new ResourceGraphBuilder().AddResource("todoItems").Build(); return new ResponseDeserializer(resourceGraph); } diff --git a/test/UnitTests/Builders/ContextGraphBuilder_Tests.cs b/test/UnitTests/Builders/ContextGraphBuilder_Tests.cs index 058c8f05eb..434f2ba27d 100644 --- a/test/UnitTests/Builders/ContextGraphBuilder_Tests.cs +++ b/test/UnitTests/Builders/ContextGraphBuilder_Tests.cs @@ -29,15 +29,15 @@ public void Can_Build_ResourceGraph_Using_Builder() { // Arrange var services = new ServiceCollection(); - services.AddJsonApi(resources: builder => builder.AddResource("non-db-resources")); + services.AddJsonApi(resources: builder => builder.AddResource("nonDbResources")); // Act var container = services.BuildServiceProvider(); // Assert var resourceGraph = container.GetRequiredService(); - var dbResource = resourceGraph.GetResourceContext("db-resources"); - var nonDbResource = resourceGraph.GetResourceContext("non-db-resources"); + var dbResource = resourceGraph.GetResourceContext("dbResources"); + var nonDbResource = resourceGraph.GetResourceContext("nonDbResources"); Assert.Equal(typeof(DbResource), dbResource.ResourceType); Assert.Equal(typeof(NonDbResource), nonDbResource.ResourceType); Assert.Equal(typeof(ResourceDefinition), nonDbResource.ResourceDefinitionType); @@ -55,7 +55,7 @@ public void Resources_Without_Names_Specified_Will_Use_Default_Formatter() // Assert var resource = resourceGraph.GetResourceContext(typeof(TestResource)); - Assert.Equal("test-resources", resource.ResourceName); + Assert.Equal("testResources", resource.ResourceName); } [Fact] @@ -85,7 +85,7 @@ public void Attrs_Without_Names_Specified_Will_Use_Default_Formatter() // Assert var resource = resourceGraph.GetResourceContext(typeof(TestResource)); - Assert.Contains(resource.Attributes, (i) => i.PublicAttributeName == "compound-attribute"); + Assert.Contains(resource.Attributes, (i) => i.PublicAttributeName == "compoundAttribute"); } [Fact] @@ -115,8 +115,8 @@ public void Relationships_Without_Names_Specified_Will_Use_Default_Formatter() // Assert var resource = resourceGraph.GetResourceContext(typeof(TestResource)); - Assert.Equal("related-resource", resource.Relationships.Single(r => r.IsHasOne).PublicRelationshipName); - Assert.Equal("related-resources", resource.Relationships.Single(r => r.IsHasMany).PublicRelationshipName); + Assert.Equal("relatedResource", resource.Relationships.Single(r => r.IsHasOne).PublicRelationshipName); + Assert.Equal("relatedResources", resource.Relationships.Single(r => r.IsHasMany).PublicRelationshipName); } public class TestResource : Identifiable diff --git a/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs b/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs index d33ba1da04..06a95fd5e2 100644 --- a/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs +++ b/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs @@ -16,7 +16,7 @@ public class BaseJsonApiController_Tests { public class Resource : Identifiable { - [Attr("test-attribute")] public string TestAttribute { get; set; } + [Attr] public string TestAttribute { get; set; } } [Fact] diff --git a/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs b/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs index bd81705deb..7cae18b8df 100644 --- a/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs +++ b/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs @@ -152,7 +152,7 @@ public void AddJsonApi_With_Context_Uses_Resource_Type_Name_If_NoOtherSpecified( var provider = services.BuildServiceProvider(); var resourceGraph = provider.GetService(); var resource = resourceGraph.GetResourceContext(typeof(IntResource)); - Assert.Equal("int-resources", resource.ResourceName); + Assert.Equal("intResources", resource.ResourceName); } public class IntResource : Identifiable { } diff --git a/test/UnitTests/Models/ResourceDefinitionTests.cs b/test/UnitTests/Models/ResourceDefinitionTests.cs index 41529fc742..28e42dfbb5 100644 --- a/test/UnitTests/Models/ResourceDefinitionTests.cs +++ b/test/UnitTests/Models/ResourceDefinitionTests.cs @@ -49,9 +49,9 @@ public void Request_Filter_Uses_NewExpression() public class Model : Identifiable { - [Attr("name")] public string AlwaysExcluded { get; set; } - [Attr("password")] public string Password { get; set; } - [Attr("prop")] public string Prop { get; set; } + [Attr] public string AlwaysExcluded { get; set; } + [Attr] public string Password { get; set; } + [Attr] public string Prop { get; set; } } public class RequestFilteredResource : ResourceDefinition diff --git a/test/UnitTests/QueryParameters/IncludeServiceTests.cs b/test/UnitTests/QueryParameters/IncludeServiceTests.cs index 2230ed0b41..5c98aa2f04 100644 --- a/test/UnitTests/QueryParameters/IncludeServiceTests.cs +++ b/test/UnitTests/QueryParameters/IncludeServiceTests.cs @@ -34,7 +34,7 @@ public void Name_IncludeService_IsCorrect() public void Parse_MultipleNestedChains_CanParse() { // Arrange - const string chain = "author.blogs.reviewer.favorite-food,reviewer.blogs.author.favorite-song"; + const string chain = "author.blogs.reviewer.favoriteFood,reviewer.blogs.author.favoriteSong"; var query = new KeyValuePair("include", new StringValues(chain)); var service = GetService(); @@ -46,17 +46,17 @@ public void Parse_MultipleNestedChains_CanParse() Assert.Equal(2, chains.Count); var firstChain = chains[0]; Assert.Equal("author", firstChain.First().PublicRelationshipName); - Assert.Equal("favorite-food", firstChain.Last().PublicRelationshipName); + Assert.Equal("favoriteFood", firstChain.Last().PublicRelationshipName); var secondChain = chains[1]; Assert.Equal("reviewer", secondChain.First().PublicRelationshipName); - Assert.Equal("favorite-song", secondChain.Last().PublicRelationshipName); + Assert.Equal("favoriteSong", secondChain.Last().PublicRelationshipName); } [Fact] public void Parse_ChainsOnWrongMainResource_ThrowsJsonApiException() { // Arrange - const string chain = "author.blogs.reviewer.favorite-food,reviewer.blogs.author.favorite-song"; + const string chain = "author.blogs.reviewer.favoriteFood,reviewer.blogs.author.favoriteSong"; var query = new KeyValuePair("include", new StringValues(chain)); var service = GetService(_resourceGraph.GetResourceContext()); @@ -69,7 +69,7 @@ public void Parse_ChainsOnWrongMainResource_ThrowsJsonApiException() public void Parse_NotIncludable_ThrowsJsonApiException() { // Arrange - const string chain = "cannot-include"; + const string chain = "cannotInclude"; var query = new KeyValuePair("include", new StringValues(chain)); var service = GetService(); diff --git a/test/UnitTests/QueryParameters/SparseFieldsServiceTests.cs b/test/UnitTests/QueryParameters/SparseFieldsServiceTests.cs index a87b9e6927..75ccf847c9 100644 --- a/test/UnitTests/QueryParameters/SparseFieldsServiceTests.cs +++ b/test/UnitTests/QueryParameters/SparseFieldsServiceTests.cs @@ -33,7 +33,7 @@ public void Parse_ValidSelection_CanParse() { // Arrange const string type = "articles"; - const string attrName = "some-field"; + const string attrName = "someField"; const string internalAttrName = "SomeField"; var attribute = new AttrAttribute(attrName) { InternalAttributeName = internalAttrName }; var idAttribute = new AttrAttribute("id") { InternalAttributeName = "Id" }; @@ -63,7 +63,7 @@ public void Parse_TypeNameAsNavigation_Throws400ErrorWithRelationshipsOnlyMessag { // Arrange const string type = "articles"; - const string attrName = "some-field"; + const string attrName = "someField"; const string internalAttrName = "SomeField"; var attribute = new AttrAttribute(attrName) { InternalAttributeName = internalAttrName }; var idAttribute = new AttrAttribute("id") { InternalAttributeName = "Id" }; @@ -89,7 +89,7 @@ public void Parse_DeeplyNestedSelection_Throws400ErrorWithDeeplyNestedMessage() // Arrange const string type = "articles"; const string relationship = "author.employer"; - const string attrName = "some-field"; + const string attrName = "someField"; const string internalAttrName = "SomeField"; var attribute = new AttrAttribute(attrName) { InternalAttributeName = internalAttrName }; var idAttribute = new AttrAttribute("id") { InternalAttributeName = "Id" }; diff --git a/test/UnitTests/ResourceHooks/AffectedEntitiesHelperTests.cs b/test/UnitTests/ResourceHooks/AffectedEntitiesHelperTests.cs index 2d22742625..ec748a8308 100644 --- a/test/UnitTests/ResourceHooks/AffectedEntitiesHelperTests.cs +++ b/test/UnitTests/ResourceHooks/AffectedEntitiesHelperTests.cs @@ -12,11 +12,11 @@ public class Dummy : Identifiable public string SomeUpdatedProperty { get; set; } public string SomeNotUpdatedProperty { get; set; } - [HasOne("first-to-one")] + [HasOne] public ToOne FirstToOne { get; set; } - [HasOne("second-to-one")] + [HasOne] public ToOne SecondToOne { get; set; } - [HasMany("to-manies")] + [HasMany] public List ToManies { get; set; } } @@ -38,19 +38,19 @@ public class RelationshipDictionaryTests public readonly HashSet AllEntities; public RelationshipDictionaryTests() { - FirstToOneAttr = new HasOneAttribute("first-to-one") + FirstToOneAttr = new HasOneAttribute("firstToOne") { LeftType = typeof(Dummy), RightType = typeof(ToOne), InternalRelationshipName = "FirstToOne" }; - SecondToOneAttr = new HasOneAttribute("second-to-one") + SecondToOneAttr = new HasOneAttribute("secondToOne") { LeftType = typeof(Dummy), RightType = typeof(ToOne), InternalRelationshipName = "SecondToOne" }; - ToManyAttr = new HasManyAttribute("to-manies") + ToManyAttr = new HasManyAttribute("toManies") { LeftType = typeof(Dummy), RightType = typeof(ToMany), diff --git a/test/UnitTests/ResourceHooks/ResourceHookExecutor/Create/BeforeCreate_WithDbValues_Tests.cs b/test/UnitTests/ResourceHooks/ResourceHookExecutor/Create/BeforeCreate_WithDbValues_Tests.cs index ab9d15ad29..31246bb210 100644 --- a/test/UnitTests/ResourceHooks/ResourceHookExecutor/Create/BeforeCreate_WithDbValues_Tests.cs +++ b/test/UnitTests/ResourceHooks/ResourceHookExecutor/Create/BeforeCreate_WithDbValues_Tests.cs @@ -26,11 +26,11 @@ public BeforeCreate_WithDbValues_Tests() todoList[0].Id = 0; todoList[0].Description = description; - var _personId = todoList[0].ToOnePerson.Id; + var _personId = todoList[0].OneToOnePerson.Id; personId = _personId.ToString(); var implicitTodo = _todoFaker.Generate(); implicitTodo.Id += 1000; - implicitTodo.ToOnePersonId = _personId; + implicitTodo.OneToOnePersonId = _personId; implicitTodo.Description = description + description; options = InitInMemoryDb(context => diff --git a/test/UnitTests/ResourceHooks/ResourceHookExecutor/Delete/BeforeDelete_WithDbValue_Tests.cs b/test/UnitTests/ResourceHooks/ResourceHookExecutor/Delete/BeforeDelete_WithDbValue_Tests.cs index 45db4ecb9a..07f59ec219 100644 --- a/test/UnitTests/ResourceHooks/ResourceHookExecutor/Delete/BeforeDelete_WithDbValue_Tests.cs +++ b/test/UnitTests/ResourceHooks/ResourceHookExecutor/Delete/BeforeDelete_WithDbValue_Tests.cs @@ -25,7 +25,7 @@ public BeforeDelete_WithDbValues_Tests() person.Passport = passport; person.TodoItems = new List { todo1 }; - person.StakeHolderTodo = todo2; + person.StakeHolderTodoItem = todo2; options = InitInMemoryDb(context => { context.Set().Add(person); diff --git a/test/UnitTests/ResourceHooks/ResourceHookExecutor/Read/BeforeReadTests.cs b/test/UnitTests/ResourceHooks/ResourceHookExecutor/Read/BeforeReadTests.cs index e776868689..3cb8a7dc72 100644 --- a/test/UnitTests/ResourceHooks/ResourceHookExecutor/Read/BeforeReadTests.cs +++ b/test/UnitTests/ResourceHooks/ResourceHookExecutor/Read/BeforeReadTests.cs @@ -39,8 +39,8 @@ public void BeforeReadWithInclusion() var (iqMock, _, hookExecutor, todoResourceMock, ownerResourceMock) = CreateTestObjects(todoDiscovery, personDiscovery); var todoList = CreateTodoWithOwner(); - // eg a call on api/todo-items?include=owner,assignee,stake-holders - iqMock.Setup(c => c.Get()).Returns(GetIncludedRelationshipsChains("owner", "assignee", "stake-holders")); + // eg a call on api/todoItems?include=owner,assignee,stakeHolders + iqMock.Setup(c => c.Get()).Returns(GetIncludedRelationshipsChains("owner", "assignee", "stakeHolders")); // Act hookExecutor.BeforeRead(ResourcePipeline.Get); @@ -61,8 +61,8 @@ public void BeforeReadWithNestedInclusion() var (iqMock, hookExecutor, todoResourceMock, ownerResourceMock, passportResourceMock) = CreateTestObjects(todoDiscovery, personDiscovery, passportDiscovery); var todoList = CreateTodoWithOwner(); - // eg a call on api/todo-items?include=owner.passport,assignee,stake-holders - iqMock.Setup(c => c.Get()).Returns(GetIncludedRelationshipsChains("owner.passport", "assignee", "stake-holders")); + // eg a call on api/todoItems?include=owner.passport,assignee,stakeHolders + iqMock.Setup(c => c.Get()).Returns(GetIncludedRelationshipsChains("owner.passport", "assignee", "stakeHolders")); // Act hookExecutor.BeforeRead(ResourcePipeline.Get); @@ -85,8 +85,8 @@ public void BeforeReadWithNestedInclusion_No_Parent_Hook_Implemented() var (iqMock, hookExecutor, todoResourceMock, ownerResourceMock, passportResourceMock) = CreateTestObjects(todoDiscovery, personDiscovery, passportDiscovery); var todoList = CreateTodoWithOwner(); - // eg a call on api/todo-items?include=owner.passport,assignee,stake-holders - iqMock.Setup(c => c.Get()).Returns(GetIncludedRelationshipsChains("owner.passport", "assignee", "stake-holders")); + // eg a call on api/todoItems?include=owner.passport,assignee,stakeHolders + iqMock.Setup(c => c.Get()).Returns(GetIncludedRelationshipsChains("owner.passport", "assignee", "stakeHolders")); // Act hookExecutor.BeforeRead(ResourcePipeline.Get); @@ -107,8 +107,8 @@ public void BeforeReadWithNestedInclusion_No_Child_Hook_Implemented() var (iqMock, hookExecutor, todoResourceMock, ownerResourceMock, passportResourceMock) = CreateTestObjects(todoDiscovery, personDiscovery, passportDiscovery); var todoList = CreateTodoWithOwner(); - // eg a call on api/todo-items?include=owner.passport,assignee,stake-holders - iqMock.Setup(c => c.Get()).Returns(GetIncludedRelationshipsChains("owner.passport", "assignee", "stake-holders")); + // eg a call on api/todoItems?include=owner.passport,assignee,stakeHolders + iqMock.Setup(c => c.Get()).Returns(GetIncludedRelationshipsChains("owner.passport", "assignee", "stakeHolders")); // Act hookExecutor.BeforeRead(ResourcePipeline.Get); @@ -129,8 +129,8 @@ public void BeforeReadWithNestedInclusion_No_Grandchild_Hook_Implemented() var (iqMock, hookExecutor, todoResourceMock, ownerResourceMock, passportResourceMock) = CreateTestObjects(todoDiscovery, personDiscovery, passportDiscovery); var todoList = CreateTodoWithOwner(); - // eg a call on api/todo-items?include=owner.passport,assignee,stake-holders - iqMock.Setup(c => c.Get()).Returns(GetIncludedRelationshipsChains("owner.passport", "assignee", "stake-holders")); + // eg a call on api/todoItems?include=owner.passport,assignee,stakeHolders + iqMock.Setup(c => c.Get()).Returns(GetIncludedRelationshipsChains("owner.passport", "assignee", "stakeHolders")); // Act hookExecutor.BeforeRead(ResourcePipeline.Get); @@ -152,8 +152,8 @@ public void BeforeReadWithNestedInclusion_Without_Any_Hook_Implemented() var (iqMock, hookExecutor, todoResourceMock, ownerResourceMock, passportResourceMock) = CreateTestObjects(todoDiscovery, personDiscovery, passportDiscovery); var todoList = CreateTodoWithOwner(); - // eg a call on api/todo-items?include=owner.passport,assignee,stake-holders - iqMock.Setup(c => c.Get()).Returns(GetIncludedRelationshipsChains("owner.passport", "assignee", "stake-holders")); + // eg a call on api/todoItems?include=owner.passport,assignee,stakeHolders + iqMock.Setup(c => c.Get()).Returns(GetIncludedRelationshipsChains("owner.passport", "assignee", "stakeHolders")); // Act hookExecutor.BeforeRead(ResourcePipeline.Get); diff --git a/test/UnitTests/ResourceHooks/ResourceHookExecutor/ScenarioTests.cs b/test/UnitTests/ResourceHooks/ResourceHookExecutor/ScenarioTests.cs index ca1c96db33..544b3df2e0 100644 --- a/test/UnitTests/ResourceHooks/ResourceHookExecutor/ScenarioTests.cs +++ b/test/UnitTests/ResourceHooks/ResourceHookExecutor/ScenarioTests.cs @@ -21,7 +21,7 @@ public void Entity_Has_Multiple_Relations_To_Same_Type() var todo = new TodoItem { Owner = person1 }; var person2 = new Person { AssignedTodoItems = new List() { todo } }; todo.Assignee = person2; - var person3 = new Person { StakeHolderTodo = todo }; + var person3 = new Person { StakeHolderTodoItem = todo }; todo.StakeHolders = new List { person3 }; var todoList = new List() { todo }; @@ -41,8 +41,8 @@ public void Entity_Has_Cyclic_Relations() var todoDiscovery = SetDiscoverableHooks(targetHooks, DisableDbValues); (var contextMock, var hookExecutor, var todoResourceMock) = CreateTestObjects(todoDiscovery); var todo = new TodoItem(); - todo.ParentTodoItem = todo; - todo.ChildrenTodoItems = new List { todo }; + todo.ParentTodo = todo; + todo.ChildrenTodos = new List { todo }; var todoList = new List() { todo }; // Act @@ -60,13 +60,13 @@ public void Entity_Has_Nested_Cyclic_Relations() var todoDiscovery = SetDiscoverableHooks(targetHooks, DisableDbValues); (var contextMock, var hookExecutor, var todoResourceMock) = CreateTestObjects(todoDiscovery); var rootTodo = new TodoItem() { Id = 1 }; - var child = new TodoItem { ParentTodoItem = rootTodo, Id = 2 }; - rootTodo.ChildrenTodoItems = new List { child }; - var grandChild = new TodoItem() { ParentTodoItem = child, Id = 3 }; - child.ChildrenTodoItems = new List { grandChild }; - var greatGrandChild = new TodoItem() { ParentTodoItem = grandChild, Id = 4 }; - grandChild.ChildrenTodoItems = new List { greatGrandChild }; - greatGrandChild.ChildrenTodoItems = new List { rootTodo }; + var child = new TodoItem { ParentTodo = rootTodo, Id = 2 }; + rootTodo.ChildrenTodos = new List { child }; + var grandChild = new TodoItem() { ParentTodo = child, Id = 3 }; + child.ChildrenTodos = new List { grandChild }; + var greatGrandChild = new TodoItem() { ParentTodo = grandChild, Id = 4 }; + grandChild.ChildrenTodos = new List { greatGrandChild }; + greatGrandChild.ChildrenTodos = new List { rootTodo }; var todoList = new List() { rootTodo }; // Act diff --git a/test/UnitTests/ResourceHooks/ResourceHookExecutor/Update/BeforeUpdate_WithDbValues_Tests.cs b/test/UnitTests/ResourceHooks/ResourceHookExecutor/Update/BeforeUpdate_WithDbValues_Tests.cs index 05425ffb8e..ed145f23b3 100644 --- a/test/UnitTests/ResourceHooks/ResourceHookExecutor/Update/BeforeUpdate_WithDbValues_Tests.cs +++ b/test/UnitTests/ResourceHooks/ResourceHookExecutor/Update/BeforeUpdate_WithDbValues_Tests.cs @@ -25,20 +25,20 @@ public BeforeUpdate_WithDbValues_Tests() todoList = CreateTodoWithToOnePerson(); var todoId = todoList[0].Id; - var _personId = todoList[0].ToOnePerson.Id; + var _personId = todoList[0].OneToOnePerson.Id; personId = _personId.ToString(); var _implicitPersonId = (_personId + 10000); var implicitTodo = _todoFaker.Generate(); implicitTodo.Id += 1000; - implicitTodo.ToOnePersonId = _personId; + implicitTodo.OneToOnePersonId = _personId; implicitTodo.Description = description + description; options = InitInMemoryDb(context => { context.Set().Add(new Person { Id = _personId, LastName = lastName }); context.Set().Add(new Person { Id = _implicitPersonId, LastName = lastName + lastName }); - context.Set().Add(new TodoItem { Id = todoId, ToOnePersonId = _implicitPersonId, Description = description }); + context.Set().Add(new TodoItem { Id = todoId, OneToOnePersonId = _implicitPersonId, Description = description }); context.Set().Add(implicitTodo); context.SaveChanges(); }); @@ -82,7 +82,7 @@ public void BeforeUpdate_Deleting_Relationship() var personDiscovery = SetDiscoverableHooks(targetHooks, EnableDbValues); var (_, ufMock, hookExecutor, todoResourceMock, ownerResourceMock) = CreateTestObjects(todoDiscovery, personDiscovery, repoDbContextOptions: options); - ufMock.Setup(c => c.Relationships).Returns(_resourceGraph.GetRelationships((TodoItem t) => t.ToOnePerson)); + ufMock.Setup(c => c.Relationships).Returns(_resourceGraph.GetRelationships((TodoItem t) => t.OneToOnePerson)); // Act var _todoList = new List() { new TodoItem { Id = this.todoList[0].Id } }; @@ -207,9 +207,9 @@ private bool TodoCheckDiff(IDiffableEntityHashSet entities, string che var diffPairCheck = (dbCheck && reqCheck); var updatedRelationship = entities.GetByRelationship().Single(); - var diffcheck = updatedRelationship.Key.PublicRelationshipName == "one-to-one-person"; + var diffcheck = updatedRelationship.Key.PublicRelationshipName == "oneToOnePerson"; - var getAffectedCheck = entities.GetAffected(e => e.ToOnePerson).Any(); + var getAffectedCheck = entities.GetAffected(e => e.OneToOnePerson).Any(); return (dbCheck && reqCheck && diffcheck && getAffectedCheck); } diff --git a/test/UnitTests/ResourceHooks/ResourceHooksTestsSetup.cs b/test/UnitTests/ResourceHooks/ResourceHooksTestsSetup.cs index ea7db285d6..35dfe52cde 100644 --- a/test/UnitTests/ResourceHooks/ResourceHooksTestsSetup.cs +++ b/test/UnitTests/ResourceHooks/ResourceHooksTestsSetup.cs @@ -64,8 +64,8 @@ protected List CreateTodoWithToOnePerson() var todoItem = _todoFaker.Generate(); var person = _personFaker.Generate(); var todoList = new List() { todoItem }; - person.ToOneTodoItem = todoItem; - todoItem.ToOnePerson = person; + person.OneToOneTodoItem = todoItem; + todoItem.OneToOnePerson = person; return todoList; } diff --git a/test/UnitTests/Serialization/Client/RequestSerializerTests.cs b/test/UnitTests/Serialization/Client/RequestSerializerTests.cs index 7938cae1ea..ce4e2ad578 100644 --- a/test/UnitTests/Serialization/Client/RequestSerializerTests.cs +++ b/test/UnitTests/Serialization/Client/RequestSerializerTests.cs @@ -33,16 +33,16 @@ public void SerializeSingle_ResourceWithDefaultTargetFields_CanBuild() var expectedFormatted = @"{ ""data"":{ - ""type"":""test-resource"", + ""type"":""testResource"", ""id"":""1"", ""attributes"":{ - ""string-field"":""value"", - ""date-time-field"":""0001-01-01T00:00:00"", - ""nullable-date-time-field"":null, - ""int-field"":0, - ""nullable-int-field"":123, - ""guid-field"":""00000000-0000-0000-0000-000000000000"", - ""complex-field"":null, + ""stringField"":""value"", + ""dateTimeField"":""0001-01-01T00:00:00"", + ""nullableDateTimeField"":null, + ""intField"":0, + ""nullableIntField"":123, + ""guidField"":""00000000-0000-0000-0000-000000000000"", + ""complexField"":null, ""immutable"":null } } @@ -65,10 +65,10 @@ public void SerializeSingle_ResourceWithTargetedSetAttributes_CanBuild() var expectedFormatted = @"{ ""data"":{ - ""type"":""test-resource"", + ""type"":""testResource"", ""id"":""1"", ""attributes"":{ - ""string-field"":""value"" + ""stringField"":""value"" } } }"; @@ -90,9 +90,9 @@ public void SerializeSingle_NoIdWithTargetedSetAttributes_CanBuild() var expectedFormatted = @"{ ""data"":{ - ""type"":""test-resource"", + ""type"":""testResource"", ""attributes"":{ - ""string-field"":""value"" + ""stringField"":""value"" } } }"; @@ -115,7 +115,7 @@ public void SerializeSingle_ResourceWithoutTargetedAttributes_CanBuild() var expectedFormatted = @"{ ""data"":{ - ""type"":""test-resource"", + ""type"":""testResource"", ""id"":""1"" } }"; @@ -141,27 +141,27 @@ public void SerializeSingle_ResourceWithTargetedRelationships_CanBuild() var expectedFormatted = @"{ ""data"":{ - ""type"":""multi-principals"", + ""type"":""multiPrincipals"", ""attributes"":{ - ""attribute-member"":null + ""attributeMember"":null }, ""relationships"":{ - ""empty-to-one"":{ + ""emptyToOne"":{ ""data"":null }, - ""empty-to-manies"":{ + ""emptyToManies"":{ ""data"":[ ] }, - ""populated-to-one"":{ + ""populatedToOne"":{ ""data"":{ - ""type"":""one-to-one-dependents"", + ""type"":""oneToOneDependents"", ""id"":""10"" } }, - ""populated-to-manies"":{ + ""populatedToManies"":{ ""data"":[ { - ""type"":""one-to-many-dependents"", + ""type"":""oneToManyDependents"", ""id"":""20"" } ] @@ -192,17 +192,17 @@ public void SerializeMany_ResourcesWithTargetedAttributes_CanBuild() @"{ ""data"":[ { - ""type"":""test-resource"", + ""type"":""testResource"", ""id"":""1"", ""attributes"":{ - ""string-field"":""value1"" + ""stringField"":""value1"" } }, { - ""type"":""test-resource"", + ""type"":""testResource"", ""id"":""2"", ""attributes"":{ - ""string-field"":""value2"" + ""stringField"":""value2"" } } ] diff --git a/test/UnitTests/Serialization/Client/ResponseDeserializerTests.cs b/test/UnitTests/Serialization/Client/ResponseDeserializerTests.cs index f798e77388..0ffdc6f5ef 100644 --- a/test/UnitTests/Serialization/Client/ResponseDeserializerTests.cs +++ b/test/UnitTests/Serialization/Client/ResponseDeserializerTests.cs @@ -101,33 +101,33 @@ public void DeserializeSingle_ResourceWithAttributes_CanDeserialize() Assert.Null(result.Links); Assert.Null(result.Meta); Assert.Equal(1, entity.Id); - Assert.Equal(content.SingleData.Attributes["string-field"], entity.StringField); + Assert.Equal(content.SingleData.Attributes["stringField"], entity.StringField); } [Fact] public void DeserializeSingle_MultipleDependentRelationshipsWithIncluded_CanDeserialize() { // Arrange - var content = CreateDocumentWithRelationships("multi-principals"); - content.SingleData.Relationships.Add("populated-to-one", CreateRelationshipData("one-to-one-dependents")); - content.SingleData.Relationships.Add("populated-to-manies", CreateRelationshipData("one-to-many-dependents", isToManyData: true)); - content.SingleData.Relationships.Add("empty-to-one", CreateRelationshipData()); - content.SingleData.Relationships.Add("empty-to-manies", CreateRelationshipData(isToManyData: true)); - var toOneAttributeValue = "populated-to-one member content"; - var toManyAttributeValue = "populated-to-manies member content"; + var content = CreateDocumentWithRelationships("multiPrincipals"); + content.SingleData.Relationships.Add("populatedToOne", CreateRelationshipData("oneToOneDependents")); + content.SingleData.Relationships.Add("populatedToManies", CreateRelationshipData("oneToManyDependents", isToManyData: true)); + content.SingleData.Relationships.Add("emptyToOne", CreateRelationshipData()); + content.SingleData.Relationships.Add("emptyToManies", CreateRelationshipData(isToManyData: true)); + var toOneAttributeValue = "populatedToOne member content"; + var toManyAttributeValue = "populatedToManies member content"; content.Included = new List() { new ResourceObject() { - Type = "one-to-one-dependents", + Type = "oneToOneDependents", Id = "10", - Attributes = new Dictionary() { {"attribute-member", toOneAttributeValue } } + Attributes = new Dictionary() { {"attributeMember", toOneAttributeValue } } }, new ResourceObject() { - Type = "one-to-many-dependents", + Type = "oneToManyDependents", Id = "10", - Attributes = new Dictionary() { {"attribute-member", toManyAttributeValue } } + Attributes = new Dictionary() { {"attributeMember", toManyAttributeValue } } } }; var body = JsonConvert.SerializeObject(content); @@ -151,26 +151,26 @@ public void DeserializeSingle_MultipleDependentRelationshipsWithIncluded_CanDese public void DeserializeSingle_MultiplePrincipalRelationshipsWithIncluded_CanDeserialize() { // Arrange - var content = CreateDocumentWithRelationships("multi-dependents"); - content.SingleData.Relationships.Add("populated-to-one", CreateRelationshipData("one-to-one-principals")); - content.SingleData.Relationships.Add("populated-to-many", CreateRelationshipData("one-to-many-principals")); - content.SingleData.Relationships.Add("empty-to-one", CreateRelationshipData()); - content.SingleData.Relationships.Add("empty-to-many", CreateRelationshipData()); - var toOneAttributeValue = "populated-to-one member content"; - var toManyAttributeValue = "populated-to-manies member content"; + var content = CreateDocumentWithRelationships("multiDependents"); + content.SingleData.Relationships.Add("populatedToOne", CreateRelationshipData("oneToOnePrincipals")); + content.SingleData.Relationships.Add("populatedToMany", CreateRelationshipData("oneToManyPrincipals")); + content.SingleData.Relationships.Add("emptyToOne", CreateRelationshipData()); + content.SingleData.Relationships.Add("emptyToMany", CreateRelationshipData()); + var toOneAttributeValue = "populatedToOne member content"; + var toManyAttributeValue = "populatedToManies member content"; content.Included = new List() { new ResourceObject() { - Type = "one-to-one-principals", + Type = "oneToOnePrincipals", Id = "10", - Attributes = new Dictionary() { {"attribute-member", toOneAttributeValue } } + Attributes = new Dictionary() { {"attributeMember", toOneAttributeValue } } }, new ResourceObject() { - Type = "one-to-many-principals", + Type = "oneToManyPrincipals", Id = "10", - Attributes = new Dictionary() { {"attribute-member", toManyAttributeValue } } + Attributes = new Dictionary() { {"attributeMember", toManyAttributeValue } } } }; var body = JsonConvert.SerializeObject(content); @@ -193,24 +193,24 @@ public void DeserializeSingle_MultiplePrincipalRelationshipsWithIncluded_CanDese public void DeserializeSingle_NestedIncluded_CanDeserialize() { // Arrange - var content = CreateDocumentWithRelationships("multi-principals"); - content.SingleData.Relationships.Add("populated-to-manies", CreateRelationshipData("one-to-many-dependents", isToManyData: true)); - var toManyAttributeValue = "populated-to-manies member content"; + var content = CreateDocumentWithRelationships("multiPrincipals"); + content.SingleData.Relationships.Add("populatedToManies", CreateRelationshipData("oneToManyDependents", isToManyData: true)); + var toManyAttributeValue = "populatedToManies member content"; var nestedIncludeAttributeValue = "nested include member content"; content.Included = new List() { new ResourceObject() { - Type = "one-to-many-dependents", + Type = "oneToManyDependents", Id = "10", - Attributes = new Dictionary() { {"attribute-member", toManyAttributeValue } }, - Relationships = new Dictionary { { "principal", CreateRelationshipData("one-to-many-principals") } } + Attributes = new Dictionary() { {"attributeMember", toManyAttributeValue } }, + Relationships = new Dictionary { { "principal", CreateRelationshipData("oneToManyPrincipals") } } }, new ResourceObject() { - Type = "one-to-many-principals", + Type = "oneToManyPrincipals", Id = "10", - Attributes = new Dictionary() { {"attribute-member", nestedIncludeAttributeValue } } + Attributes = new Dictionary() { {"attributeMember", nestedIncludeAttributeValue } } } }; var body = JsonConvert.SerializeObject(content); @@ -236,8 +236,8 @@ public void DeserializeSingle_NestedIncluded_CanDeserialize() public void DeserializeSingle_DeeplyNestedIncluded_CanDeserialize() { // Arrange - var content = CreateDocumentWithRelationships("multi-principals"); - content.SingleData.Relationships.Add("multi", CreateRelationshipData("multi-principals")); + var content = CreateDocumentWithRelationships("multiPrincipals"); + content.SingleData.Relationships.Add("multi", CreateRelationshipData("multiPrincipals")); var includedAttributeValue = "multi member content"; var nestedIncludedAttributeValue = "nested include member content"; var deeplyNestedIncludedAttributeValue = "deeply nested member content"; @@ -245,23 +245,23 @@ public void DeserializeSingle_DeeplyNestedIncluded_CanDeserialize() { new ResourceObject() { - Type = "multi-principals", + Type = "multiPrincipals", Id = "10", - Attributes = new Dictionary() { {"attribute-member", includedAttributeValue } }, - Relationships = new Dictionary { { "populated-to-manies", CreateRelationshipData("one-to-many-dependents", isToManyData: true) } } + Attributes = new Dictionary() { {"attributeMember", includedAttributeValue } }, + Relationships = new Dictionary { { "populatedToManies", CreateRelationshipData("oneToManyDependents", isToManyData: true) } } }, new ResourceObject() { - Type = "one-to-many-dependents", + Type = "oneToManyDependents", Id = "10", - Attributes = new Dictionary() { {"attribute-member", nestedIncludedAttributeValue } }, - Relationships = new Dictionary { { "principal", CreateRelationshipData("one-to-many-principals") } } + Attributes = new Dictionary() { {"attributeMember", nestedIncludedAttributeValue } }, + Relationships = new Dictionary { { "principal", CreateRelationshipData("oneToManyPrincipals") } } }, new ResourceObject() { - Type = "one-to-many-principals", + Type = "oneToManyPrincipals", Id = "10", - Attributes = new Dictionary() { {"attribute-member", deeplyNestedIncludedAttributeValue } } + Attributes = new Dictionary() { {"attributeMember", deeplyNestedIncludedAttributeValue } } }, }; var body = JsonConvert.SerializeObject(content); @@ -288,8 +288,8 @@ public void DeserializeSingle_DeeplyNestedIncluded_CanDeserialize() public void DeserializeList_DeeplyNestedIncluded_CanDeserialize() { // Arrange - var content = new Document { Data = new List { CreateDocumentWithRelationships("multi-principals").SingleData } }; - content.ManyData[0].Relationships.Add("multi", CreateRelationshipData("multi-principals")); + var content = new Document { Data = new List { CreateDocumentWithRelationships("multiPrincipals").SingleData } }; + content.ManyData[0].Relationships.Add("multi", CreateRelationshipData("multiPrincipals")); var includedAttributeValue = "multi member content"; var nestedIncludedAttributeValue = "nested include member content"; var deeplyNestedIncludedAttributeValue = "deeply nested member content"; @@ -297,23 +297,23 @@ public void DeserializeList_DeeplyNestedIncluded_CanDeserialize() { new ResourceObject() { - Type = "multi-principals", + Type = "multiPrincipals", Id = "10", - Attributes = new Dictionary() { {"attribute-member", includedAttributeValue } }, - Relationships = new Dictionary { { "populated-to-manies", CreateRelationshipData("one-to-many-dependents", isToManyData: true) } } + Attributes = new Dictionary() { {"attributeMember", includedAttributeValue } }, + Relationships = new Dictionary { { "populatedToManies", CreateRelationshipData("oneToManyDependents", isToManyData: true) } } }, new ResourceObject() { - Type = "one-to-many-dependents", + Type = "oneToManyDependents", Id = "10", - Attributes = new Dictionary() { {"attribute-member", nestedIncludedAttributeValue } }, - Relationships = new Dictionary { { "principal", CreateRelationshipData("one-to-many-principals") } } + Attributes = new Dictionary() { {"attributeMember", nestedIncludedAttributeValue } }, + Relationships = new Dictionary { { "principal", CreateRelationshipData("oneToManyPrincipals") } } }, new ResourceObject() { - Type = "one-to-many-principals", + Type = "oneToManyPrincipals", Id = "10", - Attributes = new Dictionary() { {"attribute-member", deeplyNestedIncludedAttributeValue } } + Attributes = new Dictionary() { {"attributeMember", deeplyNestedIncludedAttributeValue } } }, }; var body = JsonConvert.SerializeObject(content); diff --git a/test/UnitTests/Serialization/Common/DocumentParserTests.cs b/test/UnitTests/Serialization/Common/DocumentParserTests.cs index 562fb7d2c5..aef9e115f5 100644 --- a/test/UnitTests/Serialization/Common/DocumentParserTests.cs +++ b/test/UnitTests/Serialization/Common/DocumentParserTests.cs @@ -27,7 +27,7 @@ public void DeserializeResourceIdentifiers_SingleData_CanDeserialize() { Data = new ResourceObject { - Type = "test-resource", + Type = "testResource", Id = "1", } }; @@ -64,7 +64,7 @@ public void DeserializeResourceIdentifiers_ArrayData_CanDeserialize() { new ResourceObject { - Type = "test-resource", + Type = "testResource", Id = "1", } } @@ -92,18 +92,18 @@ public void DeserializeResourceIdentifiers_EmptyArrayData_CanDeserialize() } [Theory] - [InlineData("string-field", "some string")] - [InlineData("string-field", null)] - [InlineData("int-field", null, true)] - [InlineData("int-field", 1)] - [InlineData("int-field", "1")] - [InlineData("nullable-int-field", null)] - [InlineData("nullable-int-field", "1")] - [InlineData("guid-field", "bad format", true)] - [InlineData("guid-field", "1a68be43-cc84-4924-a421-7f4d614b7781")] - [InlineData("date-time-field", "9/11/2019 11:41:40 AM")] - [InlineData("date-time-field", null, true)] - [InlineData("nullable-date-time-field", null)] + [InlineData("stringField", "some string")] + [InlineData("stringField", null)] + [InlineData("intField", null, true)] + [InlineData("intField", 1)] + [InlineData("intField", "1")] + [InlineData("nullableIntField", null)] + [InlineData("nullableIntField", "1")] + [InlineData("guidField", "bad format", true)] + [InlineData("guidField", "1a68be43-cc84-4924-a421-7f4d614b7781")] + [InlineData("dateTimeField", "9/11/2019 11:41:40 AM")] + [InlineData("dateTimeField", null, true)] + [InlineData("nullableDateTimeField", null)] public void DeserializeAttributes_VariousDataTypes_CanDeserialize(string member, object value, bool expectError = false) { // Arrange @@ -111,7 +111,7 @@ public void DeserializeAttributes_VariousDataTypes_CanDeserialize(string member, { Data = new ResourceObject { - Type = "test-resource", + Type = "testResource", Id = "1", Attributes = new Dictionary { @@ -132,26 +132,26 @@ public void DeserializeAttributes_VariousDataTypes_CanDeserialize(string member, var entity = (TestResource)_deserializer.Deserialize(body); // Assert - var pi = _resourceGraph.GetResourceContext("test-resource").Attributes.Single(attr => attr.PublicAttributeName == member).PropertyInfo; + var pi = _resourceGraph.GetResourceContext("testResource").Attributes.Single(attr => attr.PublicAttributeName == member).PropertyInfo; var deserializedValue = pi.GetValue(entity); - if (member == "int-field") + if (member == "intField") { Assert.Equal(1, deserializedValue); } - else if (member == "nullable-int-field" && value == null) + else if (member == "nullableIntField" && value == null) { Assert.Null(deserializedValue); } - else if (member == "nullable-int-field" && (string)value == "1") + else if (member == "nullableIntField" && (string)value == "1") { Assert.Equal(1, deserializedValue); } - else if (member == "guid-field") + else if (member == "guidField") { Assert.Equal(deserializedValue, Guid.Parse("1a68be43-cc84-4924-a421-7f4d614b7781")); } - else if (member == "date-time-field") + else if (member == "dateTimeField") { Assert.Equal(deserializedValue, DateTime.Parse("9/11/2019 11:41:40 AM")); } @@ -169,11 +169,11 @@ public void DeserializeAttributes_ComplexType_CanDeserialize() { Data = new ResourceObject { - Type = "test-resource", + Type = "testResource", Id = "1", Attributes = new Dictionary { - { "complex-field", new Dictionary { {"compoundName", "testName" } } } // this is not right + { "complexField", new Dictionary { {"compoundName", "testName" } } } // this is not right } } }; @@ -195,11 +195,11 @@ public void DeserializeAttributes_ComplexListType_CanDeserialize() { Data = new ResourceObject { - Type = "test-resource-with-list", + Type = "testResource-with-list", Id = "1", Attributes = new Dictionary { - { "complex-fields", new [] { new Dictionary { {"compoundName", "testName" } } } } + { "complexFields", new [] { new Dictionary { {"compoundName", "testName" } } } } } } }; @@ -219,7 +219,7 @@ public void DeserializeAttributes_ComplexListType_CanDeserialize() public void DeserializeRelationships_EmptyOneToOneDependent_NavigationPropertyIsNull() { // Arrange - var content = CreateDocumentWithRelationships("one-to-one-principals", "dependent"); + var content = CreateDocumentWithRelationships("oneToOnePrincipals", "dependent"); var body = JsonConvert.SerializeObject(content); // Act @@ -235,7 +235,7 @@ public void DeserializeRelationships_EmptyOneToOneDependent_NavigationPropertyIs public void DeserializeRelationships_PopulatedOneToOneDependent_NavigationPropertyIsPopulated() { // Arrange - var content = CreateDocumentWithRelationships("one-to-one-principals", "dependent", "one-to-one-dependents"); + var content = CreateDocumentWithRelationships("oneToOnePrincipals", "dependent", "oneToOneDependents"); var body = JsonConvert.SerializeObject(content); // Act @@ -251,7 +251,7 @@ public void DeserializeRelationships_PopulatedOneToOneDependent_NavigationProper public void DeserializeRelationships_EmptyOneToOnePrincipal_NavigationPropertyAndForeignKeyAreNull() { // Arrange - var content = CreateDocumentWithRelationships("one-to-one-dependents", "principal"); + var content = CreateDocumentWithRelationships("oneToOneDependents", "principal"); var body = JsonConvert.SerializeObject(content); // Act @@ -267,7 +267,7 @@ public void DeserializeRelationships_EmptyOneToOnePrincipal_NavigationPropertyAn public void DeserializeRelationships_EmptyRequiredOneToOnePrincipal_ThrowsFormatException() { // Arrange - var content = CreateDocumentWithRelationships("one-to-one-required-dependents", "principal"); + var content = CreateDocumentWithRelationships("oneToOneRequiredDependents", "principal"); var body = JsonConvert.SerializeObject(content); // Act, assert @@ -278,7 +278,7 @@ public void DeserializeRelationships_EmptyRequiredOneToOnePrincipal_ThrowsFormat public void DeserializeRelationships_PopulatedOneToOnePrincipal_NavigationPropertyAndForeignKeyArePopulated() { // Arrange - var content = CreateDocumentWithRelationships("one-to-one-dependents", "principal", "one-to-one-principals"); + var content = CreateDocumentWithRelationships("oneToOneDependents", "principal", "oneToOnePrincipals"); var body = JsonConvert.SerializeObject(content); // Act @@ -296,7 +296,7 @@ public void DeserializeRelationships_PopulatedOneToOnePrincipal_NavigationProper public void DeserializeRelationships_EmptyOneToManyPrincipal_NavigationAndForeignKeyAreNull() { // Arrange - var content = CreateDocumentWithRelationships("one-to-many-dependents", "principal"); + var content = CreateDocumentWithRelationships("oneToManyDependents", "principal"); var body = JsonConvert.SerializeObject(content); // Act @@ -313,7 +313,7 @@ public void DeserializeRelationships_EmptyOneToManyPrincipal_NavigationAndForeig public void DeserializeRelationships_EmptyOneToManyRequiredPrincipal_ThrowsFormatException() { // Arrange - var content = CreateDocumentWithRelationships("one-to-many-required-dependents", "principal"); + var content = CreateDocumentWithRelationships("oneToMany-requiredDependents", "principal"); var body = JsonConvert.SerializeObject(content); // Act, assert @@ -324,7 +324,7 @@ public void DeserializeRelationships_EmptyOneToManyRequiredPrincipal_ThrowsForma public void DeserializeRelationships_PopulatedOneToManyPrincipal_NavigationAndForeignKeyArePopulated() { // Arrange - var content = CreateDocumentWithRelationships("one-to-many-dependents", "principal", "one-to-many-principals"); + var content = CreateDocumentWithRelationships("oneToManyDependents", "principal", "oneToManyPrincipals"); var body = JsonConvert.SerializeObject(content); // Act @@ -342,7 +342,7 @@ public void DeserializeRelationships_PopulatedOneToManyPrincipal_NavigationAndFo public void DeserializeRelationships_EmptyOneToManyDependent_NavigationIsNull() { // Arrange - var content = CreateDocumentWithRelationships("one-to-many-principals", "dependents"); + var content = CreateDocumentWithRelationships("oneToManyPrincipals", "dependents"); var body = JsonConvert.SerializeObject(content); // Act @@ -358,7 +358,7 @@ public void DeserializeRelationships_EmptyOneToManyDependent_NavigationIsNull() public void DeserializeRelationships_PopulatedOneToManyDependent_NavigationIsPopulated() { // Arrange - var content = CreateDocumentWithRelationships("one-to-many-principals", "dependents", "one-to-many-dependents", isToManyData: true); + var content = CreateDocumentWithRelationships("oneToManyPrincipals", "dependents", "oneToManyDependents", isToManyData: true); var body = JsonConvert.SerializeObject(content); // Act diff --git a/test/UnitTests/Serialization/Common/ResourceObjectBuilderTests.cs b/test/UnitTests/Serialization/Common/ResourceObjectBuilderTests.cs index de04a47a97..46304c5e9d 100644 --- a/test/UnitTests/Serialization/Common/ResourceObjectBuilderTests.cs +++ b/test/UnitTests/Serialization/Common/ResourceObjectBuilderTests.cs @@ -32,7 +32,7 @@ public void EntityToResourceObject_EmptyResource_CanBuild() Assert.Null(resourceObject.Attributes); Assert.Null(resourceObject.Relationships); Assert.Null(resourceObject.Id); - Assert.Equal("test-resource", resourceObject.Type); + Assert.Equal("testResource", resourceObject.Type); } [Fact] @@ -48,7 +48,7 @@ public void EntityToResourceObject_ResourceWithId_CanBuild() Assert.Equal("1", resourceObject.Id); Assert.Null(resourceObject.Attributes); Assert.Null(resourceObject.Relationships); - Assert.Equal("test-resource", resourceObject.Type); + Assert.Equal("testResource", resourceObject.Type); } [Theory] @@ -66,8 +66,8 @@ public void EntityToResourceObject_ResourceWithIncludedAttrs_CanBuild(string str // Assert Assert.NotNull(resourceObject.Attributes); Assert.Equal(2, resourceObject.Attributes.Keys.Count); - Assert.Equal(stringFieldValue, resourceObject.Attributes["string-field"]); - Assert.Equal(intFieldValue, resourceObject.Attributes["nullable-int-field"]); + Assert.Equal(stringFieldValue, resourceObject.Attributes["stringField"]); + Assert.Equal(intFieldValue, resourceObject.Attributes["nullableIntField"]); } [Fact] @@ -83,7 +83,7 @@ public void EntityWithRelationshipsToResourceObject_EmptyResource_CanBuild() Assert.Null(resourceObject.Attributes); Assert.Null(resourceObject.Relationships); Assert.Null(resourceObject.Id); - Assert.Equal("multi-principals", resourceObject.Type); + Assert.Equal("multiPrincipals", resourceObject.Type); } [Fact] @@ -102,7 +102,7 @@ public void EntityWithRelationshipsToResourceObject_ResourceWithId_CanBuild() Assert.Null(resourceObject.Attributes); Assert.Null(resourceObject.Relationships); Assert.Null(resourceObject.Id); - Assert.Equal("multi-principals", resourceObject.Type); + Assert.Equal("multiPrincipals", resourceObject.Type); } [Fact] @@ -121,16 +121,16 @@ public void EntityWithRelationshipsToResourceObject_WithIncludedRelationshipsAtt // Assert Assert.Equal(4, resourceObject.Relationships.Count); - Assert.Null(resourceObject.Relationships["empty-to-one"].Data); - Assert.Empty((IList)resourceObject.Relationships["empty-to-manies"].Data); - var populatedToOneData = (ResourceIdentifierObject)resourceObject.Relationships["populated-to-one"].Data; + Assert.Null(resourceObject.Relationships["emptyToOne"].Data); + Assert.Empty((IList)resourceObject.Relationships["emptyToManies"].Data); + var populatedToOneData = (ResourceIdentifierObject)resourceObject.Relationships["populatedToOne"].Data; Assert.NotNull(populatedToOneData); Assert.Equal("10", populatedToOneData.Id); - Assert.Equal("one-to-one-dependents", populatedToOneData.Type); - var populatedToManiesData = (List)resourceObject.Relationships["populated-to-manies"].Data; + Assert.Equal("oneToOneDependents", populatedToOneData.Type); + var populatedToManiesData = (List)resourceObject.Relationships["populatedToManies"].Data; Assert.Single(populatedToManiesData); Assert.Equal("20", populatedToManiesData.First().Id); - Assert.Equal("one-to-many-dependents", populatedToManiesData.First().Type); + Assert.Equal("oneToManyDependents", populatedToManiesData.First().Type); } [Fact] diff --git a/test/UnitTests/Serialization/DeserializerTestsSetup.cs b/test/UnitTests/Serialization/DeserializerTestsSetup.cs index dc9dff4aae..bfdfdacfee 100644 --- a/test/UnitTests/Serialization/DeserializerTestsSetup.cs +++ b/test/UnitTests/Serialization/DeserializerTestsSetup.cs @@ -62,15 +62,15 @@ protected Document CreateTestResourceDocument() { Data = new ResourceObject { - Type = "test-resource", + Type = "testResource", Id = "1", Attributes = new Dictionary { - { "string-field", "some string" }, - { "int-field", 1 }, - { "nullable-int-field", null }, - { "guid-field", "1a68be43-cc84-4924-a421-7f4d614b7781" }, - { "date-time-field", "9/11/2019 11:41:40 AM" } + { "stringField", "some string" }, + { "intField", 1 }, + { "nullableIntField", null }, + { "guidField", "1a68be43-cc84-4924-a421-7f4d614b7781" }, + { "dateTimeField", "9/11/2019 11:41:40 AM" } } } }; diff --git a/test/UnitTests/Serialization/SerializationTestsSetupBase.cs b/test/UnitTests/Serialization/SerializationTestsSetupBase.cs index c56e4a532e..81ea58bb92 100644 --- a/test/UnitTests/Serialization/SerializationTestsSetupBase.cs +++ b/test/UnitTests/Serialization/SerializationTestsSetupBase.cs @@ -38,19 +38,19 @@ public SerializationTestsSetupBase() protected IResourceGraph BuildGraph() { var resourceGraphBuilder = new ResourceGraphBuilder(); - resourceGraphBuilder.AddResource("test-resource"); - resourceGraphBuilder.AddResource("test-resource-with-list"); + resourceGraphBuilder.AddResource("testResource"); + resourceGraphBuilder.AddResource("testResource-with-list"); // one to one relationships - resourceGraphBuilder.AddResource("one-to-one-principals"); - resourceGraphBuilder.AddResource("one-to-one-dependents"); - resourceGraphBuilder.AddResource("one-to-one-required-dependents"); + resourceGraphBuilder.AddResource("oneToOnePrincipals"); + resourceGraphBuilder.AddResource("oneToOneDependents"); + resourceGraphBuilder.AddResource("oneToOneRequiredDependents"); // one to many relationships - resourceGraphBuilder.AddResource("one-to-many-principals"); - resourceGraphBuilder.AddResource("one-to-many-dependents"); - resourceGraphBuilder.AddResource("one-to-many-required-dependents"); + resourceGraphBuilder.AddResource("oneToManyPrincipals"); + resourceGraphBuilder.AddResource("oneToManyDependents"); + resourceGraphBuilder.AddResource("oneToMany-requiredDependents"); // collective relationships - resourceGraphBuilder.AddResource("multi-principals"); - resourceGraphBuilder.AddResource("multi-dependents"); + resourceGraphBuilder.AddResource("multiPrincipals"); + resourceGraphBuilder.AddResource("multiDependents"); resourceGraphBuilder.AddResource
(); resourceGraphBuilder.AddResource(); diff --git a/test/UnitTests/Serialization/Server/IncludedResourceObjectBuilderTests.cs b/test/UnitTests/Serialization/Server/IncludedResourceObjectBuilderTests.cs index b477023432..f30d40dc5b 100644 --- a/test/UnitTests/Serialization/Server/IncludedResourceObjectBuilderTests.cs +++ b/test/UnitTests/Serialization/Server/IncludedResourceObjectBuilderTests.cs @@ -16,7 +16,7 @@ public void BuildIncluded_DeeplyNestedCircularChainOfSingleData_CanBuild() { // Arrange var (article, author, authorFood, reviewer, reviewerFood) = GetAuthorChainInstances(); - var authorChain = GetIncludedRelationshipsChain("author.blogs.reviewer.favorite-food"); + var authorChain = GetIncludedRelationshipsChain("author.blogs.reviewer.favoriteFood"); var builder = GetBuilder(); // Act @@ -27,11 +27,11 @@ public void BuildIncluded_DeeplyNestedCircularChainOfSingleData_CanBuild() Assert.Equal(6, result.Count); var authorResourceObject = result.Single((ro) => ro.Type == "people" && ro.Id == author.StringId); - var authorFoodRelation = authorResourceObject.Relationships["favorite-food"].SingleData; + var authorFoodRelation = authorResourceObject.Relationships["favoriteFood"].SingleData; Assert.Equal(author.FavoriteFood.StringId, authorFoodRelation.Id); var reviewerResourceObject = result.Single((ro) => ro.Type == "people" && ro.Id == reviewer.StringId); - var reviewerFoodRelation = reviewerResourceObject.Relationships["favorite-food"].SingleData; + var reviewerFoodRelation = reviewerResourceObject.Relationships["favoriteFood"].SingleData; Assert.Equal(reviewer.FavoriteFood.StringId, reviewerFoodRelation.Id); } @@ -45,7 +45,7 @@ public void BuildIncluded_DeeplyNestedCircularChainOfManyData_BuildsWithoutDupli var builder = GetBuilder(); // Act - var authorChain = GetIncludedRelationshipsChain("author.blogs.reviewer.favorite-food"); + var authorChain = GetIncludedRelationshipsChain("author.blogs.reviewer.favoriteFood"); builder.IncludeRelationshipChain(authorChain, article); builder.IncludeRelationshipChain(authorChain, secondArticle); @@ -58,12 +58,12 @@ public void BuildIncluded_DeeplyNestedCircularChainOfManyData_BuildsWithoutDupli public void BuildIncluded_OverlappingDeeplyNestedCirculairChains_CanBuild() { // Arrange - var authorChain = GetIncludedRelationshipsChain("author.blogs.reviewer.favorite-food"); + var authorChain = GetIncludedRelationshipsChain("author.blogs.reviewer.favoriteFood"); var (article, author, authorFood, reviewer, reviewerFood) = GetAuthorChainInstances(); var sharedBlog = author.Blogs.First(); var sharedBlogAuthor = reviewer; var (_reviewer, _reviewerSong, _author, _authorSong) = GetReviewerChainInstances(article, sharedBlog, sharedBlogAuthor); - var reviewerChain = GetIncludedRelationshipsChain("reviewer.blogs.author.favorite-song"); + var reviewerChain = GetIncludedRelationshipsChain("reviewer.blogs.author.favoriteSong"); var builder = GetBuilder(); // Act @@ -82,9 +82,9 @@ public void BuildIncluded_OverlappingDeeplyNestedCirculairChains_CanBuild() Assert.Single(blog.Relationships.Keys.ToList()); var sharedAuthorResourceObject = result.Single((ro) => ro.Type == "people" && ro.Id == sharedBlogAuthor.StringId); - var sharedAuthorSongRelation = sharedAuthorResourceObject.Relationships["favorite-song"].SingleData; + var sharedAuthorSongRelation = sharedAuthorResourceObject.Relationships["favoriteSong"].SingleData; Assert.Equal(_authorSong.StringId, sharedBlogAuthor.FavoriteSong.StringId); - var sharedAuthorFoodRelation = sharedAuthorResourceObject.Relationships["favorite-food"].SingleData; + var sharedAuthorFoodRelation = sharedAuthorResourceObject.Relationships["favoriteFood"].SingleData; Assert.Equal(reviewerFood.StringId, sharedBlogAuthor.FavoriteFood.StringId); } diff --git a/test/UnitTests/Serialization/Server/RequestDeserializerTests.cs b/test/UnitTests/Serialization/Server/RequestDeserializerTests.cs index ac68e8b37b..faef53944e 100644 --- a/test/UnitTests/Serialization/Server/RequestDeserializerTests.cs +++ b/test/UnitTests/Serialization/Server/RequestDeserializerTests.cs @@ -46,7 +46,7 @@ public void DeserializeAttributes_UpdatedImmutableMember_ThrowsInvalidOperationE { Data = new ResourceObject { - Type = "test-resource", + Type = "testResource", Id = "1", Attributes = new Dictionary { @@ -65,11 +65,11 @@ public void DeserializeRelationships_MultipleDependentRelationships_RegistersUpd { // Arrange SetupFieldsManager(out List attributesToUpdate, out List relationshipsToUpdate); - var content = CreateDocumentWithRelationships("multi-principals"); - content.SingleData.Relationships.Add("populated-to-one", CreateRelationshipData("one-to-one-dependents")); - content.SingleData.Relationships.Add("empty-to-one", CreateRelationshipData()); - content.SingleData.Relationships.Add("populated-to-manies", CreateRelationshipData("one-to-many-dependents", isToManyData: true)); - content.SingleData.Relationships.Add("empty-to-manies", CreateRelationshipData(isToManyData: true)); + var content = CreateDocumentWithRelationships("multiPrincipals"); + content.SingleData.Relationships.Add("populatedToOne", CreateRelationshipData("oneToOneDependents")); + content.SingleData.Relationships.Add("emptyToOne", CreateRelationshipData()); + content.SingleData.Relationships.Add("populatedToManies", CreateRelationshipData("oneToManyDependents", isToManyData: true)); + content.SingleData.Relationships.Add("emptyToManies", CreateRelationshipData(isToManyData: true)); var body = JsonConvert.SerializeObject(content); // Act @@ -85,11 +85,11 @@ public void DeserializeRelationships_MultiplePrincipalRelationships_RegistersUpd { // Arrange SetupFieldsManager(out List attributesToUpdate, out List relationshipsToUpdate); - var content = CreateDocumentWithRelationships("multi-dependents"); - content.SingleData.Relationships.Add("populated-to-one", CreateRelationshipData("one-to-one-principals")); - content.SingleData.Relationships.Add("empty-to-one", CreateRelationshipData()); - content.SingleData.Relationships.Add("populated-to-many", CreateRelationshipData("one-to-many-principals")); - content.SingleData.Relationships.Add("empty-to-many", CreateRelationshipData()); + var content = CreateDocumentWithRelationships("multiDependents"); + content.SingleData.Relationships.Add("populatedToOne", CreateRelationshipData("oneToOnePrincipals")); + content.SingleData.Relationships.Add("emptyToOne", CreateRelationshipData()); + content.SingleData.Relationships.Add("populatedToMany", CreateRelationshipData("oneToManyPrincipals")); + content.SingleData.Relationships.Add("emptyToMany", CreateRelationshipData()); var body = JsonConvert.SerializeObject(content); // Act diff --git a/test/UnitTests/Serialization/Server/ResponseSerializerTests.cs b/test/UnitTests/Serialization/Server/ResponseSerializerTests.cs index 382755f6b5..72cf105684 100644 --- a/test/UnitTests/Serialization/Server/ResponseSerializerTests.cs +++ b/test/UnitTests/Serialization/Server/ResponseSerializerTests.cs @@ -26,16 +26,16 @@ public void SerializeSingle_ResourceWithDefaultTargetFields_CanSerialize() var expectedFormatted = @"{ ""data"":{ - ""type"":""test-resource"", + ""type"":""testResource"", ""id"":""1"", ""attributes"":{ - ""string-field"":""value"", - ""date-time-field"":""0001-01-01T00:00:00"", - ""nullable-date-time-field"":null, - ""int-field"":0, - ""nullable-int-field"":123, - ""guid-field"":""00000000-0000-0000-0000-000000000000"", - ""complex-field"":null, + ""stringField"":""value"", + ""dateTimeField"":""0001-01-01T00:00:00"", + ""nullableDateTimeField"":null, + ""intField"":0, + ""nullableIntField"":123, + ""guidField"":""00000000-0000-0000-0000-000000000000"", + ""complexField"":null, ""immutable"":null } } @@ -60,16 +60,16 @@ public void SerializeMany_ResourceWithDefaultTargetFields_CanSerialize() var expectedFormatted = @"{ ""data"":[{ - ""type"":""test-resource"", + ""type"":""testResource"", ""id"":""1"", ""attributes"":{ - ""string-field"":""value"", - ""date-time-field"":""0001-01-01T00:00:00"", - ""nullable-date-time-field"":null, - ""int-field"":0, - ""nullable-int-field"":123, - ""guid-field"":""00000000-0000-0000-0000-000000000000"", - ""complex-field"":null, + ""stringField"":""value"", + ""dateTimeField"":""0001-01-01T00:00:00"", + ""nullableDateTimeField"":null, + ""intField"":0, + ""nullableIntField"":123, + ""guidField"":""00000000-0000-0000-0000-000000000000"", + ""complexField"":null, ""immutable"":null } }] @@ -99,39 +99,39 @@ public void SerializeSingle_ResourceWithIncludedRelationships_CanSerialize() var expectedFormatted = @"{ ""data"":{ - ""type"":""multi-principals"", + ""type"":""multiPrincipals"", ""id"":""1"", - ""attributes"":{ ""attribute-member"":null }, + ""attributes"":{ ""attributeMember"":null }, ""relationships"":{ - ""populated-to-one"":{ + ""populatedToOne"":{ ""data"":{ - ""type"":""one-to-one-dependents"", + ""type"":""oneToOneDependents"", ""id"":""10"" } }, - ""empty-to-one"": { ""data"":null }, - ""populated-to-manies"":{ + ""emptyToOne"": { ""data"":null }, + ""populatedToManies"":{ ""data"":[ { - ""type"":""one-to-many-dependents"", + ""type"":""oneToManyDependents"", ""id"":""20"" } ] }, - ""empty-to-manies"": { ""data"":[ ] }, + ""emptyToManies"": { ""data"":[ ] }, ""multi"":{ ""data"":null } } }, ""included"":[ { - ""type"":""one-to-one-dependents"", + ""type"":""oneToOneDependents"", ""id"":""10"", - ""attributes"":{ ""attribute-member"":null } + ""attributes"":{ ""attributeMember"":null } }, { - ""type"":""one-to-many-dependents"", + ""type"":""oneToManyDependents"", ""id"":""20"", - ""attributes"":{ ""attribute-member"":null } + ""attributes"":{ ""attributeMember"":null } } ] }"; @@ -156,7 +156,7 @@ public void SerializeSingle_ResourceWithDeeplyIncludedRelationships_CanSerialize .Select(r => { var chain = new List { r }; - if (r.PublicRelationshipName != "populated-to-manies") + if (r.PublicRelationshipName != "populatedToManies") return new List { r }; chain.AddRange(_resourceGraph.GetRelationships()); return chain; @@ -171,27 +171,27 @@ public void SerializeSingle_ResourceWithDeeplyIncludedRelationships_CanSerialize var expectedFormatted = @"{ ""data"":{ - ""type"":""multi-principals"", + ""type"":""multiPrincipals"", ""id"":""10"", ""attributes"":{ - ""attribute-member"":null + ""attributeMember"":null }, ""relationships"":{ - ""populated-to-one"":{ + ""populatedToOne"":{ ""data"":null }, - ""empty-to-one"":{ + ""emptyToOne"":{ ""data"":null }, - ""populated-to-manies"":{ + ""populatedToManies"":{ ""data"":[ { - ""type"":""one-to-many-dependents"", + ""type"":""oneToManyDependents"", ""id"":""20"" } ] }, - ""empty-to-manies"":{ + ""emptyToManies"":{ ""data"":[] }, ""multi"":{ @@ -201,25 +201,25 @@ public void SerializeSingle_ResourceWithDeeplyIncludedRelationships_CanSerialize }, ""included"":[ { - ""type"":""one-to-many-dependents"", + ""type"":""oneToManyDependents"", ""id"":""20"", ""attributes"":{ - ""attribute-member"":null + ""attributeMember"":null }, ""relationships"":{ ""principal"":{ ""data"":{ - ""type"":""one-to-many-principals"", + ""type"":""oneToManyPrincipals"", ""id"":""30"" } } } }, { - ""type"":""one-to-many-principals"", + ""type"":""oneToManyPrincipals"", ""id"":""30"", ""attributes"":{ - ""attribute-member"":""deep"" + ""attributeMember"":""deep"" } } ] @@ -279,10 +279,10 @@ public void SerializeSingle_ResourceWithLinksEnabled_CanSerialize() ""last"":""http://www.dummy.com/dummy-last-link"" }, ""data"":{ - ""type"":""one-to-many-principals"", + ""type"":""oneToManyPrincipals"", ""id"":""10"", ""attributes"":{ - ""attribute-member"":null + ""attributeMember"":null }, ""relationships"":{ ""dependents"":{ @@ -318,10 +318,10 @@ public void SerializeSingle_ResourceWithMeta_IncludesMetaInResult() @"{ ""meta"":{ ""test"": ""meta"" }, ""data"":{ - ""type"":""one-to-many-principals"", + ""type"":""oneToManyPrincipals"", ""id"":""10"", ""attributes"":{ - ""attribute-member"":null + ""attributeMember"":null } } }"; @@ -392,7 +392,7 @@ public void SerializeSingleWithRequestRelationship_PopulatedToOneRelationship_Ca var expectedFormatted = @"{ ""data"":{ - ""type"":""one-to-one-dependents"", + ""type"":""oneToOneDependents"", ""id"":""1"" } }"; @@ -438,7 +438,7 @@ public void SerializeSingleWithRequestRelationship_PopulatedToManyRelationship_C var expectedFormatted = @"{ ""data"":[{ - ""type"":""one-to-many-dependents"", + ""type"":""oneToManyDependents"", ""id"":""1"" }] }";