diff --git a/Octokit.Tests.Integration/Clients/SearchClientTests.cs b/Octokit.Tests.Integration/Clients/SearchClientTests.cs index 9d1e90d1..6b931d19 100644 --- a/Octokit.Tests.Integration/Clients/SearchClientTests.cs +++ b/Octokit.Tests.Integration/Clients/SearchClientTests.cs @@ -82,9 +82,10 @@ public class SearchClientTests [IntegrationTest] public async Task SearchForFilesInOrganization() { + var orgs = new[] { "octokit", "github" }; var request = new SearchCodeRequest() { - Organization = "octokit", + Organizations = orgs, FileName = "readme.md" }; @@ -92,7 +93,25 @@ public class SearchClientTests foreach (var searchResult in searchResults.Items) { - Assert.Equal("octokit", searchResult.Repository.Owner.Login); + Assert.Contains(searchResult.Repository.Owner.Login, orgs); + } + } + + [IntegrationTest] + public async Task SearchForFilesInUsers() + { + var users = new[] { "octokit", "github" }; + var request = new SearchCodeRequest() + { + Users = users, + FileName = "readme.md" + }; + + var searchResults = await _gitHubClient.Search.SearchCode(request); + + foreach (var searchResult in searchResults.Items) + { + Assert.Contains(searchResult.Repository.Owner.Login, users); } } diff --git a/Octokit.Tests/Clients/SearchClientTests.cs b/Octokit.Tests/Clients/SearchClientTests.cs index e9fc20ac..1ead16eb 100644 --- a/Octokit.Tests/Clients/SearchClientTests.cs +++ b/Octokit.Tests/Clients/SearchClientTests.cs @@ -1850,8 +1850,10 @@ namespace Octokit.Tests.Clients { var connection = Substitute.For(); var client = new SearchClient(connection); - var request = new SearchCodeRequest("something"); - request.User = "alfhenrik"; + var request = new SearchCodeRequest("something") + { + Users = new[] { "alfhenrik" } + }; client.SearchCode(request); @@ -1860,6 +1862,23 @@ namespace Octokit.Tests.Clients Arg.Is>(d => d["q"] == "something+user:alfhenrik")); } + [Fact] + public void TestingTheUserQualifier_Multiple() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchCodeRequest("something") + { + Users = new[] { "johnDoe", "janeDoe" } + }; + + client.SearchCode(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/code"), + Arg.Is>(d => d["q"] == "something+user:johnDoe+user:janeDoe")); + } + [Fact] public void TestingTheRepoQualifier() { @@ -1879,8 +1898,10 @@ namespace Octokit.Tests.Clients { var connection = Substitute.For(); var client = new SearchClient(connection); - var request = new SearchCodeRequest("something"); - request.Organization = "octokit"; + var request = new SearchCodeRequest("something") + { + Organizations = new[] { "octokit" } + }; client.SearchCode(request); @@ -1889,6 +1910,23 @@ namespace Octokit.Tests.Clients Arg.Is>(d => d["q"] == "something+org:octokit")); } + [Fact] + public void TestingTheOrgQualifier_Multiple() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchCodeRequest("something") + { + Organizations = new[] { "octokit", "dotnet" } + }; + + client.SearchCode(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/code"), + Arg.Is>(d => d["q"] == "something+org:octokit+org:dotnet")); + } + [Fact] public void TestingTheRepoAndPathAndExtensionQualifiers() { @@ -1908,6 +1946,44 @@ namespace Octokit.Tests.Clients d["q"] == "something+path:tools/FAKE.core+extension:fs+extension:cs+repo:octokit/octokit.net")); } + [Fact] + public void TestingTheRepoAndPathAndUsersQualifiers() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchCodeRequest("something", "octokit", "octokit.net") + { + Users = new[] { "johnDoe", "janeDoe" } + }; + request.Path = "tools/FAKE.core"; + + client.SearchCode(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/code"), + Arg.Is>(d => + d["q"] == "something+path:tools/FAKE.core+user:johnDoe+user:janeDoe+repo:octokit/octokit.net")); + } + + [Fact] + public void TestingTheRepoAndPathAndOrganizationsQualifiers() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchCodeRequest("something", "octokit", "octokit.net") + { + Organizations = new[] { "johnDoe", "janeDoe" } + }; + request.Path = "tools/FAKE.core"; + + client.SearchCode(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/code"), + Arg.Is>(d => + d["q"] == "something+path:tools/FAKE.core+repo:octokit/octokit.net+org:johnDoe+org:janeDoe")); + } + [Fact] public async Task ErrorOccursWhenSpecifyingInvalidFormatForRepos() { diff --git a/Octokit/Models/Request/SearchCodeRequest.cs b/Octokit/Models/Request/SearchCodeRequest.cs index 9c4795fa..bc9574c8 100644 --- a/Octokit/Models/Request/SearchCodeRequest.cs +++ b/Octokit/Models/Request/SearchCodeRequest.cs @@ -116,7 +116,7 @@ namespace Octokit public string Path { get; set; } /// - /// Matches files with a certain extensions. + /// Matches files with certain extensions. /// /// /// https://help.github.com/articles/searching-code#extension @@ -132,20 +132,20 @@ namespace Octokit public string FileName { get; set; } /// - /// Limits searches to a specific user. + /// Limits searches to specific users. /// /// /// https://help.github.com/articles/searching-code#users-organizations-and-repositories /// - public string User { get; set; } + public IEnumerable Users { get; set; } = new List(); /// - /// Limits searches to a specific organization. + /// Limits searches to specific organizations. /// /// /// https://help.github.com/articles/searching-code/#search-within-a-users-or-organizations-repositories /// - public string Organization { get; set; } + public IEnumerable Organizations { get; set; } = new List(); /// /// Limits searches to a specific repository. @@ -202,9 +202,13 @@ namespace Octokit parameters.Add(string.Format(CultureInfo.InvariantCulture, "filename:{0}", FileName)); } - if (User.IsNotBlank()) + + if (Users.Any()) { - parameters.Add(string.Format(CultureInfo.InvariantCulture, "user:{0}", User)); + foreach (var user in Users) + { + parameters.Add(string.Format(CultureInfo.InvariantCulture, "user:{0}", user)); + } } if (Repos.Any()) @@ -219,9 +223,12 @@ namespace Octokit string.Join("+", Repos.Select(x => "repo:" + x))); } - if (Organization.IsNotBlank()) + if (Organizations.Any()) { - parameters.Add(string.Format(CultureInfo.InvariantCulture, "org:{0}", Organization)); + foreach (var org in Organizations) + { + parameters.Add(string.Format(CultureInfo.InvariantCulture, "org:{0}", org)); + } } return new ReadOnlyCollection(parameters); diff --git a/docs/search.md b/docs/search.md index bead98bc..1c3e1c7f 100644 --- a/docs/search.md +++ b/docs/search.md @@ -198,10 +198,10 @@ var request = new SearchCodeRequest("auth") { // we can restrict search to the file, path or search both In = new[] { CodeInQualifier.File, CodeInQualifier.Path }, - + // how about we find a file based on a certain language Language = Language.JavaScript, - + // do we want to search forks too? Forks = true, @@ -210,15 +210,16 @@ var request = new SearchCodeRequest("auth") // we may want to restrict the search to the path of a file Path = "app/assets", - + // we may want to restrict the file based on file extension Extensions = new[] { "json", "sql" }, - + // restrict search to a specific file name FileName = "app.json", - + // search within a users or orgs repo - User = "dhh" + Users = new[] { "johnDoe", "janeDoe" } + Organizations = new[] { "johnDoe", "janeDoe" } }; ```