Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ internal static partial class OpenApiV3Deserializer
"schema",
(o, n, t) => o.Schema = LoadSchema(n, t)
},
{
"content", (o, n, t) =>
{
o.Content = n.CreateMap(LoadMediaType, t);
}
},
{
"examples",
(o, n, t) => o.Examples = n.CreateMap(LoadExample, t)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ internal static partial class OpenApiV31Deserializer
o.Schema = LoadSchema(n, t);
}
},
{
"content", (o, n, t) =>
{
o.Content = n.CreateMap(LoadMediaType, t);
}
},
{
"examples", (o, n, t) =>
{
Expand Down
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
Loading