Skip to content

Commit

Permalink
Implement Nested Teams preview API changes (#1682)
Browse files Browse the repository at this point in the history
* Add new AcceptsHeader
add Parent field to Team
add ParentId field to NewTeam and UpdateTeam
update Create Edit and Delete Team methods to use preview header

* Implement new API call GetAllChildTeams()

* Implement GetAllChildTeams for ObservableClient

* add integration test for observable client

* Add pagination tests for GetAllChildTeams

* Add NestedTeams preview header to all the API calls that use it

* Update tests for accepts header

* Add accepts header to observable client calls

* Fix DELETE implementation to use correct overload

* Fix tests - parent and child teams must be visibility Closed whereas the default if not specified is Private

* make sure all tests are flagged as [OrganizationTest]

* Make sure Update tests change the parent of the team

* Update new methods with NesterTeams preview API header and adjust tests
  • Loading branch information
ryangribble committed Oct 4, 2017
1 parent da0c7a5 commit e93646c
Show file tree
Hide file tree
Showing 15 changed files with 487 additions and 33 deletions.
18 changes: 18 additions & 0 deletions Octokit.Reactive/Clients/IObservableTeamsClient.cs
Expand Up @@ -58,6 +58,24 @@ public interface IObservableTeamsClient
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
IObservable<Team> GetAllForCurrent(ApiOptions options);

/// <summary>
/// Returns all child teams of the given team.
/// </summary>
/// <param name="id">The team identifier</param>
/// <remarks>
/// https://developer.github.com/v3/orgs/teams/#list-child-teams
/// </remarks>
IObservable<Team> GetAllChildTeams(int id);

/// <summary>
/// Returns all child teams of the given team.
/// </summary>
/// <param name="id">The team identifier</param>
/// <remarks>
/// https://developer.github.com/v3/orgs/teams/#list-child-teams
/// </remarks>
IObservable<Team> GetAllChildTeams(int id, ApiOptions options);

/// <summary>
/// Returns all members of the given team.
/// </summary>
Expand Down
36 changes: 31 additions & 5 deletions Octokit.Reactive/Clients/ObservableTeamsClient.cs
Expand Up @@ -64,7 +64,7 @@ public IObservable<Team> GetAll(string org, ApiOptions options)
Ensure.ArgumentNotNullOrEmptyString(org, "org");
Ensure.ArgumentNotNull(options, "options");

return _connection.GetAndFlattenAllPages<Team>(ApiUrls.OrganizationTeams(org), options);
return _connection.GetAndFlattenAllPages<Team>(ApiUrls.OrganizationTeams(org), null, AcceptHeaders.NestedTeamsPreview, options);
}

/// <summary>
Expand All @@ -87,7 +87,33 @@ public IObservable<Team> GetAllForCurrent(ApiOptions options)
{
Ensure.ArgumentNotNull(options, "options");

return _connection.GetAndFlattenAllPages<Team>(ApiUrls.UserTeams(), options);
return _connection.GetAndFlattenAllPages<Team>(ApiUrls.UserTeams(), null, AcceptHeaders.NestedTeamsPreview, options);
}

/// <summary>
/// Returns all child teams of the given team.
/// </summary>
/// <param name="id">The team identifier</param>
/// <remarks>
/// https://developer.github.com/v3/orgs/teams/#list-child-teams
/// </remarks>
public IObservable<Team> GetAllChildTeams(int id)
{
return GetAllChildTeams(id, ApiOptions.None);
}

/// <summary>
/// Returns all child teams of the given team.
/// </summary>
/// <param name="id">The team identifier</param>
/// <remarks>
/// https://developer.github.com/v3/orgs/teams/#list-child-teams
/// </remarks>
public IObservable<Team> GetAllChildTeams(int id, ApiOptions options)
{
Ensure.ArgumentNotNull(options, "options");

return _connection.GetAndFlattenAllPages<Team>(ApiUrls.TeamChildTeams(id), null, AcceptHeaders.NestedTeamsPreview, options);
}

/// <summary>
Expand Down Expand Up @@ -118,7 +144,7 @@ public IObservable<User> GetAllMembers(int id, ApiOptions options)
{
Ensure.ArgumentNotNull(options, "options");

return _connection.GetAndFlattenAllPages<User>(ApiUrls.TeamMembers(id), options);
return _connection.GetAndFlattenAllPages<User>(ApiUrls.TeamMembers(id), null, AcceptHeaders.NestedTeamsPreview, options);
}

/// <summary>
Expand Down Expand Up @@ -150,7 +176,7 @@ public IObservable<User> GetAllMembers(int id, TeamMembersRequest request, ApiOp
Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(options, nameof(options));

return _connection.GetAndFlattenAllPages<User>(ApiUrls.TeamMembers(id), request.ToParametersDictionary(), options);
return _connection.GetAndFlattenAllPages<User>(ApiUrls.TeamMembers(id), request.ToParametersDictionary(), AcceptHeaders.NestedTeamsPreview, options);
}

/// <summary>
Expand Down Expand Up @@ -289,7 +315,7 @@ public IObservable<Repository> GetAllRepositories(int id, ApiOptions options)
{
Ensure.ArgumentNotNull(options, "options");

return _connection.GetAndFlattenAllPages<Repository>(ApiUrls.TeamRepositories(id), null, AcceptHeaders.OrganizationPermissionsPreview, options);
return _connection.GetAndFlattenAllPages<Repository>(ApiUrls.TeamRepositories(id), null, AcceptHeaders.NestedTeamsPreview, options);
}

/// <summary>
Expand Down
105 changes: 103 additions & 2 deletions Octokit.Tests.Integration/Clients/TeamsClientTests.cs
Expand Up @@ -43,7 +43,7 @@ public async Task CreatesTeam()

public class TheGetAllForCurrentMethod
{
[IntegrationTest]
[OrganizationTest]
public async Task GetsAllForCurrentWhenAuthenticated()
{
var github = Helper.GetAuthenticatedClient();
Expand All @@ -52,6 +52,104 @@ public async Task GetsAllForCurrentWhenAuthenticated()
}
}

public class TheGetAllChildTeamsMethod
{
private readonly IGitHubClient _github;

public TheGetAllChildTeamsMethod()
{
_github = Helper.GetAuthenticatedClient();
}

[OrganizationTest]
public async Task GetsAllChildTeams()
{
using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team"))))
{
var team1 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });
var team2 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });

var teams = await _github.Organization.Team.GetAllChildTeams(parentTeamContext.TeamId);

Assert.Equal(2, teams.Count);
Assert.True(teams.Any(x => x.Id == team1.Id));
Assert.True(teams.Any(x => x.Id == team2.Id));
}
}

[OrganizationTest]
public async Task ReturnsCorrectCountOfChildTeamsWithoutStart()
{
using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team"))))
{
var team1 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });
var team2 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });

var options = new ApiOptions
{
PageSize = 1,
PageCount = 1
};

var teams = await _github.Organization.Team.GetAllChildTeams(parentTeamContext.TeamId, options);

Assert.Equal(1, teams.Count);
Assert.Equal(team1.Id, teams[0].Id);
}
}

[OrganizationTest]
public async Task ReturnsCorrectCountOfChildTeamsWithStart()
{
using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team"))))
{
var team1 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });
var team2 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });

var options = new ApiOptions
{
PageSize = 1,
PageCount = 1,
StartPage = 2
};

var teams = await _github.Organization.Team.GetAllChildTeams(parentTeamContext.TeamId, options);

Assert.Equal(1, teams.Count);
Assert.Equal(team2.Id, teams[0].Id);
}
}

[OrganizationTest]
public async Task ReturnsDistinctChildTeamsBasedOnStartPage()
{
using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team"))))
{
var team1 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });
var team2 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });

var startOptions = new ApiOptions
{
PageSize = 1,
PageCount = 1
};

var firstPage = await _github.Organization.Team.GetAllChildTeams(parentTeamContext.TeamId, startOptions);

var skipStartOptions = new ApiOptions
{
PageSize = 1,
PageCount = 1,
StartPage = 2
};

var secondPage = await _github.Organization.Team.GetAllChildTeams(parentTeamContext.TeamId, skipStartOptions);

Assert.NotEqual(firstPage[0].Id, secondPage[0].Id);
}
}
}

public class TheAddOrEditMembershipMethod : IDisposable
{
private readonly IGitHubClient _github;
Expand Down Expand Up @@ -384,21 +482,24 @@ public TheUpdateMethod()
[OrganizationTest]
public async Task UpdatesTeam()
{
using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team"))))
using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team-fixture"))))
{
var teamName = Helper.MakeNameWithTimestamp("updated-team");
var teamDescription = Helper.MakeNameWithTimestamp("updated description");
var update = new UpdateTeam(teamName)
{
Description = teamDescription,
Privacy = TeamPrivacy.Closed
Privacy = TeamPrivacy.Closed,
ParentTeamId = parentTeamContext.TeamId
};

var team = await _github.Organization.Team.Update(teamContext.TeamId, update);

Assert.Equal(teamName, team.Name);
Assert.Equal(teamDescription, team.Description);
Assert.Equal(TeamPrivacy.Closed, team.Privacy);
Assert.Equal(parentTeamContext.TeamId, team.Parent.Id);
}
}
}
Expand Down
Expand Up @@ -28,6 +28,7 @@ internal static async Task<RepositoryContext> CreateRepositoryContext(this IGitH

internal static async Task<TeamContext> CreateTeamContext(this IGitHubClient client, string organization, NewTeam newTeam)
{
newTeam.Privacy = TeamPrivacy.Closed;
var team = await client.Organization.Team.Create(organization, newTeam);

return new TeamContext(client.Connection, team);
Expand Down
Expand Up @@ -30,6 +30,7 @@ internal static async Task<RepositoryContext> CreateRepositoryContext(this IObse

internal static async Task<TeamContext> CreateTeamContext(this IObservableGitHubClient client, string organization, NewTeam newTeam)
{
newTeam.Privacy = TeamPrivacy.Closed;
var team = await client.Organization.Team.Create(organization, newTeam);

return new TeamContext(client.Connection, team);
Expand Down
132 changes: 132 additions & 0 deletions Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs
Expand Up @@ -10,6 +10,104 @@

public class ObservableTeamsClientTests
{
public class TheGetAllChildTeamsMethod
{
private readonly IObservableGitHubClient _github;

public TheGetAllChildTeamsMethod()
{
_github = new ObservableGitHubClient(Helper.GetAuthenticatedClient());
}

[OrganizationTest]
public async Task GetsChildTeams()
{
using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team"))))
{
var team1 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });
var team2 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });

var teams = await _github.Organization.Team.GetAllChildTeams(parentTeamContext.TeamId).ToList();

Assert.Equal(2, teams.Count);
Assert.True(teams.Any(x => x.Id == team1.Id));
Assert.True(teams.Any(x => x.Id == team2.Id));
}
}

[OrganizationTest]
public async Task ReturnsCorrectCountOfChildTeamsWithoutStart()
{
using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team"))))
{
var team1 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });
var team2 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });

var options = new ApiOptions
{
PageSize = 1,
PageCount = 1
};

var teams = await _github.Organization.Team.GetAllChildTeams(parentTeamContext.TeamId, options).ToList();

Assert.Equal(1, teams.Count);
Assert.Equal(team1.Id, teams[0].Id);
}
}

[OrganizationTest]
public async Task ReturnsCorrectCountOfChildTeamsWithStart()
{
using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team"))))
{
var team1 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });
var team2 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });

var options = new ApiOptions
{
PageSize = 1,
PageCount = 1,
StartPage = 2
};

var teams = await _github.Organization.Team.GetAllChildTeams(parentTeamContext.TeamId, options).ToList();

Assert.Equal(1, teams.Count);
Assert.Equal(team2.Id, teams[0].Id);
}
}

[OrganizationTest]
public async Task ReturnsDistinctChildTeamsBasedOnStartPage()
{
using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team"))))
{
var team1 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });
var team2 = await _github.Organization.Team.Create(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("child-team")) { Privacy = TeamPrivacy.Closed, ParentTeamId = parentTeamContext.TeamId });

var startOptions = new ApiOptions
{
PageSize = 1,
PageCount = 1
};

var firstPage = await _github.Organization.Team.GetAllChildTeams(parentTeamContext.TeamId, startOptions).ToList();

var skipStartOptions = new ApiOptions
{
PageSize = 1,
PageCount = 1,
StartPage = 2
};

var secondPage = await _github.Organization.Team.GetAllChildTeams(parentTeamContext.TeamId, skipStartOptions).ToList();

Assert.NotEqual(firstPage[0].Id, secondPage[0].Id);
}
}
}

public class TheAddOrEditMembershipMethod : IDisposable
{
private readonly IObservableGitHubClient _github;
Expand Down Expand Up @@ -263,4 +361,38 @@ public async Task ReturnsCorrectCountOfPendingInvitationsWithStart()
}
}
}

public class TheUpdateMethod
{
private readonly IObservableGitHubClient _github;

public TheUpdateMethod()
{
_github = new ObservableGitHubClient(Helper.GetAuthenticatedClient());
}

[OrganizationTest]
public async Task UpdatesTeam()
{
using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team"))))
using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team-fixture"))))
{
var teamName = Helper.MakeNameWithTimestamp("updated-team");
var teamDescription = Helper.MakeNameWithTimestamp("updated description");
var update = new UpdateTeam(teamName)
{
Description = teamDescription,
Privacy = TeamPrivacy.Closed,
ParentTeamId = parentTeamContext.TeamId
};

var team = await _github.Organization.Team.Update(teamContext.TeamId, update);

Assert.Equal(teamName, team.Name);
Assert.Equal(teamDescription, team.Description);
Assert.Equal(TeamPrivacy.Closed, team.Privacy);
Assert.Equal(parentTeamContext.TeamId, team.Parent.Id);
}
}
}
}

0 comments on commit e93646c

Please sign in to comment.