Skip to content

Commit f0f4aa2

Browse files
committed
Added tests for pascal and camelcase and introduced fixes to make them work.
1 parent 9963cdf commit f0f4aa2

34 files changed

+4369
-167
lines changed

Diff for: src/JsonApiDotNetCore.OpenApi.Client/ApiException.cs

+2-4
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ public ApiException(string message, int statusCode, string response, IReadOnlyDi
3131
public override string ToString()
3232
{
3333
return $"HTTP Response: \n\n{Response}\n\n{base.ToString()}";
34-
}
35-
}
34+
}}
3635

3736
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
3837
internal sealed class ApiException<TResult> : ApiException
@@ -44,6 +43,5 @@ public ApiException(string message, int statusCode, string response, IReadOnlyDi
4443
: base(message, statusCode, response, headers, innerException)
4544
{
4645
Result = result;
47-
}
48-
}
46+
}}
4947
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Documents/NullableResourceIdentifierResponseDocument.cs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
66
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
77
using JsonApiDotNetCore.Resources;
8-
using JsonApiDotNetCore.Serialization.Objects;
98

109
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents
1110
{

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Documents/NullableSecondaryResourceResponseDocument.cs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
66
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
77
using JsonApiDotNetCore.Resources;
8-
using JsonApiDotNetCore.Serialization.Objects;
98

109
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents
1110
{

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Documents/PrimaryResourceResponseDocument.cs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
66
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
77
using JsonApiDotNetCore.Resources;
8-
using JsonApiDotNetCore.Serialization.Objects;
98

109
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents
1110
{

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Documents/ResourceCollectionResponseDocument.cs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
66
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
77
using JsonApiDotNetCore.Resources;
8-
using JsonApiDotNetCore.Serialization.Objects;
98

109
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents
1110
{

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Documents/ResourceIdentifierCollectionResponseDocument.cs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
66
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
77
using JsonApiDotNetCore.Resources;
8-
using JsonApiDotNetCore.Serialization.Objects;
98

109
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents
1110
{

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Documents/ResourceIdentifierResponseDocument.cs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
66
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
77
using JsonApiDotNetCore.Resources;
8-
using JsonApiDotNetCore.Serialization.Objects;
98

109
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents
1110
{

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Documents/SecondaryResourceResponseDocument.cs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
66
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
77
using JsonApiDotNetCore.Resources;
8-
using JsonApiDotNetCore.Serialization.Objects;
98

109
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents
1110
{

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiOperationIdSelector.cs

+7-9
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,13 @@ internal sealed class JsonApiOperationIdSelector
3939

4040
private readonly IControllerResourceMapping _controllerResourceMapping;
4141
private readonly JsonNamingPolicy? _namingPolicy;
42-
private readonly ResourceNameFormatter _formatter;
4342

4443
public JsonApiOperationIdSelector(IControllerResourceMapping controllerResourceMapping, JsonNamingPolicy? namingPolicy)
4544
{
4645
ArgumentGuard.NotNull(controllerResourceMapping, nameof(controllerResourceMapping));
4746

4847
_controllerResourceMapping = controllerResourceMapping;
4948
_namingPolicy = namingPolicy;
50-
_formatter = new ResourceNameFormatter(namingPolicy);
5149
}
5250

5351
public string GetOperationId(ApiDescription endpoint)
@@ -64,7 +62,7 @@ public string GetOperationId(ApiDescription endpoint)
6462

6563
string template = GetTemplate(primaryResourceType.ClrType, endpoint);
6664

67-
return ApplyTemplate(template, primaryResourceType.ClrType, endpoint);
65+
return ApplyTemplate(template, primaryResourceType, endpoint);
6866
}
6967

7068
private static string GetTemplate(Type resourceClrType, ApiDescription endpoint)
@@ -111,24 +109,24 @@ private static Type GetDocumentType(Type primaryResourceClrType, ApiDescription
111109
return type.IsConstructedGenericType ? type.GetGenericTypeDefinition() : null;
112110
}
113111

114-
private string ApplyTemplate(string operationIdTemplate, Type resourceClrType, ApiDescription endpoint)
112+
private string ApplyTemplate(string operationIdTemplate, ResourceType resourceType, ApiDescription endpoint)
115113
{
116114
string method = endpoint.HttpMethod!.ToLowerInvariant();
117-
string primaryResourceName = _formatter.FormatResourceName(resourceClrType).Singularize();
118115
string relationshipName = operationIdTemplate.Contains("[RelationshipName]") ? endpoint.RelativePath.Split("/").Last() : string.Empty;
119116

120117
// @formatter:wrap_chained_method_calls chop_always
121118
// @formatter:keep_existing_linebreaks true
122119

123-
string pascalCaseId = operationIdTemplate
120+
string pascalCaseOperationId = operationIdTemplate
124121
.Replace("[Method]", method)
125-
.Replace("[PrimaryResourceName]", primaryResourceName)
126-
.Replace("[RelationshipName]", relationshipName);
122+
.Replace("[PrimaryResourceName]", resourceType.PublicName.Singularize())
123+
.Replace("[RelationshipName]", relationshipName)
124+
.Pascalize();
127125

128126
// @formatter:keep_existing_linebreaks restore
129127
// @formatter:wrap_chained_method_calls restore
130128

131-
return _namingPolicy != null ? _namingPolicy.ConvertName(pascalCaseId) : pascalCaseId;
129+
return _namingPolicy != null ? _namingPolicy.ConvertName(pascalCaseOperationId) : pascalCaseOperationId;
132130
}
133131
}
134132
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiSchemaIdSelector.cs

+8-10
Original file line numberDiff line numberDiff line change
@@ -65,23 +65,21 @@ public string GetSchemaId(Type type)
6565

6666
if (type.IsConstructedGenericType && OpenTypeToSchemaTemplateMap.ContainsKey(type.GetGenericTypeDefinition()))
6767
{
68-
string pascalCaseSchemaIdTemplate = OpenTypeToSchemaTemplateMap[type.GetGenericTypeDefinition()];
68+
Type openType = type.GetGenericTypeDefinition();
6969
Type resourceClrType = type.GetGenericArguments().First();
70+
resourceType = _resourceGraph.FindResourceType(resourceClrType);
7071

71-
// @formatter:wrap_chained_method_calls chop_always
72-
// @formatter:keep_existing_linebreaks true
72+
if (resourceType == null)
73+
{
74+
throw new UnreachableCodeException();
75+
}
7376

74-
string pascalCaseSchemaId = pascalCaseSchemaIdTemplate
75-
.Replace("[ResourceName]", resourceClrType.Name)
76-
.Replace(" ", "");
77-
78-
// @formatter:keep_existing_linebreaks restore
79-
// @formatter:wrap_chained_method_calls restore
77+
string pascalCaseSchemaId = OpenTypeToSchemaTemplateMap[openType].Replace("[ResourceName]", resourceType.PublicName.Singularize()).Pascalize();
8078

8179
return _namingPolicy != null ? _namingPolicy.ConvertName(pascalCaseSchemaId) : pascalCaseSchemaId;
8280
}
8381

84-
// Used for a fixed set of types, such as jsonapi-object, links-in-many-resource-document etc.
82+
// Used for a fixed set of types, such as JsonApiObject, LinksInResourceCollectionDocument etc.
8583
return _namingPolicy != null ? _namingPolicy.ConvertName(type.Name) : type.Name;
8684
}
8785
}

Diff for: src/JsonApiDotNetCore.OpenApi/StringExtensions.cs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System.Text.RegularExpressions;
2+
3+
namespace JsonApiDotNetCore.OpenApi
4+
{
5+
internal static class StringExtensions
6+
{
7+
public static string Pascalize(this string source)
8+
{
9+
return Regex.Replace(source, "(?:^|-|_| +)(.)", match => match.Groups[1].Value.ToUpper());
10+
}
11+
}
12+
}

Diff for: src/JsonApiDotNetCore.OpenApi/SwaggerComponents/NullableReferenceSchemaGenerator.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ internal sealed class NullableReferenceSchemaGenerator
99
{
1010
private const string PascalCaseNullableSchemaReferenceId = "NullValue";
1111

12-
private static readonly NullableReferenceSchemaStrategy NullableReferenceStrategy =
12+
private readonly NullableReferenceSchemaStrategy _nullableReferenceStrategy =
1313
Enum.Parse<NullableReferenceSchemaStrategy>(NullableReferenceSchemaStrategy.Implicit.ToString());
1414

15-
private static OpenApiSchema? _referenceSchemaForExplicitNullValue;
1615
private readonly string _nullableSchemaReferenceId;
1716
private readonly ISchemaRepositoryAccessor _schemaRepositoryAccessor;
1817

18+
private OpenApiSchema? _referenceSchemaForExplicitNullValue;
19+
1920
public NullableReferenceSchemaGenerator(ISchemaRepositoryAccessor schemaRepositoryAccessor, JsonNamingPolicy? namingPolicy)
2021
{
2122
ArgumentGuard.NotNull(schemaRepositoryAccessor, nameof(schemaRepositoryAccessor));
@@ -35,7 +36,7 @@ public OpenApiSchema GenerateSchema(OpenApiSchema referenceSchema)
3536
OneOf = new List<OpenApiSchema>
3637
{
3738
referenceSchema,
38-
NullableReferenceStrategy == NullableReferenceSchemaStrategy.Explicit ? GetExplicitNullSchema() : GetImplicitNullSchema()
39+
_nullableReferenceStrategy == NullableReferenceSchemaStrategy.Explicit ? GetExplicitNullSchema() : GetImplicitNullSchema()
3940
}
4041
};
4142
}

Diff for: src/JsonApiDotNetCore.OpenApi/SwaggerComponents/ResourceObjectSchemaGenerator.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ public ResourceObjectSchemaGenerator(SchemaGenerator defaultSchemaGenerator, IRe
2929
_resourceGraph = resourceGraph;
3030
_schemaRepositoryAccessor = schemaRepositoryAccessor;
3131

32-
_resourceTypeSchemaGenerator = new ResourceTypeSchemaGenerator(schemaRepositoryAccessor, resourceGraph);
32+
_resourceTypeSchemaGenerator =
33+
new ResourceTypeSchemaGenerator(schemaRepositoryAccessor, resourceGraph, options.SerializerOptions.PropertyNamingPolicy);
34+
3335
_allowClientGeneratedIds = options.AllowClientGeneratedIds;
3436

3537
_resourceFieldObjectSchemaBuilderFactory = resourceTypeInfo => new ResourceFieldObjectSchemaBuilder(resourceTypeInfo, schemaRepositoryAccessor,

Diff for: src/JsonApiDotNetCore.OpenApi/SwaggerComponents/ResourceTypeSchemaGenerator.cs

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Text.Json;
4+
using Humanizer;
35
using JsonApiDotNetCore.Configuration;
46
using Microsoft.OpenApi.Any;
57
using Microsoft.OpenApi.Models;
@@ -8,17 +10,20 @@ namespace JsonApiDotNetCore.OpenApi.SwaggerComponents
810
{
911
internal sealed class ResourceTypeSchemaGenerator
1012
{
13+
private const string ResourceTypeSchemaIdTemplate = "[ResourceName] Resource Type";
1114
private readonly ISchemaRepositoryAccessor _schemaRepositoryAccessor;
1215
private readonly IResourceGraph _resourceGraph;
16+
private readonly JsonNamingPolicy? _namingPolicy;
1317
private readonly Dictionary<Type, OpenApiSchema> _resourceClrTypeSchemaCache = new();
1418

15-
public ResourceTypeSchemaGenerator(ISchemaRepositoryAccessor schemaRepositoryAccessor, IResourceGraph resourceGraph)
19+
public ResourceTypeSchemaGenerator(ISchemaRepositoryAccessor schemaRepositoryAccessor, IResourceGraph resourceGraph, JsonNamingPolicy? namingPolicy)
1620
{
1721
ArgumentGuard.NotNull(schemaRepositoryAccessor, nameof(schemaRepositoryAccessor));
1822
ArgumentGuard.NotNull(resourceGraph, nameof(resourceGraph));
1923

2024
_schemaRepositoryAccessor = schemaRepositoryAccessor;
2125
_resourceGraph = resourceGraph;
26+
_namingPolicy = namingPolicy;
2227
}
2328

2429
public OpenApiSchema Get(Type resourceClrType)
@@ -41,11 +46,13 @@ public OpenApiSchema Get(Type resourceClrType)
4146
}
4247
};
4348

49+
string schemaId = GetSchemaId(resourceType);
50+
4451
referenceSchema = new OpenApiSchema
4552
{
4653
Reference = new OpenApiReference
4754
{
48-
Id = $"{resourceType.PublicName}-resource-type",
55+
Id = schemaId,
4956
Type = ReferenceType.Schema
5057
}
5158
};
@@ -55,5 +62,12 @@ public OpenApiSchema Get(Type resourceClrType)
5562

5663
return referenceSchema;
5764
}
65+
66+
private string GetSchemaId(ResourceType resourceType)
67+
{
68+
string pascalCaseSchemaId = ResourceTypeSchemaIdTemplate.Replace("[ResourceName]", resourceType.PublicName.Singularize()).Pascalize();
69+
70+
return _namingPolicy != null ? _namingPolicy.ConvertName(pascalCaseSchemaId) : pascalCaseSchemaId;
71+
}
5872
}
5973
}

Diff for: src/JsonApiDotNetCore/Serialization/Objects/JsonapiObject.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace JsonApiDotNetCore.Serialization.Objects
88
/// See https://jsonapi.org/format/1.1/#document-jsonapi-object.
99
/// </summary>
1010
[PublicAPI]
11-
public sealed class JsonapiObject
11+
public sealed class JsonApiObject
1212
{
1313
[JsonPropertyName("version")]
1414
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]

Diff for: test/OpenApiClientTests/LegacyClient/ClientAttributeRegistrationLifeTimeTests.cs

+13-13
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public async Task Disposed_attribute_registration_for_document_does_not_affect_r
2323
Data = new AirplaneDataInPatchRequest
2424
{
2525
Id = airplaneId,
26-
Type = AirplanesResourceType.Airplanes,
26+
Type = AirplaneResourceType.Airplanes,
2727
Attributes = new AirplaneAttributesInPatchRequest()
2828
}
2929
};
@@ -65,7 +65,7 @@ public async Task Attribute_registration_can_be_used_for_multiple_requests()
6565
Data = new AirplaneDataInPatchRequest
6666
{
6767
Id = airplaneId,
68-
Type = AirplanesResourceType.Airplanes,
68+
Type = AirplaneResourceType.Airplanes,
6969
Attributes = new AirplaneAttributesInPatchRequest
7070
{
7171
AirtimeInHours = 100
@@ -112,7 +112,7 @@ public async Task Request_is_unaffected_by_attribute_registration_for_different_
112112
Data = new AirplaneDataInPatchRequest
113113
{
114114
Id = airplaneId1,
115-
Type = AirplanesResourceType.Airplanes,
115+
Type = AirplaneResourceType.Airplanes,
116116
Attributes = new AirplaneAttributesInPatchRequest()
117117
}
118118
};
@@ -124,7 +124,7 @@ public async Task Request_is_unaffected_by_attribute_registration_for_different_
124124
Data = new AirplaneDataInPatchRequest
125125
{
126126
Id = airplaneId2,
127-
Type = AirplanesResourceType.Airplanes,
127+
Type = AirplaneResourceType.Airplanes,
128128
Attributes = new AirplaneAttributesInPatchRequest()
129129
}
130130
};
@@ -167,7 +167,7 @@ public async Task Attribute_values_can_be_changed_after_attribute_registration()
167167
Data = new AirplaneDataInPatchRequest
168168
{
169169
Id = airplaneId,
170-
Type = AirplanesResourceType.Airplanes,
170+
Type = AirplaneResourceType.Airplanes,
171171
Attributes = new AirplaneAttributesInPatchRequest
172172
{
173173
IsInMaintenance = true
@@ -210,7 +210,7 @@ public async Task Attribute_registration_is_unaffected_by_successive_attribute_r
210210
Data = new AirplaneDataInPatchRequest
211211
{
212212
Id = airplaneId1,
213-
Type = AirplanesResourceType.Airplanes,
213+
Type = AirplaneResourceType.Airplanes,
214214
Attributes = new AirplaneAttributesInPatchRequest()
215215
}
216216
};
@@ -219,7 +219,7 @@ public async Task Attribute_registration_is_unaffected_by_successive_attribute_r
219219
{
220220
Data = new AirplaneDataInPostRequest
221221
{
222-
Type = AirplanesResourceType.Airplanes,
222+
Type = AirplaneResourceType.Airplanes,
223223
Attributes = new AirplaneAttributesInPostRequest()
224224
}
225225
};
@@ -261,7 +261,7 @@ public async Task Attribute_registration_is_unaffected_by_preceding_disposed_att
261261
Data = new AirplaneDataInPatchRequest
262262
{
263263
Id = airplaneId1,
264-
Type = AirplanesResourceType.Airplanes,
264+
Type = AirplaneResourceType.Airplanes,
265265
Attributes = new AirplaneAttributesInPatchRequest()
266266
}
267267
};
@@ -279,7 +279,7 @@ public async Task Attribute_registration_is_unaffected_by_preceding_disposed_att
279279
Data = new AirplaneDataInPatchRequest
280280
{
281281
Id = airplaneId2,
282-
Type = AirplanesResourceType.Airplanes,
282+
Type = AirplaneResourceType.Airplanes,
283283
Attributes = new AirplaneAttributesInPatchRequest
284284
{
285285
ManufacturedInCity = "Everett"
@@ -320,7 +320,7 @@ public async Task Attribute_registration_is_unaffected_by_preceding_disposed_att
320320
{
321321
Data = new AirplaneDataInPostRequest
322322
{
323-
Type = AirplanesResourceType.Airplanes,
323+
Type = AirplaneResourceType.Airplanes,
324324
Attributes = new AirplaneAttributesInPostRequest()
325325
}
326326
};
@@ -338,7 +338,7 @@ public async Task Attribute_registration_is_unaffected_by_preceding_disposed_att
338338
Data = new AirplaneDataInPatchRequest
339339
{
340340
Id = airplaneId,
341-
Type = AirplanesResourceType.Airplanes,
341+
Type = AirplaneResourceType.Airplanes,
342342
Attributes = new AirplaneAttributesInPatchRequest
343343
{
344344
ManufacturedInCity = "Everett"
@@ -382,7 +382,7 @@ public async Task Attribute_registration_is_unaffected_by_preceding_attribute_re
382382
Data = new AirplaneDataInPatchRequest
383383
{
384384
Id = airplaneId1,
385-
Type = AirplanesResourceType.Airplanes,
385+
Type = AirplaneResourceType.Airplanes,
386386
Attributes = new AirplaneAttributesInPatchRequest()
387387
}
388388
};
@@ -394,7 +394,7 @@ public async Task Attribute_registration_is_unaffected_by_preceding_attribute_re
394394
Data = new AirplaneDataInPatchRequest
395395
{
396396
Id = airplaneId2,
397-
Type = AirplanesResourceType.Airplanes,
397+
Type = AirplaneResourceType.Airplanes,
398398
Attributes = new AirplaneAttributesInPatchRequest()
399399
}
400400
};

0 commit comments

Comments
 (0)