Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pagination support to GetIdpGroupId method #1277

Closed
Closed
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
7 changes: 3 additions & 4 deletions src/Octoshift/Services/GithubApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -574,11 +574,10 @@ public virtual async Task<int> GetIdpGroupId(string org, string groupName)
{
var url = $"{_apiUrl}/orgs/{org.EscapeDataString()}/external-groups";

// TODO: Need to implement paging
var response = await _client.GetAsync(url);
var data = JObject.Parse(response);
var group = await _client.GetAllAsync(url, data => (JArray)data["groups"])
.SingleAsync(x => string.Equals((string)x["group_name"], groupName, StringComparison.OrdinalIgnoreCase));

return (int)data["groups"].Children().Single(x => ((string)x["group_name"]).ToUpper() == groupName.ToUpper())["group_id"];
return (int)group["group_id"];
}

public virtual async Task<string> GetTeamSlug(string org, string teamName)
Expand Down
16 changes: 14 additions & 2 deletions src/Octoshift/Services/GithubClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,25 @@ public GithubClient(OctoLogger log, HttpClient httpClient, IVersionProvider vers

public virtual async Task<string> GetAsync(string url, Dictionary<string, string> customHeaders = null) => (await GetWithRetry(url, customHeaders)).Content;

public virtual async IAsyncEnumerable<JToken> GetAllAsync(string url, Dictionary<string, string> customHeaders = null)
public virtual IAsyncEnumerable<JToken> GetAllAsync(string url, Dictionary<string, string> customHeaders = null) =>
GetAllAsync(url, jToken => (JArray)jToken, customHeaders);

public virtual async IAsyncEnumerable<JToken> GetAllAsync(
string url,
Func<JToken, JArray> resultCollectionSelector,
Dictionary<string, string> customHeaders = null)
{
if (resultCollectionSelector is null)
{
throw new ArgumentNullException(nameof(resultCollectionSelector));
}

var nextUrl = url;
do
{
var (content, headers) = await GetWithRetry(nextUrl, customHeaders: customHeaders);
foreach (var jToken in JArray.Parse(content))
var jContent = JToken.Parse(content);
foreach (var jToken in resultCollectionSelector(jContent))
{
yield return jToken;
}
Expand Down
36 changes: 19 additions & 17 deletions src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1606,25 +1606,27 @@ public async Task GetIdpGroupId_Returns_The_Idp_Group_Id()

var url = $"https://api.github.com/orgs/{GITHUB_ORG}/external-groups";
const int expectedGroupId = 123;
var response = $@"
{{
""groups"": [
{{
""group_id"": ""{expectedGroupId}"",
""group_name"": ""{groupName}"",
""updated_at"": ""2021-01-24T11:31:04-06:00""
}},
{{
""group_id"": ""456"",
""group_name"": ""Octocat admins"",
""updated_at"": ""2021-03-24T11:31:04-06:00""
}},
]
}}";

var group1 = new
{
group_id = expectedGroupId,
group_name = groupName,
updated_at = DateTime.Parse("2021-01-24T11:31:04-06:00")
};
var group2 = new
{
group_id = "456",
group_name = "Octocat admins",
updated_at = DateTime.Parse("2021-03-24T11:31:04-06:00")
};

_githubClientMock
.Setup(m => m.GetAsync(url, null))
.ReturnsAsync(response);
.Setup(m => m.GetAllAsync(url, It.IsAny<Func<JToken, JArray>>(), null))
.Returns(new[]
{
JToken.FromObject(group1),
JToken.FromObject(group2)
}.ToAsyncEnumerable());

// Act
var actualGroupId = await _githubApi.GetIdpGroupId(GITHUB_ORG, groupName);
Expand Down
42 changes: 42 additions & 0 deletions src/OctoshiftCLI.Tests/Octoshift/Services/GithubClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,48 @@ public async Task GetAllAsync_Retries_On_Non_Success()
results.Should().BeEquivalentTo(firstItem, secondItem);
}

[Fact]
public async Task GetAllAsync_Should_Use_Result_Collection_Selector()
{
// Arrange
const string url = "https://api.github.com/orgs/foo/external-groups";

const string firstGroupId = "123";
const string firstGroupName = "Octocat readers";
const string secondGroupId = "456";
const string secondGroupName = "Octocat admins";
const string response = $@"
{{
""groups"": [
{{
""group_id"": ""{firstGroupId}"",
""group_name"": ""{firstGroupName}"",
""updated_at"": ""2021-01-24T11:31:04-06:00""
}},
{{
""group_id"": ""{secondGroupId}"",
""group_name"": ""{secondGroupName}"",
""updated_at"": ""2021-03-24T11:31:04-06:00""
}},
]
}}";

var handlerMock = MockHttpHandler(req => req.Method == HttpMethod.Get && req.RequestUri.ToString() == url, CreateHttpResponseFactory(content: response));

using var httpClient = new HttpClient(handlerMock.Object);
var githubClient = new GithubClient(_mockOctoLogger.Object, httpClient, null, _retryPolicy, _dateTimeProvider.Object, PERSONAL_ACCESS_TOKEN);

// Act
var results = await githubClient.GetAllAsync(url, data => (JArray)data["groups"]).ToListAsync();

// Assert
results.Should().HaveCount(2);
results[0]["group_id"].Value<string>().Should().Be(firstGroupId);
results[0]["group_name"].Value<string>().Should().Be(firstGroupName);
results[1]["group_id"].Value<string>().Should().Be(secondGroupId);
results[1]["group_name"].Value<string>().Should().Be(secondGroupName);
}

[Fact]
public async Task PostGraphQLWithPaginationAsync_Should_Return_All_Pages()
{
Expand Down
Loading