Skip to content

Commit 7313d3e

Browse files
committed
Added union for content
1 parent 8a95cec commit 7313d3e

6 files changed

Lines changed: 70 additions & 59 deletions

File tree

src/TestableHttpClient/Request.cs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@ internal readonly struct Headers
1212
public Headers(HeaderList value) => Value = value;
1313
}
1414

15+
internal record struct AnyContent;
16+
internal record struct Pattern(string pattern);
17+
internal readonly struct Content
18+
{
19+
public readonly object? Value { get; }
20+
public Content() => Value = new AnyContent();
21+
public Content(AnyContent value) => Value = value;
22+
public Content(Pattern value) => Value = value;
23+
}
24+
1525
internal sealed record Request : IEquatable<HttpRequestMessage>
1626
{
1727
public Request(UriPatternMatchingOptions uriPatternMatchingOptions)
@@ -27,7 +37,7 @@ public Request(UriPatternMatchingOptions uriPatternMatchingOptions)
2737

2838
public Headers Headers { get; init; } = new();
2939

30-
public string? Content { get; init; }
40+
public Content Content { get; init; } = new();
3141

3242
public Request AddHeader(string headerName) => AddHeader(headerName, Value.Any());
3343

@@ -85,31 +95,27 @@ public bool Equals(HttpRequestMessage? other)
8595
}
8696
}
8797

88-
if (Content is not null)
98+
string? stringContent = null;
99+
if (other.Content is not null)
89100
{
90-
if (other.Content is null)
91-
{
92-
return false;
93-
}
94-
95-
var stringContent = other.Content.ReadAsStringAsync()
101+
stringContent = other.Content.ReadAsStringAsync()
96102
.ConfigureAwait(false)
97103
.GetAwaiter()
98104
.GetResult();
105+
}
99106

100-
var contentMatches = Content switch
101-
{
102-
"" => stringContent == Content,
103-
"*" => true,
104-
_ => StringMatcher.Matches(stringContent, Content),
105-
};
107+
bool contentMatches = Content.Value switch
108+
{
109+
AnyContent => true,
110+
Pattern value when stringContent is null => false,
111+
Pattern value => StringMatcher.Matches(stringContent, value.pattern, false),
112+
_ => throw new UnreachableException()
113+
};
106114

107-
if (!contentMatches)
108-
{
109-
return false;
110-
}
115+
if (!contentMatches)
116+
{
117+
return false;
111118
}
112-
113119
return true;
114120
}
115121
}

src/TestableHttpClient/RequestBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public RequestBuilder WithContent(string pattern)
8585
{
8686
Guard.ThrowIfNull(pattern);
8787

88-
request = request with { Content = pattern };
88+
request = request with { Content = new(new Pattern(pattern)) };
8989
return this;
9090
}
9191

src/TestableHttpClient/Utils/MessageBuilder.cs

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,27 +39,12 @@ internal static string BuildMessage(int? expectedCount, int actualCount, Request
3939
_ => throw new UnreachableException()
4040
};
4141

42-
string content = string.Empty;
43-
44-
if (!string.IsNullOrEmpty(expectedRequest.Content))
42+
string content = expectedRequest.Content.Value switch
4543
{
46-
StringBuilder contentBuilder = new();
47-
if (string.IsNullOrEmpty(headers))
48-
{
49-
contentBuilder.AppendLine(" with content:");
50-
}
51-
else
52-
{
53-
contentBuilder.AppendLine("and content:");
54-
}
55-
56-
string[] splitcontent = expectedRequest.Content!.Split(['\n']);
57-
foreach (var line in splitcontent)
58-
{
59-
contentBuilder.AppendLine(CultureInfo.InvariantCulture, $" {line.Trim('\r')}");
60-
}
61-
content = contentBuilder.ToString();
62-
}
44+
AnyContent => "",
45+
Pattern pattern => BuildContent(pattern, string.IsNullOrEmpty(headers)),
46+
_ => throw new UnreachableException()
47+
};
6348

6449
var actualMessage = actualCount switch
6550
{
@@ -164,4 +149,24 @@ private static string BuildValue(Value value)
164149
_ => throw new UnreachableException()
165150
};
166151
}
152+
153+
private static string BuildContent(Pattern value, bool hasHeaders)
154+
{
155+
string[] content = value.pattern.Split(['\n']);
156+
157+
StringBuilder contentBuilder = new();
158+
if (hasHeaders)
159+
{
160+
contentBuilder.AppendLine(" with content:");
161+
}
162+
else
163+
{
164+
contentBuilder.AppendLine("and content:");
165+
}
166+
foreach (var line in content)
167+
{
168+
contentBuilder.AppendLine(CultureInfo.InvariantCulture, $" {line.Trim('\r')}");
169+
}
170+
return contentBuilder.ToString();
171+
}
167172
}

test/TestableHttpClient.Tests/RequestBuilderExtensionsTests.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public void Get_ShouldSetHttpMethodAndRequestUri()
3030
Assert.Equal(UriPatternParser.Parse("https://localhost"), request.RequestUri);
3131
Assert.Null(request.Version);
3232
Assert.Equal(new AnyHeader(), request.Headers.Value);
33-
Assert.Null(request.Content);
33+
Assert.Equal(new AnyContent(), request.Content.Value);
3434
}
3535

3636
[Fact]
@@ -61,7 +61,7 @@ public void Post_ShouldBuildCorrectRequest()
6161
Assert.Equal(UriPatternParser.Parse("https://localhost"), request.RequestUri);
6262
Assert.Null(request.Version);
6363
Assert.Equal(new AnyHeader(), request.Headers.Value);
64-
Assert.Equal("{\"hello\":1}", request.Content);
64+
Assert.Equal(new Pattern("{\"hello\":1}"), request.Content.Value);
6565
}
6666

6767
[Fact]
@@ -87,7 +87,7 @@ public void PostAsJson_WithNullContent_ShouldBuildCorrectRequest()
8787
Assert.Equal(UriPatternParser.Parse("https://localhost"), request.RequestUri);
8888
Assert.Null(request.Version);
8989
Assert.Equivalent(new Dictionary<string, Value>() { ["Content-Type"] = Value.Pattern("application/json*") }, request.Headers.Value);
90-
Assert.Equal("null", request.Content);
90+
Assert.Equal(new Pattern("null"), request.Content.Value);
9191
}
9292

9393
[Fact]
@@ -99,7 +99,7 @@ public void PostAsJson_ShouldBuildCorrectRequest()
9999
Assert.Equal(UriPatternParser.Parse("https://localhost"), request.RequestUri);
100100
Assert.Null(request.Version);
101101
Assert.Equivalent(new Dictionary<string, Value>() { ["Content-Type"] = Value.Pattern("application/json*") }, request.Headers.Value);
102-
Assert.Equal("{\"hello\":1}", request.Content);
102+
Assert.Equal(new Pattern("{\"hello\":1}"), request.Content.Value);
103103
}
104104

105105
[Fact]
@@ -119,7 +119,7 @@ public void WithJsonContent_WithNullContent_ShouldBuildCorrectRequest()
119119
Assert.Null(request.RequestUri);
120120
Assert.Null(request.Version);
121121
Assert.Equivalent(new Dictionary<string, Value>() { ["Content-Type"] = Value.Pattern("application/json*") }, request.Headers.Value);
122-
Assert.Equal("null", request.Content);
122+
Assert.Equal(new Pattern("null"), request.Content.Value);
123123
}
124124

125125
[Fact]
@@ -131,7 +131,7 @@ public void WithJsonContent_ShouldBuildCorrectRequest()
131131
Assert.Null(request.RequestUri);
132132
Assert.Null(request.Version);
133133
Assert.Equivalent(new Dictionary<string, Value>() { ["Content-Type"] = Value.Pattern("application/json*") }, request.Headers.Value);
134-
Assert.Equal("{\"hello\":1}", request.Content);
134+
Assert.Equal(new Pattern("{\"hello\":1}"), request.Content.Value);
135135
}
136136

137137
[Fact]
@@ -148,11 +148,11 @@ public void WithJsonContent_WithCustomOptions_ShouldBuildCorrectRequest()
148148
Assert.Null(request.RequestUri);
149149
Assert.Null(request.Version);
150150
Assert.Equivalent(new Dictionary<string, Value>() { ["Content-Type"] = Value.Pattern("application/json*") }, request.Headers.Value);
151-
Assert.Equal("""
151+
Assert.Equal(new Pattern("""
152152
{
153153
"hello": 1
154154
}
155-
""", request.Content);
155+
"""), request.Content.Value);
156156
}
157157

158158
[Fact]
@@ -178,6 +178,6 @@ public void WithFormUrlEncodedContent_ShouldBuildCorrectRequest()
178178
Assert.Null(request.RequestUri);
179179
Assert.Null(request.Version);
180180
Assert.Equivalent(new Dictionary<string, Value>() { ["Content-Type"] = Value.Pattern("application/x-www-form-urlencoded*") }, request.Headers.Value);
181-
Assert.Equal("username=alice", request.Content);
181+
Assert.Equal(new Pattern("username=alice"), request.Content.Value);
182182
}
183183
}

test/TestableHttpClient.Tests/RequestBuilderTests.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public void Build_ByDefault_CreatesEmptyRequest()
1515
Assert.Null(request.RequestUri);
1616
Assert.Null(request.Version);
1717
Assert.Equal(new AnyHeader(), request.Headers.Value);
18-
Assert.Null(request.Content);
18+
Assert.Equal(new AnyContent(), request.Content.Value);
1919
}
2020

2121
[Fact]
@@ -33,7 +33,7 @@ public void WithMethod_CreatesRequestWithMethod()
3333
Assert.Null(request.RequestUri);
3434
Assert.Null(request.Version);
3535
Assert.Equal(new AnyHeader(), request.Headers.Value);
36-
Assert.Null(request.Content);
36+
Assert.Equal(new AnyContent(), request.Content.Value);
3737
}
3838

3939
[Fact]
@@ -57,7 +57,7 @@ public void WithRequestUri_UriPattern_ShouldSetRequestUri()
5757
Assert.Equal(UriPatternParser.Parse("http*//test.example"), request.RequestUri);
5858
Assert.Null(request.Version);
5959
Assert.Equal(new AnyHeader(), request.Headers.Value);
60-
Assert.Null(request.Content);
60+
Assert.Equal(new AnyContent(), request.Content.Value);
6161
}
6262

6363
[Fact]
@@ -75,7 +75,7 @@ public void WithVersion_CreatesRequestWithVersion()
7575
Assert.Null(request.RequestUri);
7676
Assert.Equal(HttpVersion.Version11, request.Version);
7777
Assert.Equal(new AnyHeader(), request.Headers.Value);
78-
Assert.Null(request.Content);
78+
Assert.Equal(new AnyContent(), request.Content.Value);
7979
}
8080

8181
[Fact]
@@ -101,7 +101,7 @@ public void WithHeader_ValidHeaderNameNoValue_CreatesRequestWithHeaderWithAnyVal
101101
Assert.Null(request.RequestUri);
102102
Assert.Null(request.Version);
103103
Assert.Equal(new Dictionary<string, Value>() { ["Content-Length"] = Value.Any() }, request.Headers.Value);
104-
Assert.Null(request.Content);
104+
Assert.Equal(new AnyContent(), request.Content.Value);
105105
}
106106

107107
[Fact]
@@ -125,7 +125,7 @@ public void WithHeader_ValidHeaderNamePatternValue_CreatesRequestWithHeaderWithA
125125
Assert.Null(request.RequestUri);
126126
Assert.Null(request.Version);
127127
Assert.Equal(new Dictionary<string, Value>() { ["Content-Length"] = Value.Pattern("*") }, request.Headers.Value);
128-
Assert.Null(request.Content);
128+
Assert.Equal(new AnyContent(), request.Content.Value);
129129
}
130130

131131
[Fact]
@@ -143,6 +143,6 @@ public void WithContent_CreatesRequestWithContent()
143143
Assert.Null(request.RequestUri);
144144
Assert.Null(request.Version);
145145
Assert.Equal(new AnyHeader(), request.Headers.Value);
146-
Assert.Equal("content", request.Content);
146+
Assert.Equal(new Pattern("content"), request.Content.Value);
147147
}
148148
}

test/TestableHttpClient.Tests/Utils/MessageBuilderTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public void BuildMessage_OnexpectedCountZeroActualCountRequestSpecifyingContent(
108108
{
109109
Request request = new(new())
110110
{
111-
Content = "test"
111+
Content = new(new Pattern("test"))
112112
};
113113

114114
var result = MessageBuilder.BuildMessage(1, 0, request);
@@ -129,11 +129,11 @@ public void BuildMessage_OnexpectedCountZeroActualCountRequestSpecifyingHeadersS
129129
{
130130
["Content-Type"] = Value.Exact("application/json")
131131
}),
132-
Content = """
132+
Content = new(new Pattern("""
133133
{
134134
"test": "value"
135135
}
136-
"""
136+
"""))
137137
};
138138

139139
var result = MessageBuilder.BuildMessage(1, 0, request);

0 commit comments

Comments
 (0)