Implemented GetReadme API endpoint

This commit is contained in:
Haacked
2013-01-28 09:50:09 -08:00
parent 041d58a4b7
commit b435972616
9 changed files with 151 additions and 55 deletions
@@ -51,7 +51,6 @@
<ItemGroup>
<Compile Include="RepositoriesEndpointTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Readme.cs" />
<Compile Include="UsersEndpointTests.cs" />
</ItemGroup>
<ItemGroup>
-54
View File
@@ -1,54 +0,0 @@
using System.Threading.Tasks;
using Octopi.Http;
namespace Octopi.Tests
{
public class Readme
{
public Readme()
{
// create an anonymous client
var client = new GitHubClient();
// create a client with basic auth
client = new GitHubClient { Credentials = new Credentials("xapitestaccountx", "octocat11") };
// create a client with an oauth token
client = new GitHubClient { Credentials = new Credentials("ouathtoken") };
}
public async Task UserApi()
{
var github = new GitHubClient { Credentials = new Credentials("xapitestaccountx", "octocat11") };
// Get the authenticated user
var user = await github.User.Current();
// Get a user by username
user = await github.User.Get("tclem");
// Update a user
user = await github.User.Update(new UserUpdate { Name = "octolish" });
}
public async Task AuthorizationsApi()
{
var github = new GitHubClient { Credentials = new Credentials("xapitestaccountx", "octocat11") };
// create a new auth
var auth = await github.Authorization.CreateAsync(new AuthorizationUpdate { Note = "integration test", NoteUrl = "http://example.com", Scopes = new[] { "public_repo" } });
// list all authorizations for the authenticated user
var auths = await github.Authorization.GetAll();
// get a specific auth
auth = await github.Authorization.GetAsync(auth.Id);
// update an auth
auth = await github.Authorization.UpdateAsync(auth.Id, new AuthorizationUpdate { Note = "integration test update" });
// delete a specific auth
await github.Authorization.DeleteAsync(auth.Id);
}
}
}
@@ -38,5 +38,24 @@ namespace Octopi.Tests.Integration
repositories.Count.Should().BeGreaterThan(80);
}
}
public class TheGetReadmeMethod
{
[Fact]
public async Task ReturnsReadmeForOctopi()
{
var github = new GitHubClient
{
Credentials = new Credentials("xapitestaccountx", "octocat11")
};
// TODO: Change this to request github/octopi once we make this OSS.
var readme = await github.Repository.GetReadme("haacked", "seegit");
readme.Name.Should().Be("README.md");
var readMeHtml = await readme.GetHtmlContent();
readMeHtml.Should().Contain(@"<div id=""readme""");
readMeHtml.Should().Contain("<p><strong>WARNING: This is some haacky code.");
}
}
}
}
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using NSubstitute;
@@ -130,5 +131,48 @@ namespace Octopi.Tests
.GetAsync<List<Repository>>(Arg.Is<Uri>(u => u.ToString() == "/orgs/orgName/repos"));
}
}
public class TheGetReadmeMethod
{
[Fact]
public async Task ReturnsReadme()
{
var links = new Dictionary<string, Uri>();
var scopes = new List<string>();
string encodedContent = Convert.ToBase64String(Encoding.UTF8.GetBytes("Hello world"));
IResponse<ReadmeResponse> apiResponse = new ApiResponse<ReadmeResponse>
{
ApiInfo = new ApiInfo(links, scopes, scopes, "", 1, 1),
BodyAsObject = new ReadmeResponse
{
Content = encodedContent,
Encoding = "base64",
Name = "README.md",
Url = "https://github.example.com/readme.md",
HtmlUrl = "https://github.example.com/readme"
}
};
IResponse<string> htmlResponse = new ApiResponse<string>
{
Body = "<html></html>"
};
var connection = Substitute.For<IConnection>();
connection.GetAsync<ReadmeResponse>(Args.Uri).Returns(Task.FromResult(apiResponse));
connection.GetHtml(Args.Uri).Returns(Task.FromResult(htmlResponse));
var reposEndpoint = new RepositoriesEndpoint(connection);
var readme = await reposEndpoint.GetReadme("fake", "repo");
readme.Name.Should().Be("README.md");
connection.Received()
.GetAsync<ReadmeResponse>(Arg.Is<Uri>(u => u.ToString() == "/repos/fake/repo/readme"));
connection.DidNotReceive()
.GetHtml(Arg.Is<Uri>(u => u.ToString() == "https://github.example.com/readme"));
var htmlReadme = await readme.GetHtmlContent();
htmlReadme.Should().Be("<html></html>");
connection.Received()
.GetHtml(Arg.Is<Uri>(u => u.ToString() == "https://github.example.com/readme"));
}
}
}
}
+11
View File
@@ -48,5 +48,16 @@ namespace Octopi.Endpoints
return await GetAll(endpoint);
}
public async Task<Readme> GetReadme(string owner, string name)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");
var endpoint = new Uri(string.Format("/repos/{0}/{1}/readme", owner, name), UriKind.Relative);
var response = await Connection.GetAsync<ReadmeResponse>(endpoint);
var readmeResponse = response.BodyAsObject;
return new Readme(readmeResponse, Connection);
}
}
}
+48
View File
@@ -1,5 +1,8 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Threading.Tasks;
using Octopi.Http;
namespace Octopi
{
@@ -287,6 +290,51 @@ namespace Octopi
public string Url { get; set; }
}
internal class ReadmeResponse
{
public string Content { get; set; }
public string Name { get; set; }
public string HtmlUrl { get; set; }
public string Url { get; set; }
public string Encoding { get; set; }
}
public class Readme
{
readonly Lazy<Task<string>> htmlContent;
internal Readme(ReadmeResponse response, IConnection connection)
{
Ensure.ArgumentNotNull(response, "response");
Name = response.Name;
Url = new Uri(response.Url);
HtmlUrl = new Uri(response.HtmlUrl);
if (response.Encoding.Equals("base64", StringComparison.OrdinalIgnoreCase))
{
var contentAsBytes = Convert.FromBase64String(response.Content);
Content = Encoding.UTF8.GetString(contentAsBytes, 0, contentAsBytes.Length);
}
htmlContent = new Lazy<Task<string>>(async () =>
{
var resp = await connection.GetHtml(HtmlUrl);
return resp.Body;
});
}
public string Content { get; private set; }
public string Name { get; private set; }
public Uri HtmlUrl { get; private set; }
public Uri Url { get; private set; }
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
Justification = "Makse a network request")]
public async Task<string> GetHtmlContent()
{
return await htmlContent.Value;
}
}
public class SshKey
{
/// <summary>
+19
View File
@@ -59,6 +59,16 @@ namespace Octopi.Http
});
}
public async Task<IResponse<string>> GetHtml(Uri endpoint)
{
return await GetHtml(new Request
{
Method = HttpMethod.Get,
BaseAddress = BaseAddress,
Endpoint = endpoint
});
}
public async Task<IResponse<T>> PatchAsync<T>(Uri endpoint, object body)
{
return await Run<T>(new Request
@@ -109,6 +119,15 @@ namespace Octopi.Http
}
}
async Task<IResponse<string>> GetHtml(IRequest request)
{
authenticator.Apply(request);
request.Headers.Add("Accept", "application/vnd.github.html");
var response = await httpClient.Send<string>(request);
apiInfoParser.ParseApiHttpHeaders(response);
return response;
}
async Task<IResponse<T>> Run<T>(IRequest request)
{
jsonPipeline.SerializeRequest(request);
+2
View File
@@ -6,6 +6,8 @@ namespace Octopi.Http
{
public interface IConnection
{
Task<IResponse<string>> GetHtml(Uri endpoint);
Task<IResponse<T>> GetAsync<T>(Uri endpoint);
Task<IResponse<T>> PatchAsync<T>(Uri endpoint, object body);
Task<IResponse<T>> PostAsync<T>(Uri endpoint, object body);
+8
View File
@@ -48,5 +48,13 @@ namespace Octopi
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
Justification = "Makes a network request")]
Task<IReadOnlyCollection<Repository>> GetAllForOrg(string organization);
/// <summary>
/// Returns the HTML rendered README.
/// </summary>
/// <param name="owner">The owner of the repository.</param>
/// <param name="name">The name of the repository.</param>
/// <returns></returns>
Task<Readme> GetReadme(string owner, string name);
}
}