diff --git a/.editorconfig b/.editorconfig index 5a036d1797..37fda299fb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,60 +4,119 @@ root = true [*] indent_style = space indent_size = 4 +tab-width = 4 charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[*.{config,csproj,css,js,json,props,ruleset,xslt,html}] +[*.{config,csproj,css,js,json,props,targets,xml,ruleset,xsd,xslt,html,yml,yaml}] indent_size = 2 +tab-width = 2 +max_line_length = 160 + +[*.{cs,cshtml,ascx,aspx}] -[*.{cs}] #### C#/.NET Coding Conventions #### +# Default severity for IDE* analyzers with category 'Style' +# Note: specific rules below use severity silent, because Resharper code cleanup auto-fixes them. +dotnet_analyzer_diagnostic.category-Style.severity = warning + # 'using' directive preferences dotnet_sort_system_directives_first = true -csharp_using_directive_placement = outside_namespace:suggestion +csharp_using_directive_placement = outside_namespace:silent +# IDE0005: Remove unnecessary import +dotnet_diagnostic.IDE0005.severity = silent # Namespace declarations -csharp_style_namespace_declarations = file_scoped:suggestion +csharp_style_namespace_declarations = file_scoped:silent +# IDE0160: Use block-scoped namespace +dotnet_diagnostic.IDE0160.severity = silent +# IDE0161: Use file-scoped namespace +dotnet_diagnostic.IDE0161.severity = silent # this. preferences -dotnet_style_qualification_for_field = false:suggestion -dotnet_style_qualification_for_property = false:suggestion -dotnet_style_qualification_for_method = false:suggestion -dotnet_style_qualification_for_event = false:suggestion +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_event = false:silent +# IDE0003: Remove this or Me qualification +dotnet_diagnostic.IDE0003.severity = silent +# IDE0009: Add this or Me qualification +dotnet_diagnostic.IDE0009.severity = silent # Language keywords vs BCL types preferences -dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion -dotnet_style_predefined_type_for_member_access = true:suggestion +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +# IDE0049: Use language keywords instead of framework type names for type references +dotnet_diagnostic.IDE0049.severity = silent # Modifier preferences -dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion -csharp_preferred_modifier_order = public, private, protected, internal, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async:suggestion -csharp_style_pattern_local_over_anonymous_function = false:silent +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +# IDE0040: Add accessibility modifiers +dotnet_diagnostic.IDE0040.severity = silent +csharp_preferred_modifier_order = public, private, protected, internal, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async:silent +# IDE0036: Order modifiers +dotnet_diagnostic.IDE0036.severity = silent # Expression-level preferences dotnet_style_operator_placement_when_wrapping = end_of_line -dotnet_style_prefer_auto_properties = true:suggestion -dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion -dotnet_style_prefer_conditional_expression_over_return = true:suggestion -csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion +dotnet_style_prefer_auto_properties = true:silent +# IDE0032: Use auto property +dotnet_diagnostic.IDE0032.severity = silent +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +# IDE0045: Use conditional expression for assignment +dotnet_diagnostic.IDE0045.severity = silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +# IDE0046: Use conditional expression for return +dotnet_diagnostic.IDE0046.severity = silent +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +# IDE0058: Remove unused expression value +dotnet_diagnostic.IDE0058.severity = silent + +# Collection expression preferences (note: partially turned off in Directory.Build.props) +dotnet_style_prefer_collection_expression = when_types_exactly_match # Parameter preferences -dotnet_code_quality_unused_parameters = non_public:suggestion +dotnet_code_quality_unused_parameters = non_public + +# Local functions vs lambdas +csharp_style_prefer_local_over_anonymous_function = false:silent +# IDE0039: Use local function instead of lambda +dotnet_diagnostic.IDE0039.severity = silent # Expression-bodied members -csharp_style_expression_bodied_accessors = true:suggestion -csharp_style_expression_bodied_constructors = false:suggestion -csharp_style_expression_bodied_indexers = true:suggestion -csharp_style_expression_bodied_lambdas = true:suggestion -csharp_style_expression_bodied_local_functions = false:suggestion -csharp_style_expression_bodied_methods = false:suggestion -csharp_style_expression_bodied_operators = false:suggestion -csharp_style_expression_bodied_properties = true:suggestion +csharp_style_expression_bodied_accessors = true:silent +# IDE0027: Use expression body for accessors +dotnet_diagnostic.IDE0027.severity = silent +csharp_style_expression_bodied_constructors = false:silent +# IDE0021: Use expression body for constructors +dotnet_diagnostic.IDE0021.severity = silent +csharp_style_expression_bodied_indexers = true:silent +# IDE0026: Use expression body for indexers +dotnet_diagnostic.IDE0026.severity = silent +csharp_style_expression_bodied_lambdas = true:silent +# IDE0053: Use expression body for lambdas +dotnet_diagnostic.IDE0053.severity = silent +csharp_style_expression_bodied_local_functions = false:silent +# IDE0061: Use expression body for local functions +dotnet_diagnostic.IDE0061.severity = silent +csharp_style_expression_bodied_methods = false:silent +# IDE0022: Use expression body for methods +dotnet_diagnostic.IDE0022.severity = silent +csharp_style_expression_bodied_operators = false:silent +# IDE0023: Use expression body for conversion operators +dotnet_diagnostic.IDE0023.severity = silent +# IDE0024: Use expression body for operators +dotnet_diagnostic.IDE0024.severity = silent +csharp_style_expression_bodied_properties = true:silent +# IDE0025: Use expression body for properties +dotnet_diagnostic.IDE0025.severity = silent # Code-block preferences -csharp_prefer_braces = true:suggestion +csharp_prefer_braces = true:silent +# IDE0011: Add braces +dotnet_diagnostic.IDE0011.severity = silent # Indentation preferences csharp_indent_case_contents_when_block = false @@ -66,19 +125,42 @@ csharp_indent_case_contents_when_block = false csharp_preserve_single_line_statements = false # 'var' usage preferences -csharp_style_var_for_built_in_types = false:none -csharp_style_var_when_type_is_apparent = true:none -csharp_style_var_elsewhere = false:none +csharp_style_var_for_built_in_types = false:silent +csharp_style_var_when_type_is_apparent = true:silent +csharp_style_var_elsewhere = false:silent +# IDE0007: Use var instead of explicit type +dotnet_diagnostic.IDE0007.severity = silent +# IDE0008: Use explicit type instead of var +dotnet_diagnostic.IDE0008.severity = silent # Parentheses preferences -dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:suggestion -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion -dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:suggestion - -# Expression value is never used -dotnet_diagnostic.IDE0058.severity = none - -#### Naming Style #### +dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:silent +# IDE0047: Remove unnecessary parentheses +dotnet_diagnostic.IDE0047.severity = silent +# IDE0048: Add parentheses for clarity +dotnet_diagnostic.IDE0048.severity = silent + +# IDE0010: Add missing cases to switch statement +dotnet_diagnostic.IDE0010.severity = silent +# IDE0072: Add missing cases to switch expression +dotnet_diagnostic.IDE0072.severity = silent + +# IDE0029: Null check can be simplified +dotnet_diagnostic.IDE0029.severity = silent +# IDE0030: Null check can be simplified +dotnet_diagnostic.IDE0030.severity = silent +# IDE0270: Null check can be simplified +dotnet_diagnostic.IDE0270.severity = silent + +# JSON002: Probable JSON string detected +dotnet_diagnostic.JSON002.severity = silent + +# CA1062: Validate arguments of public methods +dotnet_code_quality.CA1062.excluded_symbol_names = Accept|DefaultVisit|Visit*|Apply* + +#### .NET Naming Style #### dotnet_diagnostic.IDE1006.severity = warning diff --git a/CodingGuidelines.ruleset b/CodingGuidelines.ruleset index e647ad9e58..b29d7423b4 100644 --- a/CodingGuidelines.ruleset +++ b/CodingGuidelines.ruleset @@ -1,32 +1,54 @@  - + + + - - - - - - + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 375ee5066f..b06480623f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,4 +1,29 @@ + + enable + latest + enable + false + false + true + Recommended + $(MSBuildThisFileDirectory)CodingGuidelines.ruleset + $(MSBuildThisFileDirectory)tests.runsettings + 5.6.1 + + + + + IDE0028;IDE0300;IDE0301;IDE0302;IDE0303;IDE0304;IDE0305 + $(NoWarn);$(UseCollectionExpressionRules) + + $(NoWarn);AV2210 @@ -13,20 +38,23 @@ true + + $(NoWarn);CA1707;CA1062 + + + + $(NoWarn);CA1062 + + + + + $(NoWarn);SYSLIB1006 + + - - - enable - latest - enable - false - false - $(MSBuildThisFileDirectory)CodingGuidelines.ruleset - $(MSBuildThisFileDirectory)tests.runsettings - 5.6.1 - diff --git a/benchmarks/Deserialization/DeserializationBenchmarkBase.cs b/benchmarks/Deserialization/DeserializationBenchmarkBase.cs index bbf746d1a8..4febabba1a 100644 --- a/benchmarks/Deserialization/DeserializationBenchmarkBase.cs +++ b/benchmarks/Deserialization/DeserializationBenchmarkBase.cs @@ -11,10 +11,12 @@ namespace Benchmarks.Deserialization; -public abstract class DeserializationBenchmarkBase +public abstract class DeserializationBenchmarkBase : IDisposable { - protected readonly JsonSerializerOptions SerializerReadOptions; - protected readonly DocumentAdapter DocumentAdapter; + private readonly ServiceContainer _serviceProvider = new(); + + protected JsonSerializerOptions SerializerReadOptions { get; } + protected DocumentAdapter DocumentAdapter { get; } protected DeserializationBenchmarkBase() { @@ -23,12 +25,11 @@ protected DeserializationBenchmarkBase() options.SerializerOptions.Converters.Add(new ResourceObjectConverter(resourceGraph)); SerializerReadOptions = ((IJsonApiOptions)options).SerializerReadOptions; - var serviceContainer = new ServiceContainer(); - var resourceFactory = new ResourceFactory(serviceContainer); - var resourceDefinitionAccessor = new ResourceDefinitionAccessor(resourceGraph, serviceContainer); + var resourceFactory = new ResourceFactory(_serviceProvider); + var resourceDefinitionAccessor = new ResourceDefinitionAccessor(resourceGraph, _serviceProvider); - serviceContainer.AddService(typeof(IResourceDefinitionAccessor), resourceDefinitionAccessor); - serviceContainer.AddService(typeof(IResourceDefinition), new JsonApiResourceDefinition(resourceGraph)); + _serviceProvider.AddService(typeof(IResourceDefinitionAccessor), resourceDefinitionAccessor); + _serviceProvider.AddService(typeof(IResourceDefinition), new JsonApiResourceDefinition(resourceGraph)); // ReSharper disable once VirtualMemberCallInConstructor JsonApiRequest request = CreateJsonApiRequest(resourceGraph); @@ -53,6 +54,22 @@ protected DeserializationBenchmarkBase() protected abstract JsonApiRequest CreateJsonApiRequest(IResourceGraph resourceGraph); + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + +#pragma warning disable CA1063 // Implement IDisposable Correctly + private void Dispose(bool disposing) +#pragma warning restore CA1063 // Implement IDisposable Correctly + { + if (disposing) + { + _serviceProvider.Dispose(); + } + } + [UsedImplicitly(ImplicitUseTargetFlags.Members)] public sealed class IncomingResource : Identifiable { diff --git a/benchmarks/Program.cs b/benchmarks/Program.cs index b1e3307931..04d5fa1eaa 100644 --- a/benchmarks/Program.cs +++ b/benchmarks/Program.cs @@ -3,20 +3,12 @@ using Benchmarks.QueryString; using Benchmarks.Serialization; -namespace Benchmarks; +var switcher = new BenchmarkSwitcher([ + typeof(ResourceDeserializationBenchmarks), + typeof(OperationsDeserializationBenchmarks), + typeof(ResourceSerializationBenchmarks), + typeof(OperationsSerializationBenchmarks), + typeof(QueryStringParserBenchmarks) +]); -internal static class Program -{ - private static void Main(string[] args) - { - var switcher = new BenchmarkSwitcher([ - typeof(ResourceDeserializationBenchmarks), - typeof(OperationsDeserializationBenchmarks), - typeof(ResourceSerializationBenchmarks), - typeof(OperationsSerializationBenchmarks), - typeof(QueryStringParserBenchmarks) - ]); - - switcher.Run(args); - } -} +switcher.Run(args); diff --git a/benchmarks/QueryString/QueryStringParserBenchmarks.cs b/benchmarks/QueryString/QueryStringParserBenchmarks.cs index 0b2f88134a..548c08d532 100644 --- a/benchmarks/QueryString/QueryStringParserBenchmarks.cs +++ b/benchmarks/QueryString/QueryStringParserBenchmarks.cs @@ -14,8 +14,9 @@ namespace Benchmarks.QueryString; [MarkdownExporter] [SimpleJob(3, 10, 20)] [MemoryDiagnoser] -public class QueryStringParserBenchmarks +public class QueryStringParserBenchmarks : IDisposable { + private readonly ServiceContainer _serviceProvider = new(); private readonly FakeRequestQueryStringAccessor _queryStringAccessor = new(); private readonly QueryStringReader _queryStringReader; @@ -34,7 +35,7 @@ public QueryStringParserBenchmarks() IsCollection = true }; - var resourceFactory = new ResourceFactory(new ServiceContainer()); + var resourceFactory = new ResourceFactory(_serviceProvider); var includeParser = new IncludeParser(options); var includeReader = new IncludeQueryStringParameterReader(includeParser, request, resourceGraph); @@ -92,4 +93,20 @@ public void ComplexQuery() _queryStringAccessor.SetQueryString(queryString); _queryStringReader.ReadAll(null); } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + +#pragma warning disable CA1063 // Implement IDisposable Correctly + private void Dispose(bool disposing) +#pragma warning restore CA1063 // Implement IDisposable Correctly + { + if (disposing) + { + _serviceProvider.Dispose(); + } + } } diff --git a/benchmarks/Serialization/OperationsSerializationBenchmarks.cs b/benchmarks/Serialization/OperationsSerializationBenchmarks.cs index 458c4eecae..8c4a00b6da 100644 --- a/benchmarks/Serialization/OperationsSerializationBenchmarks.cs +++ b/benchmarks/Serialization/OperationsSerializationBenchmarks.cs @@ -13,7 +13,7 @@ namespace Benchmarks.Serialization; // ReSharper disable once ClassCanBeSealed.Global public class OperationsSerializationBenchmarks : SerializationBenchmarkBase { - private readonly IEnumerable _responseOperations; + private readonly List _responseOperations; public OperationsSerializationBenchmarks() { @@ -23,7 +23,7 @@ public OperationsSerializationBenchmarks() _responseOperations = CreateResponseOperations(request); } - private static IEnumerable CreateResponseOperations(IJsonApiRequest request) + private static List CreateResponseOperations(IJsonApiRequest request) { var resource1 = new OutgoingResource { @@ -102,14 +102,14 @@ private static IEnumerable CreateResponseOperations(IJsonApi var targetedFields = new TargetedFields(); - return new List - { - new(resource1, targetedFields, request), - new(resource2, targetedFields, request), - new(resource3, targetedFields, request), - new(resource4, targetedFields, request), - new(resource5, targetedFields, request) - }; + return + [ + new OperationContainer(resource1, targetedFields, request), + new OperationContainer(resource2, targetedFields, request), + new OperationContainer(resource3, targetedFields, request), + new OperationContainer(resource4, targetedFields, request), + new OperationContainer(resource5, targetedFields, request) + ]; } [Benchmark] diff --git a/benchmarks/Serialization/ResourceSerializationBenchmarks.cs b/benchmarks/Serialization/ResourceSerializationBenchmarks.cs index a2d76b87b1..6f979e86b9 100644 --- a/benchmarks/Serialization/ResourceSerializationBenchmarks.cs +++ b/benchmarks/Serialization/ResourceSerializationBenchmarks.cs @@ -1,7 +1,6 @@ using System.Collections.Immutable; using System.Text.Json; using BenchmarkDotNet.Attributes; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Queries; @@ -97,12 +96,17 @@ private static OutgoingResource CreateResponseResource() resource1.Single2 = resource2; resource2.Single3 = resource3; - resource3.Multi4 = resource4.AsHashSet(); - resource4.Multi5 = resource5.AsHashSet(); + resource3.Multi4 = ToHashSet(resource4); + resource4.Multi5 = ToHashSet(resource5); return resource1; } + private static HashSet ToHashSet(T element) + { + return [element]; + } + [Benchmark] public string SerializeResourceResponse() { diff --git a/benchmarks/Serialization/SerializationBenchmarkBase.cs b/benchmarks/Serialization/SerializationBenchmarkBase.cs index eba222c9d1..c8451835cc 100644 --- a/benchmarks/Serialization/SerializationBenchmarkBase.cs +++ b/benchmarks/Serialization/SerializationBenchmarkBase.cs @@ -14,9 +14,9 @@ namespace Benchmarks.Serialization; public abstract class SerializationBenchmarkBase { - protected readonly JsonSerializerOptions SerializerWriteOptions; - protected readonly IResponseModelAdapter ResponseModelAdapter; - protected readonly IResourceGraph ResourceGraph; + protected JsonSerializerOptions SerializerWriteOptions { get; } + protected IResponseModelAdapter ResponseModelAdapter { get; } + protected IResourceGraph ResourceGraph { get; } protected SerializationBenchmarkBase() { diff --git a/src/Examples/DapperExample/Program.cs b/src/Examples/DapperExample/Program.cs index 00ab54ca97..f7bf198af9 100644 --- a/src/Examples/DapperExample/Program.cs +++ b/src/Examples/DapperExample/Program.cs @@ -86,7 +86,7 @@ await CreateDatabaseAsync(app.Services); -app.Run(); +await app.RunAsync(); static DatabaseProvider GetDatabaseProvider(IConfiguration configuration) { diff --git a/src/Examples/DapperExample/Repositories/DapperFacade.cs b/src/Examples/DapperExample/Repositories/DapperFacade.cs index 4d30e430c7..feb0a88e06 100644 --- a/src/Examples/DapperExample/Repositories/DapperFacade.cs +++ b/src/Examples/DapperExample/Repositories/DapperFacade.cs @@ -73,7 +73,7 @@ public IReadOnlyCollection BuildSqlCommandsForOneToOneRelatio } } - return sqlCommands; + return sqlCommands.AsReadOnly(); } public IReadOnlyCollection BuildSqlCommandsForChangedRelationshipsHavingForeignKeyAtRightSide(ResourceChangeDetector changeDetector, @@ -107,20 +107,20 @@ public IReadOnlyCollection BuildSqlCommandsForChangedRelation object[] rightIdsToRemove = currentRightIds.Except(newRightIds).ToArray(); object[] rightIdsToAdd = newRightIds.Except(currentRightIds).ToArray(); - if (rightIdsToRemove.Any()) + if (rightIdsToRemove.Length > 0) { CommandDefinition sqlCommand = BuildSqlCommandForRemoveFromToMany(foreignKey, rightIdsToRemove, cancellationToken); sqlCommands.Add(sqlCommand); } - if (rightIdsToAdd.Any()) + if (rightIdsToAdd.Length > 0) { CommandDefinition sqlCommand = BuildSqlCommandForAddToToMany(foreignKey, leftId!, rightIdsToAdd, cancellationToken); sqlCommands.Add(sqlCommand); } } - return sqlCommands; + return sqlCommands.AsReadOnly(); } public CommandDefinition BuildSqlCommandForRemoveFromToMany(RelationshipForeignKey foreignKey, object[] rightResourceIdValues, @@ -180,7 +180,7 @@ public CommandDefinition BuildSqlCommandForCreate(ResourceChangeDetector changeD IReadOnlyDictionary columnsToUpdate = changeDetector.GetChangedColumnValues(); - if (columnsToUpdate.Any()) + if (columnsToUpdate.Count > 0) { var updateBuilder = new UpdateResourceStatementBuilder(_dataModelService); UpdateNode updateNode = updateBuilder.Build(changeDetector.ResourceType, columnsToUpdate, leftId!); diff --git a/src/Examples/DapperExample/Repositories/DapperRepository.cs b/src/Examples/DapperExample/Repositories/DapperRepository.cs index 0c54b34353..23e9806139 100644 --- a/src/Examples/DapperExample/Repositories/DapperRepository.cs +++ b/src/Examples/DapperExample/Repositories/DapperRepository.cs @@ -1,3 +1,4 @@ +using System.Data; using System.Data.Common; using System.Diagnostics.CodeAnalysis; using Dapper; @@ -90,7 +91,7 @@ namespace DapperExample.Repositories; /// /// /// -public sealed class DapperRepository : IResourceRepository, IRepositorySupportsTransaction +public sealed partial class DapperRepository : IResourceRepository, IRepositorySupportsTransaction where TResource : class, IIdentifiable { private readonly ITargetedFields _targetedFields; @@ -216,7 +217,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected > 1) { - throw new DataStoreUpdateException(new Exception("Multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Multiple rows found.")); } } @@ -233,7 +234,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected == 0) { - throw new DataStoreUpdateException(new Exception("Row does not exist.")); + throw new DataStoreUpdateException(new DataException("Row does not exist.")); } } }, cancellationToken); @@ -313,7 +314,7 @@ public async Task UpdateAsync(TResource resourceFromRequest, TResource resourceF IReadOnlyCollection postSqlCommands = _dapperFacade.BuildSqlCommandsForChangedRelationshipsHavingForeignKeyAtRightSide(changeDetector, resourceFromDatabase.Id, cancellationToken); - if (preSqlCommands.Any() || updateCommand != null || postSqlCommands.Any()) + if (preSqlCommands.Count > 0 || updateCommand != null || postSqlCommands.Count > 0) { await ExecuteInTransactionAsync(async transaction => { @@ -324,7 +325,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected > 1) { - throw new DataStoreUpdateException(new Exception("Multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Multiple rows found.")); } } @@ -335,7 +336,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected != 1) { - throw new DataStoreUpdateException(new Exception("Row does not exist or multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Row does not exist or multiple rows found.")); } } @@ -346,7 +347,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected == 0) { - throw new DataStoreUpdateException(new Exception("Row does not exist.")); + throw new DataStoreUpdateException(new DataException("Row does not exist.")); } } }, cancellationToken); @@ -374,7 +375,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected != 1) { - throw new DataStoreUpdateException(new Exception("Row does not exist or multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Row does not exist or multiple rows found.")); } }, cancellationToken); @@ -409,7 +410,7 @@ public async Task SetRelationshipAsync(TResource leftResource, object? rightValu IReadOnlyCollection postSqlCommands = _dapperFacade.BuildSqlCommandsForChangedRelationshipsHavingForeignKeyAtRightSide(changeDetector, leftResource.Id, cancellationToken); - if (preSqlCommands.Any() || updateCommand != null || postSqlCommands.Any()) + if (preSqlCommands.Count > 0 || updateCommand != null || postSqlCommands.Count > 0) { await ExecuteInTransactionAsync(async transaction => { @@ -420,7 +421,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected > 1) { - throw new DataStoreUpdateException(new Exception("Multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Multiple rows found.")); } } @@ -431,7 +432,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected != 1) { - throw new DataStoreUpdateException(new Exception("Row does not exist or multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Row does not exist or multiple rows found.")); } } @@ -442,7 +443,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected == 0) { - throw new DataStoreUpdateException(new Exception("Row does not exist.")); + throw new DataStoreUpdateException(new DataException("Row does not exist.")); } } }, cancellationToken); @@ -467,7 +468,7 @@ public async Task AddToToManyRelationshipAsync(TResource? leftResource, [Disallo await _resourceDefinitionAccessor.OnWritingAsync(leftPlaceholderResource, WriteOperationKind.AddToRelationship, cancellationToken); - if (rightResourceIds.Any()) + if (rightResourceIds.Count > 0) { RelationshipForeignKey foreignKey = _dataModelService.GetForeignKey(relationship); object[] rightResourceIdValues = rightResourceIds.Select(resource => resource.GetTypedId()).ToArray(); @@ -482,7 +483,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected != rightResourceIdValues.Length) { - throw new DataStoreUpdateException(new Exception("Row does not exist or multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Row does not exist or multiple rows found.")); } }, cancellationToken); @@ -503,7 +504,7 @@ public async Task RemoveFromToManyRelationshipAsync(TResource leftResource, ISet await _resourceDefinitionAccessor.OnWritingAsync(leftResource, WriteOperationKind.RemoveFromRelationship, cancellationToken); - if (rightResourceIds.Any()) + if (rightResourceIds.Count > 0) { RelationshipForeignKey foreignKey = _dataModelService.GetForeignKey(relationship); object[] rightResourceIdValues = rightResourceIds.Select(resource => resource.GetTypedId()).ToArray(); @@ -516,7 +517,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected != rightResourceIdValues.Length) { - throw new DataStoreUpdateException(new Exception("Row does not exist or multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Row does not exist or multiple rows found.")); } }, cancellationToken); @@ -530,19 +531,18 @@ private void LogSqlCommand(CommandDefinition command) _captureStore.Add(command.CommandText, parameters); - string message = GetLogText(command.CommandText, parameters); - _logger.LogInformation(message); - } - - private string GetLogText(string statement, IDictionary? parameters) - { - if (parameters?.Any() == true) + if (_logger.IsEnabled(LogLevel.Information)) { - string parametersText = string.Join(", ", parameters.Select(parameter => _parameterFormatter.Format(parameter.Key, parameter.Value))); - return $"Executing SQL with parameters: {parametersText}{Environment.NewLine}{statement}"; + if (parameters?.Count > 0) + { + string parametersText = string.Join(", ", parameters.Select(parameter => _parameterFormatter.Format(parameter.Key, parameter.Value))); + LogExecuteWithParameters(Environment.NewLine, command.CommandText, parametersText); + } + else + { + LogExecute(Environment.NewLine, command.CommandText); + } } - - return $"Executing SQL: {Environment.NewLine}{statement}"; } private async Task ExecuteQueryAsync(Func> asyncAction, CancellationToken cancellationToken) @@ -580,4 +580,10 @@ private async Task ExecuteInTransactionAsync(Func asyncActi throw new DataStoreUpdateException(exception); } } + + [LoggerMessage(Level = LogLevel.Information, SkipEnabledCheck = true, Message = "Executing SQL: {LineBreak}{Query}")] + private partial void LogExecute(string lineBreak, string query); + + [LoggerMessage(Level = LogLevel.Information, SkipEnabledCheck = true, Message = "Executing SQL with parameters: {Parameters}{LineBreak}{Query}")] + private partial void LogExecuteWithParameters(string lineBreak, string query, string parameters); } diff --git a/src/Examples/DapperExample/Repositories/ResourceChangeDetector.cs b/src/Examples/DapperExample/Repositories/ResourceChangeDetector.cs index 1d9b998340..6b075d6cae 100644 --- a/src/Examples/DapperExample/Repositories/ResourceChangeDetector.cs +++ b/src/Examples/DapperExample/Repositories/ResourceChangeDetector.cs @@ -18,8 +18,8 @@ internal sealed class ResourceChangeDetector private Dictionary _currentColumnValues = []; private Dictionary _newColumnValues = []; - private Dictionary> _currentRightResourcesByRelationship = []; - private Dictionary> _newRightResourcesByRelationship = []; + private Dictionary> _currentRightResourcesByRelationship = []; + private Dictionary> _newRightResourcesByRelationship = []; public ResourceType ResourceType { get; } @@ -62,9 +62,9 @@ public void CaptureNewValues(IIdentifiable resource) return columnValues; } - private Dictionary> CaptureRightResourcesByRelationship(IIdentifiable resource) + private Dictionary> CaptureRightResourcesByRelationship(IIdentifiable resource) { - Dictionary> relationshipValues = []; + Dictionary> relationshipValues = []; foreach (RelationshipAttribute relationship in ResourceType.Relationships) { @@ -88,7 +88,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName if (!foreignKey.IsNullable) { object? currentRightId = - _currentRightResourcesByRelationship.TryGetValue(hasOneRelationship, out ISet? currentRightResources) + _currentRightResourcesByRelationship.TryGetValue(hasOneRelationship, out HashSet? currentRightResources) ? currentRightResources.FirstOrDefault()?.GetTypedId() : null; @@ -118,7 +118,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName if (newRightId != null) { object? currentRightId = - _currentRightResourcesByRelationship.TryGetValue(hasOneRelationship, out ISet? currentRightResources) + _currentRightResourcesByRelationship.TryGetValue(hasOneRelationship, out HashSet? currentRightResources) ? currentRightResources.FirstOrDefault()?.GetTypedId() : null; @@ -130,7 +130,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName } } - return changes; + return changes.AsReadOnly(); } public IReadOnlyDictionary GetChangedColumnValues() @@ -147,7 +147,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName } } - return changes; + return changes.AsReadOnly(); } public IReadOnlyDictionary GetChangedToOneRelationshipsWithForeignKeyAtRightSide() @@ -165,7 +165,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName continue; } - object? currentRightId = _currentRightResourcesByRelationship.TryGetValue(hasOneRelationship, out ISet? currentRightResources) + object? currentRightId = _currentRightResourcesByRelationship.TryGetValue(hasOneRelationship, out HashSet? currentRightResources) ? currentRightResources.FirstOrDefault()?.GetTypedId() : null; @@ -178,7 +178,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName } } - return changes; + return changes.AsReadOnly(); } public IReadOnlyDictionary currentRightIds, ISet newRightIds)> GetChangedToManyRelationships() @@ -192,7 +192,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName HashSet newRightIds = newRightResources.Select(resource => resource.GetTypedId()).ToHashSet(); HashSet currentRightIds = - _currentRightResourcesByRelationship.TryGetValue(hasManyRelationship, out ISet? currentRightResources) + _currentRightResourcesByRelationship.TryGetValue(hasManyRelationship, out HashSet? currentRightResources) ? currentRightResources.Select(resource => resource.GetTypedId()).ToHashSet() : []; @@ -203,7 +203,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName } } - return changes; + return changes.AsReadOnly(); } private static void AssertSameType(ResourceType resourceType, IIdentifiable resource) diff --git a/src/Examples/DapperExample/Repositories/ResultSetMapper.cs b/src/Examples/DapperExample/Repositories/ResultSetMapper.cs index 4a90bd587a..1b20f74dd9 100644 --- a/src/Examples/DapperExample/Repositories/ResultSetMapper.cs +++ b/src/Examples/DapperExample/Repositories/ResultSetMapper.cs @@ -3,6 +3,9 @@ using JsonApiDotNetCore.Queries.Expressions; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; +#if NET6_0 +using JsonApiDotNetCore; +#endif namespace DapperExample.Repositories; @@ -124,7 +127,7 @@ private void RecursiveSetRelationships(object leftResource, IEnumerable 0) { RecursiveSetRelationships(rightResource, includeElement.Children, joinObjects); } @@ -148,7 +151,7 @@ private void SetRelationship(object leftResource, RelationshipAttribute relation public IReadOnlyCollection GetResources() { - return _primaryResourcesInOrder.DistinctBy(resource => resource.Id).ToList(); + return _primaryResourcesInOrder.DistinctBy(resource => resource.Id).ToArray().AsReadOnly(); } private sealed class IncludeElementWalker(IncludeExpression include) diff --git a/src/Examples/DapperExample/Repositories/SqlCaptureStore.cs b/src/Examples/DapperExample/Repositories/SqlCaptureStore.cs index 15d4e95d81..701f1ca740 100644 --- a/src/Examples/DapperExample/Repositories/SqlCaptureStore.cs +++ b/src/Examples/DapperExample/Repositories/SqlCaptureStore.cs @@ -11,7 +11,7 @@ public sealed class SqlCaptureStore { private readonly List _sqlCommands = []; - public IReadOnlyList SqlCommands => _sqlCommands; + public IReadOnlyList SqlCommands => _sqlCommands.AsReadOnly(); public void Clear() { diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/DeleteOneToOneStatementBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/DeleteOneToOneStatementBuilder.cs index 3ea368b299..74484ac1dc 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/DeleteOneToOneStatementBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/DeleteOneToOneStatementBuilder.cs @@ -11,7 +11,7 @@ internal sealed class DeleteOneToOneStatementBuilder(IDataModelService dataModel public DeleteNode Build(ResourceType resourceType, string whereColumnName, object? whereValue) { ArgumentGuard.NotNull(resourceType); - ArgumentGuard.NotNull(whereColumnName); + ArgumentGuard.NotNullNorEmpty(whereColumnName); ResetState(); diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/DeleteResourceStatementBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/DeleteResourceStatementBuilder.cs index 1910075a8c..7d39e939af 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/DeleteResourceStatementBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/DeleteResourceStatementBuilder.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using DapperExample.TranslationToSql.DataModel; using DapperExample.TranslationToSql.TreeNodes; using JsonApiDotNetCore; @@ -25,7 +26,7 @@ public DeleteNode Build(ResourceType resourceType, params object[] idValues) private WhereNode GetWhere(ColumnNode idColumn, IEnumerable idValues) { - List parameters = idValues.Select(idValue => ParameterGenerator.Create(idValue)).ToList(); + ReadOnlyCollection parameters = idValues.Select(ParameterGenerator.Create).ToArray().AsReadOnly(); FilterNode filter = parameters.Count == 1 ? new ComparisonNode(ComparisonOperator.Equals, idColumn, parameters[0]) : new InNode(idColumn, parameters); return new WhereNode(filter); } diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/InsertStatementBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/InsertStatementBuilder.cs index 5f8374df65..8701269a8a 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/InsertStatementBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/InsertStatementBuilder.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using DapperExample.TranslationToSql.DataModel; using DapperExample.TranslationToSql.TreeNodes; using JsonApiDotNetCore; @@ -16,12 +17,12 @@ public InsertNode Build(ResourceType resourceType, IReadOnlyDictionary assignments = GetColumnAssignments(columnsToSet, table); + ReadOnlyCollection assignments = GetColumnAssignments(columnsToSet, table); return new InsertNode(table, assignments); } - private List GetColumnAssignments(IReadOnlyDictionary columnsToSet, TableNode table) + private ReadOnlyCollection GetColumnAssignments(IReadOnlyDictionary columnsToSet, TableNode table) { List assignments = []; ColumnNode idColumn = table.GetIdColumn(table.Alias); @@ -45,6 +46,6 @@ private List GetColumnAssignments(IReadOnlyDictionary columnMappings = _queryState.DataModelService.GetColumnMappings(resourceType); var table = new TableNode(resourceType, columnMappings, _queryState.TableAliasGenerator.GetNext()); @@ -194,8 +195,8 @@ private void SetColumnSelectors(TableAccessorNode tableAccessor, IEnumerable PreserveColumnOrderEnsuringUniqueNames(IEnumerable columns) @@ -213,7 +214,7 @@ private List PreserveColumnOrderEnsuringUniqueNames(IEnumerable OrderColumnsWithIdAtFrontEnsuringUniqueNames(IEnumerable columns) + private SelectorNode[] OrderColumnsWithIdAtFrontEnsuringUniqueNames(IEnumerable columns) { Dictionary> selectorsPerTable = []; @@ -236,7 +237,7 @@ private List OrderColumnsWithIdAtFrontEnsuringUniqueNames(IEnumera } } - return selectorsPerTable.SelectMany(selector => selector.Value).ToList(); + return selectorsPerTable.SelectMany(selector => selector.Value).ToArray(); } private string GetUniqueSelectorName(string columnName) @@ -260,7 +261,7 @@ private void ConvertNestedQueryLayer(TableAccessorNode tableAccessor, Relationsh { var subSelectBuilder = new SelectStatementBuilder(_queryState); - TableAccessorNode primaryTableAccessor = subSelectBuilder.CreatePrimaryTable(relationship.RightType); + FromNode primaryTableAccessor = subSelectBuilder.CreatePrimaryTable(relationship.RightType); subSelectBuilder.ConvertQueryLayer(nextLayer, primaryTableAccessor); string[] innerTableAliases = subSelectBuilder._selectorsPerTable.Keys.Select(accessor => accessor.Source.Alias).Cast().ToArray(); @@ -271,7 +272,7 @@ private void ConvertNestedQueryLayer(TableAccessorNode tableAccessor, Relationsh subSelectBuilder.SelectAllColumnsInAllTables(selectorsToKeep.Keys); // Since there's no pagination support, it's pointless to preserve orderings in the sub-query. - List orderingsToKeep = subSelectBuilder._orderByTerms.ToList(); + OrderByTermNode[] orderingsToKeep = subSelectBuilder._orderByTerms.ToArray(); subSelectBuilder._orderByTerms.Clear(); SelectNode aliasedSubQuery = subSelectBuilder.ToSelect(true, true); @@ -283,10 +284,11 @@ private void ConvertNestedQueryLayer(TableAccessorNode tableAccessor, Relationsh TableAccessorNode outerTableAccessor = CreateRelatedTable(tableAccessor, relationship, aliasedSubQuery); // In the outer query, select only what was originally selected. - _selectorsPerTable[outerTableAccessor] = MapSelectorsFromSubQuery(selectorsToKeep.SelectMany(selector => selector.Value), aliasedSubQuery); + _selectorsPerTable[outerTableAccessor] = + MapSelectorsFromSubQuery(selectorsToKeep.SelectMany(selector => selector.Value), aliasedSubQuery).AsReadOnly(); // To achieve total ordering, all orderings from sub-query must always appear in the root query. - IReadOnlyList outerOrderingsToAdd = MapOrderingsFromSubQuery(orderingsToKeep, aliasedSubQuery); + List outerOrderingsToAdd = MapOrderingsFromSubQuery(orderingsToKeep, aliasedSubQuery); _orderByTerms.AddRange(outerOrderingsToAdd); } else @@ -356,7 +358,7 @@ private void TrackRelatedTable(TableAccessorNode leftTableAccessor, Relationship _queryState.RelatedTables[leftTableAccessor].Add(relationship, rightTableAccessor); } - private IReadOnlyList MapSelectorsFromSubQuery(IEnumerable innerSelectorsToKeep, SelectNode select) + private List MapSelectorsFromSubQuery(IEnumerable innerSelectorsToKeep, SelectNode select) { List outerColumnsToKeep = []; @@ -379,7 +381,7 @@ private IReadOnlyList MapSelectorsFromSubQuery(IEnumerable MapOrderingsFromSubQuery(IEnumerable innerOrderingsToKeep, SelectNode select) + private List MapOrderingsFromSubQuery(IEnumerable innerOrderingsToKeep, SelectNode select) { List orderingsToKeep = []; @@ -419,9 +421,9 @@ private TableAccessorNode GetOrCreateRelatedTable(TableAccessorNode leftTableAcc return relatedTableAccessor; } - private TableAccessorNode CreatePrimaryTableWithIdentityCondition(TableSourceNode outerTableSource, RelationshipAttribute relationship) + private FromNode CreatePrimaryTableWithIdentityCondition(TableSourceNode outerTableSource, RelationshipAttribute relationship) { - TableAccessorNode innerTableAccessor = CreatePrimaryTable(relationship.RightType); + FromNode innerTableAccessor = CreatePrimaryTable(relationship.RightType); ComparisonNode joinCondition = CreateJoinCondition(outerTableSource, relationship, innerTableAccessor.Source); _whereFilters.Add(joinCondition); @@ -438,14 +440,14 @@ private TableAccessorNode CreatePrimaryTableWithIdentityCondition(TableSourceNod private SelectNode ToSelect(bool isSubQuery, bool createAlias) { WhereNode? where = GetWhere(); - OrderByNode? orderBy = !_orderByTerms.Any() ? null : new OrderByNode(_orderByTerms); + OrderByNode? orderBy = _orderByTerms.Count == 0 ? null : new OrderByNode(_orderByTerms.AsReadOnly()); // Materialization using Dapper requires selectors to match property names, so adjust selector names accordingly. Dictionary> selectorsPerTable = isSubQuery ? _selectorsPerTable : AliasSelectorsToTableColumnNames(_selectorsPerTable); string? alias = createAlias ? _queryState.TableAliasGenerator.GetNext() : null; - return new SelectNode(selectorsPerTable, where, orderBy, alias); + return new SelectNode(selectorsPerTable.AsReadOnly(), where, orderBy, alias); } private WhereNode? GetWhere() @@ -457,7 +459,7 @@ private SelectNode ToSelect(bool isSubQuery, bool createAlias) var combinator = new LogicalCombinator(); - FilterNode filter = _whereFilters.Count == 1 ? _whereFilters[0] : new LogicalNode(LogicalOperator.And, _whereFilters); + FilterNode filter = _whereFilters.Count == 1 ? _whereFilters[0] : new LogicalNode(LogicalOperator.And, _whereFilters.AsReadOnly()); FilterNode collapsed = combinator.Collapse(filter); return new WhereNode(collapsed); @@ -470,7 +472,7 @@ private static Dictionary> AliasS foreach ((TableAccessorNode tableAccessor, IReadOnlyList tableSelectors) in selectorsPerTable) { - aliasedSelectors[tableAccessor] = tableSelectors.Select(AliasToTableColumnName).ToList(); + aliasedSelectors[tableAccessor] = tableSelectors.Select(AliasToTableColumnName).ToArray().AsReadOnly(); } return aliasedSelectors; @@ -569,15 +571,15 @@ public override SqlTreeNode VisitLiteralConstant(LiteralConstantExpression expre public override SqlTreeNode VisitLogical(LogicalExpression expression, TableAccessorNode tableAccessor) { - FilterNode[] terms = VisitSequence(expression.Terms, tableAccessor).ToArray(); + ReadOnlyCollection terms = VisitSequence(expression.Terms, tableAccessor); return new LogicalNode(expression.Operator, terms); } - private IEnumerable VisitSequence(IEnumerable source, TableAccessorNode tableAccessor) + private ReadOnlyCollection VisitSequence(IEnumerable source, TableAccessorNode tableAccessor) where TIn : QueryExpression where TOut : SqlTreeNode { - return source.Select(expression => (TOut)Visit(expression, tableAccessor)).ToList(); + return source.Select(expression => (TOut)Visit(expression, tableAccessor)).ToArray().AsReadOnly(); } public override SqlTreeNode VisitNot(NotExpression expression, TableAccessorNode tableAccessor) @@ -588,12 +590,9 @@ public override SqlTreeNode VisitNot(NotExpression expression, TableAccessorNode var finder = new NullableAttributeFinder(_queryState.DataModelService); finder.Visit(expression, null); - if (finder.AttributesToNullCheck.Any()) + if (finder.AttributesToNullCheck.Count > 0) { - var orTerms = new List - { - filter - }; + List orTerms = [filter]; foreach (ResourceFieldChainExpression fieldChain in finder.AttributesToNullCheck) { @@ -602,7 +601,7 @@ public override SqlTreeNode VisitNot(NotExpression expression, TableAccessorNode orTerms.Add(isNullCheck); } - return new LogicalNode(LogicalOperator.Or, orTerms); + return new LogicalNode(LogicalOperator.Or, orTerms.AsReadOnly()); } return filter; @@ -656,7 +655,7 @@ public override SqlTreeNode VisitSortElement(SortElementExpression expression, T public override SqlTreeNode VisitSort(SortExpression expression, TableAccessorNode tableAccessor) { - OrderByTermNode[] terms = VisitSequence(expression.Elements, tableAccessor).ToArray(); + ReadOnlyCollection terms = VisitSequence(expression.Elements, tableAccessor); return new OrderByNode(terms); } @@ -688,17 +687,17 @@ public override SqlTreeNode VisitAny(AnyExpression expression, TableAccessorNode { var column = (ColumnNode)Visit(expression.TargetAttribute, tableAccessor); - ParameterNode[] parameters = - VisitSequence(expression.Constants.OrderBy(constant => constant.TypedValue), tableAccessor).ToArray(); + ReadOnlyCollection parameters = + VisitSequence(expression.Constants.OrderBy(constant => constant.TypedValue), tableAccessor); - return parameters.Length == 1 ? new ComparisonNode(ComparisonOperator.Equals, column, parameters[0]) : new InNode(column, parameters); + return parameters.Count == 1 ? new ComparisonNode(ComparisonOperator.Equals, column, parameters[0]) : new InNode(column, parameters); } private sealed class NullableAttributeFinder : QueryExpressionRewriter { private readonly IDataModelService _dataModelService; - public IList AttributesToNullCheck { get; } = new List(); + public List AttributesToNullCheck { get; } = []; public NullableAttributeFinder(IDataModelService dataModelService) { diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/SqlQueryBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/SqlQueryBuilder.cs index a082d3ecad..e8cb8f894a 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/SqlQueryBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/SqlQueryBuilder.cs @@ -477,7 +477,7 @@ internal static string FormatIdentifier(string value, DatabaseProvider databaseP }; } - private IDisposable Indent() + private RevertIndentOnDispose Indent() { _indentDepth++; return new RevertIndentOnDispose(this); diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/UpdateClearOneToOneStatementBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/UpdateClearOneToOneStatementBuilder.cs index 712561528d..9d76361bab 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/UpdateClearOneToOneStatementBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/UpdateClearOneToOneStatementBuilder.cs @@ -11,8 +11,8 @@ internal sealed class UpdateClearOneToOneStatementBuilder(IDataModelService data public UpdateNode Build(ResourceType resourceType, string setColumnName, string whereColumnName, object? whereValue) { ArgumentGuard.NotNull(resourceType); - ArgumentGuard.NotNull(setColumnName); - ArgumentGuard.NotNull(whereColumnName); + ArgumentGuard.NotNullNorEmpty(setColumnName); + ArgumentGuard.NotNullNorEmpty(whereColumnName); ResetState(); diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/UpdateResourceStatementBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/UpdateResourceStatementBuilder.cs index a279ad45e5..5941ce3e29 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/UpdateResourceStatementBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/UpdateResourceStatementBuilder.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using DapperExample.TranslationToSql.DataModel; using DapperExample.TranslationToSql.TreeNodes; using JsonApiDotNetCore; @@ -17,7 +18,7 @@ public UpdateNode Build(ResourceType resourceType, IReadOnlyDictionary assignments = GetColumnAssignments(columnsToUpdate, table); + ReadOnlyCollection assignments = GetColumnAssignments(columnsToUpdate, table); ColumnNode idColumn = table.GetIdColumn(table.Alias); WhereNode where = GetWhere(idColumn, idValues); @@ -25,7 +26,7 @@ public UpdateNode Build(ResourceType resourceType, IReadOnlyDictionary GetColumnAssignments(IReadOnlyDictionary columnsToUpdate, TableNode table) + private ReadOnlyCollection GetColumnAssignments(IReadOnlyDictionary columnsToUpdate, TableNode table) { List assignments = []; @@ -38,12 +39,12 @@ private List GetColumnAssignments(IReadOnlyDictionary idValues) { - List parameters = idValues.Select(idValue => ParameterGenerator.Create(idValue)).ToList(); + ReadOnlyCollection parameters = idValues.Select(ParameterGenerator.Create).ToArray().AsReadOnly(); FilterNode filter = parameters.Count == 1 ? new ComparisonNode(ComparisonOperator.Equals, idColumn, parameters[0]) : new InNode(idColumn, parameters); return new WhereNode(filter); } diff --git a/src/Examples/DapperExample/TranslationToSql/DataModel/BaseDataModelService.cs b/src/Examples/DapperExample/TranslationToSql/DataModel/BaseDataModelService.cs index 589852ad80..235e3e72d5 100644 --- a/src/Examples/DapperExample/TranslationToSql/DataModel/BaseDataModelService.cs +++ b/src/Examples/DapperExample/TranslationToSql/DataModel/BaseDataModelService.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.ComponentModel.DataAnnotations.Schema; using System.Data; using System.Data.Common; @@ -16,7 +17,7 @@ namespace DapperExample.TranslationToSql.DataModel; /// public abstract class BaseDataModelService : IDataModelService { - private readonly Dictionary> _columnMappingsByType = []; + private readonly Dictionary> _columnMappingsByType = []; protected IResourceGraph ResourceGraph { get; } @@ -52,7 +53,7 @@ private void ScanColumnMappings() } } - private IReadOnlyDictionary ScanColumnMappings(ResourceType resourceType) + private ReadOnlyDictionary ScanColumnMappings(ResourceType resourceType) { Dictionary mappings = []; @@ -93,7 +94,7 @@ private void ScanColumnMappings() mappings[columnName] = field; } - return mappings; + return mappings.AsReadOnly(); } private static bool IsMapped(PropertyInfo property) @@ -103,7 +104,7 @@ private static bool IsMapped(PropertyInfo property) public IReadOnlyDictionary GetColumnMappings(ResourceType resourceType) { - if (_columnMappingsByType.TryGetValue(resourceType, out IReadOnlyDictionary? columnMappings)) + if (_columnMappingsByType.TryGetValue(resourceType, out ReadOnlyDictionary? columnMappings)) { return columnMappings; } diff --git a/src/Examples/DapperExample/TranslationToSql/Transformations/ColumnSelectorUsageCollector.cs b/src/Examples/DapperExample/TranslationToSql/Transformations/ColumnSelectorUsageCollector.cs index b5d560448c..d218093936 100644 --- a/src/Examples/DapperExample/TranslationToSql/Transformations/ColumnSelectorUsageCollector.cs +++ b/src/Examples/DapperExample/TranslationToSql/Transformations/ColumnSelectorUsageCollector.cs @@ -6,7 +6,7 @@ namespace DapperExample.TranslationToSql.Transformations; /// /// Collects all s in selectors that are referenced elsewhere in the query. /// -internal sealed class ColumnSelectorUsageCollector : SqlTreeNodeVisitor +internal sealed partial class ColumnSelectorUsageCollector : SqlTreeNodeVisitor { private readonly HashSet _usedColumns = []; private readonly ILogger _logger; @@ -24,12 +24,12 @@ public void Collect(SelectNode select) { ArgumentGuard.NotNull(select); - _logger.LogDebug("Started collection of used columns."); + LogStarted(); _usedColumns.Clear(); InnerVisit(select, ColumnVisitMode.Reference); - _logger.LogDebug("Finished collection of used columns."); + LogFinished(); } public override object? VisitSelect(SelectNode node, ColumnVisitMode mode) @@ -70,7 +70,7 @@ public void Collect(SelectNode select) if (mode == ColumnVisitMode.Reference) { _usedColumns.Add(node.Column); - _logger.LogDebug($"Added used column {node.Column}."); + LogColumnAdded(node.Column); } InnerVisit(node.Column, mode); @@ -160,4 +160,13 @@ private void VisitSequence(IEnumerable nodes, ColumnVisitMode mode) InnerVisit(node, mode); } } + + [LoggerMessage(Level = LogLevel.Debug, Message = "Started collection of used columns.")] + private partial void LogStarted(); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Finished collection of used columns.")] + private partial void LogFinished(); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Added used column {Column}.")] + private partial void LogColumnAdded(ColumnNode column); } diff --git a/src/Examples/DapperExample/TranslationToSql/Transformations/LogicalCombinator.cs b/src/Examples/DapperExample/TranslationToSql/Transformations/LogicalCombinator.cs index 0fcd047a3d..95359462f7 100644 --- a/src/Examples/DapperExample/TranslationToSql/Transformations/LogicalCombinator.cs +++ b/src/Examples/DapperExample/TranslationToSql/Transformations/LogicalCombinator.cs @@ -14,7 +14,7 @@ public FilterNode Collapse(FilterNode filter) public override SqlTreeNode VisitLogical(LogicalNode node, object? argument) { - var newTerms = new List(); + List newTerms = []; foreach (FilterNode newTerm in node.Terms.Select(TypedVisit)) { @@ -28,7 +28,7 @@ public override SqlTreeNode VisitLogical(LogicalNode node, object? argument) } } - return new LogicalNode(node.Operator, newTerms); + return new LogicalNode(node.Operator, newTerms.AsReadOnly()); } public override SqlTreeNode DefaultVisit(SqlTreeNode node, object? argument) diff --git a/src/Examples/DapperExample/TranslationToSql/Transformations/StaleColumnReferenceRewriter.cs b/src/Examples/DapperExample/TranslationToSql/Transformations/StaleColumnReferenceRewriter.cs index a632c43e51..6f42345ee1 100644 --- a/src/Examples/DapperExample/TranslationToSql/Transformations/StaleColumnReferenceRewriter.cs +++ b/src/Examples/DapperExample/TranslationToSql/Transformations/StaleColumnReferenceRewriter.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using DapperExample.TranslationToSql.TreeNodes; using JsonApiDotNetCore; @@ -28,7 +29,7 @@ namespace DapperExample.TranslationToSql.Transformations; ///

/// The reference to t1 in the WHERE clause has become stale and needs to be pulled out into scope, which is t2. /// -internal sealed class StaleColumnReferenceRewriter : SqlTreeNodeVisitor +internal sealed partial class StaleColumnReferenceRewriter : SqlTreeNodeVisitor { private readonly IReadOnlyDictionary _oldToNewTableAliasMap; private readonly ILogger _logger; @@ -59,12 +60,13 @@ public override SqlTreeNode VisitSelect(SelectNode node, ColumnVisitMode mode) { IncludeTableAliasInCurrentScope(node); - using IDisposable scope = EnterSelectScope(); - - IReadOnlyDictionary> selectors = VisitSelectors(node.Selectors, mode); - WhereNode? where = TypedVisit(node.Where, mode); - OrderByNode? orderBy = TypedVisit(node.OrderBy, mode); - return new SelectNode(selectors, where, orderBy, node.Alias); + using (EnterSelectScope()) + { + ReadOnlyDictionary> selectors = VisitSelectors(node.Selectors, mode); + WhereNode? where = TypedVisit(node.Where, mode); + OrderByNode? orderBy = TypedVisit(node.OrderBy, mode); + return new SelectNode(selectors, where, orderBy, node.Alias); + } } private void IncludeTableAliasInCurrentScope(TableSourceNode tableSource) @@ -76,7 +78,7 @@ private void IncludeTableAliasInCurrentScope(TableSourceNode tableSource) } } - private IDisposable EnterSelectScope() + private PopStackOnDispose> EnterSelectScope() { Dictionary newScope = CopyTopStackElement(); _tablesInScopeStack.Push(newScope); @@ -95,7 +97,7 @@ private Dictionary CopyTopStackElement() return new Dictionary(topElement); } - private IReadOnlyDictionary> VisitSelectors( + private ReadOnlyDictionary> VisitSelectors( IReadOnlyDictionary> selectors, ColumnVisitMode mode) { Dictionary> newSelectors = []; @@ -103,12 +105,12 @@ private IReadOnlyDictionary> Visi foreach ((TableAccessorNode tableAccessor, IReadOnlyList tableSelectors) in selectors) { TableAccessorNode newTableAccessor = TypedVisit(tableAccessor, mode); - IReadOnlyList newTableSelectors = VisitList(tableSelectors, ColumnVisitMode.Declaration); + ReadOnlyCollection newTableSelectors = VisitSequence(tableSelectors, ColumnVisitMode.Declaration); newSelectors.Add(newTableAccessor, newTableSelectors); } - return newSelectors; + return newSelectors.AsReadOnly(); } public override SqlTreeNode VisitTable(TableNode node, ColumnVisitMode mode) @@ -142,7 +144,7 @@ public override SqlTreeNode VisitColumnInTable(ColumnInTableNode node, ColumnVis return MapColumnInTable(node, tablesInScope); } - private ColumnNode MapColumnInTable(ColumnInTableNode column, IDictionary tablesInScope) + private ColumnNode MapColumnInTable(ColumnInTableNode column, Dictionary tablesInScope) { if (column.TableAlias != null && !tablesInScope.ContainsKey(column.TableAlias)) { @@ -159,7 +161,7 @@ private ColumnNode MapColumnInTable(ColumnInTableNode column, IDictionary terms = VisitList(node.Terms, mode); + ReadOnlyCollection terms = VisitSequence(node.Terms, mode); return new LogicalNode(node.Operator, terms); } @@ -233,7 +235,7 @@ public override SqlTreeNode VisitLike(LikeNode node, ColumnVisitMode mode) public override SqlTreeNode VisitIn(InNode node, ColumnVisitMode mode) { ColumnNode column = TypedVisit(node.Column, mode); - IReadOnlyList values = VisitList(node.Values, mode); + ReadOnlyCollection values = VisitSequence(node.Values, mode); return new InNode(column, values); } @@ -251,7 +253,7 @@ public override SqlTreeNode VisitCount(CountNode node, ColumnVisitMode mode) public override SqlTreeNode VisitOrderBy(OrderByNode node, ColumnVisitMode mode) { - IReadOnlyList terms = VisitList(node.Terms, mode); + ReadOnlyCollection terms = VisitSequence(node.Terms, mode); return new OrderByNode(terms); } @@ -277,19 +279,22 @@ public override SqlTreeNode VisitNullConstant(NullConstantNode node, ColumnVisit return node; } - [return: NotNullIfNotNull("node")] + [return: NotNullIfNotNull(nameof(node))] private T? TypedVisit(T? node, ColumnVisitMode mode) where T : SqlTreeNode { return node != null ? (T)Visit(node, mode) : null; } - private IReadOnlyList VisitList(IEnumerable nodes, ColumnVisitMode mode) + private ReadOnlyCollection VisitSequence(IEnumerable nodes, ColumnVisitMode mode) where T : SqlTreeNode { - return nodes.Select(element => TypedVisit(element, mode)).ToList(); + return nodes.Select(element => TypedVisit(element, mode)).ToArray().AsReadOnly(); } + [LoggerMessage(Level = LogLevel.Debug, Message = "Mapped inaccessible column {FromColumn} to {ToColumn}.")] + private partial void LogColumnMapped(ColumnNode fromColumn, ColumnNode toColumn); + private sealed class PopStackOnDispose(Stack stack) : IDisposable { private readonly Stack _stack = stack; diff --git a/src/Examples/DapperExample/TranslationToSql/Transformations/UnusedSelectorsRewriter.cs b/src/Examples/DapperExample/TranslationToSql/Transformations/UnusedSelectorsRewriter.cs index 7cffc8e29a..08f09da99a 100644 --- a/src/Examples/DapperExample/TranslationToSql/Transformations/UnusedSelectorsRewriter.cs +++ b/src/Examples/DapperExample/TranslationToSql/Transformations/UnusedSelectorsRewriter.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using DapperExample.TranslationToSql.TreeNodes; using JsonApiDotNetCore; @@ -26,7 +27,7 @@ namespace DapperExample.TranslationToSql.Transformations; ///

/// The selectors t1."AccountId" and t1."FirstName" have no references and can be removed. /// -internal sealed class UnusedSelectorsRewriter : SqlTreeNodeVisitor, SqlTreeNode> +internal sealed partial class UnusedSelectorsRewriter : SqlTreeNodeVisitor, SqlTreeNode> { private readonly ColumnSelectorUsageCollector _usageCollector; private readonly ILogger _logger; @@ -52,9 +53,9 @@ public SelectNode RemoveUnusedSelectorsInSubQueries(SelectNode select) _hasChanged = false; _usageCollector.Collect(_rootSelect); - _logger.LogDebug("Started removal of unused selectors."); + LogStarted(); _rootSelect = TypedVisit(_rootSelect, _usageCollector.UsedColumns); - _logger.LogDebug("Finished removal of unused selectors."); + LogFinished(); } while (_hasChanged); @@ -68,13 +69,13 @@ public override SqlTreeNode DefaultVisit(SqlTreeNode node, ISet used public override SqlTreeNode VisitSelect(SelectNode node, ISet usedColumns) { - IReadOnlyDictionary> selectors = VisitSelectors(node, usedColumns); + ReadOnlyDictionary> selectors = VisitSelectors(node, usedColumns); WhereNode? where = TypedVisit(node.Where, usedColumns); OrderByNode? orderBy = TypedVisit(node.OrderBy, usedColumns); return new SelectNode(selectors, where, orderBy, node.Alias); } - private IReadOnlyDictionary> VisitSelectors(SelectNode select, ISet usedColumns) + private ReadOnlyDictionary> VisitSelectors(SelectNode select, ISet usedColumns) { Dictionary> newSelectors = []; @@ -85,10 +86,10 @@ private IReadOnlyDictionary> Visi newSelectors.Add(newTableAccessor, newTableSelectors); } - return newSelectors; + return newSelectors.AsReadOnly(); } - private List VisitTableSelectors(IEnumerable selectors, ISet usedColumns) + private ReadOnlyCollection VisitTableSelectors(IEnumerable selectors, ISet usedColumns) { List newTableSelectors = []; @@ -98,7 +99,7 @@ private List VisitTableSelectors(IEnumerable selecto { if (!usedColumns.Contains(columnSelector.Column)) { - _logger.LogDebug($"Removing unused selector {columnSelector}."); + LogSelectorRemoved(columnSelector); _hasChanged = true; continue; } @@ -107,7 +108,7 @@ private List VisitTableSelectors(IEnumerable selecto newTableSelectors.Add(selector); } - return newTableSelectors; + return newTableSelectors.AsReadOnly(); } public override SqlTreeNode VisitFrom(FromNode node, ISet usedColumns) @@ -150,7 +151,7 @@ public override SqlTreeNode VisitNot(NotNode node, ISet usedColumns) public override SqlTreeNode VisitLogical(LogicalNode node, ISet usedColumns) { - IReadOnlyList terms = VisitList(node.Terms, usedColumns); + ReadOnlyCollection terms = VisitSequence(node.Terms, usedColumns); return new LogicalNode(node.Operator, terms); } @@ -170,7 +171,7 @@ public override SqlTreeNode VisitLike(LikeNode node, ISet usedColumn public override SqlTreeNode VisitIn(InNode node, ISet usedColumns) { ColumnNode column = TypedVisit(node.Column, usedColumns); - IReadOnlyList values = VisitList(node.Values, usedColumns); + ReadOnlyCollection values = VisitSequence(node.Values, usedColumns); return new InNode(column, values); } @@ -188,7 +189,7 @@ public override SqlTreeNode VisitCount(CountNode node, ISet usedColu public override SqlTreeNode VisitOrderBy(OrderByNode node, ISet usedColumns) { - IReadOnlyList terms = VisitList(node.Terms, usedColumns); + ReadOnlyCollection terms = VisitSequence(node.Terms, usedColumns); return new OrderByNode(terms); } @@ -204,16 +205,25 @@ public override SqlTreeNode VisitOrderByCount(OrderByCountNode node, ISet(T? node, ISet usedColumns) where T : SqlTreeNode { return node != null ? (T)Visit(node, usedColumns) : null; } - private IReadOnlyList VisitList(IEnumerable nodes, ISet usedColumns) + private ReadOnlyCollection VisitSequence(IEnumerable nodes, ISet usedColumns) where T : SqlTreeNode { - return nodes.Select(element => TypedVisit(element, usedColumns)).ToList(); + return nodes.Select(element => TypedVisit(element, usedColumns)).ToArray().AsReadOnly(); } + + [LoggerMessage(Level = LogLevel.Debug, Message = "Started removal of unused selectors.")] + private partial void LogStarted(); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Finished removal of unused selectors.")] + private partial void LogFinished(); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Removing unused selector {Selector}.")] + private partial void LogSelectorRemoved(ColumnSelectorNode selector); } diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/LogicalNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/LogicalNode.cs index 40fc95b88c..a01306d061 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/LogicalNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/LogicalNode.cs @@ -14,7 +14,7 @@ internal sealed class LogicalNode : FilterNode public IReadOnlyList Terms { get; } public LogicalNode(LogicalOperator @operator, params FilterNode[] terms) - : this(@operator, terms.ToList()) + : this(@operator, terms.AsReadOnly()) { } diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ParameterNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ParameterNode.cs index c2a5824f72..a9feaa7836 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ParameterNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ParameterNode.cs @@ -16,7 +16,7 @@ internal sealed class ParameterNode : SqlValueNode public ParameterNode(string name, object? value) { - ArgumentGuard.NotNull(name); + ArgumentGuard.NotNullNorEmpty(name); if (!name.StartsWith('@') || name.Length < 2) { diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/SelectNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/SelectNode.cs index 0fc42b1ba0..add1ddc433 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/SelectNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/SelectNode.cs @@ -19,7 +19,7 @@ internal sealed class SelectNode : TableSourceNode public WhereNode? Where { get; } public OrderByNode? OrderBy { get; } - public override IReadOnlyList Columns => _columns; + public override IReadOnlyList Columns => _columns.AsReadOnly(); public SelectNode(IReadOnlyDictionary> selectors, WhereNode? where, OrderByNode? orderBy, string? alias) : base(alias) diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableNode.cs index 31977f1546..6abb913418 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableNode.cs @@ -21,7 +21,7 @@ internal sealed class TableNode : TableSourceNode public string Name => _resourceType.ClrType.Name.Pluralize(); - public override IReadOnlyList Columns => _columns; + public override IReadOnlyList Columns => _columns.AsReadOnly(); public TableNode(ResourceType resourceType, IReadOnlyDictionary columnMappings, string? alias) : base(alias) diff --git a/src/Examples/DatabasePerTenantExample/Program.cs b/src/Examples/DatabasePerTenantExample/Program.cs index 1414e28424..4b88357d78 100644 --- a/src/Examples/DatabasePerTenantExample/Program.cs +++ b/src/Examples/DatabasePerTenantExample/Program.cs @@ -38,7 +38,7 @@ await CreateDatabaseAsync("AdventureWorks", app.Services); await CreateDatabaseAsync("Contoso", app.Services); -app.Run(); +await app.RunAsync(); [Conditional("DEBUG")] static void SetDbContextDebugOptions(DbContextOptionsBuilder options) diff --git a/src/Examples/GettingStarted/Program.cs b/src/Examples/GettingStarted/Program.cs index 9ce6beda08..634e130a3f 100644 --- a/src/Examples/GettingStarted/Program.cs +++ b/src/Examples/GettingStarted/Program.cs @@ -38,7 +38,7 @@ await CreateDatabaseAsync(app.Services); -app.Run(); +await app.RunAsync(); [Conditional("DEBUG")] static void SetDbContextDebugOptions(DbContextOptionsBuilder options) diff --git a/src/Examples/JsonApiDotNetCoreExample/AppLog.cs b/src/Examples/JsonApiDotNetCoreExample/AppLog.cs new file mode 100644 index 0000000000..6cb4af1a55 --- /dev/null +++ b/src/Examples/JsonApiDotNetCoreExample/AppLog.cs @@ -0,0 +1,9 @@ +#pragma warning disable AV1008 // Class should not be static + +namespace JsonApiDotNetCoreExample; + +internal static partial class AppLog +{ + [LoggerMessage(Level = LogLevel.Information, SkipEnabledCheck = true, Message = "Measurement results for application startup:{LineBreak}{TimingResults}")] + public static partial void LogStartupTimings(ILogger logger, string lineBreak, string timingResults); +} diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/NonJsonApiController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/NonJsonApiController.cs index 3c89ac3bcf..aa51110869 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/NonJsonApiController.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/NonJsonApiController.cs @@ -16,7 +16,8 @@ public IActionResult Get() [HttpPost] public async Task PostAsync() { - string name = await new StreamReader(Request.Body).ReadToEndAsync(); + using var reader = new StreamReader(Request.Body, leaveOpen: true); + string name = await reader.ReadToEndAsync(); if (string.IsNullOrEmpty(name)) { diff --git a/src/Examples/JsonApiDotNetCoreExample/Program.cs b/src/Examples/JsonApiDotNetCoreExample/Program.cs index 52b27759e9..4c11a71660 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Program.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Program.cs @@ -3,6 +3,7 @@ using System.Text.Json.Serialization; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Diagnostics; +using JsonApiDotNetCoreExample; using JsonApiDotNetCoreExample.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -17,7 +18,7 @@ await CreateDatabaseAsync(app.Services); -app.Run(); +await app.RunAsync(); static WebApplication CreateWebApplication(string[] args) { @@ -34,10 +35,10 @@ static WebApplication CreateWebApplication(string[] args) // Configure the HTTP request pipeline. ConfigurePipeline(app); - if (CodeTimingSessionManager.IsEnabled) + if (CodeTimingSessionManager.IsEnabled && app.Logger.IsEnabled(LogLevel.Information)) { string timingResults = CodeTimingSessionManager.Current.GetResults(); - app.Logger.LogInformation($"Measurement results for application startup:{Environment.NewLine}{timingResults}"); + AppLog.LogStartupTimings(app.Logger, Environment.NewLine, timingResults); } return app; diff --git a/src/Examples/MultiDbContextExample/Program.cs b/src/Examples/MultiDbContextExample/Program.cs index 2cf567b9b5..481e8f7118 100644 --- a/src/Examples/MultiDbContextExample/Program.cs +++ b/src/Examples/MultiDbContextExample/Program.cs @@ -52,7 +52,7 @@ await CreateDatabaseAsync(app.Services); -app.Run(); +await app.RunAsync(); [Conditional("DEBUG")] static void SetDbContextDebugOptions(DbContextOptionsBuilder options) diff --git a/src/Examples/NoEntityFrameworkExample/Program.cs b/src/Examples/NoEntityFrameworkExample/Program.cs index f21d116e5f..8eff35d7a9 100755 --- a/src/Examples/NoEntityFrameworkExample/Program.cs +++ b/src/Examples/NoEntityFrameworkExample/Program.cs @@ -35,4 +35,4 @@ app.UseJsonApi(); app.MapControllers(); -app.Run(); +await app.RunAsync(); diff --git a/src/Examples/NoEntityFrameworkExample/Repositories/InMemoryResourceRepository.cs b/src/Examples/NoEntityFrameworkExample/Repositories/InMemoryResourceRepository.cs index 9d0852ad7f..9eba0b8326 100644 --- a/src/Examples/NoEntityFrameworkExample/Repositories/InMemoryResourceRepository.cs +++ b/src/Examples/NoEntityFrameworkExample/Repositories/InMemoryResourceRepository.cs @@ -32,7 +32,11 @@ public Task> GetAsync(QueryLayer queryLayer, Canc IEnumerable dataSource = GetDataSource(); IEnumerable resources = _queryLayerToLinqConverter.ApplyQueryLayer(queryLayer, dataSource); - return Task.FromResult>(resources.ToList()); +#if NET6_0 + return Task.FromResult>(Array.AsReadOnly(resources.ToArray())); +#else + return Task.FromResult>(resources.ToArray().AsReadOnly()); +#endif } /// diff --git a/src/Examples/NoEntityFrameworkExample/Services/InMemoryResourceService.cs b/src/Examples/NoEntityFrameworkExample/Services/InMemoryResourceService.cs index ee9d2196e9..e55b9340b6 100644 --- a/src/Examples/NoEntityFrameworkExample/Services/InMemoryResourceService.cs +++ b/src/Examples/NoEntityFrameworkExample/Services/InMemoryResourceService.cs @@ -31,7 +31,7 @@ namespace NoEntityFrameworkExample.Services; /// /// The resource identifier type. /// -public abstract class InMemoryResourceService( +public abstract partial class InMemoryResourceService( IJsonApiOptions options, IResourceGraph resourceGraph, IQueryLayerComposer queryLayerComposer, IPaginationContext paginationContext, IEnumerable constraintProviders, IQueryableBuilder queryableBuilder, IReadOnlyModel entityModel, ILoggerFactory loggerFactory) : IResourceQueryService @@ -40,7 +40,7 @@ public abstract class InMemoryResourceService( private readonly IJsonApiOptions _options = options; private readonly IQueryLayerComposer _queryLayerComposer = queryLayerComposer; private readonly IPaginationContext _paginationContext = paginationContext; - private readonly IEnumerable _constraintProviders = constraintProviders; + private readonly IQueryConstraintProvider[] _constraintProviders = constraintProviders as IQueryConstraintProvider[] ?? constraintProviders.ToArray(); private readonly ILogger> _logger = loggerFactory.CreateLogger>(); private readonly ResourceType _resourceType = resourceGraph.GetResourceType(); private readonly QueryLayerToLinqConverter _queryLayerToLinqConverter = new(entityModel, queryableBuilder); @@ -58,14 +58,18 @@ public Task> GetAsync(CancellationToken cancellat QueryLayer queryLayer = _queryLayerComposer.ComposeFromConstraints(_resourceType); IEnumerable dataSource = GetDataSource(_resourceType).Cast(); - List resources = _queryLayerToLinqConverter.ApplyQueryLayer(queryLayer, dataSource).ToList(); + TResource[] resources = _queryLayerToLinqConverter.ApplyQueryLayer(queryLayer, dataSource).ToArray(); - if (queryLayer.Pagination?.PageSize?.Value == resources.Count) + if (queryLayer.Pagination?.PageSize?.Value == resources.Length) { _paginationContext.IsPageFull = true; } - return Task.FromResult>(resources); +#if NET6_0 + return Task.FromResult>(Array.AsReadOnly(resources)); +#else + return Task.FromResult>(resources.AsReadOnly()); +#endif } private void LogFiltersInTopScope() @@ -87,7 +91,7 @@ private void LogFiltersInTopScope() if (filter != null) { - _logger.LogInformation($"Incoming top-level filter from query string: {filter}"); + LogIncomingFilter(filter); } } @@ -195,4 +199,7 @@ private void SetNonPrimaryTotalCount([DisallowNull] TId id, RelationshipAttribut } protected abstract IEnumerable GetDataSource(ResourceType resourceType); + + [LoggerMessage(Level = LogLevel.Information, Message = "Incoming top-level filter from query string: {Filter}")] + private partial void LogIncomingFilter(FilterExpression filter); } diff --git a/src/Examples/ReportsExample/Program.cs b/src/Examples/ReportsExample/Program.cs index 04920d0068..7f89ad9301 100644 --- a/src/Examples/ReportsExample/Program.cs +++ b/src/Examples/ReportsExample/Program.cs @@ -24,4 +24,4 @@ app.UseJsonApi(); app.MapControllers(); -app.Run(); +await app.RunAsync(); diff --git a/src/Examples/ReportsExample/Services/ReportService.cs b/src/Examples/ReportsExample/Services/ReportService.cs index c04e821347..62bb7c9554 100644 --- a/src/Examples/ReportsExample/Services/ReportService.cs +++ b/src/Examples/ReportsExample/Services/ReportService.cs @@ -5,24 +5,19 @@ namespace ReportsExample.Services; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] -public class ReportService(ILoggerFactory loggerFactory) : IGetAllService +public class ReportService : IGetAllService { - private readonly ILogger _logger = loggerFactory.CreateLogger(); - public Task> GetAsync(CancellationToken cancellationToken) { - _logger.LogInformation("GetAsync"); - - IReadOnlyCollection reports = GetReports(); - + IReadOnlyCollection reports = GetReports().AsReadOnly(); return Task.FromResult(reports); } - private IReadOnlyCollection GetReports() + private List GetReports() { - return new List - { - new() + return + [ + new Report { Id = 1, Title = "Status Report", @@ -32,6 +27,6 @@ private IReadOnlyCollection GetReports() HoursSpent = 24 } } - }; + ]; } } diff --git a/src/JsonApiDotNetCore.Annotations/ArgumentGuard.cs b/src/JsonApiDotNetCore.Annotations/ArgumentGuard.cs index 4264c5db8b..e01b80d776 100644 --- a/src/JsonApiDotNetCore.Annotations/ArgumentGuard.cs +++ b/src/JsonApiDotNetCore.Annotations/ArgumentGuard.cs @@ -3,20 +3,21 @@ using SysNotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute; #pragma warning disable AV1008 // Class should not be static +#pragma warning disable format namespace JsonApiDotNetCore; internal static class ArgumentGuard { [AssertionMethod] - public static void NotNull([NoEnumeration] [SysNotNull] T? value, [CallerArgumentExpression("value")] string? parameterName = null) + public static void NotNull([NoEnumeration] [SysNotNull] T? value, [CallerArgumentExpression(nameof(value))] string? parameterName = null) where T : class { ArgumentNullException.ThrowIfNull(value, parameterName); } [AssertionMethod] - public static void NotNullNorEmpty([SysNotNull] IEnumerable? value, [CallerArgumentExpression("value")] string? parameterName = null) + public static void NotNullNorEmpty([SysNotNull] IEnumerable? value, [CallerArgumentExpression(nameof(value))] string? parameterName = null) { ArgumentNullException.ThrowIfNull(value, parameterName); @@ -27,13 +28,32 @@ public static void NotNullNorEmpty([SysNotNull] IEnumerable? value, [Calle } [AssertionMethod] - public static void NotNullNorEmpty([SysNotNull] string? value, [CallerArgumentExpression("value")] string? parameterName = null) + public static void NotNullNorEmpty([SysNotNull] string? value, [CallerArgumentExpression(nameof(value))] string? parameterName = null) { +#if !NET6_0 + ArgumentException.ThrowIfNullOrEmpty(value, parameterName); +#else ArgumentNullException.ThrowIfNull(value, parameterName); - if (value == string.Empty) + if (value.Length == 0) { throw new ArgumentException("String cannot be null or empty.", parameterName); } +#endif + } + + [AssertionMethod] + public static void NotNullNorWhitespace([SysNotNull] string? value, [CallerArgumentExpression(nameof(value))] string? parameterName = null) + { +#if !NET6_0 + ArgumentException.ThrowIfNullOrWhiteSpace(value, parameterName); +#else + ArgumentNullException.ThrowIfNull(value, parameterName); + + if (string.IsNullOrWhiteSpace(value)) + { + throw new ArgumentException("String cannot be null, empty, or whitespace.", parameterName); + } +#endif } } diff --git a/src/JsonApiDotNetCore.Annotations/CollectionConverter.cs b/src/JsonApiDotNetCore.Annotations/CollectionConverter.cs index e95d306329..750b896c27 100644 --- a/src/JsonApiDotNetCore.Annotations/CollectionConverter.cs +++ b/src/JsonApiDotNetCore.Annotations/CollectionConverter.cs @@ -5,15 +5,15 @@ namespace JsonApiDotNetCore; internal sealed class CollectionConverter { - private static readonly ISet HashSetCompatibleCollectionTypes = new HashSet - { + private static readonly HashSet HashSetCompatibleCollectionTypes = + [ typeof(HashSet<>), typeof(ISet<>), typeof(IReadOnlySet<>), typeof(ICollection<>), typeof(IReadOnlyCollection<>), typeof(IEnumerable<>) - }; + ]; /// /// Creates a collection instance based on the specified collection type and copies the specified elements into it. @@ -70,10 +70,10 @@ public IReadOnlyCollection ExtractResources(object? value) { return value switch { - List resourceList => resourceList, - HashSet resourceSet => resourceSet, + List resourceList => resourceList.AsReadOnly(), + HashSet resourceSet => resourceSet.AsReadOnly(), IReadOnlyCollection resourceCollection => resourceCollection, - IEnumerable resources => resources.ToList(), + IEnumerable resources => resources.ToArray().AsReadOnly(), IIdentifiable resource => [resource], _ => Array.Empty() }; diff --git a/src/JsonApiDotNetCore.Annotations/Configuration/ResourceType.cs b/src/JsonApiDotNetCore.Annotations/Configuration/ResourceType.cs index 47542def56..d8d5d63f3e 100644 --- a/src/JsonApiDotNetCore.Annotations/Configuration/ResourceType.cs +++ b/src/JsonApiDotNetCore.Annotations/Configuration/ResourceType.cs @@ -9,6 +9,10 @@ namespace JsonApiDotNetCore.Configuration; [PublicAPI] public sealed class ResourceType { + private static readonly IReadOnlySet EmptyResourceTypeSet = new HashSet().AsReadOnly(); + private static readonly IReadOnlySet EmptyAttributeSet = new HashSet().AsReadOnly(); + private static readonly IReadOnlySet EmptyRelationshipSet = new HashSet().AsReadOnly(); + private readonly Dictionary _fieldsByPublicName = []; private readonly Dictionary _fieldsByPropertyName = []; private readonly Lazy> _lazyAllConcreteDerivedTypes; @@ -42,7 +46,7 @@ public sealed class ResourceType /// /// The resource types that directly derive from this one. /// - public IReadOnlySet DirectlyDerivedTypes { get; internal set; } = new HashSet(); + public IReadOnlySet DirectlyDerivedTypes { get; internal set; } = EmptyResourceTypeSet; /// /// Exposed resource attributes and relationships. See https://jsonapi.org/format/#document-resource-object-fields. When using resource inheritance, this @@ -107,7 +111,7 @@ public ResourceType(string publicName, ClientIdGenerationMode? clientIdGeneratio IReadOnlyCollection? eagerLoads, LinkTypes topLevelLinks = LinkTypes.NotConfigured, LinkTypes resourceLinks = LinkTypes.NotConfigured, LinkTypes relationshipLinks = LinkTypes.NotConfigured) { - ArgumentGuard.NotNullNorEmpty(publicName); + ArgumentGuard.NotNullNorWhitespace(publicName); ArgumentGuard.NotNull(clrType); ArgumentGuard.NotNull(identityClrType); @@ -121,7 +125,7 @@ public ResourceType(string publicName, ClientIdGenerationMode? clientIdGeneratio TopLevelLinks = topLevelLinks; ResourceLinks = resourceLinks; RelationshipLinks = relationshipLinks; - Fields = Attributes.Cast().Concat(Relationships).ToArray(); + Fields = Attributes.Cast().Concat(Relationships).ToArray().AsReadOnly(); foreach (ResourceFieldAttribute field in Fields) { @@ -134,10 +138,10 @@ public ResourceType(string publicName, ClientIdGenerationMode? clientIdGeneratio private IReadOnlySet ResolveAllConcreteDerivedTypes() { - var allConcreteDerivedTypes = new HashSet(); + HashSet allConcreteDerivedTypes = []; AddConcreteDerivedTypes(this, allConcreteDerivedTypes); - return allConcreteDerivedTypes; + return allConcreteDerivedTypes.AsReadOnly(); } private static void AddConcreteDerivedTypes(ResourceType resourceType, ISet allConcreteDerivedTypes) @@ -259,7 +263,20 @@ public ResourceType GetTypeOrDerived(Type clrType) internal IReadOnlySet GetAttributesInTypeOrDerived(string publicName) { - return GetAttributesInTypeOrDerived(this, publicName); + if (IsPartOfTypeHierarchy()) + { + return GetAttributesInTypeOrDerived(this, publicName); + } + + AttrAttribute? attribute = FindAttributeByPublicName(publicName); + + if (attribute == null) + { + return EmptyAttributeSet; + } + + HashSet attributes = [attribute]; + return attributes.AsReadOnly(); } private static IReadOnlySet GetAttributesInTypeOrDerived(ResourceType resourceType, string publicName) @@ -268,7 +285,8 @@ private static IReadOnlySet GetAttributesInTypeOrDerived(Resource if (attribute != null) { - return attribute.AsHashSet(); + HashSet attributes = [attribute]; + return attributes.AsReadOnly(); } // Hiding base members using the 'new' keyword instead of 'override' (effectively breaking inheritance) is currently not supported. @@ -281,12 +299,25 @@ private static IReadOnlySet GetAttributesInTypeOrDerived(Resource attributesInDerivedTypes.Add(attributeInDerivedType); } - return attributesInDerivedTypes; + return attributesInDerivedTypes.AsReadOnly(); } internal IReadOnlySet GetRelationshipsInTypeOrDerived(string publicName) { - return GetRelationshipsInTypeOrDerived(this, publicName); + if (IsPartOfTypeHierarchy()) + { + return GetRelationshipsInTypeOrDerived(this, publicName); + } + + RelationshipAttribute? relationship = FindRelationshipByPublicName(publicName); + + if (relationship == null) + { + return EmptyRelationshipSet; + } + + HashSet relationships = [relationship]; + return relationships.AsReadOnly(); } private static IReadOnlySet GetRelationshipsInTypeOrDerived(ResourceType resourceType, string publicName) @@ -295,7 +326,8 @@ private static IReadOnlySet GetRelationshipsInTypeOrDeriv if (relationship != null) { - return relationship.AsHashSet(); + HashSet relationships = [relationship]; + return relationships.AsReadOnly(); } // Hiding base members using the 'new' keyword instead of 'override' (effectively breaking inheritance) is currently not supported. @@ -309,12 +341,12 @@ private static IReadOnlySet GetRelationshipsInTypeOrDeriv relationshipsInDerivedTypes.Add(relationshipInDerivedType); } - return relationshipsInDerivedTypes; + return relationshipsInDerivedTypes.AsReadOnly(); } internal bool IsPartOfTypeHierarchy() { - return BaseType != null || DirectlyDerivedTypes.Any(); + return BaseType != null || DirectlyDerivedTypes.Count > 0; } public override string ToString() diff --git a/src/JsonApiDotNetCore.Annotations/ObjectExtensions.cs b/src/JsonApiDotNetCore.Annotations/ObjectExtensions.cs deleted file mode 100644 index 8aa1e6c165..0000000000 --- a/src/JsonApiDotNetCore.Annotations/ObjectExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -#pragma warning disable AV1130 // Return type in method signature should be an interface to an unchangeable collection - -namespace JsonApiDotNetCore; - -internal static class ObjectExtensions -{ - public static HashSet AsHashSet(this T element) - { - return [element]; - } -} diff --git a/src/JsonApiDotNetCore.Annotations/PolyfillCollectionExtensions.cs b/src/JsonApiDotNetCore.Annotations/PolyfillCollectionExtensions.cs new file mode 100644 index 0000000000..72578e5db2 --- /dev/null +++ b/src/JsonApiDotNetCore.Annotations/PolyfillCollectionExtensions.cs @@ -0,0 +1,34 @@ +#if NET6_0 +using System.Collections.ObjectModel; +#endif + +#if NET6_0 +#pragma warning disable AV1130 // Return type in method signature should be an interface to an unchangeable collection +#endif + +namespace JsonApiDotNetCore; + +// These methods provide polyfills for lower .NET versions. +internal static class PolyfillCollectionExtensions +{ + public static IReadOnlySet AsReadOnly(this HashSet source) + { + // We can't use ReadOnlySet yet, which is being introduced in .NET 9. + return source; + } + +#if NET6_0 + public static ReadOnlyDictionary AsReadOnly(this IDictionary source) + where TKey : notnull + { + // The AsReadOnly() extension method is unavailable in .NET 6. + return new ReadOnlyDictionary(source); + } + + public static ReadOnlyCollection AsReadOnly(this T[] source) + { + // The AsReadOnly() extension method is unavailable in .NET 6. + return Array.AsReadOnly(source); + } +#endif +} diff --git a/src/JsonApiDotNetCore.Annotations/Resources/Annotations/ResourceFieldAttribute.cs b/src/JsonApiDotNetCore.Annotations/Resources/Annotations/ResourceFieldAttribute.cs index 3a3707442c..3b55c4b644 100644 --- a/src/JsonApiDotNetCore.Annotations/Resources/Annotations/ResourceFieldAttribute.cs +++ b/src/JsonApiDotNetCore.Annotations/Resources/Annotations/ResourceFieldAttribute.cs @@ -115,9 +115,11 @@ public virtual void SetValue(object resource, object? newValue) protected void AssertIsIdentifiable(object? resource) { - if (resource != null && resource is not IIdentifiable) + if (resource is not null and not IIdentifiable) { +#pragma warning disable CA1062 // Validate arguments of public methods throw new InvalidOperationException($"Resource of type '{resource.GetType()}' does not implement {nameof(IIdentifiable)}."); +#pragma warning restore CA1062 // Validate arguments of public methods } } diff --git a/src/JsonApiDotNetCore.SourceGenerators/SourceCodeWriter.cs b/src/JsonApiDotNetCore.SourceGenerators/SourceCodeWriter.cs index 1e68e5afab..3df1092c4b 100644 --- a/src/JsonApiDotNetCore.SourceGenerators/SourceCodeWriter.cs +++ b/src/JsonApiDotNetCore.SourceGenerators/SourceCodeWriter.cs @@ -10,36 +10,34 @@ internal sealed class SourceCodeWriter(GeneratorExecutionContext context, Diagno { private const int SpacesPerIndent = 4; - private static readonly IDictionary IndentTable = new Dictionary + private static readonly Dictionary IndentTable = new() { [0] = string.Empty, - [1] = new(' ', 1 * SpacesPerIndent), - [2] = new(' ', 2 * SpacesPerIndent), - [3] = new(' ', 3 * SpacesPerIndent) + [1] = new string(' ', 1 * SpacesPerIndent), + [2] = new string(' ', 2 * SpacesPerIndent), + [3] = new string(' ', 3 * SpacesPerIndent) }; - private static readonly IDictionary AggregateEndpointToServiceNameMap = - new Dictionary - { - [JsonApiEndpointsCopy.All] = ("IResourceService", "resourceService"), - [JsonApiEndpointsCopy.Query] = ("IResourceQueryService", "queryService"), - [JsonApiEndpointsCopy.Command] = ("IResourceCommandService", "commandService") - }; + private static readonly Dictionary AggregateEndpointToServiceNameMap = new() + { + [JsonApiEndpointsCopy.All] = ("IResourceService", "resourceService"), + [JsonApiEndpointsCopy.Query] = ("IResourceQueryService", "queryService"), + [JsonApiEndpointsCopy.Command] = ("IResourceCommandService", "commandService") + }; - private static readonly IDictionary EndpointToServiceNameMap = - new Dictionary - { - [JsonApiEndpointsCopy.GetCollection] = ("IGetAllService", "getAll"), - [JsonApiEndpointsCopy.GetSingle] = ("IGetByIdService", "getById"), - [JsonApiEndpointsCopy.GetSecondary] = ("IGetSecondaryService", "getSecondary"), - [JsonApiEndpointsCopy.GetRelationship] = ("IGetRelationshipService", "getRelationship"), - [JsonApiEndpointsCopy.Post] = ("ICreateService", "create"), - [JsonApiEndpointsCopy.PostRelationship] = ("IAddToRelationshipService", "addToRelationship"), - [JsonApiEndpointsCopy.Patch] = ("IUpdateService", "update"), - [JsonApiEndpointsCopy.PatchRelationship] = ("ISetRelationshipService", "setRelationship"), - [JsonApiEndpointsCopy.Delete] = ("IDeleteService", "delete"), - [JsonApiEndpointsCopy.DeleteRelationship] = ("IRemoveFromRelationshipService", "removeFromRelationship") - }; + private static readonly Dictionary EndpointToServiceNameMap = new() + { + [JsonApiEndpointsCopy.GetCollection] = ("IGetAllService", "getAll"), + [JsonApiEndpointsCopy.GetSingle] = ("IGetByIdService", "getById"), + [JsonApiEndpointsCopy.GetSecondary] = ("IGetSecondaryService", "getSecondary"), + [JsonApiEndpointsCopy.GetRelationship] = ("IGetRelationshipService", "getRelationship"), + [JsonApiEndpointsCopy.Post] = ("ICreateService", "create"), + [JsonApiEndpointsCopy.PostRelationship] = ("IAddToRelationshipService", "addToRelationship"), + [JsonApiEndpointsCopy.Patch] = ("IUpdateService", "update"), + [JsonApiEndpointsCopy.PatchRelationship] = ("ISetRelationshipService", "setRelationship"), + [JsonApiEndpointsCopy.Delete] = ("IDeleteService", "delete"), + [JsonApiEndpointsCopy.DeleteRelationship] = ("IRemoveFromRelationshipService", "removeFromRelationship") + }; private readonly GeneratorExecutionContext _context = context; private readonly DiagnosticDescriptor _missingIndentInTableErrorDescriptor = missingIndentInTableErrorDescriptor; diff --git a/src/JsonApiDotNetCore.SourceGenerators/TypeWithAttributeSyntaxReceiver.cs b/src/JsonApiDotNetCore.SourceGenerators/TypeWithAttributeSyntaxReceiver.cs index ad7b0d6ad5..17c5ffefd0 100644 --- a/src/JsonApiDotNetCore.SourceGenerators/TypeWithAttributeSyntaxReceiver.cs +++ b/src/JsonApiDotNetCore.SourceGenerators/TypeWithAttributeSyntaxReceiver.cs @@ -30,7 +30,7 @@ internal sealed class TypeWithAttributeSyntaxReceiver : ISyntaxReceiver public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { - if (syntaxNode is TypeDeclarationSyntax typeDeclarationSyntax && typeDeclarationSyntax.AttributeLists.Any()) + if (syntaxNode is TypeDeclarationSyntax { AttributeLists.Count: > 0 } typeDeclarationSyntax) { TypeDeclarations.Add(typeDeclarationSyntax); } diff --git a/src/JsonApiDotNetCore/AtomicOperations/LocalIdTracker.cs b/src/JsonApiDotNetCore/AtomicOperations/LocalIdTracker.cs index 09ebefaf93..5d22198a72 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/LocalIdTracker.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/LocalIdTracker.cs @@ -6,7 +6,7 @@ namespace JsonApiDotNetCore.AtomicOperations; /// public sealed class LocalIdTracker : ILocalIdTracker { - private readonly IDictionary _idsTracked = new Dictionary(); + private readonly Dictionary _idsTracked = new(); /// public void Reset() diff --git a/src/JsonApiDotNetCore/AtomicOperations/OperationProcessorAccessor.cs b/src/JsonApiDotNetCore/AtomicOperations/OperationProcessorAccessor.cs index 28ac16d612..927bbf92d3 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/OperationProcessorAccessor.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/OperationProcessorAccessor.cs @@ -31,6 +31,8 @@ public OperationProcessorAccessor(IServiceProvider serviceProvider) protected virtual IOperationProcessor ResolveProcessor(OperationContainer operation) { + ArgumentGuard.NotNull(operation); + Type processorInterface = GetProcessorInterface(operation.Request.WriteOperation!.Value); ResourceType resourceType = operation.Request.PrimaryResourceType!; diff --git a/src/JsonApiDotNetCore/AtomicOperations/OperationsProcessor.cs b/src/JsonApiDotNetCore/AtomicOperations/OperationsProcessor.cs index cf1cdd7b65..ff7a48dc32 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/OperationsProcessor.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/OperationsProcessor.cs @@ -51,7 +51,7 @@ public OperationsProcessor(IOperationProcessorAccessor operationProcessorAccesso _localIdValidator.Validate(operations); _localIdTracker.Reset(); - var results = new List(); + List results = []; await using IOperationsTransaction transaction = await _operationsTransactionFactory.BeginTransactionAsync(cancellationToken); @@ -101,6 +101,8 @@ public OperationsProcessor(IOperationProcessorAccessor operationProcessorAccesso protected virtual async Task ProcessOperationAsync(OperationContainer operation, CancellationToken cancellationToken) { + ArgumentGuard.NotNull(operation); + cancellationToken.ThrowIfCancellationRequested(); TrackLocalIdsForOperation(operation); @@ -113,6 +115,8 @@ public OperationsProcessor(IOperationProcessorAccessor operationProcessorAccesso protected void TrackLocalIdsForOperation(OperationContainer operation) { + ArgumentGuard.NotNull(operation); + if (operation.Request.WriteOperation == WriteOperationKind.CreateResource) { DeclareLocalId(operation.Resource, operation.Request.PrimaryResourceType!); diff --git a/src/JsonApiDotNetCore/AtomicOperations/RevertRequestStateOnDispose.cs b/src/JsonApiDotNetCore/AtomicOperations/RevertRequestStateOnDispose.cs index 1951333d0c..824e69de74 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/RevertRequestStateOnDispose.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/RevertRequestStateOnDispose.cs @@ -11,8 +11,8 @@ internal sealed class RevertRequestStateOnDispose : IDisposable private readonly IJsonApiRequest _sourceRequest; private readonly ITargetedFields? _sourceTargetedFields; - private readonly IJsonApiRequest _backupRequest = new JsonApiRequest(); - private readonly ITargetedFields _backupTargetedFields = new TargetedFields(); + private readonly JsonApiRequest _backupRequest = new(); + private readonly TargetedFields _backupTargetedFields = new(); public RevertRequestStateOnDispose(IJsonApiRequest request, ITargetedFields? targetedFields) { diff --git a/src/JsonApiDotNetCore/CollectionExtensions.cs b/src/JsonApiDotNetCore/CollectionExtensions.cs index 4e02b60fc5..6e9c74aed4 100644 --- a/src/JsonApiDotNetCore/CollectionExtensions.cs +++ b/src/JsonApiDotNetCore/CollectionExtensions.cs @@ -82,7 +82,7 @@ public static bool DictionaryEqual(this IReadOnlyDictionary EmptyIfNull(this IEnumerable? source) { - return source ?? []; + return source ?? Array.Empty(); } public static IEnumerable WhereNotNull(this IEnumerable source) diff --git a/src/JsonApiDotNetCore/Configuration/InverseNavigationResolver.cs b/src/JsonApiDotNetCore/Configuration/InverseNavigationResolver.cs index 6e3e2d718c..270444928e 100644 --- a/src/JsonApiDotNetCore/Configuration/InverseNavigationResolver.cs +++ b/src/JsonApiDotNetCore/Configuration/InverseNavigationResolver.cs @@ -11,7 +11,7 @@ namespace JsonApiDotNetCore.Configuration; public sealed class InverseNavigationResolver : IInverseNavigationResolver { private readonly IResourceGraph _resourceGraph; - private readonly IEnumerable _dbContextResolvers; + private readonly IDbContextResolver[] _dbContextResolvers; public InverseNavigationResolver(IResourceGraph resourceGraph, IEnumerable dbContextResolvers) { @@ -19,7 +19,7 @@ public InverseNavigationResolver(IResourceGraph resourceGraph, IEnumerable @@ -34,19 +34,19 @@ public void Resolve() private void Resolve(DbContext dbContext) { - foreach (ResourceType resourceType in _resourceGraph.GetResourceTypes().Where(resourceType => resourceType.Relationships.Any())) + foreach (ResourceType resourceType in _resourceGraph.GetResourceTypes().Where(resourceType => resourceType.Relationships.Count > 0)) { IEntityType? entityType = dbContext.Model.FindEntityType(resourceType.ClrType); if (entityType != null) { - IDictionary navigationMap = GetNavigations(entityType); + Dictionary navigationMap = GetNavigations(entityType); ResolveRelationships(resourceType.Relationships, navigationMap); } } } - private static IDictionary GetNavigations(IEntityType entityType) + private static Dictionary GetNavigations(IEntityType entityType) { // @formatter:wrap_chained_method_calls chop_always @@ -58,7 +58,7 @@ private static IDictionary GetNavigations(IEntityType e // @formatter:wrap_chained_method_calls restore } - private void ResolveRelationships(IReadOnlyCollection relationships, IDictionary navigationMap) + private void ResolveRelationships(IReadOnlyCollection relationships, Dictionary navigationMap) { foreach (RelationshipAttribute relationship in relationships) { diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiApplicationBuilder.cs b/src/JsonApiDotNetCore/Configuration/JsonApiApplicationBuilder.cs index 2f725e8c68..f2a0da8d02 100644 --- a/src/JsonApiDotNetCore/Configuration/JsonApiApplicationBuilder.cs +++ b/src/JsonApiDotNetCore/Configuration/JsonApiApplicationBuilder.cs @@ -137,7 +137,7 @@ public void ConfigureServiceContainer(ICollection dbContextTypes) { ArgumentGuard.NotNull(dbContextTypes); - if (dbContextTypes.Any()) + if (dbContextTypes.Count > 0) { _services.TryAddScoped(typeof(DbContextResolver<>)); diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiModelMetadataProvider.cs b/src/JsonApiDotNetCore/Configuration/JsonApiModelMetadataProvider.cs index 0f9cbf1fd2..2aaa218be7 100644 --- a/src/JsonApiDotNetCore/Configuration/JsonApiModelMetadataProvider.cs +++ b/src/JsonApiDotNetCore/Configuration/JsonApiModelMetadataProvider.cs @@ -31,6 +31,8 @@ public JsonApiModelMetadataProvider(ICompositeMetadataDetailsProvider detailsPro /// protected override ModelMetadata CreateModelMetadata(DefaultMetadataDetails entry) { + ArgumentGuard.NotNull(entry); + var metadata = (DefaultModelMetadata)base.CreateModelMetadata(entry); metadata.ValidationMetadata.PropertyValidationFilter = _jsonApiValidationFilter; diff --git a/src/JsonApiDotNetCore/Configuration/PageNumber.cs b/src/JsonApiDotNetCore/Configuration/PageNumber.cs index a2d4c0cba0..44732fc404 100644 --- a/src/JsonApiDotNetCore/Configuration/PageNumber.cs +++ b/src/JsonApiDotNetCore/Configuration/PageNumber.cs @@ -11,17 +11,21 @@ public sealed class PageNumber : IEquatable public PageNumber(int oneBasedValue) { +#if NET6_0 if (oneBasedValue < 1) { throw new ArgumentOutOfRangeException(nameof(oneBasedValue)); } +#else + ArgumentOutOfRangeException.ThrowIfLessThan(oneBasedValue, 1); +#endif OneBasedValue = oneBasedValue; } public bool Equals(PageNumber? other) { - if (ReferenceEquals(null, other)) + if (other is null) { return false; } diff --git a/src/JsonApiDotNetCore/Configuration/PageSize.cs b/src/JsonApiDotNetCore/Configuration/PageSize.cs index 7f926f519e..46beb1419f 100644 --- a/src/JsonApiDotNetCore/Configuration/PageSize.cs +++ b/src/JsonApiDotNetCore/Configuration/PageSize.cs @@ -9,17 +9,21 @@ public sealed class PageSize : IEquatable public PageSize(int value) { +#if NET6_0 if (value < 1) { throw new ArgumentOutOfRangeException(nameof(value)); } +#else + ArgumentOutOfRangeException.ThrowIfLessThan(value, 1); +#endif Value = value; } public bool Equals(PageSize? other) { - if (ReferenceEquals(null, other)) + if (other is null) { return false; } diff --git a/src/JsonApiDotNetCore/Configuration/ResourceDescriptorAssemblyCache.cs b/src/JsonApiDotNetCore/Configuration/ResourceDescriptorAssemblyCache.cs index a220d96e01..78d83425ce 100644 --- a/src/JsonApiDotNetCore/Configuration/ResourceDescriptorAssemblyCache.cs +++ b/src/JsonApiDotNetCore/Configuration/ResourceDescriptorAssemblyCache.cs @@ -8,7 +8,7 @@ namespace JsonApiDotNetCore.Configuration; internal sealed class ResourceDescriptorAssemblyCache { private readonly TypeLocator _typeLocator = new(); - private readonly Dictionary?> _resourceDescriptorsPerAssembly = []; + private readonly Dictionary _resourceDescriptorsPerAssembly = []; public void RegisterAssembly(Assembly assembly) { @@ -19,7 +19,7 @@ public IReadOnlyCollection GetResourceDescriptors() { EnsureAssembliesScanned(); - return _resourceDescriptorsPerAssembly.SelectMany(pair => pair.Value!).ToArray(); + return _resourceDescriptorsPerAssembly.SelectMany(pair => pair.Value!).ToArray().AsReadOnly(); } public IReadOnlyCollection GetAssemblies() diff --git a/src/JsonApiDotNetCore/Configuration/ResourceGraph.cs b/src/JsonApiDotNetCore/Configuration/ResourceGraph.cs index e763ec2ae0..b0eddedc91 100644 --- a/src/JsonApiDotNetCore/Configuration/ResourceGraph.cs +++ b/src/JsonApiDotNetCore/Configuration/ResourceGraph.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Linq.Expressions; using System.Reflection; using JetBrains.Annotations; @@ -117,12 +118,12 @@ public IReadOnlyCollection GetRelationships(Ex return FilterFields(selector); } - private IReadOnlyCollection FilterFields(Expression> selector) + private ReadOnlyCollection FilterFields(Expression> selector) where TResource : class, IIdentifiable where TField : ResourceFieldAttribute { IReadOnlyCollection source = GetFieldsOfType(); - var matches = new List(); + List matches = []; foreach (string memberName in ToMemberNames(selector)) { @@ -136,7 +137,7 @@ private IReadOnlyCollection FilterFields(Expression GetFieldsOfType() diff --git a/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs b/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs index b0ebd8bb60..159ce5be69 100644 --- a/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs +++ b/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Reflection; using JetBrains.Annotations; using JsonApiDotNetCore.Errors; @@ -13,7 +14,7 @@ namespace JsonApiDotNetCore.Configuration; /// Builds and configures the . /// [PublicAPI] -public class ResourceGraphBuilder +public partial class ResourceGraphBuilder { private readonly IJsonApiOptions _options; private readonly ILogger _logger; @@ -34,11 +35,11 @@ public ResourceGraphBuilder(IJsonApiOptions options, ILoggerFactory loggerFactor /// public IResourceGraph Build() { - HashSet resourceTypes = [.. _resourceTypesByClrType.Values]; + IReadOnlySet resourceTypes = _resourceTypesByClrType.Values.ToHashSet().AsReadOnly(); - if (!resourceTypes.Any()) + if (resourceTypes.Count == 0) { - _logger.LogWarning("The resource graph is empty."); + LogResourceGraphIsEmpty(); } var resourceGraph = new ResourceGraph(resourceTypes); @@ -91,18 +92,22 @@ private static void SetDirectlyDerivedTypes(ResourceGraph resourceGraph) { resourceType.BaseType = baseType; - if (!directlyDerivedTypesPerBaseType.ContainsKey(baseType)) + if (!directlyDerivedTypesPerBaseType.TryGetValue(baseType, out HashSet? directlyDerivedTypes)) { - directlyDerivedTypesPerBaseType[baseType] = []; + directlyDerivedTypes = []; + directlyDerivedTypesPerBaseType[baseType] = directlyDerivedTypes; } - directlyDerivedTypesPerBaseType[baseType].Add(resourceType); + directlyDerivedTypes.Add(resourceType); } } foreach ((ResourceType baseType, HashSet directlyDerivedTypes) in directlyDerivedTypesPerBaseType) { - baseType.DirectlyDerivedTypes = directlyDerivedTypes; + if (directlyDerivedTypes.Count > 0) + { + baseType.DirectlyDerivedTypes = directlyDerivedTypes.AsReadOnly(); + } } } @@ -227,8 +232,7 @@ public ResourceGraphBuilder Add(Type resourceClrType, Type? idClrType = null, st { if (resourceClrType.GetCustomAttribute() == null) { - _logger.LogWarning( - $"Skipping: Type '{resourceClrType}' does not implement '{nameof(IIdentifiable)}'. Add [NoResource] to suppress this warning."); + LogResourceTypeDoesNotImplementInterface(resourceClrType, nameof(IIdentifiable)); } } @@ -239,9 +243,9 @@ private ResourceType CreateResourceType(string publicName, Type resourceClrType, { ClientIdGenerationMode? clientIdGeneration = GetClientIdGeneration(resourceClrType); - IReadOnlyCollection attributes = GetAttributes(resourceClrType); - IReadOnlyCollection relationships = GetRelationships(resourceClrType); - IReadOnlyCollection eagerLoads = GetEagerLoads(resourceClrType); + Dictionary.ValueCollection attributes = GetAttributes(resourceClrType); + Dictionary.ValueCollection relationships = GetRelationships(resourceClrType); + ReadOnlyCollection eagerLoads = GetEagerLoads(resourceClrType); AssertNoDuplicatePublicName(attributes, relationships); @@ -259,7 +263,7 @@ private ResourceType CreateResourceType(string publicName, Type resourceClrType, return resourceAttribute?.NullableClientIdGeneration; } - private IReadOnlyCollection GetAttributes(Type resourceClrType) + private Dictionary.ValueCollection GetAttributes(Type resourceClrType) { var attributesByName = new Dictionary(); @@ -296,13 +300,13 @@ private IReadOnlyCollection GetAttributes(Type resourceClrType) if (attributesByName.Count < 2) { - _logger.LogWarning($"Type '{resourceClrType}' does not contain any attributes."); + LogResourceTypeHasNoAttributes(resourceClrType); } return attributesByName.Values; } - private IReadOnlyCollection GetRelationships(Type resourceClrType) + private Dictionary.ValueCollection GetRelationships(Type resourceClrType) { var relationshipsByName = new Dictionary(); PropertyInfo[] properties = resourceClrType.GetProperties(); @@ -376,11 +380,11 @@ private void SetHasManyRelationshipCapabilities(HasManyAttribute hasManyRelation } } - private IReadOnlyCollection GetEagerLoads(Type resourceClrType, int recursionDepth = 0) + private ReadOnlyCollection GetEagerLoads(Type resourceClrType, int recursionDepth = 0) { AssertNoInfiniteRecursion(recursionDepth); - var attributes = new List(); + List eagerLoads = []; PropertyInfo[] properties = resourceClrType.GetProperties(); foreach (PropertyInfo property in properties) @@ -396,10 +400,10 @@ private IReadOnlyCollection GetEagerLoads(Type resourceClrTy eagerLoad.Children = GetEagerLoads(innerType, recursionDepth + 1); eagerLoad.Property = property; - attributes.Add(eagerLoad); + eagerLoads.Add(eagerLoad); } - return attributes; + return eagerLoads.AsReadOnly(); } private static void IncludeField(Dictionary fieldsByName, TField field) @@ -475,4 +479,14 @@ private string FormatPropertyName(PropertyInfo resourceProperty) ? resourceProperty.Name : _options.SerializerOptions.PropertyNamingPolicy.ConvertName(resourceProperty.Name); } + + [LoggerMessage(Level = LogLevel.Warning, Message = "The resource graph is empty.")] + private partial void LogResourceGraphIsEmpty(); + + [LoggerMessage(Level = LogLevel.Warning, + Message = "Skipping: Type '{ResourceType}' does not implement '{InterfaceType}'. Add [NoResource] to suppress this warning.")] + private partial void LogResourceTypeDoesNotImplementInterface(Type resourceType, string interfaceType); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Type '{ResourceType}' does not contain any attributes.")] + private partial void LogResourceTypeHasNoAttributes(Type resourceType); } diff --git a/src/JsonApiDotNetCore/Configuration/TypeLocator.cs b/src/JsonApiDotNetCore/Configuration/TypeLocator.cs index 9f65b46b97..bce31946f1 100644 --- a/src/JsonApiDotNetCore/Configuration/TypeLocator.cs +++ b/src/JsonApiDotNetCore/Configuration/TypeLocator.cs @@ -110,33 +110,6 @@ private static (Type implementationType, Type serviceInterface)? GetContainerReg return null; } - /// - /// Scans for types in the specified assembly that derive from the specified unbound generic type. - /// - /// - /// The assembly to search for derived types. - /// - /// - /// The unbound generic type to match against. - /// - /// - /// Generic type arguments to construct . - /// - /// - /// ), typeof(Article), typeof(int)) - /// ]]> - /// - public IReadOnlyCollection GetDerivedTypesForUnboundType(Assembly assembly, Type unboundType, params Type[] typeArguments) - { - ArgumentGuard.NotNull(assembly); - ArgumentGuard.NotNull(unboundType); - ArgumentGuard.NotNull(typeArguments); - - Type closedType = unboundType.MakeGenericType(typeArguments); - return GetDerivedTypes(assembly, closedType).ToArray(); - } - /// /// Gets all derivatives of the specified type. /// diff --git a/src/JsonApiDotNetCore/Controllers/Annotations/DisableQueryStringAttribute.cs b/src/JsonApiDotNetCore/Controllers/Annotations/DisableQueryStringAttribute.cs index eba4b8340c..b659fdc370 100644 --- a/src/JsonApiDotNetCore/Controllers/Annotations/DisableQueryStringAttribute.cs +++ b/src/JsonApiDotNetCore/Controllers/Annotations/DisableQueryStringAttribute.cs @@ -27,7 +27,7 @@ public sealed class DisableQueryStringAttribute : Attribute /// public DisableQueryStringAttribute(JsonApiQueryStringParameters parameters) { - var parameterNames = new HashSet(); + HashSet parameterNames = []; foreach (JsonApiQueryStringParameters value in Enum.GetValues()) { @@ -37,7 +37,7 @@ public DisableQueryStringAttribute(JsonApiQueryStringParameters parameters) } } - ParameterNames = parameterNames; + ParameterNames = parameterNames.AsReadOnly(); } /// @@ -48,7 +48,7 @@ public DisableQueryStringAttribute(string parameterNames) { ArgumentGuard.NotNullNorEmpty(parameterNames); - ParameterNames = parameterNames.Split(",").ToHashSet(); + ParameterNames = parameterNames.Split(",").ToHashSet().AsReadOnly(); } public bool ContainsParameter(JsonApiQueryStringParameters parameter) diff --git a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs index bef962a971..d293a98701 100644 --- a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs +++ b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs @@ -134,7 +134,8 @@ public virtual async Task GetAsync([DisallowNull] TId id, Cancell /// GET /articles/1/revisions HTTP/1.1 /// ]]> /// - public virtual async Task GetSecondaryAsync([DisallowNull] TId id, string relationshipName, CancellationToken cancellationToken) + public virtual async Task GetSecondaryAsync([DisallowNull] TId id, [PreserveEmptyString] string relationshipName, + CancellationToken cancellationToken) { _traceWriter.LogMethodStart(new { @@ -142,7 +143,7 @@ public virtual async Task GetSecondaryAsync([DisallowNull] TId id relationshipName }); - ArgumentGuard.NotNullNorEmpty(relationshipName); + ArgumentGuard.NotNull(relationshipName); if (_getSecondary == null) { @@ -163,7 +164,8 @@ public virtual async Task GetSecondaryAsync([DisallowNull] TId id /// GET /articles/1/relationships/revisions HTTP/1.1 /// ]]> /// - public virtual async Task GetRelationshipAsync([DisallowNull] TId id, string relationshipName, CancellationToken cancellationToken) + public virtual async Task GetRelationshipAsync([DisallowNull] TId id, [PreserveEmptyString] string relationshipName, + CancellationToken cancellationToken) { _traceWriter.LogMethodStart(new { @@ -171,7 +173,7 @@ public virtual async Task GetRelationshipAsync([DisallowNull] TId relationshipName }); - ArgumentGuard.NotNullNorEmpty(relationshipName); + ArgumentGuard.NotNull(relationshipName); if (_getRelationship == null) { @@ -214,7 +216,7 @@ public virtual async Task PostAsync([FromBody] TResource resource if (newResource == null) { - HttpContext.Response.Headers["Location"] = locationUrl; + HttpContext.Response.Headers.Location = locationUrl; return NoContent(); } @@ -247,7 +249,7 @@ private string GetLocationUrl(string resourceId) /// /// Propagates notification that request handling should be canceled. /// - public virtual async Task PostRelationshipAsync([DisallowNull] TId id, string relationshipName, + public virtual async Task PostRelationshipAsync([DisallowNull] TId id, [PreserveEmptyString] string relationshipName, [FromBody] ISet rightResourceIds, CancellationToken cancellationToken) { _traceWriter.LogMethodStart(new @@ -257,7 +259,7 @@ public virtual async Task PostRelationshipAsync([DisallowNull] TI rightResourceIds }); - ArgumentGuard.NotNullNorEmpty(relationshipName); + ArgumentGuard.NotNull(relationshipName); ArgumentGuard.NotNull(rightResourceIds); if (_addToRelationship == null) @@ -322,8 +324,8 @@ public virtual async Task PatchAsync([DisallowNull] TId id, [From /// /// Propagates notification that request handling should be canceled. /// - public virtual async Task PatchRelationshipAsync([DisallowNull] TId id, string relationshipName, [FromBody] object? rightValue, - CancellationToken cancellationToken) + public virtual async Task PatchRelationshipAsync([DisallowNull] TId id, [PreserveEmptyString] string relationshipName, + [FromBody] object? rightValue, CancellationToken cancellationToken) { _traceWriter.LogMethodStart(new { @@ -332,7 +334,7 @@ public virtual async Task PatchRelationshipAsync([DisallowNull] T rightValue }); - ArgumentGuard.NotNullNorEmpty(relationshipName); + ArgumentGuard.NotNull(relationshipName); if (_setRelationship == null) { @@ -383,7 +385,7 @@ public virtual async Task DeleteAsync([DisallowNull] TId id, Canc /// /// Propagates notification that request handling should be canceled. /// - public virtual async Task DeleteRelationshipAsync([DisallowNull] TId id, string relationshipName, + public virtual async Task DeleteRelationshipAsync([DisallowNull] TId id, [PreserveEmptyString] string relationshipName, [FromBody] ISet rightResourceIds, CancellationToken cancellationToken) { _traceWriter.LogMethodStart(new @@ -393,7 +395,7 @@ public virtual async Task DeleteRelationshipAsync([DisallowNull] rightResourceIds }); - ArgumentGuard.NotNullNorEmpty(relationshipName); + ArgumentGuard.NotNull(relationshipName); ArgumentGuard.NotNull(rightResourceIds); if (_removeFromRelationship == null) diff --git a/src/JsonApiDotNetCore/Controllers/BaseJsonApiOperationsController.cs b/src/JsonApiDotNetCore/Controllers/BaseJsonApiOperationsController.cs index b169bdd005..1ed6afec83 100644 --- a/src/JsonApiDotNetCore/Controllers/BaseJsonApiOperationsController.cs +++ b/src/JsonApiDotNetCore/Controllers/BaseJsonApiOperationsController.cs @@ -129,6 +129,8 @@ public virtual async Task PostOperationsAsync([FromBody] IList operations) { + ArgumentGuard.NotNull(operations); + List errors = []; for (int operationIndex = 0; operationIndex < operations.Count; operationIndex++) @@ -191,13 +193,15 @@ private static string GetOperationCodeText(WriteOperationKind operationKind) protected virtual void ValidateModelState(IList operations) { + ArgumentGuard.NotNull(operations); + // We must validate the resource inside each operation manually, because they are typed as IIdentifiable. // Instead of validating IIdentifiable we need to validate the resource runtime-type. using IDisposable _ = new RevertRequestStateOnDispose(_request, _targetedFields); int operationIndex = 0; - var requestModelState = new List<(string key, ModelStateEntry? entry)>(); + List<(string key, ModelStateEntry? entry)> requestModelState = []; int maxErrorsRemaining = ModelState.MaxAllowedErrors; foreach (OperationContainer operation in operations) @@ -212,7 +216,7 @@ protected virtual void ValidateModelState(IList operations) operationIndex++; } - if (requestModelState.Any()) + if (requestModelState.Count > 0) { Dictionary modelStateDictionary = requestModelState.ToDictionary(tuple => tuple.key, tuple => tuple.entry); diff --git a/src/JsonApiDotNetCore/Controllers/CoreJsonApiController.cs b/src/JsonApiDotNetCore/Controllers/CoreJsonApiController.cs index b4626ba031..332a9bf255 100644 --- a/src/JsonApiDotNetCore/Controllers/CoreJsonApiController.cs +++ b/src/JsonApiDotNetCore/Controllers/CoreJsonApiController.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using JsonApiDotNetCore.Serialization.Objects; using Microsoft.AspNetCore.Mvc; @@ -20,17 +21,17 @@ protected IActionResult Error(ErrorObject error) protected IActionResult Error(IEnumerable errors) { - IReadOnlyList? errorList = ToErrorList(errors); - ArgumentGuard.NotNullNorEmpty(errorList); + ReadOnlyCollection? errorCollection = ToCollection(errors); + ArgumentGuard.NotNullNorEmpty(errorCollection, nameof(errors)); - return new ObjectResult(errorList) + return new ObjectResult(errorCollection) { - StatusCode = (int)ErrorObject.GetResponseStatusCode(errorList) + StatusCode = (int)ErrorObject.GetResponseStatusCode(errorCollection) }; } - private static IReadOnlyList? ToErrorList(IEnumerable? errors) + private static ReadOnlyCollection? ToCollection(IEnumerable? errors) { - return errors?.ToArray(); + return errors?.ToArray().AsReadOnly(); } } diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiCommandController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiCommandController.cs index 290487cb76..cd58e2d18d 100644 --- a/src/JsonApiDotNetCore/Controllers/JsonApiCommandController.cs +++ b/src/JsonApiDotNetCore/Controllers/JsonApiCommandController.cs @@ -15,16 +15,8 @@ namespace JsonApiDotNetCore.Controllers; /// /// The resource identifier type. /// -public abstract class JsonApiCommandController : JsonApiController - where TResource : class, IIdentifiable -{ - /// - /// Creates an instance from a write-only service. - /// - protected JsonApiCommandController(IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, - IResourceCommandService commandService) - : base(options, resourceGraph, loggerFactory, null, null, null, null, commandService, commandService, commandService, commandService, commandService, - commandService) - { - } -} +public abstract class JsonApiCommandController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IResourceCommandService commandService) + : JsonApiController(options, resourceGraph, loggerFactory, null, null, null, null, commandService, commandService, commandService, + commandService, commandService, commandService) + where TResource : class, IIdentifiable; diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiController.cs index 846fedb28b..84e4dad3b5 100644 --- a/src/JsonApiDotNetCore/Controllers/JsonApiController.cs +++ b/src/JsonApiDotNetCore/Controllers/JsonApiController.cs @@ -6,6 +6,8 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; +#pragma warning disable format + namespace JsonApiDotNetCore.Controllers; /// diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiQueryController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiQueryController.cs index fa101c2118..6db14e9fde 100644 --- a/src/JsonApiDotNetCore/Controllers/JsonApiQueryController.cs +++ b/src/JsonApiDotNetCore/Controllers/JsonApiQueryController.cs @@ -15,15 +15,7 @@ namespace JsonApiDotNetCore.Controllers; /// /// The resource identifier type. /// -public abstract class JsonApiQueryController : JsonApiController - where TResource : class, IIdentifiable -{ - /// - /// Creates an instance from a read-only service. - /// - protected JsonApiQueryController(IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, - IResourceQueryService queryService) - : base(options, resourceGraph, loggerFactory, queryService, queryService, queryService, queryService) - { - } -} +public abstract class JsonApiQueryController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IResourceQueryService queryService) + : JsonApiController(options, resourceGraph, loggerFactory, queryService, queryService, queryService, queryService) + where TResource : class, IIdentifiable; diff --git a/src/JsonApiDotNetCore/Controllers/PreserveEmptyStringAttribute.cs b/src/JsonApiDotNetCore/Controllers/PreserveEmptyStringAttribute.cs new file mode 100644 index 0000000000..d76f94ace1 --- /dev/null +++ b/src/JsonApiDotNetCore/Controllers/PreserveEmptyStringAttribute.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.Controllers; + +[PublicAPI] +[AttributeUsage(AttributeTargets.Parameter)] +public sealed class PreserveEmptyStringAttribute : DisplayFormatAttribute +{ + public PreserveEmptyStringAttribute() + { + // Workaround for https://github.com/dotnet/aspnetcore/issues/29948#issuecomment-1898216682 + ConvertEmptyStringToNull = false; + } +} diff --git a/src/JsonApiDotNetCore/Diagnostics/CascadingCodeTimer.cs b/src/JsonApiDotNetCore/Diagnostics/CascadingCodeTimer.cs index 8fc75dad4e..48109b4c98 100644 --- a/src/JsonApiDotNetCore/Diagnostics/CascadingCodeTimer.cs +++ b/src/JsonApiDotNetCore/Diagnostics/CascadingCodeTimer.cs @@ -3,6 +3,8 @@ using System.Runtime.InteropServices; using System.Text; +#pragma warning disable CA2000 // Dispose objects before losing scope + namespace JsonApiDotNetCore.Diagnostics; /// @@ -65,7 +67,7 @@ private void Close(MeasureScope scope) _activeScopeStack.Pop(); - if (!_activeScopeStack.Any()) + if (_activeScopeStack.Count == 0) { _completedScopes.Add(scope); } @@ -92,7 +94,7 @@ private int GetPaddingLength() maxLength = Math.Max(maxLength, nextLength); } - if (_activeScopeStack.Any()) + if (_activeScopeStack.Count > 0) { MeasureScope scope = _activeScopeStack.Peek(); int nextLength = scope.GetPaddingLength(); @@ -109,7 +111,7 @@ private void WriteResult(StringBuilder builder, int paddingLength) scope.WriteResult(builder, 0, paddingLength); } - if (_activeScopeStack.Any()) + if (_activeScopeStack.Count > 0) { MeasureScope scope = _activeScopeStack.Peek(); scope.WriteResult(builder, 0, paddingLength); @@ -130,7 +132,7 @@ public void Dispose() private sealed class MeasureScope : IDisposable { private readonly CascadingCodeTimer _owner; - private readonly IList _children = new List(); + private readonly List _children = []; private readonly bool _excludeInRelativeCost; private readonly TimeSpan _startedAt; private TimeSpan? _stoppedAt; diff --git a/src/JsonApiDotNetCore/Diagnostics/CodeTimingSessionManager.cs b/src/JsonApiDotNetCore/Diagnostics/CodeTimingSessionManager.cs index 5a862409bc..47f4007db0 100644 --- a/src/JsonApiDotNetCore/Diagnostics/CodeTimingSessionManager.cs +++ b/src/JsonApiDotNetCore/Diagnostics/CodeTimingSessionManager.cs @@ -10,7 +10,7 @@ namespace JsonApiDotNetCore.Diagnostics; /// public static class CodeTimingSessionManager { - public static readonly bool IsEnabled; + public static readonly bool IsEnabled = GetDefaultIsEnabled(); private static ICodeTimerSession? _session; public static ICodeTimer Current @@ -28,12 +28,12 @@ public static ICodeTimer Current } } - static CodeTimingSessionManager() + private static bool GetDefaultIsEnabled() { #if DEBUG - IsEnabled = !IsRunningInTest() && !IsRunningInBenchmark(); + return !IsRunningInTest() && !IsRunningInBenchmark(); #else - IsEnabled = false; + return false; #endif } diff --git a/src/JsonApiDotNetCore/Diagnostics/DefaultCodeTimerSession.cs b/src/JsonApiDotNetCore/Diagnostics/DefaultCodeTimerSession.cs index a1662095cb..5737dbe3f2 100644 --- a/src/JsonApiDotNetCore/Diagnostics/DefaultCodeTimerSession.cs +++ b/src/JsonApiDotNetCore/Diagnostics/DefaultCodeTimerSession.cs @@ -27,10 +27,14 @@ public DefaultCodeTimerSession() private void AssertNotDisposed() { +#if NET6_0 if (_codeTimerInContext.Value == null) { throw new ObjectDisposedException(nameof(DefaultCodeTimerSession)); } +#else + ObjectDisposedException.ThrowIf(_codeTimerInContext.Value == null, this); +#endif } public void Dispose() diff --git a/src/JsonApiDotNetCore/Errors/InvalidModelStateException.cs b/src/JsonApiDotNetCore/Errors/InvalidModelStateException.cs index 396694b50a..478553f16b 100644 --- a/src/JsonApiDotNetCore/Errors/InvalidModelStateException.cs +++ b/src/JsonApiDotNetCore/Errors/InvalidModelStateException.cs @@ -20,7 +20,7 @@ public sealed class InvalidModelStateException( Func? getCollectionElementTypeCallback = null) : JsonApiException(FromModelStateDictionary(modelState, modelType, resourceGraph, includeExceptionStackTraceInErrors, getCollectionElementTypeCallback)) { - private static IEnumerable FromModelStateDictionary(IReadOnlyDictionary modelState, Type modelType, + private static List FromModelStateDictionary(IReadOnlyDictionary modelState, Type modelType, IResourceGraph resourceGraph, bool includeExceptionStackTraceInErrors, Func? getCollectionElementTypeCallback) { ArgumentGuard.NotNull(modelState); @@ -186,7 +186,7 @@ private static ErrorObject FromModelError(ModelError modelError, string? sourceP Exception exception = modelError.Exception.Demystify(); string[] stackTraceLines = exception.ToString().Split(Environment.NewLine); - if (stackTraceLines.Any()) + if (stackTraceLines.Length > 0) { error.Meta ??= new Dictionary(); error.Meta["StackTrace"] = stackTraceLines; @@ -246,7 +246,7 @@ protected ModelStateKeySegment(Type modelType, bool isInComplexType, string next { ArgumentGuard.NotNull(modelType); - return _nextKey == string.Empty ? null : CreateSegment(modelType, _nextKey, isInComplexType, this, sourcePointer, GetCollectionElementTypeCallback); + return _nextKey.Length == 0 ? null : CreateSegment(modelType, _nextKey, isInComplexType, this, sourcePointer, GetCollectionElementTypeCallback); } public static ModelStateKeySegment Create(Type modelType, string key, Func? getCollectionElementTypeCallback) @@ -271,7 +271,7 @@ private static ModelStateKeySegment CreateSegment(Type modelType, string key, bo if (bracketCloseIndex != -1) { - segmentValue = key[1.. bracketCloseIndex]; + segmentValue = key[1..bracketCloseIndex]; int nextKeyStartIndex = key.Length > bracketCloseIndex + 1 && key[bracketCloseIndex + 1] == Dot ? bracketCloseIndex + 2 diff --git a/src/JsonApiDotNetCore/Errors/InvalidRequestBodyException.cs b/src/JsonApiDotNetCore/Errors/InvalidRequestBodyException.cs index 25297a4056..0b667d532e 100644 --- a/src/JsonApiDotNetCore/Errors/InvalidRequestBodyException.cs +++ b/src/JsonApiDotNetCore/Errors/InvalidRequestBodyException.cs @@ -2,6 +2,8 @@ using JetBrains.Annotations; using JsonApiDotNetCore.Serialization.Objects; +#pragma warning disable format + namespace JsonApiDotNetCore.Errors; /// diff --git a/src/JsonApiDotNetCore/Errors/JsonApiException.cs b/src/JsonApiDotNetCore/Errors/JsonApiException.cs index 097b972089..1f15a127b4 100644 --- a/src/JsonApiDotNetCore/Errors/JsonApiException.cs +++ b/src/JsonApiDotNetCore/Errors/JsonApiException.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Serialization; @@ -32,15 +33,15 @@ public JsonApiException(ErrorObject error, Exception? innerException = null) public JsonApiException(IEnumerable errors, Exception? innerException = null) : base(null, innerException) { - IReadOnlyList? errorList = ToErrorList(errors); - ArgumentGuard.NotNullNorEmpty(errorList); + ReadOnlyCollection? errorCollection = ToCollection(errors); + ArgumentGuard.NotNullNorEmpty(errorCollection, nameof(errors)); - Errors = errorList; + Errors = errorCollection; } - private static IReadOnlyList? ToErrorList(IEnumerable? errors) + private static ReadOnlyCollection? ToCollection(IEnumerable? errors) { - return errors?.ToList(); + return errors?.ToArray().AsReadOnly(); } public string GetSummary() diff --git a/src/JsonApiDotNetCore/Errors/MissingResourceInRelationship.cs b/src/JsonApiDotNetCore/Errors/MissingResourceInRelationship.cs index 42082d6126..c2afd80cbf 100644 --- a/src/JsonApiDotNetCore/Errors/MissingResourceInRelationship.cs +++ b/src/JsonApiDotNetCore/Errors/MissingResourceInRelationship.cs @@ -11,9 +11,9 @@ public sealed class MissingResourceInRelationship public MissingResourceInRelationship(string relationshipName, string resourceType, string resourceId) { - ArgumentGuard.NotNullNorEmpty(relationshipName); - ArgumentGuard.NotNullNorEmpty(resourceType); - ArgumentGuard.NotNullNorEmpty(resourceId); + ArgumentGuard.NotNull(relationshipName); + ArgumentGuard.NotNull(resourceType); + ArgumentGuard.NotNull(resourceId); RelationshipName = relationshipName; ResourceType = resourceType; diff --git a/src/JsonApiDotNetCore/Errors/UnsuccessfulActionResultException.cs b/src/JsonApiDotNetCore/Errors/UnsuccessfulActionResultException.cs index b5ab3859cc..16f79db822 100644 --- a/src/JsonApiDotNetCore/Errors/UnsuccessfulActionResultException.cs +++ b/src/JsonApiDotNetCore/Errors/UnsuccessfulActionResultException.cs @@ -31,7 +31,7 @@ private static IEnumerable ToErrorObjects(ProblemDetails problemDet HttpStatusCode status = problemDetails.Status != null ? (HttpStatusCode)problemDetails.Status.Value : HttpStatusCode.InternalServerError; - if (problemDetails is HttpValidationProblemDetails validationProblemDetails && validationProblemDetails.Errors.Any()) + if (problemDetails is HttpValidationProblemDetails { Errors.Count: > 0 } validationProblemDetails) { foreach (string errorMessage in validationProblemDetails.Errors.SelectMany(pair => pair.Value)) { diff --git a/src/JsonApiDotNetCore/Middleware/ExceptionHandler.cs b/src/JsonApiDotNetCore/Middleware/ExceptionHandler.cs index 816c5ffbb7..0712f659ac 100644 --- a/src/JsonApiDotNetCore/Middleware/ExceptionHandler.cs +++ b/src/JsonApiDotNetCore/Middleware/ExceptionHandler.cs @@ -10,7 +10,7 @@ namespace JsonApiDotNetCore.Middleware; /// [PublicAPI] -public class ExceptionHandler : IExceptionHandler +public partial class ExceptionHandler : IExceptionHandler { private readonly IJsonApiOptions _options; private readonly ILogger _logger; @@ -40,7 +40,7 @@ private void LogException(Exception exception) LogLevel level = GetLogLevel(exception); string message = GetLogMessage(exception); - _logger.Log(level, exception, message); + LogException(level, exception, message); } protected virtual LogLevel GetLogLevel(Exception exception) @@ -74,21 +74,21 @@ protected virtual IReadOnlyList CreateErrorResponse(Exception excep IReadOnlyList errors = exception switch { JsonApiException jsonApiException => jsonApiException.Errors, - OperationCanceledException => - [ + OperationCanceledException => new[] + { new ErrorObject((HttpStatusCode)499) { Title = "Request execution was canceled." } - ], - _ => - [ + }.AsReadOnly(), + _ => new[] + { new ErrorObject(HttpStatusCode.InternalServerError) { Title = "An unhandled error occurred while processing this request.", Detail = exception.Message } - ] + }.AsReadOnly() }; if (_options.IncludeExceptionStackTraceInErrors && exception is not InvalidModelStateException) @@ -103,7 +103,7 @@ private void IncludeStackTraces(Exception exception, IReadOnlyList { string[] stackTraceLines = exception.ToString().Split(Environment.NewLine); - if (stackTraceLines.Any()) + if (stackTraceLines.Length > 0) { foreach (ErrorObject error in errors) { @@ -112,4 +112,7 @@ private void IncludeStackTraces(Exception exception, IReadOnlyList } } } + + [LoggerMessage(Message = "{Message}")] + private partial void LogException(LogLevel level, Exception exception, string message); } diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs b/src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs index 4d9896ce8a..8983c00a6f 100644 --- a/src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs +++ b/src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs @@ -18,7 +18,7 @@ namespace JsonApiDotNetCore.Middleware; /// Intercepts HTTP requests to populate injected instance for JSON:API requests. /// [PublicAPI] -public sealed class JsonApiMiddleware +public sealed partial class JsonApiMiddleware { private static readonly string[] NonOperationsContentTypes = [HeaderConstants.MediaType]; private static readonly MediaTypeHeaderValue[] NonOperationsMediaTypes = [MediaTypeHeaderValue.Parse(HeaderConstants.MediaType)]; @@ -36,40 +36,48 @@ public sealed class JsonApiMiddleware ]; private readonly RequestDelegate? _next; + private readonly IControllerResourceMapping _controllerResourceMapping; + private readonly IJsonApiOptions _options; + private readonly ILogger _logger; - public JsonApiMiddleware(RequestDelegate? next, IHttpContextAccessor httpContextAccessor) + public JsonApiMiddleware(RequestDelegate? next, IHttpContextAccessor httpContextAccessor, IControllerResourceMapping controllerResourceMapping, + IJsonApiOptions options, ILogger logger) { ArgumentGuard.NotNull(httpContextAccessor); + ArgumentGuard.NotNull(controllerResourceMapping); + ArgumentGuard.NotNull(options); + ArgumentGuard.NotNull(logger); _next = next; + _controllerResourceMapping = controllerResourceMapping; + _options = options; + _logger = logger; +#pragma warning disable CA2000 // Dispose objects before losing scope var session = new AspNetCodeTimerSession(httpContextAccessor); +#pragma warning restore CA2000 // Dispose objects before losing scope CodeTimingSessionManager.Capture(session); } - public async Task InvokeAsync(HttpContext httpContext, IControllerResourceMapping controllerResourceMapping, IJsonApiOptions options, - IJsonApiRequest request, ILogger logger) + public async Task InvokeAsync(HttpContext httpContext, IJsonApiRequest request) { ArgumentGuard.NotNull(httpContext); - ArgumentGuard.NotNull(controllerResourceMapping); - ArgumentGuard.NotNull(options); ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(logger); using (CodeTimingSessionManager.Current.Measure("JSON:API middleware")) { - if (!await ValidateIfMatchHeaderAsync(httpContext, options.SerializerWriteOptions)) + if (!await ValidateIfMatchHeaderAsync(httpContext, _options.SerializerWriteOptions)) { return; } RouteValueDictionary routeValues = httpContext.GetRouteData().Values; - ResourceType? primaryResourceType = CreatePrimaryResourceType(httpContext, controllerResourceMapping); + ResourceType? primaryResourceType = CreatePrimaryResourceType(httpContext, _controllerResourceMapping); if (primaryResourceType != null) { - if (!await ValidateContentTypeHeaderAsync(NonOperationsContentTypes, httpContext, options.SerializerWriteOptions) || - !await ValidateAcceptHeaderAsync(NonOperationsMediaTypes, httpContext, options.SerializerWriteOptions)) + if (!await ValidateContentTypeHeaderAsync(NonOperationsContentTypes, httpContext, _options.SerializerWriteOptions) || + !await ValidateAcceptHeaderAsync(NonOperationsMediaTypes, httpContext, _options.SerializerWriteOptions)) { return; } @@ -80,8 +88,8 @@ public async Task InvokeAsync(HttpContext httpContext, IControllerResourceMappin } else if (IsRouteForOperations(routeValues)) { - if (!await ValidateContentTypeHeaderAsync(OperationsContentTypes, httpContext, options.SerializerWriteOptions) || - !await ValidateAcceptHeaderAsync(OperationsMediaTypes, httpContext, options.SerializerWriteOptions)) + if (!await ValidateContentTypeHeaderAsync(OperationsContentTypes, httpContext, _options.SerializerWriteOptions) || + !await ValidateAcceptHeaderAsync(OperationsMediaTypes, httpContext, _options.SerializerWriteOptions)) { return; } @@ -100,12 +108,12 @@ public async Task InvokeAsync(HttpContext httpContext, IControllerResourceMappin } } - if (CodeTimingSessionManager.IsEnabled) + if (CodeTimingSessionManager.IsEnabled && _logger.IsEnabled(LogLevel.Information)) { string timingResults = CodeTimingSessionManager.Current.GetResults(); - string url = httpContext.Request.GetDisplayUrl(); - string method = httpContext.Request.Method.Replace(Environment.NewLine, ""); - logger.LogInformation($"Measurement results for {method} {url}:{Environment.NewLine}{timingResults}"); + string requestMethod = httpContext.Request.Method.Replace(Environment.NewLine, ""); + string requestUrl = httpContext.Request.GetEncodedUrl(); + LogMeasurement(requestMethod, requestUrl, Environment.NewLine, timingResults); } } @@ -138,7 +146,7 @@ private async Task ValidateIfMatchHeaderAsync(HttpContext httpContext, Jso : null; } - private static async Task ValidateContentTypeHeaderAsync(ICollection allowedContentTypes, HttpContext httpContext, + private static async Task ValidateContentTypeHeaderAsync(string[] allowedContentTypes, HttpContext httpContext, JsonSerializerOptions serializerOptions) { string? contentType = httpContext.Request.ContentType; @@ -163,12 +171,12 @@ private static async Task ValidateContentTypeHeaderAsync(ICollection ValidateAcceptHeaderAsync(ICollection allowedMediaTypes, HttpContext httpContext, + private static async Task ValidateAcceptHeaderAsync(MediaTypeHeaderValue[] allowedMediaTypes, HttpContext httpContext, JsonSerializerOptions serializerOptions) { string[] acceptHeaders = httpContext.Request.Headers.GetCommaSeparatedValues("Accept"); - if (!acceptHeaders.Any()) + if (acceptHeaders.Length == 0) { return true; } @@ -308,4 +316,8 @@ private static void SetupOperationsRequest(JsonApiRequest request) request.IsReadOnly = false; request.Kind = EndpointKind.AtomicOperations; } + + [LoggerMessage(Level = LogLevel.Information, SkipEnabledCheck = true, + Message = "Measurement results for {RequestMethod} {RequestUrl}:{LineBreak}{TimingResults}")] + private partial void LogMeasurement(string requestMethod, string requestUrl, string lineBreak, string timingResults); } diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs b/src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs index c2df736e96..d0b4ec13b4 100644 --- a/src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs +++ b/src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs @@ -27,7 +27,7 @@ namespace JsonApiDotNetCore.Middleware; /// public class SomeVeryCustomController : CoreJsonApiController { } // => /someVeryCustoms/relationship/relatedResource /// ]]> [PublicAPI] -public sealed class JsonApiRoutingConvention : IJsonApiRoutingConvention +public sealed partial class JsonApiRoutingConvention : IJsonApiRoutingConvention { private readonly IJsonApiOptions _options; private readonly IResourceGraph _resourceGraph; @@ -83,8 +83,7 @@ public void Apply(ApplicationModel application) // ProblemDetails, where the origin of the error gets lost. As a result, we can't populate the source pointer in JSON:API error responses. // For backwards-compatibility, we log a warning instead of throwing. But we can't think of any use cases where having [ApiController] makes sense. - _logger.LogWarning( - $"Found JSON:API controller '{controller.ControllerType}' with [ApiController]. Please remove this attribute for optimal JSON:API compliance."); + LogApiControllerAttributeFound(controller.ControllerType); } if (!IsOperationsController(controller.ControllerType)) @@ -214,4 +213,8 @@ private static bool IsOperationsController(Type type) Type baseControllerType = typeof(BaseJsonApiOperationsController); return baseControllerType.IsAssignableFrom(type); } + + [LoggerMessage(Level = LogLevel.Warning, + Message = "Found JSON:API controller '{ControllerType}' with [ApiController]. Please remove this attribute for optimal JSON:API compliance.")] + private partial void LogApiControllerAttributeFound(TypeInfo controllerType); } diff --git a/src/JsonApiDotNetCore/Middleware/TraceLogWriter.cs b/src/JsonApiDotNetCore/Middleware/TraceLogWriter.cs index e17f02ed21..b78670286e 100644 --- a/src/JsonApiDotNetCore/Middleware/TraceLogWriter.cs +++ b/src/JsonApiDotNetCore/Middleware/TraceLogWriter.cs @@ -118,43 +118,29 @@ public override void Write(Utf8JsonWriter writer, TWrapper value, JsonSerializer } } -internal sealed class TraceLogWriter(ILoggerFactory loggerFactory) : TraceLogWriter +internal sealed partial class TraceLogWriter(ILoggerFactory loggerFactory) : TraceLogWriter { private readonly ILogger _logger = loggerFactory.CreateLogger(typeof(T)); - private bool IsEnabled => _logger.IsEnabled(LogLevel.Trace); - public void LogMethodStart(object? parameters = null, [CallerMemberName] string memberName = "") { - if (IsEnabled) + if (_logger.IsEnabled(LogLevel.Trace)) { - string message = FormatMessage(memberName, parameters); - WriteMessageToLog(message); - } - } + var builder = new StringBuilder(); + WriteProperties(builder, parameters); + string parameterValues = builder.ToString(); - public void LogMessage(Func messageFactory) - { - if (IsEnabled) - { - string message = messageFactory(); - WriteMessageToLog(message); + if (parameterValues.Length == 0) + { + LogEnteringMember(memberName); + } + else + { + LogEnteringMemberWithParameters(memberName, parameterValues); + } } } - private static string FormatMessage(string memberName, object? parameters) - { - var builder = new StringBuilder(); - - builder.Append("Entering "); - builder.Append(memberName); - builder.Append('('); - WriteProperties(builder, parameters); - builder.Append(')'); - - return builder.ToString(); - } - private static void WriteProperties(StringBuilder builder, object? propertyContainer) { if (propertyContainer != null) @@ -218,8 +204,9 @@ private static string SerializeObject(object? value) } } - private void WriteMessageToLog(string message) - { - _logger.LogTrace(message); - } + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "Entering {MemberName}({ParameterValues})")] + private partial void LogEnteringMemberWithParameters(string memberName, string parameterValues); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "Entering {MemberName}()")] + private partial void LogEnteringMember(string memberName); } diff --git a/src/JsonApiDotNetCore/Queries/EvaluatedIncludeCache.cs b/src/JsonApiDotNetCore/Queries/EvaluatedIncludeCache.cs index 7c9d983d63..ea54da96af 100644 --- a/src/JsonApiDotNetCore/Queries/EvaluatedIncludeCache.cs +++ b/src/JsonApiDotNetCore/Queries/EvaluatedIncludeCache.cs @@ -5,7 +5,7 @@ namespace JsonApiDotNetCore.Queries; /// internal sealed class EvaluatedIncludeCache : IEvaluatedIncludeCache { - private readonly IEnumerable _constraintProviders; + private readonly IQueryConstraintProvider[] _constraintProviders; private IncludeExpression? _include; private bool _isAssigned; @@ -13,7 +13,7 @@ public EvaluatedIncludeCache(IEnumerable constraintPro { ArgumentGuard.NotNull(constraintProviders); - _constraintProviders = constraintProviders; + _constraintProviders = constraintProviders as IQueryConstraintProvider[] ?? constraintProviders.ToArray(); } /// diff --git a/src/JsonApiDotNetCore/Queries/Expressions/IncludeChainConverter.cs b/src/JsonApiDotNetCore/Queries/Expressions/IncludeChainConverter.cs index f88cb60a86..5915886e72 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/IncludeChainConverter.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/IncludeChainConverter.cs @@ -31,7 +31,7 @@ public IReadOnlyCollection GetRelationshipChains(I { ArgumentGuard.NotNull(include); - if (!include.Elements.Any()) + if (include.Elements.Count == 0) { return Array.Empty(); } @@ -39,7 +39,7 @@ public IReadOnlyCollection GetRelationshipChains(I var converter = new IncludeToChainsConverter(); converter.Visit(include, null); - return converter.Chains; + return converter.Chains.AsReadOnly(); } private sealed class IncludeToChainsConverter : QueryExpressionVisitor @@ -60,7 +60,7 @@ private sealed class IncludeToChainsConverter : QueryExpressionVisitor 0) { builder.Append('{'); builder.Append(string.Join(",", Children.Select(child => toFullString ? child.ToFullString() : child.ToString()).OrderBy(name => name))); diff --git a/src/JsonApiDotNetCore/Queries/Expressions/PaginationElementQueryStringValueExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/PaginationElementQueryStringValueExpression.cs index 7e39ca5735..b6e182a714 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/PaginationElementQueryStringValueExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/PaginationElementQueryStringValueExpression.cs @@ -29,7 +29,7 @@ public class PaginationElementQueryStringValueExpression(ResourceFieldChainExpre public override TResult Accept(QueryExpressionVisitor visitor, TArgument argument) { - return visitor.PaginationElementQueryStringValue(this, argument); + return visitor.VisitPaginationElementQueryStringValue(this, argument); } public override string ToString() diff --git a/src/JsonApiDotNetCore/Queries/Expressions/PaginationQueryStringValueExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/PaginationQueryStringValueExpression.cs index f16ca0cbd6..2a70ea7d8c 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/PaginationQueryStringValueExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/PaginationQueryStringValueExpression.cs @@ -27,7 +27,7 @@ public PaginationQueryStringValueExpression(IImmutableList(QueryExpressionVisitor visitor, TArgument argument) { - return visitor.PaginationQueryStringValue(this, argument); + return visitor.VisitPaginationQueryStringValue(this, argument); } public override string ToString() diff --git a/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionRewriter.cs b/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionRewriter.cs index 4439e37c21..173c77503c 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionRewriter.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionRewriter.cs @@ -2,6 +2,8 @@ using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; +#pragma warning disable IDE0019 // Use pattern matching + namespace JsonApiDotNetCore.Queries.Expressions; /// @@ -214,7 +216,7 @@ public override QueryExpression VisitSparseFieldSet(SparseFieldSetExpression exp return null; } - public override QueryExpression PaginationQueryStringValue(PaginationQueryStringValueExpression expression, TArgument argument) + public override QueryExpression VisitPaginationQueryStringValue(PaginationQueryStringValueExpression expression, TArgument argument) { IImmutableList newElements = VisitList(expression.Elements, argument); @@ -222,7 +224,7 @@ public override QueryExpression PaginationQueryStringValue(PaginationQueryString return newExpression.Equals(expression) ? expression : newExpression; } - public override QueryExpression PaginationElementQueryStringValue(PaginationElementQueryStringValueExpression expression, TArgument argument) + public override QueryExpression VisitPaginationElementQueryStringValue(PaginationElementQueryStringValueExpression expression, TArgument argument) { ResourceFieldChainExpression? newScope = expression.Scope != null ? Visit(expression.Scope, argument) as ResourceFieldChainExpression : null; diff --git a/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionVisitor.cs b/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionVisitor.cs index 12242c29ff..a0472306f7 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionVisitor.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionVisitor.cs @@ -109,12 +109,12 @@ public virtual TResult VisitQueryStringParameterScope(QueryStringParameterScopeE return DefaultVisit(expression, argument); } - public virtual TResult PaginationQueryStringValue(PaginationQueryStringValueExpression expression, TArgument argument) + public virtual TResult VisitPaginationQueryStringValue(PaginationQueryStringValueExpression expression, TArgument argument) { return DefaultVisit(expression, argument); } - public virtual TResult PaginationElementQueryStringValue(PaginationElementQueryStringValueExpression expression, TArgument argument) + public virtual TResult VisitPaginationElementQueryStringValue(PaginationElementQueryStringValueExpression expression, TArgument argument) { return DefaultVisit(expression, argument); } diff --git a/src/JsonApiDotNetCore/Queries/FieldSelection.cs b/src/JsonApiDotNetCore/Queries/FieldSelection.cs index 7f62db1fcf..53cf38268e 100644 --- a/src/JsonApiDotNetCore/Queries/FieldSelection.cs +++ b/src/JsonApiDotNetCore/Queries/FieldSelection.cs @@ -16,7 +16,7 @@ public sealed class FieldSelection : Dictionary public IReadOnlySet GetResourceTypes() { - return Keys.ToHashSet(); + return Keys.ToHashSet().AsReadOnly(); } #pragma warning disable AV1130 // Return type in method signature should be an interface to an unchangeable collection diff --git a/src/JsonApiDotNetCore/Queries/Parsing/FilterParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/FilterParser.cs index 077d727368..fd300c0431 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/FilterParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/FilterParser.cs @@ -179,6 +179,8 @@ protected virtual NotExpression ParseNot() protected virtual LogicalExpression ParseLogical(string operatorName) { + ArgumentGuard.NotNullNorEmpty(operatorName); + EatText(operatorName); EatSingleCharacterToken(TokenKind.OpenParen); @@ -208,6 +210,8 @@ protected virtual LogicalExpression ParseLogical(string operatorName) protected virtual ComparisonExpression ParseComparison(string operatorName) { + ArgumentGuard.NotNullNorEmpty(operatorName); + var comparisonOperator = Enum.Parse(operatorName.Pascalize()); EatText(operatorName); @@ -311,6 +315,8 @@ private QueryExpression ParseTypedComparisonRightTerm(Type leftType, ConstantVal protected virtual MatchTextExpression ParseTextMatch(string operatorName) { + ArgumentGuard.NotNullNorEmpty(operatorName); + EatText(operatorName); EatSingleCharacterToken(TokenKind.OpenParen); @@ -516,6 +522,8 @@ private NullConstantExpression ParseNull() protected virtual ConstantValueConverter GetConstantValueConverterForType(Type destinationType) { + ArgumentGuard.NotNull(destinationType); + return (stringValue, position) => { try @@ -558,6 +566,8 @@ private object DeObfuscateStringId(ResourceType resourceType, string stringId) protected override void ValidateField(ResourceFieldAttribute field, int position) { + ArgumentGuard.NotNull(field); + if (field.IsFilterBlocked()) { string kind = field is AttrAttribute ? "attribute" : "relationship"; diff --git a/src/JsonApiDotNetCore/Queries/Parsing/IncludeParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/IncludeParser.cs index 1ab0e61326..99674b239d 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/IncludeParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/IncludeParser.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using System.Collections.ObjectModel; using System.Text; using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; @@ -38,10 +39,13 @@ public IncludeExpression Parse(string source, ResourceType resourceType) protected virtual IncludeExpression ParseInclude(string source, ResourceType resourceType) { + ArgumentGuard.NotNull(source); + ArgumentGuard.NotNull(resourceType); + var treeRoot = IncludeTreeNode.CreateRoot(resourceType); bool isAtStart = true; - while (TokenStack.Any()) + while (TokenStack.Count > 0) { if (!isAtStart) { @@ -86,7 +90,7 @@ private void ParseRelationshipChain(string source, IncludeTreeNode treeRoot) // that there's currently no way to include Products without Articles. We could add such optional upcast syntax // in the future, if desired. - ICollection children = ParseRelationshipName(source, [treeRoot]); + ReadOnlyCollection children = ParseRelationshipName(source, [treeRoot]); while (TokenStack.TryPeek(out Token? nextToken) && nextToken.Kind == TokenKind.Period) { @@ -96,7 +100,7 @@ private void ParseRelationshipChain(string source, IncludeTreeNode treeRoot) } } - private ICollection ParseRelationshipName(string source, ICollection parents) + private ReadOnlyCollection ParseRelationshipName(string source, IReadOnlyCollection parents) { int position = GetNextTokenPositionOrEnd(); @@ -108,8 +112,8 @@ private ICollection ParseRelationshipName(string source, IColle throw new QueryParseException("Relationship name expected.", position); } - private static ICollection LookupRelationshipName(string relationshipName, ICollection parents, string source, - int position) + private static ReadOnlyCollection LookupRelationshipName(string relationshipName, IReadOnlyCollection parents, + string source, int position) { List children = []; HashSet relationshipsFound = []; @@ -120,12 +124,12 @@ private static ICollection LookupRelationshipName(string relati // This is compensated for when rendering the response, which substitutes relationships on base types with the derived ones. IReadOnlySet relationships = parent.Relationship.RightType.GetRelationshipsInTypeOrDerived(relationshipName); - if (relationships.Any()) + if (relationships.Count > 0) { relationshipsFound.UnionWith(relationships); RelationshipAttribute[] relationshipsToInclude = relationships.Where(relationship => !relationship.IsIncludeBlocked()).ToArray(); - ICollection affectedChildren = parent.EnsureChildren(relationshipsToInclude); + ReadOnlyCollection affectedChildren = parent.EnsureChildren(relationshipsToInclude); children.AddRange(affectedChildren); } } @@ -133,13 +137,13 @@ private static ICollection LookupRelationshipName(string relati AssertRelationshipsFound(relationshipsFound, relationshipName, parents, position); AssertAtLeastOneCanBeIncluded(relationshipsFound, relationshipName, source, position); - return children; + return children.AsReadOnly(); } - private static void AssertRelationshipsFound(ISet relationshipsFound, string relationshipName, ICollection parents, - int position) + private static void AssertRelationshipsFound(HashSet relationshipsFound, string relationshipName, + IReadOnlyCollection parents, int position) { - if (relationshipsFound.Any()) + if (relationshipsFound.Count > 0) { return; } @@ -152,11 +156,11 @@ private static void AssertRelationshipsFound(ISet relatio throw new QueryParseException(message, position); } - private static string GetErrorMessageForNoneFound(string relationshipName, ICollection parentResourceTypes, bool hasDerivedTypes) + private static string GetErrorMessageForNoneFound(string relationshipName, ResourceType[] parentResourceTypes, bool hasDerivedTypes) { var builder = new StringBuilder($"Relationship '{relationshipName}'"); - if (parentResourceTypes.Count == 1) + if (parentResourceTypes.Length == 1) { builder.Append($" does not exist on resource type '{parentResourceTypes.First().PublicName}'"); } @@ -171,7 +175,7 @@ private static string GetErrorMessageForNoneFound(string relationshipName, IColl return builder.ToString(); } - private static void AssertAtLeastOneCanBeIncluded(ISet relationshipsFound, string relationshipName, string source, int position) + private static void AssertAtLeastOneCanBeIncluded(HashSet relationshipsFound, string relationshipName, string source, int position) { if (relationshipsFound.All(relationship => relationship.IsIncludeBlocked())) { @@ -220,7 +224,7 @@ private static void ThrowIfMaximumDepthExceeded(IncludeElementExpression include private sealed class IncludeTreeNode { - private readonly IDictionary _children = new Dictionary(); + private readonly Dictionary _children = []; public RelationshipAttribute Relationship { get; } @@ -235,7 +239,7 @@ public static IncludeTreeNode CreateRoot(ResourceType resourceType) return new IncludeTreeNode(relationship); } - public ICollection EnsureChildren(ICollection relationships) + public ReadOnlyCollection EnsureChildren(RelationshipAttribute[] relationships) { foreach (RelationshipAttribute relationship in relationships) { @@ -246,7 +250,7 @@ public ICollection EnsureChildren(ICollection relationships.Contains(pair.Key)).Select(pair => pair.Value).ToList(); + return _children.Where(pair => relationships.Contains(pair.Key)).Select(pair => pair.Value).ToArray().AsReadOnly(); } public IncludeExpression ToExpression() @@ -255,7 +259,7 @@ public IncludeExpression ToExpression() if (element.Relationship is HiddenRootRelationshipAttribute) { - return element.Children.Any() ? new IncludeExpression(element.Children) : IncludeExpression.Empty; + return element.Children.Count > 0 ? new IncludeExpression(element.Children) : IncludeExpression.Empty; } return new IncludeExpression(ImmutableHashSet.Create(element)); diff --git a/src/JsonApiDotNetCore/Queries/Parsing/PaginationParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/PaginationParser.cs index 059eb82a55..fff06ed3ec 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/PaginationParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/PaginationParser.cs @@ -26,13 +26,15 @@ public PaginationQueryStringValueExpression Parse(string source, ResourceType re protected virtual PaginationQueryStringValueExpression ParsePagination(ResourceType resourceType) { + ArgumentGuard.NotNull(resourceType); + ImmutableArray.Builder elementsBuilder = ImmutableArray.CreateBuilder(); PaginationElementQueryStringValueExpression element = ParsePaginationElement(resourceType); elementsBuilder.Add(element); - while (TokenStack.Any()) + while (TokenStack.Count > 0) { EatSingleCharacterToken(TokenKind.Comma); @@ -45,6 +47,8 @@ protected virtual PaginationQueryStringValueExpression ParsePagination(ResourceT protected virtual PaginationElementQueryStringValueExpression ParsePaginationElement(ResourceType resourceType) { + ArgumentGuard.NotNull(resourceType); + int position = GetNextTokenPositionOrEnd(); int? number = TryParseNumber(); diff --git a/src/JsonApiDotNetCore/Queries/Parsing/QueryExpressionParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/QueryExpressionParser.cs index 5f1d3c1e89..fc93c3fb81 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/QueryExpressionParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/QueryExpressionParser.cs @@ -43,6 +43,8 @@ protected virtual void ValidateField(ResourceFieldAttribute field, int position) /// protected virtual void Tokenize(string source) { + ArgumentGuard.NotNull(source); + var tokenizer = new QueryTokenizer(source); TokenStack = new Stack(tokenizer.EnumerateTokens().Reverse()); _endOfSourcePosition = source.Length; @@ -118,6 +120,8 @@ private string EatFieldChain(string? alternativeErrorMessage) /// protected void EatText(string text) { + ArgumentGuard.NotNull(text); + if (!TokenStack.TryPop(out Token? token) || token.Kind != TokenKind.Text || token.Value != text) { int position = token?.Position ?? GetNextTokenPositionOrEnd(); @@ -176,7 +180,7 @@ protected int GetRelativePositionOfLastFieldInChain(ResourceFieldChainExpression /// protected void AssertTokenStackIsEmpty() { - if (TokenStack.Any()) + if (TokenStack.Count > 0) { int position = GetNextTokenPositionOrEnd(); throw new QueryParseException("End of expression expected.", position); diff --git a/src/JsonApiDotNetCore/Queries/Parsing/QueryStringParameterScopeParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/QueryStringParameterScopeParser.cs index 2272b94caa..8b7b80f70c 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/QueryStringParameterScopeParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/QueryStringParameterScopeParser.cs @@ -27,6 +27,9 @@ public QueryStringParameterScopeExpression Parse(string source, ResourceType res protected virtual QueryStringParameterScopeExpression ParseQueryStringParameterScope(ResourceType resourceType, FieldChainPattern pattern, FieldChainPatternMatchOptions options) { + ArgumentGuard.NotNull(resourceType); + ArgumentGuard.NotNull(pattern); + int position = GetNextTokenPositionOrEnd(); if (!TokenStack.TryPop(out Token? token) || token.Kind != TokenKind.Text) diff --git a/src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs b/src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs index 9360d95be3..c73a8042d1 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs @@ -1,4 +1,3 @@ -using System.Collections.ObjectModel; using System.Text; using JetBrains.Annotations; @@ -7,18 +6,17 @@ namespace JsonApiDotNetCore.Queries.Parsing; [PublicAPI] public sealed class QueryTokenizer { - public static readonly IReadOnlyDictionary SingleCharacterToTokenKinds = new ReadOnlyDictionary( - new Dictionary - { - ['('] = TokenKind.OpenParen, - [')'] = TokenKind.CloseParen, - ['['] = TokenKind.OpenBracket, - [']'] = TokenKind.CloseBracket, - ['.'] = TokenKind.Period, - [','] = TokenKind.Comma, - [':'] = TokenKind.Colon, - ['-'] = TokenKind.Minus - }); + public static readonly Dictionary SingleCharacterToTokenKinds = new() + { + ['('] = TokenKind.OpenParen, + [')'] = TokenKind.CloseParen, + ['['] = TokenKind.OpenBracket, + [']'] = TokenKind.CloseBracket, + ['.'] = TokenKind.Period, + [','] = TokenKind.Comma, + [':'] = TokenKind.Colon, + ['-'] = TokenKind.Minus + }; private readonly string _source; private readonly StringBuilder _textBuffer = new(); diff --git a/src/JsonApiDotNetCore/Queries/Parsing/SortParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/SortParser.cs index aaf636deca..db622873d2 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/SortParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/SortParser.cs @@ -27,12 +27,14 @@ public SortExpression Parse(string source, ResourceType resourceType) protected virtual SortExpression ParseSort(ResourceType resourceType) { + ArgumentGuard.NotNull(resourceType); + SortElementExpression firstElement = ParseSortElement(resourceType); ImmutableArray.Builder elementsBuilder = ImmutableArray.CreateBuilder(); elementsBuilder.Add(firstElement); - while (TokenStack.Any()) + while (TokenStack.Count > 0) { EatSingleCharacterToken(TokenKind.Comma); @@ -45,6 +47,8 @@ protected virtual SortExpression ParseSort(ResourceType resourceType) protected virtual SortElementExpression ParseSortElement(ResourceType resourceType) { + ArgumentGuard.NotNull(resourceType); + bool isAscending = true; if (TokenStack.TryPeek(out Token? nextToken) && nextToken.Kind == TokenKind.Minus) @@ -134,6 +138,8 @@ private CountExpression ParseCount(ResourceType resourceType) protected override void ValidateField(ResourceFieldAttribute field, int position) { + ArgumentGuard.NotNull(field); + if (field is AttrAttribute attribute && !attribute.Capabilities.HasFlag(AttrCapabilities.AllowSort)) { throw new QueryParseException($"Sorting on attribute '{attribute.PublicName}' is not allowed.", position); diff --git a/src/JsonApiDotNetCore/Queries/Parsing/SparseFieldSetParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/SparseFieldSetParser.cs index 7bbea5c082..d4ac0ff921 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/SparseFieldSetParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/SparseFieldSetParser.cs @@ -27,9 +27,11 @@ public class SparseFieldSetParser : QueryExpressionParser, ISparseFieldSetParser protected virtual SparseFieldSetExpression? ParseSparseFieldSet(ResourceType resourceType) { + ArgumentGuard.NotNull(resourceType); + ImmutableHashSet.Builder fieldSetBuilder = ImmutableHashSet.CreateBuilder(); - while (TokenStack.Any()) + while (TokenStack.Count > 0) { if (fieldSetBuilder.Count > 0) { @@ -43,11 +45,13 @@ public class SparseFieldSetParser : QueryExpressionParser, ISparseFieldSetParser fieldSetBuilder.Add(nextField); } - return fieldSetBuilder.Any() ? new SparseFieldSetExpression(fieldSetBuilder.ToImmutable()) : null; + return fieldSetBuilder.Count > 0 ? new SparseFieldSetExpression(fieldSetBuilder.ToImmutable()) : null; } protected override void ValidateField(ResourceFieldAttribute field, int position) { + ArgumentGuard.NotNull(field); + if (field.IsViewBlocked()) { string kind = field is AttrAttribute ? "attribute" : "relationship"; diff --git a/src/JsonApiDotNetCore/Queries/QueryLayer.cs b/src/JsonApiDotNetCore/Queries/QueryLayer.cs index 3a755d519b..e30de0ef03 100644 --- a/src/JsonApiDotNetCore/Queries/QueryLayer.cs +++ b/src/JsonApiDotNetCore/Queries/QueryLayer.cs @@ -42,7 +42,7 @@ internal void WriteLayer(IndentingStringWriter writer, string? prefix) using (writer.Indent()) { - if (Include != null && Include.Elements.Any()) + if (Include is { Elements.Count: > 0 }) { writer.WriteLine($"{nameof(Include)}: {Include}"); } diff --git a/src/JsonApiDotNetCore/Queries/QueryLayerComposer.cs b/src/JsonApiDotNetCore/Queries/QueryLayerComposer.cs index 1c4ca77119..d030a95462 100644 --- a/src/JsonApiDotNetCore/Queries/QueryLayerComposer.cs +++ b/src/JsonApiDotNetCore/Queries/QueryLayerComposer.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; @@ -14,7 +15,7 @@ namespace JsonApiDotNetCore.Queries; public class QueryLayerComposer : IQueryLayerComposer { private readonly CollectionConverter _collectionConverter = new(); - private readonly IEnumerable _constraintProviders; + private readonly IQueryConstraintProvider[] _constraintProviders; private readonly IResourceDefinitionAccessor _resourceDefinitionAccessor; private readonly IJsonApiOptions _options; private readonly IPaginationContext _paginationContext; @@ -34,7 +35,7 @@ public QueryLayerComposer(IEnumerable constraintProvid ArgumentGuard.NotNull(evaluatedIncludeCache); ArgumentGuard.NotNull(sparseFieldSetCache); - _constraintProviders = constraintProviders; + _constraintProviders = constraintProviders as IQueryConstraintProvider[] ?? constraintProviders.ToArray(); _resourceDefinitionAccessor = resourceDefinitionAccessor; _options = options; _paginationContext = paginationContext; @@ -46,16 +47,16 @@ public QueryLayerComposer(IEnumerable constraintProvid /// public FilterExpression? GetPrimaryFilterFromConstraints(ResourceType primaryResourceType) { - ExpressionInScope[] constraints = _constraintProviders.SelectMany(provider => provider.GetConstraints()).ToArray(); - // @formatter:wrap_chained_method_calls chop_always // @formatter:wrap_before_first_method_call true - FilterExpression[] filtersInTopScope = constraints + ReadOnlyCollection filtersInTopScope = _constraintProviders + .SelectMany(provider => provider.GetConstraints()) .Where(constraint => constraint.Scope == null) .Select(constraint => constraint.Expression) .OfType() - .ToArray(); + .ToArray() + .AsReadOnly(); // @formatter:wrap_before_first_method_call restore // @formatter:wrap_chained_method_calls restore @@ -81,16 +82,16 @@ public QueryLayerComposer(IEnumerable constraintProvid return null; } - ExpressionInScope[] constraints = _constraintProviders.SelectMany(provider => provider.GetConstraints()).ToArray(); - // @formatter:wrap_chained_method_calls chop_always // @formatter:wrap_before_first_method_call true - FilterExpression[] filtersInSecondaryScope = constraints + ReadOnlyCollection filtersInSecondaryScope = _constraintProviders + .SelectMany(provider => provider.GetConstraints()) .Where(constraint => constraint.Scope == null) .Select(constraint => constraint.Expression) .OfType() - .ToArray(); + .ToArray() + .AsReadOnly(); // @formatter:wrap_before_first_method_call restore // @formatter:wrap_chained_method_calls restore @@ -111,7 +112,7 @@ private static FilterExpression GetInverseRelationshipFilter([DisallowNull] : GetInverseHasOneRelationshipFilter(primaryId, relationship, (HasOneAttribute)inverseRelationship); } - private static FilterExpression GetInverseHasOneRelationshipFilter([DisallowNull] TId primaryId, HasManyAttribute relationship, + private static ComparisonExpression GetInverseHasOneRelationshipFilter([DisallowNull] TId primaryId, HasManyAttribute relationship, HasOneAttribute inverseRelationship) { AttrAttribute idAttribute = GetIdAttribute(relationship.LeftType); @@ -120,7 +121,7 @@ private static FilterExpression GetInverseHasOneRelationshipFilter([Disallo return new ComparisonExpression(ComparisonOperator.Equals, idChain, new LiteralConstantExpression(primaryId)); } - private static FilterExpression GetInverseHasManyRelationshipFilter([DisallowNull] TId primaryId, HasManyAttribute relationship, + private static HasExpression GetInverseHasManyRelationshipFilter([DisallowNull] TId primaryId, HasManyAttribute relationship, HasManyAttribute inverseRelationship) { AttrAttribute idAttribute = GetIdAttribute(relationship.LeftType); @@ -135,7 +136,11 @@ public QueryLayer ComposeFromConstraints(ResourceType requestResourceType) { ArgumentGuard.NotNull(requestResourceType); - ExpressionInScope[] constraints = _constraintProviders.SelectMany(provider => provider.GetConstraints()).ToArray(); +#if NET6_0 + ImmutableArray constraints = _constraintProviders.SelectMany(provider => provider.GetConstraints()).ToImmutableArray(); +#else + ImmutableArray constraints = [.. _constraintProviders.SelectMany(provider => provider.GetConstraints())]; +#endif QueryLayer topLayer = ComposeTopLayer(constraints, requestResourceType); topLayer.Include = ComposeChildren(topLayer, constraints); @@ -145,17 +150,18 @@ public QueryLayer ComposeFromConstraints(ResourceType requestResourceType) return topLayer; } - private QueryLayer ComposeTopLayer(IEnumerable constraints, ResourceType resourceType) + private QueryLayer ComposeTopLayer(ImmutableArray constraints, ResourceType resourceType) { using IDisposable _ = CodeTimingSessionManager.Current.Measure("Top-level query composition"); // @formatter:wrap_chained_method_calls chop_always // @formatter:wrap_before_first_method_call true - QueryExpression[] expressionsInTopScope = constraints + ReadOnlyCollection expressionsInTopScope = constraints .Where(constraint => constraint.Scope == null) .Select(constraint => constraint.Expression) - .ToArray(); + .ToArray() + .AsReadOnly(); // @formatter:wrap_before_first_method_call restore // @formatter:wrap_chained_method_calls restore @@ -173,7 +179,7 @@ private QueryLayer ComposeTopLayer(IEnumerable constraints, R }; } - private IncludeExpression ComposeChildren(QueryLayer topLayer, ICollection constraints) + private IncludeExpression ComposeChildren(QueryLayer topLayer, ImmutableArray constraints) { using IDisposable _ = CodeTimingSessionManager.Current.Measure("Nested query composition"); @@ -189,15 +195,16 @@ private IncludeExpression ComposeChildren(QueryLayer topLayer, ICollection includeElements = ProcessIncludeSet(include.Elements, topLayer, new List(), constraints); + IImmutableSet includeElements = + ProcessIncludeSet(include.Elements, topLayer, ImmutableArray.Empty, constraints); return !ReferenceEquals(includeElements, include.Elements) - ? includeElements.Any() ? new IncludeExpression(includeElements) : IncludeExpression.Empty + ? includeElements.Count > 0 ? new IncludeExpression(includeElements) : IncludeExpression.Empty : include; } private IImmutableSet ProcessIncludeSet(IImmutableSet includeElements, QueryLayer parentLayer, - ICollection parentRelationshipChain, ICollection constraints) + ImmutableArray parentRelationshipChain, ImmutableArray constraints) { IImmutableSet includeElementsEvaluated = GetIncludeElements(includeElements, parentLayer.ResourceType); @@ -210,18 +217,16 @@ private IImmutableSet ProcessIncludeSet(IImmutableSet< if (!selectors.ContainsField(includeElement.Relationship)) { - var relationshipChain = new List(parentRelationshipChain) - { - includeElement.Relationship - }; + ImmutableArray relationshipChain = parentRelationshipChain.Add(includeElement.Relationship); // @formatter:wrap_chained_method_calls chop_always // @formatter:wrap_before_first_method_call true - QueryExpression[] expressionsInCurrentScope = constraints + ReadOnlyCollection expressionsInCurrentScope = constraints .Where(constraint => constraint.Scope != null && constraint.Scope.Fields.SequenceEqual(relationshipChain)) .Select(constraint => constraint.Expression) - .ToArray(); + .ToArray() + .AsReadOnly(); // @formatter:wrap_before_first_method_call restore // @formatter:wrap_chained_method_calls restore @@ -248,11 +253,11 @@ private IImmutableSet ProcessIncludeSet(IImmutableSet< } } - return !updatesInChildren.Any() ? includeElementsEvaluated : ApplyIncludeElementUpdates(includeElementsEvaluated, updatesInChildren); + return updatesInChildren.Count == 0 ? includeElementsEvaluated : ApplyIncludeElementUpdates(includeElementsEvaluated, updatesInChildren); } - private static IImmutableSet ApplyIncludeElementUpdates(IImmutableSet includeElements, - IDictionary> updatesInChildren) + private static ImmutableHashSet ApplyIncludeElementUpdates(IImmutableSet includeElements, + Dictionary> updatesInChildren) { ImmutableHashSet.Builder newElementsBuilder = ImmutableHashSet.CreateBuilder(); newElementsBuilder.UnionWith(includeElements); @@ -360,18 +365,18 @@ private IncludeExpression RewriteIncludeForSecondaryEndpoint(IncludeExpression? return new IncludeExpression(ImmutableHashSet.Create(parentElement)); } - private FilterExpression? CreateFilterByIds(IReadOnlyCollection ids, AttrAttribute idAttribute, FilterExpression? existingFilter) + private FilterExpression? CreateFilterByIds(TId[] ids, AttrAttribute idAttribute, FilterExpression? existingFilter) { var idChain = new ResourceFieldChainExpression(idAttribute); FilterExpression? filter = null; - if (ids.Count == 1) + if (ids.Length == 1) { var constant = new LiteralConstantExpression(ids.Single()!); filter = new ComparisonExpression(ComparisonOperator.Equals, idChain, constant); } - else if (ids.Count > 1) + else if (ids.Length > 1) { ImmutableHashSet constants = ids.Select(id => new LiteralConstantExpression(id!)).ToImmutableHashSet(); filter = new AnyExpression(idChain, constants); @@ -390,8 +395,8 @@ public QueryLayer ComposeForUpdate([DisallowNull] TId id, ResourceType prim AttrAttribute primaryIdAttribute = GetIdAttribute(primaryResourceType); - QueryLayer primaryLayer = ComposeTopLayer(Array.Empty(), primaryResourceType); - primaryLayer.Include = includeElements.Any() ? new IncludeExpression(includeElements) : IncludeExpression.Empty; + QueryLayer primaryLayer = ComposeTopLayer(ImmutableArray.Empty, primaryResourceType); + primaryLayer.Include = includeElements.Count > 0 ? new IncludeExpression(includeElements) : IncludeExpression.Empty; primaryLayer.Sort = null; primaryLayer.Pagination = null; primaryLayer.Filter = CreateFilterByIds([id], primaryIdAttribute, primaryLayer.Filter); @@ -410,7 +415,7 @@ public QueryLayer ComposeForUpdate([DisallowNull] TId id, ResourceType prim object? rightValue = relationship.GetValue(primaryResource); HashSet rightResourceIds = _collectionConverter.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); - if (rightResourceIds.Any()) + if (rightResourceIds.Count > 0) { QueryLayer queryLayer = ComposeForGetRelationshipRightIds(relationship, rightResourceIds); yield return (queryLayer, relationship); @@ -426,7 +431,7 @@ public QueryLayer ComposeForGetRelationshipRightIds(RelationshipAttribute relati AttrAttribute rightIdAttribute = GetIdAttribute(relationship.RightType); - HashSet typedIds = rightResourceIds.Select(resource => resource.GetTypedId()).ToHashSet(); + object[] typedIds = rightResourceIds.Select(resource => resource.GetTypedId()).ToArray(); FilterExpression? baseFilter = GetFilter(Array.Empty(), relationship.RightType); FilterExpression? filter = CreateFilterByIds(typedIds, rightIdAttribute, baseFilter); @@ -451,7 +456,7 @@ public QueryLayer ComposeForHasMany(HasManyAttribute hasManyRelationship, [ AttrAttribute leftIdAttribute = GetIdAttribute(hasManyRelationship.LeftType); AttrAttribute rightIdAttribute = GetIdAttribute(hasManyRelationship.RightType); - HashSet rightTypedIds = rightResourceIds.Select(resource => resource.GetTypedId()).ToHashSet(); + object[] rightTypedIds = rightResourceIds.Select(resource => resource.GetTypedId()).ToArray(); FilterExpression? leftFilter = CreateFilterByIds([leftId], leftIdAttribute, null); FilterExpression? rightFilter = CreateFilterByIds(rightTypedIds, rightIdAttribute, null); @@ -482,6 +487,7 @@ public QueryLayer ComposeForHasMany(HasManyAttribute hasManyRelationship, [ protected virtual IImmutableSet GetIncludeElements(IImmutableSet includeElements, ResourceType resourceType) { + ArgumentGuard.NotNull(includeElements); ArgumentGuard.NotNull(resourceType); return _resourceDefinitionAccessor.OnApplyIncludes(resourceType, includeElements); @@ -546,7 +552,7 @@ protected virtual PaginationExpression GetPagination(IReadOnlyCollection fieldSet = _sparseFieldSetCache.GetSparseFieldSetForQuery(nextType); - if (!fieldSet.Any()) + if (fieldSet.Count == 0) { continue; } diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/IncludeClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/IncludeClauseBuilder.cs index 3bd19eb21f..fedc3679b2 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/IncludeClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/IncludeClauseBuilder.cs @@ -34,7 +34,7 @@ public override Expression VisitInclude(IncludeExpression expression, QueryClaus return ToExpression(context.Source, context.LambdaScope.Parameter.Type, propertyPaths); } - private static void ProcessRelationshipChain(ResourceFieldChainExpression chain, ISet outputPropertyPaths) + private static void ProcessRelationshipChain(ResourceFieldChainExpression chain, HashSet outputPropertyPaths) { string? path = null; @@ -71,7 +71,7 @@ private static Expression ToExpression(Expression source, Type entityType, HashS return expression; } - private static Expression IncludeExtensionMethodCall(Expression source, Type entityType, string navigationPropertyPath) + private static MethodCallExpression IncludeExtensionMethodCall(Expression source, Type entityType, string navigationPropertyPath) { Expression navigationExpression = Expression.Constant(navigationPropertyPath); diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/OrderClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/OrderClauseBuilder.cs index 93dd7c53d1..ab37d2aff1 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/OrderClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/OrderClauseBuilder.cs @@ -54,7 +54,7 @@ private static string GetOperationName(bool isAscending, QueryClauseBuilderConte return isAscending ? "OrderBy" : "OrderByDescending"; } - private static Expression ExtensionMethodCall(Expression source, string operationName, Type keyType, LambdaExpression keySelector, + private static MethodCallExpression ExtensionMethodCall(Expression source, string operationName, Type keyType, LambdaExpression keySelector, QueryClauseBuilderContext context) { Type[] typeArguments = diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilder.cs index 4e2743fa02..b34e5b56cd 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilder.cs @@ -19,7 +19,7 @@ public override Expression VisitCount(CountExpression expression, QueryClauseBui { Expression collectionExpression = Visit(expression.TargetCollection, context); - Expression? propertyExpression = GetCollectionCount(collectionExpression); + MemberExpression? propertyExpression = GetCollectionCount(collectionExpression); if (propertyExpression == null) { @@ -29,7 +29,7 @@ public override Expression VisitCount(CountExpression expression, QueryClauseBui return propertyExpression; } - private static Expression? GetCollectionCount(Expression? collectionExpression) + private static MemberExpression? GetCollectionCount(Expression? collectionExpression) { if (collectionExpression != null) { diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryableBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryableBuilder.cs index a1dd644f88..6b52b3d69b 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryableBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryableBuilder.cs @@ -68,6 +68,11 @@ public virtual Expression ApplyQuery(QueryLayer layer, QueryableBuilderContext c protected virtual Expression ApplyInclude(Expression source, IncludeExpression include, ResourceType resourceType, QueryableBuilderContext context) { + ArgumentGuard.NotNull(source); + ArgumentGuard.NotNull(include); + ArgumentGuard.NotNull(resourceType); + ArgumentGuard.NotNull(context); + using LambdaScope lambdaScope = context.LambdaScopeFactory.CreateScope(context.ElementType); QueryClauseBuilderContext clauseContext = context.CreateClauseContext(this, source, resourceType, lambdaScope); @@ -76,6 +81,11 @@ protected virtual Expression ApplyInclude(Expression source, IncludeExpression i protected virtual Expression ApplyFilter(Expression source, FilterExpression filter, ResourceType resourceType, QueryableBuilderContext context) { + ArgumentGuard.NotNull(source); + ArgumentGuard.NotNull(filter); + ArgumentGuard.NotNull(resourceType); + ArgumentGuard.NotNull(context); + using LambdaScope lambdaScope = context.LambdaScopeFactory.CreateScope(context.ElementType); QueryClauseBuilderContext clauseContext = context.CreateClauseContext(this, source, resourceType, lambdaScope); @@ -84,6 +94,11 @@ protected virtual Expression ApplyFilter(Expression source, FilterExpression fil protected virtual Expression ApplySort(Expression source, SortExpression sort, ResourceType resourceType, QueryableBuilderContext context) { + ArgumentGuard.NotNull(source); + ArgumentGuard.NotNull(sort); + ArgumentGuard.NotNull(resourceType); + ArgumentGuard.NotNull(context); + using LambdaScope lambdaScope = context.LambdaScopeFactory.CreateScope(context.ElementType); QueryClauseBuilderContext clauseContext = context.CreateClauseContext(this, source, resourceType, lambdaScope); @@ -92,6 +107,11 @@ protected virtual Expression ApplySort(Expression source, SortExpression sort, R protected virtual Expression ApplyPagination(Expression source, PaginationExpression pagination, ResourceType resourceType, QueryableBuilderContext context) { + ArgumentGuard.NotNull(source); + ArgumentGuard.NotNull(pagination); + ArgumentGuard.NotNull(resourceType); + ArgumentGuard.NotNull(context); + using LambdaScope lambdaScope = context.LambdaScopeFactory.CreateScope(context.ElementType); QueryClauseBuilderContext clauseContext = context.CreateClauseContext(this, source, resourceType, lambdaScope); @@ -100,6 +120,11 @@ protected virtual Expression ApplyPagination(Expression source, PaginationExpres protected virtual Expression ApplySelection(Expression source, FieldSelection selection, ResourceType resourceType, QueryableBuilderContext context) { + ArgumentGuard.NotNull(source); + ArgumentGuard.NotNull(selection); + ArgumentGuard.NotNull(resourceType); + ArgumentGuard.NotNull(context); + using LambdaScope lambdaScope = context.LambdaScopeFactory.CreateScope(context.ElementType); QueryClauseBuilderContext clauseContext = context.CreateClauseContext(this, source, resourceType, lambdaScope); diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/SelectClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/SelectClauseBuilder.cs index c67b785d89..7e099fb091 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/SelectClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/SelectClauseBuilder.cs @@ -71,7 +71,7 @@ private Expression CreateLambdaBodyInitializerForTypeHierarchy(FieldSelection se if (!fieldSelectors.IsEmpty) { - ICollection propertySelectors = + Dictionary.ValueCollection propertySelectors = ToPropertySelectors(fieldSelectors, resourceType, entityType.ClrType, context.EntityModel); MemberBinding[] propertyAssignments = propertySelectors.Select(selector => CreatePropertyAssignment(selector, lambdaScope, context)) @@ -101,11 +101,13 @@ private static BinaryExpression CreateRuntimeTypeCheck(LambdaScope lambdaScope, return Expression.MakeBinary(ExpressionType.Equal, getTypeCall, concreteTypeConstant, false, TypeOpEqualityMethod); } - private Expression CreateLambdaBodyInitializerForSingleType(FieldSelection selection, ResourceType resourceType, LambdaScope lambdaScope, + private MemberInitExpression CreateLambdaBodyInitializerForSingleType(FieldSelection selection, ResourceType resourceType, LambdaScope lambdaScope, QueryClauseBuilderContext context) { FieldSelectors fieldSelectors = selection.GetOrCreateSelectors(resourceType); - ICollection propertySelectors = ToPropertySelectors(fieldSelectors, resourceType, lambdaScope.Accessor.Type, context.EntityModel); + + Dictionary.ValueCollection propertySelectors = + ToPropertySelectors(fieldSelectors, resourceType, lambdaScope.Accessor.Type, context.EntityModel); MemberBinding[] propertyAssignments = propertySelectors.Select(selector => CreatePropertyAssignment(selector, lambdaScope, context)) .Cast().ToArray(); @@ -114,8 +116,8 @@ private Expression CreateLambdaBodyInitializerForSingleType(FieldSelection selec return Expression.MemberInit(createInstance, propertyAssignments); } - private static ICollection ToPropertySelectors(FieldSelectors fieldSelectors, ResourceType resourceType, Type elementType, - IReadOnlyModel entityModel) + private static Dictionary.ValueCollection ToPropertySelectors(FieldSelectors fieldSelectors, ResourceType resourceType, + Type elementType, IReadOnlyModel entityModel) { var propertySelectors = new Dictionary(); @@ -221,8 +223,8 @@ private Expression CreateAssignmentRightHandSideForLayer(QueryLayer layer, Lambd return CreateLambdaBodyInitializer(layer.Selection, layer.ResourceType, scope, true, context); } - private static Expression CreateCollectionInitializer(LambdaScope lambdaScope, PropertyInfo collectionProperty, Type elementType, QueryLayer layer, - QueryClauseBuilderContext context) + private static MethodCallExpression CreateCollectionInitializer(LambdaScope lambdaScope, PropertyInfo collectionProperty, Type elementType, + QueryLayer layer, QueryClauseBuilderContext context) { MemberExpression propertyExpression = Expression.Property(lambdaScope.Accessor, collectionProperty); @@ -235,18 +237,18 @@ private static Expression CreateCollectionInitializer(LambdaScope lambdaScope, P return CopyCollectionExtensionMethodCall(layerExpression, operationName, elementType); } - private static Expression TestForNull(Expression expressionToTest, Expression ifFalseExpression) + private static ConditionalExpression TestForNull(Expression expressionToTest, Expression ifFalseExpression) { BinaryExpression equalsNull = Expression.Equal(expressionToTest, NullConstant); return Expression.Condition(equalsNull, Expression.Convert(NullConstant, expressionToTest.Type), ifFalseExpression); } - private static Expression CopyCollectionExtensionMethodCall(Expression source, string operationName, Type elementType) + private static MethodCallExpression CopyCollectionExtensionMethodCall(Expression source, string operationName, Type elementType) { return Expression.Call(typeof(Enumerable), operationName, [elementType], source); } - private static Expression SelectExtensionMethodCall(Type extensionType, Expression source, Type elementType, Expression selectBody) + private static MethodCallExpression SelectExtensionMethodCall(Type extensionType, Expression source, Type elementType, Expression selectBody) { Type[] typeArguments = [ diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/SkipTakeClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/SkipTakeClauseBuilder.cs index 4c54586cb6..7fa3795549 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/SkipTakeClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/SkipTakeClauseBuilder.cs @@ -34,7 +34,7 @@ public override Expression VisitPagination(PaginationExpression expression, Quer return skipTakeExpression; } - private static Expression ExtensionMethodCall(Expression source, string operationName, int value, QueryClauseBuilderContext context) + private static MethodCallExpression ExtensionMethodCall(Expression source, string operationName, int value, QueryClauseBuilderContext context) { Expression constant = SystemExpressionBuilder.CloseOver(value); diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/WhereClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/WhereClauseBuilder.cs index b5fafdd21b..a51aeefee7 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/WhereClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/WhereClauseBuilder.cs @@ -31,7 +31,7 @@ private LambdaExpression GetPredicateLambda(FilterExpression filter, QueryClause return Expression.Lambda(body, context.LambdaScope.Parameter); } - private static Expression WhereExtensionMethodCall(LambdaExpression predicate, QueryClauseBuilderContext context) + private static MethodCallExpression WhereExtensionMethodCall(LambdaExpression predicate, QueryClauseBuilderContext context) { return Expression.Call(context.ExtensionType, "Where", [context.LambdaScope.Parameter.Type], context.Source, predicate); } @@ -123,7 +123,7 @@ public override Expression VisitAny(AnyExpression expression, QueryClauseBuilder return ContainsExtensionMethodCall(collection, property); } - private static Expression ContainsExtensionMethodCall(Expression collection, Expression value) + private static MethodCallExpression ContainsExtensionMethodCall(Expression collection, Expression value) { return Expression.Call(typeof(Enumerable), "Contains", [value.Type], collection, value); } @@ -147,7 +147,7 @@ private static BinaryExpression Compose(Queue argumentQueue, Func 0) { Expression nextArgument = argumentQueue.Dequeue(); tempExpression = applyOperator(tempExpression, nextArgument); diff --git a/src/JsonApiDotNetCore/Queries/SparseFieldSetCache.cs b/src/JsonApiDotNetCore/Queries/SparseFieldSetCache.cs index d812dc121b..6e11d93a0c 100644 --- a/src/JsonApiDotNetCore/Queries/SparseFieldSetCache.cs +++ b/src/JsonApiDotNetCore/Queries/SparseFieldSetCache.cs @@ -13,8 +13,8 @@ public sealed class SparseFieldSetCache : ISparseFieldSetCache private static readonly ConcurrentDictionary ViewableFieldSetCache = new(); private readonly IResourceDefinitionAccessor _resourceDefinitionAccessor; - private readonly Lazy>> _lazySourceTable; - private readonly IDictionary> _visitedTable; + private readonly Lazy>> _lazySourceTable; + private readonly Dictionary> _visitedTable = []; public SparseFieldSetCache(IEnumerable constraintProviders, IResourceDefinitionAccessor resourceDefinitionAccessor) { @@ -22,11 +22,11 @@ public SparseFieldSetCache(IEnumerable constraintProvi ArgumentGuard.NotNull(resourceDefinitionAccessor); _resourceDefinitionAccessor = resourceDefinitionAccessor; - _lazySourceTable = new Lazy>>(() => BuildSourceTable(constraintProviders)); - _visitedTable = new Dictionary>(); + _lazySourceTable = new Lazy>>(() => BuildSourceTable(constraintProviders)); } - private static IDictionary> BuildSourceTable(IEnumerable constraintProviders) + private static Dictionary> BuildSourceTable( + IEnumerable constraintProviders) { // @formatter:wrap_chained_method_calls chop_always // @formatter:wrap_before_first_method_call true @@ -47,15 +47,16 @@ private static IDictionary> foreach ((ResourceType resourceType, SparseFieldSetExpression sparseFieldSet) in sparseFieldTables) { - if (!mergedTable.ContainsKey(resourceType)) + if (!mergedTable.TryGetValue(resourceType, out ImmutableHashSet.Builder? builder)) { - mergedTable[resourceType] = ImmutableHashSet.CreateBuilder(); + builder = ImmutableHashSet.CreateBuilder(); + mergedTable[resourceType] = builder; } - AddSparseFieldsToSet(sparseFieldSet.Fields, mergedTable[resourceType]); + AddSparseFieldsToSet(sparseFieldSet.Fields, builder); } - return mergedTable.ToDictionary(pair => pair.Key, pair => (IImmutableSet)pair.Value.ToImmutable()); + return mergedTable.ToDictionary(pair => pair.Key, pair => pair.Value.ToImmutable()); } private static void AddSparseFieldsToSet(IImmutableSet sparseFieldsToAdd, @@ -72,22 +73,20 @@ public IImmutableSet GetSparseFieldSetForQuery(ResourceT { ArgumentGuard.NotNull(resourceType); - if (!_visitedTable.ContainsKey(resourceType)) + if (!_visitedTable.TryGetValue(resourceType, out IImmutableSet? outputFields)) { - SparseFieldSetExpression? inputExpression = _lazySourceTable.Value.TryGetValue(resourceType, out IImmutableSet? inputFields) - ? new SparseFieldSetExpression(inputFields) - : null; + SparseFieldSetExpression? inputExpression = + _lazySourceTable.Value.TryGetValue(resourceType, out ImmutableHashSet? inputFields) + ? new SparseFieldSetExpression(inputFields) + : null; SparseFieldSetExpression? outputExpression = _resourceDefinitionAccessor.OnApplySparseFieldSet(resourceType, inputExpression); - - IImmutableSet outputFields = outputExpression == null - ? ImmutableHashSet.Empty - : outputExpression.Fields; + outputFields = outputExpression == null ? ImmutableHashSet.Empty : outputExpression.Fields; _visitedTable[resourceType] = outputFields; } - return _visitedTable[resourceType]; + return outputFields; } /// @@ -114,29 +113,30 @@ public IImmutableSet GetSparseFieldSetForSerializer(Reso { ArgumentGuard.NotNull(resourceType); - if (!_visitedTable.ContainsKey(resourceType)) + if (!_visitedTable.TryGetValue(resourceType, out IImmutableSet? outputFields)) { - SparseFieldSetExpression inputExpression = _lazySourceTable.Value.TryGetValue(resourceType, out IImmutableSet? inputFields) - ? new SparseFieldSetExpression(inputFields) - : GetCachedViewableFieldSet(resourceType); + SparseFieldSetExpression inputExpression = + _lazySourceTable.Value.TryGetValue(resourceType, out ImmutableHashSet? inputFields) + ? new SparseFieldSetExpression(inputFields) + : GetCachedViewableFieldSet(resourceType); SparseFieldSetExpression? outputExpression = _resourceDefinitionAccessor.OnApplySparseFieldSet(resourceType, inputExpression); - IImmutableSet outputFields = outputExpression == null + outputFields = outputExpression == null ? GetCachedViewableFieldSet(resourceType).Fields : inputExpression.Fields.Intersect(outputExpression.Fields); _visitedTable[resourceType] = outputFields; } - return _visitedTable[resourceType]; + return outputFields; } private static SparseFieldSetExpression GetCachedViewableFieldSet(ResourceType resourceType) { if (!ViewableFieldSetCache.TryGetValue(resourceType, out SparseFieldSetExpression? fieldSet)) { - IImmutableSet viewableFields = GetViewableFields(resourceType); + ImmutableHashSet viewableFields = GetViewableFields(resourceType); fieldSet = new SparseFieldSetExpression(viewableFields); ViewableFieldSetCache[resourceType] = fieldSet; } @@ -144,16 +144,9 @@ private static SparseFieldSetExpression GetCachedViewableFieldSet(ResourceType r return fieldSet; } - private static IImmutableSet GetViewableFields(ResourceType resourceType) + private static ImmutableHashSet GetViewableFields(ResourceType resourceType) { - ImmutableHashSet.Builder fieldSetBuilder = ImmutableHashSet.CreateBuilder(); - - foreach (ResourceFieldAttribute field in resourceType.Fields.Where(nextField => !nextField.IsViewBlocked())) - { - fieldSetBuilder.Add(field); - } - - return fieldSetBuilder.ToImmutable(); + return resourceType.Fields.Where(nextField => !nextField.IsViewBlocked()).ToImmutableHashSet(); } public void Reset() diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainParser.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainParser.cs index e6dac0b258..448b802cec 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainParser.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainParser.cs @@ -9,7 +9,7 @@ public IEnumerable Parse(string source) { ArgumentGuard.NotNull(source); - if (source != string.Empty) + if (source.Length > 0) { var fields = new List(source.Split('.')); int position = 0; diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchError.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchError.cs index 8fe555b2f3..3707151560 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchError.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchError.cs @@ -37,7 +37,7 @@ public static MatchError CreateForBrokenFieldChain(FieldChainFormatException exc public static MatchError CreateForUnknownField(int position, ResourceType? resourceType, string publicName, bool allowDerivedTypes) { - bool hasDerivedTypes = allowDerivedTypes && resourceType != null && resourceType.DirectlyDerivedTypes.Any(); + bool hasDerivedTypes = allowDerivedTypes && resourceType is { DirectlyDerivedTypes.Count: > 0 }; var builder = new MessageBuilder(); diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchState.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchState.cs index a0aa58e377..fa05753ae8 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchState.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchState.cs @@ -253,7 +253,7 @@ public IReadOnlyList GetAllFieldsMatched() fields.AddRange(matches); } - return fields; + return fields.AsReadOnly(); } private static void AssertIsSuccess(MatchState state) diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchTraceScope.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchTraceScope.cs index 653c029e46..a4cf569173 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchTraceScope.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchTraceScope.cs @@ -1,13 +1,11 @@ using Microsoft.Extensions.Logging; -#pragma warning disable CA2254 // Template should be a static expression - namespace JsonApiDotNetCore.QueryStrings.FieldChains; /// /// Logs the pattern matching steps at level. /// -internal sealed class MatchTraceScope : IDisposable +internal sealed partial class MatchTraceScope : IDisposable { private readonly FieldChainPattern? _pattern; private readonly bool _isEnabled; @@ -29,15 +27,15 @@ public static MatchTraceScope CreateRoot(MatchState startState, ILogger logger) ArgumentGuard.NotNull(logger); bool isEnabled = logger.IsEnabled(LogLevel.Trace); + var scope = new MatchTraceScope(startState.Pattern, isEnabled, logger, 0); if (isEnabled) { string fieldsRemaining = FormatFieldsRemaining(startState); - string message = $"Start matching pattern '{startState.Pattern}' against the complete chain '{fieldsRemaining}'"; - logger.LogTrace(message); + scope.LogMatchFirst(startState.Pattern, fieldsRemaining); } - return new MatchTraceScope(startState.Pattern, isEnabled, logger, 0); + return scope; } public MatchTraceScope CreateChild(MatchState startState) @@ -49,8 +47,9 @@ public MatchTraceScope CreateChild(MatchState startState) if (_isEnabled) { + string indent = GetIndentText(); string fieldsRemaining = FormatFieldsRemaining(startState); - LogMessage($"Start matching '{patternSegment}' against the remaining chain '{fieldsRemaining}'"); + LogMatchNext(indent, patternSegment, fieldsRemaining); } return new MatchTraceScope(patternSegment, _isEnabled, _logger, indentDepth); @@ -62,14 +61,16 @@ public void LogMatchResult(MatchState resultState) if (_isEnabled) { + string indent = GetIndentText(); + if (resultState.Error == null) { string fieldsMatched = FormatFieldsMatched(resultState); - LogMessage($"Match '{_pattern}' against '{fieldsMatched}': Success"); + LogMatchSuccess(indent, _pattern, fieldsMatched); } else { - List chain = [..resultState.FieldsMatched.Select(attribute => attribute.PublicName)]; + List chain = [.. resultState.FieldsMatched.Select(attribute => attribute.PublicName)]; if (resultState.FieldsRemaining != null) { @@ -77,7 +78,7 @@ public void LogMatchResult(MatchState resultState) } string chainText = string.Join('.', chain); - LogMessage($"Match '{_pattern}' against '{chainText}': Failed"); + LogMatchFailed(indent, _pattern, chainText); } } } @@ -88,8 +89,9 @@ public void LogBacktrackTo(MatchState backtrackState) if (_isEnabled) { + string indent = GetIndentText(); string fieldsMatched = FormatFieldsMatched(backtrackState); - LogMessage($"Backtracking to successful match against '{fieldsMatched}'"); + LogBacktrack(indent, fieldsMatched); } } @@ -109,7 +111,16 @@ public void Dispose() if (_isEnabled) { - LogMessage(_endState.Error == null ? "Matching completed with success" : "Matching completed with failure"); + string indent = GetIndentText(); + + if (_endState.Error == null) + { + LogCompletionSuccess(indent); + } + else + { + LogCompletionFailure(indent); + } } } @@ -123,9 +134,30 @@ private static string FormatFieldsMatched(MatchState state) return string.Join('.', state.FieldsMatched); } - private void LogMessage(string message) + private string GetIndentText() { - string indent = new(' ', _indentDepth * 2); - _logger.LogTrace($"{indent}{message}"); + return new string(' ', _indentDepth * 2); } + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "Start matching pattern '{Pattern}' against the complete chain '{Chain}'.")] + private partial void LogMatchFirst(FieldChainPattern? pattern, string chain); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, + Message = "{Indent}Start matching pattern '{Pattern}' against the remaining chain '{Chain}'.")] + private partial void LogMatchNext(string indent, FieldChainPattern? pattern, string chain); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "{Indent}Match pattern '{Pattern}' against the chain '{Chain}': Success.")] + private partial void LogMatchSuccess(string indent, FieldChainPattern? pattern, string chain); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "{Indent}Match pattern '{Pattern}' against the chain '{Chain}': Failed.")] + private partial void LogMatchFailed(string indent, FieldChainPattern? pattern, string chain); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "{Indent}Backtracking to successful match against '{Chain}'.")] + private partial void LogBacktrack(string indent, string chain); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "{Indent}Matching completed with success.")] + private partial void LogCompletionSuccess(string indent); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "{Indent}Matching completed with failure.")] + private partial void LogCompletionFailure(string indent); } diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternMatcher.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternMatcher.cs index 049aac2b94..d05f4e3d12 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternMatcher.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternMatcher.cs @@ -157,7 +157,7 @@ private MatchState MatchField(MatchState state) HashSet fields = LookupFields(state.ResourceType, publicName); - if (!fields.Any()) + if (fields.Count == 0) { return state.FailureForUnknownField(publicName, _allowDerivedTypes); } diff --git a/src/JsonApiDotNetCore/QueryStrings/FilterQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/FilterQueryStringParameterReader.cs index 6ebdd4fd29..052e4ac93e 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FilterQueryStringParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FilterQueryStringParameterReader.cs @@ -140,24 +140,25 @@ private void StoreFilterInScope(FilterExpression filter, ResourceFieldChainExpre } else { - if (!_filtersPerScope.ContainsKey(scope)) + if (!_filtersPerScope.TryGetValue(scope, out ImmutableArray.Builder? builder)) { - _filtersPerScope[scope] = ImmutableArray.CreateBuilder(); + builder = ImmutableArray.CreateBuilder(); + _filtersPerScope[scope] = builder; } - _filtersPerScope[scope].Add(filter); + builder.Add(filter); } } /// public virtual IReadOnlyCollection GetConstraints() { - return EnumerateFiltersInScopes().ToArray(); + return EnumerateFiltersInScopes().ToArray().AsReadOnly(); } private IEnumerable EnumerateFiltersInScopes() { - if (_filtersInGlobalScope.Any()) + if (_filtersInGlobalScope.Count > 0) { FilterExpression filter = MergeFilters(_filtersInGlobalScope.ToImmutable()); yield return new ExpressionInScope(null, filter); @@ -172,6 +173,6 @@ private IEnumerable EnumerateFiltersInScopes() private static FilterExpression MergeFilters(IImmutableList filters) { - return filters.Count > 1 ? new LogicalExpression(LogicalOperator.Or, filters) : filters.First(); + return filters.Count > 1 ? new LogicalExpression(LogicalOperator.Or, filters) : filters[0]; } } diff --git a/src/JsonApiDotNetCore/QueryStrings/IncludeQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/IncludeQueryStringParameterReader.cs index ba0f889809..7b3739da8e 100644 --- a/src/JsonApiDotNetCore/QueryStrings/IncludeQueryStringParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/IncludeQueryStringParameterReader.cs @@ -39,6 +39,8 @@ public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttr /// public virtual bool CanRead(string parameterName) { + ArgumentGuard.NotNullNorEmpty(parameterName); + return parameterName == "include"; } diff --git a/src/JsonApiDotNetCore/QueryStrings/PaginationQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/PaginationQueryStringParameterReader.cs index e46e59ce18..6484253574 100644 --- a/src/JsonApiDotNetCore/QueryStrings/PaginationQueryStringParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/PaginationQueryStringParameterReader.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using System.Collections.ObjectModel; using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Controllers.Annotations; @@ -48,6 +49,8 @@ public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttr /// public virtual bool CanRead(string parameterName) { + ArgumentGuard.NotNullNorEmpty(parameterName); + return parameterName is PageSizeParameterName or PageNumberParameterName; } @@ -92,6 +95,8 @@ private PaginationQueryStringValueExpression GetPageConstraint(string parameterV protected virtual void ValidatePageSize(PaginationQueryStringValueExpression constraint) { + ArgumentGuard.NotNull(constraint); + foreach (PaginationElementQueryStringValueExpression element in constraint.Elements) { if (_options.MaximumPageSize != null) @@ -116,6 +121,8 @@ protected virtual void ValidatePageSize(PaginationQueryStringValueExpression con protected virtual void ValidatePageNumber(PaginationQueryStringValueExpression constraint) { + ArgumentGuard.NotNull(constraint); + foreach (PaginationElementQueryStringValueExpression element in constraint.Elements) { if (_options.MaximumPageNumber != null) @@ -194,9 +201,9 @@ private void ApplyOptionsInEntry(MutablePaginationEntry entry, IJsonApiOptions o entry.PageNumber ??= PageNumber.ValueOne; } - public IReadOnlyCollection GetExpressionsInScope() + public ReadOnlyCollection GetExpressionsInScope() { - return EnumerateExpressionsInScope().ToArray(); + return EnumerateExpressionsInScope().ToArray().AsReadOnly(); } private IEnumerable EnumerateExpressionsInScope() diff --git a/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs b/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs index e3c944a045..fd19e78236 100644 --- a/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs @@ -8,11 +8,11 @@ namespace JsonApiDotNetCore.QueryStrings; /// -public sealed class QueryStringReader : IQueryStringReader +public sealed partial class QueryStringReader : IQueryStringReader { private readonly IJsonApiOptions _options; private readonly IRequestQueryStringAccessor _queryStringAccessor; - private readonly IEnumerable _parameterReaders; + private readonly IQueryStringParameterReader[] _parameterReaders; private readonly ILogger _logger; public QueryStringReader(IJsonApiOptions options, IRequestQueryStringAccessor queryStringAccessor, @@ -25,7 +25,7 @@ public QueryStringReader(IJsonApiOptions options, IRequestQueryStringAccessor qu _options = options; _queryStringAccessor = queryStringAccessor; - _parameterReaders = parameterReaders; + _parameterReaders = parameterReaders as IQueryStringParameterReader[] ?? parameterReaders.ToArray(); _logger = loggerFactory.CreateLogger(); } @@ -47,7 +47,7 @@ public void ReadAll(DisableQueryStringAttribute? disableQueryStringAttribute) if (reader != null) { - _logger.LogDebug($"Query string parameter '{parameterName}' with value '{parameterValue}' was accepted by {reader.GetType().Name}."); + LogParameterAccepted(parameterName, parameterValue, reader.GetType().Name); if (!reader.AllowEmptyValue && string.IsNullOrEmpty(parameterValue)) { @@ -63,7 +63,7 @@ public void ReadAll(DisableQueryStringAttribute? disableQueryStringAttribute) } reader.Read(parameterName, parameterValue); - _logger.LogDebug($"Query string parameter '{parameterName}' was successfully read."); + LogParameterRead(parameterName); } else if (!_options.AllowUnknownQueryStringParameters) { @@ -73,4 +73,10 @@ public void ReadAll(DisableQueryStringAttribute? disableQueryStringAttribute) } } } + + [LoggerMessage(Level = LogLevel.Debug, Message = "Query string parameter '{ParameterName}' with value '{ParameterValue}' was accepted by {ReaderType}.")] + private partial void LogParameterAccepted(string parameterName, StringValues parameterValue, string readerType); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Query string parameter '{ParameterName}' was successfully read.")] + private partial void LogParameterRead(string parameterName); } diff --git a/src/JsonApiDotNetCore/QueryStrings/ResourceDefinitionQueryableParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/ResourceDefinitionQueryableParameterReader.cs index 3d844e4b48..54ed090d78 100644 --- a/src/JsonApiDotNetCore/QueryStrings/ResourceDefinitionQueryableParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/ResourceDefinitionQueryableParameterReader.cs @@ -37,6 +37,8 @@ public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttr /// public virtual bool CanRead(string parameterName) { + ArgumentGuard.NotNullNorEmpty(parameterName); + if (_request.Kind == EndpointKind.AtomicOperations) { return false; @@ -71,6 +73,6 @@ public virtual void Read(string parameterName, StringValues parameterValue) /// public virtual IReadOnlyCollection GetConstraints() { - return _constraints; + return _constraints.AsReadOnly(); } } diff --git a/src/JsonApiDotNetCore/QueryStrings/SortQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/SortQueryStringParameterReader.cs index d1ff5fface..98d11b2344 100644 --- a/src/JsonApiDotNetCore/QueryStrings/SortQueryStringParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/SortQueryStringParameterReader.cs @@ -92,6 +92,6 @@ private SortExpression GetSort(string parameterValue, ResourceFieldChainExpressi /// public virtual IReadOnlyCollection GetConstraints() { - return _constraints; + return _constraints.AsReadOnly(); } } diff --git a/src/JsonApiDotNetCore/QueryStrings/SparseFieldSetQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/SparseFieldSetQueryStringParameterReader.cs index c147285636..ad2d728fa8 100644 --- a/src/JsonApiDotNetCore/QueryStrings/SparseFieldSetQueryStringParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/SparseFieldSetQueryStringParameterReader.cs @@ -24,7 +24,7 @@ public class SparseFieldSetQueryStringParameterReader : QueryStringParameterRead ImmutableDictionary.CreateBuilder(); /// - bool IQueryStringParameterReader.AllowEmptyValue => true; + public bool AllowEmptyValue => true; public SparseFieldSetQueryStringParameterReader(ISparseFieldTypeParser scopeParser, ISparseFieldSetParser sparseFieldSetParser, IJsonApiRequest request, IResourceGraph resourceGraph) @@ -95,7 +95,7 @@ private SparseFieldSetExpression GetSparseFieldSet(string parameterValue, Resour /// public virtual IReadOnlyCollection GetConstraints() { - return _sparseFieldTableBuilder.Any() + return _sparseFieldTableBuilder.Count > 0 ? [new ExpressionInScope(null, new SparseFieldTableExpression(_sparseFieldTableBuilder.ToImmutable()))] : Array.Empty(); } diff --git a/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs b/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs index 72eeff5c27..9fc76bdefb 100644 --- a/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs +++ b/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs @@ -36,7 +36,7 @@ public class EntityFrameworkCoreRepository : IResourceRepository private readonly DbContext _dbContext; private readonly IResourceGraph _resourceGraph; private readonly IResourceFactory _resourceFactory; - private readonly IEnumerable _constraintProviders; + private readonly IQueryConstraintProvider[] _constraintProviders; private readonly IResourceDefinitionAccessor _resourceDefinitionAccessor; private readonly TraceLogWriter> _traceWriter; @@ -59,7 +59,7 @@ public EntityFrameworkCoreRepository(ITargetedFields targetedFields, IDbContextR _dbContext = dbContextResolver.GetContext(); _resourceGraph = resourceGraph; _resourceFactory = resourceFactory; - _constraintProviders = constraintProviders; + _constraintProviders = constraintProviders as IQueryConstraintProvider[] ?? constraintProviders.ToArray(); _resourceDefinitionAccessor = resourceDefinitionAccessor; _traceWriter = new TraceLogWriter>(loggerFactory); } @@ -80,7 +80,8 @@ public virtual async Task> GetAsync(QueryLayer qu using (CodeTimingSessionManager.Current.Measure("Execute SQL (data)", MeasurementSettings.ExcludeDatabaseInPercentages)) { - return await query.ToListAsync(cancellationToken); + List resources = await query.ToListAsync(cancellationToken); + return resources.AsReadOnly(); } } } @@ -113,6 +114,8 @@ public virtual async Task CountAsync(FilterExpression? filter, Cancellation protected virtual IQueryable ApplyQueryLayer(QueryLayer queryLayer) { + ArgumentGuard.NotNull(queryLayer); + _traceWriter.LogMethodStart(new { queryLayer @@ -316,6 +319,8 @@ public virtual async Task UpdateAsync(TResource resourceFromRequest, TResource r protected void AssertIsNotClearingRequiredToOneRelationship(RelationshipAttribute relationship, object? rightValue) { + ArgumentGuard.NotNull(relationship); + if (relationship is HasOneAttribute) { INavigation? navigation = GetNavigation(relationship); @@ -455,10 +460,10 @@ public virtual async Task AddToToManyRelationshipAsync(TResource? leftResource, await _resourceDefinitionAccessor.OnAddToRelationshipAsync(leftPlaceholderResource, relationship, rightResourceIds, cancellationToken); - if (rightResourceIds.Any()) + if (rightResourceIds.Count > 0) { var leftResourceTracked = (TResource)_dbContext.GetTrackedOrAttach(leftPlaceholderResource); - IEnumerable rightValueToStore = GetRightValueToStoreForAddToToMany(leftResourceTracked, relationship, rightResourceIds); + ISet rightValueToStore = GetRightValueToStoreForAddToToMany(leftResourceTracked, relationship, rightResourceIds); await UpdateRelationshipAsync(relationship, leftResourceTracked, rightValueToStore, cancellationToken); @@ -471,7 +476,8 @@ public virtual async Task AddToToManyRelationshipAsync(TResource? leftResource, } } - private IEnumerable GetRightValueToStoreForAddToToMany(TResource leftResource, HasManyAttribute relationship, ISet rightResourceIdsToAdd) + private ISet GetRightValueToStoreForAddToToMany(TResource leftResource, HasManyAttribute relationship, + ISet rightResourceIdsToAdd) { object? rightValueStored = relationship.GetValue(leftResource); @@ -480,13 +486,13 @@ private IEnumerable GetRightValueToStoreForAddToToMany(TResource leftResource, H HashSet rightResourceIdsStored = _collectionConverter .ExtractResources(rightValueStored) - .Select(rightResource => _dbContext.GetTrackedOrAttach(rightResource)) + .Select(_dbContext.GetTrackedOrAttach) .ToHashSet(IdentifiableComparer.Instance); // @formatter:wrap_before_first_method_call restore // @formatter:wrap_chained_method_calls restore - if (rightResourceIdsStored.Any()) + if (rightResourceIdsStored.Count > 0) { rightResourceIdsStored.UnionWith(rightResourceIdsToAdd); return rightResourceIdsStored; @@ -515,7 +521,7 @@ public virtual async Task RemoveFromToManyRelationshipAsync(TResource leftResour await _resourceDefinitionAccessor.OnRemoveFromRelationshipAsync(leftResource, relationship, rightResourceIdsToRemove, cancellationToken); - if (rightResourceIdsToRemove.Any()) + if (rightResourceIdsToRemove.Count > 0) { var leftResourceTracked = (TResource)_dbContext.GetTrackedOrAttach(leftResource); @@ -530,7 +536,7 @@ public virtual async Task RemoveFromToManyRelationshipAsync(TResource leftResour IIdentifiable[] rightResourceIdsStored = _collectionConverter .ExtractResources(rightValueStored) .Concat(extraResourceIdsToRemove) - .Select(rightResource => _dbContext.GetTrackedOrAttach(rightResource)) + .Select(_dbContext.GetTrackedOrAttach) .ToArray(); // @formatter:wrap_before_first_method_call restore @@ -576,7 +582,7 @@ private void MarkManyToManyRelationshipAsLoaded(EntityEntry leftEntry string[] foreignKeyNames = skipNavigation.ForeignKey.Properties.Select(property => property.Name).ToArray(); - foreach (EntityEntry joinEntry in _dbContext.ChangeTracker.Entries().Where(entry => entry.Metadata == skipNavigation.JoinEntityType).ToList()) + foreach (EntityEntry joinEntry in _dbContext.ChangeTracker.Entries().Where(entry => entry.Metadata == skipNavigation.JoinEntityType).ToArray()) { object?[] foreignKeyValues = GetCurrentKeyValues(joinEntry, foreignKeyNames); @@ -595,6 +601,9 @@ private void MarkManyToManyRelationshipAsLoaded(EntityEntry leftEntry protected async Task UpdateRelationshipAsync(RelationshipAttribute relationship, TResource leftResource, object? valueToAssign, CancellationToken cancellationToken) { + ArgumentGuard.NotNull(relationship); + ArgumentGuard.NotNull(leftResource); + object? trackedValueToAssign = EnsureRelationshipValueToAssignIsTracked(valueToAssign, relationship.Property.PropertyType); if (RequireLoadOfInverseRelationship(relationship, trackedValueToAssign)) @@ -616,7 +625,7 @@ protected async Task UpdateRelationshipAsync(RelationshipAttribute relationship, } IReadOnlyCollection rightResources = _collectionConverter.ExtractResources(rightValue); - IIdentifiable[] rightResourcesTracked = rightResources.Select(rightResource => _dbContext.GetTrackedOrAttach(rightResource)).ToArray(); + IIdentifiable[] rightResourcesTracked = rightResources.Select(_dbContext.GetTrackedOrAttach).ToArray(); return rightValue is IEnumerable ? _collectionConverter.CopyToTypedCollection(rightResourcesTracked, relationshipPropertyType) diff --git a/src/JsonApiDotNetCore/Repositories/ResourceRepositoryAccessor.cs b/src/JsonApiDotNetCore/Repositories/ResourceRepositoryAccessor.cs index 6f19f51c1d..23d03eb9dd 100644 --- a/src/JsonApiDotNetCore/Repositories/ResourceRepositoryAccessor.cs +++ b/src/JsonApiDotNetCore/Repositories/ResourceRepositoryAccessor.cs @@ -33,6 +33,8 @@ public ResourceRepositoryAccessor(IServiceProvider serviceProvider, IResourceGra public async Task> GetAsync(QueryLayer queryLayer, CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentGuard.NotNull(queryLayer); + dynamic repository = ResolveReadRepository(typeof(TResource)); return (IReadOnlyCollection)await repository.GetAsync(queryLayer, cancellationToken); } @@ -41,6 +43,7 @@ public async Task> GetAsync(QueryLayer public async Task> GetAsync(ResourceType resourceType, QueryLayer queryLayer, CancellationToken cancellationToken) { ArgumentGuard.NotNull(resourceType); + ArgumentGuard.NotNull(queryLayer); dynamic repository = ResolveReadRepository(resourceType); return (IReadOnlyCollection)await repository.GetAsync(queryLayer, cancellationToken); @@ -49,6 +52,8 @@ public async Task> GetAsync(ResourceType reso /// public async Task CountAsync(ResourceType resourceType, FilterExpression? filter, CancellationToken cancellationToken) { + ArgumentGuard.NotNull(resourceType); + dynamic repository = ResolveReadRepository(resourceType); return (int)await repository.CountAsync(filter, cancellationToken); } @@ -57,6 +62,8 @@ public async Task CountAsync(ResourceType resourceType, FilterExpression? f public async Task GetForCreateAsync(Type resourceClrType, [DisallowNull] TId id, CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentGuard.NotNull(resourceClrType); + dynamic repository = GetWriteRepository(typeof(TResource)); return await repository.GetForCreateAsync(resourceClrType, id, cancellationToken); } @@ -65,6 +72,9 @@ public async Task GetForCreateAsync(Type resourceClrT public async Task CreateAsync(TResource resourceFromRequest, TResource resourceForDatabase, CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentGuard.NotNull(resourceFromRequest); + ArgumentGuard.NotNull(resourceForDatabase); + dynamic repository = GetWriteRepository(typeof(TResource)); await repository.CreateAsync(resourceFromRequest, resourceForDatabase, cancellationToken); } @@ -73,6 +83,8 @@ public async Task CreateAsync(TResource resourceFromRequest, TResourc public async Task GetForUpdateAsync(QueryLayer queryLayer, CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentGuard.NotNull(queryLayer); + dynamic repository = GetWriteRepository(typeof(TResource)); return await repository.GetForUpdateAsync(queryLayer, cancellationToken); } @@ -81,6 +93,9 @@ public async Task CreateAsync(TResource resourceFromRequest, TResourc public async Task UpdateAsync(TResource resourceFromRequest, TResource resourceFromDatabase, CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentGuard.NotNull(resourceFromRequest); + ArgumentGuard.NotNull(resourceFromDatabase); + dynamic repository = GetWriteRepository(typeof(TResource)); await repository.UpdateAsync(resourceFromRequest, resourceFromDatabase, cancellationToken); } @@ -97,6 +112,8 @@ public async Task DeleteAsync(TResource? resourceFromDatabase, [ public async Task SetRelationshipAsync(TResource leftResource, object? rightValue, CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentGuard.NotNull(leftResource); + dynamic repository = GetWriteRepository(typeof(TResource)); await repository.SetRelationshipAsync(leftResource, rightValue, cancellationToken); } @@ -106,6 +123,8 @@ public async Task AddToToManyRelationshipAsync(TResource? leftRe CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentGuard.NotNull(rightResourceIds); + dynamic repository = GetWriteRepository(typeof(TResource)); await repository.AddToToManyRelationshipAsync(leftResource, leftId, rightResourceIds, cancellationToken); } @@ -115,18 +134,25 @@ public async Task RemoveFromToManyRelationshipAsync(TResource leftRes CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentGuard.NotNull(leftResource); + ArgumentGuard.NotNull(rightResourceIds); + dynamic repository = GetWriteRepository(typeof(TResource)); await repository.RemoveFromToManyRelationshipAsync(leftResource, rightResourceIds, cancellationToken); } protected object ResolveReadRepository(Type resourceClrType) { + ArgumentGuard.NotNull(resourceClrType); + ResourceType resourceType = _resourceGraph.GetResourceType(resourceClrType); return ResolveReadRepository(resourceType); } protected virtual object ResolveReadRepository(ResourceType resourceType) { + ArgumentGuard.NotNull(resourceType); + Type repositoryType = typeof(IResourceReadRepository<,>).MakeGenericType(resourceType.ClrType, resourceType.IdentityClrType); return _serviceProvider.GetRequiredService(repositoryType); } @@ -154,6 +180,8 @@ private object GetWriteRepository(Type resourceClrType) protected virtual object ResolveWriteRepository(Type resourceClrType) { + ArgumentGuard.NotNull(resourceClrType); + ResourceType resourceType = _resourceGraph.GetResourceType(resourceClrType); Type resourceDefinitionType = typeof(IResourceWriteRepository<,>).MakeGenericType(resourceType.ClrType, resourceType.IdentityClrType); diff --git a/src/JsonApiDotNetCore/Resources/ResourceChangeTracker.cs b/src/JsonApiDotNetCore/Resources/ResourceChangeTracker.cs index 7eb57813ca..795c33f16b 100644 --- a/src/JsonApiDotNetCore/Resources/ResourceChangeTracker.cs +++ b/src/JsonApiDotNetCore/Resources/ResourceChangeTracker.cs @@ -12,9 +12,9 @@ public sealed class ResourceChangeTracker : IResourceChangeTracker? _initiallyStoredAttributeValues; - private IDictionary? _requestAttributeValues; - private IDictionary? _finallyStoredAttributeValues; + private Dictionary? _initiallyStoredAttributeValues; + private Dictionary? _requestAttributeValues; + private Dictionary? _finallyStoredAttributeValues; public ResourceChangeTracker(IJsonApiRequest request, ITargetedFields targetedFields) { @@ -49,7 +49,7 @@ public void SetFinallyStoredAttributeValues(TResource resource) _finallyStoredAttributeValues = CreateAttributeDictionary(resource, _request.PrimaryResourceType!.Attributes); } - private IDictionary CreateAttributeDictionary(TResource resource, IEnumerable attributes) + private Dictionary CreateAttributeDictionary(TResource resource, IEnumerable attributes) { var result = new Dictionary(); diff --git a/src/JsonApiDotNetCore/Resources/ResourceDefinitionAccessor.cs b/src/JsonApiDotNetCore/Resources/ResourceDefinitionAccessor.cs index 93b71a5546..28079b7e2a 100644 --- a/src/JsonApiDotNetCore/Resources/ResourceDefinitionAccessor.cs +++ b/src/JsonApiDotNetCore/Resources/ResourceDefinitionAccessor.cs @@ -92,7 +92,7 @@ public IImmutableSet OnApplyIncludes(ResourceType reso ArgumentGuard.NotNullNorEmpty(parameterName); dynamic resourceDefinition = ResolveResourceDefinition(resourceClrType); - dynamic handlers = resourceDefinition.OnRegisterQueryableHandlersForQueryStringParameters(); + dynamic? handlers = resourceDefinition.OnRegisterQueryableHandlersForQueryStringParameters(); if (handlers != null) { @@ -216,12 +216,16 @@ public void OnSerialize(IIdentifiable resource) protected object ResolveResourceDefinition(Type resourceClrType) { + ArgumentGuard.NotNull(resourceClrType); + ResourceType resourceType = _resourceGraph.GetResourceType(resourceClrType); return ResolveResourceDefinition(resourceType); } protected virtual object ResolveResourceDefinition(ResourceType resourceType) { + ArgumentGuard.NotNull(resourceType); + Type resourceDefinitionType = typeof(IResourceDefinition<,>).MakeGenericType(resourceType.ClrType, resourceType.IdentityClrType); return _serviceProvider.GetRequiredService(resourceDefinitionType); } diff --git a/src/JsonApiDotNetCore/Resources/ResourceFactory.cs b/src/JsonApiDotNetCore/Resources/ResourceFactory.cs index f8af9dfa2f..9b02953c84 100644 --- a/src/JsonApiDotNetCore/Resources/ResourceFactory.cs +++ b/src/JsonApiDotNetCore/Resources/ResourceFactory.cs @@ -92,7 +92,7 @@ public NewExpression CreateNewExpression(Type resourceClrType) return Expression.New(resourceClrType); } - var constructorArguments = new List(); + List constructorArguments = []; ConstructorInfo longestConstructor = GetLongestConstructor(resourceClrType); diff --git a/src/JsonApiDotNetCore/Resources/SortExpressionLambdaConverter.cs b/src/JsonApiDotNetCore/Resources/SortExpressionLambdaConverter.cs index 8696195e28..92862d4d99 100644 --- a/src/JsonApiDotNetCore/Resources/SortExpressionLambdaConverter.cs +++ b/src/JsonApiDotNetCore/Resources/SortExpressionLambdaConverter.cs @@ -11,7 +11,7 @@ namespace JsonApiDotNetCore.Resources; internal sealed class SortExpressionLambdaConverter { private readonly IResourceGraph _resourceGraph; - private readonly IList _fields = new List(); + private readonly List _fields = []; public SortExpressionLambdaConverter(IResourceGraph resourceGraph) { diff --git a/src/JsonApiDotNetCore/Resources/TargetedFields.cs b/src/JsonApiDotNetCore/Resources/TargetedFields.cs index 2e841873b2..3b44c4a261 100644 --- a/src/JsonApiDotNetCore/Resources/TargetedFields.cs +++ b/src/JsonApiDotNetCore/Resources/TargetedFields.cs @@ -7,8 +7,8 @@ namespace JsonApiDotNetCore.Resources; [PublicAPI] public sealed class TargetedFields : ITargetedFields { - IReadOnlySet ITargetedFields.Attributes => Attributes; - IReadOnlySet ITargetedFields.Relationships => Relationships; + IReadOnlySet ITargetedFields.Attributes => Attributes.AsReadOnly(); + IReadOnlySet ITargetedFields.Relationships => Relationships.AsReadOnly(); public HashSet Attributes { get; } = []; public HashSet Relationships { get; } = []; @@ -16,6 +16,8 @@ public sealed class TargetedFields : ITargetedFields /// public void CopyFrom(ITargetedFields other) { + ArgumentGuard.NotNull(other); + Clear(); Attributes.UnionWith(other.Attributes); diff --git a/src/JsonApiDotNetCore/Serialization/JsonConverters/JsonObjectConverter.cs b/src/JsonApiDotNetCore/Serialization/JsonConverters/JsonObjectConverter.cs index 32e4351e12..c470b991d6 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonConverters/JsonObjectConverter.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonConverters/JsonObjectConverter.cs @@ -7,6 +7,8 @@ public abstract class JsonObjectConverter : JsonConverter { protected static TValue? ReadSubTree(ref Utf8JsonReader reader, JsonSerializerOptions options) { + ArgumentGuard.NotNull(options); + if (typeof(TValue) != typeof(object) && options.GetConverter(typeof(TValue)) is JsonConverter converter) { return converter.Read(ref reader, typeof(TValue), options); @@ -17,6 +19,8 @@ public abstract class JsonObjectConverter : JsonConverter protected static void WriteSubTree(Utf8JsonWriter writer, TValue value, JsonSerializerOptions options) { + ArgumentGuard.NotNull(options); + if (typeof(TValue) != typeof(object) && options.GetConverter(typeof(TValue)) is JsonConverter converter) { converter.Write(writer, value, options); diff --git a/src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs b/src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs index 25218b1ba9..b76fc343a5 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs @@ -157,7 +157,7 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver return null; } - private static IDictionary ReadAttributes(ref Utf8JsonReader reader, JsonSerializerOptions options, ResourceType resourceType) + private static Dictionary ReadAttributes(ref Utf8JsonReader reader, JsonSerializerOptions options, ResourceType resourceType) { var attributes = new Dictionary(); @@ -224,6 +224,9 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver /// public override void Write(Utf8JsonWriter writer, ResourceObject value, JsonSerializerOptions options) { + ArgumentGuard.NotNull(writer); + ArgumentGuard.NotNull(value); + writer.WriteStartObject(); writer.WriteString(TypeText, value.Type); diff --git a/src/JsonApiDotNetCore/Serialization/JsonConverters/SingleOrManyDataConverterFactory.cs b/src/JsonApiDotNetCore/Serialization/JsonConverters/SingleOrManyDataConverterFactory.cs index 457f5082ef..48d90f9c8f 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonConverters/SingleOrManyDataConverterFactory.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonConverters/SingleOrManyDataConverterFactory.cs @@ -14,12 +14,16 @@ public sealed class SingleOrManyDataConverterFactory : JsonConverterFactory /// public override bool CanConvert(Type typeToConvert) { + ArgumentGuard.NotNull(typeToConvert); + return typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(SingleOrManyData<>); } /// public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { + ArgumentGuard.NotNull(typeToConvert); + Type objectType = typeToConvert.GetGenericArguments()[0]; Type converterType = typeof(SingleOrManyDataConverter<>).MakeGenericType(objectType); @@ -31,7 +35,7 @@ private sealed class SingleOrManyDataConverter : JsonObjectConverter Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - var objects = new List(); + List objects = []; bool isManyData = false; bool hasCompletedToMany = false; diff --git a/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyDocumentConverter.cs b/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyDocumentConverter.cs index a8f3e7f81e..2195ff2ec8 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyDocumentConverter.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyDocumentConverter.cs @@ -32,6 +32,9 @@ public override Document Read(ref Utf8JsonReader reader, Type typeToConvert, Jso /// public override void Write(Utf8JsonWriter writer, Document value, JsonSerializerOptions options) { + ArgumentGuard.NotNull(writer); + ArgumentGuard.NotNull(value); + writer.WriteStartObject(); if (value.JsonApi != null) diff --git a/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyRelationshipObjectConverter.cs b/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyRelationshipObjectConverter.cs index e34fc7636f..30a26c055b 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyRelationshipObjectConverter.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyRelationshipObjectConverter.cs @@ -27,6 +27,9 @@ public override RelationshipObject Read(ref Utf8JsonReader reader, Type typeToCo /// public override void Write(Utf8JsonWriter writer, RelationshipObject value, JsonSerializerOptions options) { + ArgumentGuard.NotNull(writer); + ArgumentGuard.NotNull(value); + writer.WriteStartObject(); if (value.Links != null && value.Links.HasValue()) diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicOperationObjectAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicOperationObjectAdapter.cs index 795030598c..a9205ce4fa 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicOperationObjectAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicOperationObjectAdapter.cs @@ -31,6 +31,9 @@ public AtomicOperationObjectAdapter(IJsonApiOptions options, IAtomicReferenceAda /// public OperationContainer Convert(AtomicOperationObject atomicOperationObject, RequestAdapterState state) { + ArgumentGuard.NotNull(atomicOperationObject); + ArgumentGuard.NotNull(state); + AssertNoHref(atomicOperationObject, state); WriteOperationKind writeOperation = ConvertOperationCode(atomicOperationObject, state); diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/BaseAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/BaseAdapter.cs index fb1111bea1..f7bbcb2121 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/BaseAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/BaseAdapter.cs @@ -13,6 +13,8 @@ public abstract class BaseAdapter protected static void AssertHasData(SingleOrManyData data, RequestAdapterState state) where T : ResourceIdentifierObject, new() { + ArgumentGuard.NotNull(state); + if (!data.IsAssigned) { throw new ModelConversionException(state.Position, "The 'data' element is required.", null); @@ -23,6 +25,8 @@ protected static void AssertHasData(SingleOrManyData data, RequestAdapterS protected static void AssertDataHasSingleValue(SingleOrManyData data, bool allowNull, RequestAdapterState state) where T : ResourceIdentifierObject, new() { + ArgumentGuard.NotNull(state); + if (data.SingleValue == null) { if (!allowNull) @@ -46,6 +50,8 @@ protected static void AssertDataHasSingleValue(SingleOrManyData data, bool protected static void AssertDataHasManyValue(SingleOrManyData data, RequestAdapterState state) where T : ResourceIdentifierObject, new() { + ArgumentGuard.NotNull(state); + if (data.ManyValue == null) { throw new ModelConversionException(state.Position, @@ -56,6 +62,8 @@ protected static void AssertDataHasManyValue(SingleOrManyData data, Reques protected static void AssertObjectIsNotNull([SysNotNull] T? value, RequestAdapterState state) where T : class { + ArgumentGuard.NotNull(state); + if (value is null) { throw new ModelConversionException(state.Position, "Expected an object, instead of 'null'.", null); diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInOperationsRequestAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInOperationsRequestAdapter.cs index 2a272c4cfd..7187ef0398 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInOperationsRequestAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInOperationsRequestAdapter.cs @@ -21,9 +21,11 @@ public DocumentInOperationsRequestAdapter(IJsonApiOptions options, IAtomicOperat } /// - public IReadOnlyList Convert(Document document, RequestAdapterState state) + public IList Convert(Document document, RequestAdapterState state) { + ArgumentGuard.NotNull(document); ArgumentGuard.NotNull(state); + AssertHasOperations(document.Operations, state); using IDisposable _ = state.Position.PushElement("atomic:operations"); @@ -40,7 +42,7 @@ private static void AssertHasOperations([NotNull] IEnumerable atomicOperationObjects, RequestAdapterState state) + private void AssertMaxOperationsNotExceeded(IList atomicOperationObjects, RequestAdapterState state) { if (atomicOperationObjects.Count > _options.MaximumOperationsPerRequest) { @@ -50,9 +52,9 @@ private void AssertMaxOperationsNotExceeded(ICollection } } - private IReadOnlyList ConvertOperations(IEnumerable atomicOperationObjects, RequestAdapterState state) + private List ConvertOperations(IEnumerable atomicOperationObjects, RequestAdapterState state) { - var operations = new List(); + List operations = []; int operationIndex = 0; foreach (AtomicOperationObject? atomicOperationObject in atomicOperationObjects) diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInResourceOrRelationshipRequestAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInResourceOrRelationshipRequestAdapter.cs index 8a031b692e..f6acf6212a 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInResourceOrRelationshipRequestAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInResourceOrRelationshipRequestAdapter.cs @@ -27,6 +27,9 @@ public DocumentInResourceOrRelationshipRequestAdapter(IJsonApiOptions options, I /// public object? Convert(Document document, RequestAdapterState state) { + ArgumentGuard.NotNull(document); + ArgumentGuard.NotNull(state); + state.WritableTargetedFields = new TargetedFields(); switch (state.Request.WriteOperation) diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/IDocumentInOperationsRequestAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/IDocumentInOperationsRequestAdapter.cs index b4e929cba3..7f6a6935cf 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/IDocumentInOperationsRequestAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/IDocumentInOperationsRequestAdapter.cs @@ -11,5 +11,7 @@ public interface IDocumentInOperationsRequestAdapter /// /// Validates and converts the specified . /// - IReadOnlyList Convert(Document document, RequestAdapterState state); +#pragma warning disable AV1130 // Return type in method signature should be an interface to an unchangeable collection + IList Convert(Document document, RequestAdapterState state); +#pragma warning restore AV1130 // Return type in method signature should be an interface to an unchangeable collection } diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RelationshipDataAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RelationshipDataAdapter.cs index 0e7f292394..b0b230094d 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RelationshipDataAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RelationshipDataAdapter.cs @@ -95,7 +95,7 @@ private IEnumerable ConvertToManyRelationshipData(SingleOrManyData(); + List rightResources = []; foreach (ResourceIdentifierObject resourceIdentifierObject in data.ManyValue!) { diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterPosition.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterPosition.cs index 3b114f61f4..4c047afaea 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterPosition.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterPosition.cs @@ -1,6 +1,8 @@ using System.Text; using JetBrains.Annotations; +#pragma warning disable CA1001 // Types that own disposable fields should be disposable + namespace JsonApiDotNetCore.Serialization.Request.Adapters; /// @@ -19,7 +21,7 @@ public RequestAdapterPosition() public IDisposable PushElement(string name) { - ArgumentGuard.NotNullNorEmpty(name); + ArgumentGuard.NotNullNorWhitespace(name); _stack.Push($"/{name}"); return _disposable; @@ -33,7 +35,7 @@ public IDisposable PushArrayIndex(int index) public string? ToSourcePointer() { - if (!_stack.Any()) + if (_stack.Count == 0) { return null; } @@ -41,7 +43,7 @@ public IDisposable PushArrayIndex(int index) var builder = new StringBuilder(); var clone = new Stack(_stack); - while (clone.Any()) + while (clone.Count > 0) { string element = clone.Pop(); builder.Append(element); diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterState.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterState.cs index c7d40e1794..e0c8a0d1c6 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterState.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterState.cs @@ -11,7 +11,7 @@ namespace JsonApiDotNetCore.Serialization.Request.Adapters; [PublicAPI] public sealed class RequestAdapterState : IDisposable { - private readonly IDisposable? _backupRequestState; + private readonly RevertRequestStateOnDispose? _backupRequestState; public IJsonApiRequest InjectableRequest { get; } public ITargetedFields InjectableTargetedFields { get; } diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataAdapter.cs index ffe971f42f..4717436085 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataAdapter.cs @@ -42,6 +42,9 @@ public IIdentifiable Convert(SingleOrManyData data, ResourceIden protected virtual (IIdentifiable resource, ResourceType resourceType) ConvertResourceObject(SingleOrManyData data, ResourceIdentityRequirements requirements, RequestAdapterState state) { + ArgumentGuard.NotNull(requirements); + ArgumentGuard.NotNull(state); + return _resourceObjectAdapter.Convert(data.SingleValue!, requirements, state); } } diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataInOperationsRequestAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataInOperationsRequestAdapter.cs index 7c299b0b5e..004363cd7f 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataInOperationsRequestAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataInOperationsRequestAdapter.cs @@ -11,6 +11,9 @@ public sealed class ResourceDataInOperationsRequestAdapter(IResourceDefinitionAc protected override (IIdentifiable resource, ResourceType resourceType) ConvertResourceObject(SingleOrManyData data, ResourceIdentityRequirements requirements, RequestAdapterState state) { + ArgumentGuard.NotNull(requirements); + ArgumentGuard.NotNull(state); + // This override ensures that we enrich IJsonApiRequest before calling into IResourceDefinition, so it is ready for consumption there. (IIdentifiable resource, ResourceType resourceType) = base.ConvertResourceObject(data, requirements, state); diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceIdentityAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceIdentityAdapter.cs index 8019b5884e..44e56cce99 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceIdentityAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceIdentityAdapter.cs @@ -238,6 +238,10 @@ private void AssignStringId(ResourceIdentity identity, IIdentifiable resource, R protected static void AssertIsKnownRelationship([NotNull] RelationshipAttribute? relationship, string relationshipName, ResourceType resourceType, RequestAdapterState state) { + ArgumentGuard.NotNull(relationshipName); + ArgumentGuard.NotNull(resourceType); + ArgumentGuard.NotNull(state); + if (relationship == null) { throw new ModelConversionException(state.Position, "Unknown relationship found.", @@ -247,6 +251,9 @@ protected static void AssertIsKnownRelationship([NotNull] RelationshipAttribute? protected internal static void AssertToManyInAddOrRemoveRelationship(RelationshipAttribute relationship, RequestAdapterState state) { + ArgumentGuard.NotNull(relationship); + ArgumentGuard.NotNull(state); + bool requireToManyRelationship = state.Request.WriteOperation is WriteOperationKind.AddToRelationship or WriteOperationKind.RemoveFromRelationship; if (requireToManyRelationship && relationship is not HasManyAttribute) diff --git a/src/JsonApiDotNetCore/Serialization/Request/JsonApiReader.cs b/src/JsonApiDotNetCore/Serialization/Request/JsonApiReader.cs index 4bd3741b7e..2d5fd0a66b 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/JsonApiReader.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/JsonApiReader.cs @@ -5,7 +5,6 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Diagnostics; using JsonApiDotNetCore.Errors; -using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Serialization.Objects; using JsonApiDotNetCore.Serialization.Request.Adapters; using Microsoft.AspNetCore.Http; @@ -17,21 +16,21 @@ namespace JsonApiDotNetCore.Serialization.Request; /// -public sealed class JsonApiReader : IJsonApiReader +public sealed partial class JsonApiReader : IJsonApiReader { private readonly IJsonApiOptions _options; private readonly IDocumentAdapter _documentAdapter; - private readonly TraceLogWriter _traceWriter; + private readonly ILogger _logger; - public JsonApiReader(IJsonApiOptions options, IDocumentAdapter documentAdapter, ILoggerFactory loggerFactory) + public JsonApiReader(IJsonApiOptions options, IDocumentAdapter documentAdapter, ILogger logger) { ArgumentGuard.NotNull(options); ArgumentGuard.NotNull(documentAdapter); - ArgumentGuard.NotNull(loggerFactory); + ArgumentGuard.NotNull(logger); _options = options; _documentAdapter = documentAdapter; - _traceWriter = new TraceLogWriter(loggerFactory); + _logger = logger; } /// @@ -40,9 +39,13 @@ public JsonApiReader(IJsonApiOptions options, IDocumentAdapter documentAdapter, ArgumentGuard.NotNull(httpRequest); string requestBody = await ReceiveRequestBodyAsync(httpRequest); - string method = httpRequest.Method.Replace(Environment.NewLine, ""); - _traceWriter.LogMessage(() => $"Received {method} request at '{httpRequest.GetEncodedUrl()}' with body: <<{requestBody}>>"); + if (_logger.IsEnabled(LogLevel.Trace)) + { + string requestMethod = httpRequest.Method.Replace(Environment.NewLine, ""); + string requestUrl = httpRequest.GetEncodedUrl(); + LogRequest(requestMethod, requestUrl, requestBody); + } return GetModel(requestBody); } @@ -117,4 +120,8 @@ private void AssertHasDocument([SysNotNull] Document? document, string requestBo exception.SourcePointer, exception.StatusCode, exception); } } + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, + Message = "Received {RequestMethod} request at '{RequestUrl}' with body: <<{RequestBody}>>")] + private partial void LogRequest(string requestMethod, string requestUrl, string requestBody); } diff --git a/src/JsonApiDotNetCore/Serialization/Request/JsonInvalidAttributeInfo.cs b/src/JsonApiDotNetCore/Serialization/Request/JsonInvalidAttributeInfo.cs index ed0afee834..2fcb31daa1 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/JsonInvalidAttributeInfo.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/JsonInvalidAttributeInfo.cs @@ -16,7 +16,7 @@ internal sealed class JsonInvalidAttributeInfo public JsonInvalidAttributeInfo(string attributeName, Type attributeType, string? jsonValue, JsonValueKind jsonType) { - ArgumentGuard.NotNullNorEmpty(attributeName); + ArgumentGuard.NotNull(attributeName); ArgumentGuard.NotNull(attributeType); AttributeName = attributeName; diff --git a/src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs b/src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs index 9a4e8869e7..57d166ee36 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs @@ -11,12 +11,13 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; namespace JsonApiDotNetCore.Serialization.Response; /// -public sealed class JsonApiWriter : IJsonApiWriter +public sealed partial class JsonApiWriter : IJsonApiWriter { private static readonly MediaTypeHeaderValue OperationsMediaType = MediaTypeHeaderValue.Parse(HeaderConstants.AtomicOperationsMediaType); private static readonly MediaTypeHeaderValue RelaxedOperationsMediaType = MediaTypeHeaderValue.Parse(HeaderConstants.RelaxedAtomicOperationsMediaType); @@ -32,24 +33,24 @@ public sealed class JsonApiWriter : IJsonApiWriter private readonly IResponseModelAdapter _responseModelAdapter; private readonly IExceptionHandler _exceptionHandler; private readonly IETagGenerator _eTagGenerator; - private readonly TraceLogWriter _traceWriter; + private readonly ILogger _logger; public JsonApiWriter(IJsonApiRequest request, IJsonApiOptions options, IResponseModelAdapter responseModelAdapter, IExceptionHandler exceptionHandler, - IETagGenerator eTagGenerator, ILoggerFactory loggerFactory) + IETagGenerator eTagGenerator, ILogger logger) { ArgumentGuard.NotNull(request); ArgumentGuard.NotNull(responseModelAdapter); ArgumentGuard.NotNull(exceptionHandler); ArgumentGuard.NotNull(eTagGenerator); ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(loggerFactory); + ArgumentGuard.NotNull(logger); _request = request; _options = options; _responseModelAdapter = responseModelAdapter; _exceptionHandler = exceptionHandler; _eTagGenerator = eTagGenerator; - _traceWriter = new TraceLogWriter(loggerFactory); + _logger = logger; } /// @@ -71,13 +72,12 @@ public async Task WriteAsync(object? model, HttpContext httpContext) return; } - _traceWriter.LogMessage(() => + if (_logger.IsEnabled(LogLevel.Trace)) { - string method = httpContext.Request.Method.Replace(Environment.NewLine, ""); - string url = httpContext.Request.GetEncodedUrl(); - - return $"Sending {httpContext.Response.StatusCode} response for {method} request at '{url}' with body: <<{responseBody}>>"; - }); + string requestMethod = httpContext.Request.Method.Replace(Environment.NewLine, ""); + string requestUrl = httpContext.Request.GetEncodedUrl(); + LogResponse(requestMethod, requestUrl, responseBody, httpContext.Response.StatusCode); + } string responseContentType = GetResponseContentType(httpContext.Request); await SendResponseBodyAsync(httpContext.Response, responseBody, responseContentType); @@ -162,8 +162,8 @@ private bool SetETagResponseHeader(HttpRequest request, HttpResponse response, s private static bool RequestContainsMatchingETag(IHeaderDictionary requestHeaders, EntityTagHeaderValue responseETag) { - if (requestHeaders.Keys.Contains(HeaderNames.IfNoneMatch) && - EntityTagHeaderValue.TryParseList(requestHeaders[HeaderNames.IfNoneMatch], out IList? requestETags)) + if (requestHeaders.TryGetValue(HeaderNames.IfNoneMatch, out StringValues headerValues) && + EntityTagHeaderValue.TryParseList(headerValues, out IList? requestETags)) { foreach (EntityTagHeaderValue requestETag in requestETags) { @@ -223,4 +223,8 @@ private async Task SendResponseBodyAsync(HttpResponse httpResponse, string? resp await writer.FlushAsync(); } } + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, + Message = "Sending {ResponseStatusCode} response for {RequestMethod} request at '{RequestUrl}' with body: <<{ResponseBody}>>")] + private partial void LogResponse(string requestMethod, string requestUrl, string? responseBody, int responseStatusCode); } diff --git a/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs b/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs index 27cf775d70..6d85052177 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs @@ -189,7 +189,7 @@ private void SetPaginationInTopLevelLinks(ResourceType resourceType, TopLevelLin string parameterValue = string.Join(',', elements.Select(expression => expression.Scope == null ? expression.Value.ToString() : $"{expression.Scope}:{expression.Value}")); - return parameterValue == string.Empty ? null : parameterValue; + return parameterValue.Length == 0 ? null : parameterValue; } private IImmutableList ParsePageSizeExpression(string? pageSizeParameterValue, ResourceType resourceType) @@ -219,7 +219,7 @@ private string GetLinkForPagination(int pageOffset, string? pageSizeValue) private string GetQueryStringInPaginationLink(int pageOffset, string? pageSizeValue) { - IDictionary parameters = HttpContext.Request.Query.ToDictionary(pair => pair.Key, pair => (string?)pair.Value.ToString()); + Dictionary parameters = HttpContext.Request.Query.ToDictionary(pair => pair.Key, pair => (string?)pair.Value.ToString()); if (pageSizeValue == null) { @@ -275,7 +275,7 @@ private bool ShouldIncludeResourceLink(LinkTypes linkType, ResourceType resource private string? GetLinkForResourceSelf(ResourceType resourceType, IIdentifiable resource) { string? controllerName = _controllerResourceMapping.GetControllerNameForResourceType(resourceType); - IDictionary routeValues = GetRouteValues(resource.StringId!, null); + RouteValueDictionary routeValues = GetRouteValues(resource.StringId!, null); return RenderLinkForAction(controllerName, GetPrimaryControllerActionName, routeValues); } @@ -304,7 +304,7 @@ private bool ShouldIncludeResourceLink(LinkTypes linkType, ResourceType resource private string? GetLinkForRelationshipSelf(string leftId, RelationshipAttribute relationship) { string? controllerName = _controllerResourceMapping.GetControllerNameForResourceType(relationship.LeftType); - IDictionary routeValues = GetRouteValues(leftId, relationship.PublicName); + RouteValueDictionary routeValues = GetRouteValues(leftId, relationship.PublicName); return RenderLinkForAction(controllerName, GetRelationshipControllerActionName, routeValues); } @@ -312,12 +312,12 @@ private bool ShouldIncludeResourceLink(LinkTypes linkType, ResourceType resource private string? GetLinkForRelationshipRelated(string leftId, RelationshipAttribute relationship) { string? controllerName = _controllerResourceMapping.GetControllerNameForResourceType(relationship.LeftType); - IDictionary routeValues = GetRouteValues(leftId, relationship.PublicName); + RouteValueDictionary routeValues = GetRouteValues(leftId, relationship.PublicName); return RenderLinkForAction(controllerName, GetSecondaryControllerActionName, routeValues); } - private IDictionary GetRouteValues(string primaryId, string? relationshipName) + private RouteValueDictionary GetRouteValues(string primaryId, string? relationshipName) { // By default, we copy all route parameters from the *current* endpoint, which helps in case all endpoints have the same // set of non-standard parameters. There is no way we can know which non-standard parameters a *different* endpoint needs, @@ -332,6 +332,9 @@ private bool ShouldIncludeResourceLink(LinkTypes linkType, ResourceType resource protected virtual string? RenderLinkForAction(string? controllerName, string actionName, IDictionary routeValues) { + ArgumentGuard.NotNull(actionName); + ArgumentGuard.NotNull(routeValues); + if (controllerName == null) { // When passing null to LinkGenerator, it uses the controller for the current endpoint. This is incorrect for diff --git a/src/JsonApiDotNetCore/Serialization/Response/MetaBuilder.cs b/src/JsonApiDotNetCore/Serialization/Response/MetaBuilder.cs index a5e647c853..cafe2fad52 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/MetaBuilder.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/MetaBuilder.cs @@ -50,6 +50,6 @@ public void Add(IDictionary values) Add(extraMeta); } - return _meta.Any() ? _meta : null; + return _meta.Count > 0 ? _meta : null; } } diff --git a/src/JsonApiDotNetCore/Serialization/Response/ResourceObjectTreeNode.cs b/src/JsonApiDotNetCore/Serialization/Response/ResourceObjectTreeNode.cs index ab50d6f674..e6b61527b2 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/ResourceObjectTreeNode.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/ResourceObjectTreeNode.cs @@ -92,11 +92,11 @@ public IReadOnlySet GetUniqueNodes() { AssertIsTreeRoot(); - var visited = new HashSet(); + HashSet visited = []; VisitSubtree(this, visited); - return visited; + return visited.AsReadOnly(); } private static void VisitSubtree(ResourceObjectTreeNode treeNode, ISet visited) @@ -151,7 +151,7 @@ private static void VisitRelationshipChildInSubtree(HashSet? GetRightNodesInRelationship(RelationshipAttribute relationship) { return _childrenByRelationship != null && _childrenByRelationship.TryGetValue(relationship, out HashSet? rightNodes) - ? rightNodes + ? rightNodes.AsReadOnly() : null; } @@ -162,7 +162,7 @@ public IReadOnlyList GetResponseData() { AssertIsTreeRoot(); - return GetDirectChildren().Select(child => child.ResourceObject).ToArray(); + return GetDirectChildren().Select(child => child.ResourceObject).ToArray().AsReadOnly(); } /// @@ -174,14 +174,14 @@ public IList GetResponseIncluded() { AssertIsTreeRoot(); - var visited = new HashSet(); + HashSet visited = []; foreach (ResourceObjectTreeNode child in GetDirectChildren()) { VisitRelationshipChildrenInSubtree(child, visited); } - ISet primaryResourceObjectSet = GetDirectChildren().Select(node => node.ResourceObject).ToHashSet(ResourceObjectComparer.Instance); + HashSet primaryResourceObjectSet = GetDirectChildren().Select(node => node.ResourceObject).ToHashSet(ResourceObjectComparer.Instance); List includes = []; foreach (ResourceObject include in visited.Select(node => node.ResourceObject)) @@ -210,7 +210,7 @@ private void AssertIsTreeRoot() public bool Equals(ResourceObjectTreeNode? other) { - if (ReferenceEquals(null, other)) + if (other is null) { return false; } diff --git a/src/JsonApiDotNetCore/Serialization/Response/ResponseModelAdapter.cs b/src/JsonApiDotNetCore/Serialization/Response/ResponseModelAdapter.cs index 9457b05502..0e4e605d96 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/ResponseModelAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/ResponseModelAdapter.cs @@ -103,11 +103,12 @@ public Document Convert(object? model) } else if (model is IEnumerable errorObjects) { - document.Errors = errorObjects.ToArray(); + document.Errors = errorObjects.ToList(); } else if (model is ErrorObject errorObject) { - document.Errors = [errorObject]; + List errors = [errorObject]; + document.Errors = errors; } else { @@ -124,6 +125,8 @@ public Document Convert(object? model) protected virtual AtomicResultObject ConvertOperation(OperationContainer? operation, IImmutableSet includeElements) { + ArgumentGuard.NotNull(includeElements); + ResourceObject? resourceObject = null; if (operation != null) @@ -205,6 +208,9 @@ private static ResourceType GetEffectiveResourceType(IIdentifiable resource, Res protected virtual ResourceObject ConvertResource(IIdentifiable resource, ResourceType resourceType, EndpointKind kind) { + ArgumentGuard.NotNull(resource); + ArgumentGuard.NotNull(resourceType); + bool isRelationship = kind == EndpointKind.Relationship; if (!isRelationship) @@ -235,6 +241,10 @@ protected virtual ResourceObject ConvertResource(IIdentifiable resource, Resourc #pragma warning restore AV1130 // Return type in method signature should be an interface to an unchangeable collection IImmutableSet fieldSet) { + ArgumentGuard.NotNull(resource); + ArgumentGuard.NotNull(resourceType); + ArgumentGuard.NotNull(fieldSet); + var attrMap = new Dictionary(resourceType.Attributes.Count); foreach (AttrAttribute attr in resourceType.Attributes) @@ -260,7 +270,7 @@ protected virtual ResourceObject ConvertResource(IIdentifiable resource, Resourc attrMap.Add(attr.PublicName, value); } - return attrMap.Any() ? attrMap : null; + return attrMap.Count > 0 ? attrMap : null; } private void TraverseRelationships(IIdentifiable leftResource, ResourceObjectTreeNode leftTreeNode, IImmutableSet includeElements, @@ -393,7 +403,7 @@ private static SingleOrManyData GetRelationshipData(Re { IList resourceObjects = rootNode.GetResponseIncluded(); - if (resourceObjects.Any()) + if (resourceObjects.Count > 0) { return resourceObjects; } diff --git a/src/JsonApiDotNetCore/Serialization/Response/UriNormalizer.cs b/src/JsonApiDotNetCore/Serialization/Response/UriNormalizer.cs index 5b2517f4b0..f0d9a7400d 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/UriNormalizer.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/UriNormalizer.cs @@ -70,11 +70,6 @@ private static bool AreSameServer(Uri left, Uri right) string leftUserInfo = left.GetComponents(UriComponents.UserInfo, UriFormat.UriEscaped); string rightUserInfo = right.GetComponents(UriComponents.UserInfo, UriFormat.UriEscaped); - if (!string.Equals(leftUserInfo, rightUserInfo)) - { - return false; - } - - return true; + return leftUserInfo == rightUserInfo; } } diff --git a/src/JsonApiDotNetCore/Services/AsyncCollectionExtensions.cs b/src/JsonApiDotNetCore/Services/AsyncCollectionExtensions.cs index 11e483b419..31dc56bbec 100644 --- a/src/JsonApiDotNetCore/Services/AsyncCollectionExtensions.cs +++ b/src/JsonApiDotNetCore/Services/AsyncCollectionExtensions.cs @@ -20,7 +20,7 @@ public static async Task> ToListAsync(this IAsyncEnumerable source { ArgumentGuard.NotNull(source); - var list = new List(); + List list = []; await foreach (T element in source.WithCancellation(cancellationToken)) { diff --git a/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs b/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs index 478d38ab72..2fc11684fc 100644 --- a/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs +++ b/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs @@ -109,6 +109,7 @@ public virtual async Task GetAsync([DisallowNull] TId id, Cancellatio using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Get secondary resource(s)"); + ArgumentGuard.NotNull(relationshipName); AssertPrimaryResourceTypeInJsonApiRequestIsNotNull(_request.PrimaryResourceType); AssertHasRelationship(_request.Relationship, relationshipName); @@ -146,10 +147,9 @@ public virtual async Task GetAsync([DisallowNull] TId id, Cancellatio relationshipName }); - ArgumentGuard.NotNullNorEmpty(relationshipName); - using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Get relationship"); + ArgumentGuard.NotNull(relationshipName); AssertPrimaryResourceTypeInJsonApiRequestIsNotNull(_request.PrimaryResourceType); AssertHasRelationship(_request.Relationship, relationshipName); @@ -238,6 +238,8 @@ private async Task RetrieveResourceCountForNonPrimaryEndpointAsync([DisallowNull protected async Task AssertPrimaryResourceDoesNotExistAsync(TResource resource, CancellationToken cancellationToken) { + ArgumentGuard.NotNull(resource); + if (!Equals(resource.Id, default(TId))) { TResource? existingResource = await GetPrimaryResourceByIdOrDefaultAsync(resource.Id!, TopFieldSelection.OnlyIdAttribute, cancellationToken); @@ -251,6 +253,8 @@ protected async Task AssertPrimaryResourceDoesNotExistAsync(TResource resource, protected virtual async Task InitializeResourceAsync(TResource resourceForDatabase, CancellationToken cancellationToken) { + ArgumentGuard.NotNull(resourceForDatabase); + await _resourceDefinitionAccessor.OnPrepareWriteAsync(resourceForDatabase, WriteOperationKind.CreateResource, cancellationToken); } @@ -261,13 +265,15 @@ private async Task AccurizeResourceTypesInHierarchyToAssignInRelationshipsAsync( protected async Task AssertResourcesToAssignInRelationshipsExistAsync(TResource primaryResource, CancellationToken cancellationToken) { + ArgumentGuard.NotNull(primaryResource); + await ValidateResourcesToAssignInRelationshipsExistWithRefreshAsync(primaryResource, false, cancellationToken); } private async Task ValidateResourcesToAssignInRelationshipsExistWithRefreshAsync(TResource primaryResource, bool onlyIfTypeHierarchy, CancellationToken cancellationToken) { - var missingResources = new List(); + List missingResources = []; foreach ((QueryLayer queryLayer, RelationshipAttribute relationship) in _queryLayerComposer.ComposeForGetTargetedSecondaryResourceIds(primaryResource)) { @@ -276,7 +282,7 @@ private async Task ValidateResourcesToAssignInRelationshipsExistWithRefreshAsync object? rightValue = relationship.GetValue(primaryResource); HashSet rightResourceIds = _collectionConverter.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); - if (rightResourceIds.Any()) + if (rightResourceIds.Count > 0) { IAsyncEnumerable missingResourcesInRelationship = GetMissingRightResourcesAsync(queryLayer, relationship, rightResourceIds, cancellationToken); @@ -294,14 +300,14 @@ private async Task ValidateResourcesToAssignInRelationshipsExistWithRefreshAsync } } - if (missingResources.Any()) + if (missingResources.Count > 0) { throw new ResourcesInRelationshipsNotFoundException(missingResources); } } private async IAsyncEnumerable GetMissingRightResourcesAsync(QueryLayer existingRightResourceIdsQueryLayer, - RelationshipAttribute relationship, ISet rightResourceIds, [EnumeratorCancellation] CancellationToken cancellationToken) + RelationshipAttribute relationship, HashSet rightResourceIds, [EnumeratorCancellation] CancellationToken cancellationToken) { IReadOnlyCollection existingResources = await _repositoryAccessor.GetAsync(existingRightResourceIdsQueryLayer.ResourceType, existingRightResourceIdsQueryLayer, cancellationToken); @@ -344,16 +350,15 @@ public virtual async Task AddToToManyRelationshipAsync([DisallowNull] TId leftId rightResourceIds }); - ArgumentGuard.NotNullNorEmpty(relationshipName); - ArgumentGuard.NotNull(rightResourceIds); - using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Add to to-many relationship"); + ArgumentGuard.NotNull(relationshipName); + ArgumentGuard.NotNull(rightResourceIds); AssertHasRelationship(_request.Relationship, relationshipName); TResource? resourceFromDatabase = null; - if (rightResourceIds.Any() && _request.Relationship is HasManyAttribute { IsManyToMany: true } manyToManyRelationship) + if (rightResourceIds.Count > 0 && _request.Relationship is HasManyAttribute { IsManyToMany: true } manyToManyRelationship) { // In the case of a many-to-many relationship, creating a duplicate entry in the join table results in a // unique constraint violation. We avoid that by excluding already-existing entries from the set in advance. @@ -420,7 +425,7 @@ private async Task GetForHasManyUpdateAsync(HasManyAttribute hasManyR HashSet rightResourceIds = _collectionConverter.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); object? newRightValue = rightValue; - if (rightResourceIds.Any()) + if (rightResourceIds.Count > 0) { QueryLayer queryLayer = _queryLayerComposer.ComposeForGetRelationshipRightIds(_request.Relationship, rightResourceIds); @@ -433,7 +438,7 @@ private async Task GetForHasManyUpdateAsync(HasManyAttribute hasManyR ? rightResourceIds.FirstOrDefault() : _collectionConverter.CopyToTypedCollection(rightResourceIds, _request.Relationship.Property.PropertyType); - if (missingResources.Any()) + if (missingResources.Count > 0) { throw new ResourcesInRelationshipsNotFoundException(missingResources); } @@ -495,10 +500,9 @@ public virtual async Task SetRelationshipAsync([DisallowNull] TId leftId, string rightValue }); - ArgumentGuard.NotNullNorEmpty(relationshipName); - using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Set relationship"); + ArgumentGuard.NotNull(relationshipName); AssertHasRelationship(_request.Relationship, relationshipName); object? effectiveRightValue = _request.Relationship.RightType.IsPartOfTypeHierarchy() @@ -567,11 +571,10 @@ public virtual async Task RemoveFromToManyRelationshipAsync([DisallowNull] TId l rightResourceIds }); - ArgumentGuard.NotNullNorEmpty(relationshipName); - ArgumentGuard.NotNull(rightResourceIds); - using IDisposable _ = CodeTimingSessionManager.Current.Measure("Repository - Remove from to-many relationship"); + ArgumentGuard.NotNull(relationshipName); + ArgumentGuard.NotNull(rightResourceIds); AssertHasRelationship(_request.Relationship, relationshipName); var hasManyRelationship = (HasManyAttribute)_request.Relationship; diff --git a/test/DapperTests/IntegrationTests/AtomicOperations/AtomicOperationsTests.cs b/test/DapperTests/IntegrationTests/AtomicOperations/AtomicOperationsTests.cs index a3d665cc61..bec6919496 100644 --- a/test/DapperTests/IntegrationTests/AtomicOperations/AtomicOperationsTests.cs +++ b/test/DapperTests/IntegrationTests/AtomicOperations/AtomicOperationsTests.cs @@ -29,10 +29,10 @@ public async Task Can_use_multiple_operations() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person newOwner = _fakers.Person.Generate(); - Person newAssignee = _fakers.Person.Generate(); - Tag newTag = _fakers.Tag.Generate(); - TodoItem newTodoItem = _fakers.TodoItem.Generate(); + Person newOwner = _fakers.Person.GenerateOne(); + Person newAssignee = _fakers.Person.GenerateOne(); + Tag newTag = _fakers.Tag.GenerateOne(); + TodoItem newTodoItem = _fakers.TodoItem.GenerateOne(); const string ownerLocalId = "new-owner"; const string assigneeLocalId = "new-assignee"; @@ -415,16 +415,13 @@ public async Task Can_rollback_on_error() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person newPerson = _fakers.Person.Generate(); + Person newPerson = _fakers.Person.GenerateOne(); const long unknownTodoItemId = Unknown.TypedId.Int64; const string personLocalId = "new-person"; - await _testContext.RunOnDatabaseAsync(async dbContext => - { - await _testContext.ClearAllTablesAsync(dbContext); - }); + await _testContext.RunOnDatabaseAsync(_testContext.ClearAllTablesAsync); var requestBody = new { diff --git a/test/DapperTests/IntegrationTests/DapperTestContext.cs b/test/DapperTests/IntegrationTests/DapperTestContext.cs index 5817db099a..9fdc330c74 100644 --- a/test/DapperTests/IntegrationTests/DapperTestContext.cs +++ b/test/DapperTests/IntegrationTests/DapperTestContext.cs @@ -52,7 +52,10 @@ public DapperTestContext() private WebApplicationFactory CreateFactory() { +#pragma warning disable CA2000 // Dispose objects before losing scope + // Justification: The child factory returned by WithWebHostBuilder() is owned by the parent factory, which disposes it. return new WebApplicationFactory().WithWebHostBuilder(builder => +#pragma warning restore CA2000 // Dispose objects before losing scope { builder.UseSetting("ConnectionStrings:DapperExamplePostgreSql", $"Host=localhost;Database=DapperExample-{Guid.NewGuid():N};User ID=postgres;Password=postgres;Include Error Detail=true"); @@ -119,10 +122,14 @@ public async Task ClearAllTablesAsync(DbContext dbContext) _ => throw new NotSupportedException($"Unsupported database provider '{databaseProvider}'.") }; +#if !NET6_0 #pragma warning disable EF1002 // Risk of vulnerability to SQL injection. +#endif // Justification: Table names cannot be parameterized. await dbContext.Database.ExecuteSqlRawAsync($"DELETE FROM {escapedTableName}"); +#if !NET6_0 #pragma warning restore EF1002 // Risk of vulnerability to SQL injection. +#endif } } } diff --git a/test/DapperTests/IntegrationTests/QueryStrings/FilterTests.cs b/test/DapperTests/IntegrationTests/QueryStrings/FilterTests.cs index 56bfdd5a7c..03ebd81bd9 100644 --- a/test/DapperTests/IntegrationTests/QueryStrings/FilterTests.cs +++ b/test/DapperTests/IntegrationTests/QueryStrings/FilterTests.cs @@ -28,8 +28,8 @@ public async Task Can_filter_equals_on_obfuscated_id_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List tags = _fakers.Tag.Generate(3); - tags.ForEach(tag => tag.Color = _fakers.RgbColor.Generate()); + List tags = _fakers.Tag.GenerateList(3); + tags.ForEach(tag => tag.Color = _fakers.RgbColor.GenerateOne()); tags[0].Color!.StringId = "FF0000"; tags[1].Color!.StringId = "00FF00"; @@ -93,8 +93,8 @@ public async Task Can_filter_any_on_obfuscated_id_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List tags = _fakers.Tag.Generate(3); - tags.ForEach(tag => tag.Color = _fakers.RgbColor.Generate()); + List tags = _fakers.Tag.GenerateList(3); + tags.ForEach(tag => tag.Color = _fakers.RgbColor.GenerateOne()); tags[0].Color!.StringId = "FF0000"; tags[1].Color!.StringId = "00FF00"; @@ -160,9 +160,9 @@ public async Task Can_filter_equals_null_on_relationship_at_secondary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); - person.OwnedTodoItems.ElementAt(0).Assignee = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(2); + person.OwnedTodoItems.ElementAt(0).Assignee = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -227,8 +227,8 @@ public async Task Can_filter_equals_null_on_attribute_at_secondary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(2); person.OwnedTodoItems.ElementAt(1).DurationInHours = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -292,8 +292,8 @@ public async Task Can_filter_equals_on_enum_attribute_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(3); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(3); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); todoItems.ForEach(todoItem => todoItem.Priority = TodoItemPriority.Low); todoItems[1].Priority = TodoItemPriority.Medium; @@ -354,9 +354,9 @@ public async Task Can_filter_equals_on_string_attribute_at_secondary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.AssignedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); - person.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + Person person = _fakers.Person.GenerateOne(); + person.AssignedTodoItems = _fakers.TodoItem.GenerateSet(2); + person.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); person.AssignedTodoItems.ElementAt(1).Description = "Take exam"; @@ -424,9 +424,9 @@ public async Task Can_filter_equality_on_attributes_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(2); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); - todoItems.ForEach(todoItem => todoItem.Assignee = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(2); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); + todoItems.ForEach(todoItem => todoItem.Assignee = _fakers.Person.GenerateOne()); todoItems[1].Assignee!.FirstName = todoItems[1].Assignee!.LastName; @@ -486,8 +486,8 @@ public async Task Can_filter_any_with_single_constant_at_secondary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(2); person.OwnedTodoItems.ElementAt(0).Priority = TodoItemPriority.Low; person.OwnedTodoItems.ElementAt(1).Priority = TodoItemPriority.Medium; @@ -555,9 +555,9 @@ public async Task Can_filter_not_not_not_not_equals_on_string_attribute_at_prima var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); todoItem.Description = "X"; - todoItem.Owner = _fakers.Person.Generate(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -615,7 +615,7 @@ public async Task Can_filter_not_equals_on_nullable_attribute_at_primary_endpoin var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List people = _fakers.Person.Generate(3); + List people = _fakers.Person.GenerateList(3); people[0].FirstName = "X"; people[1].FirstName = null; people[2].FirstName = "Y"; @@ -677,10 +677,10 @@ public async Task Can_filter_not_equals_on_attributes_of_optional_relationship_a var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(2); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(2); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); - todoItems[1].Assignee = _fakers.Person.Generate(); + todoItems[1].Assignee = _fakers.Person.GenerateOne(); todoItems[1].Assignee!.FirstName = "X"; todoItems[1].Assignee!.LastName = "Y"; @@ -744,8 +744,8 @@ public async Task Can_filter_text_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(3); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(3); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); todoItems[0].Description = "One"; todoItems[1].Description = "Two"; @@ -815,7 +815,7 @@ public async Task Can_filter_special_characters_in_text_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List tags = _fakers.Tag.Generate(6); + List tags = _fakers.Tag.GenerateList(6); tags[0].Name = "A%Z"; tags[1].Name = "A_Z"; tags[2].Name = @"A\Z"; @@ -881,8 +881,8 @@ public async Task Can_filter_numeric_range_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(3); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(3); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); todoItems[0].DurationInHours = 100; todoItems[1].DurationInHours = 200; @@ -947,11 +947,11 @@ public async Task Can_filter_count_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(2); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(2); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); - todoItems[1].Owner.AssignedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); - todoItems[1].Owner.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + todoItems[1].Owner.AssignedTodoItems = _fakers.TodoItem.GenerateSet(2); + todoItems[1].Owner.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1021,17 +1021,17 @@ public async Task Can_filter_nested_conditional_has_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(2); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(2); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); - todoItems[1].Owner.AssignedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); + todoItems[1].Owner.AssignedTodoItems = _fakers.TodoItem.GenerateSet(2); todoItems[1].Owner.AssignedTodoItems.ForEach(todoItem => { todoItem.Description = "Homework"; - todoItem.Owner = _fakers.Person.Generate(); + todoItem.Owner = _fakers.Person.GenerateOne(); todoItem.Owner.LastName = "Smith"; - todoItem.Tags = _fakers.Tag.Generate(1).ToHashSet(); + todoItem.Tags = _fakers.Tag.GenerateSet(1); }); todoItems[1].Owner.AssignedTodoItems.ElementAt(1).Tags.ElementAt(0).Name = "Personal"; @@ -1117,14 +1117,14 @@ public async Task Can_filter_conditional_has_with_null_check_at_primary_endpoint var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List people = _fakers.Person.Generate(3); - people.ForEach(person => person.OwnedTodoItems = _fakers.TodoItem.Generate(1).ToHashSet()); + List people = _fakers.Person.GenerateList(3); + people.ForEach(person => person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(1)); people[0].OwnedTodoItems.ElementAt(0).Assignee = null; - people[1].OwnedTodoItems.ElementAt(0).Assignee = _fakers.Person.Generate(); + people[1].OwnedTodoItems.ElementAt(0).Assignee = _fakers.Person.GenerateOne(); - people[2].OwnedTodoItems.ElementAt(0).Assignee = _fakers.Person.Generate(); + people[2].OwnedTodoItems.ElementAt(0).Assignee = _fakers.Person.GenerateOne(); people[2].OwnedTodoItems.ElementAt(0).Assignee!.FirstName = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -1191,8 +1191,8 @@ public async Task Can_filter_using_logical_operators_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(5); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(5); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); todoItems[0].Description = "0"; todoItems[0].Priority = TodoItemPriority.High; @@ -1276,7 +1276,7 @@ public async Task Cannot_filter_on_unmapped_attribute() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/QueryStrings/IncludeTests.cs b/test/DapperTests/IntegrationTests/QueryStrings/IncludeTests.cs index 09d307a256..a1f06cd736 100644 --- a/test/DapperTests/IntegrationTests/QueryStrings/IncludeTests.cs +++ b/test/DapperTests/IntegrationTests/QueryStrings/IncludeTests.cs @@ -28,12 +28,12 @@ public async Task Can_get_primary_resources_with_multiple_include_chains() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person owner = _fakers.Person.Generate(); + Person owner = _fakers.Person.GenerateOne(); - List todoItems = _fakers.TodoItem.Generate(2); + List todoItems = _fakers.TodoItem.GenerateList(2); todoItems.ForEach(todoItem => todoItem.Owner = owner); - todoItems.ForEach(todoItem => todoItem.Tags = _fakers.Tag.Generate(2).ToHashSet()); - todoItems[1].Assignee = _fakers.Person.Generate(); + todoItems.ForEach(todoItem => todoItem.Tags = _fakers.Tag.GenerateSet(2)); + todoItems[1].Assignee = _fakers.Person.GenerateOne(); todoItems[0].Priority = TodoItemPriority.High; todoItems[1].Priority = TodoItemPriority.Low; @@ -179,10 +179,10 @@ public async Task Can_get_primary_resources_with_includes() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(25); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); - todoItems.ForEach(todoItem => todoItem.Tags = _fakers.Tag.Generate(15).ToHashSet()); - todoItems.ForEach(todoItem => todoItem.Tags.ForEach(tag => tag.Color = _fakers.RgbColor.Generate())); + List todoItems = _fakers.TodoItem.GenerateList(25); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); + todoItems.ForEach(todoItem => todoItem.Tags = _fakers.Tag.GenerateSet(15)); + todoItems.ForEach(todoItem => todoItem.Tags.ForEach(tag => tag.Color = _fakers.RgbColor.GenerateOne())); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/QueryStrings/PaginationTests.cs b/test/DapperTests/IntegrationTests/QueryStrings/PaginationTests.cs index 137ba693f0..e87469cfbf 100644 --- a/test/DapperTests/IntegrationTests/QueryStrings/PaginationTests.cs +++ b/test/DapperTests/IntegrationTests/QueryStrings/PaginationTests.cs @@ -23,8 +23,8 @@ public PaginationTests(DapperTestContext testContext, ITestOutputHelper testOutp public async Task Cannot_use_pagination() { // Arrange - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/QueryStrings/SortTests.cs b/test/DapperTests/IntegrationTests/QueryStrings/SortTests.cs index 33643519ce..6a66d5e7e3 100644 --- a/test/DapperTests/IntegrationTests/QueryStrings/SortTests.cs +++ b/test/DapperTests/IntegrationTests/QueryStrings/SortTests.cs @@ -28,8 +28,8 @@ public async Task Can_sort_on_attributes_in_primary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(3); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(3); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); todoItems[0].Description = "B"; todoItems[1].Description = "A"; @@ -87,14 +87,14 @@ public async Task Can_sort_on_attributes_in_secondary_and_included_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(3).ToHashSet(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(3); person.OwnedTodoItems.ElementAt(0).DurationInHours = 40; person.OwnedTodoItems.ElementAt(1).DurationInHours = 100; person.OwnedTodoItems.ElementAt(2).DurationInHours = 250; - person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.Generate(2).ToHashSet(); + person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.GenerateSet(2); person.OwnedTodoItems.ElementAt(1).Tags.ElementAt(0).Name = "B"; person.OwnedTodoItems.ElementAt(1).Tags.ElementAt(1).Name = "A"; @@ -162,12 +162,12 @@ public async Task Can_sort_on_count_in_primary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(3); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(3); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); - todoItems[0].Tags = _fakers.Tag.Generate(2).ToHashSet(); - todoItems[1].Tags = _fakers.Tag.Generate(1).ToHashSet(); - todoItems[2].Tags = _fakers.Tag.Generate(3).ToHashSet(); + todoItems[0].Tags = _fakers.Tag.GenerateSet(2); + todoItems[1].Tags = _fakers.Tag.GenerateSet(1); + todoItems[2].Tags = _fakers.Tag.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -225,12 +225,12 @@ public async Task Can_sort_on_count_in_secondary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(3).ToHashSet(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(3); - person.OwnedTodoItems.ElementAt(0).Tags = _fakers.Tag.Generate(2).ToHashSet(); - person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.Generate(1).ToHashSet(); - person.OwnedTodoItems.ElementAt(2).Tags = _fakers.Tag.Generate(3).ToHashSet(); + person.OwnedTodoItems.ElementAt(0).Tags = _fakers.Tag.GenerateSet(2); + person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.GenerateSet(1); + person.OwnedTodoItems.ElementAt(2).Tags = _fakers.Tag.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -294,12 +294,12 @@ public async Task Can_sort_on_count_in_secondary_resources_with_include() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(3).ToHashSet(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(3); - person.OwnedTodoItems.ElementAt(0).Tags = _fakers.Tag.Generate(2).ToHashSet(); - person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.Generate(1).ToHashSet(); - person.OwnedTodoItems.ElementAt(2).Tags = _fakers.Tag.Generate(3).ToHashSet(); + person.OwnedTodoItems.ElementAt(0).Tags = _fakers.Tag.GenerateSet(2); + person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.GenerateSet(1); + person.OwnedTodoItems.ElementAt(2).Tags = _fakers.Tag.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -364,12 +364,12 @@ public async Task Can_sort_on_count_in_included_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(4).ToHashSet(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(4); - person.OwnedTodoItems.ElementAt(0).Tags = _fakers.Tag.Generate(2).ToHashSet(); - person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.Generate(1).ToHashSet(); - person.OwnedTodoItems.ElementAt(2).Tags = _fakers.Tag.Generate(3).ToHashSet(); + person.OwnedTodoItems.ElementAt(0).Tags = _fakers.Tag.GenerateSet(2); + person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.GenerateSet(1); + person.OwnedTodoItems.ElementAt(2).Tags = _fakers.Tag.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/QueryStrings/SparseFieldSets.cs b/test/DapperTests/IntegrationTests/QueryStrings/SparseFieldSets.cs index e66616810e..af09f014a2 100644 --- a/test/DapperTests/IntegrationTests/QueryStrings/SparseFieldSets.cs +++ b/test/DapperTests/IntegrationTests/QueryStrings/SparseFieldSets.cs @@ -28,9 +28,9 @@ public async Task Can_select_fields_in_primary_and_included_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); - todoItem.Assignee = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); + todoItem.Assignee = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -117,8 +117,8 @@ public async Task Can_select_attribute_in_primary_resource() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -163,9 +163,9 @@ public async Task Can_select_relationship_in_secondary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); - todoItem.Tags = _fakers.Tag.Generate(1).ToHashSet(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); + todoItem.Tags = _fakers.Tag.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -230,7 +230,7 @@ public async Task Can_select_ID() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -274,7 +274,7 @@ public async Task Can_select_empty_fieldset() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -318,7 +318,7 @@ public async Task Fetches_all_scalar_properties_when_fieldset_contains_readonly_ var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -363,9 +363,9 @@ public async Task Returns_related_resources_on_broken_resource_linkage() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); - todoItem.Tags = _fakers.Tag.Generate(2).ToHashSet(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); + todoItem.Tags = _fakers.Tag.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/AddToToManyRelationshipTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/AddToToManyRelationshipTests.cs index e6c49c1f62..2bf6277f10 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/AddToToManyRelationshipTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/AddToToManyRelationshipTests.cs @@ -28,11 +28,11 @@ public async Task Can_add_to_OneToMany_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.OwnedTodoItems = _fakers.TodoItem.Generate(1).ToHashSet(); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.OwnedTodoItems = _fakers.TodoItem.GenerateSet(1); - List existingTodoItems = _fakers.TodoItem.Generate(2); - existingTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List existingTodoItems = _fakers.TodoItem.GenerateList(2); + existingTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/FetchRelationshipTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/FetchRelationshipTests.cs index 227bbdb755..949494e5f0 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/FetchRelationshipTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/FetchRelationshipTests.cs @@ -28,8 +28,8 @@ public async Task Can_get_ToOne_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -75,8 +75,8 @@ public async Task Can_get_empty_ToOne_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -120,9 +120,9 @@ public async Task Can_get_ToMany_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); - todoItem.Tags = _fakers.Tag.Generate(2).ToHashSet(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); + todoItem.Tags = _fakers.Tag.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/RemoveFromToManyRelationshipTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/RemoveFromToManyRelationshipTests.cs index f31a89c73e..82dace581f 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/RemoveFromToManyRelationshipTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/RemoveFromToManyRelationshipTests.cs @@ -28,9 +28,9 @@ public async Task Can_remove_from_OneToMany_relationship_with_nullable_foreign_k var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.AssignedTodoItems = _fakers.TodoItem.Generate(3).ToHashSet(); - existingPerson.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.AssignedTodoItems = _fakers.TodoItem.GenerateSet(3); + existingPerson.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -134,8 +134,8 @@ public async Task Can_remove_from_OneToMany_relationship_with_required_foreign_k var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.OwnedTodoItems = _fakers.TodoItem.Generate(3).ToHashSet(); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.OwnedTodoItems = _fakers.TodoItem.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/ReplaceToManyRelationshipTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/ReplaceToManyRelationshipTests.cs index 05b0710132..d2a4d0865a 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/ReplaceToManyRelationshipTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/ReplaceToManyRelationshipTests.cs @@ -27,9 +27,9 @@ public async Task Can_clear_OneToMany_relationship_with_nullable_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.AssignedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); - existingPerson.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.AssignedTodoItems = _fakers.TodoItem.GenerateSet(2); + existingPerson.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -95,9 +95,9 @@ public async Task Can_clear_OneToMany_relationship_with_required_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.OwnedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); - existingPerson.OwnedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.OwnedTodoItems = _fakers.TodoItem.GenerateSet(2); + existingPerson.OwnedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -161,10 +161,10 @@ public async Task Can_create_OneToMany_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); - List existingTodoItems = _fakers.TodoItem.Generate(2); - existingTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List existingTodoItems = _fakers.TodoItem.GenerateList(2); + existingTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -245,12 +245,12 @@ public async Task Can_replace_OneToMany_relationship_with_nullable_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.AssignedTodoItems = _fakers.TodoItem.Generate(1).ToHashSet(); - existingPerson.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.AssignedTodoItems = _fakers.TodoItem.GenerateSet(1); + existingPerson.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -336,12 +336,12 @@ public async Task Can_replace_OneToMany_relationship_with_required_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.OwnedTodoItems = _fakers.TodoItem.Generate(1).ToHashSet(); - existingPerson.OwnedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.OwnedTodoItems = _fakers.TodoItem.GenerateSet(1); + existingPerson.OwnedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/UpdateToOneRelationshipTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/UpdateToOneRelationshipTests.cs index e42efaf2e1..5f3b2ad0fb 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/UpdateToOneRelationshipTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/UpdateToOneRelationshipTests.cs @@ -28,9 +28,9 @@ public async Task Can_clear_OneToOne_relationship_with_nullable_foreign_key_at_l var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.Account = _fakers.LoginAccount.Generate(); - existingPerson.Account.Recovery = _fakers.AccountRecovery.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.Account = _fakers.LoginAccount.GenerateOne(); + existingPerson.Account.Recovery = _fakers.AccountRecovery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -100,9 +100,9 @@ public async Task Can_clear_OneToOne_relationship_with_nullable_foreign_key_at_r var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - LoginAccount existingLoginAccount = _fakers.LoginAccount.Generate(); - existingLoginAccount.Recovery = _fakers.AccountRecovery.Generate(); - existingLoginAccount.Person = _fakers.Person.Generate(); + LoginAccount existingLoginAccount = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount.Recovery = _fakers.AccountRecovery.GenerateOne(); + existingLoginAccount.Person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -172,8 +172,8 @@ public async Task Can_clear_OneToOne_relationship_with_nullable_foreign_key_at_r var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - LoginAccount existingLoginAccount = _fakers.LoginAccount.Generate(); - existingLoginAccount.Recovery = _fakers.AccountRecovery.Generate(); + LoginAccount existingLoginAccount = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount.Recovery = _fakers.AccountRecovery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -218,8 +218,8 @@ public async Task Cannot_clear_OneToOne_relationship_with_required_foreign_key_a var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - LoginAccount existingLoginAccount = _fakers.LoginAccount.Generate(); - existingLoginAccount.Recovery = _fakers.AccountRecovery.Generate(); + LoginAccount existingLoginAccount = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount.Recovery = _fakers.AccountRecovery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -270,8 +270,8 @@ public async Task Cannot_clear_OneToOne_relationship_with_required_foreign_key_a var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - AccountRecovery existingAccountRecovery = _fakers.AccountRecovery.Generate(); - existingAccountRecovery.Account = _fakers.LoginAccount.Generate(); + AccountRecovery existingAccountRecovery = _fakers.AccountRecovery.GenerateOne(); + existingAccountRecovery.Account = _fakers.LoginAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -322,9 +322,9 @@ public async Task Can_clear_ManyToOne_relationship_with_nullable_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); - existingTodoItem.Assignee = _fakers.Person.Generate(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); + existingTodoItem.Assignee = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -389,8 +389,8 @@ public async Task Cannot_clear_ManyToOne_relationship_with_required_foreign_key( var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -441,10 +441,10 @@ public async Task Can_create_OneToOne_relationship_with_nullable_foreign_key_at_ var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); - LoginAccount existingLoginAccount = _fakers.LoginAccount.Generate(); - existingLoginAccount.Recovery = _fakers.AccountRecovery.Generate(); + LoginAccount existingLoginAccount = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount.Recovery = _fakers.AccountRecovery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -527,10 +527,10 @@ public async Task Can_create_OneToOne_relationship_with_nullable_foreign_key_at_ var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - LoginAccount existingLoginAccount = _fakers.LoginAccount.Generate(); - existingLoginAccount.Recovery = _fakers.AccountRecovery.Generate(); + LoginAccount existingLoginAccount = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount.Recovery = _fakers.AccountRecovery.GenerateOne(); - Person existingPerson = _fakers.Person.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -601,10 +601,10 @@ public async Task Can_create_ManyToOne_relationship_with_nullable_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); - Person existingPerson = _fakers.Person.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -674,13 +674,13 @@ public async Task Can_replace_OneToOne_relationship_with_nullable_foreign_key_at var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson1 = _fakers.Person.Generate(); - existingPerson1.Account = _fakers.LoginAccount.Generate(); - existingPerson1.Account.Recovery = _fakers.AccountRecovery.Generate(); + Person existingPerson1 = _fakers.Person.GenerateOne(); + existingPerson1.Account = _fakers.LoginAccount.GenerateOne(); + existingPerson1.Account.Recovery = _fakers.AccountRecovery.GenerateOne(); - Person existingPerson2 = _fakers.Person.Generate(); - existingPerson2.Account = _fakers.LoginAccount.Generate(); - existingPerson2.Account.Recovery = _fakers.AccountRecovery.Generate(); + Person existingPerson2 = _fakers.Person.GenerateOne(); + existingPerson2.Account = _fakers.LoginAccount.GenerateOne(); + existingPerson2.Account.Recovery = _fakers.AccountRecovery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -767,13 +767,13 @@ public async Task Can_replace_OneToOne_relationship_with_nullable_foreign_key_at var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - LoginAccount existingLoginAccount1 = _fakers.LoginAccount.Generate(); - existingLoginAccount1.Recovery = _fakers.AccountRecovery.Generate(); - existingLoginAccount1.Person = _fakers.Person.Generate(); + LoginAccount existingLoginAccount1 = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount1.Recovery = _fakers.AccountRecovery.GenerateOne(); + existingLoginAccount1.Person = _fakers.Person.GenerateOne(); - LoginAccount existingLoginAccount2 = _fakers.LoginAccount.Generate(); - existingLoginAccount2.Recovery = _fakers.AccountRecovery.Generate(); - existingLoginAccount2.Person = _fakers.Person.Generate(); + LoginAccount existingLoginAccount2 = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount2.Recovery = _fakers.AccountRecovery.GenerateOne(); + existingLoginAccount2.Person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -862,11 +862,11 @@ public async Task Can_replace_OneToOne_relationship_with_required_foreign_key_at var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - LoginAccount existingLoginAccount1 = _fakers.LoginAccount.Generate(); - existingLoginAccount1.Recovery = _fakers.AccountRecovery.Generate(); + LoginAccount existingLoginAccount1 = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount1.Recovery = _fakers.AccountRecovery.GenerateOne(); - LoginAccount existingLoginAccount2 = _fakers.LoginAccount.Generate(); - existingLoginAccount2.Recovery = _fakers.AccountRecovery.Generate(); + LoginAccount existingLoginAccount2 = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount2.Recovery = _fakers.AccountRecovery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -953,11 +953,11 @@ public async Task Can_replace_OneToOne_relationship_with_required_foreign_key_at var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - AccountRecovery existingAccountRecovery1 = _fakers.AccountRecovery.Generate(); - existingAccountRecovery1.Account = _fakers.LoginAccount.Generate(); + AccountRecovery existingAccountRecovery1 = _fakers.AccountRecovery.GenerateOne(); + existingAccountRecovery1.Account = _fakers.LoginAccount.GenerateOne(); - AccountRecovery existingAccountRecovery2 = _fakers.AccountRecovery.Generate(); - existingAccountRecovery2.Account = _fakers.LoginAccount.Generate(); + AccountRecovery existingAccountRecovery2 = _fakers.AccountRecovery.GenerateOne(); + existingAccountRecovery2.Account = _fakers.LoginAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1044,13 +1044,13 @@ public async Task Can_replace_ManyToOne_relationship_with_nullable_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem1 = _fakers.TodoItem.Generate(); - existingTodoItem1.Owner = _fakers.Person.Generate(); - existingTodoItem1.Assignee = _fakers.Person.Generate(); + TodoItem existingTodoItem1 = _fakers.TodoItem.GenerateOne(); + existingTodoItem1.Owner = _fakers.Person.GenerateOne(); + existingTodoItem1.Assignee = _fakers.Person.GenerateOne(); - TodoItem existingTodoItem2 = _fakers.TodoItem.Generate(); - existingTodoItem2.Owner = _fakers.Person.Generate(); - existingTodoItem2.Assignee = _fakers.Person.Generate(); + TodoItem existingTodoItem2 = _fakers.TodoItem.GenerateOne(); + existingTodoItem2.Owner = _fakers.Person.GenerateOne(); + existingTodoItem2.Assignee = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1120,11 +1120,11 @@ public async Task Can_replace_ManyToOne_relationship_with_required_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem1 = _fakers.TodoItem.Generate(); - existingTodoItem1.Owner = _fakers.Person.Generate(); + TodoItem existingTodoItem1 = _fakers.TodoItem.GenerateOne(); + existingTodoItem1.Owner = _fakers.Person.GenerateOne(); - TodoItem existingTodoItem2 = _fakers.TodoItem.Generate(); - existingTodoItem2.Owner = _fakers.Person.Generate(); + TodoItem existingTodoItem2 = _fakers.TodoItem.GenerateOne(); + existingTodoItem2.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Resources/CreateResourceTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Resources/CreateResourceTests.cs index 199c8641e6..1f3a540315 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Resources/CreateResourceTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Resources/CreateResourceTests.cs @@ -29,10 +29,10 @@ public async Task Can_create_resource() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem newTodoItem = _fakers.TodoItem.Generate(); + TodoItem newTodoItem = _fakers.TodoItem.GenerateOne(); - Person existingPerson = _fakers.Person.Generate(); - Tag existingTag = _fakers.Tag.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); + Tag existingTag = _fakers.Tag.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -186,9 +186,9 @@ public async Task Can_create_resource_with_only_required_fields() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem newTodoItem = _fakers.TodoItem.Generate(); + TodoItem newTodoItem = _fakers.TodoItem.GenerateOne(); - Person existingPerson = _fakers.Person.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -357,10 +357,10 @@ public async Task Can_create_resource_with_unmapped_property() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - AccountRecovery existingAccountRecovery = _fakers.AccountRecovery.Generate(); - Person existingPerson = _fakers.Person.Generate(); + AccountRecovery existingAccountRecovery = _fakers.AccountRecovery.GenerateOne(); + Person existingPerson = _fakers.Person.GenerateOne(); - string newUserName = _fakers.LoginAccount.Generate().UserName; + string newUserName = _fakers.LoginAccount.GenerateOne().UserName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -497,7 +497,7 @@ public async Task Can_create_resource_with_calculated_attribute() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person newPerson = _fakers.Person.Generate(); + Person newPerson = _fakers.Person.GenerateOne(); var requestBody = new { @@ -574,9 +574,9 @@ public async Task Can_create_resource_with_client_generated_ID() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Tag existingTag = _fakers.Tag.Generate(); + Tag existingTag = _fakers.Tag.GenerateOne(); - RgbColor newColor = _fakers.RgbColor.Generate(); + RgbColor newColor = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -673,10 +673,10 @@ public async Task Cannot_create_resource_for_existing_client_generated_ID() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - RgbColor existingColor = _fakers.RgbColor.Generate(); - existingColor.Tag = _fakers.Tag.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); + existingColor.Tag = _fakers.Tag.GenerateOne(); - Tag existingTag = _fakers.Tag.Generate(); + Tag existingTag = _fakers.Tag.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Resources/DeleteResourceTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Resources/DeleteResourceTests.cs index af81d138a6..842f736ee9 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Resources/DeleteResourceTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Resources/DeleteResourceTests.cs @@ -29,10 +29,10 @@ public async Task Can_delete_resource() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); - existingTodoItem.Tags = _fakers.Tag.Generate(1).ToHashSet(); - existingTodoItem.Tags.ElementAt(0).Color = _fakers.RgbColor.Generate(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); + existingTodoItem.Tags = _fakers.Tag.GenerateSet(1); + existingTodoItem.Tags.ElementAt(0).Color = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Resources/FetchResourceTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Resources/FetchResourceTests.cs index 0027de1d38..20d08e1b9f 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Resources/FetchResourceTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Resources/FetchResourceTests.cs @@ -28,8 +28,8 @@ public async Task Can_get_primary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(2); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(2); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); todoItems[0].Priority = TodoItemPriority.Low; todoItems[1].Priority = TodoItemPriority.High; @@ -101,8 +101,8 @@ public async Task Can_get_primary_resource_by_ID() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -192,9 +192,9 @@ public async Task Can_get_secondary_ToMany_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); - todoItem.Tags = _fakers.Tag.Generate(2).ToHashSet(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); + todoItem.Tags = _fakers.Tag.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -261,8 +261,8 @@ public async Task Can_get_secondary_ToOne_resource() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -311,8 +311,8 @@ public async Task Can_get_empty_secondary_ToOne_resource() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Resources/UpdateResourceTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Resources/UpdateResourceTests.cs index f51b7c6b52..b248db2e02 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Resources/UpdateResourceTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Resources/UpdateResourceTests.cs @@ -29,8 +29,8 @@ public async Task Can_update_resource_without_attributes_or_relationships() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Tag existingTag = _fakers.Tag.Generate(); - existingTag.Color = _fakers.RgbColor.Generate(); + Tag existingTag = _fakers.Tag.GenerateOne(); + existingTag.Color = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -107,13 +107,13 @@ public async Task Can_partially_update_resource_attributes() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); - existingTodoItem.Assignee = _fakers.Person.Generate(); - existingTodoItem.Tags = _fakers.Tag.Generate(1).ToHashSet(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); + existingTodoItem.Assignee = _fakers.Person.GenerateOne(); + existingTodoItem.Tags = _fakers.Tag.GenerateSet(1); - string newDescription = _fakers.TodoItem.Generate().Description; - long newDurationInHours = _fakers.TodoItem.Generate().DurationInHours!.Value; + string newDescription = _fakers.TodoItem.GenerateOne().Description; + long newDurationInHours = _fakers.TodoItem.GenerateOne().DurationInHours!.Value; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -230,16 +230,16 @@ public async Task Can_completely_update_resource() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); - existingTodoItem.Assignee = _fakers.Person.Generate(); - existingTodoItem.Tags = _fakers.Tag.Generate(2).ToHashSet(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); + existingTodoItem.Assignee = _fakers.Person.GenerateOne(); + existingTodoItem.Tags = _fakers.Tag.GenerateSet(2); - TodoItem newTodoItem = _fakers.TodoItem.Generate(); + TodoItem newTodoItem = _fakers.TodoItem.GenerateOne(); - Tag existingTag = _fakers.Tag.Generate(); - Person existingPerson1 = _fakers.Person.Generate(); - Person existingPerson2 = _fakers.Person.Generate(); + Tag existingTag = _fakers.Tag.GenerateOne(); + Person existingPerson1 = _fakers.Person.GenerateOne(); + Person existingPerson2 = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/Sql/SubQueryInJoinTests.cs b/test/DapperTests/IntegrationTests/Sql/SubQueryInJoinTests.cs index ed75d24d65..e9b2b001a5 100644 --- a/test/DapperTests/IntegrationTests/Sql/SubQueryInJoinTests.cs +++ b/test/DapperTests/IntegrationTests/Sql/SubQueryInJoinTests.cs @@ -27,7 +27,7 @@ public async Task Join_with_table_on_ToOne_include() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -76,7 +76,7 @@ public async Task Join_with_table_on_ToMany_include() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -125,7 +125,7 @@ public async Task Join_with_table_on_ToMany_include_with_nested_sort_on_attribut var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -174,7 +174,7 @@ public async Task Join_with_table_on_ToMany_include_with_nested_sort_on_count() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -227,7 +227,7 @@ public async Task Join_with_tables_on_includes_with_nested_sorts() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -281,8 +281,8 @@ public async Task Join_with_tables_on_includes_with_nested_sorts_on_counts() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -344,7 +344,7 @@ public async Task Join_with_sub_query_on_ToMany_include_with_nested_filter() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -398,7 +398,7 @@ public async Task Join_with_sub_query_on_ToMany_include_with_nested_filter_on_ha var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -455,7 +455,7 @@ public async Task Join_with_sub_query_on_ToMany_include_with_nested_filter_on_co var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -513,7 +513,7 @@ public async Task Join_with_sub_query_on_includes_with_nested_filter_and_sorts() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -573,7 +573,7 @@ public async Task Join_with_nested_sub_queries_with_filters_and_sorts() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/DapperTests/IntegrationTests/SqlTextAdapter.cs b/test/DapperTests/IntegrationTests/SqlTextAdapter.cs index de860f5814..4529dd2178 100644 --- a/test/DapperTests/IntegrationTests/SqlTextAdapter.cs +++ b/test/DapperTests/IntegrationTests/SqlTextAdapter.cs @@ -5,10 +5,16 @@ namespace DapperTests.IntegrationTests; internal sealed class SqlTextAdapter(DatabaseProvider databaseProvider) { +#if NET6_0 + private const RegexOptions Options = RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture; +#else + private const RegexOptions Options = RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.NonBacktracking; +#endif + private static readonly Dictionary SqlServerReplacements = new() { - [new Regex("\"([^\"]+)\"", RegexOptions.Compiled)] = "[$+]", - [new Regex($@"(VALUES \([^)]*\)){Environment.NewLine}RETURNING \[Id\]", RegexOptions.Compiled)] = $"OUTPUT INSERTED.[Id]{Environment.NewLine}$1" + [new Regex("\"([^\"]+)\"", Options)] = "[$+]", + [new Regex($@"(VALUES \([^)]*\)){Environment.NewLine}RETURNING \[Id\]", Options)] = $"OUTPUT INSERTED.[Id]{Environment.NewLine}$1" }; private readonly DatabaseProvider _databaseProvider = databaseProvider; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Archiving/ArchiveTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Archiving/ArchiveTests.cs index 6b400325e3..b80d7c3e3c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Archiving/ArchiveTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Archiving/ArchiveTests.cs @@ -28,7 +28,7 @@ public ArchiveTests(IntegrationTestContext, public async Task Can_get_archived_resource_by_ID() { // Arrange - TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -53,7 +53,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_unarchived_resource_by_ID() { // Arrange - TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.GenerateOne(); broadcast.ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -79,7 +79,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_excludes_archived() { // Arrange - List broadcasts = _fakers.TelevisionBroadcast.Generate(2); + List broadcasts = _fakers.TelevisionBroadcast.GenerateList(2); broadcasts[1].ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -106,7 +106,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_filter_includes_archived() { // Arrange - List broadcasts = _fakers.TelevisionBroadcast.Generate(2); + List broadcasts = _fakers.TelevisionBroadcast.GenerateList(2); broadcasts[1].ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -136,8 +136,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resource_by_ID_with_include_excludes_archived() { // Arrange - TelevisionStation station = _fakers.TelevisionStation.Generate(); - station.Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionStation station = _fakers.TelevisionStation.GenerateOne(); + station.Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); station.Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -166,8 +166,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resource_by_ID_with_include_and_filter_includes_archived() { // Arrange - TelevisionStation station = _fakers.TelevisionStation.Generate(); - station.Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionStation station = _fakers.TelevisionStation.GenerateOne(); + station.Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); station.Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -198,8 +198,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resource_includes_archived() { // Arrange - BroadcastComment comment = _fakers.BroadcastComment.Generate(); - comment.AppliesTo = _fakers.TelevisionBroadcast.Generate(); + BroadcastComment comment = _fakers.BroadcastComment.GenerateOne(); + comment.AppliesTo = _fakers.TelevisionBroadcast.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -224,8 +224,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resources_excludes_archived() { // Arrange - TelevisionStation station = _fakers.TelevisionStation.Generate(); - station.Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionStation station = _fakers.TelevisionStation.GenerateOne(); + station.Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); station.Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -251,8 +251,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resources_with_filter_includes_archived() { // Arrange - TelevisionStation station = _fakers.TelevisionStation.Generate(); - station.Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionStation station = _fakers.TelevisionStation.GenerateOne(); + station.Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); station.Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -283,9 +283,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resource_by_ID_with_include_excludes_archived() { // Arrange - TelevisionNetwork network = _fakers.TelevisionNetwork.Generate(); - network.Stations = _fakers.TelevisionStation.Generate(1).ToHashSet(); - network.Stations.ElementAt(0).Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionNetwork network = _fakers.TelevisionNetwork.GenerateOne(); + network.Stations = _fakers.TelevisionStation.GenerateSet(1); + network.Stations.ElementAt(0).Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); network.Stations.ElementAt(0).Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -313,9 +313,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Get_secondary_resource_by_ID_with_include_and_filter_includes_archived() { - TelevisionNetwork network = _fakers.TelevisionNetwork.Generate(); - network.Stations = _fakers.TelevisionStation.Generate(1).ToHashSet(); - network.Stations.ElementAt(0).Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionNetwork network = _fakers.TelevisionNetwork.GenerateOne(); + network.Stations = _fakers.TelevisionStation.GenerateSet(1); + network.Stations.ElementAt(0).Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); network.Stations.ElementAt(0).Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -349,8 +349,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_excludes_archived() { // Arrange - TelevisionStation station = _fakers.TelevisionStation.Generate(); - station.Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionStation station = _fakers.TelevisionStation.GenerateOne(); + station.Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); station.Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -375,8 +375,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_with_filter_includes_archived() { // Arrange - TelevisionStation station = _fakers.TelevisionStation.Generate(); - station.Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionStation station = _fakers.TelevisionStation.GenerateOne(); + station.Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); station.Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -402,7 +402,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_unarchived_resource() { // Arrange - TelevisionBroadcast newBroadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast newBroadcast = _fakers.TelevisionBroadcast.GenerateOne(); var requestBody = new { @@ -435,7 +435,7 @@ public async Task Can_create_unarchived_resource() public async Task Cannot_create_archived_resource() { // Arrange - TelevisionBroadcast newBroadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast newBroadcast = _fakers.TelevisionBroadcast.GenerateOne(); var requestBody = new { @@ -471,10 +471,10 @@ public async Task Cannot_create_archived_resource() public async Task Can_archive_resource() { // Arrange - TelevisionBroadcast existingBroadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast existingBroadcast = _fakers.TelevisionBroadcast.GenerateOne(); existingBroadcast.ArchivedAt = null; - DateTimeOffset newArchivedAt = _fakers.TelevisionBroadcast.Generate().ArchivedAt!.Value; + DateTimeOffset newArchivedAt = _fakers.TelevisionBroadcast.GenerateOne().ArchivedAt!.Value; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -517,7 +517,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_unarchive_resource() { // Arrange - TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -560,9 +560,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_shift_archive_date() { // Arrange - TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.GenerateOne(); - DateTimeOffset? newArchivedAt = _fakers.TelevisionBroadcast.Generate().ArchivedAt; + DateTimeOffset? newArchivedAt = _fakers.TelevisionBroadcast.GenerateOne().ArchivedAt; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -603,7 +603,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_archived_resource() { // Arrange - TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -633,7 +633,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_delete_unarchived_resource() { // Arrange - TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.GenerateOne(); broadcast.ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicCustomConstrainedOperationsControllerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicCustomConstrainedOperationsControllerTests.cs index 099168b124..3cdf4f20c0 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicCustomConstrainedOperationsControllerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicCustomConstrainedOperationsControllerTests.cs @@ -23,8 +23,8 @@ public AtomicCustomConstrainedOperationsControllerTests(IntegrationTestContext { @@ -161,8 +161,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_ToMany_relationship_for_inaccessible_operation() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - Performer existingPerformer = _fakers.Performer.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicDefaultConstrainedOperationsControllerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicDefaultConstrainedOperationsControllerTests.cs index caffc32e2b..0b60bfe782 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicDefaultConstrainedOperationsControllerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicDefaultConstrainedOperationsControllerTests.cs @@ -23,7 +23,7 @@ public AtomicDefaultConstrainedOperationsControllerTests(IntegrationTestContext< public async Task Cannot_delete_resource_for_inaccessible_operation() { // Arrange - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -69,8 +69,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_change_ToMany_relationship_for_inaccessible_operations() { // Arrange - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); - Lyric existingLyric = _fakers.Lyric.Generate(); + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceTests.cs index c77610d8dc..247a827a34 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceTests.cs @@ -36,8 +36,8 @@ public AtomicCreateResourceTests(IntegrationTestContext newTracks = _fakers.MusicTrack.Generate(elementCount); + List newTracks = _fakers.MusicTrack.GenerateList(elementCount); var operationElements = new List(elementCount); @@ -228,7 +228,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_unknown_attribute() { // Arrange - string newName = _fakers.Playlist.Generate().Name; + string newName = _fakers.Playlist.GenerateOne().Name; var requestBody = new { @@ -276,7 +276,7 @@ public async Task Can_create_resource_with_unknown_attribute() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - string newName = _fakers.Playlist.Generate().Name; + string newName = _fakers.Playlist.GenerateOne().Name; var requestBody = new { @@ -381,7 +381,7 @@ public async Task Can_create_resource_with_unknown_relationship() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - string newLyricText = _fakers.Lyric.Generate().Text; + string newLyricText = _fakers.Lyric.GenerateOne().Text; var requestBody = new { @@ -444,7 +444,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_client_generated_ID() { // Arrange - MusicTrack newTrack = _fakers.MusicTrack.Generate(); + MusicTrack newTrack = _fakers.MusicTrack.GenerateOne(); newTrack.Id = Guid.NewGuid(); var requestBody = new @@ -632,7 +632,7 @@ public async Task Cannot_create_resource_for_null_data() public async Task Cannot_create_resource_for_array_data() { // Arrange - string newArtistName = _fakers.Performer.Generate().ArtistName!; + string newArtistName = _fakers.Performer.GenerateOne().ArtistName!; var requestBody = new { @@ -757,7 +757,7 @@ public async Task Cannot_create_resource_for_unknown_type() public async Task Cannot_create_resource_with_readonly_attribute() { // Arrange - string newPlaylistName = _fakers.Playlist.Generate().Name; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; var requestBody = new { @@ -844,11 +844,11 @@ public async Task Cannot_create_resource_with_incompatible_attribute_value() public async Task Can_create_resource_with_attributes_and_multiple_relationship_types() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); - Performer existingPerformer = _fakers.Performer.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); - string newTitle = _fakers.MusicTrack.Generate().Title; + string newTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs index 2d18a44a52..4d7b7177cf 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs @@ -41,7 +41,7 @@ public async Task Can_create_resource_with_client_generated_guid_ID_having_side_ var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - TextLanguage newLanguage = _fakers.TextLanguage.Generate(); + TextLanguage newLanguage = _fakers.TextLanguage.GenerateOne(); newLanguage.Id = Guid.NewGuid(); var requestBody = new @@ -101,7 +101,7 @@ public async Task Can_create_resource_with_client_generated_guid_ID_having_no_si var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - MusicTrack newTrack = _fakers.MusicTrack.Generate(); + MusicTrack newTrack = _fakers.MusicTrack.GenerateOne(); newTrack.Id = Guid.NewGuid(); var requestBody = new @@ -153,7 +153,7 @@ public async Task Can_create_resource_for_missing_client_generated_ID_having_sid var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - string? newIsoCode = _fakers.TextLanguage.Generate().IsoCode; + string? newIsoCode = _fakers.TextLanguage.GenerateOne().IsoCode; var requestBody = new { @@ -211,7 +211,7 @@ public async Task Cannot_create_resource_for_missing_client_generated_ID(ClientI var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - string? newIsoCode = _fakers.TextLanguage.Generate().IsoCode; + string? newIsoCode = _fakers.TextLanguage.GenerateOne().IsoCode; var requestBody = new { @@ -260,10 +260,10 @@ public async Task Cannot_create_resource_for_existing_client_generated_ID(Client var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); existingLanguage.Id = Guid.NewGuid(); - TextLanguage languageToCreate = _fakers.TextLanguage.Generate(); + TextLanguage languageToCreate = _fakers.TextLanguage.GenerateOne(); languageToCreate.Id = existingLanguage.Id; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -368,7 +368,7 @@ public async Task Can_create_resource_with_local_ID(ClientIdGenerationMode mode) var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - string newTitle = _fakers.MusicTrack.Generate().Title; + string newTitle = _fakers.MusicTrack.GenerateOne().Title; var requestBody = new { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs index 61a1db5164..0d4d367c12 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs @@ -28,8 +28,8 @@ public AtomicCreateResourceWithToManyRelationshipTests(IntegrationTestContext existingPerformers = _fakers.Performer.Generate(2); - string newTitle = _fakers.MusicTrack.Generate().Title; + List existingPerformers = _fakers.Performer.GenerateList(2); + string newTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -108,8 +108,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_ManyToMany_relationship() { // Arrange - List existingTracks = _fakers.MusicTrack.Generate(3); - string newName = _fakers.Playlist.Generate().Name; + List existingTracks = _fakers.MusicTrack.GenerateList(3); + string newName = _fakers.Playlist.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -348,7 +348,7 @@ public async Task Cannot_create_for_missing_relationship_ID() public async Task Cannot_create_for_unknown_relationship_IDs() { // Arrange - string newTitle = _fakers.MusicTrack.Generate().Title; + string newTitle = _fakers.MusicTrack.GenerateOne().Title; string performerId1 = Unknown.StringId.For(); string performerId2 = Unknown.StringId.AltFor(); @@ -474,8 +474,8 @@ public async Task Cannot_create_on_relationship_type_mismatch() public async Task Can_create_with_duplicates() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); - string newTitle = _fakers.MusicTrack.Generate().Title; + Performer existingPerformer = _fakers.Performer.GenerateOne(); + string newTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs index 5d138404ba..a522105806 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs @@ -29,9 +29,9 @@ public AtomicCreateResourceWithToOneRelationshipTests(IntegrationTestContext { @@ -101,8 +101,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_dependent_side() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -174,8 +174,8 @@ public async Task Can_create_resources_with_ToOne_relationship() // Arrange const int elementCount = 5; - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); - string[] newTrackTitles = _fakers.MusicTrack.Generate(elementCount).Select(musicTrack => musicTrack.Title).ToArray(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); + string[] newTrackTitles = _fakers.MusicTrack.GenerateList(elementCount).Select(musicTrack => musicTrack.Title).ToArray(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -552,7 +552,7 @@ public async Task Cannot_create_for_missing_relationship_ID() public async Task Cannot_create_with_unknown_relationship_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; string lyricId = Unknown.StringId.For(); @@ -658,8 +658,8 @@ public async Task Cannot_create_on_relationship_type_mismatch() public async Task Can_create_resource_with_duplicate_relationship() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs index c2dc97b612..cbc3280aed 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs @@ -23,7 +23,7 @@ public AtomicDeleteResourceTests(IntegrationTestContext { @@ -71,7 +71,7 @@ public async Task Can_delete_existing_resources() // Arrange const int elementCount = 5; - List existingTracks = _fakers.MusicTrack.Generate(elementCount); + List existingTracks = _fakers.MusicTrack.GenerateList(elementCount); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -122,8 +122,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_with_OneToOne_relationship_from_principal_side() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - existingLyric.Track = _fakers.MusicTrack.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + existingLyric.Track = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -173,8 +173,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_with_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -224,8 +224,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_existing_resource_with_OneToMany_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(2); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -276,8 +276,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_existing_resource_with_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(1); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicAbsoluteLinksTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicAbsoluteLinksTests.cs index 4b1ed95619..4686e55244 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicAbsoluteLinksTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicAbsoluteLinksTests.cs @@ -32,8 +32,8 @@ public AtomicAbsoluteLinksTests(IntegrationTestContext { @@ -121,7 +121,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_and_missing_resource_controller_hides_links() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicRelativeLinksWithNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicRelativeLinksWithNamespaceTests.cs index 6d5a276ecb..86b8ad9846 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicRelativeLinksWithNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicRelativeLinksWithNamespaceTests.cs @@ -33,7 +33,7 @@ public AtomicRelativeLinksWithNamespaceTests( public async Task Create_resource_with_side_effects_returns_relative_links() { // Arrange - string newCompanyName = _fakers.RecordCompany.Generate().Name; + string newCompanyName = _fakers.RecordCompany.GenerateOne().Name; var requestBody = new { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/LocalIds/AtomicLocalIdTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/LocalIds/AtomicLocalIdTests.cs index df5bc5f90b..e65b218764 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/LocalIds/AtomicLocalIdTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/LocalIds/AtomicLocalIdTests.cs @@ -23,8 +23,8 @@ public AtomicLocalIdTests(IntegrationTestContext public async Task Can_create_resource_with_OneToMany_relationship_using_local_ID() { // Arrange - Performer newPerformer = _fakers.Performer.Generate(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + Performer newPerformer = _fakers.Performer.GenerateOne(); + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; const string performerLocalId = "performer-1"; @@ -214,8 +214,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_ManyToMany_relationship_using_local_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newPlaylistName = _fakers.Playlist.Generate().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; const string trackLocalId = "track-1"; @@ -310,7 +310,7 @@ public async Task Cannot_consume_local_ID_that_is_assigned_in_same_operation() // Arrange const string companyLocalId = "company-1"; - string newCompanyName = _fakers.RecordCompany.Generate().Name; + string newCompanyName = _fakers.RecordCompany.GenerateOne().Name; var requestBody = new { @@ -374,7 +374,7 @@ public async Task Cannot_consume_local_ID_that_is_assigned_in_same_operation() public async Task Cannot_reassign_local_ID() { // Arrange - string newPlaylistName = _fakers.Playlist.Generate().Name; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; const string playlistLocalId = "playlist-1"; var requestBody = new @@ -441,8 +441,8 @@ public async Task Cannot_reassign_local_ID() public async Task Can_update_resource_using_local_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newTrackGenre = _fakers.MusicTrack.Generate().Genre!; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newTrackGenre = _fakers.MusicTrack.GenerateOne().Genre!; const string trackLocalId = "track-1"; @@ -514,9 +514,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_relationships_using_local_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newArtistName = _fakers.Performer.Generate().ArtistName!; - string newCompanyName = _fakers.RecordCompany.Generate().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newArtistName = _fakers.Performer.GenerateOne().ArtistName!; + string newCompanyName = _fakers.RecordCompany.GenerateOne().Name; const string trackLocalId = "track-1"; const string performerLocalId = "performer-1"; @@ -664,8 +664,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_ManyToOne_relationship_using_local_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newCompanyName = _fakers.RecordCompany.Generate().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newCompanyName = _fakers.RecordCompany.GenerateOne().Name; const string trackLocalId = "track-1"; const string companyLocalId = "company-1"; @@ -763,8 +763,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToMany_relationship_using_local_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newArtistName = _fakers.Performer.Generate().ArtistName!; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newArtistName = _fakers.Performer.GenerateOne().ArtistName!; const string trackLocalId = "track-1"; const string performerLocalId = "performer-1"; @@ -865,8 +865,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_ManyToMany_relationship_using_local_ID() { // Arrange - string newPlaylistName = _fakers.Playlist.Generate().Name; - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; const string playlistLocalId = "playlist-1"; const string trackLocalId = "track-1"; @@ -967,10 +967,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship_using_local_ID() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newArtistName = _fakers.Performer.Generate().ArtistName!; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newArtistName = _fakers.Performer.GenerateOne().ArtistName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1091,10 +1091,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToMany_relationship_using_local_ID() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); - string newPlaylistName = _fakers.Playlist.Generate().Name; - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1215,10 +1215,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_OneToMany_relationship_using_local_ID() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newArtistName = _fakers.Performer.Generate().ArtistName!; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newArtistName = _fakers.Performer.GenerateOne().ArtistName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1343,10 +1343,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ManyToMany_relationship_using_local_ID() { // Arrange - List existingTracks = _fakers.MusicTrack.Generate(2); + List existingTracks = _fakers.MusicTrack.GenerateList(2); - string newPlaylistName = _fakers.Playlist.Generate().Name; - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; const string playlistLocalId = "playlist-1"; const string trackLocalId = "track-1"; @@ -1488,11 +1488,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_OneToMany_relationship_using_local_ID() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newArtistName1 = _fakers.Performer.Generate().ArtistName!; - string newArtistName2 = _fakers.Performer.Generate().ArtistName!; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newArtistName1 = _fakers.Performer.GenerateOne().ArtistName!; + string newArtistName2 = _fakers.Performer.GenerateOne().ArtistName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1648,10 +1648,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ManyToMany_relationship_using_local_ID() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(2); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(2); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; const string trackLocalId = "track-1"; @@ -1771,7 +1771,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_using_local_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; const string trackLocalId = "track-1"; @@ -1934,7 +1934,7 @@ public async Task Cannot_consume_unassigned_local_ID_in_data_element() public async Task Cannot_consume_unassigned_local_ID_in_data_array() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1998,7 +1998,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_consume_unassigned_local_ID_in_relationship_data_element() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; var requestBody = new { @@ -2061,7 +2061,7 @@ public async Task Cannot_consume_unassigned_local_ID_in_relationship_data_elemen public async Task Cannot_consume_unassigned_local_ID_in_relationship_data_array() { // Arrange - string newPlaylistName = _fakers.Playlist.Generate().Name; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; var requestBody = new { @@ -2128,7 +2128,7 @@ public async Task Cannot_consume_local_ID_of_different_type_in_same_operation() { // Arrange const string trackLocalId = "track-1"; - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; var requestBody = new { @@ -2194,7 +2194,7 @@ public async Task Cannot_consume_local_ID_of_different_type_in_ref() // Arrange const string companyLocalId = "company-1"; - string newCompanyName = _fakers.RecordCompany.Generate().Name; + string newCompanyName = _fakers.RecordCompany.GenerateOne().Name; var requestBody = new { @@ -2317,11 +2317,11 @@ public async Task Cannot_consume_local_ID_of_different_type_in_data_element() public async Task Cannot_consume_local_ID_of_different_type_in_data_array() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); const string companyLocalId = "company-1"; - string newCompanyName = _fakers.RecordCompany.Generate().Name; + string newCompanyName = _fakers.RecordCompany.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2398,8 +2398,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_consume_local_ID_of_different_type_in_relationship_data_element() { // Arrange - string newPlaylistName = _fakers.Playlist.Generate().Name; - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; const string playlistLocalId = "playlist-1"; @@ -2478,7 +2478,7 @@ public async Task Cannot_consume_local_ID_of_different_type_in_relationship_data { // Arrange const string performerLocalId = "performer-1"; - string newPlaylistName = _fakers.Playlist.Generate().Name; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; var requestBody = new { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs index f98bc1b49d..8c08ccedae 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs @@ -40,8 +40,8 @@ public async Task Returns_resource_meta_in_create_resource_with_side_effects() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - string newTitle1 = _fakers.MusicTrack.Generate().Title; - string newTitle2 = _fakers.MusicTrack.Generate().Title; + string newTitle1 = _fakers.MusicTrack.GenerateOne().Title; + string newTitle2 = _fakers.MusicTrack.GenerateOne().Title; var requestBody = new { @@ -121,7 +121,7 @@ public async Task Returns_resource_meta_in_update_resource_with_side_effects() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResponseMetaTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResponseMetaTests.cs index e4c31db1e6..88e7115f66 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResponseMetaTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResponseMetaTests.cs @@ -91,7 +91,7 @@ public async Task Returns_top_level_meta_in_create_resource_with_side_effects() public async Task Returns_top_level_meta_in_update_resource_with_side_effects() { // Arrange - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicLoggingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicLoggingTests.cs index 412a3f388c..34618f95f8 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicLoggingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicLoggingTests.cs @@ -19,28 +19,24 @@ public AtomicLoggingTests(IntegrationTestContext(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Information); - testContext.ConfigureLogging(options => { - options.ClearProviders(); - options.AddProvider(loggerFactory); + var loggerProvider = new CapturingLoggerProvider(LogLevel.Information); + options.AddProvider(loggerProvider); options.SetMinimumLevel(LogLevel.Information); - }); - testContext.ConfigureServices(services => - { - services.AddSingleton(loggerFactory); - services.AddSingleton(); + options.Services.AddSingleton(loggerProvider); }); + + testContext.ConfigureServices(services => services.AddSingleton()); } [Fact] public async Task Logs_unhandled_exception_at_Error_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); var transactionFactory = (ThrowingOperationsTransactionFactory)_testContext.Factory.Services.GetRequiredService(); transactionFactory.ThrowOnOperationStart = true; @@ -80,19 +76,18 @@ public async Task Logs_unhandled_exception_at_Error_level() error.Source.ShouldNotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); - IReadOnlyList logMessages = loggerFactory.Logger.GetMessages(); - logMessages.ShouldNotBeEmpty(); + IReadOnlyList logMessages = loggerProvider.GetMessages(); - logMessages.Should().ContainSingle(message => message.LogLevel == LogLevel.Error && - message.Text.Contains("Simulated failure.", StringComparison.Ordinal)); + logMessages.Should().ContainSingle(message => + message.LogLevel == LogLevel.Error && message.Text.Contains("Simulated failure.", StringComparison.Ordinal)); } [Fact] public async Task Logs_invalid_request_body_error_at_Information_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); var transactionFactory = (ThrowingOperationsTransactionFactory)_testContext.Factory.Services.GetRequiredService(); transactionFactory.ThrowOnOperationStart = false; @@ -118,8 +113,7 @@ public async Task Logs_invalid_request_body_error_at_Information_level() responseDocument.Errors.ShouldHaveCount(1); - IReadOnlyList logMessages = loggerFactory.Logger.GetMessages(); - logMessages.ShouldNotBeEmpty(); + IReadOnlyList logMessages = loggerProvider.GetMessages(); logMessages.Should().ContainSingle(message => message.LogLevel == LogLevel.Information && message.Text.Contains("Failed to deserialize request body", StringComparison.Ordinal)); @@ -165,7 +159,7 @@ private Task ThrowIfEnabled() { if (_owner.ThrowOnOperationStart) { - throw new Exception("Simulated failure."); + throw new InvalidOperationException("Simulated failure."); } return Task.CompletedTask; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicSerializationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicSerializationTests.cs index fc6d366f94..0d0a54bc58 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicSerializationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicSerializationTests.cs @@ -38,9 +38,9 @@ public AtomicSerializationTests(IntegrationTestContext diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicTraceLoggingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicTraceLoggingTests.cs index f3c47ed4b5..e56d88e419 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicTraceLoggingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicTraceLoggingTests.cs @@ -19,36 +19,35 @@ public AtomicTraceLoggingTests(IntegrationTestContext(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Trace); - testContext.ConfigureLogging(options => { - options.ClearProviders(); - options.AddProvider(loggerFactory); + var loggerProvider = new CapturingLoggerProvider((category, level) => + level >= LogLevel.Trace && category.StartsWith("JsonApiDotNetCore.", StringComparison.Ordinal)); + + options.AddProvider(loggerProvider); options.SetMinimumLevel(LogLevel.Trace); - options.AddFilter((category, _) => category != null && category.StartsWith("JsonApiDotNetCore.", StringComparison.Ordinal)); - }); - testContext.ConfigureServices(services => services.AddSingleton(loggerFactory)); + options.Services.AddSingleton(loggerProvider); + }); } [Fact] public async Task Logs_execution_flow_at_Trace_level_on_operations_request() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); - string newGenre = _fakers.MusicTrack.Generate().Genre!; + string newGenre = _fakers.MusicTrack.GenerateOne().Genre!; - Lyric existingLyric = _fakers.Lyric.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); - Performer existingPerformer = _fakers.Performer.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -116,7 +115,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Should().BeEmpty(); - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.Should().BeEquivalentTo(new[] { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ModelStateValidation/AtomicModelStateValidationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ModelStateValidation/AtomicModelStateValidationTests.cs index 1d095377bd..82c190dc58 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ModelStateValidation/AtomicModelStateValidationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ModelStateValidation/AtomicModelStateValidationTests.cs @@ -119,8 +119,8 @@ public async Task Cannot_create_resource_when_violation_from_custom_ValidationAt public async Task Can_create_resource_with_annotated_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - string newPlaylistName = _fakers.Playlist.Generate().Name; + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -186,7 +186,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_multiple_violations() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -244,8 +244,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_omitted_required_attribute() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - string newTrackGenre = _fakers.MusicTrack.Generate().Genre!; + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + string newTrackGenre = _fakers.MusicTrack.GenerateOne().Genre!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -296,8 +296,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_annotated_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -358,8 +358,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -412,8 +412,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsFakers.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsFakers.cs index b66fa6d5df..f09dfbdf0a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsFakers.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsFakers.cs @@ -9,7 +9,7 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.AtomicOperations; internal sealed class OperationsFakers { - private static readonly Lazy> LazyLanguageIsoCodes = new(() => CultureInfo + private static readonly Lazy LazyLanguageIsoCodes = new(() => CultureInfo .GetCultures(CultureTypes.NeutralCultures) .Where(culture => !string.IsNullOrEmpty(culture.Name)) .Select(culture => culture.Name) @@ -33,7 +33,7 @@ internal sealed class OperationsFakers private readonly Lazy> _lazyTextLanguageFaker = new(() => new Faker() .MakeDeterministic() - .RuleFor(textLanguage => textLanguage.IsoCode, faker => faker.PickRandom(LazyLanguageIsoCodes.Value))); + .RuleFor(textLanguage => textLanguage.IsoCode, faker => faker.PickRandom(LazyLanguageIsoCodes.Value))); private readonly Lazy> _lazyPerformerFaker = new(() => new Faker() .MakeDeterministic() diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/AtomicQueryStringTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/AtomicQueryStringTests.cs index 6db0926773..35cd7ed32b 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/AtomicQueryStringTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/AtomicQueryStringTests.cs @@ -274,7 +274,7 @@ public async Task Can_use_Queryable_handler_at_resource_endpoint() // Arrange var clock = _testContext.Factory.Services.GetRequiredService(); - List musicTracks = _fakers.MusicTrack.Generate(3); + List musicTracks = _fakers.MusicTrack.GenerateList(3); musicTracks[0].ReleasedAt = clock.UtcNow.AddMonths(5); musicTracks[1].ReleasedAt = clock.UtcNow.AddMonths(-5); musicTracks[2].ReleasedAt = clock.UtcNow.AddMonths(-1); @@ -302,7 +302,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_use_Queryable_handler_at_operations_endpoint() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; var requestBody = new { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/Serialization/AtomicSerializationResourceDefinitionTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/Serialization/AtomicSerializationResourceDefinitionTests.cs index 4e2fa4f937..8e3c2ac7f9 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/Serialization/AtomicSerializationResourceDefinitionTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/Serialization/AtomicSerializationResourceDefinitionTests.cs @@ -40,7 +40,7 @@ public async Task Transforms_on_create_resource_with_side_effects() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List newCompanies = _fakers.RecordCompany.Generate(2); + List newCompanies = _fakers.RecordCompany.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -133,9 +133,9 @@ public async Task Skips_on_create_resource_with_ToOne_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -192,7 +192,7 @@ public async Task Transforms_on_update_resource_with_side_effects() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List existingCompanies = _fakers.RecordCompany.Generate(2); + List existingCompanies = _fakers.RecordCompany.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -285,8 +285,8 @@ public async Task Skips_on_update_resource_with_ToOne_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -343,8 +343,8 @@ public async Task Skips_on_update_ToOne_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/SparseFieldSets/AtomicSparseFieldSetResourceDefinitionTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/SparseFieldSets/AtomicSparseFieldSetResourceDefinitionTests.cs index 63fb7e8eb2..983a9c5213 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/SparseFieldSets/AtomicSparseFieldSetResourceDefinitionTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/SparseFieldSets/AtomicSparseFieldSetResourceDefinitionTests.cs @@ -43,7 +43,7 @@ public async Task Hides_text_in_create_resource_with_side_effects() var provider = _testContext.Factory.Services.GetRequiredService(); provider.CanViewText = false; - List newLyrics = _fakers.Lyric.Generate(2); + List newLyrics = _fakers.Lyric.GenerateList(2); var requestBody = new { @@ -118,7 +118,7 @@ public async Task Hides_text_in_update_resource_with_side_effects() var provider = _testContext.Factory.Services.GetRequiredService(); provider.CanViewText = false; - List existingLyrics = _fakers.Lyric.Generate(2); + List existingLyrics = _fakers.Lyric.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs index 82646686d4..b4f393d901 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs @@ -23,9 +23,9 @@ public AtomicRollbackTests(IntegrationTestContext { @@ -111,7 +111,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_restore_to_previous_savepoint_on_error() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs index 9c054c349b..4b5a6afc1b 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs @@ -78,7 +78,7 @@ public async Task Cannot_use_non_transactional_repository() public async Task Cannot_use_transactional_repository_without_active_transaction() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; var requestBody = new { @@ -121,7 +121,7 @@ public async Task Cannot_use_transactional_repository_without_active_transaction public async Task Cannot_use_distributed_transaction() { // Arrange - string newLyricText = _fakers.Lyric.Generate().Text; + string newLyricText = _fakers.Lyric.GenerateOne().Text; var requestBody = new { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs index 293b4b495c..e59b9d24d5 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs @@ -23,8 +23,8 @@ public AtomicAddToToManyRelationshipTests(IntegrationTestContext { @@ -77,10 +77,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_OneToMany_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); - List existingPerformers = _fakers.Performer.Generate(2); + List existingPerformers = _fakers.Performer.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -157,10 +157,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(1); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(1); - List existingTracks = _fakers.MusicTrack.Generate(2); + List existingTracks = _fakers.MusicTrack.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -390,7 +390,7 @@ public async Task Cannot_add_for_missing_ID_in_ref() public async Task Cannot_add_for_unknown_ID_in_ref() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -568,7 +568,7 @@ public async Task Cannot_add_for_unknown_relationship_in_ref() public async Task Cannot_add_for_missing_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -616,7 +616,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_for_null_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -665,7 +665,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_for_object_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -907,7 +907,7 @@ public async Task Cannot_add_for_ID_and_local_ID_in_data() public async Task Cannot_add_for_unknown_IDs_in_data() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); string[] trackIds = [ @@ -980,7 +980,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_for_relationship_mismatch_between_ref_and_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1036,8 +1036,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_with_empty_data_array() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1086,7 +1086,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_with_blocked_capability() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs index 7e9654ab30..f7bf47e989 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs @@ -23,8 +23,8 @@ public AtomicRemoveFromToManyRelationshipTests(IntegrationTestContext { @@ -77,8 +77,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_OneToMany_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(3); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -156,8 +156,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(3); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -389,7 +389,7 @@ public async Task Cannot_remove_for_missing_ID_in_ref() public async Task Cannot_remove_for_unknown_ID_in_ref() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -528,7 +528,7 @@ public async Task Cannot_remove_for_unknown_relationship_in_ref() public async Task Cannot_remove_for_missing_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -576,7 +576,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_for_null_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -625,7 +625,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_for_object_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -867,7 +867,7 @@ public async Task Cannot_remove_for_ID_and_local_ID_in_data() public async Task Cannot_remove_for_unknown_IDs_in_data() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); string[] trackIds = [ @@ -940,7 +940,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_for_relationship_mismatch_between_ref_and_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -996,8 +996,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_with_empty_data_array() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1047,7 +1047,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_with_blocked_capability() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs index bcedf104bf..c8e093f9ff 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs @@ -23,8 +23,8 @@ public AtomicReplaceToManyRelationshipTests(IntegrationTestContext { @@ -76,8 +76,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(2); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -130,10 +130,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); - List existingPerformers = _fakers.Performer.Generate(2); + List existingPerformers = _fakers.Performer.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -200,10 +200,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(1); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(1); - List existingTracks = _fakers.MusicTrack.Generate(2); + List existingTracks = _fakers.MusicTrack.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -424,7 +424,7 @@ public async Task Cannot_replace_for_missing_ID_in_ref() public async Task Cannot_replace_for_unknown_ID_in_ref() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -484,7 +484,7 @@ public async Task Cannot_replace_for_incompatible_ID_in_ref() // Arrange string guid = Unknown.StringId.Guid; - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -621,7 +621,7 @@ public async Task Cannot_replace_for_unknown_relationship_in_ref() public async Task Cannot_replace_for_missing_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -669,7 +669,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_null_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -718,7 +718,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_object_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -960,7 +960,7 @@ public async Task Cannot_replace_for_ID_and_local_ID_in_data() public async Task Cannot_replace_for_unknown_IDs_in_data() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); string[] trackIds = [ @@ -1033,7 +1033,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_incompatible_ID_in_data() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1089,7 +1089,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_relationship_mismatch_between_ref_and_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1145,7 +1145,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs index 026b4b0e1e..e9f99c6171 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs @@ -23,8 +23,8 @@ public AtomicUpdateToOneRelationshipTests(IntegrationTestContext { @@ -76,8 +76,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -129,8 +129,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -182,8 +182,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_principal_side() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -236,8 +236,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - Lyric existingLyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -290,8 +290,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -344,10 +344,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToOne_relationship_from_principal_side() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - existingLyric.Track = _fakers.MusicTrack.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + existingLyric.Track = _fakers.MusicTrack.GenerateOne(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -404,10 +404,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -464,10 +464,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -679,7 +679,7 @@ public async Task Cannot_create_for_unknown_ID_in_ref() // Arrange string trackId = Unknown.StringId.For(); - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -732,7 +732,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_incompatible_ID_in_ref() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -866,7 +866,7 @@ public async Task Cannot_create_for_unknown_relationship_in_ref() public async Task Cannot_create_for_missing_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -914,7 +914,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_array_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1149,7 +1149,7 @@ public async Task Cannot_create_for_ID_and_local_ID_in_data() public async Task Cannot_create_for_unknown_ID_in_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1204,7 +1204,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_incompatible_ID_in_data() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1257,7 +1257,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_relationship_mismatch_between_ref_and_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1310,7 +1310,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs index 10da541794..17778fc0a6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs @@ -23,8 +23,8 @@ public AtomicReplaceToManyRelationshipTests(IntegrationTestContext { @@ -81,8 +81,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(2); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -140,10 +140,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); - List existingPerformers = _fakers.Performer.Generate(2); + List existingPerformers = _fakers.Performer.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -215,10 +215,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(1); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(1); - List existingTracks = _fakers.MusicTrack.Generate(2); + List existingTracks = _fakers.MusicTrack.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -291,7 +291,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_missing_data_in_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -344,7 +344,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_null_data_in_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -398,7 +398,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_object_data_in_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -665,7 +665,7 @@ public async Task Cannot_replace_for_ID_and_local_ID_relationship_in_data() public async Task Cannot_replace_for_unknown_IDs_in_relationship_data() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); string[] trackIds = [ @@ -743,7 +743,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_relationship_mismatch() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -804,7 +804,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs index 943d2d9bb4..282fcea377 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs @@ -42,8 +42,8 @@ public async Task Can_update_resources() // Arrange const int elementCount = 5; - List existingTracks = _fakers.MusicTrack.Generate(elementCount); - string[] newTrackTitles = _fakers.MusicTrack.Generate(elementCount).Select(musicTrack => musicTrack.Title).ToArray(); + List existingTracks = _fakers.MusicTrack.GenerateList(elementCount); + string[] newTrackTitles = _fakers.MusicTrack.GenerateList(elementCount).Select(musicTrack => musicTrack.Title).ToArray(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -106,8 +106,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_without_attributes_or_relationships() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -163,8 +163,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_unknown_attribute() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - string newTitle = _fakers.MusicTrack.Generate().Title; + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + string newTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -219,8 +219,8 @@ public async Task Can_update_resource_with_unknown_attribute() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - string newTitle = _fakers.MusicTrack.Generate().Title; + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + string newTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -271,7 +271,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_unknown_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -332,7 +332,7 @@ public async Task Can_update_resource_with_unknown_relationship() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -382,10 +382,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_partially_update_resource_without_side_effects() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); - string newGenre = _fakers.MusicTrack.Generate().Genre!; + string newGenre = _fakers.MusicTrack.GenerateOne().Genre!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -441,13 +441,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_completely_update_resource_without_side_effects() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); - string newTitle = _fakers.MusicTrack.Generate().Title; - decimal? newLengthInSeconds = _fakers.MusicTrack.Generate().LengthInSeconds; - string newGenre = _fakers.MusicTrack.Generate().Genre!; - DateTimeOffset newReleasedAt = _fakers.MusicTrack.Generate().ReleasedAt; + string newTitle = _fakers.MusicTrack.GenerateOne().Title; + decimal? newLengthInSeconds = _fakers.MusicTrack.GenerateOne().LengthInSeconds; + string newGenre = _fakers.MusicTrack.GenerateOne().Genre!; + DateTimeOffset newReleasedAt = _fakers.MusicTrack.GenerateOne().ReleasedAt; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -506,8 +506,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_side_effects() { // Arrange - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); - string newIsoCode = _fakers.TextLanguage.Generate().IsoCode!; + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); + string newIsoCode = _fakers.TextLanguage.GenerateOne().IsoCode!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -566,8 +566,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_hides_relationship_data_in_response() { // Arrange - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); - existingLanguage.Lyrics = _fakers.Lyric.Generate(1); + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); + existingLanguage.Lyrics = _fakers.Lyric.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -647,8 +647,8 @@ public async Task Cannot_update_resource_for_href_element() public async Task Can_update_resource_for_ref_element() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); - string newArtistName = _fakers.Performer.Generate().ArtistName!; + Performer existingPerformer = _fakers.Performer.GenerateOne(); + string newArtistName = _fakers.Performer.GenerateOne().ArtistName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -922,7 +922,7 @@ public async Task Cannot_update_resource_for_null_data() public async Task Cannot_update_resource_for_array_data() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1508,7 +1508,7 @@ public async Task Cannot_update_resource_for_incompatible_ID() public async Task Cannot_update_resource_with_readonly_attribute() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1559,7 +1559,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_change_ID_of_existing_resource() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1610,7 +1610,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_incompatible_attribute_value() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1661,16 +1661,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_attributes_and_multiple_relationship_types() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); - string newGenre = _fakers.MusicTrack.Generate().Genre!; + string newGenre = _fakers.MusicTrack.GenerateOne().Genre!; - Lyric existingLyric = _fakers.Lyric.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); - Performer existingPerformer = _fakers.Performer.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1770,7 +1770,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_attribute_with_blocked_capability() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs index 931e75e789..0206ef1e9c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs @@ -23,8 +23,8 @@ public AtomicUpdateToOneRelationshipTests(IntegrationTestContext { @@ -81,8 +81,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -139,8 +139,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -197,8 +197,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_principal_side() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -256,8 +256,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - Lyric existingLyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -315,8 +315,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -374,10 +374,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToOne_relationship_from_principal_side() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - existingLyric.Track = _fakers.MusicTrack.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + existingLyric.Track = _fakers.MusicTrack.GenerateOne(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -439,10 +439,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -504,10 +504,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -569,7 +569,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_null_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -620,7 +620,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_missing_data_in_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -673,7 +673,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_array_data_in_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -933,7 +933,7 @@ public async Task Cannot_create_for_ID_and_local_ID_in_relationship_data() public async Task Cannot_create_for_unknown_ID_in_relationship_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -993,7 +993,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_relationship_mismatch() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1051,7 +1051,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeOperationsTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeOperationsTests.cs index 57af5bce7a..d19378c0ce 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeOperationsTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeOperationsTests.cs @@ -27,8 +27,8 @@ public ScopeOperationsTests(IntegrationTestContext { @@ -103,7 +103,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_with_write_scope() { // Arrange - Genre genre = _fakers.Genre.Generate(); + Genre genre = _fakers.Genre.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -133,7 +133,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_with_redundant_scopes() { // Arrange - Actor actor = _fakers.Actor.Generate(); + Actor actor = _fakers.Actor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeWriteTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeWriteTests.cs index bb9d1d05cb..1db9a7cf36 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeWriteTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeWriteTests.cs @@ -24,7 +24,7 @@ public ScopeWriteTests(IntegrationTestContext, Sc public async Task Cannot_create_resource_without_scopes() { // Arrange - Movie newMovie = _fakers.Movie.Generate(); + Movie newMovie = _fakers.Movie.GenerateOne(); var requestBody = new { @@ -62,7 +62,7 @@ public async Task Cannot_create_resource_without_scopes() public async Task Cannot_create_resource_with_relationships_without_scopes() { // Arrange - Movie newMovie = _fakers.Movie.Generate(); + Movie newMovie = _fakers.Movie.GenerateOne(); var requestBody = new { @@ -122,7 +122,7 @@ public async Task Cannot_create_resource_with_relationships_without_scopes() public async Task Cannot_create_resource_with_relationships_with_read_scopes() { // Arrange - Movie newMovie = _fakers.Movie.Generate(); + Movie newMovie = _fakers.Movie.GenerateOne(); var requestBody = new { @@ -185,7 +185,7 @@ public async Task Cannot_create_resource_with_relationships_with_read_scopes() public async Task Cannot_update_resource_without_scopes() { // Arrange - string newTitle = _fakers.Movie.Generate().Title; + string newTitle = _fakers.Movie.GenerateOne().Title; var requestBody = new { @@ -222,7 +222,7 @@ public async Task Cannot_update_resource_without_scopes() public async Task Cannot_update_resource_with_relationships_without_scopes() { // Arrange - string newTitle = _fakers.Movie.Generate().Title; + string newTitle = _fakers.Movie.GenerateOne().Title; var requestBody = new { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Blobs/BlobTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Blobs/BlobTests.cs index fca26c66c3..faac9f2b1f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Blobs/BlobTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Blobs/BlobTests.cs @@ -26,7 +26,7 @@ public BlobTests(IntegrationTestContext, BlobDbCo public async Task Can_get_primary_resource_by_ID() { // Arrange - ImageContainer container = _fakers.ImageContainer.Generate(); + ImageContainer container = _fakers.ImageContainer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -55,7 +55,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource() { // Arrange - ImageContainer newContainer = _fakers.ImageContainer.Generate(); + ImageContainer newContainer = _fakers.ImageContainer.GenerateOne(); var requestBody = new { @@ -102,10 +102,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource() { // Arrange - ImageContainer existingContainer = _fakers.ImageContainer.Generate(); + ImageContainer existingContainer = _fakers.ImageContainer.GenerateOne(); - byte[] newData = _fakers.ImageContainer.Generate().Data; - byte[] newThumbnail = _fakers.ImageContainer.Generate().Thumbnail!; + byte[] newData = _fakers.ImageContainer.GenerateOne().Data; + byte[] newThumbnail = _fakers.ImageContainer.GenerateOne().Thumbnail!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -157,7 +157,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_empty_blob() { // Arrange - ImageContainer existingContainer = _fakers.ImageContainer.Generate(); + ImageContainer existingContainer = _fakers.ImageContainer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -206,7 +206,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_null_blob() { // Arrange - ImageContainer existingContainer = _fakers.ImageContainer.Generate(); + ImageContainer existingContainer = _fakers.ImageContainer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarCompositeKeyAwareRepository.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarCompositeKeyAwareRepository.cs index b818c0f094..089f487908 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarCompositeKeyAwareRepository.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarCompositeKeyAwareRepository.cs @@ -39,8 +39,7 @@ private void RecursiveRewriteFilterInLayer(QueryLayer queryLayer) if (queryLayer.Selection is { IsEmpty: false }) { - foreach (QueryLayer? nextLayer in queryLayer.Selection.GetResourceTypes() - .Select(resourceType => queryLayer.Selection.GetOrCreateSelectors(resourceType)) + foreach (QueryLayer? nextLayer in queryLayer.Selection.GetResourceTypes().Select(queryLayer.Selection.GetOrCreateSelectors) .SelectMany(selectors => selectors.Select(selector => selector.Value).Where(layer => layer != null))) { RecursiveRewriteFilterInLayer(nextLayer!); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarExpressionRewriter.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarExpressionRewriter.cs index c85a2b2a31..e7802bcb09 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarExpressionRewriter.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarExpressionRewriter.cs @@ -89,14 +89,14 @@ private QueryExpression RewriteFilterOnCarStringIds(ResourceFieldChainExpression StringId = carStringId }; - FilterExpression keyComparison = CreateEqualityComparisonOnCompositeKey(existingCarIdChain, tempCar.RegionId, tempCar.LicensePlate!); + LogicalExpression keyComparison = CreateEqualityComparisonOnCompositeKey(existingCarIdChain, tempCar.RegionId, tempCar.LicensePlate!); outerTermsBuilder.Add(keyComparison); } return outerTermsBuilder.Count == 1 ? outerTermsBuilder[0] : new LogicalExpression(LogicalOperator.Or, outerTermsBuilder.ToImmutable()); } - private FilterExpression CreateEqualityComparisonOnCompositeKey(ResourceFieldChainExpression existingCarIdChain, long regionIdValue, + private LogicalExpression CreateEqualityComparisonOnCompositeKey(ResourceFieldChainExpression existingCarIdChain, long regionIdValue, string licensePlateValue) { ResourceFieldChainExpression regionIdChain = ReplaceLastAttributeInChain(existingCarIdChain, _regionIdAttribute); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeKeyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeKeyTests.cs index a015ac52fa..01e8b18fb7 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeKeyTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeKeyTests.cs @@ -32,7 +32,7 @@ public CompositeKeyTests(IntegrationTestContext { @@ -57,7 +57,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_by_ID() { // Arrange - Car car = _fakers.Car.Generate(); + Car car = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -82,7 +82,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_ID() { // Arrange - Car car = _fakers.Car.Generate(); + Car car = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -107,7 +107,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_select_ID() { // Arrange - Car car = _fakers.Car.Generate(); + Car car = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -132,9 +132,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource() { // Arrange - Engine existingEngine = _fakers.Engine.Generate(); + Engine existingEngine = _fakers.Engine.GenerateOne(); - Car newCar = _fakers.Car.Generate(); + Car newCar = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -190,8 +190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship() { // Arrange - Car existingCar = _fakers.Car.Generate(); - Engine existingEngine = _fakers.Engine.Generate(); + Car existingCar = _fakers.Car.GenerateOne(); + Engine existingEngine = _fakers.Engine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -243,8 +243,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_OneToOne_relationship() { // Arrange - Engine existingEngine = _fakers.Engine.Generate(); - existingEngine.Car = _fakers.Car.Generate(); + Engine existingEngine = _fakers.Engine.GenerateOne(); + existingEngine.Car = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -291,8 +291,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_OneToMany_relationship() { // Arrange - Dealership existingDealership = _fakers.Dealership.Generate(); - existingDealership.Inventory = _fakers.Car.Generate(2).ToHashSet(); + Dealership existingDealership = _fakers.Dealership.GenerateOne(); + existingDealership.Inventory = _fakers.Car.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -336,8 +336,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_OneToMany_relationship() { // Arrange - Dealership existingDealership = _fakers.Dealership.Generate(); - Car existingCar = _fakers.Car.Generate(); + Dealership existingDealership = _fakers.Dealership.GenerateOne(); + Car existingCar = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -381,10 +381,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship() { // Arrange - Dealership existingDealership = _fakers.Dealership.Generate(); - existingDealership.Inventory = _fakers.Car.Generate(2).ToHashSet(); + Dealership existingDealership = _fakers.Dealership.GenerateOne(); + existingDealership.Inventory = _fakers.Car.GenerateSet(2); - Car existingCar = _fakers.Car.Generate(); + Car existingCar = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -434,9 +434,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_ManyToOne_relationship_for_unknown_relationship_ID() { // Arrange - Dealership existingDealership = _fakers.Dealership.Generate(); + Dealership existingDealership = _fakers.Dealership.GenerateOne(); - string unknownCarId = _fakers.Car.Generate().StringId!; + string unknownCarId = _fakers.Car.GenerateOne().StringId!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -477,7 +477,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - Car existingCar = _fakers.Car.Generate(); + Car existingCar = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -509,8 +509,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ManyToMany_relationship() { // Arrange - Dealership existingDealership = _fakers.Dealership.Generate(); - existingDealership.SoldCars = _fakers.Car.Generate(2).ToHashSet(); + Dealership existingDealership = _fakers.Dealership.GenerateOne(); + existingDealership.SoldCars = _fakers.Car.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/ApiControllerAttributeLogTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/ApiControllerAttributeLogTests.cs index 5a83599a3a..69c71e5d82 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/ApiControllerAttributeLogTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/ApiControllerAttributeLogTests.cs @@ -6,39 +6,49 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.CustomRoutes; -public sealed class ApiControllerAttributeLogTests : IntegrationTestContext, CustomRouteDbContext> +public sealed class ApiControllerAttributeLogTests : IntegrationTestContext, CustomRouteDbContext>, IAsyncDisposable { - private readonly FakeLoggerFactory _loggerFactory; + private readonly CapturingLoggerProvider _loggerProvider; public ApiControllerAttributeLogTests() { UseController(); - _loggerFactory = new FakeLoggerFactory(LogLevel.Warning); + _loggerProvider = new CapturingLoggerProvider(LogLevel.Warning); ConfigureLogging(options => { - options.ClearProviders(); - options.AddProvider(_loggerFactory); - }); + options.AddProvider(_loggerProvider); - ConfigureServices(services => services.AddSingleton(_loggerFactory)); + options.Services.AddSingleton(_loggerProvider); + }); } [Fact] public void Logs_warning_at_startup_when_ApiControllerAttribute_found() { // Arrange - _loggerFactory.Logger.Clear(); + _loggerProvider.Clear(); // Act _ = Factory; // Assert - IReadOnlyList logLines = _loggerFactory.Logger.GetLines(); + IReadOnlyList logLines = _loggerProvider.GetLines(); logLines.ShouldHaveCount(1); logLines[0].Should().Be( $"[WARNING] Found JSON:API controller '{typeof(CiviliansController)}' with [ApiController]. Please remove this attribute for optimal JSON:API compliance."); } + + public override Task DisposeAsync() + { + _loggerProvider.Dispose(); + return base.DisposeAsync(); + } + + async ValueTask IAsyncDisposable.DisposeAsync() + { + await DisposeAsync(); + } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteTests.cs index e89641470d..92ba48b2f9 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteTests.cs @@ -25,8 +25,8 @@ public CustomRouteTests(IntegrationTestContext { @@ -67,7 +67,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_resources_at_custom_action_method() { // Arrange - List towns = _fakers.Town.Generate(7); + List towns = _fakers.Town.GenerateList(7); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -86,7 +86,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.ManyValue.ShouldHaveCount(5); responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Type == "towns"); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Attributes.ShouldNotBeNull().Any()); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Relationships.ShouldNotBeNull().Any()); + responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Attributes.ShouldNotBeNull().Count > 0); + responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Relationships.ShouldNotBeNull().Count > 0); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/EagerLoadingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/EagerLoadingTests.cs index f12123c203..353417d1ba 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/EagerLoadingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/EagerLoadingTests.cs @@ -32,10 +32,10 @@ public EagerLoadingTests(IntegrationTestContext { @@ -63,15 +63,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_with_nested_eager_loads() { // Arrange - Street street = _fakers.Street.Generate(); - street.Buildings = _fakers.Building.Generate(2); + Street street = _fakers.Street.GenerateOne(); + street.Buildings = _fakers.Building.GenerateList(2); - street.Buildings[0].Windows = _fakers.Window.Generate(2); - street.Buildings[0].PrimaryDoor = _fakers.Door.Generate(); + street.Buildings[0].Windows = _fakers.Window.GenerateList(2); + street.Buildings[0].PrimaryDoor = _fakers.Door.GenerateOne(); - street.Buildings[1].Windows = _fakers.Window.Generate(3); - street.Buildings[1].PrimaryDoor = _fakers.Door.Generate(); - street.Buildings[1].SecondaryDoor = _fakers.Door.Generate(); + street.Buildings[1].Windows = _fakers.Window.GenerateList(3); + street.Buildings[1].PrimaryDoor = _fakers.Door.GenerateOne(); + street.Buildings[1].SecondaryDoor = _fakers.Door.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -99,10 +99,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_with_fieldset() { // Arrange - Street street = _fakers.Street.Generate(); - street.Buildings = _fakers.Building.Generate(1); - street.Buildings[0].Windows = _fakers.Window.Generate(3); - street.Buildings[0].PrimaryDoor = _fakers.Door.Generate(); + Street street = _fakers.Street.GenerateOne(); + street.Buildings = _fakers.Building.GenerateList(1); + street.Buildings[0].Windows = _fakers.Window.GenerateList(3); + street.Buildings[0].PrimaryDoor = _fakers.Door.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -129,12 +129,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_with_includes() { // Arrange - State state = _fakers.State.Generate(); - state.Cities = _fakers.City.Generate(1); - state.Cities[0].Streets = _fakers.Street.Generate(1); - state.Cities[0].Streets[0].Buildings = _fakers.Building.Generate(1); - state.Cities[0].Streets[0].Buildings[0].PrimaryDoor = _fakers.Door.Generate(); - state.Cities[0].Streets[0].Buildings[0].Windows = _fakers.Window.Generate(3); + State state = _fakers.State.GenerateOne(); + state.Cities = _fakers.City.GenerateList(1); + state.Cities[0].Streets = _fakers.Street.GenerateList(1); + state.Cities[0].Streets[0].Buildings = _fakers.Building.GenerateList(1); + state.Cities[0].Streets[0].Buildings[0].PrimaryDoor = _fakers.Door.GenerateOne(); + state.Cities[0].Streets[0].Buildings[0].Windows = _fakers.Window.GenerateList(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -171,13 +171,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources_with_include_and_fieldsets() { // Arrange - State state = _fakers.State.Generate(); - state.Cities = _fakers.City.Generate(1); - state.Cities[0].Streets = _fakers.Street.Generate(1); - state.Cities[0].Streets[0].Buildings = _fakers.Building.Generate(1); - state.Cities[0].Streets[0].Buildings[0].PrimaryDoor = _fakers.Door.Generate(); - state.Cities[0].Streets[0].Buildings[0].SecondaryDoor = _fakers.Door.Generate(); - state.Cities[0].Streets[0].Buildings[0].Windows = _fakers.Window.Generate(1); + State state = _fakers.State.GenerateOne(); + state.Cities = _fakers.City.GenerateList(1); + state.Cities[0].Streets = _fakers.Street.GenerateList(1); + state.Cities[0].Streets[0].Buildings = _fakers.Building.GenerateList(1); + state.Cities[0].Streets[0].Buildings[0].PrimaryDoor = _fakers.Door.GenerateOne(); + state.Cities[0].Streets[0].Buildings[0].SecondaryDoor = _fakers.Door.GenerateOne(); + state.Cities[0].Streets[0].Buildings[0].Windows = _fakers.Window.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -212,7 +212,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource() { // Arrange - Building newBuilding = _fakers.Building.Generate(); + Building newBuilding = _fakers.Building.GenerateOne(); var requestBody = new { @@ -269,13 +269,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource() { // Arrange - Building existingBuilding = _fakers.Building.Generate(); - existingBuilding.PrimaryDoor = _fakers.Door.Generate(); - existingBuilding.SecondaryDoor = _fakers.Door.Generate(); - existingBuilding.Windows = _fakers.Window.Generate(2); + Building existingBuilding = _fakers.Building.GenerateOne(); + existingBuilding.PrimaryDoor = _fakers.Door.GenerateOne(); + existingBuilding.SecondaryDoor = _fakers.Door.GenerateOne(); + existingBuilding.Windows = _fakers.Window.GenerateList(2); - string newBuildingNumber = _fakers.Building.Generate().Number; - string newPrimaryDoorColor = _fakers.Door.Generate().Color; + string newBuildingNumber = _fakers.Building.GenerateOne().Number; + string newPrimaryDoorColor = _fakers.Door.GenerateOne().Color; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -334,8 +334,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_when_primaryDoorColor_is_set_to_null() { // Arrange - Building existingBuilding = _fakers.Building.Generate(); - existingBuilding.PrimaryDoor = _fakers.Door.Generate(); + Building existingBuilding = _fakers.Building.GenerateOne(); + existingBuilding.PrimaryDoor = _fakers.Door.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -378,8 +378,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - Building existingBuilding = _fakers.Building.Generate(); - existingBuilding.PrimaryDoor = _fakers.Door.Generate(); + Building existingBuilding = _fakers.Building.GenerateOne(); + existingBuilding.PrimaryDoor = _fakers.Door.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ExceptionHandlerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ExceptionHandlerTests.cs index 06ad682591..66096c667e 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ExceptionHandlerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ExceptionHandlerTests.cs @@ -22,19 +22,18 @@ public ExceptionHandlerTests(IntegrationTestContext(); testContext.UseController(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Warning); - testContext.ConfigureLogging(options => { - options.ClearProviders(); - options.AddProvider(loggerFactory); + var loggerProvider = new CapturingLoggerProvider(LogLevel.Warning); + options.AddProvider(loggerProvider); + + options.Services.AddSingleton(loggerProvider); }); testContext.ConfigureServices(services => { services.AddResourceService(); - services.AddSingleton(loggerFactory); services.AddScoped(); }); } @@ -43,8 +42,8 @@ public ExceptionHandlerTests(IntegrationTestContext(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); var consumerArticle = new ConsumerArticle { @@ -80,7 +79,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Meta.Should().BeNull(); - IReadOnlyList logMessages = loggerFactory.Logger.GetMessages(); + IReadOnlyList logMessages = loggerProvider.GetMessages(); logMessages.ShouldHaveCount(1); logMessages[0].LogLevel.Should().Be(LogLevel.Warning); @@ -91,8 +90,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Logs_and_produces_error_response_on_deserialization_failure() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); const string requestBody = """{ "data": { "type": "" } }"""; @@ -125,7 +124,7 @@ public async Task Logs_and_produces_error_response_on_deserialization_failure() stackTraceLines.ShouldNotBeEmpty(); }); - IReadOnlyList logMessages = loggerFactory.Logger.GetMessages(); + IReadOnlyList logMessages = loggerProvider.GetMessages(); logMessages.Should().BeEmpty(); } @@ -133,8 +132,8 @@ public async Task Logs_and_produces_error_response_on_deserialization_failure() public async Task Logs_and_produces_error_response_on_serialization_failure() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); var throwingArticle = new ThrowingArticle(); @@ -169,7 +168,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Meta.Should().BeNull(); - IReadOnlyList logMessages = loggerFactory.Logger.GetMessages(); + IReadOnlyList logMessages = loggerProvider.GetMessages(); logMessages.ShouldHaveCount(1); logMessages[0].LogLevel.Should().Be(LogLevel.Error); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/HostingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/HostingTests.cs index 872cd44c3a..397da59595 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/HostingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/HostingTests.cs @@ -25,8 +25,8 @@ public HostingTests(IntegrationTestContext, Hos public async Task Get_primary_resources_with_include_returns_links() { // Arrange - ArtGallery gallery = _fakers.ArtGallery.Generate(); - gallery.Paintings = _fakers.Painting.Generate(1).ToHashSet(); + ArtGallery gallery = _fakers.ArtGallery.GenerateOne(); + gallery.Paintings = _fakers.Painting.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -92,8 +92,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_on_custom_route_returns_links() { // Arrange - Painting painting = _fakers.Painting.Generate(); - painting.ExposedAt = _fakers.ArtGallery.Generate(); + Painting painting = _fakers.Painting.GenerateOne(); + painting.ExposedAt = _fakers.ArtGallery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/IdObfuscationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/IdObfuscationTests.cs index 031ed80fce..02b0001268 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/IdObfuscationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/IdObfuscationTests.cs @@ -24,7 +24,7 @@ public IdObfuscationTests(IntegrationTestContext accounts = _fakers.BankAccount.Generate(2); + List accounts = _fakers.BankAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -72,7 +72,7 @@ public async Task Cannot_filter_equality_for_invalid_ID() public async Task Can_filter_any_in_primary_resources() { // Arrange - List accounts = _fakers.BankAccount.Generate(2); + List accounts = _fakers.BankAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -118,8 +118,8 @@ public async Task Cannot_get_primary_resource_for_invalid_ID() public async Task Can_get_primary_resource_by_ID() { // Arrange - DebitCard card = _fakers.DebitCard.Generate(); - card.Account = _fakers.BankAccount.Generate(); + DebitCard card = _fakers.DebitCard.GenerateOne(); + card.Account = _fakers.BankAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -143,8 +143,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources() { // Arrange - BankAccount account = _fakers.BankAccount.Generate(); - account.Cards = _fakers.DebitCard.Generate(2); + BankAccount account = _fakers.BankAccount.GenerateOne(); + account.Cards = _fakers.DebitCard.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -169,8 +169,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_resource_with_sparse_fieldset() { // Arrange - BankAccount account = _fakers.BankAccount.Generate(); - account.Cards = _fakers.DebitCard.Generate(1); + BankAccount account = _fakers.BankAccount.GenerateOne(); + account.Cards = _fakers.DebitCard.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -199,8 +199,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_relationship() { // Arrange - BankAccount account = _fakers.BankAccount.Generate(); - account.Cards = _fakers.DebitCard.Generate(1); + BankAccount account = _fakers.BankAccount.GenerateOne(); + account.Cards = _fakers.DebitCard.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -224,8 +224,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_relationship() { // Arrange - BankAccount existingAccount = _fakers.BankAccount.Generate(); - DebitCard newCard = _fakers.DebitCard.Generate(); + BankAccount existingAccount = _fakers.BankAccount.GenerateOne(); + DebitCard newCard = _fakers.DebitCard.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -289,13 +289,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_relationship() { // Arrange - BankAccount existingAccount = _fakers.BankAccount.Generate(); - existingAccount.Cards = _fakers.DebitCard.Generate(1); + BankAccount existingAccount = _fakers.BankAccount.GenerateOne(); + existingAccount.Cards = _fakers.DebitCard.GenerateList(1); - DebitCard existingCard = _fakers.DebitCard.Generate(); - existingCard.Account = _fakers.BankAccount.Generate(); + DebitCard existingCard = _fakers.DebitCard.GenerateOne(); + existingCard.Account = _fakers.BankAccount.GenerateOne(); - string newIban = _fakers.BankAccount.Generate().Iban; + string newIban = _fakers.BankAccount.GenerateOne().Iban; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -356,11 +356,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ToMany_relationship() { // Arrange - BankAccount existingAccount = _fakers.BankAccount.Generate(); - existingAccount.Cards = _fakers.DebitCard.Generate(1); + BankAccount existingAccount = _fakers.BankAccount.GenerateOne(); + existingAccount.Cards = _fakers.DebitCard.GenerateList(1); - DebitCard existingDebitCard = _fakers.DebitCard.Generate(); - existingDebitCard.Account = _fakers.BankAccount.Generate(); + DebitCard existingDebitCard = _fakers.DebitCard.GenerateOne(); + existingDebitCard.Account = _fakers.BankAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -402,8 +402,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ToMany_relationship() { // Arrange - BankAccount existingAccount = _fakers.BankAccount.Generate(); - existingAccount.Cards = _fakers.DebitCard.Generate(2); + BankAccount existingAccount = _fakers.BankAccount.GenerateOne(); + existingAccount.Cards = _fakers.DebitCard.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -445,8 +445,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - BankAccount existingAccount = _fakers.BankAccount.Generate(); - existingAccount.Cards = _fakers.DebitCard.Generate(1); + BankAccount existingAccount = _fakers.BankAccount.GenerateOne(); + existingAccount.Cards = _fakers.DebitCard.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscatedIdentifiableController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscatedIdentifiableController.cs index 1c93a9c08c..d82342a0bc 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscatedIdentifiableController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscatedIdentifiableController.cs @@ -6,6 +6,8 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; +#pragma warning disable format + namespace JsonApiDotNetCoreTests.IntegrationTests.IdObfuscation; public abstract class ObfuscatedIdentifiableController( @@ -29,14 +31,16 @@ public Task GetAsync([Required] string id, CancellationToken canc } [HttpGet("{id}/{relationshipName}")] - public Task GetSecondaryAsync([Required] string id, [Required] string relationshipName, CancellationToken cancellationToken) + public Task GetSecondaryAsync([Required] string id, [Required] [PreserveEmptyString] string relationshipName, + CancellationToken cancellationToken) { int idValue = _codec.Decode(id); return base.GetSecondaryAsync(idValue, relationshipName, cancellationToken); } [HttpGet("{id}/relationships/{relationshipName}")] - public Task GetRelationshipAsync([Required] string id, [Required] string relationshipName, CancellationToken cancellationToken) + public Task GetRelationshipAsync([Required] string id, [Required] [PreserveEmptyString] string relationshipName, + CancellationToken cancellationToken) { int idValue = _codec.Decode(id); return base.GetRelationshipAsync(idValue, relationshipName, cancellationToken); @@ -49,7 +53,7 @@ public override Task PostAsync([FromBody] [Required] TResource re } [HttpPost("{id}/relationships/{relationshipName}")] - public Task PostRelationshipAsync([Required] string id, [Required] string relationshipName, + public Task PostRelationshipAsync([Required] string id, [Required] [PreserveEmptyString] string relationshipName, [FromBody] [Required] ISet rightResourceIds, CancellationToken cancellationToken) { int idValue = _codec.Decode(id); @@ -65,8 +69,8 @@ public Task PatchAsync([Required] string id, [FromBody] [Required [HttpPatch("{id}/relationships/{relationshipName}")] // Parameter `[Required] object? rightValue` makes Swashbuckle generate the OpenAPI request body as required. We don't actually validate ModelState, so it doesn't hurt. - public Task PatchRelationshipAsync([Required] string id, [Required] string relationshipName, [FromBody] [Required] object? rightValue, - CancellationToken cancellationToken) + public Task PatchRelationshipAsync([Required] string id, [Required] [PreserveEmptyString] string relationshipName, + [FromBody] [Required] object? rightValue, CancellationToken cancellationToken) { int idValue = _codec.Decode(id); return base.PatchRelationshipAsync(idValue, relationshipName, rightValue, cancellationToken); @@ -80,7 +84,7 @@ public Task DeleteAsync([Required] string id, CancellationToken c } [HttpDelete("{id}/relationships/{relationshipName}")] - public Task DeleteRelationshipAsync([Required] string id, [Required] string relationshipName, + public Task DeleteRelationshipAsync([Required] string id, [Required] [PreserveEmptyString] string relationshipName, [FromBody] [Required] ISet rightResourceIds, CancellationToken cancellationToken) { int idValue = _codec.Decode(id); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateValidationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateValidationTests.cs index 21fe575a2b..93cdf43453 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateValidationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateValidationTests.cs @@ -136,7 +136,7 @@ public async Task Cannot_create_resource_with_invalid_attribute_value() public async Task Cannot_create_resource_with_invalid_DateOnly_TimeOnly_attribute_value() { // Arrange - SystemFile newFile = _fakers.SystemFile.Generate(); + SystemFile newFile = _fakers.SystemFile.GenerateOne(); var requestBody = new { @@ -183,7 +183,7 @@ public async Task Cannot_create_resource_with_invalid_DateOnly_TimeOnly_attribut public async Task Can_create_resource_with_valid_attribute_value() { // Arrange - SystemDirectory newDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory newDirectory = _fakers.SystemDirectory.GenerateOne(); var requestBody = new { @@ -301,11 +301,11 @@ public async Task Does_not_exceed_MaxModelValidationErrors() public async Task Can_create_resource_with_annotated_relationships() { // Arrange - SystemDirectory existingParentDirectory = _fakers.SystemDirectory.Generate(); - SystemDirectory existingSubdirectory = _fakers.SystemDirectory.Generate(); - SystemFile existingFile = _fakers.SystemFile.Generate(); + SystemDirectory existingParentDirectory = _fakers.SystemDirectory.GenerateOne(); + SystemDirectory existingSubdirectory = _fakers.SystemDirectory.GenerateOne(); + SystemFile existingFile = _fakers.SystemFile.GenerateOne(); - SystemDirectory newDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory newDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -377,8 +377,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_annotated_ToMany_relationship() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); - SystemFile existingFile = _fakers.SystemFile.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); + SystemFile existingFile = _fakers.SystemFile.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -413,9 +413,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_omitted_required_attribute_value() { // Arrange - SystemFile existingFile = _fakers.SystemFile.Generate(); + SystemFile existingFile = _fakers.SystemFile.GenerateOne(); - long? newSizeInBytes = _fakers.SystemFile.Generate().SizeInBytes; + long? newSizeInBytes = _fakers.SystemFile.GenerateOne().SizeInBytes; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -451,7 +451,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_null_for_required_attribute_values() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -502,7 +502,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_invalid_attribute_value() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -597,9 +597,9 @@ public async Task Cannot_update_resource_with_invalid_ID() public async Task Can_update_resource_with_valid_attribute_value() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); - string newDirectoryName = _fakers.SystemDirectory.Generate().Name; + string newDirectoryName = _fakers.SystemDirectory.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -635,16 +635,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_annotated_relationships() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); - existingDirectory.Subdirectories = _fakers.SystemDirectory.Generate(1); - existingDirectory.Files = _fakers.SystemFile.Generate(1); - existingDirectory.Parent = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); + existingDirectory.Subdirectories = _fakers.SystemDirectory.GenerateList(1); + existingDirectory.Files = _fakers.SystemFile.GenerateList(1); + existingDirectory.Parent = _fakers.SystemDirectory.GenerateOne(); - SystemDirectory existingParent = _fakers.SystemDirectory.Generate(); - SystemDirectory existingSubdirectory = _fakers.SystemDirectory.Generate(); - SystemFile existingFile = _fakers.SystemFile.Generate(); + SystemDirectory existingParent = _fakers.SystemDirectory.GenerateOne(); + SystemDirectory existingSubdirectory = _fakers.SystemDirectory.GenerateOne(); + SystemFile existingFile = _fakers.SystemFile.GenerateOne(); - string newDirectoryName = _fakers.SystemDirectory.Generate().Name; + string newDirectoryName = _fakers.SystemDirectory.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -714,7 +714,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_multiple_self_references() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -765,7 +765,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_collection_of_self_references() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -811,10 +811,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_annotated_ToOne_relationship() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); - existingDirectory.Parent = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); + existingDirectory.Parent = _fakers.SystemDirectory.GenerateOne(); - SystemDirectory otherExistingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory otherExistingDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -846,10 +846,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_annotated_ToMany_relationship() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); - existingDirectory.Files = _fakers.SystemFile.Generate(2); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); + existingDirectory.Files = _fakers.SystemFile.GenerateList(2); - SystemFile existingFile = _fakers.SystemFile.Generate(); + SystemFile existingFile = _fakers.SystemFile.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -884,8 +884,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_annotated_ToMany_relationship() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); - existingDirectory.Files = _fakers.SystemFile.Generate(1); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); + existingDirectory.Files = _fakers.SystemFile.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/NoModelStateValidationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/NoModelStateValidationTests.cs index ec3d49fe7a..41133fd27f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/NoModelStateValidationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/NoModelStateValidationTests.cs @@ -54,7 +54,7 @@ public async Task Can_create_resource_with_invalid_attribute_value() public async Task Can_update_resource_with_invalid_attribute_value() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -90,8 +90,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_clear_required_OneToOne_relationship_at_primary_endpoint() { // Arrange - SystemVolume existingVolume = _fakers.SystemVolume.Generate(); - existingVolume.RootDirectory = _fakers.SystemDirectory.Generate(); + SystemVolume existingVolume = _fakers.SystemVolume.GenerateOne(); + existingVolume.RootDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDefinition.cs index cdcd268558..bb0b81de2f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDefinition.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDefinition.cs @@ -11,24 +11,28 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.InputValidation.RequestBody; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] public sealed class WorkflowDefinition(IResourceGraph resourceGraph) : JsonApiResourceDefinition(resourceGraph) { - private static readonly Dictionary> StageTransitionTable = new() + private static readonly Dictionary StageTransitionTable = new() { - [WorkflowStage.Created] = new[] - { + // @formatter:place_simple_list_pattern_on_single_line false + + [WorkflowStage.Created] = + [ WorkflowStage.InProgress - }, - [WorkflowStage.InProgress] = new[] - { + ], + [WorkflowStage.InProgress] = + [ WorkflowStage.OnHold, WorkflowStage.Succeeded, WorkflowStage.Failed, WorkflowStage.Canceled - }, - [WorkflowStage.OnHold] = new[] - { + ], + [WorkflowStage.OnHold] = + [ WorkflowStage.InProgress, WorkflowStage.Canceled - } + ] + + // @formatter:place_simple_list_pattern_on_single_line restore }; private WorkflowStage _previousStage; @@ -93,7 +97,7 @@ private static void AssertCanTransitionToStage(WorkflowStage fromStage, Workflow private static bool CanTransitionToStage(WorkflowStage fromStage, WorkflowStage toStage) { - if (StageTransitionTable.TryGetValue(fromStage, out ICollection? possibleNextStages)) + if (StageTransitionTable.TryGetValue(fromStage, out WorkflowStage[]? possibleNextStages)) { return possibleNextStages.Contains(toStage); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithNamespaceTests.cs index 6806eeed7b..a58f68219f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithNamespaceTests.cs @@ -35,7 +35,7 @@ public AbsoluteLinksWithNamespaceTests(IntegrationTestContext { @@ -77,8 +77,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_returns_absolute_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -145,8 +145,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resource_returns_absolute_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -190,8 +190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resources_returns_absolute_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -239,8 +239,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToOne_relationship_returns_absolute_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -274,8 +274,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_returns_absolute_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -309,9 +309,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Create_resource_with_side_effects_and_include_returns_absolute_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); - string newAlbumName = _fakers.PhotoAlbum.Generate().Name; + string newAlbumName = _fakers.PhotoAlbum.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -402,8 +402,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_and_include_returns_absolute_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); - PhotoAlbum existingAlbum = _fakers.PhotoAlbum.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); + PhotoAlbum existingAlbum = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithoutNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithoutNamespaceTests.cs index 6efcf034fa..aaa62c1338 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithoutNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithoutNamespaceTests.cs @@ -35,7 +35,7 @@ public AbsoluteLinksWithoutNamespaceTests(IntegrationTestContext { @@ -77,8 +77,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_returns_absolute_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -145,8 +145,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resource_returns_absolute_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -190,8 +190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resources_returns_absolute_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -239,8 +239,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToOne_relationship_returns_absolute_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -274,8 +274,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_returns_absolute_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -309,9 +309,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Create_resource_with_side_effects_and_include_returns_absolute_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); - string newAlbumName = _fakers.PhotoAlbum.Generate().Name; + string newAlbumName = _fakers.PhotoAlbum.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -402,8 +402,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_and_include_returns_absolute_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); - PhotoAlbum existingAlbum = _fakers.PhotoAlbum.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); + PhotoAlbum existingAlbum = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionIncludeTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionIncludeTests.cs index 6b11fb5403..a7a033d17d 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionIncludeTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionIncludeTests.cs @@ -22,9 +22,9 @@ public LinkInclusionIncludeTests(IntegrationTestContext { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionTests.cs index 1405d648f2..50920697f0 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionTests.cs @@ -24,9 +24,9 @@ public LinkInclusionTests(IntegrationTestContext public async Task Get_primary_resource_with_include_applies_links_visibility_from_ResourceLinksAttribute() { // Arrange - PhotoLocation location = _fakers.PhotoLocation.Generate(); - location.Photo = _fakers.Photo.Generate(); - location.Album = _fakers.PhotoAlbum.Generate(); + PhotoLocation location = _fakers.PhotoLocation.GenerateOne(); + location.Photo = _fakers.Photo.GenerateOne(); + location.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -96,8 +96,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resource_applies_links_visibility_from_ResourceLinksAttribute() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Location = _fakers.PhotoLocation.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Location = _fakers.PhotoLocation.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithNamespaceTests.cs index fbb642844f..27a432f261 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithNamespaceTests.cs @@ -35,7 +35,7 @@ public RelativeLinksWithNamespaceTests(IntegrationTestContext { @@ -77,8 +77,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_returns_relative_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -145,8 +145,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resource_returns_relative_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -190,8 +190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resources_returns_relative_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -239,8 +239,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToOne_relationship_returns_relative_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -274,8 +274,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_returns_relative_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -309,9 +309,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Create_resource_with_side_effects_and_include_returns_relative_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); - string newAlbumName = _fakers.PhotoAlbum.Generate().Name; + string newAlbumName = _fakers.PhotoAlbum.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -402,8 +402,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_and_include_returns_relative_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); - PhotoAlbum existingAlbum = _fakers.PhotoAlbum.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); + PhotoAlbum existingAlbum = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithoutNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithoutNamespaceTests.cs index f767b0cca6..37f24c4ceb 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithoutNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithoutNamespaceTests.cs @@ -35,7 +35,7 @@ public RelativeLinksWithoutNamespaceTests(IntegrationTestContext { @@ -77,8 +77,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_returns_relative_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -145,8 +145,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resource_returns_relative_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -190,8 +190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resources_returns_relative_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -239,8 +239,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToOne_relationship_returns_relative_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -274,8 +274,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_returns_relative_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -309,9 +309,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Create_resource_with_side_effects_and_include_returns_relative_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); - string newAlbumName = _fakers.PhotoAlbum.Generate().Name; + string newAlbumName = _fakers.PhotoAlbum.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -402,8 +402,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_and_include_returns_relative_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); - PhotoAlbum existingAlbum = _fakers.PhotoAlbum.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); + PhotoAlbum existingAlbum = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Logging/LoggingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Logging/LoggingTests.cs index cc56c3980f..9fbd9e8051 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Logging/LoggingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Logging/LoggingTests.cs @@ -20,27 +20,26 @@ public LoggingTests(IntegrationTestContext, Lo testContext.UseController(); testContext.UseController(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Trace); - testContext.ConfigureLogging(options => { - options.ClearProviders(); - options.AddProvider(loggerFactory); + var loggerProvider = new CapturingLoggerProvider((category, level) => + level >= LogLevel.Trace && category.StartsWith("JsonApiDotNetCore.", StringComparison.Ordinal)); + + options.AddProvider(loggerProvider); options.SetMinimumLevel(LogLevel.Trace); - options.AddFilter((category, _) => category != null && category.StartsWith("JsonApiDotNetCore.", StringComparison.Ordinal)); - }); - testContext.ConfigureServices(services => services.AddSingleton(loggerFactory)); + options.Services.AddSingleton(loggerProvider); + }); } [Fact] public async Task Logs_request_body_at_Trace_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); - AuditEntry newEntry = _fakers.AuditEntry.Generate(); + AuditEntry newEntry = _fakers.AuditEntry.GenerateOne(); var requestBody = new { @@ -64,8 +63,7 @@ public async Task Logs_request_body_at_Trace_level() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); - logLines.ShouldNotBeEmpty(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.Should().ContainSingle(line => line.StartsWith("[TRACE] Received POST request at 'http://localhost/auditEntries' with body: <<", StringComparison.Ordinal)); @@ -75,8 +73,8 @@ public async Task Logs_request_body_at_Trace_level() public async Task Logs_response_body_at_Trace_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); // Arrange const string route = "/auditEntries"; @@ -87,8 +85,7 @@ public async Task Logs_response_body_at_Trace_level() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); - logLines.ShouldNotBeEmpty(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.Should().ContainSingle(line => line.StartsWith("[TRACE] Sending 200 response for GET request at 'http://localhost/auditEntries' with body: <<", StringComparison.Ordinal)); @@ -98,8 +95,8 @@ public async Task Logs_response_body_at_Trace_level() public async Task Logs_invalid_request_body_error_at_Information_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); // Arrange const string requestBody = "{ \"data\" {"; @@ -112,21 +109,19 @@ public async Task Logs_invalid_request_body_error_at_Information_level() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - IReadOnlyList logMessages = loggerFactory.Logger.GetMessages(); - logMessages.ShouldNotBeEmpty(); - - logMessages.Should().ContainSingle(message => message.LogLevel == LogLevel.Information && message.Text.Contains("Failed to deserialize request body.")); + LogMessage[] infoMessages = loggerProvider.GetMessages().Where(message => message.LogLevel == LogLevel.Information).ToArray(); + infoMessages.Should().ContainSingle(message => message.Text.Contains("Failed to deserialize request body.")); } [Fact] public async Task Logs_method_parameters_of_abstract_resource_type_at_Trace_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); var existingBowl = new FruitBowl(); - Banana existingBanana = _fakers.Banana.Generate(); + Banana existingBanana = _fakers.Banana.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -157,7 +152,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Should().BeEmpty(); - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.Should().BeEquivalentTo(new[] { @@ -232,11 +227,11 @@ [TRACE] Entering AddToToManyRelationshipAsync(leftResource: null, leftId: {{exis public async Task Logs_method_parameters_of_concrete_resource_type_at_Trace_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); var existingBowl = new FruitBowl(); - Peach existingPeach = _fakers.Peach.Generate(); + Peach existingPeach = _fakers.Peach.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -267,7 +262,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Should().BeEmpty(); - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.Should().BeEquivalentTo(new[] { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/ResourceMetaTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/ResourceMetaTests.cs index 230bdd8b23..6913e57761 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/ResourceMetaTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/ResourceMetaTests.cs @@ -37,7 +37,7 @@ public async Task Returns_resource_meta_from_ResourceDefinition() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List tickets = _fakers.SupportTicket.Generate(3); + List tickets = _fakers.SupportTicket.GenerateList(3); tickets[0].Description = $"Critical: {tickets[0].Description}"; tickets[2].Description = $"Critical: {tickets[2].Description}"; @@ -75,8 +75,8 @@ public async Task Returns_resource_meta_from_ResourceDefinition_in_included_reso // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - ProductFamily family = _fakers.ProductFamily.Generate(); - family.Tickets = _fakers.SupportTicket.Generate(1); + ProductFamily family = _fakers.ProductFamily.GenerateOne(); + family.Tickets = _fakers.SupportTicket.GenerateList(1); family.Tickets[0].Description = $"Critical: {family.Tickets[0].Description}"; await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/TopLevelCountTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/TopLevelCountTests.cs index d074c87160..5a72d4af80 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/TopLevelCountTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/TopLevelCountTests.cs @@ -31,7 +31,7 @@ public TopLevelCountTests(IntegrationTestContext, public async Task Renders_resource_count_at_primary_resources_endpoint_with_filter() { // Arrange - List tickets = _fakers.SupportTicket.Generate(2); + List tickets = _fakers.SupportTicket.GenerateList(2); tickets[1].Description = "Update firmware version"; @@ -57,8 +57,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_resource_count_at_secondary_resources_endpoint_with_filter() { // Arrange - ProductFamily family = _fakers.ProductFamily.Generate(); - family.Tickets = _fakers.SupportTicket.Generate(2); + ProductFamily family = _fakers.ProductFamily.GenerateOne(); + family.Tickets = _fakers.SupportTicket.GenerateList(2); family.Tickets[1].Description = "Update firmware version"; @@ -103,7 +103,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Hides_resource_count_in_create_resource_response() { // Arrange - string newDescription = _fakers.SupportTicket.Generate().Description; + string newDescription = _fakers.SupportTicket.GenerateOne().Description; var requestBody = new { @@ -132,9 +132,9 @@ public async Task Hides_resource_count_in_create_resource_response() public async Task Hides_resource_count_in_update_resource_response() { // Arrange - SupportTicket existingTicket = _fakers.SupportTicket.Generate(); + SupportTicket existingTicket = _fakers.SupportTicket.GenerateOne(); - string newDescription = _fakers.SupportTicket.Generate().Description; + string newDescription = _fakers.SupportTicket.GenerateOne().Description; await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.Group.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.Group.cs index 7421c06256..c37f65b9eb 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.Group.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.Group.cs @@ -17,7 +17,7 @@ public async Task Create_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - string newGroupName = _fakers.DomainGroup.Generate().Name; + string newGroupName = _fakers.DomainGroup.GenerateOne().Name; var requestBody = new { @@ -65,12 +65,12 @@ public async Task Create_group_with_users_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); - string newGroupName = _fakers.DomainGroup.Generate().Name; + string newGroupName = _fakers.DomainGroup.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -153,9 +153,9 @@ public async Task Update_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newGroupName = _fakers.DomainGroup.Generate().Name; + string newGroupName = _fakers.DomainGroup.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -208,18 +208,18 @@ public async Task Update_group_with_users_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup1.Group = existingGroup; - DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup2.Group = existingGroup; - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -301,7 +301,7 @@ public async Task Delete_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -338,8 +338,8 @@ public async Task Delete_group_with_users_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); - existingGroup.Users = _fakers.DomainUser.Generate(1).ToHashSet(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); + existingGroup.Users = _fakers.DomainUser.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -380,18 +380,18 @@ public async Task Replace_users_in_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup1.Group = existingGroup; - DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup2.Group = existingGroup; - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -462,15 +462,15 @@ public async Task Add_users_to_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithSameGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup.Group = existingGroup; - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -531,12 +531,12 @@ public async Task Remove_users_from_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup1.Group = existingGroup; - DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup2.Group = existingGroup; await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.User.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.User.cs index 1a53699b03..0f8c75e7a1 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.User.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.User.cs @@ -17,8 +17,8 @@ public async Task Create_user_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - string newLoginName = _fakers.DomainUser.Generate().LoginName; - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newLoginName = _fakers.DomainUser.GenerateOne().LoginName; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; var requestBody = new { @@ -69,9 +69,9 @@ public async Task Create_user_in_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newLoginName = _fakers.DomainUser.Generate().LoginName; + string newLoginName = _fakers.DomainUser.GenerateOne().LoginName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -143,10 +143,10 @@ public async Task Update_user_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); - string newLoginName = _fakers.DomainUser.Generate().LoginName; - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newLoginName = _fakers.DomainUser.GenerateOne().LoginName; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -205,10 +205,10 @@ public async Task Update_user_clear_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -273,10 +273,10 @@ public async Task Update_user_add_to_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -345,12 +345,12 @@ public async Task Update_user_move_to_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -420,7 +420,7 @@ public async Task Delete_user_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -457,8 +457,8 @@ public async Task Delete_user_in_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -499,8 +499,8 @@ public async Task Clear_group_from_user_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -545,8 +545,8 @@ public async Task Assign_group_to_user_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -595,10 +595,10 @@ public async Task Replace_group_for_user_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.cs index 86456d2d43..e025b7caad 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.cs @@ -77,7 +77,7 @@ public async Task Does_not_rollback_on_message_delivery_error() var messageBroker = _testContext.Factory.Services.GetRequiredService(); messageBroker.SimulateFailure = true; - DomainUser existingUser = _fakers.DomainUser.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/MessagingGroupDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/MessagingGroupDefinition.cs index 7c392eaf7a..048206e20f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/MessagingGroupDefinition.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/MessagingGroupDefinition.cs @@ -53,7 +53,7 @@ public override async Task OnSetToManyRelationshipAsync(DomainGroup group, HasMa { content = new UserAddedToGroupContent(beforeUser.Id, group.Id); } - else if (beforeUser.Group != null && beforeUser.Group.Id != group.Id) + else if (beforeUser.Group.Id != group.Id) { content = new UserMovedToGroupContent(beforeUser.Id, beforeUser.Group.Id, group.Id); } @@ -94,7 +94,7 @@ public override async Task OnAddToRelationshipAsync(DomainGroup group, HasManyAt { content = new UserAddedToGroupContent(beforeUser.Id, group.Id); } - else if (beforeUser.Group != null && beforeUser.Group.Id != group.Id) + else if (beforeUser.Group.Id != group.Id) { content = new UserMovedToGroupContent(beforeUser.Id, beforeUser.Group.Id, group.Id); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.Group.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.Group.cs index cc5b5e84ab..86c01c83b1 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.Group.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.Group.cs @@ -17,7 +17,7 @@ public async Task Create_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - string newGroupName = _fakers.DomainGroup.Generate().Name; + string newGroupName = _fakers.DomainGroup.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -73,12 +73,12 @@ public async Task Create_group_with_users_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); - string newGroupName = _fakers.DomainGroup.Generate().Name; + string newGroupName = _fakers.DomainGroup.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -165,9 +165,9 @@ public async Task Update_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newGroupName = _fakers.DomainGroup.Generate().Name; + string newGroupName = _fakers.DomainGroup.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -224,18 +224,18 @@ public async Task Update_group_with_users_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup1.Group = existingGroup; - DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup2.Group = existingGroup; - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -321,7 +321,7 @@ public async Task Delete_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -362,8 +362,8 @@ public async Task Delete_group_with_users_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); - existingGroup.Users = _fakers.DomainUser.Generate(1).ToHashSet(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); + existingGroup.Users = _fakers.DomainUser.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -408,18 +408,18 @@ public async Task Replace_users_in_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup1.Group = existingGroup; - DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup2.Group = existingGroup; - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -494,15 +494,15 @@ public async Task Add_users_to_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithSameGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup.Group = existingGroup; - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -567,12 +567,12 @@ public async Task Remove_users_from_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup1.Group = existingGroup; - DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup2.Group = existingGroup; await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.User.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.User.cs index 5ec47bb34a..d4c64ab622 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.User.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.User.cs @@ -17,8 +17,8 @@ public async Task Create_user_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - string newLoginName = _fakers.DomainUser.Generate().LoginName; - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newLoginName = _fakers.DomainUser.GenerateOne().LoginName; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -77,9 +77,9 @@ public async Task Create_user_in_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newLoginName = _fakers.DomainUser.Generate().LoginName; + string newLoginName = _fakers.DomainUser.GenerateOne().LoginName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -155,10 +155,10 @@ public async Task Update_user_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); - string newLoginName = _fakers.DomainUser.Generate().LoginName; - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newLoginName = _fakers.DomainUser.GenerateOne().LoginName; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -221,10 +221,10 @@ public async Task Update_user_clear_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -293,10 +293,10 @@ public async Task Update_user_add_to_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -369,12 +369,12 @@ public async Task Update_user_move_to_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -448,7 +448,7 @@ public async Task Delete_user_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -489,8 +489,8 @@ public async Task Delete_user_in_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -535,8 +535,8 @@ public async Task Clear_group_from_user_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -585,8 +585,8 @@ public async Task Assign_group_to_user_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -639,10 +639,10 @@ public async Task Replace_group_for_user_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.cs index 2faa69051a..c0d43533f3 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.cs @@ -41,9 +41,9 @@ public async Task Does_not_add_to_outbox_on_write_error() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUser = _fakers.DomainUser.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); string unknownUserId = Unknown.StringId.For(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyTests.cs index e48470c6ab..530186d540 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyTests.cs @@ -43,7 +43,7 @@ public MultiTenancyTests(IntegrationTestContext shops = _fakers.WebShop.Generate(2); + List shops = _fakers.WebShop.GenerateList(2); shops[0].TenantId = OtherTenantId; shops[1].TenantId = ThisTenantId; @@ -70,12 +70,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Filter_on_primary_resources_hides_other_tenants() { // Arrange - List shops = _fakers.WebShop.Generate(2); + List shops = _fakers.WebShop.GenerateList(2); shops[0].TenantId = OtherTenantId; - shops[0].Products = _fakers.WebProduct.Generate(1); + shops[0].Products = _fakers.WebProduct.GenerateList(1); shops[1].TenantId = ThisTenantId; - shops[1].Products = _fakers.WebProduct.Generate(1); + shops[1].Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -100,12 +100,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_hides_other_tenants() { // Arrange - List shops = _fakers.WebShop.Generate(2); + List shops = _fakers.WebShop.GenerateList(2); shops[0].TenantId = OtherTenantId; - shops[0].Products = _fakers.WebProduct.Generate(1); + shops[0].Products = _fakers.WebProduct.GenerateList(1); shops[1].TenantId = ThisTenantId; - shops[1].Products = _fakers.WebProduct.Generate(1); + shops[1].Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -135,7 +135,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_primary_resource_by_ID_from_other_tenant() { // Arrange - WebShop shop = _fakers.WebShop.Generate(); + WebShop shop = _fakers.WebShop.GenerateOne(); shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -164,9 +164,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resources_from_other_parent_tenant() { // Arrange - WebShop shop = _fakers.WebShop.Generate(); + WebShop shop = _fakers.WebShop.GenerateOne(); shop.TenantId = OtherTenantId; - shop.Products = _fakers.WebProduct.Generate(1); + shop.Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -194,8 +194,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resource_from_other_parent_tenant() { // Arrange - WebProduct product = _fakers.WebProduct.Generate(); - product.Shop = _fakers.WebShop.Generate(); + WebProduct product = _fakers.WebProduct.GenerateOne(); + product.Shop = _fakers.WebShop.GenerateOne(); product.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -224,9 +224,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToMany_relationship_for_other_parent_tenant() { // Arrange - WebShop shop = _fakers.WebShop.Generate(); + WebShop shop = _fakers.WebShop.GenerateOne(); shop.TenantId = OtherTenantId; - shop.Products = _fakers.WebProduct.Generate(1); + shop.Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -254,8 +254,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToOne_relationship_for_other_parent_tenant() { // Arrange - WebProduct product = _fakers.WebProduct.Generate(); - product.Shop = _fakers.WebShop.Generate(); + WebProduct product = _fakers.WebProduct.GenerateOne(); + product.Shop = _fakers.WebShop.GenerateOne(); product.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -284,7 +284,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource() { // Arrange - string newShopUrl = _fakers.WebShop.Generate().Url; + string newShopUrl = _fakers.WebShop.GenerateOne().Url; var requestBody = new { @@ -325,11 +325,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_ToMany_relationship_to_other_tenant() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; - string newShopUrl = _fakers.WebShop.Generate().Url; + string newShopUrl = _fakers.WebShop.GenerateOne().Url; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -383,10 +383,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_ToOne_relationship_to_other_tenant() { // Arrange - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = OtherTenantId; - string newProductName = _fakers.WebProduct.Generate().Name; + string newProductName = _fakers.WebProduct.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -437,11 +437,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = ThisTenantId; - string newProductName = _fakers.WebProduct.Generate().Name; + string newProductName = _fakers.WebProduct.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -485,11 +485,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_from_other_tenant() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; - string newProductName = _fakers.WebProduct.Generate().Name; + string newProductName = _fakers.WebProduct.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -530,11 +530,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_ToMany_relationship_to_other_tenant() { // Arrange - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = ThisTenantId; - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -586,11 +586,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_ToOne_relationship_to_other_tenant() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = ThisTenantId; - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -639,9 +639,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToMany_relationship_for_other_parent_tenant() { // Arrange - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = OtherTenantId; - existingShop.Products = _fakers.WebProduct.Generate(1); + existingShop.Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -674,11 +674,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToMany_relationship_to_other_tenant() { // Arrange - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = ThisTenantId; - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -719,8 +719,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToOne_relationship_for_other_parent_tenant() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -754,11 +754,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToOne_relationship_to_other_tenant() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = ThisTenantId; - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -796,11 +796,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_ToMany_relationship_for_other_parent_tenant() { // Arrange - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = OtherTenantId; - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = ThisTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -840,11 +840,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Cannot_add_to_ToMany_relationship_with_other_tenant() { - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = ThisTenantId; - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -885,9 +885,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_ToMany_relationship_for_other_parent_tenant() { // Arrange - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = OtherTenantId; - existingShop.Products = _fakers.WebProduct.Generate(1); + existingShop.Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -927,8 +927,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = ThisTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -959,8 +959,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_delete_resource_from_other_tenant() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -989,9 +989,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_links_with_tenant_route_parameter() { // Arrange - WebShop shop = _fakers.WebShop.Generate(); + WebShop shop = _fakers.WebShop.GenerateOne(); shop.TenantId = ThisTenantId; - shop.Products = _fakers.WebProduct.Generate(1); + shop.Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/JsonKebabCaseNamingPolicy.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/JsonKebabCaseNamingPolicy.cs index d47de4cf66..1d2f948068 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/JsonKebabCaseNamingPolicy.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/JsonKebabCaseNamingPolicy.cs @@ -36,9 +36,9 @@ public override string ConvertName(string name) if (position + 1 != spanName.Length) { - isNextLower = spanName[position + 1] > 96 && spanName[position + 1] < 123; - isNextUpper = spanName[position + 1] > 64 && spanName[position + 1] < 91; - isNextSpace = spanName[position + 1] == 32; + isNextLower = spanName[position + 1] is >= 'a' and <= 'z'; + isNextUpper = spanName[position + 1] is >= 'A' and <= 'Z'; + isNextSpace = spanName[position + 1] == ' '; } if (isCurrentSpace && (isPreviousSpace || isPreviousSeparator || isNextUpper || isNextSpace)) @@ -47,9 +47,9 @@ public override string ConvertName(string name) } else { - bool isCurrentUpper = spanName[position] > 64 && spanName[position] < 91; - bool isPreviousLower = spanName[position - 1] > 96 && spanName[position - 1] < 123; - bool isPreviousNumber = spanName[position - 1] > 47 && spanName[position - 1] < 58; + bool isCurrentUpper = spanName[position] is >= 'A' and <= 'Z'; + bool isPreviousLower = spanName[position - 1] is >= 'a' and <= 'z'; + bool isPreviousNumber = spanName[position - 1] is >= '0' and <= '9'; if (isCurrentUpper && (isPreviousLower || isPreviousNumber || isNextLower || isNextSpace)) { @@ -76,6 +76,6 @@ public override string ConvertName(string name) } } - return stringBuilder.ToString().ToLower(); + return stringBuilder.ToString().ToLowerInvariant(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/KebabCasingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/KebabCasingTests.cs index f7d407696e..c3e6c30fe4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/KebabCasingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/KebabCasingTests.cs @@ -23,8 +23,8 @@ public KebabCasingTests(IntegrationTestContext pools = _fakers.SwimmingPool.Generate(2); - pools[1].DivingBoards = _fakers.DivingBoard.Generate(1); + List pools = _fakers.SwimmingPool.GenerateList(2); + pools[1].DivingBoards = _fakers.DivingBoard.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -63,8 +63,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_secondary_resources_with_sparse_fieldset() { // Arrange - SwimmingPool pool = _fakers.SwimmingPool.Generate(); - pool.WaterSlides = _fakers.WaterSlide.Generate(2); + SwimmingPool pool = _fakers.SwimmingPool.GenerateOne(); + pool.WaterSlides = _fakers.WaterSlide.GenerateList(2); pool.WaterSlides[0].LengthInMeters = 1; pool.WaterSlides[1].LengthInMeters = 5; @@ -93,7 +93,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource() { // Arrange - SwimmingPool newPool = _fakers.SwimmingPool.Generate(); + SwimmingPool newPool = _fakers.SwimmingPool.GenerateOne(); var requestBody = new { @@ -172,7 +172,7 @@ public async Task Applies_casing_convention_on_error_stack_trace() public async Task Applies_casing_convention_on_source_pointer_from_ModelState() { // Arrange - DivingBoard existingBoard = _fakers.DivingBoard.Generate(); + DivingBoard existingBoard = _fakers.DivingBoard.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/PascalCasingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/PascalCasingTests.cs index 9f71d9de16..22ed5abc87 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/PascalCasingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/PascalCasingTests.cs @@ -24,8 +24,8 @@ public PascalCasingTests(IntegrationTestContext pools = _fakers.SwimmingPool.Generate(2); - pools[1].DivingBoards = _fakers.DivingBoard.Generate(1); + List pools = _fakers.SwimmingPool.GenerateList(2); + pools[1].DivingBoards = _fakers.DivingBoard.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -68,8 +68,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_secondary_resources_with_sparse_fieldset() { // Arrange - SwimmingPool pool = _fakers.SwimmingPool.Generate(); - pool.WaterSlides = _fakers.WaterSlide.Generate(2); + SwimmingPool pool = _fakers.SwimmingPool.GenerateOne(); + pool.WaterSlides = _fakers.WaterSlide.GenerateList(2); pool.WaterSlides[0].LengthInMeters = 1; pool.WaterSlides[1].LengthInMeters = 5; @@ -97,7 +97,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource() { // Arrange - SwimmingPool newPool = _fakers.SwimmingPool.Generate(); + SwimmingPool newPool = _fakers.SwimmingPool.GenerateOne(); var requestBody = new { @@ -176,7 +176,7 @@ public async Task Applies_casing_convention_on_error_stack_trace() public async Task Applies_casing_convention_on_source_pointer_from_ModelState() { // Arrange - DivingBoard existingBoard = _fakers.DivingBoard.Generate(); + DivingBoard existingBoard = _fakers.DivingBoard.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiController.cs index 59a17ab95a..86e99d791c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiController.cs @@ -15,7 +15,8 @@ public IActionResult Get() [HttpPost] public async Task PostAsync() { - string name = await new StreamReader(Request.Body).ReadToEndAsync(); + using var reader = new StreamReader(Request.Body, leaveOpen: true); + string name = await reader.ReadToEndAsync(); if (string.IsNullOrEmpty(name)) { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterParseTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterParseTests.cs index ff0f8f6e09..864b599a37 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterParseTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterParseTests.cs @@ -20,7 +20,8 @@ public sealed class IsUpperCaseFilterParseTests : BaseParseTests public IsUpperCaseFilterParseTests() { - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var scopeParser = new QueryStringParameterScopeParser(); var valueParser = new IsUpperCaseFilterParser(resourceFactory); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterTests.cs index be3240fdef..024930c98b 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterTests.cs @@ -31,7 +31,7 @@ public IsUpperCaseFilterTests(IntegrationTestContext blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = blogs[0].Title.ToLowerInvariant(); blogs[1].Title = blogs[1].Title.ToUpperInvariant(); @@ -60,8 +60,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_casing_in_compound_expression_at_secondary_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(3); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(3); blog.Posts[0].Caption = blog.Posts[0].Caption.ToUpperInvariant(); blog.Posts[0].Url = blog.Posts[0].Url.ToUpperInvariant(); @@ -95,11 +95,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_casing_in_included_resources() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = blogs[0].Title.ToLowerInvariant(); blogs[1].Title = blogs[1].Title.ToUpperInvariant(); - blogs[1].Posts = _fakers.BlogPost.Generate(2); + blogs[1].Posts = _fakers.BlogPost.GenerateList(2); blogs[1].Posts[0].Caption = blogs[1].Posts[0].Caption.ToLowerInvariant(); blogs[1].Posts[1].Caption = blogs[1].Posts[1].Caption.ToUpperInvariant(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseWhereClauseBuilder.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseWhereClauseBuilder.cs index 691a5aacde..4968392ee4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseWhereClauseBuilder.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseWhereClauseBuilder.cs @@ -19,7 +19,7 @@ public override Expression DefaultVisit(QueryExpression expression, QueryClauseB return base.DefaultVisit(expression, context); } - private Expression VisitIsUpperCase(IsUpperCaseExpression expression, QueryClauseBuilderContext context) + private BinaryExpression VisitIsUpperCase(IsUpperCaseExpression expression, QueryClauseBuilderContext context) { Expression propertyAccess = Visit(expression.TargetAttribute, context); MethodCallExpression toUpperMethodCall = Expression.Call(propertyAccess, ToUpperMethod); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterParseTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterParseTests.cs index e9f07521ac..dfecb680db 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterParseTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterParseTests.cs @@ -20,7 +20,8 @@ public sealed class LengthFilterParseTests : BaseParseTests public LengthFilterParseTests() { - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var scopeParser = new QueryStringParameterScopeParser(); var valueParser = new LengthFilterParser(resourceFactory); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterTests.cs index 5b6874f5b9..dcd6b493ea 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterTests.cs @@ -31,7 +31,7 @@ public LengthFilterTests(IntegrationTestContext blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = "X"; blogs[1].Title = "XXX"; @@ -60,8 +60,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_length_at_secondary_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(3); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(3); blog.Posts[0].Caption = "XXX"; blog.Posts[0].Url = "YYY"; @@ -95,11 +95,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_length_in_included_resources() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = "X"; blogs[1].Title = "XXX"; - blogs[1].Posts = _fakers.BlogPost.Generate(2); + blogs[1].Posts = _fakers.BlogPost.GenerateList(2); blogs[1].Posts[0].Caption = "Y"; blogs[1].Posts[1].Caption = "YYY"; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthOrderClauseBuilder.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthOrderClauseBuilder.cs index 4ea6068173..bb530a37b8 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthOrderClauseBuilder.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthOrderClauseBuilder.cs @@ -19,7 +19,7 @@ public override Expression DefaultVisit(QueryExpression expression, QueryClauseB return base.DefaultVisit(expression, context); } - private Expression VisitLength(LengthExpression expression, QueryClauseBuilderContext context) + private MemberExpression VisitLength(LengthExpression expression, QueryClauseBuilderContext context) { Expression propertyAccess = Visit(expression.TargetAttribute, context); return Expression.Property(propertyAccess, LengthPropertyGetter); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthSortTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthSortTests.cs index 340e571ecf..1ac9b05824 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthSortTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthSortTests.cs @@ -31,7 +31,7 @@ public LengthSortTests(IntegrationTestContext blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = "X"; blogs[1].Title = "XXX"; @@ -64,8 +64,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_length_at_secondary_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(3); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(3); blog.Posts[0].Caption = "XXX"; blog.Posts[0].Url = "YYY"; @@ -106,11 +106,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_length_in_included_resources() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = "XXX"; blogs[1].Title = "X"; - blogs[1].Posts = _fakers.BlogPost.Generate(2); + blogs[1].Posts = _fakers.BlogPost.GenerateList(2); blogs[1].Posts[0].Caption = "YYY"; blogs[1].Posts[1].Caption = "Y"; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthWhereClauseBuilder.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthWhereClauseBuilder.cs index 6d553bdd41..282b3416b4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthWhereClauseBuilder.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthWhereClauseBuilder.cs @@ -19,7 +19,7 @@ public override Expression DefaultVisit(QueryExpression expression, QueryClauseB return base.DefaultVisit(expression, context); } - private Expression VisitLength(LengthExpression expression, QueryClauseBuilderContext context) + private MemberExpression VisitLength(LengthExpression expression, QueryClauseBuilderContext context) { Expression propertyAccess = Visit(expression.TargetAttribute, context); return Expression.Property(propertyAccess, LengthPropertyGetter); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterParseTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterParseTests.cs index cc4c3fc7e9..d8ad2f04c3 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterParseTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterParseTests.cs @@ -20,7 +20,8 @@ public sealed class SumFilterParseTests : BaseParseTests public SumFilterParseTests() { - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var scopeParser = new QueryStringParameterScopeParser(); var valueParser = new SumFilterParser(resourceFactory); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterTests.cs index 6589120922..d866964b82 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterTests.cs @@ -32,13 +32,13 @@ public SumFilterTests(IntegrationTestContext posts = _fakers.BlogPost.Generate(2); + List posts = _fakers.BlogPost.GenerateList(2); - posts[0].Comments = _fakers.Comment.Generate(2).ToHashSet(); + posts[0].Comments = _fakers.Comment.GenerateSet(2); posts[0].Comments.ElementAt(0).NumStars = 0; posts[0].Comments.ElementAt(1).NumStars = 1; - posts[1].Comments = _fakers.Comment.Generate(2).ToHashSet(); + posts[1].Comments = _fakers.Comment.GenerateSet(2); posts[1].Comments.ElementAt(0).NumStars = 2; posts[1].Comments.ElementAt(1).NumStars = 3; @@ -66,19 +66,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_sum_on_count_at_secondary_endpoint() { // Arrange - List posts = _fakers.BlogPost.Generate(2); + List posts = _fakers.BlogPost.GenerateList(2); - posts[0].Comments = _fakers.Comment.Generate(2).ToHashSet(); + posts[0].Comments = _fakers.Comment.GenerateSet(2); posts[0].Comments.ElementAt(0).NumStars = 1; posts[0].Comments.ElementAt(1).NumStars = 1; - posts[0].Contributors = _fakers.Woman.Generate(1).OfType().ToHashSet(); + posts[0].Contributors = _fakers.Woman.GenerateSet(1); - posts[1].Comments = _fakers.Comment.Generate(2).ToHashSet(); + posts[1].Comments = _fakers.Comment.GenerateSet(2); posts[1].Comments.ElementAt(0).NumStars = 2; posts[1].Comments.ElementAt(1).NumStars = 2; - posts[1].Contributors = _fakers.Man.Generate(2).OfType().ToHashSet(); - posts[1].Contributors.ElementAt(0).Children = _fakers.Woman.Generate(3).OfType().ToHashSet(); - posts[1].Contributors.ElementAt(1).Children = _fakers.Man.Generate(3).OfType().ToHashSet(); + posts[1].Contributors = _fakers.Man.GenerateSet(2); + posts[1].Contributors.ElementAt(0).Children = _fakers.Woman.GenerateSet(3); + posts[1].Contributors.ElementAt(1).Children = _fakers.Man.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -104,14 +104,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_sum_in_included_resources() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(2); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(2); - blog.Posts[0].Comments = _fakers.Comment.Generate(2).ToHashSet(); + blog.Posts[0].Comments = _fakers.Comment.GenerateSet(2); blog.Posts[0].Comments.ElementAt(0).NumStars = 1; blog.Posts[0].Comments.ElementAt(1).NumStars = 1; - blog.Posts[1].Comments = _fakers.Comment.Generate(2).ToHashSet(); + blog.Posts[1].Comments = _fakers.Comment.GenerateSet(2); blog.Posts[1].Comments.ElementAt(0).NumStars = 1; blog.Posts[1].Comments.ElementAt(1).NumStars = 2; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumWhereClauseBuilder.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumWhereClauseBuilder.cs index b14150e793..55b9102ff4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumWhereClauseBuilder.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumWhereClauseBuilder.cs @@ -18,7 +18,7 @@ public override Expression DefaultVisit(QueryExpression expression, QueryClauseB return base.DefaultVisit(expression, context); } - private Expression VisitSum(SumExpression expression, QueryClauseBuilderContext context) + private MethodCallExpression VisitSum(SumExpression expression, QueryClauseBuilderContext context) { Expression collectionPropertyAccess = Visit(expression.TargetToManyRelationship, context); @@ -39,7 +39,7 @@ private LambdaExpression GetSelectorLambda(QueryExpression expression, QueryClau return Expression.Lambda(body, context.LambdaScope.Parameter); } - private static Expression SumExtensionMethodCall(LambdaExpression selector, QueryClauseBuilderContext context) + private static MethodCallExpression SumExtensionMethodCall(LambdaExpression selector, QueryClauseBuilderContext context) { return Expression.Call(context.ExtensionType, "Sum", [context.LambdaScope.Parameter.Type], context.Source, selector); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetExpression.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetExpression.cs index 110e91012c..1adf976257 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetExpression.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetExpression.cs @@ -36,14 +36,14 @@ public TimeOffsetExpression(LiteralConstantExpression timeSpanConstant) { ArgumentGuard.NotNull(timeSpanConstant); - if (timeSpanConstant.TypedValue.GetType() != typeof(TimeSpan)) + if (timeSpanConstant.TypedValue is not TimeSpan timeSpan) { throw new ArgumentException($"Constant must contain a {nameof(TimeSpan)}.", nameof(timeSpanConstant)); } _timeSpanConstant = timeSpanConstant; - Value = (TimeSpan)timeSpanConstant.TypedValue; + Value = timeSpan; } public override TResult Accept(QueryExpressionVisitor visitor, TArgument argument) diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetTests.cs index 8b8062674c..6dffa5ef18 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetTests.cs @@ -48,7 +48,7 @@ public async Task Can_filter_comparison_on_relative_time(string filterValue, Com // Arrange var clock = _testContext.Factory.Services.GetRequiredService(); - List reminders = _fakers.Reminder.Generate(7); + List reminders = _fakers.Reminder.GenerateList(7); reminders[0].RemindsAt = clock.UtcNow.Add(TimeSpan.FromMinutes(-15)).DateTime.AsUtc(); reminders[1].RemindsAt = clock.UtcNow.Add(TimeSpan.FromMinutes(-10)).DateTime.AsUtc(); reminders[2].RemindsAt = clock.UtcNow.Add(TimeSpan.FromMinutes(-5)).DateTime.AsUtc(); @@ -202,13 +202,13 @@ public async Task Can_filter_comparison_on_relative_time_in_nested_expression() // Arrange var clock = _testContext.Factory.Services.GetRequiredService(); - Calendar calendar = _fakers.Calendar.Generate(); - calendar.Appointments = _fakers.Appointment.Generate(2).ToHashSet(); + Calendar calendar = _fakers.Calendar.GenerateOne(); + calendar.Appointments = _fakers.Appointment.GenerateSet(2); - calendar.Appointments.ElementAt(0).Reminders = _fakers.Reminder.Generate(1); + calendar.Appointments.ElementAt(0).Reminders = _fakers.Reminder.GenerateList(1); calendar.Appointments.ElementAt(0).Reminders[0].RemindsAt = clock.UtcNow.DateTime.AsUtc(); - calendar.Appointments.ElementAt(1).Reminders = _fakers.Reminder.Generate(1); + calendar.Appointments.ElementAt(1).Reminders = _fakers.Reminder.GenerateList(1); calendar.Appointments.ElementAt(1).Reminders[0].RemindsAt = clock.UtcNow.Add(TimeSpan.FromMinutes(30)).DateTime.AsUtc(); await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDepthTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDepthTests.cs index 1bcf0563cf..6b9f74be19 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDepthTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDepthTests.cs @@ -31,7 +31,7 @@ public FilterDepthTests(IntegrationTestContext posts = _fakers.BlogPost.Generate(2); + List posts = _fakers.BlogPost.GenerateList(2); posts[0].Caption = "One"; posts[1].Caption = "Two"; @@ -58,7 +58,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_filter_in_primary_resource() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -88,8 +88,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_secondary_resources() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(2); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(2); blog.Posts[0].Caption = "One"; blog.Posts[1].Caption = "Two"; @@ -115,7 +115,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_filter_in_secondary_resource() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -145,10 +145,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_ManyToOne_relationship() { // Arrange - List posts = _fakers.BlogPost.Generate(3); - posts[0].Author = _fakers.WebAccount.Generate(); + List posts = _fakers.BlogPost.GenerateList(3); + posts[0].Author = _fakers.WebAccount.GenerateOne(); posts[0].Author!.UserName = "Conner"; - posts[1].Author = _fakers.WebAccount.Generate(); + posts[1].Author = _fakers.WebAccount.GenerateOne(); posts[1].Author!.UserName = "Smith"; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -178,8 +178,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_OneToMany_relationship() { // Arrange - List blogs = _fakers.Blog.Generate(2); - blogs[1].Posts = _fakers.BlogPost.Generate(1); + List blogs = _fakers.Blog.GenerateList(2); + blogs[1].Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -204,10 +204,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_OneToMany_relationship_with_nested_condition() { // Arrange - List blogs = _fakers.Blog.Generate(2); - blogs[0].Posts = _fakers.BlogPost.Generate(1); - blogs[1].Posts = _fakers.BlogPost.Generate(1); - blogs[1].Posts[0].Comments = _fakers.Comment.Generate(1).ToHashSet(); + List blogs = _fakers.Blog.GenerateList(2); + blogs[0].Posts = _fakers.BlogPost.GenerateList(1); + blogs[1].Posts = _fakers.BlogPost.GenerateList(1); + blogs[1].Posts[0].Comments = _fakers.Comment.GenerateSet(1); blogs[1].Posts[0].Comments.ElementAt(0).Text = "ABC"; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -233,8 +233,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_ManyToMany_relationship() { // Arrange - List posts = _fakers.BlogPost.Generate(2); - posts[1].Labels = _fakers.Label.Generate(1).ToHashSet(); + List posts = _fakers.BlogPost.GenerateList(2); + posts[1].Labels = _fakers.Label.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -259,12 +259,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_ManyToMany_relationship_with_nested_condition() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); - blogs[0].Posts = _fakers.BlogPost.Generate(1); + blogs[0].Posts = _fakers.BlogPost.GenerateList(1); - blogs[1].Posts = _fakers.BlogPost.Generate(1); - blogs[1].Posts[0].Labels = _fakers.Label.Generate(1).ToHashSet(); + blogs[1].Posts = _fakers.BlogPost.GenerateList(1); + blogs[1].Posts[0].Labels = _fakers.Label.GenerateSet(1); blogs[1].Posts[0].Labels.ElementAt(0).Color = LabelColor.Green; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -290,8 +290,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_scope_of_OneToMany_relationship() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(2); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(2); blog.Posts[0].Caption = "One"; blog.Posts[1].Caption = "Two"; @@ -320,9 +320,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_scope_of_OneToMany_relationship_at_secondary_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(2); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(2); blog.Owner.Posts[0].Caption = "One"; blog.Owner.Posts[1].Caption = "Two"; @@ -350,12 +350,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_scope_of_ManyToMany_relationship() { // Arrange - List posts = _fakers.BlogPost.Generate(2); + List posts = _fakers.BlogPost.GenerateList(2); - posts[0].Labels = _fakers.Label.Generate(1).ToHashSet(); + posts[0].Labels = _fakers.Label.GenerateSet(1); posts[0].Labels.ElementAt(0).Name = "Cold"; - posts[1].Labels = _fakers.Label.Generate(1).ToHashSet(); + posts[1].Labels = _fakers.Label.GenerateSet(1); posts[1].Labels.ElementAt(0).Name = "Hot"; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -383,9 +383,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_scope_of_relationship_chain() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(2); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(2); blog.Owner.Posts[0].Caption = "One"; blog.Owner.Posts[1].Caption = "Two"; @@ -419,7 +419,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_same_scope_multiple_times() { // Arrange - List posts = _fakers.BlogPost.Generate(3); + List posts = _fakers.BlogPost.GenerateList(3); posts[0].Caption = "One"; posts[1].Caption = "Two"; posts[2].Caption = "Three"; @@ -451,10 +451,10 @@ public async Task Can_filter_in_same_scope_multiple_times_using_legacy_notation( var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.EnableLegacyFilterNotation = true; - List posts = _fakers.BlogPost.Generate(3); - posts[0].Author = _fakers.WebAccount.Generate(); - posts[1].Author = _fakers.WebAccount.Generate(); - posts[2].Author = _fakers.WebAccount.Generate(); + List posts = _fakers.BlogPost.GenerateList(3); + posts[0].Author = _fakers.WebAccount.GenerateOne(); + posts[1].Author = _fakers.WebAccount.GenerateOne(); + posts[2].Author = _fakers.WebAccount.GenerateOne(); posts[0].Author!.UserName = "Joe"; posts[0].Author!.DisplayName = "Smith"; @@ -489,14 +489,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_multiple_scopes() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[1].Title = "Technology"; - blogs[1].Owner = _fakers.WebAccount.Generate(); + blogs[1].Owner = _fakers.WebAccount.GenerateOne(); blogs[1].Owner!.UserName = "Smith"; - blogs[1].Owner!.Posts = _fakers.BlogPost.Generate(2); + blogs[1].Owner!.Posts = _fakers.BlogPost.GenerateList(2); blogs[1].Owner!.Posts[0].Caption = "One"; blogs[1].Owner!.Posts[1].Caption = "Two"; - blogs[1].Owner!.Posts[1].Comments = _fakers.Comment.Generate(2).ToHashSet(); + blogs[1].Owner!.Posts[1].Comments = _fakers.Comment.GenerateSet(2); blogs[1].Owner!.Posts[1].Comments.ElementAt(0).CreatedAt = 1.January(2000).AsUtc(); blogs[1].Owner!.Posts[1].Comments.ElementAt(1).CreatedAt = 10.January(2010).AsUtc(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterTests.cs index 42eca44c0b..5f5c0cbeef 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterTests.cs @@ -120,7 +120,7 @@ public async Task Cannot_filter_on_ToMany_relationship_with_blocked_capability() public async Task Can_filter_on_ID() { // Arrange - List accounts = _fakers.WebAccount.Generate(2); + List accounts = _fakers.WebAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Includes/IncludeTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Includes/IncludeTests.cs index 3a5a67097d..6030600791 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Includes/IncludeTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Includes/IncludeTests.cs @@ -31,8 +31,8 @@ public IncludeTests(IntegrationTestContext public async Task Can_include_in_primary_resources() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Author = _fakers.WebAccount.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Author = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -63,8 +63,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_in_primary_resource_by_ID() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Author = _fakers.WebAccount.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Author = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -94,9 +94,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_in_secondary_resource() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(1); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -126,9 +126,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_in_secondary_resources() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(1); - blog.Posts[0].Author = _fakers.WebAccount.Generate(); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(1); + blog.Posts[0].Author = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -158,9 +158,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_ToOne_relationships() { // Arrange - Comment comment = _fakers.Comment.Generate(); - comment.Author = _fakers.WebAccount.Generate(); - comment.Parent = _fakers.BlogPost.Generate(); + Comment comment = _fakers.Comment.GenerateOne(); + comment.Author = _fakers.WebAccount.GenerateOne(); + comment.Parent = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -195,8 +195,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_OneToMany_relationship() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Comments = _fakers.Comment.Generate(1).ToHashSet(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Comments = _fakers.Comment.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -228,8 +228,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_ManyToMany_relationship() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Labels = _fakers.Label.Generate(1).ToHashSet(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Labels = _fakers.Label.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -259,8 +259,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_ManyToMany_relationship_at_secondary_endpoint() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Labels = _fakers.Label.Generate(1).ToHashSet(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Labels = _fakers.Label.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -291,10 +291,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_chain_of_ToOne_relationships() { // Arrange - Comment comment = _fakers.Comment.Generate(); - comment.Parent = _fakers.BlogPost.Generate(); - comment.Parent.Author = _fakers.WebAccount.Generate(); - comment.Parent.Author.Preferences = _fakers.AccountPreferences.Generate(); + Comment comment = _fakers.Comment.GenerateOne(); + comment.Parent = _fakers.BlogPost.GenerateOne(); + comment.Parent.Author = _fakers.WebAccount.GenerateOne(); + comment.Parent.Author.Preferences = _fakers.AccountPreferences.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -335,9 +335,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_chain_of_OneToMany_relationships() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(1); - blog.Posts[0].Comments = _fakers.Comment.Generate(1).ToHashSet(); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(1); + blog.Posts[0].Comments = _fakers.Comment.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -374,11 +374,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_chain_of_recursive_relationships() { // Arrange - Comment comment = _fakers.Comment.Generate(); - comment.Parent = _fakers.BlogPost.Generate(); - comment.Parent.Author = _fakers.WebAccount.Generate(); - comment.Parent.Comments = _fakers.Comment.Generate(2).ToHashSet(); - comment.Parent.Comments.ElementAt(0).Author = _fakers.WebAccount.Generate(); + Comment comment = _fakers.Comment.GenerateOne(); + comment.Parent = _fakers.BlogPost.GenerateOne(); + comment.Parent.Author = _fakers.WebAccount.GenerateOne(); + comment.Parent.Comments = _fakers.Comment.GenerateSet(2); + comment.Parent.Comments.ElementAt(0).Author = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -423,13 +423,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_chain_of_relationships_with_multiple_paths() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(1); - blog.Posts[0].Author = _fakers.WebAccount.Generate(); - blog.Posts[0].Author!.Preferences = _fakers.AccountPreferences.Generate(); - blog.Posts[0].Comments = _fakers.Comment.Generate(2).ToHashSet(); - blog.Posts[0].Comments.ElementAt(0).Author = _fakers.WebAccount.Generate(); - blog.Posts[0].Comments.ElementAt(0).Author!.Posts = _fakers.BlogPost.Generate(1); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(1); + blog.Posts[0].Author = _fakers.WebAccount.GenerateOne(); + blog.Posts[0].Author!.Preferences = _fakers.AccountPreferences.GenerateOne(); + blog.Posts[0].Comments = _fakers.Comment.GenerateSet(2); + blog.Posts[0].Comments.ElementAt(0).Author = _fakers.WebAccount.GenerateOne(); + blog.Posts[0].Comments.ElementAt(0).Author!.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -553,23 +553,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Can_include_chain_of_relationships_with_reused_resources() { - WebAccount author = _fakers.WebAccount.Generate(); - author.Preferences = _fakers.AccountPreferences.Generate(); - author.LoginAttempts = _fakers.LoginAttempt.Generate(1); + WebAccount author = _fakers.WebAccount.GenerateOne(); + author.Preferences = _fakers.AccountPreferences.GenerateOne(); + author.LoginAttempts = _fakers.LoginAttempt.GenerateList(1); - WebAccount reviewer = _fakers.WebAccount.Generate(); - reviewer.Preferences = _fakers.AccountPreferences.Generate(); - reviewer.LoginAttempts = _fakers.LoginAttempt.Generate(1); + WebAccount reviewer = _fakers.WebAccount.GenerateOne(); + reviewer.Preferences = _fakers.AccountPreferences.GenerateOne(); + reviewer.LoginAttempts = _fakers.LoginAttempt.GenerateList(1); - BlogPost post1 = _fakers.BlogPost.Generate(); + BlogPost post1 = _fakers.BlogPost.GenerateOne(); post1.Author = author; post1.Reviewer = reviewer; - WebAccount person = _fakers.WebAccount.Generate(); - person.Preferences = _fakers.AccountPreferences.Generate(); - person.LoginAttempts = _fakers.LoginAttempt.Generate(1); + WebAccount person = _fakers.WebAccount.GenerateOne(); + person.Preferences = _fakers.AccountPreferences.GenerateOne(); + person.LoginAttempts = _fakers.LoginAttempt.GenerateList(1); - BlogPost post2 = _fakers.BlogPost.Generate(); + BlogPost post2 = _fakers.BlogPost.GenerateOne(); post2.Author = person; post2.Reviewer = person; @@ -699,11 +699,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Can_include_chain_with_cyclic_dependency() { - List posts = _fakers.BlogPost.Generate(1); + List posts = _fakers.BlogPost.GenerateList(1); - Blog blog = _fakers.Blog.Generate(); + Blog blog = _fakers.Blog.GenerateOne(); blog.Posts = posts; - blog.Posts[0].Author = _fakers.WebAccount.Generate(); + blog.Posts[0].Author = _fakers.WebAccount.GenerateOne(); blog.Posts[0].Author!.Posts = posts; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -761,9 +761,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Prevents_duplicate_includes_over_single_resource() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); + WebAccount account = _fakers.WebAccount.GenerateOne(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); post.Author = account; post.Reviewer = account; @@ -795,9 +795,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Prevents_duplicate_includes_over_multiple_resources() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); + WebAccount account = _fakers.WebAccount.GenerateOne(); - List posts = _fakers.BlogPost.Generate(2); + List posts = _fakers.BlogPost.GenerateList(2); posts[0].Author = account; posts[1].Author = account; @@ -828,7 +828,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_select_empty_includes() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); + WebAccount account = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -945,8 +945,8 @@ public async Task Cannot_include_relationship_when_nested_inclusion_blocked() public async Task Hides_relationship_and_related_resources_when_viewing_blocked() { // Arrange - Calendar calendar = _fakers.Calendar.Generate(); - calendar.Appointments = _fakers.Appointment.Generate(2).ToHashSet(); + Calendar calendar = _fakers.Calendar.GenerateOne(); + calendar.Appointments = _fakers.Appointment.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -976,8 +976,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Hides_relationship_but_includes_related_resource_when_viewing_blocked_but_accessible_via_other_path() { // Arrange - Calendar calendar = _fakers.Calendar.Generate(); - calendar.MostRecentAppointment = _fakers.Appointment.Generate(); + Calendar calendar = _fakers.Calendar.GenerateOne(); + calendar.MostRecentAppointment = _fakers.Appointment.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -986,7 +986,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => calendar.Appointments = new[] { - _fakers.Appointment.Generate(), + _fakers.Appointment.GenerateOne(), calendar.MostRecentAppointment }.ToHashSet(); @@ -1024,8 +1024,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Ignores_null_parent_in_nested_include() { // Arrange - List posts = _fakers.BlogPost.Generate(2); - posts[0].Reviewer = _fakers.WebAccount.Generate(); + List posts = _fakers.BlogPost.GenerateList(2); + posts[0].Reviewer = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1071,7 +1071,7 @@ public async Task Can_include_at_configured_maximum_inclusion_depth() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.MaximumIncludeDepth = 1; - Blog blog = _fakers.Blog.Generate(); + Blog blog = _fakers.Blog.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithTotalCountTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithTotalCountTests.cs index ac1991ce4d..6cb1b9f851 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithTotalCountTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithTotalCountTests.cs @@ -37,7 +37,7 @@ public PaginationWithTotalCountTests(IntegrationTestContext posts = _fakers.BlogPost.Generate(2); + List posts = _fakers.BlogPost.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -69,7 +69,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_paginate_in_primary_resource() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -99,11 +99,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_in_secondary_resources() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(5); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(5); - Blog otherBlog = _fakers.Blog.Generate(); - otherBlog.Posts = _fakers.BlogPost.Generate(1); + Blog otherBlog = _fakers.Blog.GenerateOne(); + otherBlog.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -134,8 +134,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_in_secondary_resources_without_inverse_relationship() { // Arrange - WebAccount? account = _fakers.WebAccount.Generate(); - account.LoginAttempts = _fakers.LoginAttempt.Generate(2); + WebAccount account = _fakers.WebAccount.GenerateOne(); + account.LoginAttempts = _fakers.LoginAttempt.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -166,7 +166,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_paginate_in_secondary_resource() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -196,9 +196,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_in_scope_of_OneToMany_relationship() { // Arrange - List blogs = _fakers.Blog.Generate(3); - blogs[0].Posts = _fakers.BlogPost.Generate(2); - blogs[1].Posts = _fakers.BlogPost.Generate(2); + List blogs = _fakers.Blog.GenerateList(3); + blogs[0].Posts = _fakers.BlogPost.GenerateList(2); + blogs[1].Posts = _fakers.BlogPost.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -233,9 +233,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_in_scope_of_OneToMany_relationship_at_secondary_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(2); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -267,8 +267,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_OneToMany_relationship_at_relationship_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(4); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(4); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -299,8 +299,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_OneToMany_relationship_at_relationship_endpoint_without_inverse_relationship() { // Arrange - WebAccount? account = _fakers.WebAccount.Generate(); - account.LoginAttempts = _fakers.LoginAttempt.Generate(2); + WebAccount account = _fakers.WebAccount.GenerateOne(); + account.LoginAttempts = _fakers.LoginAttempt.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -333,9 +333,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_in_scope_of_ManyToMany_relationship() { // Arrange - List posts = _fakers.BlogPost.Generate(2); - posts[0].Labels = _fakers.Label.Generate(2).ToHashSet(); - posts[1].Labels = _fakers.Label.Generate(2).ToHashSet(); + List posts = _fakers.BlogPost.GenerateList(2); + posts[0].Labels = _fakers.Label.GenerateSet(2); + posts[1].Labels = _fakers.Label.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -370,8 +370,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_ManyToMany_relationship_at_relationship_endpoint() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Labels = _fakers.Label.Generate(4).ToHashSet(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Labels = _fakers.Label.GenerateSet(4); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -403,10 +403,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_in_multiple_scopes() { // Arrange - List blogs = _fakers.Blog.Generate(2); - blogs[1].Owner = _fakers.WebAccount.Generate(); - blogs[1].Owner!.Posts = _fakers.BlogPost.Generate(2); - blogs[1].Owner!.Posts[1].Comments = _fakers.Comment.Generate(2).ToHashSet(); + List blogs = _fakers.Blog.GenerateList(2); + blogs[1].Owner = _fakers.WebAccount.GenerateOne(); + blogs[1].Owner!.Posts = _fakers.BlogPost.GenerateList(2); + blogs[1].Owner!.Posts[1].Comments = _fakers.Comment.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -501,9 +501,9 @@ public async Task Uses_default_page_number_and_size() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.DefaultPageSize = new PageSize(2); - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(3); - blog.Posts.ForEach(post => post.Labels = _fakers.Label.Generate(3).ToHashSet()); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(3); + blog.Posts.ForEach(post => post.Labels = _fakers.Label.GenerateSet(3)); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -540,8 +540,8 @@ public async Task Returns_all_resources_when_pagination_is_disabled() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.DefaultPageSize = null; - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(25); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(25); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -575,10 +575,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_correct_top_level_links_for_page_number(int pageNumber, int? firstLink, int? lastLink, int? prevLink, int? nextLink) { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); + WebAccount account = _fakers.WebAccount.GenerateOne(); const int totalCount = 3 * DefaultPageSize + 3; - List posts = _fakers.BlogPost.Generate(totalCount); + List posts = _fakers.BlogPost.GenerateList(totalCount); foreach (BlogPost post in posts) { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithoutTotalCountTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithoutTotalCountTests.cs index 9af4e1201e..29d9aa146a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithoutTotalCountTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithoutTotalCountTests.cs @@ -111,7 +111,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_pagination_links_when_page_number_is_specified_in_query_string_with_partially_filled_page() { // Arrange - List posts = _fakers.BlogPost.Generate(12); + List posts = _fakers.BlogPost.GenerateList(12); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -142,7 +142,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_pagination_links_when_page_number_is_specified_in_query_string_with_full_page() { // Arrange - List posts = _fakers.BlogPost.Generate(DefaultPageSize * 3); + List posts = _fakers.BlogPost.GenerateList(DefaultPageSize * 3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -173,8 +173,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_pagination_links_when_page_number_is_specified_in_query_string_with_full_page_at_secondary_endpoint() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); - account.Posts = _fakers.BlogPost.Generate(DefaultPageSize * 3); + WebAccount account = _fakers.WebAccount.GenerateOne(); + account.Posts = _fakers.BlogPost.GenerateList(DefaultPageSize * 3); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/RangeValidationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/RangeValidationTests.cs index 024e923313..f551f4b108 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/RangeValidationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/RangeValidationTests.cs @@ -89,7 +89,7 @@ public async Task Can_use_positive_page_number() public async Task Returns_empty_set_of_resources_when_page_number_is_too_high() { // Arrange - List blogs = _fakers.Blog.Generate(3); + List blogs = _fakers.Blog.GenerateList(3); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SerializerIgnoreConditionTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SerializerIgnoreConditionTests.cs index 0a6204cce4..a0e770e555 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SerializerIgnoreConditionTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SerializerIgnoreConditionTests.cs @@ -30,11 +30,11 @@ public async Task Applies_configuration_for_ignore_condition(JsonIgnoreCondition var options = (JsonApiOptions)Factory.Services.GetRequiredService(); options.SerializerOptions.DefaultIgnoreCondition = configurationValue; - Calendar calendar = _fakers.Calendar.Generate(); + Calendar calendar = _fakers.Calendar.GenerateOne(); calendar.TimeZone = null; calendar.DefaultAppointmentDurationInMinutes = default; calendar.ShowWeekNumbers = true; - calendar.MostRecentAppointment = _fakers.Appointment.Generate(); + calendar.MostRecentAppointment = _fakers.Appointment.GenerateOne(); calendar.MostRecentAppointment.Description = null; calendar.MostRecentAppointment.StartTime = default; calendar.MostRecentAppointment.EndTime = 1.January(2001).AsUtc(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Sorting/SortTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Sorting/SortTests.cs index e1a1788105..0afda4b48e 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Sorting/SortTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Sorting/SortTests.cs @@ -27,7 +27,7 @@ public SortTests(IntegrationTestContext, Q public async Task Can_sort_in_primary_resources() { // Arrange - List posts = _fakers.BlogPost.Generate(3); + List posts = _fakers.BlogPost.GenerateList(3); posts[0].Caption = "B"; posts[1].Caption = "A"; posts[2].Caption = "C"; @@ -57,7 +57,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_sort_in_primary_resource() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -87,8 +87,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_in_secondary_resources() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(3); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(3); blog.Posts[0].Caption = "B"; blog.Posts[1].Caption = "A"; blog.Posts[2].Caption = "C"; @@ -117,7 +117,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_sort_in_secondary_resource() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -147,9 +147,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_OneToMany_relationship() { // Arrange - List blogs = _fakers.Blog.Generate(2); - blogs[0].Posts = _fakers.BlogPost.Generate(2); - blogs[1].Posts = _fakers.BlogPost.Generate(1); + List blogs = _fakers.Blog.GenerateList(2); + blogs[0].Posts = _fakers.BlogPost.GenerateList(2); + blogs[1].Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -175,9 +175,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_ManyToMany_relationship() { // Arrange - List posts = _fakers.BlogPost.Generate(2); - posts[0].Labels = _fakers.Label.Generate(1).ToHashSet(); - posts[1].Labels = _fakers.Label.Generate(2).ToHashSet(); + List posts = _fakers.BlogPost.GenerateList(2); + posts[0].Labels = _fakers.Label.GenerateSet(1); + posts[1].Labels = _fakers.Label.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -203,8 +203,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_in_scope_of_OneToMany_relationship() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); - account.Posts = _fakers.BlogPost.Generate(3); + WebAccount account = _fakers.WebAccount.GenerateOne(); + account.Posts = _fakers.BlogPost.GenerateList(3); account.Posts[0].Caption = "B"; account.Posts[1].Caption = "A"; account.Posts[2].Caption = "C"; @@ -236,9 +236,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_in_scope_of_OneToMany_relationship_at_secondary_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(3); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(3); blog.Owner.Posts[0].Caption = "B"; blog.Owner.Posts[1].Caption = "A"; blog.Owner.Posts[2].Caption = "C"; @@ -270,8 +270,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_in_scope_of_ManyToMany_relationship() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Labels = _fakers.Label.Generate(3).ToHashSet(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Labels = _fakers.Label.GenerateSet(3); post.Labels.ElementAt(0).Name = "B"; post.Labels.ElementAt(1).Name = "A"; post.Labels.ElementAt(2).Name = "C"; @@ -303,11 +303,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_multiple_fields_in_multiple_scopes() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = "Z"; blogs[1].Title = "Y"; - blogs[0].Posts = _fakers.BlogPost.Generate(4); + blogs[0].Posts = _fakers.BlogPost.GenerateList(4); blogs[0].Posts[0].Caption = "B"; blogs[0].Posts[1].Caption = "A"; blogs[0].Posts[2].Caption = "A"; @@ -317,7 +317,7 @@ public async Task Can_sort_on_multiple_fields_in_multiple_scopes() blogs[0].Posts[2].Url = "www.some1.com"; blogs[0].Posts[3].Url = ""; - blogs[0].Posts[0].Comments = _fakers.Comment.Generate(3).ToHashSet(); + blogs[0].Posts[0].Comments = _fakers.Comment.GenerateSet(3); blogs[0].Posts[0].Comments.ElementAt(0).CreatedAt = 1.January(2015).AsUtc(); blogs[0].Posts[0].Comments.ElementAt(1).CreatedAt = 1.January(2014).AsUtc(); blogs[0].Posts[0].Comments.ElementAt(2).CreatedAt = 1.January(2016).AsUtc(); @@ -369,9 +369,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_ManyToOne_relationship() { // Arrange - List posts = _fakers.BlogPost.Generate(2); - posts[0].Author = _fakers.WebAccount.Generate(); - posts[1].Author = _fakers.WebAccount.Generate(); + List posts = _fakers.BlogPost.GenerateList(2); + posts[0].Author = _fakers.WebAccount.GenerateOne(); + posts[1].Author = _fakers.WebAccount.GenerateOne(); posts[0].Author!.DisplayName = "Conner"; posts[1].Author!.DisplayName = "Smith"; @@ -400,16 +400,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_in_multiple_scopes() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = "Cooking"; blogs[1].Title = "Technology"; - blogs[1].Owner = _fakers.WebAccount.Generate(); - blogs[1].Owner!.Posts = _fakers.BlogPost.Generate(2); + blogs[1].Owner = _fakers.WebAccount.GenerateOne(); + blogs[1].Owner!.Posts = _fakers.BlogPost.GenerateList(2); blogs[1].Owner!.Posts[0].Caption = "One"; blogs[1].Owner!.Posts[1].Caption = "Two"; - blogs[1].Owner!.Posts[1].Comments = _fakers.Comment.Generate(2).ToHashSet(); + blogs[1].Owner!.Posts[1].Comments = _fakers.Comment.GenerateSet(2); blogs[1].Owner!.Posts[1].Comments.ElementAt(0).CreatedAt = 1.January(2000).AsUtc(); blogs[1].Owner!.Posts[1].Comments.ElementAt(0).CreatedAt = 10.January(2010).AsUtc(); @@ -523,7 +523,7 @@ public async Task Cannot_sort_on_attribute_with_blocked_capability() public async Task Can_sort_descending_by_ID() { // Arrange - List accounts = _fakers.WebAccount.Generate(3); + List accounts = _fakers.WebAccount.GenerateList(3); accounts[0].Id = 3000; accounts[1].Id = 2000; accounts[2].Id = 1000; @@ -557,7 +557,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Sorts_by_ID_if_none_specified() { // Arrange - List accounts = _fakers.WebAccount.Generate(4); + List accounts = _fakers.WebAccount.GenerateList(4); accounts[0].Id = 300; accounts[1].Id = 200; accounts[2].Id = 100; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs index feba8013b5..1c7477d22d 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs @@ -39,7 +39,7 @@ public async Task Can_select_fields_in_primary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -83,7 +83,7 @@ public async Task Can_select_attribute_in_primary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -118,7 +118,7 @@ public async Task Can_select_relationship_in_primary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -161,8 +161,8 @@ public async Task Can_select_fields_in_secondary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(1); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -209,7 +209,7 @@ public async Task Can_select_fields_in_primary_resource_by_ID() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -252,8 +252,8 @@ public async Task Can_select_fields_of_ManyToOne_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); - post.Author = _fakers.WebAccount.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Author = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -316,8 +316,8 @@ public async Task Can_select_fields_of_OneToMany_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - WebAccount account = _fakers.WebAccount.Generate(); - account.Posts = _fakers.BlogPost.Generate(1); + WebAccount account = _fakers.WebAccount.GenerateOne(); + account.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -377,9 +377,9 @@ public async Task Can_select_fields_of_OneToMany_relationship_at_secondary_endpo var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(1); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -440,8 +440,8 @@ public async Task Can_select_fields_of_ManyToMany_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); - post.Labels = _fakers.Label.Generate(1).ToHashSet(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Labels = _fakers.Label.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -492,9 +492,9 @@ public async Task Can_select_attributes_in_multiple_resource_types() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(1); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -553,9 +553,9 @@ public async Task Can_select_only_top_level_fields_with_multiple_includes() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(1); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -633,7 +633,7 @@ public async Task Can_select_ID() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -669,7 +669,7 @@ public async Task Can_select_empty_fieldset() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -723,7 +723,7 @@ public async Task Cannot_select_on_unknown_resource_type() public async Task Cannot_select_attribute_with_blocked_capability() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); + WebAccount account = _fakers.WebAccount.GenerateOne(); var parameterValue = new MarkedText("^password", '^'); string route = $"/webAccounts/{account.Id}?fields[webAccounts]={parameterValue.Text}"; @@ -748,7 +748,7 @@ public async Task Cannot_select_attribute_with_blocked_capability() public async Task Cannot_select_ToOne_relationship_with_blocked_capability() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); + WebAccount account = _fakers.WebAccount.GenerateOne(); var parameterValue = new MarkedText("^person", '^'); string route = $"/webAccounts/{account.Id}?fields[webAccounts]={parameterValue.Text}"; @@ -773,7 +773,7 @@ public async Task Cannot_select_ToOne_relationship_with_blocked_capability() public async Task Cannot_select_ToMany_relationship_with_blocked_capability() { // Arrange - Calendar calendar = _fakers.Calendar.Generate(); + Calendar calendar = _fakers.Calendar.GenerateOne(); var parameterValue = new MarkedText("^appointments", '^'); string route = $"/calendars/{calendar.Id}?fields[calendars]={parameterValue.Text}"; @@ -801,7 +801,7 @@ public async Task Fetches_all_scalar_properties_when_fieldset_contains_readonly_ var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Blog blog = _fakers.Blog.Generate(); + Blog blog = _fakers.Blog.GenerateOne(); blog.IsPublished = true; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -837,7 +837,7 @@ public async Task Can_select_fields_on_resource_type_multiple_times() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -879,8 +879,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Returns_related_resources_on_broken_resource_linkage() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); - account.Posts = _fakers.BlogPost.Generate(2); + WebAccount account = _fakers.WebAccount.GenerateOne(); + account.Posts = _fakers.BlogPost.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs index 39af545d0c..296dff280c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs @@ -35,7 +35,7 @@ public CreateResourceTests(IntegrationTestContext public async Task Can_create_resource_with_long_ID() { // Arrange - UserAccount newUserAccount = _fakers.UserAccount.Generate(); + UserAccount newUserAccount = _fakers.UserAccount.GenerateOne(); var requestBody = new { @@ -169,7 +169,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_guid_ID() { // Arrange - WorkItemGroup newGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup newGroup = _fakers.WorkItemGroup.GenerateOne(); var requestBody = new { @@ -257,7 +257,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_unknown_attribute() { // Arrange - WorkItem newWorkItem = _fakers.WorkItem.Generate(); + WorkItem newWorkItem = _fakers.WorkItem.GenerateOne(); var requestBody = new { @@ -298,7 +298,7 @@ public async Task Can_create_resource_with_unknown_attribute() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - WorkItem newWorkItem = _fakers.WorkItem.Generate(); + WorkItem newWorkItem = _fakers.WorkItem.GenerateOne(); var requestBody = new { @@ -829,10 +829,10 @@ public async Task Cannot_create_resource_with_incompatible_attribute_value() public async Task Can_create_resource_with_attributes_and_multiple_relationship_types() { // Arrange - List existingUserAccounts = _fakers.UserAccount.Generate(2); - WorkTag existingTag = _fakers.WorkTag.Generate(); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); + WorkTag existingTag = _fakers.WorkTag.GenerateOne(); - string newDescription = _fakers.WorkItem.Generate().Description!; + string newDescription = _fakers.WorkItem.GenerateOne().Description!; await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs index f2e2b5e836..f6c2381474 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs @@ -39,7 +39,7 @@ public async Task Can_create_resource_with_client_generated_guid_ID_having_side_ var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - WorkItemGroup newGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup newGroup = _fakers.WorkItemGroup.GenerateOne(); newGroup.Id = Guid.NewGuid(); var requestBody = new @@ -92,7 +92,7 @@ public async Task Can_create_resource_with_client_generated_guid_ID_having_side_ var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - WorkItemGroup newGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup newGroup = _fakers.WorkItemGroup.GenerateOne(); newGroup.Id = Guid.NewGuid(); var requestBody = new @@ -146,7 +146,7 @@ public async Task Can_create_resource_with_client_generated_string_ID_having_no_ var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - RgbColor newColor = _fakers.RgbColor.Generate(); + RgbColor newColor = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -197,7 +197,7 @@ public async Task Can_create_resource_with_client_generated_string_ID_having_no_ var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - RgbColor newColor = _fakers.RgbColor.Generate(); + RgbColor newColor = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -247,7 +247,7 @@ public async Task Can_create_resource_for_missing_client_generated_ID_having_sid var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - string newDisplayName = _fakers.RgbColor.Generate().DisplayName; + string newDisplayName = _fakers.RgbColor.GenerateOne().DisplayName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -303,7 +303,7 @@ public async Task Cannot_create_resource_for_missing_client_generated_ID(ClientI var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - string newDisplayName = _fakers.RgbColor.Generate().DisplayName; + string newDisplayName = _fakers.RgbColor.GenerateOne().DisplayName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -350,7 +350,7 @@ public async Task Cannot_create_resource_with_client_generated_zero_guid_ID(Clie var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - WorkItemGroup newGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup newGroup = _fakers.WorkItemGroup.GenerateOne(); var requestBody = new { @@ -393,7 +393,7 @@ public async Task Cannot_create_resource_with_client_generated_empty_guid_ID(Cli var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - WorkItemGroup newGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup newGroup = _fakers.WorkItemGroup.GenerateOne(); var requestBody = new { @@ -436,7 +436,7 @@ public async Task Can_create_resource_with_client_generated_empty_string_ID(Clie var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - RgbColor newColor = _fakers.RgbColor.Generate(); + RgbColor newColor = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -487,7 +487,7 @@ public async Task Cannot_create_resource_with_client_generated_zero_long_ID(Clie var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - UserAccount newAccount = _fakers.UserAccount.Generate(); + UserAccount newAccount = _fakers.UserAccount.GenerateOne(); var requestBody = new { @@ -531,7 +531,7 @@ public async Task Cannot_create_resource_with_client_generated_empty_long_ID(Cli var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - UserAccount newAccount = _fakers.UserAccount.Generate(); + UserAccount newAccount = _fakers.UserAccount.GenerateOne(); var requestBody = new { @@ -575,9 +575,9 @@ public async Task Cannot_create_resource_for_existing_client_generated_ID(Client var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = mode; - RgbColor existingColor = _fakers.RgbColor.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); - RgbColor newColor = _fakers.RgbColor.Generate(); + RgbColor newColor = _fakers.RgbColor.GenerateOne(); newColor.Id = existingColor.Id; await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs index f06c2b7820..8a83a14884 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs @@ -25,7 +25,7 @@ public CreateResourceWithToManyRelationshipTests(IntegrationTestContext existingUserAccounts = _fakers.UserAccount.Generate(2); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -89,7 +89,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToMany_relationship_with_include() { // Arrange - List existingUserAccounts = _fakers.UserAccount.Generate(2); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -160,7 +160,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToMany_relationship_with_include_and_secondary_fieldset() { // Arrange - List existingUserAccounts = _fakers.UserAccount.Generate(2); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -231,8 +231,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_ManyToMany_relationship_with_include_and_fieldsets() { // Arrange - List existingTags = _fakers.WorkTag.Generate(3); - WorkItem newWorkItem = _fakers.WorkItem.Generate(); + List existingTags = _fakers.WorkTag.GenerateList(3); + WorkItem newWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -461,7 +461,7 @@ public async Task Cannot_create_for_unknown_relationship_IDs() string workItemId1 = Unknown.StringId.For(); string workItemId2 = Unknown.StringId.AltFor(); - UserAccount newUserAccount = _fakers.UserAccount.Generate(); + UserAccount newUserAccount = _fakers.UserAccount.GenerateOne(); var requestBody = new { @@ -567,7 +567,7 @@ public async Task Cannot_create_on_relationship_type_mismatch() public async Task Can_create_with_duplicates() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs index 2aaf524543..88989016b1 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs @@ -32,10 +32,10 @@ public CreateResourceWithToOneRelationshipTests(IntegrationTestContext { @@ -98,11 +98,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_dependent_side() { // Arrange - RgbColor existingColor = _fakers.RgbColor.Generate(); - existingColor.Group = _fakers.WorkItemGroup.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); + existingColor.Group = _fakers.WorkItemGroup.GenerateOne(); const string newColorId = "0A0B0C"; - string newDisplayName = _fakers.RgbColor.Generate().DisplayName; + string newDisplayName = _fakers.RgbColor.GenerateOne().DisplayName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -163,7 +163,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_relationship_with_include() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -224,8 +224,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_relationship_with_include_and_primary_fieldset() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); - WorkItem newWorkItem = _fakers.WorkItem.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); + WorkItem newWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -301,7 +301,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_with_null_relationship() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -344,7 +344,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_with_missing_data_in_relationship() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -389,7 +389,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_with_array_data_in_relationship() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -651,7 +651,7 @@ public async Task Cannot_create_on_relationship_type_mismatch() public async Task Can_create_resource_with_duplicate_relationship() { // Arrange - List existingUserAccounts = _fakers.UserAccount.Generate(2); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs index 9fb79db38f..de1d1c3ca8 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs @@ -25,7 +25,7 @@ public DeleteResourceTests(IntegrationTestContext { @@ -79,8 +79,8 @@ public async Task Cannot_delete_unknown_resource() public async Task Can_delete_resource_with_OneToOne_relationship_from_dependent_side() { // Arrange - RgbColor existingColor = _fakers.RgbColor.Generate(); - existingColor.Group = _fakers.WorkItemGroup.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); + existingColor.Group = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -114,8 +114,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_existing_resource_with_OneToOne_relationship_from_principal_side() { // Arrange - WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); - existingGroup.Color = _fakers.RgbColor.Generate(); + WorkItemGroup existingGroup = _fakers.WorkItemGroup.GenerateOne(); + existingGroup.Color = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -150,8 +150,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_existing_resource_with_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -186,8 +186,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_with_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs index 35ff4abcb0..711e08d004 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs @@ -22,8 +22,8 @@ public FetchRelationshipTests(IntegrationTestContext { @@ -49,7 +49,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Can_get_empty_ManyToOne_relationship() { - WorkItem workItem = _fakers.WorkItem.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -72,8 +72,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_OneToMany_relationship() { // Arrange - UserAccount userAccount = _fakers.UserAccount.Generate(); - userAccount.AssignedItems = _fakers.WorkItem.Generate(2).ToHashSet(); + UserAccount userAccount = _fakers.UserAccount.GenerateOne(); + userAccount.AssignedItems = _fakers.WorkItem.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -106,7 +106,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_empty_OneToMany_relationship() { // Arrange - UserAccount userAccount = _fakers.UserAccount.Generate(); + UserAccount userAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -129,8 +129,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ManyToMany_relationship() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); - workItem.Tags = _fakers.WorkTag.Generate(2).ToHashSet(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); + workItem.Tags = _fakers.WorkTag.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -163,7 +163,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_empty_ManyToMany_relationship() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -220,7 +220,7 @@ public async Task Cannot_get_relationship_for_unknown_primary_ID() [Fact] public async Task Cannot_get_relationship_for_unknown_relationship_type() { - WorkItem workItem = _fakers.WorkItem.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -243,4 +243,31 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Title.Should().Be("The requested relationship does not exist."); error.Detail.Should().Be($"Resource of type 'workItems' does not contain a relationship named '{Unknown.Relationship}'."); } + + [Fact] + public async Task Cannot_get_relationship_for_whitespace_relationship_name() + { + WorkItem workItem = _fakers.WorkItem.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WorkItems.Add(workItem); + await dbContext.SaveChangesAsync(); + }); + + string route = $"/workItems/{workItem.StringId}/relationships/%20%20"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.ShouldHaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested relationship does not exist."); + error.Detail.Should().Be("Resource of type 'workItems' does not contain a relationship named ' '."); + } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs index 221ab16ec7..9aeeb8eb29 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs @@ -24,7 +24,7 @@ public FetchResourceTests(IntegrationTestContext workItems = _fakers.WorkItem.Generate(2); + List workItems = _fakers.WorkItem.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -77,7 +77,7 @@ public async Task Cannot_get_primary_resources_for_unknown_type() public async Task Can_get_primary_resource_by_ID() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -143,8 +143,8 @@ public async Task Cannot_get_primary_resource_for_unknown_ID() public async Task Can_get_secondary_ManyToOne_resource() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); - workItem.Assignee = _fakers.UserAccount.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); + workItem.Assignee = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -172,7 +172,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_unknown_secondary_ManyToOne_resource() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -195,8 +195,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_OneToMany_resources() { // Arrange - UserAccount userAccount = _fakers.UserAccount.Generate(); - userAccount.AssignedItems = _fakers.WorkItem.Generate(2).ToHashSet(); + UserAccount userAccount = _fakers.UserAccount.GenerateOne(); + userAccount.AssignedItems = _fakers.WorkItem.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -233,7 +233,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_unknown_secondary_OneToMany_resources() { // Arrange - UserAccount userAccount = _fakers.UserAccount.Generate(); + UserAccount userAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -256,8 +256,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_ManyToMany_resources() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); - workItem.Tags = _fakers.WorkTag.Generate(2).ToHashSet(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); + workItem.Tags = _fakers.WorkTag.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -292,7 +292,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_unknown_secondary_ManyToMany_resources() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -352,8 +352,8 @@ public async Task Cannot_get_secondary_resource_for_unknown_primary_ID() public async Task Cannot_get_secondary_resource_for_unknown_relationship() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); - workItem.Assignee = _fakers.UserAccount.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); + workItem.Assignee = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -376,4 +376,32 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Title.Should().Be("The requested relationship does not exist."); error.Detail.Should().Be($"Resource of type 'workItems' does not contain a relationship named '{Unknown.Relationship}'."); } + + [Fact] + public async Task Cannot_get_secondary_resource_for_whitespace_relationship_name() + { + // Arrange + WorkItem workItem = _fakers.WorkItem.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WorkItems.Add(workItem); + await dbContext.SaveChangesAsync(); + }); + + string route = $"/workItems/{workItem.StringId}/%20"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.ShouldHaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested relationship does not exist."); + error.Detail.Should().Be("Resource of type 'workItems' does not contain a relationship named ' '."); + } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs index acf46913a0..3afa0d80de 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs @@ -25,8 +25,8 @@ public AddToToManyRelationshipTests(IntegrationTestContext { @@ -65,10 +65,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_OneToMany_relationship_with_already_assigned_resources() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(2); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -118,9 +118,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ManyToMany_relationship_with_already_assigned_resources() { // Arrange - List existingWorkItems = _fakers.WorkItem.Generate(2); - existingWorkItems[0].Tags = _fakers.WorkTag.Generate(1).ToHashSet(); - existingWorkItems[1].Tags = _fakers.WorkTag.Generate(1).ToHashSet(); + List existingWorkItems = _fakers.WorkItem.GenerateList(2); + existingWorkItems[0].Tags = _fakers.WorkTag.GenerateSet(1); + existingWorkItems[1].Tags = _fakers.WorkTag.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -179,7 +179,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_for_missing_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -214,7 +214,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_for_null_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -246,7 +246,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_for_missing_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -288,7 +288,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_for_unknown_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -331,7 +331,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_for_missing_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -373,7 +373,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_unknown_IDs_to_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -428,7 +428,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_unknown_IDs_to_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -483,8 +483,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_unknown_resource_type_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -519,7 +519,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_unknown_resource_ID_in_url() { // Arrange - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -563,7 +563,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_unknown_relationship_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -601,12 +601,54 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Meta.Should().NotContainKey("requestBody"); } + [Fact] + public async Task Cannot_add_to_whitespace_relationship_in_url() + { + // Arrange + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WorkItems.Add(existingWorkItem); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new[] + { + new + { + type = "userAccounts", + id = Unknown.StringId.For() + } + } + }; + + string route = $"/workItems/{existingWorkItem.StringId}/relationships/%20%20"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.ShouldHaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested relationship does not exist."); + error.Detail.Should().Be("Resource of type 'workItems' does not contain a relationship named ' '."); + error.Source.Should().BeNull(); + error.Meta.Should().NotContainKey("requestBody"); + } + [Fact] public async Task Cannot_add_for_relationship_mismatch_between_url_and_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -649,8 +691,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_with_duplicates() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -698,7 +740,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_with_empty_list() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -733,7 +775,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_with_missing_data_in_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -767,7 +809,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_with_null_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -803,7 +845,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_with_object_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -841,8 +883,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_self_to_cyclic_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Children = _fakers.WorkItem.Generate(1); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Children = _fakers.WorkItem.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -886,8 +928,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_self_to_cyclic_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.RelatedTo = _fakers.WorkItem.Generate(1); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.RelatedTo = _fakers.WorkItem.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -943,7 +985,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_with_blocked_capability() { // Arrange - WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs index 8df5e10a60..7e773e5cb4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs @@ -36,8 +36,8 @@ public RemoveFromToManyRelationshipTests(IntegrationTestContext { @@ -76,9 +76,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_OneToMany_relationship_with_unassigned_existing_resource() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(2).ToHashSet(); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(2); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -130,8 +130,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_OneToMany_relationship_with_extra_removals_from_resource_definition() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(3).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -183,10 +183,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ManyToMany_relationship_with_unassigned_existing_resource() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(2); - WorkTag existingTag = _fakers.WorkTag.Generate(); + WorkTag existingTag = _fakers.WorkTag.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -238,8 +238,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ManyToMany_relationship_with_extra_removals_from_resource_definition() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(3).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -291,7 +291,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_for_missing_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -326,7 +326,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_for_null_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -358,8 +358,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_for_missing_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -401,7 +401,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_for_unknown_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -444,7 +444,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_for_missing_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -486,7 +486,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_unknown_IDs_from_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -541,7 +541,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_unknown_IDs_from_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -596,8 +596,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_unknown_resource_type_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -632,7 +632,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_unknown_resource_ID_in_url() { // Arrange - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -676,7 +676,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_unknown_relationship_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -714,12 +714,54 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Meta.Should().NotContainKey("requestBody"); } + [Fact] + public async Task Cannot_remove_from_whitespace_relationship_in_url() + { + // Arrange + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WorkItems.Add(existingWorkItem); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new[] + { + new + { + type = "userAccounts", + id = Unknown.StringId.For() + } + } + }; + + string route = $"/workItems/{existingWorkItem.StringId}/relationships/%20"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteDeleteAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.ShouldHaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested relationship does not exist."); + error.Detail.Should().Be("Resource of type 'workItems' does not contain a relationship named ' '."); + error.Source.Should().BeNull(); + error.Meta.Should().NotContainKey("requestBody"); + } + [Fact] public async Task Cannot_remove_for_relationship_mismatch_between_url_and_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -762,8 +804,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_with_duplicates() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -811,8 +853,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_with_empty_list() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -848,7 +890,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_with_missing_data_in_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -882,7 +924,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_with_null_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -918,7 +960,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_with_object_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -956,8 +998,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_self_from_cyclic_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Children = _fakers.WorkItem.Generate(1); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Children = _fakers.WorkItem.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1003,8 +1045,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_self_from_cyclic_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.RelatedFrom = _fakers.WorkItem.Generate(1); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.RelatedFrom = _fakers.WorkItem.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1061,7 +1103,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_with_blocked_capability() { // Arrange - WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1103,12 +1145,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => private sealed class RemoveExtraFromWorkItemDefinition(IResourceGraph resourceGraph) : JsonApiResourceDefinition(resourceGraph) { // Enables to verify that not the full relationship was loaded upfront. - public ISet PreloadedSubscribers { get; } = new HashSet(IdentifiableComparer.Instance); - public ISet PreloadedTags { get; } = new HashSet(IdentifiableComparer.Instance); + public HashSet PreloadedSubscribers { get; } = new(IdentifiableComparer.Instance); + public HashSet PreloadedTags { get; } = new(IdentifiableComparer.Instance); // Enables to verify that adding extra IDs for removal from ResourceDefinition works correctly. - public ISet ExtraSubscribersIdsToRemove { get; } = new HashSet(); - public ISet ExtraTagIdsToRemove { get; } = new HashSet(); + public HashSet ExtraSubscribersIdsToRemove { get; } = []; + public HashSet ExtraTagIdsToRemove { get; } = []; public void Reset() { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs index 48c25db786..82776c63c4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs @@ -25,8 +25,8 @@ public ReplaceToManyRelationshipTests(IntegrationTestContext { @@ -61,8 +61,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -97,10 +97,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship_with_already_assigned_resources() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(2); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -149,10 +149,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToMany_relationship_with_already_assigned_resources() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(2); - List existingTags = _fakers.WorkTag.Generate(2); + List existingTags = _fakers.WorkTag.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -208,7 +208,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_missing_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -243,7 +243,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_null_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -275,7 +275,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_missing_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -317,7 +317,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_unknown_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -360,7 +360,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_missing_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -402,7 +402,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_with_unknown_IDs_in_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -459,7 +459,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_with_unknown_IDs_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -516,8 +516,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_on_unknown_resource_type_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -552,7 +552,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_on_unknown_resource_ID_in_url() { // Arrange - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -589,7 +589,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_on_unknown_relationship_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -627,12 +627,54 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Meta.Should().NotContainKey("requestBody"); } + [Fact] + public async Task Cannot_replace_on_whitespace_relationship_in_url() + { + // Arrange + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WorkItems.Add(existingWorkItem); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new[] + { + new + { + type = "userAccounts", + id = Unknown.StringId.For() + } + } + }; + + string route = $"/workItems/{existingWorkItem.StringId}/relationships/%20%20"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.ShouldHaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested relationship does not exist."); + error.Detail.Should().Be("Resource of type 'workItems' does not contain a relationship named ' '."); + error.Source.Should().BeNull(); + error.Meta.Should().NotContainKey("requestBody"); + } + [Fact] public async Task Cannot_replace_on_relationship_mismatch_between_url_and_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -675,10 +717,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_with_duplicates() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -726,7 +768,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_with_missing_data_in_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -760,7 +802,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_with_null_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -796,7 +838,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_with_object_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -834,7 +876,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_cyclic_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -876,7 +918,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_cyclic_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -924,7 +966,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_cyclic_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -967,7 +1009,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_cyclic_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1022,7 +1064,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs index b85e268163..40504b862f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs @@ -26,8 +26,8 @@ public UpdateToOneRelationshipTests(IntegrationTestContext { @@ -62,8 +62,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_OneToOne_relationship() { // Arrange - WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); - existingGroup.Color = _fakers.RgbColor.Generate(); + WorkItemGroup existingGroup = _fakers.WorkItemGroup.GenerateOne(); + existingGroup.Color = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -98,10 +98,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_dependent_side() { // Arrange - WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); - existingGroup.Color = _fakers.RgbColor.Generate(); + WorkItemGroup existingGroup = _fakers.WorkItemGroup.GenerateOne(); + existingGroup.Color = _fakers.RgbColor.GenerateOne(); - RgbColor existingColor = _fakers.RgbColor.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -145,9 +145,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToOne_relationship_from_principal_side() { // Arrange - List existingGroups = _fakers.WorkItemGroup.Generate(2); - existingGroups[0].Color = _fakers.RgbColor.Generate(); - existingGroups[1].Color = _fakers.RgbColor.Generate(); + List existingGroups = _fakers.WorkItemGroup.GenerateList(2); + existingGroups[0].Color = _fakers.RgbColor.GenerateOne(); + existingGroups[1].Color = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -201,8 +201,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToOne_relationship() { // Arrange - List existingUserAccounts = _fakers.UserAccount.Generate(2); - existingUserAccounts[0].AssignedItems = _fakers.WorkItem.Generate(2).ToHashSet(); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); + existingUserAccounts[0].AssignedItems = _fakers.WorkItem.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -244,7 +244,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_missing_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -279,7 +279,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_null_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -311,8 +311,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_missing_data() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -346,8 +346,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_array_data() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -390,7 +390,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_missing_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -429,7 +429,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_unknown_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -469,7 +469,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_missing_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -508,7 +508,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_with_unknown_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -549,8 +549,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_on_unknown_resource_type_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -582,7 +582,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_on_unknown_resource_ID_in_url() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -623,7 +623,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_on_unknown_relationship_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -658,12 +658,51 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Meta.Should().NotContainKey("requestBody"); } + [Fact] + public async Task Cannot_create_on_whitespace_relationship_in_url() + { + // Arrange + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WorkItems.Add(existingWorkItem); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new + { + type = "userAccounts", + id = Unknown.StringId.For() + } + }; + + string route = $"/workItems/{existingWorkItem.StringId}/relationships/%20"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.ShouldHaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested relationship does not exist."); + error.Detail.Should().Be("Resource of type 'workItems' does not contain a relationship named ' '."); + error.Source.Should().BeNull(); + error.Meta.Should().NotContainKey("requestBody"); + } + [Fact] public async Task Cannot_create_on_relationship_mismatch_between_url_and_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - RgbColor existingColor = _fakers.RgbColor.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -703,7 +742,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_cyclic_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -741,7 +780,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_cyclic_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -782,7 +821,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs index 32560b2ad9..d982f48482 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs @@ -28,8 +28,8 @@ public ReplaceToManyRelationshipTests(IntegrationTestContext { @@ -75,8 +75,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -122,10 +122,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship_with_already_assigned_resources() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(2); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -185,10 +185,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToMany_relationship_with_already_assigned_resources() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(2); - List existingTags = _fakers.WorkTag.Generate(2); + List existingTags = _fakers.WorkTag.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -255,8 +255,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship_with_include() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -321,8 +321,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToMany_relationship_with_include_and_fieldsets() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - WorkTag existingTag = _fakers.WorkTag.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + WorkTag existingTag = _fakers.WorkTag.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -397,7 +397,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_missing_relationship_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -450,7 +450,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_unknown_relationship_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -504,7 +504,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_missing_relationship_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -557,7 +557,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_with_unknown_relationship_IDs() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -650,7 +650,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_on_relationship_type_mismatch() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -704,10 +704,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_with_duplicates() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -766,7 +766,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_with_missing_data_in_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -812,7 +812,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_with_null_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -859,7 +859,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_with_object_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -908,7 +908,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_cyclic_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -957,7 +957,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_cyclic_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1016,7 +1016,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_cyclic_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1070,7 +1070,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_cyclic_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1136,7 +1136,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs index 9d328bd9e4..656f2ab56b 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs @@ -40,7 +40,7 @@ public UpdateResourceTests(IntegrationTestContext { @@ -86,8 +86,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_unknown_attribute() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); - string newFirstName = _fakers.UserAccount.Generate().FirstName; + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); + string newFirstName = _fakers.UserAccount.GenerateOne().FirstName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -135,8 +135,8 @@ public async Task Can_update_resource_with_unknown_attribute() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); - string newFirstName = _fakers.UserAccount.Generate().FirstName; + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); + string newFirstName = _fakers.UserAccount.GenerateOne().FirstName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -181,7 +181,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_unknown_relationship() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -235,7 +235,7 @@ public async Task Can_update_resource_with_unknown_relationship() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -278,8 +278,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_partially_update_resource_with_guid_ID() { // Arrange - WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); - string newName = _fakers.WorkItemGroup.Generate().Name; + WorkItemGroup existingGroup = _fakers.WorkItemGroup.GenerateOne(); + string newName = _fakers.WorkItemGroup.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -334,8 +334,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_completely_update_resource_with_string_ID() { // Arrange - RgbColor existingColor = _fakers.RgbColor.Generate(); - string newDisplayName = _fakers.RgbColor.Generate().DisplayName; + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); + string newDisplayName = _fakers.RgbColor.GenerateOne().DisplayName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -382,8 +382,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_without_side_effects() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); - UserAccount newUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); + UserAccount newUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -428,8 +428,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_side_effects() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - string newDescription = _fakers.WorkItem.Generate().Description!; + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + string newDescription = _fakers.WorkItem.GenerateOne().Description!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -484,8 +484,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_side_effects_with_primary_fieldset() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - string newDescription = _fakers.WorkItem.Generate().Description!; + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + string newDescription = _fakers.WorkItem.GenerateOne().Description!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -539,10 +539,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_side_effects_with_include_and_fieldsets() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(1); - string newDescription = _fakers.WorkItem.Generate().Description!; + string newDescription = _fakers.WorkItem.GenerateOne().Description!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -610,8 +610,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_hides_relationship_data_in_response() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Assignee = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Assignee = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -646,7 +646,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_for_missing_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -681,7 +681,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_for_null_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -713,7 +713,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_for_missing_data() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -751,7 +751,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_for_null_data() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -787,7 +787,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_for_array_data() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -830,7 +830,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_for_missing_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -869,7 +869,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_for_unknown_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -909,7 +909,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_for_missing_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -948,7 +948,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_on_unknown_resource_type_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1013,7 +1013,7 @@ public async Task Cannot_update_resource_on_unknown_resource_ID_in_url() public async Task Cannot_update_on_resource_type_mismatch_between_url_and_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1053,7 +1053,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_on_resource_ID_mismatch_between_url_and_body() { // Arrange - List existingWorkItems = _fakers.WorkItem.Generate(2); + List existingWorkItems = _fakers.WorkItem.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1093,7 +1093,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_readonly_attribute() { // Arrange - WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1137,7 +1137,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_for_broken_JSON_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1169,7 +1169,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_change_ID_of_existing_resource() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1213,7 +1213,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_incompatible_ID_value() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1255,7 +1255,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_incompatible_attribute_value() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1303,15 +1303,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_attributes_and_multiple_relationship_types() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Assignee = _fakers.UserAccount.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Assignee = _fakers.UserAccount.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(1); - List existingUserAccounts = _fakers.UserAccount.Generate(2); - WorkTag existingTag = _fakers.WorkTag.Generate(); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); + WorkTag existingTag = _fakers.WorkTag.GenerateOne(); - string newDescription = _fakers.WorkItem.Generate().Description!; + string newDescription = _fakers.WorkItem.GenerateOne().Description!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1411,10 +1411,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_multiple_cyclic_relationship_types() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Parent = _fakers.WorkItem.Generate(); - existingWorkItem.Children = _fakers.WorkItem.Generate(1); - existingWorkItem.RelatedTo = _fakers.WorkItem.Generate(1); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Parent = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Children = _fakers.WorkItem.GenerateList(1); + existingWorkItem.RelatedTo = _fakers.WorkItem.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1507,7 +1507,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_attribute_with_blocked_capability() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs index e04c33d1eb..f290d4b1bd 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs @@ -29,8 +29,8 @@ public UpdateToOneRelationshipTests(IntegrationTestContext { @@ -76,10 +76,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_principal_side() { // Arrange - WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); - existingGroup.Color = _fakers.RgbColor.Generate(); + WorkItemGroup existingGroup = _fakers.WorkItemGroup.GenerateOne(); + existingGroup.Color = _fakers.RgbColor.GenerateOne(); - RgbColor existingColor = _fakers.RgbColor.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -134,9 +134,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToOne_relationship_from_dependent_side() { // Arrange - List existingGroups = _fakers.WorkItemGroup.Generate(2); - existingGroups[0].Color = _fakers.RgbColor.Generate(); - existingGroups[1].Color = _fakers.RgbColor.Generate(); + List existingGroups = _fakers.WorkItemGroup.GenerateList(2); + existingGroups[0].Color = _fakers.RgbColor.GenerateOne(); + existingGroups[1].Color = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -201,8 +201,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_OneToOne_relationship() { // Arrange - RgbColor existingColor = _fakers.RgbColor.Generate(); - existingColor.Group = _fakers.WorkItemGroup.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); + existingColor.Group = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -248,8 +248,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToOne_relationship() { // Arrange - List existingUserAccounts = _fakers.UserAccount.Generate(2); - existingUserAccounts[0].AssignedItems = _fakers.WorkItem.Generate(2).ToHashSet(); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); + existingUserAccounts[0].AssignedItems = _fakers.WorkItem.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -302,8 +302,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_relationship_with_include() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -367,10 +367,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_relationship_with_include_and_fieldsets() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Assignee = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Assignee = _fakers.UserAccount.GenerateOne(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -442,8 +442,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_with_null_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -487,8 +487,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_with_missing_data_in_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -534,8 +534,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_with_array_data_in_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -589,7 +589,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_missing_relationship_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -639,7 +639,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_unknown_relationship_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -690,7 +690,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_missing_relationship_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -740,7 +740,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_with_unknown_relationship_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -792,7 +792,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_on_relationship_type_mismatch() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -843,7 +843,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_cyclic_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -892,7 +892,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_cyclic_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -943,7 +943,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorTests.cs index 6184418d44..0e3ac0eecf 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorTests.cs @@ -31,7 +31,7 @@ public DefaultBehaviorTests(IntegrationTestContext { @@ -143,9 +143,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Deleting_principal_side_of_required_OneToOne_relationship_triggers_cascading_delete() { // Arrange - Order existingOrder = _fakers.Order.Generate(); - existingOrder.Shipment = _fakers.Shipment.Generate(); - existingOrder.Customer = _fakers.Customer.Generate(); + Order existingOrder = _fakers.Order.GenerateOne(); + existingOrder.Shipment = _fakers.Shipment.GenerateOne(); + existingOrder.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -180,9 +180,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_clear_required_ManyToOne_relationship_at_primary_endpoint() { // Arrange - Order existingOrder = _fakers.Order.Generate(); - existingOrder.Shipment = _fakers.Shipment.Generate(); - existingOrder.Customer = _fakers.Customer.Generate(); + Order existingOrder = _fakers.Order.GenerateOne(); + existingOrder.Shipment = _fakers.Shipment.GenerateOne(); + existingOrder.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -228,9 +228,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_clear_required_ManyToOne_relationship_at_relationship_endpoint() { // Arrange - Order existingOrder = _fakers.Order.Generate(); - existingOrder.Shipment = _fakers.Shipment.Generate(); - existingOrder.Customer = _fakers.Customer.Generate(); + Order existingOrder = _fakers.Order.GenerateOne(); + existingOrder.Shipment = _fakers.Shipment.GenerateOne(); + existingOrder.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -263,9 +263,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Clearing_OneToMany_relationship_at_primary_endpoint_triggers_cascading_delete() { // Arrange - Order existingOrder = _fakers.Order.Generate(); - existingOrder.Shipment = _fakers.Shipment.Generate(); - existingOrder.Customer = _fakers.Customer.Generate(); + Order existingOrder = _fakers.Order.GenerateOne(); + existingOrder.Shipment = _fakers.Shipment.GenerateOne(); + existingOrder.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -313,9 +313,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Clearing_OneToMany_relationship_at_update_relationship_endpoint_triggers_cascading_delete() { // Arrange - Order existingOrder = _fakers.Order.Generate(); - existingOrder.Shipment = _fakers.Shipment.Generate(); - existingOrder.Customer = _fakers.Customer.Generate(); + Order existingOrder = _fakers.Order.GenerateOne(); + existingOrder.Shipment = _fakers.Shipment.GenerateOne(); + existingOrder.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -352,9 +352,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Clearing_OneToMany_relationship_at_delete_relationship_endpoint_triggers_cascading_delete() { // Arrange - Order existingOrder = _fakers.Order.Generate(); - existingOrder.Shipment = _fakers.Shipment.Generate(); - existingOrder.Customer = _fakers.Customer.Generate(); + Order existingOrder = _fakers.Order.GenerateOne(); + existingOrder.Shipment = _fakers.Shipment.GenerateOne(); + existingOrder.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -398,12 +398,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_reassign_dependent_side_of_ZeroOrOneToOne_relationship_at_primary_endpoint() { // Arrange - Order orderWithShipment = _fakers.Order.Generate(); - orderWithShipment.Shipment = _fakers.Shipment.Generate(); - orderWithShipment.Customer = _fakers.Customer.Generate(); + Order orderWithShipment = _fakers.Order.GenerateOne(); + orderWithShipment.Shipment = _fakers.Shipment.GenerateOne(); + orderWithShipment.Customer = _fakers.Customer.GenerateOne(); - Order orderWithoutShipment = _fakers.Order.Generate(); - orderWithoutShipment.Customer = _fakers.Customer.Generate(); + Order orderWithoutShipment = _fakers.Order.GenerateOne(); + orderWithoutShipment.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -453,12 +453,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_reassign_dependent_side_of_ZeroOrOneToOne_relationship_at_relationship_endpoint() { // Arrange - Order orderWithShipment = _fakers.Order.Generate(); - orderWithShipment.Shipment = _fakers.Shipment.Generate(); - orderWithShipment.Customer = _fakers.Customer.Generate(); + Order orderWithShipment = _fakers.Order.GenerateOne(); + orderWithShipment.Shipment = _fakers.Shipment.GenerateOne(); + orderWithShipment.Customer = _fakers.Customer.GenerateOne(); - Order orderWithoutShipment = _fakers.Order.Generate(); - orderWithoutShipment.Customer = _fakers.Customer.Generate(); + Order orderWithoutShipment = _fakers.Order.GenerateOne(); + orderWithoutShipment.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/ResourceInjectionTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/ResourceInjectionTests.cs index 3f371b2a67..1dc86eeb1a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/ResourceInjectionTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/ResourceInjectionTests.cs @@ -33,7 +33,7 @@ public async Task Can_get_resource_by_ID() var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService(); clock.UtcNow = 27.January(2021).AsUtc(); - GiftCertificate certificate = _fakers.GiftCertificate.Generate(); + GiftCertificate certificate = _fakers.GiftCertificate.GenerateOne(); certificate.IssueDate = 28.January(2020).AsUtc(); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -63,7 +63,7 @@ public async Task Can_filter_resources_by_ID() var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService(); clock.UtcNow = 27.January(2021).At(13, 53).AsUtc(); - List postOffices = _fakers.PostOffice.Generate(2); + List postOffices = _fakers.PostOffice.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -93,8 +93,8 @@ public async Task Can_get_secondary_resource_with_fieldset() var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService(); clock.UtcNow = 27.January(2021).At(13, 53).AsUtc(); - GiftCertificate certificate = _fakers.GiftCertificate.Generate(); - certificate.Issuer = _fakers.PostOffice.Generate(); + GiftCertificate certificate = _fakers.GiftCertificate.GenerateOne(); + certificate.Issuer = _fakers.PostOffice.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -123,7 +123,7 @@ public async Task Can_create_resource_with_ToOne_relationship_and_include() var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService(); clock.UtcNow = 19.March(1998).At(6, 34).AsUtc(); - PostOffice existingOffice = _fakers.PostOffice.Generate(); + PostOffice existingOffice = _fakers.PostOffice.GenerateOne(); DateTimeOffset newIssueDate = 18.March(1997).AsUtc(); @@ -205,10 +205,10 @@ public async Task Can_update_resource_with_ToMany_relationship() var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService(); clock.UtcNow = 19.March(1998).At(6, 34).AsUtc(); - PostOffice existingOffice = _fakers.PostOffice.Generate(); - existingOffice.GiftCertificates = _fakers.GiftCertificate.Generate(1); + PostOffice existingOffice = _fakers.PostOffice.GenerateOne(); + existingOffice.GiftCertificates = _fakers.GiftCertificate.GenerateList(1); - string newAddress = _fakers.PostOffice.Generate().Address; + string newAddress = _fakers.PostOffice.GenerateOne().Address; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -268,7 +268,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - PostOffice existingOffice = _fakers.PostOffice.Generate(); + PostOffice existingOffice = _fakers.PostOffice.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -320,10 +320,10 @@ public async Task Cannot_delete_unknown_resource() public async Task Can_add_to_ToMany_relationship() { // Arrange - PostOffice existingOffice = _fakers.PostOffice.Generate(); - existingOffice.GiftCertificates = _fakers.GiftCertificate.Generate(1); + PostOffice existingOffice = _fakers.PostOffice.GenerateOne(); + existingOffice.GiftCertificates = _fakers.GiftCertificate.GenerateList(1); - GiftCertificate existingCertificate = _fakers.GiftCertificate.Generate(); + GiftCertificate existingCertificate = _fakers.GiftCertificate.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs index f1590b52ce..a7ff2a2f51 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs @@ -50,7 +50,7 @@ public async Task Include_from_resource_definition_is_blocked() var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.BlockIncludePlanetMoons(); - Planet planet = _fakers.Planet.Generate(); + Planet planet = _fakers.Planet.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -94,9 +94,9 @@ public async Task Include_from_resource_definition_is_added() var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.AutoIncludeStarGivingLightToMoon(); - Moon moon = _fakers.Moon.Generate(); - moon.OrbitsAround = _fakers.Planet.Generate(); - moon.IsGivenLightBy = _fakers.Star.Generate(); + Moon moon = _fakers.Moon.GenerateOne(); + moon.OrbitsAround = _fakers.Planet.GenerateOne(); + moon.IsGivenLightBy = _fakers.Star.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -152,9 +152,9 @@ public async Task Include_from_included_resource_definition_is_added() var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.AutoIncludeStarGivingLightToMoon(); - Planet planet = _fakers.Planet.Generate(); - planet.Moons = _fakers.Moon.Generate(1).ToHashSet(); - planet.Moons.ElementAt(0).IsGivenLightBy = _fakers.Star.Generate(); + Planet planet = _fakers.Planet.GenerateOne(); + planet.Moons = _fakers.Moon.GenerateSet(1); + planet.Moons.ElementAt(0).IsGivenLightBy = _fakers.Star.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -214,7 +214,7 @@ public async Task Filter_from_resource_definition_is_applied() var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.HidePlanetsWithPrivateName(); - List planets = _fakers.Planet.Generate(4); + List planets = _fakers.Planet.GenerateList(4); planets[0].PrivateName = "A"; planets[2].PrivateName = "B"; @@ -262,7 +262,7 @@ public async Task Filter_from_resource_definition_and_query_string_are_applied() var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.HidePlanetsWithPrivateName(); - List planets = _fakers.Planet.Generate(4); + List planets = _fakers.Planet.GenerateList(4); planets[0].HasRingSystem = true; planets[0].PrivateName = "A"; @@ -316,8 +316,8 @@ public async Task Filter_from_resource_definition_is_applied_at_secondary_endpoi var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.HidePlanetsWithPrivateName(); - Star star = _fakers.Star.Generate(); - star.Planets = _fakers.Planet.Generate(4).ToHashSet(); + Star star = _fakers.Star.GenerateOne(); + star.Planets = _fakers.Planet.GenerateSet(4); star.Planets.ElementAt(0).PrivateName = "A"; star.Planets.ElementAt(2).PrivateName = "B"; @@ -368,8 +368,8 @@ public async Task Filter_from_resource_definition_is_applied_at_relationship_end var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.HidePlanetsWithPrivateName(); - Star star = _fakers.Star.Generate(); - star.Planets = _fakers.Planet.Generate(4).ToHashSet(); + Star star = _fakers.Star.GenerateOne(); + star.Planets = _fakers.Planet.GenerateSet(4); star.Planets.ElementAt(0).PrivateName = "A"; star.Planets.ElementAt(2).PrivateName = "B"; @@ -415,7 +415,7 @@ public async Task Sort_from_resource_definition_is_applied() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List stars = _fakers.Star.Generate(3); + List stars = _fakers.Star.GenerateList(3); stars[0].SolarMass = 500m; stars[0].SolarRadius = 1m; @@ -467,7 +467,7 @@ public async Task Sort_from_query_string_is_applied() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List stars = _fakers.Star.Generate(3); + List stars = _fakers.Star.GenerateList(3); stars[0].Name = "B"; stars[0].SolarRadius = 10m; @@ -519,7 +519,7 @@ public async Task Page_size_from_resource_definition_is_applied() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List stars = _fakers.Star.Generate(10); + List stars = _fakers.Star.GenerateList(10); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -561,7 +561,7 @@ public async Task Attribute_inclusion_from_resource_definition_is_applied_for_om // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Star star = _fakers.Star.Generate(); + Star star = _fakers.Star.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -601,7 +601,7 @@ public async Task Attribute_inclusion_from_resource_definition_is_applied_for_fi // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Star star = _fakers.Star.Generate(); + Star star = _fakers.Star.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -642,7 +642,7 @@ public async Task Attribute_exclusion_from_resource_definition_is_applied_for_om // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Star star = _fakers.Star.Generate(); + Star star = _fakers.Star.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -682,7 +682,7 @@ public async Task Attribute_exclusion_from_resource_definition_is_applied_for_fi // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Star star = _fakers.Star.Generate(); + Star star = _fakers.Star.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -722,13 +722,13 @@ public async Task Queryable_parameter_handler_from_resource_definition_is_applie // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List moons = _fakers.Moon.Generate(2); + List moons = _fakers.Moon.GenerateList(2); moons[0].SolarRadius = .5m; - moons[0].OrbitsAround = _fakers.Planet.Generate(); + moons[0].OrbitsAround = _fakers.Planet.GenerateOne(); moons[1].SolarRadius = 50m; - moons[1].OrbitsAround = _fakers.Planet.Generate(); + moons[1].OrbitsAround = _fakers.Planet.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -769,23 +769,23 @@ public async Task Queryable_parameter_handler_from_resource_definition_and_query // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List moons = _fakers.Moon.Generate(4); + List moons = _fakers.Moon.GenerateList(4); moons[0].Name = "Alpha1"; moons[0].SolarRadius = 1m; - moons[0].OrbitsAround = _fakers.Planet.Generate(); + moons[0].OrbitsAround = _fakers.Planet.GenerateOne(); moons[1].Name = "Alpha2"; moons[1].SolarRadius = 5m; - moons[1].OrbitsAround = _fakers.Planet.Generate(); + moons[1].OrbitsAround = _fakers.Planet.GenerateOne(); moons[2].Name = "Beta1"; moons[2].SolarRadius = 1m; - moons[2].OrbitsAround = _fakers.Planet.Generate(); + moons[2].OrbitsAround = _fakers.Planet.GenerateOne(); moons[3].Name = "Beta2"; moons[3].SolarRadius = 5m; - moons[3].OrbitsAround = _fakers.Planet.Generate(); + moons[3].OrbitsAround = _fakers.Planet.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -826,8 +826,8 @@ public async Task Queryable_parameter_handler_from_resource_definition_is_not_ap // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Planet planet = _fakers.Planet.Generate(); - planet.Moons = _fakers.Moon.Generate(1).ToHashSet(); + Planet planet = _fakers.Planet.GenerateOne(); + planet.Moons = _fakers.Moon.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/AesEncryptionService.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/AesEncryptionService.cs index 07cd2c40d0..aa4417a223 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/AesEncryptionService.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/AesEncryptionService.cs @@ -9,7 +9,7 @@ public sealed class AesEncryptionService : IEncryptionService public string Encrypt(string value) { - using SymmetricAlgorithm cipher = CreateCipher(); + using Aes cipher = CreateCipher(); using ICryptoTransform transform = cipher.CreateEncryptor(); byte[] plaintext = Encoding.UTF8.GetBytes(value); @@ -26,7 +26,7 @@ public string Decrypt(string value) { byte[] buffer = Convert.FromBase64String(value); - using SymmetricAlgorithm cipher = CreateCipher(); + using Aes cipher = CreateCipher(); byte[] initVector = new byte[cipher.IV.Length]; Buffer.BlockCopy(buffer, 0, initVector, 0, initVector.Length); @@ -38,7 +38,7 @@ public string Decrypt(string value) return Encoding.UTF8.GetString(plainBytes); } - private static SymmetricAlgorithm CreateCipher() + private static Aes CreateCipher() { var cipher = Aes.Create(); cipher.Key = CryptoKey; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/ResourceDefinitionSerializationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/ResourceDefinitionSerializationTests.cs index 950ba84b00..adb00dbfbf 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/ResourceDefinitionSerializationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/ResourceDefinitionSerializationTests.cs @@ -42,7 +42,7 @@ public async Task Encrypts_on_get_primary_resources() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List students = _fakers.Student.Generate(2); + List students = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -91,9 +91,9 @@ public async Task Encrypts_on_get_primary_resources_with_ToMany_include() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List scholarships = _fakers.Scholarship.Generate(2); - scholarships[0].Participants = _fakers.Student.Generate(2); - scholarships[1].Participants = _fakers.Student.Generate(2); + List scholarships = _fakers.Scholarship.GenerateList(2); + scholarships[0].Participants = _fakers.Student.GenerateList(2); + scholarships[1].Participants = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -162,7 +162,7 @@ public async Task Encrypts_on_get_primary_resource_by_ID() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Student student = _fakers.Student.Generate(); + Student student = _fakers.Student.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -201,8 +201,8 @@ public async Task Encrypts_on_get_secondary_resources() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship scholarship = _fakers.Scholarship.Generate(); - scholarship.Participants = _fakers.Student.Generate(2); + Scholarship scholarship = _fakers.Scholarship.GenerateOne(); + scholarship.Participants = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -250,8 +250,8 @@ public async Task Encrypts_on_get_secondary_resource() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship scholarship = _fakers.Scholarship.Generate(); - scholarship.PrimaryContact = _fakers.Student.Generate(); + Scholarship scholarship = _fakers.Scholarship.GenerateOne(); + scholarship.PrimaryContact = _fakers.Student.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -290,8 +290,8 @@ public async Task Encrypts_on_get_secondary_resource_with_ToOne_include() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship scholarship = _fakers.Scholarship.Generate(); - scholarship.PrimaryContact = _fakers.Student.Generate(); + Scholarship scholarship = _fakers.Scholarship.GenerateOne(); + scholarship.PrimaryContact = _fakers.Student.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -332,8 +332,8 @@ public async Task Decrypts_on_create_resource() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - string newName = _fakers.Student.Generate().Name; - string newSocialSecurityNumber = _fakers.Student.Generate().SocialSecurityNumber; + string newName = _fakers.Student.GenerateOne().Name; + string newSocialSecurityNumber = _fakers.Student.GenerateOne().SocialSecurityNumber; var requestBody = new { @@ -389,10 +389,10 @@ public async Task Encrypts_on_create_resource_with_included_ToOne_relationship() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Student existingStudent = _fakers.Student.Generate(); + Student existingStudent = _fakers.Student.GenerateOne(); - string newProgramName = _fakers.Scholarship.Generate().ProgramName; - decimal newAmount = _fakers.Scholarship.Generate().Amount; + string newProgramName = _fakers.Scholarship.GenerateOne().ProgramName; + decimal newAmount = _fakers.Scholarship.GenerateOne().Amount; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -457,9 +457,9 @@ public async Task Decrypts_on_update_resource() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Student existingStudent = _fakers.Student.Generate(); + Student existingStudent = _fakers.Student.GenerateOne(); - string newSocialSecurityNumber = _fakers.Student.Generate().SocialSecurityNumber; + string newSocialSecurityNumber = _fakers.Student.GenerateOne().SocialSecurityNumber; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -519,10 +519,10 @@ public async Task Encrypts_on_update_resource_with_included_ToMany_relationship( var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship existingScholarship = _fakers.Scholarship.Generate(); - existingScholarship.Participants = _fakers.Student.Generate(3); + Scholarship existingScholarship = _fakers.Scholarship.GenerateOne(); + existingScholarship.Participants = _fakers.Student.GenerateList(3); - decimal newAmount = _fakers.Scholarship.Generate().Amount; + decimal newAmount = _fakers.Scholarship.GenerateOne().Amount; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -603,8 +603,8 @@ public async Task Skips_on_get_ToOne_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship scholarship = _fakers.Scholarship.Generate(); - scholarship.PrimaryContact = _fakers.Student.Generate(); + Scholarship scholarship = _fakers.Scholarship.GenerateOne(); + scholarship.PrimaryContact = _fakers.Student.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -632,8 +632,8 @@ public async Task Skips_on_get_ToMany_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship scholarship = _fakers.Scholarship.Generate(); - scholarship.Participants = _fakers.Student.Generate(2); + Scholarship scholarship = _fakers.Scholarship.GenerateOne(); + scholarship.Participants = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -662,8 +662,8 @@ public async Task Skips_on_update_ToOne_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship existingScholarship = _fakers.Scholarship.Generate(); - Student existingStudent = _fakers.Student.Generate(); + Scholarship existingScholarship = _fakers.Scholarship.GenerateOne(); + Student existingStudent = _fakers.Student.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -699,8 +699,8 @@ public async Task Skips_on_set_ToMany_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship existingScholarship = _fakers.Scholarship.Generate(); - List existingStudents = _fakers.Student.Generate(2); + Scholarship existingScholarship = _fakers.Scholarship.GenerateOne(); + List existingStudents = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -745,8 +745,8 @@ public async Task Skips_on_add_to_ToMany_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship existingScholarship = _fakers.Scholarship.Generate(); - List existingStudents = _fakers.Student.Generate(2); + Scholarship existingScholarship = _fakers.Scholarship.GenerateOne(); + List existingStudents = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -791,8 +791,8 @@ public async Task Skips_on_remove_from_ToMany_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship existingScholarship = _fakers.Scholarship.Generate(); - existingScholarship.Participants = _fakers.Student.Generate(2); + Scholarship existingScholarship = _fakers.Scholarship.GenerateOne(); + existingScholarship.Participants = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ChangeTracking/ResourceInheritanceChangeTrackerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ChangeTracking/ResourceInheritanceChangeTrackerTests.cs index b744a270fb..7c05fe882f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ChangeTracking/ResourceInheritanceChangeTrackerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ChangeTracking/ResourceInheritanceChangeTrackerTests.cs @@ -24,9 +24,9 @@ public ResourceInheritanceChangeTrackerTests(IntegrationTestContext { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/Tandem.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/Tandem.cs index e5c3247244..d33d9c6642 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/Tandem.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/Tandem.cs @@ -10,6 +10,9 @@ public sealed class Tandem : Bike [Attr] public int PassengerCount { get; set; } + [HasOne] + public Box? FoldingDimensions { get; set; } + [HasMany] public ISet Features { get; set; } = new HashSet(); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceReadTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceReadTests.cs index 6f830f873f..ec5c1c46f1 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceReadTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceReadTests.cs @@ -46,15 +46,15 @@ protected ResourceInheritanceReadTests(IntegrationTestContext { @@ -90,7 +90,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { value.ShouldNotBeNull(); value.Links.ShouldNotBeNull(); @@ -112,9 +112,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => resource.Attributes.ShouldContainKey("gearCount").With(value => value.Should().Be(tandem.GearCount)); resource.Attributes.ShouldContainKey("passengerCount").With(value => value.Should().Be(tandem.PassengerCount)); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { value.ShouldNotBeNull(); value.Links.ShouldNotBeNull(); @@ -138,7 +138,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "engine", "navigationSystem", "features"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { value.ShouldNotBeNull(); value.Links.ShouldNotBeNull(); @@ -162,7 +162,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "engine", "navigationSystem", "sleepingArea", "features"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { value.ShouldNotBeNull(); value.Links.ShouldNotBeNull(); @@ -176,8 +176,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_concrete_base_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); - Tandem tandem = _fakers.Tandem.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -213,7 +213,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { value.ShouldNotBeNull(); value.Links.ShouldNotBeNull(); @@ -235,9 +235,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => resource.Attributes.ShouldContainKey("gearCount").With(value => value.Should().Be(tandem.GearCount)); resource.Attributes.ShouldContainKey("passengerCount").With(value => value.Should().Be(tandem.PassengerCount)); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { value.ShouldNotBeNull(); value.Links.ShouldNotBeNull(); @@ -251,8 +251,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_concrete_derived_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); - Tandem tandem = _fakers.Tandem.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -287,9 +287,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => resource.Attributes.ShouldContainKey("gearCount").With(value => value.Should().Be(tandem.GearCount)); resource.Attributes.ShouldContainKey("passengerCount").With(value => value.Should().Be(tandem.PassengerCount)); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { value.ShouldNotBeNull(); value.Links.ShouldNotBeNull(); @@ -303,7 +303,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_at_abstract_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -323,14 +323,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.SingleValue.Type.Should().Be("tandems"); responseDocument.Data.SingleValue.Id.Should().Be(tandem.StringId); responseDocument.Data.SingleValue.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); } [Fact] public async Task Can_get_primary_resource_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -350,14 +350,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.SingleValue.Type.Should().Be("tandems"); responseDocument.Data.SingleValue.Id.Should().Be(tandem.StringId); responseDocument.Data.SingleValue.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); } [Fact] public async Task Can_get_primary_resource_at_concrete_derived_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -377,15 +377,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.SingleValue.Type.Should().Be("tandems"); responseDocument.Data.SingleValue.Id.Should().Be(tandem.StringId); responseDocument.Data.SingleValue.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); } [Fact] public async Task Can_get_secondary_resource_at_abstract_base_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -432,8 +432,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resource_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.CargoBox = _fakers.Box.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.CargoBox = _fakers.Box.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -470,8 +470,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resource_at_concrete_derived_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -518,8 +518,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resource_defined_in_derived_type_at_abstract_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -548,8 +548,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resource_defined_in_derived_type_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.FoldingDimensions = _fakers.Box.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -557,7 +557,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await dbContext.SaveChangesAsync(); }); - string route = $"/bikes/{tandem.StringId}/features"; + string route = $"/bikes/{tandem.StringId}/foldingDimensions"; // Act (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); @@ -570,7 +570,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("The requested relationship does not exist."); - error.Detail.Should().Be("Resource of type 'bikes' does not contain a relationship named 'features'."); + error.Detail.Should().Be("Resource of type 'bikes' does not contain a relationship named 'foldingDimensions'."); error.Source.Should().BeNull(); } @@ -578,9 +578,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources_at_abstract_base_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); - car.Wheels = _fakers.ChromeWheel.Generate(2).Cast().Concat(_fakers.CarbonWheel.Generate(2)).ToHashSet(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); + car.Wheels = _fakers.ChromeWheel.GenerateSet(2).Concat(_fakers.CarbonWheel.GenerateSet(2)).ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -640,8 +640,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.Wheels = _fakers.ChromeWheel.Generate(2).Cast().Concat(_fakers.CarbonWheel.Generate(2)).ToHashSet(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.Wheels = _fakers.ChromeWheel.GenerateSet(2).Concat(_fakers.CarbonWheel.GenerateSet(2)).ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -708,9 +708,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources_at_concrete_derived_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); - car.Wheels = _fakers.ChromeWheel.Generate(2).Cast().Concat(_fakers.CarbonWheel.Generate(2)).ToHashSet(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); + car.Wheels = _fakers.ChromeWheel.GenerateSet(2).Concat(_fakers.CarbonWheel.GenerateSet(2)).ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -770,9 +770,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resources_defined_in_derived_type_at_abstract_endpoint() { // Arrange - Truck truck = _fakers.Truck.Generate(); - truck.Engine = _fakers.DieselEngine.Generate(); - truck.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); + Truck truck = _fakers.Truck.GenerateOne(); + truck.Engine = _fakers.DieselEngine.GenerateOne(); + truck.Features = _fakers.GenericFeature.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -801,8 +801,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resources_defined_in_derived_type_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.Features = _fakers.GenericFeature.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -831,8 +831,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToOne_relationship_at_abstract_base_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -862,8 +862,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToOne_relationship_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.CargoBox = _fakers.Box.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.CargoBox = _fakers.Box.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -893,8 +893,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToOne_relationship_at_concrete_derived_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -924,8 +924,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToOne_relationship_defined_in_derived_type_at_abstract_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -954,9 +954,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToMany_relationship_at_abstract_base_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); - car.Wheels = _fakers.ChromeWheel.Generate(2).Cast().Concat(_fakers.CarbonWheel.Generate(2)).ToHashSet(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); + car.Wheels = _fakers.ChromeWheel.GenerateSet(2).Concat(_fakers.CarbonWheel.GenerateSet(2)).ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -993,8 +993,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToMany_relationship_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.Wheels = _fakers.ChromeWheel.Generate(2).Cast().Concat(_fakers.CarbonWheel.Generate(2)).ToHashSet(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.Wheels = _fakers.ChromeWheel.GenerateSet(2).Concat(_fakers.CarbonWheel.GenerateSet(2)).ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1038,9 +1038,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToMany_relationship_at_concrete_derived_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); - car.Wheels = _fakers.ChromeWheel.Generate(2).Cast().Concat(_fakers.CarbonWheel.Generate(2)).ToHashSet(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); + car.Wheels = _fakers.ChromeWheel.GenerateSet(2).Concat(_fakers.CarbonWheel.GenerateSet(2)).ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1077,9 +1077,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToMany_relationship_defined_in_derived_type_at_abstract_endpoint() { // Arrange - Truck truck = _fakers.Truck.Generate(); - truck.Engine = _fakers.DieselEngine.Generate(); - truck.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); + Truck truck = _fakers.Truck.GenerateOne(); + truck.Engine = _fakers.DieselEngine.GenerateOne(); + truck.Features = _fakers.GenericFeature.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1108,8 +1108,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToMany_relationship_defined_in_derived_type_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.Features = _fakers.GenericFeature.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1138,15 +1138,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_abstract_endpoint_with_all_sparse_fieldsets() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); - Truck truck = _fakers.Truck.Generate(); - truck.Engine = _fakers.DieselEngine.Generate(); + Truck truck = _fakers.Truck.GenerateOne(); + truck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1203,15 +1203,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_abstract_endpoint_with_some_sparse_fieldsets() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); - Truck truck = _fakers.Truck.Generate(); - truck.Engine = _fakers.DieselEngine.Generate(); + Truck truck = _fakers.Truck.GenerateOne(); + truck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1244,7 +1244,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { resource.Id.Should().Be(tandem.StringId); resource.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "lights", "cargoBox", "features"); + resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "lights", "cargoBox", "foldingDimensions", "features"); }); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "cars").Subject.With(resource => @@ -1266,8 +1266,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_concrete_base_endpoint_with_all_sparse_fieldsets() { // Arrange - Bike bike = _fakers.Bike.Generate(); - Tandem tandem = _fakers.Tandem.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1310,8 +1310,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_concrete_base_endpoint_with_some_sparse_fieldsets() { // Arrange - Bike bike = _fakers.Bike.Generate(); - Tandem tandem = _fakers.Tandem.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1353,40 +1353,40 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_abstract_endpoint_with_derived_includes() { // Arrange - Bike bike = _fakers.Bike.Generate(); - bike.Manufacturer = _fakers.VehicleManufacturer.Generate(); - bike.Wheels = _fakers.CarbonWheel.Generate(1).Cast().ToHashSet(); - bike.CargoBox = _fakers.Box.Generate(); - bike.Lights = _fakers.BicycleLight.Generate(1).ToHashSet(); - - Tandem tandem = _fakers.Tandem.Generate(); - tandem.Manufacturer = _fakers.VehicleManufacturer.Generate(); - tandem.Wheels = _fakers.ChromeWheel.Generate(1).Cast().ToHashSet(); - tandem.CargoBox = _fakers.Box.Generate(); - tandem.Lights = _fakers.BicycleLight.Generate(1).ToHashSet(); - tandem.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); - tandem.Features.ElementAt(0).Properties = _fakers.StringProperty.Generate(1).Cast().ToHashSet(); - ((StringProperty)tandem.Features.ElementAt(0).Properties.ElementAt(0)).Value = _fakers.StringValue.Generate(); - - Car car = _fakers.Car.Generate(); - car.Manufacturer = _fakers.VehicleManufacturer.Generate(); - car.Wheels = _fakers.CarbonWheel.Generate(1).Cast().ToHashSet(); - car.Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)car.Engine).Cylinders = _fakers.Cylinder.Generate(1).ToHashSet(); - car.NavigationSystem = _fakers.NavigationSystem.Generate(); - car.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); - car.Features.ElementAt(0).Properties = _fakers.NumberProperty.Generate(1).Cast().ToHashSet(); - ((NumberProperty)car.Features.ElementAt(0).Properties.ElementAt(0)).Value = _fakers.NumberValue.Generate(); - - Truck truck = _fakers.Truck.Generate(); - truck.Manufacturer = _fakers.VehicleManufacturer.Generate(); - truck.Wheels = _fakers.ChromeWheel.Generate(1).Cast().ToHashSet(); - truck.Engine = _fakers.DieselEngine.Generate(); - truck.NavigationSystem = _fakers.NavigationSystem.Generate(); - truck.SleepingArea = _fakers.Box.Generate(); - truck.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); - truck.Features.ElementAt(0).Properties = _fakers.StringProperty.Generate(1).Cast().ToHashSet(); - ((StringProperty)truck.Features.ElementAt(0).Properties.ElementAt(0)).Value = _fakers.StringValue.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); + bike.Manufacturer = _fakers.VehicleManufacturer.GenerateOne(); + bike.Wheels = _fakers.CarbonWheel.GenerateSet(1); + bike.CargoBox = _fakers.Box.GenerateOne(); + bike.Lights = _fakers.BicycleLight.GenerateSet(1); + + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.Manufacturer = _fakers.VehicleManufacturer.GenerateOne(); + tandem.Wheels = _fakers.ChromeWheel.GenerateSet(1); + tandem.CargoBox = _fakers.Box.GenerateOne(); + tandem.Lights = _fakers.BicycleLight.GenerateSet(1); + tandem.Features = _fakers.GenericFeature.GenerateSet(1); + tandem.Features.ElementAt(0).Properties = _fakers.StringProperty.GenerateSet(1); + ((StringProperty)tandem.Features.ElementAt(0).Properties.ElementAt(0)).Value = _fakers.StringValue.GenerateOne(); + + Car car = _fakers.Car.GenerateOne(); + car.Manufacturer = _fakers.VehicleManufacturer.GenerateOne(); + car.Wheels = _fakers.CarbonWheel.GenerateSet(1); + car.Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)car.Engine).Cylinders = _fakers.Cylinder.GenerateSet(1); + car.NavigationSystem = _fakers.NavigationSystem.GenerateOne(); + car.Features = _fakers.GenericFeature.GenerateSet(1); + car.Features.ElementAt(0).Properties = _fakers.NumberProperty.GenerateSet(1); + ((NumberProperty)car.Features.ElementAt(0).Properties.ElementAt(0)).Value = _fakers.NumberValue.GenerateOne(); + + Truck truck = _fakers.Truck.GenerateOne(); + truck.Manufacturer = _fakers.VehicleManufacturer.GenerateOne(); + truck.Wheels = _fakers.ChromeWheel.GenerateSet(1); + truck.Engine = _fakers.DieselEngine.GenerateOne(); + truck.NavigationSystem = _fakers.NavigationSystem.GenerateOne(); + truck.SleepingArea = _fakers.Box.GenerateOne(); + truck.Features = _fakers.GenericFeature.GenerateSet(1); + truck.Features.ElementAt(0).Properties = _fakers.StringProperty.GenerateSet(1); + ((StringProperty)truck.Features.ElementAt(0).Properties.ElementAt(0)).Value = _fakers.StringValue.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1547,6 +1547,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => "weight": {{tandem.Weight.ToString(CultureInfo.InvariantCulture)}} }, "relationships": { + "foldingDimensions": { + "links": { + "self": "/tandems/{{tandem.StringId}}/relationships/foldingDimensions", + "related": "/tandems/{{tandem.StringId}}/foldingDimensions" + } + }, "features": { "links": { "self": "/tandems/{{tandem.StringId}}/relationships/features", @@ -2021,12 +2027,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_derived_resource_type_at_abstract_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2053,15 +2059,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_derived_resource_type_with_condition_at_abstract_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Car car = _fakers.Car.Generate(); + Car car = _fakers.Car.GenerateOne(); car.LicensePlate = "XX-99-YY"; - car.Engine = _fakers.GasolineEngine.Generate(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); - Truck truck = _fakers.Truck.Generate(); + Truck truck = _fakers.Truck.GenerateOne(); truck.LicensePlate = "AA-11-BB"; - truck.Engine = _fakers.DieselEngine.Generate(); + truck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2087,13 +2093,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_derived_resource_type_and_derived_ToOne_relationship_type_at_abstract_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); - Truck truck = _fakers.Truck.Generate(); - truck.Engine = _fakers.DieselEngine.Generate(); + Truck truck = _fakers.Truck.GenerateOne(); + truck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2119,15 +2125,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_derived_resource_type_and_derived_ToOne_relationship_type_with_condition_at_abstract_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); - Truck truck1 = _fakers.Truck.Generate(); - truck1.Engine = _fakers.DieselEngine.Generate(); + Truck truck1 = _fakers.Truck.GenerateOne(); + truck1.Engine = _fakers.DieselEngine.GenerateOne(); ((DieselEngine)truck1.Engine).Viscosity = 25; - Truck truck2 = _fakers.Truck.Generate(); - truck2.Engine = _fakers.DieselEngine.Generate(); + Truck truck2 = _fakers.Truck.GenerateOne(); + truck2.Engine = _fakers.DieselEngine.GenerateOne(); ((DieselEngine)truck2.Engine).Viscosity = 100; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -2154,12 +2160,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_derived_resource_type_with_condition_at_concrete_base_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Tandem tandem1 = _fakers.Tandem.Generate(); + Tandem tandem1 = _fakers.Tandem.GenerateOne(); - Tandem tandem2 = _fakers.Tandem.Generate(); - tandem2.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); + Tandem tandem2 = _fakers.Tandem.GenerateOne(); + tandem2.Features = _fakers.GenericFeature.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2185,17 +2191,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_derived_resource_type_with_condition_at_concrete_derived_endpoint() { // Arrange - Car car1 = _fakers.Car.Generate(); - car1.Engine = _fakers.GasolineEngine.Generate(); - car1.Wheels = _fakers.CarbonWheel.Generate(4).Cast().ToHashSet(); + Car car1 = _fakers.Car.GenerateOne(); + car1.Engine = _fakers.GasolineEngine.GenerateOne(); + car1.Wheels = _fakers.CarbonWheel.GenerateSet(4); - Car car2 = _fakers.Car.Generate(); - car2.Engine = _fakers.GasolineEngine.Generate(); - car2.Wheels = _fakers.ChromeWheel.Generate(4).Cast().ToHashSet(); + Car car2 = _fakers.Car.GenerateOne(); + car2.Engine = _fakers.GasolineEngine.GenerateOne(); + car2.Wheels = _fakers.ChromeWheel.GenerateSet(4); - Car car3 = _fakers.Car.Generate(); - car3.Engine = _fakers.GasolineEngine.Generate(); - car3.Wheels = _fakers.ChromeWheel.Generate(4).Cast().ToHashSet(); + Car car3 = _fakers.Car.GenerateOne(); + car3.Engine = _fakers.GasolineEngine.GenerateOne(); + car3.Wheels = _fakers.ChromeWheel.GenerateSet(4); car3.Wheels.Cast().ElementAt(0).PaintColor = "light-gray"; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -2222,17 +2228,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_derived_attribute_at_abstract_endpoint() { // Arrange - Bike bike1 = _fakers.Bike.Generate(); + Bike bike1 = _fakers.Bike.GenerateOne(); bike1.GearCount = 3; - Bike bike2 = _fakers.Bike.Generate(); + Bike bike2 = _fakers.Bike.GenerateOne(); bike2.GearCount = 1; - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); tandem.GearCount = 2; - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2268,12 +2274,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_derived_attribute_at_concrete_base_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Tandem tandem1 = _fakers.Tandem.Generate(); + Tandem tandem1 = _fakers.Tandem.GenerateOne(); tandem1.PassengerCount = 2; - Tandem tandem2 = _fakers.Tandem.Generate(); + Tandem tandem2 = _fakers.Tandem.GenerateOne(); tandem2.PassengerCount = 4; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -2307,16 +2313,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_derived_relationship_at_concrete_derived_endpoint() { // Arrange - Car car1 = _fakers.Car.Generate(); - car1.Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)car1.Engine).Cylinders = _fakers.Cylinder.Generate(2).ToHashSet(); + Car car1 = _fakers.Car.GenerateOne(); + car1.Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)car1.Engine).Cylinders = _fakers.Cylinder.GenerateSet(2); - Car car2 = _fakers.Car.Generate(); - car2.Engine = _fakers.DieselEngine.Generate(); + Car car2 = _fakers.Car.GenerateOne(); + car2.Engine = _fakers.DieselEngine.GenerateOne(); - Car car3 = _fakers.Car.Generate(); - car3.Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)car3.Engine).Cylinders = _fakers.Cylinder.Generate(4).ToHashSet(); + Car car3 = _fakers.Car.GenerateOne(); + car3.Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)car3.Engine).Cylinders = _fakers.Cylinder.GenerateSet(4); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2395,25 +2401,25 @@ public async Task Cannot_sort_on_ambiguous_derived_relationship() public async Task Can_sort_on_derived_attribute_from_resource_definition_using_expression_syntax() { // Arrange - ChromeWheel chromeWheel1 = _fakers.ChromeWheel.Generate(); + ChromeWheel chromeWheel1 = _fakers.ChromeWheel.GenerateOne(); chromeWheel1.PaintColor = "blue"; - chromeWheel1.Vehicle = _fakers.Car.Generate(); - ((Car)chromeWheel1.Vehicle).Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)((Car)chromeWheel1.Vehicle).Engine).Cylinders = _fakers.Cylinder.Generate(2).ToHashSet(); + chromeWheel1.Vehicle = _fakers.Car.GenerateOne(); + ((Car)chromeWheel1.Vehicle).Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)((Car)chromeWheel1.Vehicle).Engine).Cylinders = _fakers.Cylinder.GenerateSet(2); - ChromeWheel chromeWheel2 = _fakers.ChromeWheel.Generate(); + ChromeWheel chromeWheel2 = _fakers.ChromeWheel.GenerateOne(); chromeWheel2.PaintColor = "blue"; - chromeWheel2.Vehicle = _fakers.Car.Generate(); - ((Car)chromeWheel2.Vehicle).Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)((Car)chromeWheel2.Vehicle).Engine).Cylinders = _fakers.Cylinder.Generate(1).ToHashSet(); + chromeWheel2.Vehicle = _fakers.Car.GenerateOne(); + ((Car)chromeWheel2.Vehicle).Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)((Car)chromeWheel2.Vehicle).Engine).Cylinders = _fakers.Cylinder.GenerateSet(1); - ChromeWheel chromeWheel3 = _fakers.ChromeWheel.Generate(); + ChromeWheel chromeWheel3 = _fakers.ChromeWheel.GenerateOne(); chromeWheel3.PaintColor = "black"; - CarbonWheel carbonWheel1 = _fakers.CarbonWheel.Generate(); + CarbonWheel carbonWheel1 = _fakers.CarbonWheel.GenerateOne(); carbonWheel1.HasTube = false; - CarbonWheel carbonWheel2 = _fakers.CarbonWheel.Generate(); + CarbonWheel carbonWheel2 = _fakers.CarbonWheel.GenerateOne(); carbonWheel2.HasTube = true; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -2453,25 +2459,25 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_derived_attribute_from_resource_definition_using_lambda_syntax() { // Arrange - ChromeWheel chromeWheel1 = _fakers.ChromeWheel.Generate(); + ChromeWheel chromeWheel1 = _fakers.ChromeWheel.GenerateOne(); chromeWheel1.PaintColor = "blue"; - chromeWheel1.Vehicle = _fakers.Car.Generate(); - ((Car)chromeWheel1.Vehicle).Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)((Car)chromeWheel1.Vehicle).Engine).Cylinders = _fakers.Cylinder.Generate(2).ToHashSet(); + chromeWheel1.Vehicle = _fakers.Car.GenerateOne(); + ((Car)chromeWheel1.Vehicle).Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)((Car)chromeWheel1.Vehicle).Engine).Cylinders = _fakers.Cylinder.GenerateSet(2); - ChromeWheel chromeWheel2 = _fakers.ChromeWheel.Generate(); + ChromeWheel chromeWheel2 = _fakers.ChromeWheel.GenerateOne(); chromeWheel2.PaintColor = "blue"; - chromeWheel2.Vehicle = _fakers.Car.Generate(); - ((Car)chromeWheel2.Vehicle).Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)((Car)chromeWheel2.Vehicle).Engine).Cylinders = _fakers.Cylinder.Generate(1).ToHashSet(); + chromeWheel2.Vehicle = _fakers.Car.GenerateOne(); + ((Car)chromeWheel2.Vehicle).Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)((Car)chromeWheel2.Vehicle).Engine).Cylinders = _fakers.Cylinder.GenerateSet(1); - ChromeWheel chromeWheel3 = _fakers.ChromeWheel.Generate(); + ChromeWheel chromeWheel3 = _fakers.ChromeWheel.GenerateOne(); chromeWheel3.PaintColor = "black"; - CarbonWheel carbonWheel1 = _fakers.CarbonWheel.Generate(); + CarbonWheel carbonWheel1 = _fakers.CarbonWheel.GenerateOne(); carbonWheel1.HasTube = false; - CarbonWheel carbonWheel2 = _fakers.CarbonWheel.Generate(); + CarbonWheel carbonWheel2 = _fakers.CarbonWheel.GenerateOne(); carbonWheel2.HasTube = true; await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceWriteTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceWriteTests.cs index 0e55f5ad85..1524b92ed7 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceWriteTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceWriteTests.cs @@ -75,7 +75,7 @@ protected ResourceInheritanceWriteTests(IntegrationTestContext>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); - Box existingBox = _fakers.Box.Generate(); - BicycleLight existingLight = _fakers.BicycleLight.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); + Box existingBox = _fakers.Box.GenerateOne(); + BicycleLight existingLight = _fakers.BicycleLight.GenerateOne(); - Bike newBike = _fakers.Bike.Generate(); + Bike newBike = _fakers.Bike.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -243,13 +243,13 @@ public async Task Can_create_concrete_derived_resource_at_abstract_endpoint_with // Arrange var carStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); - GasolineEngine existingGasolineEngine = _fakers.GasolineEngine.Generate(); - NavigationSystem existingNavigationSystem = _fakers.NavigationSystem.Generate(); - GenericFeature existingFeature = _fakers.GenericFeature.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); + GasolineEngine existingGasolineEngine = _fakers.GasolineEngine.GenerateOne(); + NavigationSystem existingNavigationSystem = _fakers.NavigationSystem.GenerateOne(); + GenericFeature existingFeature = _fakers.GenericFeature.GenerateOne(); - Car newCar = _fakers.Car.Generate(); + Car newCar = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -390,13 +390,13 @@ public async Task Can_create_concrete_derived_resource_at_concrete_base_endpoint // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); - Box existingBox = _fakers.Box.Generate(); - BicycleLight existingLight = _fakers.BicycleLight.Generate(); - GenericFeature existingFeature = _fakers.GenericFeature.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); + Box existingBox = _fakers.Box.GenerateOne(); + BicycleLight existingLight = _fakers.BicycleLight.GenerateOne(); + GenericFeature existingFeature = _fakers.GenericFeature.GenerateOne(); - Tandem newTandem = _fakers.Tandem.Generate(); + Tandem newTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -486,7 +486,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.SingleValue.ShouldNotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("tandems"); responseDocument.Data.SingleValue.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); long newTandemId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); @@ -537,7 +537,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_concrete_base_resource_at_concrete_derived_endpoint() { // Arrange - Bike newBike = _fakers.Bike.Generate(); + Bike newBike = _fakers.Bike.GenerateOne(); var requestBody = new { @@ -575,7 +575,7 @@ public async Task Cannot_create_concrete_base_resource_at_concrete_derived_endpo public async Task Cannot_create_resource_with_abstract_relationship_type() { // Arrange - DieselEngine existingEngine = _fakers.DieselEngine.Generate(); + DieselEngine existingEngine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -620,75 +620,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Source.Pointer.Should().Be("/data/relationships/engine/data/type"); } - [Fact] - public async Task Can_create_resource_with_concrete_base_relationship_type_stored_as_derived_type() - { - // Arrange - var carbonWheelStore = _testContext.Factory.Services.GetRequiredService>(); - - Tandem existingTandem = _fakers.Tandem.Generate(); - - await _testContext.RunOnDatabaseAsync(async dbContext => - { - dbContext.Vehicles.Add(existingTandem); - await dbContext.SaveChangesAsync(); - }); - - var requestBody = new - { - data = new - { - type = "carbonWheels", - relationships = new - { - vehicle = new - { - data = new - { - type = "bikes", - id = existingTandem.StringId - } - } - } - } - }; - - const string route = "/carbonWheels"; - - // Act - (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); - - // Assert - httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Type.Should().Be("carbonWheels"); - responseDocument.Data.SingleValue.Attributes.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); - - long newCarbonWheelId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); - - await _testContext.RunOnDatabaseAsync(async dbContext => - { - CarbonWheel carbonWheelInDatabase = await dbContext.CarbonWheels.Include(wheel => wheel.Vehicle).FirstWithIdAsync(newCarbonWheelId); - - carbonWheelInDatabase.Should().BeOfType(); - carbonWheelInDatabase.Vehicle.ShouldNotBeNull(); - carbonWheelInDatabase.Vehicle.Should().BeOfType(); - carbonWheelInDatabase.Vehicle.Id.Should().Be(existingTandem.Id); - }); - - carbonWheelStore.AssertLeftType(); - carbonWheelStore.AssertRightTypes(typeof(Tandem)); - } - [Fact] public async Task Can_create_resource_with_concrete_base_ToOne_relationship_type_stored_as_derived_type_at_resource_endpoint() { // Arrange var carbonWheelStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -750,7 +688,7 @@ public async Task Can_create_resource_with_concrete_base_ToMany_relationship_typ // Arrange var manufacturerStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -813,7 +751,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_concrete_derived_ToOne_relationship_type_stored_as_sibling_derived_type_at_resource_endpoint() { // Arrange - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -861,8 +799,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_concrete_derived_ToMany_relationship_type_stored_as_sibling_derived_type_at_resource_endpoint() { // Arrange - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.DieselEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1000,9 +938,9 @@ public async Task Cannot_create_resource_with_unknown_resources_in_ToMany_relati public async Task Cannot_update_abstract_resource_at_abstract_endpoint() { // Arrange - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); - int newPassengerCount = _fakers.Tandem.Generate().PassengerCount; + int newPassengerCount = _fakers.Tandem.GenerateOne().PassengerCount; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1047,13 +985,13 @@ public async Task Can_update_concrete_base_resource_at_abstract_endpoint_with_re // Arrange var bikeStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); - Box existingBox = _fakers.Box.Generate(); - BicycleLight existingLight = _fakers.BicycleLight.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); + Box existingBox = _fakers.Box.GenerateOne(); + BicycleLight existingLight = _fakers.BicycleLight.GenerateOne(); - Bike existingBike = _fakers.Bike.Generate(); - Bike newBike = _fakers.Bike.Generate(); + Bike existingBike = _fakers.Bike.GenerateOne(); + Bike newBike = _fakers.Bike.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1175,13 +1113,13 @@ public async Task Can_update_concrete_base_resource_stored_as_concrete_derived_a // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); - Box existingBox = _fakers.Box.Generate(); - BicycleLight existingLight = _fakers.BicycleLight.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); + Box existingBox = _fakers.Box.GenerateOne(); + BicycleLight existingLight = _fakers.BicycleLight.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); - Bike newBike = _fakers.Bike.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); + Bike newBike = _fakers.Bike.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1301,9 +1239,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_concrete_base_resource_at_concrete_derived_endpoint() { // Arrange - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); - int newPassengerCount = _fakers.Tandem.Generate().PassengerCount; + int newPassengerCount = _fakers.Tandem.GenerateOne().PassengerCount; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1346,10 +1284,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_abstract_relationship_type() { // Arrange - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.GasolineEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.GasolineEngine.GenerateOne(); - DieselEngine existingEngine = _fakers.DieselEngine.Generate(); + DieselEngine existingEngine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1402,9 +1340,9 @@ public async Task Can_update_resource_with_concrete_base_ToOne_relationship_type // Arrange var carbonWheelStore = _testContext.Factory.Services.GetRequiredService>(); - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1463,9 +1401,9 @@ public async Task Can_update_resource_with_concrete_base_ToMany_relationship_typ // Arrange var manufacturerStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1525,9 +1463,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_concrete_derived_ToOne_relationship_type_stored_as_sibling_derived_type_at_resource_endpoint() { // Arrange - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1577,10 +1515,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_concrete_derived_ToMany_relationship_type_stored_as_sibling_derived_type_at_resource_endpoint() { // Arrange - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.DieselEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1633,7 +1571,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_unknown_resource_in_ToOne_relationship_at_resource_endpoint() { // Arrange - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); string unknownTruckId = Unknown.StringId.For(); @@ -1684,7 +1622,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_unknown_resources_in_ToMany_relationship_at_resource_endpoint() { // Arrange - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); string unknownTruckId = Unknown.StringId.For(); @@ -1740,7 +1678,7 @@ public async Task Can_delete_resource_stored_as_concrete_derived_at_abstract_end // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1773,7 +1711,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_delete_concrete_base_resource_at_concrete_derived_endpoint() { // Arrange - Bike existingBike = _fakers.Bike.Generate(); + Bike existingBike = _fakers.Bike.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1804,9 +1742,9 @@ public async Task Can_set_abstract_resource_at_abstract_ToOne_relationship_endpo // Arrange var carbonWheelStore = _testContext.Factory.Services.GetRequiredService>(); - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1855,9 +1793,9 @@ public async Task Can_set_abstract_resources_at_abstract_ToMany_relationship_end // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1909,9 +1847,9 @@ public async Task Can_set_concrete_base_resource_stored_as_derived_at_abstract_T // Arrange var carbonWheelStore = _testContext.Factory.Services.GetRequiredService>(); - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1960,9 +1898,9 @@ public async Task Can_set_concrete_base_resources_stored_as_derived_at_ToMany_re // Arrange var manufacturerStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2011,9 +1949,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_set_concrete_derived_resource_stored_as_concrete_base_at_abstract_ToOne_relationship_endpoint() { // Arrange - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); - Bike existingBike = _fakers.Bike.Generate(); + Bike existingBike = _fakers.Bike.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2052,10 +1990,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_set_concrete_derived_resources_stored_as_sibling_derived_at_ToMany_relationship_endpoint() { // Arrange - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.DieselEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2097,7 +2035,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_set_unknown_resources_at_ToMany_relationship_endpoint() { // Arrange - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); string unknownTruckId = Unknown.StringId.For(); @@ -2139,8 +2077,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Cannot_clear_ToOne_relationship_for_left_type_stored_as_sibling_type() { - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.DieselEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2176,10 +2114,10 @@ public async Task Can_add_abstract_resources_at_abstract_ToMany_relationship_end // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); - existingTandem.Wheels = _fakers.CarbonWheel.Generate(1).Cast().ToHashSet(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); + existingTandem.Wheels = _fakers.CarbonWheel.GenerateSet(1); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2233,10 +2171,10 @@ public async Task Can_add_concrete_derived_resources_at_abstract_ToMany_relation // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); - existingTandem.Wheels = _fakers.CarbonWheel.Generate(1).Cast().ToHashSet(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); + existingTandem.Wheels = _fakers.CarbonWheel.GenerateSet(1); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2290,11 +2228,11 @@ public async Task Can_add_concrete_base_resources_stored_as_derived_at_ToMany_re // Arrange var manufacturerStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - existingManufacturer.Vehicles = _fakers.Car.Generate(1).Cast().ToHashSet(); - ((Car)existingManufacturer.Vehicles.ElementAt(0)).Engine = _fakers.GasolineEngine.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + existingManufacturer.Vehicles = _fakers.Car.GenerateSet(1); + ((Car)existingManufacturer.Vehicles.ElementAt(0)).Engine = _fakers.GasolineEngine.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2352,9 +2290,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_concrete_derived_resources_stored_as_sibling_derived_at_abstract_ToMany_relationship_endpoint() { // Arrange - Bike existingBike = _fakers.Bike.Generate(); + Bike existingBike = _fakers.Bike.GenerateOne(); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2396,7 +2334,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_unknown_resources_at_ToMany_relationship_endpoint() { // Arrange - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); string unknownTruckId = Unknown.StringId.For(); @@ -2438,8 +2376,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Cannot_add_to_ToMany_relationship_for_left_type_stored_as_sibling_type() { - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.DieselEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2475,8 +2413,8 @@ public async Task Can_remove_abstract_resources_at_abstract_ToMany_relationship_ // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); - existingTandem.Wheels = _fakers.ChromeWheel.Generate(2).Cast().ToHashSet(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); + existingTandem.Wheels = _fakers.ChromeWheel.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2527,8 +2465,8 @@ public async Task Can_remove_concrete_derived_resources_at_abstract_ToMany_relat // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); - existingTandem.Wheels = _fakers.ChromeWheel.Generate(2).Cast().ToHashSet(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); + existingTandem.Wheels = _fakers.ChromeWheel.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2579,9 +2517,9 @@ public async Task Can_remove_concrete_base_resources_stored_as_derived_at_ToMany // Arrange var manufacturerStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - existingManufacturer.Vehicles = _fakers.Tandem.Generate(1).Cast().Concat(_fakers.Car.Generate(1)).ToHashSet(); - ((Car)existingManufacturer.Vehicles.ElementAt(1)).Engine = _fakers.GasolineEngine.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + existingManufacturer.Vehicles = _fakers.Tandem.GenerateSet(1).Concat(_fakers.Car.GenerateSet(1)).ToHashSet(); + ((Car)existingManufacturer.Vehicles.ElementAt(1)).Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2629,8 +2567,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_concrete_derived_resources_stored_as_sibling_derived_at_abstract_ToMany_relationship_endpoint() { // Arrange - Bike existingBike = _fakers.Bike.Generate(); - existingBike.Wheels = _fakers.ChromeWheel.Generate(2).Cast().ToHashSet(); + Bike existingBike = _fakers.Bike.GenerateOne(); + existingBike.Wheels = _fakers.ChromeWheel.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2673,7 +2611,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_unknown_resources_at_ToMany_relationship_endpoint() { // Arrange - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); string unknownTruckId = Unknown.StringId.For(); @@ -2715,8 +2653,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Cannot_remove_from_ToMany_relationship_for_left_type_stored_as_sibling_type() { - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.DieselEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCaptureStore.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCaptureStore.cs index d9ac30f8c0..5d7fa01d52 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCaptureStore.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCaptureStore.cs @@ -10,8 +10,8 @@ public sealed class ResourceTypeCaptureStore { internal Type? LeftDeclaredType { get; set; } internal string? LeftReflectedTypeName { get; set; } - internal ISet RightTypeNames { get; } = new HashSet(); - internal IJsonApiRequest? Request { get; set; } + internal HashSet RightTypeNames { get; } = []; + internal JsonApiRequest? Request { get; set; } internal void Reset() { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCapturingDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCapturingDefinition.cs index 8e9a49dbfc..bae85f8754 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCapturingDefinition.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCapturingDefinition.cs @@ -110,7 +110,7 @@ private void EnsureSnapshot(TResource leftType, IEnumerable right } } - private IJsonApiRequest TakeRequestSnapshot() + private JsonApiRequest TakeRequestSnapshot() { var requestSnapshot = new JsonApiRequest(); requestSnapshot.CopyFrom(_request); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/NoRelationshipsControllerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/NoRelationshipsControllerTests.cs index 89e5c20741..0581b527e1 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/NoRelationshipsControllerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/NoRelationshipsControllerTests.cs @@ -35,7 +35,7 @@ public async Task Can_get_resources() public async Task Can_get_resource() { // Arrange - Chair chair = _fakers.Chair.Generate(); + Chair chair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -56,7 +56,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resources() { // Arrange - Chair chair = _fakers.Chair.Generate(); + Chair chair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -84,7 +84,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resource() { // Arrange - Chair chair = _fakers.Chair.Generate(); + Chair chair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -112,7 +112,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_relationship() { // Arrange - Chair chair = _fakers.Chair.Generate(); + Chair chair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -164,7 +164,7 @@ public async Task Can_create_resource() public async Task Can_update_resource() { // Arrange - Chair existingChair = _fakers.Chair.Generate(); + Chair existingChair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -197,7 +197,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - Chair existingChair = _fakers.Chair.Generate(); + Chair existingChair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -218,7 +218,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_relationship() { // Arrange - Chair existingChair = _fakers.Chair.Generate(); + Chair existingChair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -251,7 +251,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_ToMany_relationship() { // Arrange - Chair existingChair = _fakers.Chair.Generate(); + Chair existingChair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -284,7 +284,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_ToMany_relationship() { // Arrange - Chair existingChair = _fakers.Chair.Generate(); + Chair existingChair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/ReadOnlyControllerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/ReadOnlyControllerTests.cs index 37900089db..40c07d57bf 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/ReadOnlyControllerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/ReadOnlyControllerTests.cs @@ -35,7 +35,7 @@ public async Task Can_get_resources() public async Task Can_get_resource() { // Arrange - Bed bed = _fakers.Bed.Generate(); + Bed bed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -56,7 +56,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources() { // Arrange - Bed bed = _fakers.Bed.Generate(); + Bed bed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -77,7 +77,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resource() { // Arrange - Bed bed = _fakers.Bed.Generate(); + Bed bed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -98,7 +98,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_relationship() { // Arrange - Bed bed = _fakers.Bed.Generate(); + Bed bed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -150,7 +150,7 @@ public async Task Cannot_create_resource() public async Task Cannot_update_resource() { // Arrange - Bed existingBed = _fakers.Bed.Generate(); + Bed existingBed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -190,7 +190,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_delete_resource() { // Arrange - Bed existingBed = _fakers.Bed.Generate(); + Bed existingBed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -218,7 +218,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_relationship() { // Arrange - Bed existingBed = _fakers.Bed.Generate(); + Bed existingBed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -251,7 +251,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_ToMany_relationship() { // Arrange - Bed existingBed = _fakers.Bed.Generate(); + Bed existingBed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -284,7 +284,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_ToMany_relationship() { // Arrange - Bed existingBed = _fakers.Bed.Generate(); + Bed existingBed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/WriteOnlyControllerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/WriteOnlyControllerTests.cs index 7a3f42accf..35e15b402c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/WriteOnlyControllerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/WriteOnlyControllerTests.cs @@ -42,7 +42,7 @@ public async Task Cannot_get_resources() public async Task Cannot_get_resource() { // Arrange - Table table = _fakers.Table.Generate(); + Table table = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -70,7 +70,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resources() { // Arrange - Table table = _fakers.Table.Generate(); + Table table = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -98,7 +98,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resource() { // Arrange - Table table = _fakers.Table.Generate(); + Table table = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -126,7 +126,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_relationship() { // Arrange - Table table = _fakers.Table.Generate(); + Table table = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -178,7 +178,7 @@ public async Task Can_create_resource() public async Task Can_update_resource() { // Arrange - Table existingTable = _fakers.Table.Generate(); + Table existingTable = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -211,7 +211,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - Table existingTable = _fakers.Table.Generate(); + Table existingTable = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -232,7 +232,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_relationship() { // Arrange - Table existingTable = _fakers.Table.Generate(); + Table existingTable = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -258,7 +258,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ToMany_relationship() { // Arrange - Table existingTable = _fakers.Table.Generate(); + Table existingTable = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -284,7 +284,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ToMany_relationship() { // Arrange - Table existingTable = _fakers.Table.Generate(); + Table existingTable = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/ETagTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/ETagTests.cs index 4c950ee98e..2f089f5595 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/ETagTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/ETagTests.cs @@ -24,7 +24,7 @@ public ETagTests(IntegrationTestContext, public async Task Returns_ETag_for_HEAD_request() { // Arrange - List meetings = _fakers.Meeting.Generate(2); + List meetings = _fakers.Meeting.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -52,7 +52,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Returns_ETag_for_GET_request() { // Arrange - List meetings = _fakers.Meeting.Generate(2); + List meetings = _fakers.Meeting.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -98,7 +98,7 @@ public async Task Returns_no_ETag_for_POST_request() { // Arrange var newId = Guid.NewGuid(); - string newTitle = _fakers.Meeting.Generate().Title; + string newTitle = _fakers.Meeting.GenerateOne().Title; var requestBody = new { @@ -130,9 +130,9 @@ public async Task Returns_no_ETag_for_POST_request() public async Task Fails_on_ETag_in_PATCH_request() { // Arrange - Meeting existingMeeting = _fakers.Meeting.Generate(); + Meeting existingMeeting = _fakers.Meeting.GenerateOne(); - string newTitle = _fakers.Meeting.Generate().Title; + string newTitle = _fakers.Meeting.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -178,7 +178,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Returns_NotModified_for_matching_ETag() { // Arrange - List meetings = _fakers.Meeting.Generate(2); + List meetings = _fakers.Meeting.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -212,7 +212,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Returns_content_for_mismatching_ETag() { // Arrange - List meetings = _fakers.Meeting.Generate(2); + List meetings = _fakers.Meeting.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/SerializationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/SerializationTests.cs index fdac2bfc64..e500ebcdf9 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/SerializationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/SerializationTests.cs @@ -42,7 +42,7 @@ public SerializationTests(IntegrationTestContext { @@ -84,8 +84,8 @@ public async Task Returns_no_body_for_failed_HEAD_request() public async Task Can_get_primary_resources_with_include() { // Arrange - Meeting meeting = _fakers.Meeting.Generate(); - meeting.Attendees = _fakers.MeetingAttendee.Generate(1); + Meeting meeting = _fakers.Meeting.GenerateOne(); + meeting.Attendees = _fakers.MeetingAttendee.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -178,7 +178,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_with_empty_ToOne_include() { // Arrange - MeetingAttendee attendee = _fakers.MeetingAttendee.Generate(); + MeetingAttendee attendee = _fakers.MeetingAttendee.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -233,7 +233,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_with_empty_ToMany_include() { // Arrange - Meeting meeting = _fakers.Meeting.Generate(); + Meeting meeting = _fakers.Meeting.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -296,7 +296,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_by_ID() { // Arrange - Meeting meeting = _fakers.Meeting.Generate(); + Meeting meeting = _fakers.Meeting.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -382,8 +382,8 @@ public async Task Cannot_get_unknown_primary_resource_by_ID() public async Task Can_get_secondary_resource() { // Arrange - MeetingAttendee attendee = _fakers.MeetingAttendee.Generate(); - attendee.Meeting = _fakers.Meeting.Generate(); + MeetingAttendee attendee = _fakers.MeetingAttendee.GenerateOne(); + attendee.Meeting = _fakers.Meeting.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -436,7 +436,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_unknown_secondary_resource() { // Arrange - MeetingAttendee attendee = _fakers.MeetingAttendee.Generate(); + MeetingAttendee attendee = _fakers.MeetingAttendee.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -466,8 +466,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources() { // Arrange - Meeting meeting = _fakers.Meeting.Generate(); - meeting.Attendees = _fakers.MeetingAttendee.Generate(1); + Meeting meeting = _fakers.Meeting.GenerateOne(); + meeting.Attendees = _fakers.MeetingAttendee.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -527,7 +527,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_unknown_secondary_resources() { // Arrange - Meeting meeting = _fakers.Meeting.Generate(); + Meeting meeting = _fakers.Meeting.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -561,8 +561,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToOne_relationship() { // Arrange - MeetingAttendee attendee = _fakers.MeetingAttendee.Generate(); - attendee.Meeting = _fakers.Meeting.Generate(); + MeetingAttendee attendee = _fakers.MeetingAttendee.GenerateOne(); + attendee.Meeting = _fakers.Meeting.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -596,8 +596,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToMany_relationship() { // Arrange - Meeting meeting = _fakers.Meeting.Generate(); - meeting.Attendees = _fakers.MeetingAttendee.Generate(2); + Meeting meeting = _fakers.Meeting.GenerateOne(); + meeting.Attendees = _fakers.MeetingAttendee.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -644,7 +644,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_side_effects() { // Arrange - Meeting newMeeting = _fakers.Meeting.Generate(); + Meeting newMeeting = _fakers.Meeting.GenerateOne(); newMeeting.Id = Guid.NewGuid(); var requestBody = new @@ -712,7 +712,7 @@ public async Task Can_create_resource_with_side_effects() public async Task Can_update_resource_with_side_effects() { // Arrange - MeetingAttendee existingAttendee = _fakers.MeetingAttendee.Generate(); + MeetingAttendee existingAttendee = _fakers.MeetingAttendee.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -778,8 +778,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_relationship_for_type_at_end() { // Arrange - MeetingAttendee existingAttendee = _fakers.MeetingAttendee.Generate(); - existingAttendee.Meeting = _fakers.Meeting.Generate(); + MeetingAttendee existingAttendee = _fakers.MeetingAttendee.GenerateOne(); + existingAttendee.Meeting = _fakers.Meeting.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -827,7 +827,7 @@ public async Task Includes_version_at_resource_endpoint() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.IncludeJsonApiVersion = true; - MeetingAttendee attendee = _fakers.MeetingAttendee.Generate(); + MeetingAttendee attendee = _fakers.MeetingAttendee.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionTests.cs index 7bd7fe66f1..9de187d493 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionTests.cs @@ -40,7 +40,7 @@ public SoftDeletionTests(IntegrationTestContext departments = _fakers.Department.Generate(2); + List departments = _fakers.Department.GenerateList(2); departments[0].SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -66,7 +66,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Filter_on_primary_resources_excludes_soft_deleted() { // Arrange - List departments = _fakers.Department.Generate(3); + List departments = _fakers.Department.GenerateList(3); departments[0].Name = "Support"; @@ -98,12 +98,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_excludes_soft_deleted() { // Arrange - List companies = _fakers.Company.Generate(2); + List companies = _fakers.Company.GenerateList(2); companies[0].SoftDeletedAt = SoftDeletionTime; - companies[0].Departments = _fakers.Department.Generate(1); + companies[0].Departments = _fakers.Department.GenerateList(1); - companies[1].Departments = _fakers.Department.Generate(2); + companies[1].Departments = _fakers.Department.GenerateList(2); companies[1].Departments.ElementAt(1).SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -134,7 +134,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_soft_deleted_primary_resource_by_ID() { // Arrange - Department department = _fakers.Department.Generate(); + Department department = _fakers.Department.GenerateOne(); department.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -163,9 +163,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resources_for_soft_deleted_parent() { // Arrange - Company company = _fakers.Company.Generate(); + Company company = _fakers.Company.GenerateOne(); company.SoftDeletedAt = SoftDeletionTime; - company.Departments = _fakers.Department.Generate(1); + company.Departments = _fakers.Department.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -193,8 +193,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resources_excludes_soft_deleted() { // Arrange - Company company = _fakers.Company.Generate(); - company.Departments = _fakers.Department.Generate(2); + Company company = _fakers.Company.GenerateOne(); + company.Departments = _fakers.Department.GenerateList(2); company.Departments.ElementAt(0).SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -219,9 +219,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resource_for_soft_deleted_parent() { // Arrange - Department department = _fakers.Department.Generate(); + Department department = _fakers.Department.GenerateOne(); department.SoftDeletedAt = SoftDeletionTime; - department.Company = _fakers.Company.Generate(); + department.Company = _fakers.Company.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -249,8 +249,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_soft_deleted_secondary_resource() { // Arrange - Department department = _fakers.Department.Generate(); - department.Company = _fakers.Company.Generate(); + Department department = _fakers.Department.GenerateOne(); + department.Company = _fakers.Company.GenerateOne(); department.Company.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -274,9 +274,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToMany_relationship_for_soft_deleted_parent() { // Arrange - Company company = _fakers.Company.Generate(); + Company company = _fakers.Company.GenerateOne(); company.SoftDeletedAt = SoftDeletionTime; - company.Departments = _fakers.Department.Generate(1); + company.Departments = _fakers.Department.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -304,8 +304,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_excludes_soft_deleted() { // Arrange - Company company = _fakers.Company.Generate(); - company.Departments = _fakers.Department.Generate(2); + Company company = _fakers.Company.GenerateOne(); + company.Departments = _fakers.Department.GenerateList(2); company.Departments.ElementAt(0).SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -330,9 +330,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToOne_relationship_for_soft_deleted_parent() { // Arrange - Department department = _fakers.Department.Generate(); + Department department = _fakers.Department.GenerateOne(); department.SoftDeletedAt = SoftDeletionTime; - department.Company = _fakers.Company.Generate(); + department.Company = _fakers.Company.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -360,8 +360,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToOne_relationship_excludes_soft_deleted() { // Arrange - Department department = _fakers.Department.Generate(); - department.Company = _fakers.Company.Generate(); + Department department = _fakers.Department.GenerateOne(); + department.Company = _fakers.Company.GenerateOne(); department.Company.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -385,10 +385,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_ToMany_relationship_to_soft_deleted() { // Arrange - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); existingDepartment.SoftDeletedAt = SoftDeletionTime; - string newCompanyName = _fakers.Company.Generate().Name; + string newCompanyName = _fakers.Company.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -444,10 +444,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_ToOne_relationship_to_soft_deleted() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; - string newDepartmentName = _fakers.Department.Generate().Name; + string newDepartmentName = _fakers.Department.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -498,10 +498,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_soft_deleted_resource() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; - string newCompanyName = _fakers.Company.Generate().Name; + string newCompanyName = _fakers.Company.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -542,9 +542,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_ToMany_relationship_to_soft_deleted() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); existingDepartment.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -598,9 +598,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_ToOne_relationship_to_soft_deleted() { // Arrange - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -649,9 +649,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToMany_relationship_for_soft_deleted_parent() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; - existingCompany.Departments = _fakers.Department.Generate(1); + existingCompany.Departments = _fakers.Department.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -684,9 +684,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToMany_relationship_to_soft_deleted() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); existingDepartment.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -729,7 +729,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToOne_relationship_for_soft_deleted_parent() { // Arrange - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); existingDepartment.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -763,9 +763,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToOne_relationship_to_soft_deleted() { // Arrange - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -803,10 +803,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_ToMany_relationship_for_soft_deleted_parent() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -846,9 +846,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_ToMany_relationship_with_soft_deleted() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); existingDepartment.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -891,9 +891,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_ToMany_relationship_for_soft_deleted_parent() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; - existingCompany.Departments = _fakers.Department.Generate(1); + existingCompany.Departments = _fakers.Department.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -933,8 +933,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_ToMany_relationship_with_soft_deleted() { // Arrange - Company existingCompany = _fakers.Company.Generate(); - existingCompany.Departments = _fakers.Department.Generate(1); + Company existingCompany = _fakers.Company.GenerateOne(); + existingCompany.Departments = _fakers.Department.GenerateList(1); existingCompany.Departments.ElementAt(0).SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -977,7 +977,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_soft_delete_resource() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1008,7 +1008,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_delete_soft_deleted_resource() { // Arrange - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); existingDepartment.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/EmptyGuidAsKeyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/EmptyGuidAsKeyTests.cs index bde6fca28a..1fa313fa71 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/EmptyGuidAsKeyTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/EmptyGuidAsKeyTests.cs @@ -30,7 +30,7 @@ public EmptyGuidAsKeyTests(IntegrationTestContext maps = _fakers.Map.Generate(2); + List maps = _fakers.Map.GenerateList(2); maps[0].Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -62,9 +62,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_by_empty_ID_with_include() { // Arrange - Map map = _fakers.Map.Generate(); + Map map = _fakers.Map.GenerateOne(); map.Id = Guid.Empty; - map.Game = _fakers.Game.Generate(); + map.Game = _fakers.Game.GenerateOne(); map.Game.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -95,7 +95,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_empty_ID() { // Arrange - string newName = _fakers.Map.Generate().Name; + string newName = _fakers.Map.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -140,10 +140,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_empty_ID() { // Arrange - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; - string newName = _fakers.Map.Generate().Name; + string newName = _fakers.Map.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -188,8 +188,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ToOne_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.ActiveMap = _fakers.Map.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.ActiveMap = _fakers.Map.GenerateOne(); existingGame.ActiveMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -227,9 +227,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_ToOne_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -272,10 +272,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ToOne_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.ActiveMap = _fakers.Map.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.ActiveMap = _fakers.Map.GenerateOne(); - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -318,8 +318,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ToMany_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.Maps = _fakers.Map.Generate(2); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.Maps = _fakers.Map.GenerateList(2); existingGame.Maps.ElementAt(0).Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -357,9 +357,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_ToMany_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -405,10 +405,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ToMany_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.Maps = _fakers.Map.Generate(2); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.Maps = _fakers.Map.GenerateList(2); - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -454,10 +454,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ToMany_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.Maps = _fakers.Map.Generate(1); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.Maps = _fakers.Map.GenerateList(1); - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -503,8 +503,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ToMany_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.Maps = _fakers.Map.Generate(2); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.Maps = _fakers.Map.GenerateList(2); existingGame.Maps.ElementAt(0).Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -550,7 +550,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_with_empty_ID() { // Arrange - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/WhiteSpaceAsKeyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/WhiteSpaceAsKeyTests.cs index 025d8df152..9e47b3e6ce 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/WhiteSpaceAsKeyTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/WhiteSpaceAsKeyTests.cs @@ -50,7 +50,7 @@ public WhiteSpaceAsKeyTests(IntegrationTestContext players = _fakers.Player.Generate(2); + List players = _fakers.Player.GenerateList(2); players[0].Id = SingleSpace; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -82,9 +82,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_by_space_ID_with_include() { // Arrange - Player player = _fakers.Player.Generate(); + Player player = _fakers.Player.GenerateOne(); player.Id = SingleSpace; - player.ActiveGame = _fakers.Game.Generate(); + player.ActiveGame = _fakers.Game.GenerateOne(); player.ActiveGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -115,7 +115,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_space_ID() { // Arrange - string newEmailAddress = _fakers.Player.Generate().EmailAddress; + string newEmailAddress = _fakers.Player.GenerateOne().EmailAddress; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -160,10 +160,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_space_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); existingPlayer.Id = SingleSpace; - string newEmailAddress = _fakers.Player.Generate().EmailAddress; + string newEmailAddress = _fakers.Player.GenerateOne().EmailAddress; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -208,8 +208,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ToOne_relationship_with_space_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.Host = _fakers.Player.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.Host = _fakers.Player.GenerateOne(); existingGame.Host.Id = string.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -247,9 +247,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_ToOne_relationship_with_space_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); - Player existingPlayer = _fakers.Player.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); existingPlayer.Id = SingleSpace; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -292,10 +292,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ToOne_relationship_with_space_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.Host = _fakers.Player.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.Host = _fakers.Player.GenerateOne(); - Player existingPlayer = _fakers.Player.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); existingPlayer.Id = SingleSpace; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -338,8 +338,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ToMany_relationship_with_space_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.ActivePlayers = _fakers.Player.Generate(2); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.ActivePlayers = _fakers.Player.GenerateList(2); existingGame.ActivePlayers.ElementAt(0).Id = SingleSpace; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -377,9 +377,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_ToMany_relationship_with_space_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); - Player existingPlayer = _fakers.Player.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); existingPlayer.Id = SingleSpace; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -425,10 +425,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ToMany_relationship_with_space_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.ActivePlayers = _fakers.Player.Generate(2); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.ActivePlayers = _fakers.Player.GenerateList(2); - Player existingPlayer = _fakers.Player.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); existingPlayer.Id = SingleSpace; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -474,10 +474,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ToMany_relationship_with_space_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.ActivePlayers = _fakers.Player.Generate(1); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.ActivePlayers = _fakers.Player.GenerateList(1); - Player existingPlayer = _fakers.Player.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); existingPlayer.Id = SingleSpace; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -523,8 +523,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ToMany_relationship_with_space_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.ActivePlayers = _fakers.Player.Generate(2); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.ActivePlayers = _fakers.Player.GenerateList(2); existingGame.ActivePlayers.ElementAt(0).Id = SingleSpace; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -570,7 +570,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_with_space_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); existingPlayer.Id = SingleSpace; await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroAsKeyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroAsKeyTests.cs index 19baa0cf58..a0ca13c4fa 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroAsKeyTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroAsKeyTests.cs @@ -30,7 +30,7 @@ public ZeroAsKeyTests(IntegrationTestContext, public async Task Can_filter_by_zero_ID_on_primary_resources() { // Arrange - List games = _fakers.Game.Generate(2); + List games = _fakers.Game.GenerateList(2); games[0].Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -62,9 +62,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_by_zero_ID_with_include() { // Arrange - Game game = _fakers.Game.Generate(); + Game game = _fakers.Game.GenerateOne(); game.Id = 0; - game.ActivePlayers = _fakers.Player.Generate(1); + game.ActivePlayers = _fakers.Player.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -94,7 +94,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_zero_ID() { // Arrange - string newTitle = _fakers.Game.Generate().Title; + string newTitle = _fakers.Game.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -140,10 +140,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_zero_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; - string newTitle = _fakers.Game.Generate().Title; + string newTitle = _fakers.Game.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -190,8 +190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ToOne_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); - existingPlayer.ActiveGame = _fakers.Game.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.ActiveGame = _fakers.Game.GenerateOne(); existingPlayer.ActiveGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -229,9 +229,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_ToOne_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -274,10 +274,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ToOne_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); - existingPlayer.ActiveGame = _fakers.Game.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.ActiveGame = _fakers.Game.GenerateOne(); - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -320,8 +320,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ToMany_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); - existingPlayer.RecentlyPlayed = _fakers.Game.Generate(2); + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.RecentlyPlayed = _fakers.Game.GenerateList(2); existingPlayer.RecentlyPlayed.ElementAt(0).Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -359,9 +359,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_ToMany_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -407,10 +407,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ToMany_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); - existingPlayer.RecentlyPlayed = _fakers.Game.Generate(2); + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.RecentlyPlayed = _fakers.Game.GenerateList(2); - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -456,10 +456,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ToMany_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); - existingPlayer.RecentlyPlayed = _fakers.Game.Generate(1); + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.RecentlyPlayed = _fakers.Game.GenerateList(1); - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -505,8 +505,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ToMany_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); - existingPlayer.RecentlyPlayed = _fakers.Game.Generate(2); + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.RecentlyPlayed = _fakers.Game.GenerateList(2); existingPlayer.RecentlyPlayed.ElementAt(0).Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -552,7 +552,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_with_zero_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternInheritanceMatchTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternInheritanceMatchTests.cs index 067f8167d8..f5cd78f6ff 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternInheritanceMatchTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternInheritanceMatchTests.cs @@ -15,7 +15,7 @@ namespace JsonApiDotNetCoreTests.UnitTests.FieldChains; -public sealed class FieldChainPatternInheritanceMatchTests +public sealed class FieldChainPatternInheritanceMatchTests : IDisposable { private const string TBase = "bases"; private const string TDerivedQ = "derivedQs"; @@ -42,8 +42,13 @@ public sealed class FieldChainPatternInheritanceMatchTests public FieldChainPatternInheritanceMatchTests(ITestOutputHelper testOutputHelper) { +#pragma warning disable CA2000 // Dispose objects before losing scope + // Justification: LoggerFactory.AddProvider takes ownership (passing the provider as a constructor parameter does not). var loggerProvider = new XUnitLoggerProvider(testOutputHelper, null, LogOutputFields.Message); - _loggerFactory = new LoggerFactory([loggerProvider]); +#pragma warning restore CA2000 // Dispose objects before losing scope + + _loggerFactory = new LoggerFactory(); + _loggerFactory.AddProvider(loggerProvider); var options = new JsonApiOptions(); _resourceGraph = new ResourceGraphBuilder(options, NullLoggerFactory.Instance).Add().Add().Add().Build(); @@ -156,6 +161,11 @@ public void MatchFails(string patternText, string resourceTypeName, string field result.IsSuccess.Should().BeFalse(); } + public void Dispose() + { + _loggerFactory.Dispose(); + } + [UsedImplicitly(ImplicitUseTargetFlags.Members)] private abstract class Base : Identifiable { diff --git a/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternMatchTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternMatchTests.cs index 613dd4fd41..948ce73ff3 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternMatchTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternMatchTests.cs @@ -15,7 +15,7 @@ namespace JsonApiDotNetCoreTests.UnitTests.FieldChains; -public sealed class FieldChainPatternMatchTests +public sealed class FieldChainPatternMatchTests : IDisposable { private const string T = "resources"; private const string X = "unknown"; @@ -28,8 +28,13 @@ public sealed class FieldChainPatternMatchTests public FieldChainPatternMatchTests(ITestOutputHelper testOutputHelper) { +#pragma warning disable CA2000 // Dispose objects before losing scope + // Justification: LoggerFactory.AddProvider takes ownership (passing the provider as a constructor parameter does not). var loggerProvider = new XUnitLoggerProvider(testOutputHelper, null, LogOutputFields.Message); - _loggerFactory = new LoggerFactory([loggerProvider]); +#pragma warning restore CA2000 // Dispose objects before losing scope + + _loggerFactory = new LoggerFactory(); + _loggerFactory.AddProvider(loggerProvider); var options = new JsonApiOptions(); IResourceGraph resourceGraph = new ResourceGraphBuilder(options, NullLoggerFactory.Instance).Add().Build(); @@ -399,6 +404,11 @@ public void MatchFails(string patternText, string fieldChainText, string failure result.IsSuccess.Should().BeFalse(); } + public void Dispose() + { + _loggerFactory.Dispose(); + } + [UsedImplicitly(ImplicitUseTargetFlags.Members)] private sealed class Resource : Identifiable { diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Middleware/JsonApiMiddlewareTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Middleware/JsonApiMiddlewareTests.cs index 196ac6493e..a07287649f 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Middleware/JsonApiMiddlewareTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Middleware/JsonApiMiddlewareTests.cs @@ -7,7 +7,6 @@ using JsonApiDotNetCore.Resources.Annotations; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.Extensions.Logging.Abstractions; using TestBuildingBlocks; @@ -63,15 +62,17 @@ public async Task Sets_request_properties_correctly(string requestMethod, string // @formatter:wrap_chained_method_calls restore var httpContext = new DefaultHttpContext(); - IControllerResourceMapping controllerResourceMapping = SetupRoutes(httpContext, resourceGraph, requestMethod, requestPath); + FakeControllerResourceMapping controllerResourceMapping = SetupRoutes(httpContext, resourceGraph, requestMethod, requestPath); - var middleware = new JsonApiMiddleware(null, new HttpContextAccessor + var httpContextAccessor = new HttpContextAccessor { HttpContext = httpContext - }); + }; + + var middleware = new JsonApiMiddleware(null, httpContextAccessor, controllerResourceMapping, options, NullLogger.Instance); // Act - await middleware.InvokeAsync(httpContext, controllerResourceMapping, options, request, NullLogger.Instance); + await middleware.InvokeAsync(httpContext, request); // Assert request.Kind.Should().Be(expectKind); @@ -112,7 +113,7 @@ public async Task Sets_request_properties_correctly(string requestMethod, string request.WriteOperation.Should().Be(expectWriteOperation); } - private static IControllerResourceMapping SetupRoutes(HttpContext httpContext, IResourceGraph resourceGraph, string requestMethod, string requestPath) + private static FakeControllerResourceMapping SetupRoutes(HttpContext httpContext, IResourceGraph resourceGraph, string requestMethod, string requestPath) { httpContext.Request.Method = requestMethod; @@ -156,7 +157,7 @@ private static IControllerResourceMapping SetupRoutes(HttpContext httpContext, I httpContext.SetEndpoint(new Endpoint(null, new EndpointMetadataCollection(controllerActionDescriptor), null)); string? resourceTypePublicName = pathSegments.Length > 0 ? pathSegments[0] : null; - return new FakeJsonApiRoutingConvention(resourceGraph, resourceTypePublicName); + return new FakeControllerResourceMapping(resourceGraph, resourceTypePublicName); } public enum IsReadOnly @@ -165,7 +166,9 @@ public enum IsReadOnly No } +#pragma warning disable CA1711 // Identifiers should not have incorrect suffix public enum IsCollection +#pragma warning restore CA1711 // Identifiers should not have incorrect suffix { Yes, No @@ -191,16 +194,11 @@ private sealed class TodoItem : Identifiable public ISet Tags { get; set; } = new HashSet(); } - private sealed class FakeJsonApiRoutingConvention(IResourceGraph resourceGraph, string? resourceTypePublicName) : IJsonApiRoutingConvention + private sealed class FakeControllerResourceMapping(IResourceGraph resourceGraph, string? resourceTypePublicName) : IControllerResourceMapping { private readonly IResourceGraph _resourceGraph = resourceGraph; private readonly string? _resourceTypePublicName = resourceTypePublicName; - public void Apply(ApplicationModel application) - { - throw new NotImplementedException(); - } - public ResourceType? GetResourceTypeForController(Type? controllerType) { return _resourceTypePublicName != null ? _resourceGraph.FindResourceType(_resourceTypePublicName) : null; diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Queries/QueryExpressionRewriterTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Queries/QueryExpressionRewriterTests.cs index 3d2d8faa85..7f18610f89 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Queries/QueryExpressionRewriterTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Queries/QueryExpressionRewriterTests.cs @@ -52,11 +52,11 @@ public void VisitInclude(string expressionText, string expectedTypes) rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); - List expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); + string[] expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToArray(); visitedTypeNames.Should().ContainInOrder(expectedTypeNames); - visitedTypeNames.Should().HaveCount(expectedTypeNames.Count); + visitedTypeNames.Should().HaveCount(expectedTypeNames.Length); } [Theory] @@ -75,11 +75,11 @@ public void VisitSparseFieldSet(string expressionText, string expectedTypes) rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); - List expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); + string[] expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToArray(); visitedTypeNames.Should().ContainInOrder(expectedTypeNames); - visitedTypeNames.Should().HaveCount(expectedTypeNames.Count); + visitedTypeNames.Should().HaveCount(expectedTypeNames.Length); } [Fact] @@ -104,7 +104,7 @@ public void VisitSparseFieldTable() rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); visitedTypeNames.Should().HaveCount(3); visitedTypeNames[0].Should().Be("SparseFieldTableExpression"); @@ -135,11 +135,11 @@ public void VisitFilter(string expressionText, string expectedTypes) rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); - List expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); + string[] expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToArray(); visitedTypeNames.Should().ContainInOrder(expectedTypeNames); - visitedTypeNames.Should().HaveCount(expectedTypeNames.Count); + visitedTypeNames.Should().HaveCount(expectedTypeNames.Length); } [Theory] @@ -159,11 +159,11 @@ public void VisitSort(string expressionText, string expectedTypes) rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); - List expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); + string[] expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToArray(); visitedTypeNames.Should().ContainInOrder(expectedTypeNames); - visitedTypeNames.Should().HaveCount(expectedTypeNames.Count); + visitedTypeNames.Should().HaveCount(expectedTypeNames.Length); } [Theory] @@ -182,11 +182,11 @@ public void VisitPagination(string expressionText, string expectedTypes) rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); - List expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); + string[] expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToArray(); visitedTypeNames.Should().ContainInOrder(expectedTypeNames); - visitedTypeNames.Should().HaveCount(expectedTypeNames.Count); + visitedTypeNames.Should().HaveCount(expectedTypeNames.Length); } [Theory] @@ -207,10 +207,10 @@ public void VisitParameterScope(string expressionText, string expectedTypes) rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); - List expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); + string[] expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToArray(); visitedTypeNames.Should().ContainInOrder(expectedTypeNames); - visitedTypeNames.Should().HaveCount(expectedTypeNames.Count); + visitedTypeNames.Should().HaveCount(expectedTypeNames.Length); } } diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Queries/TestableQueryExpressionRewriter.cs b/test/JsonApiDotNetCoreTests/UnitTests/Queries/TestableQueryExpressionRewriter.cs index ec4da0702a..1f46516854 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Queries/TestableQueryExpressionRewriter.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Queries/TestableQueryExpressionRewriter.cs @@ -114,16 +114,16 @@ public override QueryExpression VisitSparseFieldSet(SparseFieldSetExpression exp return base.VisitQueryStringParameterScope(expression, argument); } - public override QueryExpression PaginationQueryStringValue(PaginationQueryStringValueExpression expression, object? argument) + public override QueryExpression VisitPaginationQueryStringValue(PaginationQueryStringValueExpression expression, object? argument) { Capture(expression); - return base.PaginationQueryStringValue(expression, argument); + return base.VisitPaginationQueryStringValue(expression, argument); } - public override QueryExpression PaginationElementQueryStringValue(PaginationElementQueryStringValueExpression expression, object? argument) + public override QueryExpression VisitPaginationElementQueryStringValue(PaginationElementQueryStringValueExpression expression, object? argument) { Capture(expression); - return base.PaginationElementQueryStringValue(expression, argument); + return base.VisitPaginationElementQueryStringValue(expression, argument); } public override QueryExpression VisitInclude(IncludeExpression expression, object? argument) diff --git a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/FilterParseTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/FilterParseTests.cs index 9799d7d6ae..dd8a595523 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/FilterParseTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/FilterParseTests.cs @@ -22,7 +22,8 @@ public FilterParseTests() { Options.EnableLegacyFilterNotation = false; - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var scopeParser = new QueryStringParameterScopeParser(); var valueParser = new FilterParser(resourceFactory); _reader = new FilterQueryStringParameterReader(scopeParser, valueParser, Request, ResourceGraph, Options); @@ -221,7 +222,8 @@ public void Reader_Read_Succeeds(string parameterName, string parameterValue, st public void Throws_When_ResourceType_Scope_Not_Disposed() { // Arrange - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var parser = new NotDisposingFilterParser(resourceFactory); // Act @@ -236,7 +238,8 @@ public void Throws_When_ResourceType_Scope_Not_Disposed() public void Throws_When_No_ResourceType_In_Scope() { // Arrange - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var parser = new ResourceTypeAccessingFilterParser(resourceFactory); // Act diff --git a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/LegacyFilterParseTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/LegacyFilterParseTests.cs index 2fcc490d1e..5cbbcc1936 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/LegacyFilterParseTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/LegacyFilterParseTests.cs @@ -24,7 +24,8 @@ public LegacyFilterParseTests() Request.PrimaryResourceType = ResourceGraph.GetResourceType(); - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var scopeParser = new QueryStringParameterScopeParser(); var valueParser = new FilterParser(resourceFactory); _reader = new FilterQueryStringParameterReader(scopeParser, valueParser, Request, ResourceGraph, Options); diff --git a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/PaginationParseTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/PaginationParseTests.cs index f98ff59f59..f6efc0e597 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/PaginationParseTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/PaginationParseTests.cs @@ -15,7 +15,7 @@ namespace JsonApiDotNetCoreTests.UnitTests.QueryStringParameters; public sealed class PaginationParseTests : BaseParseTests { - private readonly IPaginationQueryStringParameterReader _reader; + private readonly PaginationQueryStringParameterReader _reader; public PaginationParseTests() { diff --git a/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/HasManyAttributeTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/HasManyAttributeTests.cs index 34ca2ef259..06339cf293 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/HasManyAttributeTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/HasManyAttributeTests.cs @@ -73,10 +73,7 @@ public void Can_set_value_to_collection_with_single_resource() var resource = new TestResource(); - var children = new List - { - resource - }; + List children = [resource]; // Act attribute.SetValue(resource, children); @@ -96,11 +93,11 @@ public void Cannot_set_value_to_collection_with_null_element() var resource = new TestResource(); - var children = new List - { + List children = + [ resource, null! - }; + ]; // Act Action action = () => attribute.SetValue(resource, children); @@ -120,11 +117,11 @@ public void Cannot_set_value_to_collection_with_primitive_element() var resource = new TestResource(); - var children = new List - { + List children = + [ resource, 1 - }; + ]; // Act Action action = () => attribute.SetValue(resource, children); diff --git a/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/ResourceGraphBuilderTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/ResourceGraphBuilderTests.cs index ebce906b9d..e37c06bb72 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/ResourceGraphBuilderTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/ResourceGraphBuilderTests.cs @@ -256,14 +256,15 @@ public void Logs_warning_when_adding_non_resource_type() { // Arrange var options = new JsonApiOptions(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Warning); + using var loggerProvider = new CapturingLoggerProvider(LogLevel.Warning); + using var loggerFactory = new LoggerFactory([loggerProvider]); var builder = new ResourceGraphBuilder(options, loggerFactory); // Act builder.Add(typeof(NonResource)); // Assert - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.ShouldHaveCount(1); logLines[0].Should().Be( @@ -275,14 +276,15 @@ public void Logs_no_warning_when_adding_non_resource_type_with_suppression() { // Arrange var options = new JsonApiOptions(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Warning); + using var loggerProvider = new CapturingLoggerProvider(LogLevel.Warning); + using var loggerFactory = new LoggerFactory([loggerProvider]); var builder = new ResourceGraphBuilder(options, loggerFactory); // Act builder.Add(typeof(NonResourceWithSuppression)); // Assert - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.Should().BeEmpty(); } @@ -291,14 +293,15 @@ public void Logs_warning_when_adding_resource_without_attributes() { // Arrange var options = new JsonApiOptions(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Warning); + using var loggerProvider = new CapturingLoggerProvider(LogLevel.Warning); + using var loggerFactory = new LoggerFactory([loggerProvider]); var builder = new ResourceGraphBuilder(options, loggerFactory); // Act builder.Add(); // Assert - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.ShouldHaveCount(1); logLines[0].Should().Be($"[WARNING] Type '{typeof(ResourceWithHasOneRelationship)}' does not contain any attributes."); @@ -309,14 +312,15 @@ public void Logs_warning_on_empty_graph() { // Arrange var options = new JsonApiOptions(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Warning); + using var loggerProvider = new CapturingLoggerProvider(LogLevel.Warning); + using var loggerFactory = new LoggerFactory([loggerProvider]); var builder = new ResourceGraphBuilder(options, loggerFactory); // Act builder.Build(); // Assert - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.ShouldHaveCount(1); logLines[0].Should().Be("[WARNING] The resource graph is empty."); diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Serialization/InputConversionTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/InputConversionTests.cs index b16d29e28f..1c0ab48c22 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Serialization/InputConversionTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/InputConversionTests.cs @@ -15,8 +15,10 @@ namespace JsonApiDotNetCoreTests.UnitTests.Serialization; -public sealed class InputConversionTests +public sealed class InputConversionTests : IDisposable { + private readonly ServiceContainer _serviceProvider = new(); + [Fact] public void Converts_various_data_types_with_values() { @@ -56,17 +58,17 @@ public void Converts_various_data_types_with_values() Value = "Single" }; - var complexObjectList = new List - { - new() + List complexObjectList = + [ + new ComplexObject { Value = "One" }, - new() + new ComplexObject { Value = "Two" } - }; + ]; var document = new Document { @@ -241,19 +243,18 @@ public void Converts_various_data_types_with_defaults() model.ComplexObjectList.Should().BeNull(); } - private static DocumentAdapter CreateDocumentAdapter(Func createRequest) + private DocumentAdapter CreateDocumentAdapter(Func createRequest) where TResource : Identifiable { var options = new JsonApiOptions(); IResourceGraph resourceGraph = new ResourceGraphBuilder(options, NullLoggerFactory.Instance).Add().Build(); options.SerializerOptions.Converters.Add(new ResourceObjectConverter(resourceGraph)); - var serviceContainer = new ServiceContainer(); - var resourceFactory = new ResourceFactory(serviceContainer); - var resourceDefinitionAccessor = new ResourceDefinitionAccessor(resourceGraph, serviceContainer); + var resourceFactory = new ResourceFactory(_serviceProvider); + var resourceDefinitionAccessor = new ResourceDefinitionAccessor(resourceGraph, _serviceProvider); - serviceContainer.AddService(typeof(IResourceDefinitionAccessor), resourceDefinitionAccessor); - serviceContainer.AddService(typeof(IResourceDefinition), new JsonApiResourceDefinition(resourceGraph)); + _serviceProvider.AddService(typeof(IResourceDefinitionAccessor), resourceDefinitionAccessor); + _serviceProvider.AddService(typeof(IResourceDefinition), new JsonApiResourceDefinition(resourceGraph)); JsonApiRequest request = createRequest(resourceGraph); var targetedFields = new TargetedFields(); @@ -275,6 +276,11 @@ private static DocumentAdapter CreateDocumentAdapter(Func { diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Response/ResponseModelAdapterTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Response/ResponseModelAdapterTests.cs index 2d2e07e600..032bcd7c1f 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Response/ResponseModelAdapterTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Response/ResponseModelAdapterTests.cs @@ -22,13 +22,13 @@ public void Resources_in_deeply_nested_circular_chain_are_written_in_relationshi // Arrange var fakers = new ResponseSerializationFakers(); - Article article = fakers.Article.Generate(); - article.Author = fakers.Person.Generate(); - article.Author.Blogs = fakers.Blog.Generate(2).ToHashSet(); + Article article = fakers.Article.GenerateOne(); + article.Author = fakers.Person.GenerateOne(); + article.Author.Blogs = fakers.Blog.GenerateSet(2); article.Author.Blogs.ElementAt(0).Reviewer = article.Author; - article.Author.Blogs.ElementAt(1).Reviewer = fakers.Person.Generate(); - article.Author.FavoriteFood = fakers.Food.Generate(); - article.Author.Blogs.ElementAt(1).Reviewer.FavoriteFood = fakers.Food.Generate(); + article.Author.Blogs.ElementAt(1).Reviewer = fakers.Person.GenerateOne(); + article.Author.FavoriteFood = fakers.Food.GenerateOne(); + article.Author.Blogs.ElementAt(1).Reviewer.FavoriteFood = fakers.Food.GenerateOne(); IJsonApiOptions options = new JsonApiOptions { @@ -163,15 +163,15 @@ public void Resources_in_deeply_nested_circular_chains_are_written_in_relationsh // Arrange var fakers = new ResponseSerializationFakers(); - Article article1 = fakers.Article.Generate(); - article1.Author = fakers.Person.Generate(); - article1.Author.Blogs = fakers.Blog.Generate(2).ToHashSet(); + Article article1 = fakers.Article.GenerateOne(); + article1.Author = fakers.Person.GenerateOne(); + article1.Author.Blogs = fakers.Blog.GenerateSet(2); article1.Author.Blogs.ElementAt(0).Reviewer = article1.Author; - article1.Author.Blogs.ElementAt(1).Reviewer = fakers.Person.Generate(); - article1.Author.FavoriteFood = fakers.Food.Generate(); - article1.Author.Blogs.ElementAt(1).Reviewer.FavoriteFood = fakers.Food.Generate(); + article1.Author.Blogs.ElementAt(1).Reviewer = fakers.Person.GenerateOne(); + article1.Author.FavoriteFood = fakers.Food.GenerateOne(); + article1.Author.Blogs.ElementAt(1).Reviewer.FavoriteFood = fakers.Food.GenerateOne(); - Article article2 = fakers.Article.Generate(); + Article article2 = fakers.Article.GenerateOne(); article2.Author = article1.Author; IJsonApiOptions options = new JsonApiOptions @@ -328,22 +328,22 @@ public void Resources_in_overlapping_deeply_nested_circular_chains_are_written_i // Arrange var fakers = new ResponseSerializationFakers(); - Article article = fakers.Article.Generate(); - article.Author = fakers.Person.Generate(); - article.Author.Blogs = fakers.Blog.Generate(2).ToHashSet(); + Article article = fakers.Article.GenerateOne(); + article.Author = fakers.Person.GenerateOne(); + article.Author.Blogs = fakers.Blog.GenerateSet(2); article.Author.Blogs.ElementAt(0).Reviewer = article.Author; - article.Author.Blogs.ElementAt(1).Reviewer = fakers.Person.Generate(); - article.Author.FavoriteFood = fakers.Food.Generate(); - article.Author.Blogs.ElementAt(1).Reviewer.FavoriteFood = fakers.Food.Generate(); + article.Author.Blogs.ElementAt(1).Reviewer = fakers.Person.GenerateOne(); + article.Author.FavoriteFood = fakers.Food.GenerateOne(); + article.Author.Blogs.ElementAt(1).Reviewer.FavoriteFood = fakers.Food.GenerateOne(); - article.Reviewer = fakers.Person.Generate(); - article.Reviewer.Blogs = fakers.Blog.Generate(1).ToHashSet(); + article.Reviewer = fakers.Person.GenerateOne(); + article.Reviewer.Blogs = fakers.Blog.GenerateSet(1); article.Reviewer.Blogs.Add(article.Author.Blogs.ElementAt(0)); article.Reviewer.Blogs.ElementAt(0).Author = article.Reviewer; article.Reviewer.Blogs.ElementAt(1).Author = article.Author.Blogs.ElementAt(1).Reviewer; - article.Author.Blogs.ElementAt(1).Reviewer.FavoriteSong = fakers.Song.Generate(); - article.Reviewer.FavoriteSong = fakers.Song.Generate(); + article.Author.Blogs.ElementAt(1).Reviewer.FavoriteSong = fakers.Song.GenerateOne(); + article.Reviewer.FavoriteSong = fakers.Song.GenerateOne(); IJsonApiOptions options = new JsonApiOptions { @@ -553,8 +553,8 @@ public void Duplicate_children_in_multiple_chains_occur_once_in_output() // Arrange var fakers = new ResponseSerializationFakers(); - Person person = fakers.Person.Generate(); - List
articles = fakers.Article.Generate(5); + Person person = fakers.Person.GenerateOne(); + List
articles = fakers.Article.GenerateList(5); articles.ForEach(article => article.Author = person); articles.ForEach(article => article.Reviewer = person); diff --git a/test/NoEntityFrameworkTests/NullSafeExpressionRewriterTests.cs b/test/NoEntityFrameworkTests/NullSafeExpressionRewriterTests.cs index 0a61821987..0258877f49 100644 --- a/test/NoEntityFrameworkTests/NullSafeExpressionRewriterTests.cs +++ b/test/NoEntityFrameworkTests/NullSafeExpressionRewriterTests.cs @@ -18,13 +18,13 @@ public void Can_rewrite_where_clause_with_constant_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -32,7 +32,7 @@ public void Can_rewrite_where_clause_with_constant_comparison() Id = generator.GetNext() } } - }; + ]; TestResource lastInDataSource = dataSource.Last(); @@ -57,13 +57,13 @@ public void Can_rewrite_where_clause_with_member_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -71,7 +71,7 @@ public void Can_rewrite_where_clause_with_member_comparison() Id = generator.GetNext() } }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -86,7 +86,7 @@ public void Can_rewrite_where_clause_with_member_comparison() } } }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -102,7 +102,7 @@ public void Can_rewrite_where_clause_with_member_comparison() } } } - }; + ]; TestResource lastInDataSource = dataSource.Last(); lastInDataSource.FirstChild!.Parent!.Id = lastInDataSource.Parent!.Id; @@ -130,13 +130,13 @@ public void Can_rewrite_where_clause_with_not_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -144,7 +144,7 @@ public void Can_rewrite_where_clause_with_not_comparison() Id = generator.GetNext() } } - }; + ]; // ReSharper disable once NegativeEqualityExpression Expression, IEnumerable>> expression = source => source.Where(resource => !(resource.Parent!.Id == 3)); @@ -168,13 +168,13 @@ public void Can_rewrite_where_clause_with_any_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -182,7 +182,7 @@ public void Can_rewrite_where_clause_with_any_comparison() Id = generator.GetNext() } }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -201,7 +201,7 @@ public void Can_rewrite_where_clause_with_any_comparison() } } } - }; + ]; TestResource lastInDataSource = dataSource.Last(); @@ -228,13 +228,13 @@ public void Can_rewrite_where_clause_with_conditional_any_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -242,7 +242,7 @@ public void Can_rewrite_where_clause_with_conditional_any_comparison() Id = generator.GetNext() } }, - new() + new TestResource { Id = generator.GetNext(), Children = @@ -260,7 +260,7 @@ public void Can_rewrite_where_clause_with_conditional_any_comparison() } } } - }; + ]; // ReSharper disable once NegativeEqualityExpression Expression, IEnumerable>> expression = source => source.Where(resource => @@ -287,14 +287,14 @@ public void Can_rewrite_where_clause_with_nested_conditional_any_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext(), Children = null! }, - new() + new TestResource { Id = generator.GetNext(), Children = @@ -312,7 +312,7 @@ public void Can_rewrite_where_clause_with_nested_conditional_any_comparison() } } }, - new() + new TestResource { Id = generator.GetNext(), Children = @@ -335,7 +335,7 @@ public void Can_rewrite_where_clause_with_nested_conditional_any_comparison() } } } - }; + ]; TestResource lastInDataSource = dataSource.Last(); @@ -363,13 +363,13 @@ public void Can_rewrite_where_clause_with_count_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -378,7 +378,7 @@ public void Can_rewrite_where_clause_with_count_comparison() }, Children = null! }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -404,14 +404,16 @@ public void Can_rewrite_where_clause_with_count_comparison() } } } - }; + ]; TestResource lastInDataSource = dataSource.Last(); +#pragma warning disable CA1829 // Use Length/Count property instead of Count() when available // ReSharper disable UseCollectionCountProperty Expression, IEnumerable>> expression = source => source.Where(resource => resource.Children.Count() > resource.Parent!.Children.Count()); // ReSharper restore UseCollectionCountProperty +#pragma warning restore CA1829 // Use Length/Count property instead of Count() when available var rewriter = new NullSafeExpressionRewriter(); @@ -433,13 +435,13 @@ public void Can_rewrite_order_by_clause_with_long() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -447,7 +449,7 @@ public void Can_rewrite_order_by_clause_with_long() Id = generator.GetNext() } }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -455,7 +457,7 @@ public void Can_rewrite_order_by_clause_with_long() Id = generator.GetNext() } } - }; + ]; Expression, IEnumerable>> expression = source => source.OrderBy(resource => resource.Parent!.Id); @@ -480,13 +482,13 @@ public void Can_rewrite_order_by_clause_with_IntPtr() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -494,7 +496,7 @@ public void Can_rewrite_order_by_clause_with_IntPtr() Id = generator.GetNext() } }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -503,7 +505,7 @@ public void Can_rewrite_order_by_clause_with_IntPtr() Pointer = OnePointer } } - }; + ]; Expression, IEnumerable>> expression = source => source.OrderBy(resource => resource.Parent!.Pointer); @@ -529,13 +531,13 @@ public void Can_rewrite_order_by_clause_with_nullable_int() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -543,7 +545,7 @@ public void Can_rewrite_order_by_clause_with_nullable_int() Id = generator.GetNext() } }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -552,7 +554,7 @@ public void Can_rewrite_order_by_clause_with_nullable_int() Number = -1 } } - }; + ]; Expression, IEnumerable>> expression = source => source.OrderBy(resource => resource.Parent!.Number); @@ -577,13 +579,13 @@ public void Can_rewrite_order_by_clause_with_enum() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -591,7 +593,7 @@ public void Can_rewrite_order_by_clause_with_enum() Id = generator.GetNext() } }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -600,7 +602,7 @@ public void Can_rewrite_order_by_clause_with_enum() Enum = TestEnum.Two } } - }; + ]; Expression, IEnumerable>> expression = source => source.OrderBy(resource => resource.Parent!.Enum); @@ -625,13 +627,13 @@ public void Can_rewrite_order_by_clause_with_string() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -639,7 +641,7 @@ public void Can_rewrite_order_by_clause_with_string() Id = generator.GetNext() } }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -648,7 +650,7 @@ public void Can_rewrite_order_by_clause_with_string() Name = "X" } } - }; + ]; Expression, IEnumerable>> expression = source => source.OrderBy(resource => resource.Parent!.Name); @@ -673,13 +675,13 @@ public void Can_rewrite_order_by_clause_with_count() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -687,7 +689,7 @@ public void Can_rewrite_order_by_clause_with_count() Id = generator.GetNext() } }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -696,7 +698,7 @@ public void Can_rewrite_order_by_clause_with_count() }, Children = null! }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -711,11 +713,13 @@ public void Can_rewrite_order_by_clause_with_count() } } } - }; + ]; +#pragma warning disable CA1829 // Use Length/Count property instead of Count() when available // ReSharper disable once UseCollectionCountProperty Expression, IEnumerable>> expression = source => source.OrderBy(resource => resource.Parent!.Children.Count()); +#pragma warning restore CA1829 // Use Length/Count property instead of Count() when available var rewriter = new NullSafeExpressionRewriter(); @@ -740,13 +744,13 @@ public void Can_rewrite_nested_descending_order_by_clauses() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { - new() + List dataSource = + [ + new TestResource { Id = generator.GetNext() }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -756,7 +760,7 @@ public void Can_rewrite_nested_descending_order_by_clauses() Number = 1 } }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -766,7 +770,7 @@ public void Can_rewrite_nested_descending_order_by_clauses() Number = 10 } }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -776,7 +780,7 @@ public void Can_rewrite_nested_descending_order_by_clauses() Number = 1 } }, - new() + new TestResource { Id = generator.GetNext(), Parent = new TestResource @@ -786,7 +790,7 @@ public void Can_rewrite_nested_descending_order_by_clauses() Number = 10 } } - }; + ]; Expression, IEnumerable>> expression = source => source.OrderByDescending(resource => resource.Parent!.Name).ThenByDescending(resource => resource.Parent!.Number); diff --git a/test/SourceGeneratorTests/SourceCodeBuilder.cs b/test/SourceGeneratorTests/SourceCodeBuilder.cs index 05bdc031a4..7ecc02cbba 100644 --- a/test/SourceGeneratorTests/SourceCodeBuilder.cs +++ b/test/SourceGeneratorTests/SourceCodeBuilder.cs @@ -12,7 +12,7 @@ public string Build() { StringBuilder builder = new(); - if (_namespaceImports.Any()) + if (_namespaceImports.Count > 0) { foreach (string namespaceImport in _namespaceImports) { diff --git a/test/TestBuildingBlocks/CapturingLoggerProvider.cs b/test/TestBuildingBlocks/CapturingLoggerProvider.cs new file mode 100644 index 0000000000..3996b1c9e2 --- /dev/null +++ b/test/TestBuildingBlocks/CapturingLoggerProvider.cs @@ -0,0 +1,118 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore; +using Microsoft.Extensions.Logging; + +namespace TestBuildingBlocks; + +[PublicAPI] +public sealed class CapturingLoggerProvider : ILoggerProvider +{ + private static readonly Func DefaultFilter = (_, _) => true; + private readonly Func _filter; + + private readonly object _lockObject = new(); + private readonly List _messages = []; + + public CapturingLoggerProvider() + : this(DefaultFilter) + { + } + + public CapturingLoggerProvider(LogLevel minimumLevel) + : this((_, logLevel) => logLevel != LogLevel.None && logLevel >= minimumLevel) + { + } + + public CapturingLoggerProvider(Func filter) + { + ArgumentGuard.NotNull(filter); + + _filter = filter; + } + + public ILogger CreateLogger(string categoryName) + { + ArgumentGuard.NotNullNorEmpty(categoryName); + + return new CapturingLogger(this, categoryName, _filter); + } + + public void Clear() + { + lock (_lockObject) + { + _messages.Clear(); + } + } + + public IReadOnlyList GetMessages() + { + LogMessage[] snapshot; + + lock (_lockObject) + { + snapshot = _messages.ToArray(); + } + + return snapshot.AsReadOnly(); + } + + public IReadOnlyList GetLines() + { + IReadOnlyList snapshot = GetMessages(); + return snapshot.Select(message => message.ToString()).ToArray().AsReadOnly(); + } + + private void Add(LogMessage message) + { + lock (_lockObject) + { + _messages.Add(message); + } + } + + public void Dispose() + { + } + + private sealed class CapturingLogger(CapturingLoggerProvider owner, string categoryName, Func filter) : ILogger + { + private readonly CapturingLoggerProvider _owner = owner; + private readonly string _categoryName = categoryName; + private readonly Func _filter = filter; + + public bool IsEnabled(LogLevel logLevel) + { + return _filter(_categoryName, logLevel); + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) + { + if (IsEnabled(logLevel)) + { + string text = formatter(state, exception); + var message = new LogMessage(logLevel, _categoryName, text); + _owner.Add(message); + } + } + + public IDisposable BeginScope(TState state) + where TState : notnull + { + return NullScope.Instance; + } + + private sealed class NullScope : IDisposable + { + public static readonly NullScope Instance = new(); + + private NullScope() + { + } + + public void Dispose() + { + } + } + } +} diff --git a/test/TestBuildingBlocks/DbContextExtensions.cs b/test/TestBuildingBlocks/DbContextExtensions.cs index d3a8a0e8ad..1d1dbc0650 100644 --- a/test/TestBuildingBlocks/DbContextExtensions.cs +++ b/test/TestBuildingBlocks/DbContextExtensions.cs @@ -44,10 +44,14 @@ private static async Task ClearTablesAsync(this DbContext dbContext, params Type } else { +#if !NET6_0 #pragma warning disable EF1002 // Risk of vulnerability to SQL injection. +#endif // Justification: Table names cannot be parameterized. await dbContext.Database.ExecuteSqlRawAsync($"DELETE FROM \"{tableName}\""); +#if !NET6_0 #pragma warning restore EF1002 // Risk of vulnerability to SQL injection. +#endif } } } diff --git a/test/TestBuildingBlocks/FakeLoggerFactory.cs b/test/TestBuildingBlocks/FakeLoggerFactory.cs deleted file mode 100644 index cb726bb4d7..0000000000 --- a/test/TestBuildingBlocks/FakeLoggerFactory.cs +++ /dev/null @@ -1,90 +0,0 @@ -using JetBrains.Annotations; -using Microsoft.Extensions.Logging; - -namespace TestBuildingBlocks; - -[PublicAPI] -public sealed class FakeLoggerFactory(LogLevel minimumLevel) : ILoggerFactory, ILoggerProvider -{ - public FakeLogger Logger { get; } = new(minimumLevel); - - public ILogger CreateLogger(string categoryName) - { - return Logger; - } - - public void AddProvider(ILoggerProvider provider) - { - } - - public void Dispose() - { - } - - public sealed class FakeLogger(LogLevel minimumLevel) : ILogger - { - private readonly LogLevel _minimumLevel = minimumLevel; - - private readonly object _lockObject = new(); - private readonly List _messages = []; - - public bool IsEnabled(LogLevel logLevel) - { - return _minimumLevel != LogLevel.None && logLevel >= _minimumLevel; - } - - public void Clear() - { - lock (_lockObject) - { - _messages.Clear(); - } - } - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) - { - if (IsEnabled(logLevel)) - { - string message = formatter(state, exception); - - lock (_lockObject) - { - _messages.Add(new FakeLogMessage(logLevel, message)); - } - } - } - - public IDisposable BeginScope(TState state) - where TState : notnull - { - return NullScope.Instance; - } - - public IReadOnlyList GetMessages() - { - lock (_lockObject) - { - List snapshot = _messages.ToList(); - return snapshot.AsReadOnly(); - } - } - - public IReadOnlyList GetLines() - { - return GetMessages().Select(message => message.ToString()).ToArray(); - } - - private sealed class NullScope : IDisposable - { - public static readonly NullScope Instance = new(); - - private NullScope() - { - } - - public void Dispose() - { - } - } - } -} diff --git a/test/TestBuildingBlocks/FakerExtensions.cs b/test/TestBuildingBlocks/FakerExtensions.cs index 282aa26c6b..cf75591839 100644 --- a/test/TestBuildingBlocks/FakerExtensions.cs +++ b/test/TestBuildingBlocks/FakerExtensions.cs @@ -79,4 +79,34 @@ private static int GetDeterministicHashCode(string source) return hash1 + hash2 * 1566083941; } } + + // The methods below exist so that a non-nullable return type is inferred. + // The Bogus NuGet package is not annotated for nullable reference types. + + public static T GenerateOne(this Faker faker) + where T : class + { + return faker.Generate(); + } + +#pragma warning disable AV1130 // Return type in method signature should be an interface to an unchangeable collection + public static List GenerateList(this Faker faker, int count) + where T : class + { + return faker.Generate(count); + } + + public static HashSet GenerateSet(this Faker faker, int count) + where T : class + { + return faker.Generate(count).ToHashSet(); + } + + public static HashSet GenerateSet(this Faker faker, int count) + where TOut : class + where TIn : class, TOut + { + return faker.Generate(count).Cast().ToHashSet(); + } +#pragma warning restore AV1130 // Return type in method signature should be an interface to an unchangeable collection } diff --git a/test/TestBuildingBlocks/IntegrationTest.cs b/test/TestBuildingBlocks/IntegrationTest.cs index 73ced10d8d..83a375a7db 100644 --- a/test/TestBuildingBlocks/IntegrationTest.cs +++ b/test/TestBuildingBlocks/IntegrationTest.cs @@ -12,14 +12,14 @@ namespace TestBuildingBlocks; /// public abstract class IntegrationTest : IAsyncLifetime { - private static readonly SemaphoreSlim ThrottleSemaphore; + private static readonly SemaphoreSlim ThrottleSemaphore = GetDefaultThrottleSemaphore(); protected abstract JsonSerializerOptions SerializerOptions { get; } - static IntegrationTest() + private static SemaphoreSlim GetDefaultThrottleSemaphore() { int maxConcurrentTestRuns = OperatingSystem.IsWindows() && Environment.GetEnvironmentVariable("CI") != null ? 32 : 64; - ThrottleSemaphore = new SemaphoreSlim(maxConcurrentTestRuns); + return new SemaphoreSlim(maxConcurrentTestRuns); } public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteHeadAsync(string requestUrl, diff --git a/test/TestBuildingBlocks/IntegrationTestContext.cs b/test/TestBuildingBlocks/IntegrationTestContext.cs index f7376741ce..a9abb26a83 100644 --- a/test/TestBuildingBlocks/IntegrationTestContext.cs +++ b/test/TestBuildingBlocks/IntegrationTestContext.cs @@ -86,16 +86,11 @@ private WebApplicationFactory CreateFactory() factory.PostConfigureServices(_postConfigureServices); - // We have placed an appsettings.json in the TestBuildingBlocks project directory and set the content root to there. Note that - // controllers are not discovered in the content root, but are registered manually using IntegrationTestContext.UseController. - WebApplicationFactory factoryWithConfiguredContentRoot = - factory.WithWebHostBuilder(builder => builder.UseSolutionRelativeContentRoot($"test/{nameof(TestBuildingBlocks)}")); - - using IServiceScope scope = factoryWithConfiguredContentRoot.Services.CreateScope(); + using IServiceScope scope = factory.Services.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService(); dbContext.Database.EnsureCreated(); - return factoryWithConfiguredContentRoot; + return factory; } [Conditional("DEBUG")] @@ -166,6 +161,13 @@ public void PostConfigureServices(Action? configureServices) _postConfigureServices = configureServices; } + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + // We have placed an appsettings.json in the TestBuildingBlocks project directory and set the content root to there. Note that + // controllers are not discovered in the content root, but are registered manually using IntegrationTestContext.UseController. + builder.UseSolutionRelativeContentRoot($"test/{nameof(TestBuildingBlocks)}"); + } + protected override IHostBuilder CreateHostBuilder() { // @formatter:wrap_chained_method_calls chop_always diff --git a/test/TestBuildingBlocks/JsonApiStringConverter.cs b/test/TestBuildingBlocks/JsonApiStringConverter.cs index faf26ef988..c20f115cf5 100644 --- a/test/TestBuildingBlocks/JsonApiStringConverter.cs +++ b/test/TestBuildingBlocks/JsonApiStringConverter.cs @@ -16,7 +16,7 @@ public static string ExtractErrorId(string responseBody) } catch (Exception exception) { - throw new Exception($"Failed to extract Error ID from response body '{responseBody}'.", exception); + throw new JsonException($"Failed to extract Error ID from response body '{responseBody}'.", exception); } } } diff --git a/test/TestBuildingBlocks/FakeLogMessage.cs b/test/TestBuildingBlocks/LogMessage.cs similarity index 69% rename from test/TestBuildingBlocks/FakeLogMessage.cs rename to test/TestBuildingBlocks/LogMessage.cs index cd6cc2bdaf..74d5552250 100644 --- a/test/TestBuildingBlocks/FakeLogMessage.cs +++ b/test/TestBuildingBlocks/LogMessage.cs @@ -4,9 +4,10 @@ namespace TestBuildingBlocks; [PublicAPI] -public sealed class FakeLogMessage(LogLevel logLevel, string text) +public sealed class LogMessage(LogLevel logLevel, string categoryName, string text) { public LogLevel LogLevel { get; } = logLevel; + public string CategoryName { get; } = categoryName; public string Text { get; } = text; public override string ToString() diff --git a/test/TestBuildingBlocks/ObjectAssertionsExtensions.cs b/test/TestBuildingBlocks/ObjectAssertionsExtensions.cs index ee2be771e1..47e08b69f1 100644 --- a/test/TestBuildingBlocks/ObjectAssertionsExtensions.cs +++ b/test/TestBuildingBlocks/ObjectAssertionsExtensions.cs @@ -60,10 +60,12 @@ public static void BeJson(this StringAssertions source, string expected, string private static string ToJsonString(JsonDocument document) { using var stream = new MemoryStream(); - var writer = new Utf8JsonWriter(stream, JsonWriterOptions); - document.WriteTo(writer); - writer.Flush(); + using (var writer = new Utf8JsonWriter(stream, JsonWriterOptions)) + { + document.WriteTo(writer); + } + return Encoding.UTF8.GetString(stream.ToArray()); } diff --git a/test/TestBuildingBlocks/TestControllerProvider.cs b/test/TestBuildingBlocks/TestControllerProvider.cs index 664fe34be1..4f183e50c1 100644 --- a/test/TestBuildingBlocks/TestControllerProvider.cs +++ b/test/TestBuildingBlocks/TestControllerProvider.cs @@ -5,9 +5,9 @@ namespace TestBuildingBlocks; internal sealed class TestControllerProvider : ControllerFeatureProvider { - private readonly ISet _allowedControllerTypes = new HashSet(); + private readonly HashSet _allowedControllerTypes = []; - internal ISet ControllerAssemblies { get; } = new HashSet(); + internal HashSet ControllerAssemblies { get; } = []; public void AddController(Type controller) { diff --git a/test/TestBuildingBlocks/XUnitLoggerProvider.cs b/test/TestBuildingBlocks/XUnitLoggerProvider.cs index 6b5e7f93ec..e264a9bf4a 100644 --- a/test/TestBuildingBlocks/XUnitLoggerProvider.cs +++ b/test/TestBuildingBlocks/XUnitLoggerProvider.cs @@ -24,7 +24,7 @@ public XUnitLoggerProvider(ITestOutputHelper testOutputHelper, string? categoryP public ILogger CreateLogger(string categoryName) { - ArgumentGuard.NotNull(categoryName); + ArgumentGuard.NotNullNorEmpty(categoryName); if (_categoryPrefixFilter == null || categoryName.StartsWith(_categoryPrefixFilter, StringComparison.Ordinal)) { diff --git a/test/UnitTests/Graph/TypeLocatorTests.cs b/test/UnitTests/Graph/TypeLocatorTests.cs index 7f5ed820d8..19699b69f4 100644 --- a/test/UnitTests/Graph/TypeLocatorTests.cs +++ b/test/UnitTests/Graph/TypeLocatorTests.cs @@ -27,24 +27,6 @@ public void GetContainerRegistrationFromAssembly_Gets_Implementation() result.Value.serviceInterface.Should().Be(typeof(IGenericInterface)); } - [Fact] - public void GetDerivedTypesForUnboundType_Gets_Implementation() - { - // Arrange - Assembly assembly = GetType().Assembly; - Type unboundType = typeof(BaseType<>); - Type typeArgument = typeof(int); - - var typeLocator = new TypeLocator(); - - // Act - IReadOnlyCollection results = typeLocator.GetDerivedTypesForUnboundType(assembly, unboundType, typeArgument); - - // Assert - results.ShouldHaveCount(1); - results.ElementAt(0).Should().Be(typeof(DerivedType)); - } - [Fact] public void GetIdType_Correctly_Identifies_JsonApiResource() { diff --git a/test/UnitTests/Models/ResourceConstructionExpressionTests.cs b/test/UnitTests/Models/ResourceConstructionExpressionTests.cs index 277af5f013..bfa4e97e32 100644 --- a/test/UnitTests/Models/ResourceConstructionExpressionTests.cs +++ b/test/UnitTests/Models/ResourceConstructionExpressionTests.cs @@ -15,7 +15,8 @@ public sealed class ResourceConstructionExpressionTests public void When_resource_has_default_constructor_it_must_succeed() { // Arrange - var factory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var factory = new ResourceFactory(serviceProvider); // Act NewExpression newExpression = factory.CreateNewExpression(typeof(ResourceWithoutConstructor)); @@ -31,7 +32,8 @@ public void When_resource_has_default_constructor_it_must_succeed() public void When_resource_has_constructor_with_string_parameter_it_must_fail() { // Arrange - var factory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var factory = new ResourceFactory(serviceProvider); // Act Action action = () => factory.CreateNewExpression(typeof(ResourceWithStringConstructor));