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

Implemented Get / IsMember for teams #449

Merged
merged 6 commits into from
Apr 22, 2014
Merged
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
8 changes: 5 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,15 @@ Run this command to confirm all the tests pass: `.\build`

Octokit has integration tests that access the GitHub API, but they must be
configured before they will be executed. To configure the tests, create a
test GitHub account (i.e., don't use your real GitHub account) and then set
the following two environment variables:
test GitHub account (i.e., don't use your real GitHub account) and a test
organization owned by that account. Then set the following environment variables:

`OCTOKIT_GITHUBUSERNAME` (set this to the test account's username)
`OCTOKIT_GITHUBPASSWORD` (set this to the test account's password)
`OCTOKIT_GITHUBORGANIZATION` (set this to the test account's organization)

Once both of these are set, the integration tests will be executed both when

Once these are set, the integration tests will be executed both when
running the FullBuild MSBuild target, and when running the
Octokit.Tests.Integration assembly through an xUnit.net-friendly test runner.

Expand Down
22 changes: 22 additions & 0 deletions Octokit.Reactive/Clients/IObservableTeamsClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reactive;

namespace Octokit.Reactive
Expand All @@ -11,6 +12,18 @@ namespace Octokit.Reactive
/// </remarks>
public interface IObservableTeamsClient
{
/// <summary>
/// Gets a single <see cref="Team"/> by identifier.
/// </summary>
/// <remarks>
/// https://developer.github.com/v3/orgs/teams/#get-team
/// </remarks>
/// <param name="id">The team identifier.</param>
/// <returns>The <see cref="Team"/> with the given identifier.</returns>
[SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get",
Justification = "Method makes a network request")]
IObservable<Team> Get(int id);

/// <summary>
/// Returns all <see cref="Team" />s for the current org.
/// </summary>
Expand Down Expand Up @@ -38,5 +51,14 @@ public interface IObservableTeamsClient
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns></returns>
IObservable<Unit> Delete(int id);

/// <summary>
/// Gets whether the user with the given <paramref name="login"/>
/// is a member of the team with the given <paramref name="id"/>.
/// </summary>
/// <param name="id">The team to check.</param>
/// <param name="login">The user to check.</param>
/// <returns><see langword="true"/> if the user is a member of the team; <see langword="false"/> otherwise.</returns>
IObservable<bool> IsMember(int id, string login);
}
}
26 changes: 26 additions & 0 deletions Octokit.Reactive/Clients/ObservableTeamsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ public ObservableTeamsClient(IGitHubClient client)
_client = client.Organization.Team;
}

/// <summary>
/// Gets a single <see cref="Team"/> by identifier.
/// </summary>
/// <remarks>
/// https://developer.github.com/v3/orgs/teams/#get-team
/// </remarks>
/// <param name="id">The team identifier.</param>
/// <returns>The <see cref="Team"/> with the given identifier.</returns>
public IObservable<Team> Get(int id)
{
return _client.Get(id).ToObservable();
}

/// <summary>
/// Returns all <see cref="Team" />s for the current org.
/// </summary>
Expand Down Expand Up @@ -67,5 +80,18 @@ public IObservable<Unit> Delete(int id)
{
return _client.Delete(id).ToObservable();
}

/// <summary>
/// Gets whether the user with the given <paramref name="login"/>
/// is a member of the team with the given <paramref name="id"/>.
/// </summary>
/// <param name="id">The team to check.</param>
/// <param name="login">The user to check.</param>
/// <returns><see langword="true"/> if the user is a member of the team; <see langword="false"/> otherwise.</returns>
public IObservable<bool> IsMember(int id, string login)
{
return _client.IsMember(id, login).ToObservable();
}

}
}
123 changes: 123 additions & 0 deletions Octokit.Tests.Integration/Clients/TeamsClientTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using System.Linq;
using System.Net;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Octokit;
using Octokit.Internal;
using Octokit.Tests.Helpers;
using Octokit.Tests.Integration;
using Xunit;
using System;
using System.Collections.Generic;
using Xunit.Sdk;

public class TeamsClientTests
{
public class TheCreateMethod
{
[OrganizationTest]
public async Task FailsWhenNotAuthenticated()
{
var github = new GitHubClient(new ProductHeaderValue("OctokitTests"));
var newTeam = new NewTeam("Test");

var e = await AssertEx.Throws<AuthorizationException>(async
() => await github.Organization.Team.Create(Helper.Organization, newTeam));

Assert.Equal(HttpStatusCode.Unauthorized, e.StatusCode);
}

[OrganizationTest]
public async Task FailsWhenAuthenticatedWithBadCredentials()
{
var github = new GitHubClient(new ProductHeaderValue("OctokitTests"))
{
Credentials = new Credentials(Helper.Credentials.Login, "bad-password")
};
var newTeam = new NewTeam("Test");

var e = await AssertEx.Throws<AuthorizationException>(async
() => await github.Organization.Team.Create(Helper.Organization, newTeam));
Assert.Equal(HttpStatusCode.Unauthorized, e.StatusCode);
}

[OrganizationTest]
public async Task SucceedsWhenAuthenticated()
{
var github = new GitHubClient(new ProductHeaderValue("OctokitTests"))
{
Credentials = Helper.Credentials
};

var newTeam = new NewTeam(Guid.NewGuid().ToString());

var team = await github.Organization.Team.Create(Helper.Organization, newTeam);

Assert.Equal(newTeam.Name, team.Name);
}
}

public class TheIsMemberMethod
{
readonly Team team;

public TheIsMemberMethod()
{
var github = new GitHubClient(new ProductHeaderValue("OctokitTests")) { Credentials = Helper.Credentials };

team = github.Organization.Team.GetAll(Helper.Organization).Result.First();
}

//TODO: seems like a bug in Github: it's actually returning the membership information!
//Maybe because it's a public organization?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me test to see if I can understand the why of this endpoint

//[OrganizationTest]
public async Task FailsWhenNotAuthenticated()
{
var github = new GitHubClient(new ProductHeaderValue("OctokitTests"));

var e = await AssertEx.Throws<AuthorizationException>(async
() => await github.Organization.Team.IsMember(team.Id, Helper.UserName));

Assert.Equal(HttpStatusCode.Unauthorized, e.StatusCode);
}

[OrganizationTest]
public async Task FailsWhenAuthenticatedWithBadCredentials()
{
var github = new GitHubClient(new ProductHeaderValue("OctokitTests"))
{
Credentials = new Credentials(Helper.Credentials.Login, "bad-password")
};

var e = await AssertEx.Throws<AuthorizationException>(async
() => await github.Organization.Team.IsMember(team.Id, Helper.UserName));
Assert.Equal(HttpStatusCode.Unauthorized, e.StatusCode);
}

[OrganizationTest]
public async Task GetsIsMemberWhenAuthenticated()
{
var github = new GitHubClient(new ProductHeaderValue("OctokitTests"))
{
Credentials = Helper.Credentials
};

var isMember = await github.Organization.Team.IsMember(team.Id, Helper.UserName);

Assert.True(isMember);
}

[OrganizationTest]
public async Task GetsIsMemberFalseForNonMemberWhenAuthenticated()
{
var github = new GitHubClient(new ProductHeaderValue("OctokitTests"))
{
Credentials = Helper.Credentials
};

var isMember = await github.Organization.Team.IsMember(team.Id, "foo");

Assert.False(isMember);
}
}
}
11 changes: 11 additions & 0 deletions Octokit.Tests.Integration/Helper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using System.Net.Http.Headers;

namespace Octokit.Tests.Integration
Expand All @@ -9,6 +10,7 @@ public static class Helper
{
var githubUsername = Environment.GetEnvironmentVariable("OCTOKIT_GITHUBUSERNAME");
UserName = githubUsername;
Organization = Environment.GetEnvironmentVariable("OCTOKIT_GITHUBORGANIZATION");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you update the CONTRIBUTING.md docs to include this new field? Also, do you want to support running both user and org tests in the same context?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so. Even for organization tests, you always needs a valid user with ownership of the org.

Team tests don't work for users since it appears only orgs can own teams (just realized of this because I got errors trying with a user, and it's not doable on the website either)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONTRIBUTING.md doc updated!


var githubToken = Environment.GetEnvironmentVariable("OCTOKIT_OAUTHTOKEN");

Expand All @@ -23,7 +25,16 @@ public static class Helper
return new Credentials(githubUsername, githubPassword);
});

static Helper()
{
// Force reading of environment variables.
// This wasn't happening if UserName/Organization were
// retrieved before Credentials.
Debug.WriteIf(Credentials == null, "No credentials specified.");
}

public static string UserName { get; private set; }
public static string Organization { get; private set; }

public static Credentials Credentials { get { return _credentialsThunk.Value; }}

Expand Down
4 changes: 3 additions & 1 deletion Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@
<Compile Include="Clients\UserEmailsClientTests.cs" />
<Compile Include="Clients\FollowersClientTests.cs" />
<Compile Include="HttpClientAdapterTests.cs" />
<Compile Include="Clients\TeamsClientTests.cs" />
<Compile Include="IntegrationTestAttribute.cs" />
<Compile Include="Clients\IssuesClientTests.cs" />
<Compile Include="Clients\MiscellaneousClientTests.cs" />
<Compile Include="OrganizationTestAttribute.cs" />
<Compile Include="Reactive\ObservableIssuesClientTests.cs" />
<Compile Include="Reactive\ObservableMilestonesClientTests.cs" />
<Compile Include="Reactive\ObservableRepositoriesClientTests.cs" />
Expand Down Expand Up @@ -121,4 +123,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
19 changes: 19 additions & 0 deletions Octokit.Tests.Integration/OrganizationTestAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Collections.Generic;
using Xunit.Sdk;

namespace Octokit.Tests.Integration
{
public class OrganizationTestAttribute : IntegrationTestAttribute
{
protected override IEnumerable<ITestCommand> EnumerateTestCommands(IMethodInfo testMethod)
{
if (Helper.Organization == null)
return new[]
{
new SkipCommand(testMethod, MethodUtility.GetDisplayName(testMethod), "Automation settings not configured. Please set the OCTOKIT_GITHUBORGANIZATION environment variable to a GitHub organization owned by the test account specified in OCTOKIT_GITHUBUSERNAME.")
};
else
return base.EnumerateTestCommands(testMethod);
}
}
}
20 changes: 20 additions & 0 deletions Octokit.Tests/Clients/TeamsClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,25 @@ public void RequestsTheCorrectUrl()
}
}

public class TheIsMemberMethod
{
[Fact]
public void EnsuresNonNullLogin()
{
var connection = Substitute.For<IApiConnection>();
var client = new TeamsClient(connection);

AssertEx.Throws<ArgumentNullException>(() => client.IsMember(1, null));
}

[Fact]
public void EnsuresNonEmptyLogin()
{
var connection = Substitute.For<IApiConnection>();
var client = new TeamsClient(connection);

AssertEx.Throws<ArgumentException>(() => client.IsMember(1, ""));
}
}
}
}
21 changes: 21 additions & 0 deletions Octokit/Clients/ITeamsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
#endif
using System.Threading.Tasks;
using System.Diagnostics.CodeAnalysis;

namespace Octokit
{
Expand All @@ -13,6 +14,18 @@ namespace Octokit
/// </remarks>
public interface ITeamsClient
{
/// <summary>
/// Gets a single <see cref="Team"/> by identifier.
/// </summary>
/// <remarks>
/// https://developer.github.com/v3/orgs/teams/#get-team
/// </remarks>
/// <param name="id">The team identifier.</param>
/// <returns>The <see cref="Team"/> with the given identifier.</returns>
[SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get",
Justification = "Method makes a network request")]
Task<Team> Get(int id);

/// <summary>
/// Returns all <see cref="Team" />s for the current org.
/// </summary>
Expand Down Expand Up @@ -41,5 +54,13 @@ public interface ITeamsClient
/// <returns></returns>
Task Delete(int id);

/// <summary>
/// Gets whether the user with the given <paramref name="login"/>
/// is a member of the team with the given <paramref name="id"/>.
/// </summary>
/// <param name="id">The team to check.</param>
/// <param name="login">The user to check.</param>
/// <returns><see langword="true"/> if the user is a member of the team; <see langword="false"/> otherwise.</returns>
Task<bool> IsMember(int id, string login);
}
}
Loading