Skip to content

Commit

Permalink
🐛 should consider all parameters within QueryString, even when repeated
Browse files Browse the repository at this point in the history
  • Loading branch information
fluffynuts committed Dec 17, 2024
1 parent 8d2890e commit cb0fbce
Show file tree
Hide file tree
Showing 5 changed files with 277 additions and 118 deletions.
249 changes: 178 additions & 71 deletions src/NExpect.Matchers.AspNetCore.Tests/TestQueryStringMatchers.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Http;
using NExpect.Exceptions;
using PeanutButter.Utils;

namespace NExpect.Matchers.AspNet.Tests;

Expand All @@ -17,11 +20,14 @@ public void ShouldThrowWhenTooFewParameters()
var qs = new QueryString();
qs = qs.Add("foo", "bar");
// Act
Assert.That(() =>
{
Expect(qs)
.To.Contain.Only(2).Items();
}, Throws.Exception.InstanceOf<UnmetExpectationException>());
Assert.That(
() =>
{
Expect(qs)
.To.Contain.Only(2).Items();
},
Throws.Exception.InstanceOf<UnmetExpectationException>()
);
// Assert
}

Expand All @@ -33,11 +39,14 @@ public void ShouldThrowWhenTooManyParameters()
qs = qs.Add("foo", "bar");
qs = qs.Add("quux", "wibble");
// Act
Assert.That(() =>
{
Expect(qs)
.To.Contain.Only(1).Item();
}, Throws.Exception.InstanceOf<UnmetExpectationException>());
Assert.That(
() =>
{
Expect(qs)
.To.Contain.Only(1).Item();
},
Throws.Exception.InstanceOf<UnmetExpectationException>()
);
// Assert
}
}
Expand All @@ -56,11 +65,14 @@ public void ShouldBeAbleToTestEquivalence()
};

// Act
Assert.That(() =>
{
Expect(qs)
.To.Be.Equivalent.To(expected);
}, Throws.Nothing);
Assert.That(
() =>
{
Expect(qs)
.To.Be.Equivalent.To(expected);
},
Throws.Nothing
);
// Assert
}

Expand All @@ -73,26 +85,35 @@ public void ShouldBeAbleToTestByKeyAndValue()
qs = qs.Add("c", "d");

// Act
Assert.That(() =>
{
Expect(qs)
.To.Contain.Key("a")
.With.Value("b");
}, Throws.Nothing);
Assert.That(
() =>
{
Expect(qs)
.To.Contain.Key("a")
.With.Value("b");
},
Throws.Nothing
);

Assert.That(() =>
{
Expect(qs)
.To.Contain.Key("a")
.With.Value("2");
}, Throws.Exception.InstanceOf<UnmetExpectationException>());
Assert.That(
() =>
{
Expect(qs)
.To.Contain.Key("a")
.With.Value("2");
},
Throws.Exception.InstanceOf<UnmetExpectationException>()
);

Assert.That(() =>
{
Expect(qs)
.To.Contain.Key("1")
.With.Value("2");
}, Throws.Exception.InstanceOf<UnmetExpectationException>());
Assert.That(
() =>
{
Expect(qs)
.To.Contain.Key("1")
.With.Value("2");
},
Throws.Exception.InstanceOf<UnmetExpectationException>()
);
// Assert
}

Expand All @@ -104,30 +125,42 @@ public void ShouldBeAbleToCompareWithAnotherQueryString()
var qs2 = new QueryString().Add("a", "b");
var qs3 = new QueryString().Add("1", "2");
// Act
Assert.That(() =>
{
Expect(qs1)
.To.Equal(qs2);
Expect(qs1)
.Not.To.Equal(qs3);
Expect(qs1)
.To.Not.Equal(qs3);
}, Throws.Nothing);
Assert.That(() =>
{
Expect(qs1)
.To.Equal(qs3);
}, Throws.Exception.InstanceOf<UnmetExpectationException>());
Assert.That(() =>
{
Expect(qs1)
.Not.To.Equal(qs2);
}, Throws.Exception.InstanceOf<UnmetExpectationException>());
Assert.That(() =>
{
Expect(qs1)
.To.Not.Equal(qs2);
}, Throws.Exception.InstanceOf<UnmetExpectationException>());
Assert.That(
() =>
{
Expect(qs1)
.To.Equal(qs2);
Expect(qs1)
.Not.To.Equal(qs3);
Expect(qs1)
.To.Not.Equal(qs3);
},
Throws.Nothing
);
Assert.That(
() =>
{
Expect(qs1)
.To.Equal(qs3);
},
Throws.Exception.InstanceOf<UnmetExpectationException>()
);
Assert.That(
() =>
{
Expect(qs1)
.Not.To.Equal(qs2);
},
Throws.Exception.InstanceOf<UnmetExpectationException>()
);
Assert.That(
() =>
{
Expect(qs1)
.To.Not.Equal(qs2);
},
Throws.Exception.InstanceOf<UnmetExpectationException>()
);
// Assert
}

Expand All @@ -137,24 +170,98 @@ public void ShouldDealWithEmptyQueryString()
// Arrange
var qs = new QueryString();
// Act
Assert.That(() =>
Assert.That(
() =>
{
Expect(qs)
.To.Be.Empty();
},
Throws.Nothing
);
Assert.That(
() =>
{
Expect(qs)
.Not.To.Be.Empty();
},
Throws.Exception.InstanceOf<UnmetExpectationException>()
);
Assert.That(
() =>
{
Expect(qs)
.To.Equal(
new Dictionary<string, string>()
{
["a"] = "b"
}
);
},
Throws.Exception.InstanceOf<UnmetExpectationException>()
);
// Assert
}

[Test]
public void ShouldMatchTheSameParameterRepeated()
{
// Arrange
var query = new QueryString("?a=1&a=2");
var expected = new Dictionary<string, string>()
{
Expect(qs)
.To.Be.Empty();
}, Throws.Nothing);
["a"] = "1,2"
};
// Act
Assert.That(() =>
{
Expect(qs)
.Not.To.Be.Empty();
}, Throws.Exception.InstanceOf<UnmetExpectationException>());
Assert.That(() =>
Expect(query)
.To.Be.Equivalent.To(expected);
}, Throws.Nothing);
// Assert
}
}
internal static class QueryStringExtensions
{
/// <summary>
/// Provides a dictionary snapshot of a QueryString
/// </summary>
/// <param name="queryString"></param>
/// <returns></returns>
public static IDictionary<string, string> AsDictionary(
this QueryString queryString
)
{
if (queryString.Value is null)
{
Expect(qs)
.To.Equal(new Dictionary<string, string>()
return new Dictionary<string, string>();
}

var str = queryString.Value;
var start = str.StartsWith("?")
? 1
: 0;
var result = new Dictionary<string, string>();
var pairs = str.Substring(start)
.Split('&')
.Select(
p =>
{
["a"] = "b"
});
}, Throws.Exception.InstanceOf<UnmetExpectationException>());
// Assert
var subs = p.Split('=');
return new KeyValuePair<string, string>(
WebUtility.UrlDecode(subs.First()),
WebUtility.UrlDecode(subs.Skip(1).JoinWith("="))
);
}
);
foreach (var item in pairs)
{
if (result.TryGetValue(item.Key, out var existing))
{
result[item.Key] = $"{existing},{item.Value}";
continue;
}
result[item.Key] = item.Value;
}
return result;
}
}
4 changes: 2 additions & 2 deletions src/NExpect.Matchers.AspNetCore/AspNetCoreExpectations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public static ICollectionExpectation<KeyValuePair<string, StringValues>> Expect(
IFormCollection form
)
{
return Expectations.Expect(
form as IEnumerable<KeyValuePair<string, StringValues>>
return Expectations.Expect<KeyValuePair<string, StringValues>>(
form
);
}

Expand Down
15 changes: 13 additions & 2 deletions src/NExpect.Matchers.AspNetCore/QueryStringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ this QueryString queryString
var start = str.StartsWith("?")
? 1
: 0;
return str.Substring(start)
var result = new Dictionary<string, string>();
var pairs = str.Substring(start)
.Split('&')
.Select(
p =>
Expand All @@ -40,6 +41,16 @@ this QueryString queryString
WebUtility.UrlDecode(subs.Skip(1).JoinWith("="))
);
}
).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
);
foreach (var item in pairs)
{
if (result.TryGetValue(item.Key, out var existing))
{
result[item.Key] = $"{existing},{item.Value}";
continue;
}
result[item.Key] = item.Value;
}
return result;
}
}
Loading

0 comments on commit cb0fbce

Please sign in to comment.