Visitar URL original
fix: missing deserialization for header content property in 3.1 and 3.0 by baywet · Pull Request #2526 · microsoft/OpenAPI.NET · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
test: adds deserialization tests for OpenAPI header
Signed-off-by: Vincent Biret <vibiret@microsoft.com>
  • Loading branch information
baywet committed Oct 3, 2025
commit af85cc96e629d53615e98995d54e46b352116f85
136 changes: 136 additions & 0 deletions test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiHeaderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.OpenApi.Reader;
using Xunit;

namespace Microsoft.OpenApi.Readers.Tests.V31Tests
{
[Collection("DefaultSettings")]
public class OpenApiHeaderTests
{
private const string SampleFolderPath = "V31Tests/Samples/OpenApiHeader/";

[Fact]
public async Task ParseBasicHeaderShouldSucceed()
{
// Arrange
using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "basicHeader.yaml"));

// Act
var header = await OpenApiModelFactory.LoadAsync<OpenApiHeader>(stream, OpenApiSpecVersion.OpenApi3_1, new(), settings: SettingsFixture.ReaderSettings);

// Assert
Assert.Equivalent(
new OpenApiHeader
{
Description = "The number of allowed requests in the current period",
Schema = new OpenApiSchema()
{
Type = JsonSchemaType.Integer
}
}, header);
}

[Fact]
public async Task ParseHeaderWithContentShouldSucceed()
{
// Arrange
using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "headerWithContent.yaml"));

// Act
var header = await OpenApiModelFactory.LoadAsync<OpenApiHeader>(stream, OpenApiSpecVersion.OpenApi3_1, new(), settings: SettingsFixture.ReaderSettings);

// Assert
Assert.Equivalent(
new OpenApiHeader
{
Description = "A complex header with content",
Content = new Dictionary<string, OpenApiMediaType>()
{
["application/json"] = new()
{
Schema = new OpenApiSchema()
{
Type = JsonSchemaType.Object,
Properties = new Dictionary<string, IOpenApiSchema>()
{
["timestamp"] = new OpenApiSchema()
{
Type = JsonSchemaType.String,
Format = "date-time"
},
["value"] = new OpenApiSchema()
{
Type = JsonSchemaType.Integer
}
}
}
}
}
}, header);
}

[Fact]
public async Task ParseHeaderWithMultipleContentTypesShouldSucceed()
{
// Arrange
using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "headerWithMultipleContentTypes.yaml"));

// Act
var header = await OpenApiModelFactory.LoadAsync<OpenApiHeader>(stream, OpenApiSpecVersion.OpenApi3_1, new(), settings: SettingsFixture.ReaderSettings);

// Assert
Assert.Equivalent(
new OpenApiHeader
{
Description = "A header that accepts multiple content types",
Content = new Dictionary<string, OpenApiMediaType>()
{
["application/json"] = new()
{
Schema = new OpenApiSchema()
{
Type = JsonSchemaType.Object,
Properties = new Dictionary<string, IOpenApiSchema>()
{
["data"] = new OpenApiSchema()
{
Type = JsonSchemaType.String
}
}
}
},
["text/plain"] = new()
{
Schema = new OpenApiSchema()
{
Type = JsonSchemaType.String
}
}
}
}, header);
}

[Fact]
public async Task ParseHeaderWithStyleAndContentShouldPreferContent()
{
// Arrange
using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "headerWithStyleAndContent.yaml"));

// Act
var header = await OpenApiModelFactory.LoadAsync<OpenApiHeader>(stream, OpenApiSpecVersion.OpenApi3_1, new(), settings: SettingsFixture.ReaderSettings);

// Assert
// Both content and style can be present, content takes precedence for serialization behavior
Assert.NotNull(header.Content);
Assert.Single(header.Content);
Assert.True(header.Content.ContainsKey("application/json"));
Assert.Equal(ParameterStyle.Simple, header.Style); // Style can still be present
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
description: "The number of allowed requests in the current period"
schema:
type: integer
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
description: "A complex header with content"
content:
application/json:
schema:
type: object
properties:
timestamp:
type: string
format: date-time
value:
type: integer
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
description: "A header that accepts multiple content types"
content:
application/json:
schema:
type: object
properties:
data:
type: string
text/plain:
schema:
type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
description: "A header with both style and content (content should take precedence)"
style: simple
schema:
type: string
content:
application/json:
schema:
type: object
properties:
value:
type: string
136 changes: 136 additions & 0 deletions test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiHeaderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.OpenApi.Reader;
using Xunit;

namespace Microsoft.OpenApi.Readers.Tests.V3Tests
{
[Collection("DefaultSettings")]
public class OpenApiHeaderTests
{
private const string SampleFolderPath = "V3Tests/Samples/OpenApiHeader/";

[Fact]
public async Task ParseBasicHeaderShouldSucceed()
{
// Arrange
using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "basicHeader.yaml"));

// Act
var header = await OpenApiModelFactory.LoadAsync<OpenApiHeader>(stream, OpenApiSpecVersion.OpenApi3_0, new(), settings: SettingsFixture.ReaderSettings);

// Assert
Assert.Equivalent(
new OpenApiHeader
{
Description = "The number of allowed requests in the current period",
Schema = new OpenApiSchema()
{
Type = JsonSchemaType.Integer
}
}, header);
}

[Fact]
public async Task ParseHeaderWithContentShouldSucceed()
{
// Arrange
using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "headerWithContent.yaml"));

// Act
var header = await OpenApiModelFactory.LoadAsync<OpenApiHeader>(stream, OpenApiSpecVersion.OpenApi3_0, new(), settings: SettingsFixture.ReaderSettings);

// Assert
Assert.Equivalent(
new OpenApiHeader
{
Description = "A complex header with content",
Content = new Dictionary<string, OpenApiMediaType>()
{
["application/json"] = new()
{
Schema = new OpenApiSchema()
{
Type = JsonSchemaType.Object,
Properties = new Dictionary<string, IOpenApiSchema>()
{
["timestamp"] = new OpenApiSchema()
{
Type = JsonSchemaType.String,
Format = "date-time"
},
["value"] = new OpenApiSchema()
{
Type = JsonSchemaType.Integer
}
}
}
}
}
}, header);
}

[Fact]
public async Task ParseHeaderWithMultipleContentTypesShouldSucceed()
{
// Arrange
using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "headerWithMultipleContentTypes.yaml"));

// Act
var header = await OpenApiModelFactory.LoadAsync<OpenApiHeader>(stream, OpenApiSpecVersion.OpenApi3_0, new(), settings: SettingsFixture.ReaderSettings);

// Assert
Assert.Equivalent(
new OpenApiHeader
{
Description = "A header that accepts multiple content types",
Content = new Dictionary<string, OpenApiMediaType>()
{
["application/json"] = new()
{
Schema = new OpenApiSchema()
{
Type = JsonSchemaType.Object,
Properties = new Dictionary<string, IOpenApiSchema>()
{
["data"] = new OpenApiSchema()
{
Type = JsonSchemaType.String
}
}
}
},
["text/plain"] = new()
{
Schema = new OpenApiSchema()
{
Type = JsonSchemaType.String
}
}
}
}, header);
}

[Fact]
public async Task ParseHeaderWithStyleAndContentShouldPreferContent()
{
// Arrange
using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "headerWithStyleAndContent.yaml"));

// Act
var header = await OpenApiModelFactory.LoadAsync<OpenApiHeader>(stream, OpenApiSpecVersion.OpenApi3_0, new(), settings: SettingsFixture.ReaderSettings);

// Assert
// Both content and style can be present, content takes precedence for serialization behavior
Assert.NotNull(header.Content);
Assert.Single(header.Content);
Assert.True(header.Content.ContainsKey("application/json"));
Assert.Equal(ParameterStyle.Simple, header.Style); // Style can still be present
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
description: "The number of allowed requests in the current period"
schema:
type: integer
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
description: "A complex header with content"
content:
application/json:
schema:
type: object
properties:
timestamp:
type: string
format: date-time
value:
type: integer
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
description: "A header that accepts multiple content types"
content:
application/json:
schema:
type: object
properties:
data:
type: string
text/plain:
schema:
type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
description: "A header with both style and content (content should take precedence)"
style: simple
schema:
type: string
content:
application/json:
schema:
type: object
properties:
value:
type: string