mirror of
https://github.com/zoriya/octokit.net.git
synced 2026-06-01 10:25:36 +00:00
Enable support for milestone-based issues queries (#1788)
* Added support for Milestone filter in SearchIssuesRequest * Fixed some styling issues to match with the style of the existing code * Wrap milestone value with double quotes as milestones can contain spaces * Allow milestone filter to contain double quotes * Ability to search by milestone exclusions * Moved the EscapeDoubleQuotes method to StringExtensions
This commit is contained in:
@@ -64,5 +64,30 @@ namespace Octokit.Tests.Helpers
|
||||
Assert.Equal(expected, template.ExpandUriTemplate(new { name = "example name.txt", label = "labeltext" }).ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public class EscapeDoubleQuotesMethod
|
||||
{
|
||||
[Fact]
|
||||
public void EscapeDoubleQuotesReturnsNullForNullInput()
|
||||
{
|
||||
Assert.Equal(null, (null as string).EscapeDoubleQuotes());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EscapeDoubleQuotesReturnsInputWithoutDoubleQuotes()
|
||||
{
|
||||
string input = "some test input without double quotes in it";
|
||||
|
||||
Assert.Equal(input, input.EscapeDoubleQuotes());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EscapeDoubleQuotesEscapesAllDoubleQuotes()
|
||||
{
|
||||
string input = "\"test milestone\"";
|
||||
|
||||
Assert.Equal("\\\"test milestone\\\"", input.EscapeDoubleQuotes());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ public class SearchIssuesRequestExclusionsTests
|
||||
{ "commenter:", (x,value) => x.Commenter = value },
|
||||
{ "involves:", (x,value) => x.Involves = value },
|
||||
{ "head:", (x,value) => x.Head = value },
|
||||
{ "base:", (x,value) => x.Base = value }
|
||||
{ "base:", (x,value) => x.Base = value },
|
||||
{ "milestone:", (x,value) => x.Milestone = value }
|
||||
};
|
||||
|
||||
foreach (var property in stringProperties)
|
||||
@@ -80,5 +81,25 @@ public class SearchIssuesRequestExclusionsTests
|
||||
|
||||
Assert.True(request.MergedQualifiers().Contains("-status:error"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HandlesMilestoneAttributeWithoutQuotes()
|
||||
{
|
||||
var request = new SearchIssuesRequestExclusions();
|
||||
Assert.False(request.MergedQualifiers().Any(x => x.Contains("-milestone:")));
|
||||
|
||||
request.Milestone = "testMilestone";
|
||||
Assert.True(request.MergedQualifiers().Contains("-milestone:\"testMilestone\""));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoesntWrapMilestoneWithDoubleQuotesForQuotedMilestone()
|
||||
{
|
||||
var request = new SearchIssuesRequestExclusions();
|
||||
Assert.False(request.MergedQualifiers().Any(x => x.Contains("-milestone:")));
|
||||
|
||||
request.Milestone = "\"testMilestone\"";
|
||||
Assert.Contains<string>("-milestone:\"\\\"testMilestone\\\"\"", request.MergedQualifiers());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,8 @@ public class SearchIssuesRequestTests
|
||||
{ "team:", (x,value) => x.Team = value },
|
||||
{ "head:", (x,value) => x.Head = value },
|
||||
{ "base:", (x,value) => x.Base = value },
|
||||
{ "user:", (x,value) => x.User = value }
|
||||
{ "user:", (x,value) => x.User = value },
|
||||
{ "milestone:", (x,value) => x.Milestone = value }
|
||||
};
|
||||
|
||||
foreach (var property in stringProperties)
|
||||
@@ -116,6 +117,26 @@ public class SearchIssuesRequestTests
|
||||
Assert.True(request.MergedQualifiers().Contains("label:label2"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HandlesMilestoneAttributeWithoutQuotes()
|
||||
{
|
||||
var request = new SearchIssuesRequest("text");
|
||||
Assert.False(request.MergedQualifiers().Any(x => x.Contains("milestone:")));
|
||||
|
||||
request.Milestone = "testMilestone";
|
||||
Assert.True(request.MergedQualifiers().Contains("milestone:\"testMilestone\""));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoesntWrapMilestoneWithDoubleQuotesForQuotedMilestone()
|
||||
{
|
||||
var request = new SearchIssuesRequest("text");
|
||||
Assert.False(request.MergedQualifiers().Any(x => x.Contains("milestone:")));
|
||||
|
||||
request.Milestone = "\"testMilestone\"";
|
||||
Assert.Contains<string>("milestone:\"\\\"testMilestone\\\"\"", request.MergedQualifiers());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HandlesNoMetadataAttributeCorrectly()
|
||||
{
|
||||
|
||||
@@ -87,6 +87,17 @@ namespace Octokit
|
||||
Ensure.ArgumentNotNullOrEmptyString(value, nameof(value));
|
||||
return string.Concat(value[0].ToString().ToUpperInvariant(), value.Substring(1));
|
||||
}
|
||||
|
||||
internal static string EscapeDoubleQuotes(this string value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
return value.Replace("\"", "\\\"");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static IEnumerable<string> SplitUpperCase(this string source)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(source, nameof(source));
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using Octokit.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Octokit.Internal;
|
||||
|
||||
namespace Octokit
|
||||
{
|
||||
@@ -168,6 +168,7 @@ namespace Octokit
|
||||
public Language? Language { get; set; }
|
||||
|
||||
private IEnumerable<IssueIsQualifier> _is;
|
||||
|
||||
/// <summary>
|
||||
/// Searches for issues using a more human syntax covering options like state, type, merged status, private/public repository
|
||||
/// </summary>
|
||||
@@ -258,6 +259,11 @@ namespace Octokit
|
||||
/// </remarks>
|
||||
public string User { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the milestone to filter issues based on
|
||||
/// </summary>
|
||||
public string Milestone { get; set; }
|
||||
|
||||
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
|
||||
public RepositoryCollection Repos { get; set; }
|
||||
|
||||
@@ -391,6 +397,11 @@ namespace Octokit
|
||||
parameters.AddRange(Repos.Select(x => string.Format(CultureInfo.InvariantCulture, "repo:{0}", x)));
|
||||
}
|
||||
|
||||
if (Milestone.IsNotBlank())
|
||||
{
|
||||
parameters.Add(string.Format(CultureInfo.InvariantCulture, "milestone:\"{0}\"", Milestone.EscapeDoubleQuotes()));
|
||||
}
|
||||
|
||||
// Add any exclusion parameters
|
||||
if (Exclusions != null)
|
||||
{
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Octokit.Internal;
|
||||
|
||||
namespace Octokit
|
||||
{
|
||||
@@ -122,6 +120,14 @@ namespace Octokit
|
||||
/// </remarks>
|
||||
public string Base { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Excludes issues which target the specified milestone.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// https://help.github.com/articles/searching-issues-and-pull-requests/#search-by-milestone-on-an-issue-or-pull-request
|
||||
/// </remarks>
|
||||
public string Milestone { get; set; }
|
||||
|
||||
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
|
||||
public IReadOnlyList<string> MergedQualifiers()
|
||||
{
|
||||
@@ -182,6 +188,11 @@ namespace Octokit
|
||||
parameters.Add(string.Format(CultureInfo.InvariantCulture, "-base:{0}", Base));
|
||||
}
|
||||
|
||||
if (Milestone.IsNotBlank())
|
||||
{
|
||||
parameters.Add(string.Format(CultureInfo.InvariantCulture, "-milestone:\"{0}\"", Milestone.EscapeDoubleQuotes()));
|
||||
}
|
||||
|
||||
return new ReadOnlyCollection<string>(parameters);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user