From 733a580c4098f30606e8c6aff101a619ad13610b Mon Sep 17 00:00:00 2001 From: Robert Mills Date: Sun, 24 Nov 2013 23:01:33 -0500 Subject: [PATCH 1/8] Support to Create Gists --- .../Clients/GistsClientTests.cs | 111 +++++++++++++++++- Octokit.Tests/Clients/GistsClientTests.cs | 25 ++++ Octokit/Clients/GistsClient.cs | 26 +++- Octokit/Clients/IGistsClient.cs | 9 ++ Octokit/Helpers/ApiUrls.cs | 10 +- Octokit/Models/Request/NewGist.cs | 23 ++++ Octokit/Models/Request/NewGistFile.cs | 10 ++ Octokit/Octokit-Mono.csproj | 2 + Octokit/Octokit-MonoAndroid.csproj | 2 + Octokit/Octokit-Monotouch.csproj | 3 + Octokit/Octokit-netcore45.csproj | 2 + Octokit/Octokit.csproj | 2 + 12 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 Octokit/Models/Request/NewGist.cs create mode 100644 Octokit/Models/Request/NewGistFile.cs diff --git a/Octokit.Tests.Integration/Clients/GistsClientTests.cs b/Octokit.Tests.Integration/Clients/GistsClientTests.cs index a5a49411..1265ad10 100644 --- a/Octokit.Tests.Integration/Clients/GistsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/GistsClientTests.cs @@ -3,10 +3,13 @@ using System.Threading.Tasks; using Octokit; using Octokit.Tests.Integration; using Xunit; +using System.Collections.Generic; +using System.Collections.ObjectModel; public class GistsClientTests { readonly IGistsClient _fixture; + readonly string testGistId = "6305249"; public GistsClientTests() { @@ -21,7 +24,113 @@ public class GistsClientTests [IntegrationTest] public async Task CanGetGist() { - var retrieved = await _fixture.Get("6305249"); + var retrieved = await _fixture.Get(testGistId); Assert.NotNull(retrieved); } + + [IntegrationTest] + public async Task CanCreateEditAndDeleteAGist() + { + var newGist = new NewGist(); + newGist.Description = "my new gist"; + newGist.Public = true; + + newGist.Files.Add("myGistTestFile.cs", "new GistsClient(connection).Create();"); + + var createdGist = await _fixture.Create(newGist); + + Assert.NotNull(createdGist); + Assert.Equal(newGist.Description, createdGist.Description); + Assert.Equal(newGist.Public, createdGist.Public); + + var gistUpdate = new GistUpdate(); + gistUpdate.Description = "my newly updated gist"; + var gistFileUpdate = new GistFileUpdate + { + NewFileName = "myNewGistTestFile.cs", + Content = "new GistsClient(connection).Edit();" + }; + + gistUpdate.Files.Add("myGistTestFile.cs", gistFileUpdate); + + var updatedGist = await _fixture.Edit(createdGist.Id, gistUpdate); + + Assert.NotNull(updatedGist); + Assert.Equal(updatedGist.Description, gistUpdate.Description); + + Assert.DoesNotThrow(async () => { await _fixture.Delete(createdGist.Id); }); + } + + [IntegrationTest] + public async Task CanStarAndUnstarAGist() + { + Assert.DoesNotThrow(async () => { await _fixture.Star(testGistId); }); + + bool isStarredTrue = await _fixture.IsStarred(testGistId); + Assert.True(isStarredTrue); + + Assert.DoesNotThrow(async () => { await _fixture.Unstar(testGistId); }); + + bool isStarredFalse = await _fixture.IsStarred(testGistId); + Assert.False(isStarredFalse); + } + + [IntegrationTest] + public async Task CanForkAGist() + { + var forkedGist = await _fixture.Fork(testGistId); + + Assert.NotNull(forkedGist); + + await _fixture.Delete(forkedGist.Id); + } + + [IntegrationTest] + public async Task CanListGists() + { + // Time is tricky between local and remote, be leinent + var startTime = DateTimeOffset.Now.Subtract(TimeSpan.FromHours(1)); + var newGist = new NewGist(); + newGist.Description = "my new gist"; + newGist.Public = true; + + newGist.Files.Add("myGistTestFile.cs", "new GistsClient(connection).Create();"); + + var createdGist = await _fixture.Create(newGist); + + // Test get all Gists + var gists = await _fixture.GetAll(); + Assert.NotNull(gists); + + // Test get all Gists since startTime + gists = await _fixture.GetAll(startTime); + + Assert.NotNull(gists); + Assert.True(gists.Count > 0); + + // Make sure we can successfully request gists for another user + Assert.DoesNotThrow(async () => { await _fixture.GetAllForUser("FakeHaacked"); }); + Assert.DoesNotThrow(async () => { await _fixture.GetAllForUser("FakeHaacked", startTime); }); + + // Test public gists + var publicGists = await _fixture.GetAllPublic(); + Assert.True(publicGists.Count > 1); + + var publicGistsSinceStartTime = await _fixture.GetAllPublic(startTime); + Assert.True(publicGistsSinceStartTime.Count > 0); + + // Test starred gists + await _fixture.Star(createdGist.Id); + var starredGists = await _fixture.GetAllStarred(); + + Assert.NotNull(starredGists); + Assert.True(starredGists.Any(x => x.Id == createdGist.Id)); + + var starredGistsSinceStartTime = await _fixture.GetAllStarred(startTime); + Assert.NotNull(starredGistsSinceStartTime); + Assert.True(starredGistsSinceStartTime.Any(x => x.Id == createdGist.Id)); + + await _fixture.Delete(createdGist.Id); + } +} } \ No newline at end of file diff --git a/Octokit.Tests/Clients/GistsClientTests.cs b/Octokit.Tests/Clients/GistsClientTests.cs index ad3f6d76..ffe07e85 100644 --- a/Octokit.Tests/Clients/GistsClientTests.cs +++ b/Octokit.Tests/Clients/GistsClientTests.cs @@ -2,6 +2,8 @@ using NSubstitute; using Octokit; using Xunit; +using System.Collections.ObjectModel; +using System.Collections.Generic; public class GistsClientTests { @@ -19,6 +21,29 @@ public class GistsClientTests } } + public class TheCreateMethod + { + [Fact] + public void PostsToTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + var newGist = new NewGist(); + newGist.Description = "my new gist"; + newGist.Public = true; + + var gistFiles = new Dictionary(); + gistFiles.Add("myGistTestFile.cs", new NewGistFile { Content = "new GistsClient(connection).Create();"}); + + newGist.Files = gistFiles; + + client.Create(newGist); + + connection.Received().Post(Arg.Is(u => u.ToString() == "gists"), Arg.Any()); + } + } + public class TheCtor { [Fact] diff --git a/Octokit/Clients/GistsClient.cs b/Octokit/Clients/GistsClient.cs index 44a62b69..a53ec72b 100644 --- a/Octokit/Clients/GistsClient.cs +++ b/Octokit/Clients/GistsClient.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; namespace Octokit { @@ -33,5 +34,28 @@ namespace Octokit { return ApiConnection.Get(ApiUrls.Gist(id)); } + + /// + /// Creates a new gist + /// + /// + /// http://developer.github.com/v3/gists/#create-a-gist + /// + /// The new gist to create + public Task Create(NewGist newGist) + { + Ensure.ArgumentNotNull(newGist, "newGist"); + + //Required to create anonymous object to match signature of files hash. Allowing the serializer + //to handle Dictionary will fail to match. + var filesAsJsonObject = new JsonObject(); + foreach(var kvp in newGist.Files) + { + filesAsJsonObject.Add(new KeyValuePair(kvp.Key, kvp.Value)); + } + var gist = new { Description = newGist.Description, Public = newGist.Public, Files = filesAsJsonObject }; + + return ApiConnection.Post(ApiUrls.Gist(), gist); + } } } \ No newline at end of file diff --git a/Octokit/Clients/IGistsClient.cs b/Octokit/Clients/IGistsClient.cs index 3c1787a9..72571f19 100644 --- a/Octokit/Clients/IGistsClient.cs +++ b/Octokit/Clients/IGistsClient.cs @@ -23,5 +23,14 @@ namespace Octokit [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] Task Get(string id); + + /// + /// Creates a new gist + /// + /// + /// http://developer.github.com/v3/gists/#create-a-gist + /// + /// The new gist to create + Task Create(NewGist newGist); } } \ No newline at end of file diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index d7dd4a54..7a9770fc 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -602,7 +602,15 @@ namespace Octokit /// public static Uri Feeds() { - return "feeds".FormatUri(); + return "feeds".FormatUri (); + } + + /// + /// Returns the that returns the list of public gists. + /// + public static Uri Gist() + { + return "gists".FormatUri(); } /// diff --git a/Octokit/Models/Request/NewGist.cs b/Octokit/Models/Request/NewGist.cs new file mode 100644 index 00000000..b5093bc6 --- /dev/null +++ b/Octokit/Models/Request/NewGist.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +namespace Octokit +{ + public class NewGist + { + /// + /// The description of the gist. + /// + public string Description { get; set; } + + /// + /// Indicates whether the gist is public + /// + public bool Public { get; set; } + + /// + /// Files that make up this gist using the key as filename + /// + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public IDictionary Files { get; set; } + } +} \ No newline at end of file diff --git a/Octokit/Models/Request/NewGistFile.cs b/Octokit/Models/Request/NewGistFile.cs new file mode 100644 index 00000000..5faaa1ca --- /dev/null +++ b/Octokit/Models/Request/NewGistFile.cs @@ -0,0 +1,10 @@ +namespace Octokit +{ + public class NewGistFile + { + /// + /// The content of the file. + /// + public string Content { get; set; } + } +} \ No newline at end of file diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj index 62434eae..38ec47da 100644 --- a/Octokit/Octokit-Mono.csproj +++ b/Octokit/Octokit-Mono.csproj @@ -95,6 +95,8 @@ + + diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj index 2f28263d..8e966115 100644 --- a/Octokit/Octokit-MonoAndroid.csproj +++ b/Octokit/Octokit-MonoAndroid.csproj @@ -308,6 +308,8 @@ + + \ No newline at end of file diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj index 96608bc0..fdabd977 100644 --- a/Octokit/Octokit-Monotouch.csproj +++ b/Octokit/Octokit-Monotouch.csproj @@ -303,6 +303,9 @@ + + + \ No newline at end of file diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj index 09841236..1ada8759 100644 --- a/Octokit/Octokit-netcore45.csproj +++ b/Octokit/Octokit-netcore45.csproj @@ -176,6 +176,8 @@ + + diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index 5d0559fc..b43962d3 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -99,6 +99,8 @@ + + From 616ac3b4255fb114aaf3fd1781403541fcdbb41d Mon Sep 17 00:00:00 2001 From: Robert Mills Date: Mon, 25 Nov 2013 00:11:22 -0500 Subject: [PATCH 2/8] Remove need for NewGistFile.cs --- Octokit.Tests/Clients/GistsClientTests.cs | 4 ++-- Octokit/Clients/GistsClient.cs | 14 ++++++++++---- Octokit/Models/Request/NewGist.cs | 5 +++-- Octokit/Models/Request/NewGistFile.cs | 10 ---------- Octokit/Octokit-Mono.csproj | 1 - Octokit/Octokit-MonoAndroid.csproj | 1 - Octokit/Octokit-Monotouch.csproj | 4 ++-- Octokit/Octokit-netcore45.csproj | 1 - Octokit/Octokit.csproj | 1 - 9 files changed, 17 insertions(+), 24 deletions(-) delete mode 100644 Octokit/Models/Request/NewGistFile.cs diff --git a/Octokit.Tests/Clients/GistsClientTests.cs b/Octokit.Tests/Clients/GistsClientTests.cs index ffe07e85..4e89758b 100644 --- a/Octokit.Tests/Clients/GistsClientTests.cs +++ b/Octokit.Tests/Clients/GistsClientTests.cs @@ -33,8 +33,8 @@ public class GistsClientTests newGist.Description = "my new gist"; newGist.Public = true; - var gistFiles = new Dictionary(); - gistFiles.Add("myGistTestFile.cs", new NewGistFile { Content = "new GistsClient(connection).Create();"}); + var gistFiles = new Dictionary(); + gistFiles.Add("myGistTestFile.cs", "new GistsClient(connection).Create();"); newGist.Files = gistFiles; diff --git a/Octokit/Clients/GistsClient.cs b/Octokit/Clients/GistsClient.cs index a53ec72b..6429417f 100644 --- a/Octokit/Clients/GistsClient.cs +++ b/Octokit/Clients/GistsClient.cs @@ -46,14 +46,20 @@ namespace Octokit { Ensure.ArgumentNotNull(newGist, "newGist"); - //Required to create anonymous object to match signature of files hash. Allowing the serializer - //to handle Dictionary will fail to match. + //Required to create anonymous object to match signature of files hash. + // Allowing the serializer to handle Dictionary + // will fail to match. var filesAsJsonObject = new JsonObject(); foreach(var kvp in newGist.Files) { - filesAsJsonObject.Add(new KeyValuePair(kvp.Key, kvp.Value)); + filesAsJsonObject.Add(kvp.Key, new { Content = kvp.Value }); } - var gist = new { Description = newGist.Description, Public = newGist.Public, Files = filesAsJsonObject }; + + var gist = new { + Description = newGist.Description, + Public = newGist.Public, + Files = filesAsJsonObject + }; return ApiConnection.Post(ApiUrls.Gist(), gist); } diff --git a/Octokit/Models/Request/NewGist.cs b/Octokit/Models/Request/NewGist.cs index b5093bc6..bef676ed 100644 --- a/Octokit/Models/Request/NewGist.cs +++ b/Octokit/Models/Request/NewGist.cs @@ -15,9 +15,10 @@ namespace Octokit public bool Public { get; set; } /// - /// Files that make up this gist using the key as filename + /// Files that make up this gist using the key as Filename + /// and value as Content /// [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] - public IDictionary Files { get; set; } + public IDictionary Files { get; set; } } } \ No newline at end of file diff --git a/Octokit/Models/Request/NewGistFile.cs b/Octokit/Models/Request/NewGistFile.cs deleted file mode 100644 index 5faaa1ca..00000000 --- a/Octokit/Models/Request/NewGistFile.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Octokit -{ - public class NewGistFile - { - /// - /// The content of the file. - /// - public string Content { get; set; } - } -} \ No newline at end of file diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj index 38ec47da..0ba47a12 100644 --- a/Octokit/Octokit-Mono.csproj +++ b/Octokit/Octokit-Mono.csproj @@ -96,7 +96,6 @@ - diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj index 8e966115..9c36915d 100644 --- a/Octokit/Octokit-MonoAndroid.csproj +++ b/Octokit/Octokit-MonoAndroid.csproj @@ -309,7 +309,6 @@ - \ No newline at end of file diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj index fdabd977..1fb714a2 100644 --- a/Octokit/Octokit-Monotouch.csproj +++ b/Octokit/Octokit-Monotouch.csproj @@ -248,6 +248,7 @@ +<<<<<<< HEAD @@ -303,9 +304,8 @@ - + - \ No newline at end of file diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj index 1ada8759..c52fd9d8 100644 --- a/Octokit/Octokit-netcore45.csproj +++ b/Octokit/Octokit-netcore45.csproj @@ -177,7 +177,6 @@ - diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index b43962d3..c2fe81e0 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -100,7 +100,6 @@ - From 9d6345d0eabcef5ea28f358b0a04703480d7b815 Mon Sep 17 00:00:00 2001 From: Robert Mills Date: Thu, 28 Nov 2013 17:50:14 -0500 Subject: [PATCH 3/8] Initialize Files Initialize Files to reduce needless setup to create a gist. --- Octokit.Tests/Clients/GistsClientTests.cs | 5 +---- Octokit/Models/Request/NewGist.cs | 6 ++++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Octokit.Tests/Clients/GistsClientTests.cs b/Octokit.Tests/Clients/GistsClientTests.cs index 4e89758b..2554b95e 100644 --- a/Octokit.Tests/Clients/GistsClientTests.cs +++ b/Octokit.Tests/Clients/GistsClientTests.cs @@ -33,10 +33,7 @@ public class GistsClientTests newGist.Description = "my new gist"; newGist.Public = true; - var gistFiles = new Dictionary(); - gistFiles.Add("myGistTestFile.cs", "new GistsClient(connection).Create();"); - - newGist.Files = gistFiles; + newGist.Files.Add("myGistTestFile.cs", "new GistsClient(connection).Create();"); client.Create(newGist); diff --git a/Octokit/Models/Request/NewGist.cs b/Octokit/Models/Request/NewGist.cs index bef676ed..9bdd6d35 100644 --- a/Octokit/Models/Request/NewGist.cs +++ b/Octokit/Models/Request/NewGist.cs @@ -1,9 +1,15 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; + namespace Octokit { public class NewGist { + public NewGist() + { + Files = new Dictionary(); + } + /// /// The description of the gist. /// From f644376d528a95164ece3debe949e66e261b02cf Mon Sep 17 00:00:00 2001 From: Robert Mills Date: Mon, 2 Dec 2013 20:08:04 -0500 Subject: [PATCH 4/8] Remove suppress attribute --- Octokit/Models/Request/NewGist.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Octokit/Models/Request/NewGist.cs b/Octokit/Models/Request/NewGist.cs index 9bdd6d35..66726721 100644 --- a/Octokit/Models/Request/NewGist.cs +++ b/Octokit/Models/Request/NewGist.cs @@ -24,7 +24,6 @@ namespace Octokit /// Files that make up this gist using the key as Filename /// and value as Content /// - [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] - public IDictionary Files { get; set; } + public IDictionary Files { get; private set; } } } \ No newline at end of file From c82498a439d9160c953cabbb328c0b7026ed08f1 Mon Sep 17 00:00:00 2001 From: Robert Mills Date: Mon, 2 Dec 2013 20:08:30 -0500 Subject: [PATCH 5/8] Delete Gist Add ability to delete gist with test cases. --- Octokit.Tests/Clients/GistsClientTests.cs | 26 +++++++++++++++++++++++ Octokit/Clients/GistsClient.cs | 14 ++++++++++++ Octokit/Clients/IGistsClient.cs | 9 ++++++++ 3 files changed, 49 insertions(+) diff --git a/Octokit.Tests/Clients/GistsClientTests.cs b/Octokit.Tests/Clients/GistsClientTests.cs index 2554b95e..2477fe5e 100644 --- a/Octokit.Tests/Clients/GistsClientTests.cs +++ b/Octokit.Tests/Clients/GistsClientTests.cs @@ -4,6 +4,8 @@ using Octokit; using Xunit; using System.Collections.ObjectModel; using System.Collections.Generic; +using System.Threading.Tasks; +using Octokit.Tests.Helpers; public class GistsClientTests { @@ -41,6 +43,30 @@ public class GistsClientTests } } + public class TheDeleteMethod + { + [Fact] + public void PostsToTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + client.Delete("1"); + + connection.Received().Delete(Arg.Is(u => u.ToString() == "gists/1")); + } + + [Fact] + public async Task EnsuresArgumentsNotNull() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + AssertEx.Throws(async () => await + client.Delete(null)); + } + } + public class TheCtor { [Fact] diff --git a/Octokit/Clients/GistsClient.cs b/Octokit/Clients/GistsClient.cs index 6429417f..7dc92efc 100644 --- a/Octokit/Clients/GistsClient.cs +++ b/Octokit/Clients/GistsClient.cs @@ -63,5 +63,19 @@ namespace Octokit return ApiConnection.Post(ApiUrls.Gist(), gist); } + + /// + /// Deletes a gist + /// + /// + /// http://developer.github.com/v3/gists/#delete-a-gist + /// + /// The id of the gist + public Task Delete(string id) + { + Ensure.ArgumentNotNull(id, "id"); + + return ApiConnection.Delete(ApiUrls.Gist(id)); + } } } \ No newline at end of file diff --git a/Octokit/Clients/IGistsClient.cs b/Octokit/Clients/IGistsClient.cs index 72571f19..587d0b4f 100644 --- a/Octokit/Clients/IGistsClient.cs +++ b/Octokit/Clients/IGistsClient.cs @@ -32,5 +32,14 @@ namespace Octokit /// /// The new gist to create Task Create(NewGist newGist); + + /// + /// Deletes a gist + /// + /// + /// http://developer.github.com/v3/gists/#delete-a-gist + /// + /// The id of the gist + Task Delete(string id); } } \ No newline at end of file From 91db7e59e9fa06b5202e48ee3309f4d96b464b3b Mon Sep 17 00:00:00 2001 From: Robert Mills Date: Mon, 2 Dec 2013 22:44:28 -0500 Subject: [PATCH 6/8] Complete Gist API --- Octokit.Tests/Clients/GistsClientTests.cs | 176 +++++++++++++++++++ Octokit/Clients/GistsClient.cs | 200 +++++++++++++++++++++- Octokit/Clients/IGistsClient.cs | 123 ++++++++++++- Octokit/Helpers/ApiUrls.cs | 25 +++ Octokit/Models/Request/GistRequest.cs | 15 ++ Octokit/Models/Request/GistUpdate.cs | 23 +++ Octokit/Octokit-Mono.csproj | 2 + Octokit/Octokit-netcore45.csproj | 2 + Octokit/Octokit.csproj | 2 + 9 files changed, 566 insertions(+), 2 deletions(-) create mode 100644 Octokit/Models/Request/GistRequest.cs create mode 100644 Octokit/Models/Request/GistUpdate.cs diff --git a/Octokit.Tests/Clients/GistsClientTests.cs b/Octokit.Tests/Clients/GistsClientTests.cs index 2477fe5e..48a1bd6c 100644 --- a/Octokit.Tests/Clients/GistsClientTests.cs +++ b/Octokit.Tests/Clients/GistsClientTests.cs @@ -23,6 +23,107 @@ public class GistsClientTests } } + public class TheGetAllMethods + { + [Fact] + public void RequestsCorrectGetAllUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + client.GetAll(); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists"), null); + } + + [Fact] + public void RequestsCorrectGetAllWithSinceUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + DateTimeOffset since = DateTimeOffset.Now; + client.GetAll(since); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists"), + Arg.Is>(x => x.ContainsKey("since"))); + } + + [Fact] + public void RequestsCorrectGetAllPublicUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + client.GetAllPublic(); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists/public"), + Arg.Is>(x => x.ContainsKey("since"))); + } + + [Fact] + public void RequestsCorrectGetAllPublicWithSinceUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + DateTimeOffset since = DateTimeOffset.Now; + client.GetAllPublic(since); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists/public"), + Arg.Is>(x => x.ContainsKey("since"))); + } + + [Fact] + public void RequestsCorrectGetAllStarredUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + client.GetAllStarred(); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists/starred"), + Arg.Is>(x => x.ContainsKey("since"))); + } + + [Fact] + public void RequestsCorrectGetAllStarredWithSinceUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + DateTimeOffset since = DateTimeOffset.Now; + client.GetAllStarred(since); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists/starred"), + Arg.Is>(x => x.ContainsKey("since"))); + } + + [Fact] + public void RequestsCorrectGetGistsForAUserUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + client.GetAllForUser("octokit"); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "users/octokit/gists"), + Arg.Is>(x => x.ContainsKey("since"))); + } + + [Fact] + public void RequestsCorrectGetGistsForAUserWithSinceUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + DateTimeOffset since = DateTimeOffset.Now; + client.GetAllForUser("octokit", since); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "users/octokit/gists"), + Arg.Is>(x => x.ContainsKey("since"))); + } + } + public class TheCreateMethod { [Fact] @@ -67,6 +168,81 @@ public class GistsClientTests } } + public class TheStarMethods + { + [Fact] + public void RequestsCorrectStarUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + client.Star("1"); + + connection.Received().Get(Arg.Is(u => u.ToString() == "gists/1/star"), null); + } + + [Fact] + public void RequestsCorrectUnstarUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + client.Unstar("1"); + + connection.Received().Get(Arg.Is(u => u.ToString() == "gists/1/star"), null); + } + + [Fact] + public void RequestsCorrectCheckIfStarredUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + client.IsStarred("1"); + + connection.Received().Get(Arg.Is(u => u.ToString() == "gists/1/star"), null); + } + } + + public class TheForkMethod + { + [Fact] + public void RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + client.Fork("1"); + + connection.Received().Post(Arg.Is(u => u.ToString() == "gists/1/fork"), + Arg.Is(o => o == null)); + } + } + + public class TheEditMethod + { + [Fact] + public void PostsToTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + var updateGist = new GistUpdate(); + updateGist.Description = "my newly updated gist"; + var gistFileUpdate = new GistFileUpdate + { + NewFileName = "myNewGistTestFile.cs", + Content = "new GistsClient(connection).Edit();" + }; + + updateGist.Files.Add("myGistTestFile.cs", gistFileUpdate); + + client.Edit("1", updateGist); + + connection.Received().Post(Arg.Is(u => u.ToString() == "gists/1"), Arg.Any()); + } + } + public class TheCtor { [Fact] diff --git a/Octokit/Clients/GistsClient.cs b/Octokit/Clients/GistsClient.cs index 7dc92efc..ae816607 100644 --- a/Octokit/Clients/GistsClient.cs +++ b/Octokit/Clients/GistsClient.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Net; using System.Threading.Tasks; namespace Octokit @@ -64,6 +66,18 @@ namespace Octokit return ApiConnection.Post(ApiUrls.Gist(), gist); } + /// + /// Creates a fork of a gist + /// + /// + /// http://developer.github.com/v3/gists/#fork-a-gist + /// + /// The id of the gist to fork + public Task Fork(string id) + { + return ApiConnection.Post(ApiUrls.ForkGist(id), new object()); + } + /// /// Deletes a gist /// @@ -77,5 +91,189 @@ namespace Octokit return ApiConnection.Delete(ApiUrls.Gist(id)); } + + /// + /// List the authenticated user’s gists or if called anonymously, + /// this will return all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + public Task> GetAll() + { + return ApiConnection.GetAll(ApiUrls.Gist()); + } + + /// + /// List the authenticated user’s gists or if called anonymously, + /// this will return all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + public Task> GetAll(DateTimeOffset since) + { + var request = new GistRequest(since); + return ApiConnection.GetAll(ApiUrls.Gist(), request.ToParametersDictionary()); + } + + /// + /// Lists all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + public Task> GetAllPublic() + { + return ApiConnection.GetAll(ApiUrls.PublicGists()); + } + + /// + /// Lists all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + public Task> GetAllPublic(DateTimeOffset since) + { + var request = new GistRequest(since); + return ApiConnection.GetAll(ApiUrls.PublicGists(), request.ToParametersDictionary()); + } + + /// + /// List the authenticated user’s starred gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + public Task> GetAllStarred() + { + return ApiConnection.GetAll(ApiUrls.StarredGists()); + } + + /// + /// List the authenticated user’s starred gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + public Task> GetAllStarred(DateTimeOffset since) + { + var request = new GistRequest(since); + return ApiConnection.GetAll(ApiUrls.StarredGists(), request.ToParametersDictionary()); + } + + /// + /// List a user's gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// The user + public Task> GetAllForUser(string user) + { + Ensure.ArgumentNotNull(user, "user"); + + return ApiConnection.GetAll(ApiUrls.UsersGists(user)); + } + + /// + /// List a user's gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// The user + /// Only gists updated at or after this time are returned + public Task> GetAllForUser(string user, DateTimeOffset since) + { + Ensure.ArgumentNotNull(user, "user"); + + var request = new GistRequest(since); + return ApiConnection.GetAll(ApiUrls.UsersGists(user), request.ToParametersDictionary()); + } + + /// + /// Edits a gist + /// + /// + /// http://developer.github.com/v3/gists/#edit-a-gist + /// + /// The id of the gist + /// The update to the gist + public Task Edit(string id, GistUpdate gistUpdate) + { + Ensure.ArgumentNotNull(id, "id"); + Ensure.ArgumentNotNull(gistUpdate, "gistUpdate"); + + var filesAsJsonObject = new JsonObject(); + foreach (var kvp in gistUpdate.Files) + { + filesAsJsonObject.Add(kvp.Key, new { Content = kvp.Value.Content, Filename = kvp.Value.NewFileName }); + } + + var gist = new + { + Description = gistUpdate.Description, + Files = filesAsJsonObject + }; + + return ApiConnection.Patch(ApiUrls.Gist(id), gist); + } + + /// + /// Stars a gist + /// + /// + /// http://developer.github.com/v3/gists/#star-a-gist + /// + /// The id of the gist + public Task Star(string id) + { + return ApiConnection.Put(ApiUrls.StarGist(id)); + } + + /// + /// Unstars a gist + /// + /// + /// http://developer.github.com/v3/gists/#unstar-a-gist + /// + /// The id of the gist + public Task Unstar(string id) + { + return ApiConnection.Delete(ApiUrls.StarGist(id)); + } + + /// + /// Checks if the gist is starred + /// + /// + /// http://developer.github.com/v3/gists/#check-if-a-gist-is-starred + /// + /// The id of the gist + public async Task IsStarred(string id) + { + Ensure.ArgumentNotNullOrEmptyString(id, "id"); + + try + { + var response = await Connection.GetAsync(ApiUrls.StarGist(id), null, null) + .ConfigureAwait(false); + if (response.StatusCode != HttpStatusCode.NotFound && response.StatusCode != HttpStatusCode.NoContent) + { + throw new ApiException("Invalid Status Code returned. Expected a 204 or a 404", response.StatusCode); + } + return response.StatusCode == HttpStatusCode.NoContent; + } + catch (NotFoundException) + { + return false; + } + } } } \ No newline at end of file diff --git a/Octokit/Clients/IGistsClient.cs b/Octokit/Clients/IGistsClient.cs index 587d0b4f..9ffdfbb5 100644 --- a/Octokit/Clients/IGistsClient.cs +++ b/Octokit/Clients/IGistsClient.cs @@ -1,4 +1,6 @@ -using System.Diagnostics.CodeAnalysis; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; namespace Octokit @@ -24,6 +26,78 @@ namespace Octokit Justification = "Method makes a network request")] Task Get(string id); + /// + /// List the authenticated user’s gists or if called anonymously, + /// this will return all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + Task> GetAll(); + + /// + /// List the authenticated user’s gists or if called anonymously, + /// this will return all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + Task> GetAll(DateTimeOffset since); + + /// + /// Lists all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + Task> GetAllPublic(); + + /// + /// Lists all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + Task> GetAllPublic(DateTimeOffset since); + + /// + /// List the authenticated user’s starred gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + Task> GetAllStarred(); + + /// + /// List the authenticated user’s starred gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + Task> GetAllStarred(DateTimeOffset since); + + /// + /// List a user's gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// The user + Task> GetAllForUser(string user); + + /// + /// List a user's gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// The user + /// Only gists updated at or after this time are returned + Task> GetAllForUser(string user, DateTimeOffset since); + /// /// Creates a new gist /// @@ -33,6 +107,25 @@ namespace Octokit /// The new gist to create Task Create(NewGist newGist); + /// + /// Creates a fork of a gist + /// + /// + /// http://developer.github.com/v3/gists/#fork-a-gist + /// + /// The id of the gist to fork + Task Fork(string id); + + /// + /// Edits a gist + /// + /// + /// http://developer.github.com/v3/gists/#delete-a-gist + /// + /// The id of the gist + /// The update to the gist + Task Edit(string id, GistUpdate gistUpdate); + /// /// Deletes a gist /// @@ -41,5 +134,33 @@ namespace Octokit /// /// The id of the gist Task Delete(string id); + + /// + /// Stars a gist + /// + /// + /// http://developer.github.com/v3/gists/#star-a-gist + /// + /// The id of the gist + Task Star(string id); + + /// + /// Unstars a gist + /// + /// + /// http://developer.github.com/v3/gists/#unstar-a-gist + /// + /// The id of the gist + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unstar")] + Task Unstar(string id); + + /// + /// Checks if the gist is starred + /// + /// + /// http://developer.github.com/v3/gists/#check-if-a-gist-is-starred + /// + /// The id of the gist + Task IsStarred(string id); } } \ No newline at end of file diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index 7a9770fc..a861044d 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -622,6 +622,31 @@ namespace Octokit return "gists/{0}".FormatUri(id); } + public static Uri ForkGist(string id) + { + return "gists/{0}/forks".FormatUri(id); + } + + public static Uri PublicGists() + { + return "gists/public".FormatUri(); + } + + public static Uri StarredGists() + { + return "gists/starred".FormatUri(); + } + + public static Uri UsersGists(string user) + { + return "users/{0}/gists".FormatUri(user); + } + + public static Uri StarGist(string id) + { + return "gists/{0}/star".FormatUri(id); + } + /// /// Returns the for the comments for the specified gist. /// diff --git a/Octokit/Models/Request/GistRequest.cs b/Octokit/Models/Request/GistRequest.cs new file mode 100644 index 00000000..d37133e7 --- /dev/null +++ b/Octokit/Models/Request/GistRequest.cs @@ -0,0 +1,15 @@ +using System; +using Octokit.Internal; + +namespace Octokit +{ + public class GistRequest : RequestParameters + { + public GistRequest(DateTimeOffset since) + { + Since = since; + } + + public DateTimeOffset Since { get; set; } + } +} diff --git a/Octokit/Models/Request/GistUpdate.cs b/Octokit/Models/Request/GistUpdate.cs new file mode 100644 index 00000000..1d89b251 --- /dev/null +++ b/Octokit/Models/Request/GistUpdate.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using Octokit.Internal; + +namespace Octokit +{ + public class GistUpdate + { + public GistUpdate() + { + Files = new Dictionary(); + } + + public string Description { get; set; } + public IDictionary Files { get; private set; } + } + + public class GistFileUpdate + { + public string NewFileName { get; set; } + public string Content { get; set; } + } +} diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj index 0ba47a12..a8b6e175 100644 --- a/Octokit/Octokit-Mono.csproj +++ b/Octokit/Octokit-Mono.csproj @@ -89,6 +89,8 @@ + + diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj index c52fd9d8..c8803836 100644 --- a/Octokit/Octokit-netcore45.csproj +++ b/Octokit/Octokit-netcore45.csproj @@ -166,6 +166,8 @@ + + diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index c2fe81e0..e672a525 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -99,6 +99,8 @@ + + From 6f3e3232ed78b0f9502708da0ed381013ee50651 Mon Sep 17 00:00:00 2001 From: Robert Mills Date: Tue, 3 Dec 2013 08:27:53 -0500 Subject: [PATCH 7/8] Passing tests and fix build for MonoAndroid and MonoTouch --- .../Clients/GistsClientTests.cs | 3 +- Octokit.Tests/Clients/GistsClientTests.cs | 70 +++++++++++++------ Octokit/Clients/GistsClient.cs | 3 +- Octokit/Octokit-MonoAndroid.csproj | 2 + Octokit/Octokit-Monotouch.csproj | 4 +- 5 files changed, 54 insertions(+), 28 deletions(-) diff --git a/Octokit.Tests.Integration/Clients/GistsClientTests.cs b/Octokit.Tests.Integration/Clients/GistsClientTests.cs index 1265ad10..344431ff 100644 --- a/Octokit.Tests.Integration/Clients/GistsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/GistsClientTests.cs @@ -5,6 +5,8 @@ using Octokit.Tests.Integration; using Xunit; using System.Collections.Generic; using System.Collections.ObjectModel; +using System; +using System.Linq; public class GistsClientTests { @@ -132,5 +134,4 @@ public class GistsClientTests await _fixture.Delete(createdGist.Id); } -} } \ No newline at end of file diff --git a/Octokit.Tests/Clients/GistsClientTests.cs b/Octokit.Tests/Clients/GistsClientTests.cs index 48a1bd6c..3a3d8769 100644 --- a/Octokit.Tests/Clients/GistsClientTests.cs +++ b/Octokit.Tests/Clients/GistsClientTests.cs @@ -1,11 +1,14 @@ -using System; -using NSubstitute; +using NSubstitute; using Octokit; -using Xunit; -using System.Collections.ObjectModel; -using System.Collections.Generic; -using System.Threading.Tasks; +using Octokit.Internal; using Octokit.Tests.Helpers; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Net; +using System.Threading.Tasks; +using Xunit; +using Xunit.Extensions; public class GistsClientTests { @@ -33,7 +36,7 @@ public class GistsClientTests client.GetAll(); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists"), null); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists")); } [Fact] @@ -56,8 +59,7 @@ public class GistsClientTests client.GetAllPublic(); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists/public"), - Arg.Is>(x => x.ContainsKey("since"))); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists/public")); } [Fact] @@ -81,8 +83,7 @@ public class GistsClientTests client.GetAllStarred(); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists/starred"), - Arg.Is>(x => x.ContainsKey("since"))); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists/starred")); } [Fact] @@ -106,8 +107,7 @@ public class GistsClientTests client.GetAllForUser("octokit"); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "users/octokit/gists"), - Arg.Is>(x => x.ContainsKey("since"))); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "users/octokit/gists")); } [Fact] @@ -178,7 +178,7 @@ public class GistsClientTests client.Star("1"); - connection.Received().Get(Arg.Is(u => u.ToString() == "gists/1/star"), null); + connection.Received().Put(Arg.Is(u => u.ToString() == "gists/1/star")); } [Fact] @@ -189,18 +189,42 @@ public class GistsClientTests client.Unstar("1"); - connection.Received().Get(Arg.Is(u => u.ToString() == "gists/1/star"), null); + connection.Received().Delete(Arg.Is(u => u.ToString() == "gists/1/star")); + } + + [Theory] + [InlineData(HttpStatusCode.NoContent, true)] + [InlineData(HttpStatusCode.NotFound, false)] + public async Task RequestsCorrectValueForStatusCode(HttpStatusCode status, bool expected) + { + var response = Task.Factory.StartNew>(() => + new ApiResponse { StatusCode = status }); + var connection = Substitute.For(); + connection.GetAsync(Arg.Is(u => u.ToString() == "gists/1/star"), + null, null).Returns(response); + var apiConnection = Substitute.For(); + apiConnection.Connection.Returns(connection); + var client = new GistsClient(apiConnection); + + var result = await client.IsStarred("1"); + + Assert.Equal(expected, result); } [Fact] - public void RequestsCorrectCheckIfStarredUrl() + public async Task ThrowsExceptionForInvalidStatusCode() { - var connection = Substitute.For(); - var client = new GistsClient(connection); + var response = Task.Factory.StartNew>(() => + new ApiResponse { StatusCode = HttpStatusCode.Conflict }); + var connection = Substitute.For(); + connection.GetAsync(Arg.Is(u => u.ToString() == "gists/1/star"), + null, null).Returns(response); + var apiConnection = Substitute.For(); + apiConnection.Connection.Returns(connection); - client.IsStarred("1"); + var client = new GistsClient(apiConnection); - connection.Received().Get(Arg.Is(u => u.ToString() == "gists/1/star"), null); + AssertEx.Throws(async () => await client.IsStarred("1")); } } @@ -214,8 +238,8 @@ public class GistsClientTests client.Fork("1"); - connection.Received().Post(Arg.Is(u => u.ToString() == "gists/1/fork"), - Arg.Is(o => o == null)); + connection.Received().Post(Arg.Is(u => u.ToString() == "gists/1/forks"), + Arg.Any()); } } @@ -239,7 +263,7 @@ public class GistsClientTests client.Edit("1", updateGist); - connection.Received().Post(Arg.Is(u => u.ToString() == "gists/1"), Arg.Any()); + connection.Received().Patch(Arg.Is(u => u.ToString() == "gists/1"), Arg.Any()); } } diff --git a/Octokit/Clients/GistsClient.cs b/Octokit/Clients/GistsClient.cs index ae816607..e40bfb3c 100644 --- a/Octokit/Clients/GistsClient.cs +++ b/Octokit/Clients/GistsClient.cs @@ -99,7 +99,6 @@ namespace Octokit /// /// http://developer.github.com/v3/gists/#list-gists /// - /// Only gists updated at or after this time are returned public Task> GetAll() { return ApiConnection.GetAll(ApiUrls.Gist()); @@ -201,7 +200,7 @@ namespace Octokit /// Edits a gist /// /// - /// http://developer.github.com/v3/gists/#edit-a-gist + /// http://developer.github.com/v3/gists/#delete-a-gist /// /// The id of the gist /// The update to the gist diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj index 9c36915d..30fc8b52 100644 --- a/Octokit/Octokit-MonoAndroid.csproj +++ b/Octokit/Octokit-MonoAndroid.csproj @@ -309,6 +309,8 @@ + + \ No newline at end of file diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj index 1fb714a2..e75a3941 100644 --- a/Octokit/Octokit-Monotouch.csproj +++ b/Octokit/Octokit-Monotouch.csproj @@ -248,7 +248,6 @@ -<<<<<<< HEAD @@ -304,7 +303,8 @@ - + + From f3f2b9f132da5aa9aef44a0d8d5f9ecced468745 Mon Sep 17 00:00:00 2001 From: Marius Ungureanu Date: Wed, 26 Feb 2014 04:11:27 +0200 Subject: [PATCH 8/8] Fix convention tests running for gists --- .../Clients/IObservableGistsClient.cs | 140 +++++++++++- .../Clients/ObservableGistsClient.cs | 203 ++++++++++++++++++ Octokit/Helpers/ApiUrls.cs | 2 +- Octokit/Models/Request/GistRequest.cs | 12 +- Octokit/Models/Request/GistUpdate.cs | 12 +- Octokit/Models/Request/NewGist.cs | 12 ++ 6 files changed, 377 insertions(+), 4 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableGistsClient.cs b/Octokit.Reactive/Clients/IObservableGistsClient.cs index 5bb29ede..31ea9da5 100644 --- a/Octokit.Reactive/Clients/IObservableGistsClient.cs +++ b/Octokit.Reactive/Clients/IObservableGistsClient.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Reactive; namespace Octokit.Reactive { @@ -16,6 +17,143 @@ namespace Octokit.Reactive /// The id of the gist [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] - IObservable Get(string id); + IObservable Get(string id); + + /// + /// List the authenticated user’s gists or if called anonymously, + /// this will return all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + IObservable GetAll(); + + /// + /// List the authenticated user’s gists or if called anonymously, + /// this will return all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + IObservable GetAll(DateTimeOffset since); + + /// + /// Lists all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + IObservable GetAllPublic(); + + /// + /// Lists all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + IObservable GetAllPublic(DateTimeOffset since); + + /// + /// List the authenticated user’s starred gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + IObservable GetAllStarred(); + + /// + /// List the authenticated user’s starred gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + IObservable GetAllStarred(DateTimeOffset since); + + /// + /// List a user's gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// The user + IObservable GetAllForUser(string user); + + /// + /// List a user's gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// The user + /// Only gists updated at or after this time are returned + IObservable GetAllForUser(string user, DateTimeOffset since); + + /// + /// Creates a new gist + /// + /// + /// http://developer.github.com/v3/gists/#create-a-gist + /// + /// The new gist to create + IObservable Create(NewGist newGist); + + /// + /// Creates a fork of a gist + /// + /// + /// http://developer.github.com/v3/gists/#fork-a-gist + /// + /// The id of the gist to fork + IObservable Fork(string id); + + /// + /// Edits a gist + /// + /// + /// http://developer.github.com/v3/gists/#delete-a-gist + /// + /// The id of the gist + /// The update to the gist + IObservable Edit(string id, GistUpdate gistUpdate); + + /// + /// Deletes a gist + /// + /// + /// http://developer.github.com/v3/gists/#delete-a-gist + /// + /// The id of the gist + IObservable Delete(string id); + + /// + /// Stars a gist + /// + /// + /// http://developer.github.com/v3/gists/#star-a-gist + /// + /// The id of the gist + IObservable Star(string id); + + /// + /// Unstars a gist + /// + /// + /// http://developer.github.com/v3/gists/#unstar-a-gist + /// + /// The id of the gist + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unstar")] + IObservable Unstar(string id); + + /// + /// Checks if the gist is starred + /// + /// + /// http://developer.github.com/v3/gists/#check-if-a-gist-is-starred + /// + /// The id of the gist + IObservable IsStarred(string id); } } \ No newline at end of file diff --git a/Octokit.Reactive/Clients/ObservableGistsClient.cs b/Octokit.Reactive/Clients/ObservableGistsClient.cs index 63c2e6b7..8fe981b8 100644 --- a/Octokit.Reactive/Clients/ObservableGistsClient.cs +++ b/Octokit.Reactive/Clients/ObservableGistsClient.cs @@ -1,17 +1,22 @@ using System; using System.Reactive.Threading.Tasks; +using System.Reactive; +using System.Net; +using Octokit.Reactive.Internal; namespace Octokit.Reactive { public class ObservableGistsClient : IObservableGistsClient { readonly IGistsClient _client; + readonly IConnection _connection; public ObservableGistsClient(IGitHubClient client) { Ensure.ArgumentNotNull(client, "client"); _client = client.Gist; + _connection = client.Connection; Comment = new ObservableGistCommentsClient(client); } @@ -31,5 +36,203 @@ namespace Octokit.Reactive return _client.Get(id).ToObservable(); } + + /// + /// Creates a new gist + /// + /// + /// http://developer.github.com/v3/gists/#create-a-gist + /// + /// The new gist to create + public IObservable Create(NewGist newGist) + { + Ensure.ArgumentNotNull(newGist, "newGist"); + + return _client.Create(newGist).ToObservable(); + } + + /// + /// Creates a fork of a gist + /// + /// + /// http://developer.github.com/v3/gists/#fork-a-gist + /// + /// The id of the gist to fork + public IObservable Fork(string id) + { + return _client.Fork(id).ToObservable(); + } + + /// + /// Deletes a gist + /// + /// + /// http://developer.github.com/v3/gists/#delete-a-gist + /// + /// The id of the gist + public IObservable Delete(string id) + { + Ensure.ArgumentNotNull(id, "id"); + + return _client.Delete(id).ToObservable(); + } + + /// + /// List the authenticated user’s gists or if called anonymously, + /// this will return all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + public IObservable GetAll() + { + return _connection.GetAndFlattenAllPages(ApiUrls.Gist()); + } + + /// + /// List the authenticated user’s gists or if called anonymously, + /// this will return all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + public IObservable GetAll(DateTimeOffset since) + { + var request = new GistRequest(since); + return _connection.GetAndFlattenAllPages(ApiUrls.Gist(), request.ToParametersDictionary()); + } + + /// + /// Lists all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + public IObservable GetAllPublic() + { + return _connection.GetAndFlattenAllPages(ApiUrls.PublicGists()); + } + + /// + /// Lists all public gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + public IObservable GetAllPublic(DateTimeOffset since) + { + var request = new GistRequest(since); + return _connection.GetAndFlattenAllPages(ApiUrls.PublicGists(), request.ToParametersDictionary()); + } + + /// + /// List the authenticated user’s starred gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + public IObservable GetAllStarred() + { + return _connection.GetAndFlattenAllPages(ApiUrls.StarredGists()); + } + + /// + /// List the authenticated user’s starred gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// Only gists updated at or after this time are returned + public IObservable GetAllStarred(DateTimeOffset since) + { + var request = new GistRequest(since); + return _connection.GetAndFlattenAllPages(ApiUrls.StarredGists(), request.ToParametersDictionary()); + } + + /// + /// List a user's gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// The user + public IObservable GetAllForUser(string user) + { + Ensure.ArgumentNotNull(user, "user"); + + return _connection.GetAndFlattenAllPages(ApiUrls.UsersGists(user)); + } + + /// + /// List a user's gists + /// + /// + /// http://developer.github.com/v3/gists/#list-gists + /// + /// The user + /// Only gists updated at or after this time are returned + public IObservable GetAllForUser(string user, DateTimeOffset since) + { + Ensure.ArgumentNotNull(user, "user"); + + var request = new GistRequest(since); + return _connection.GetAndFlattenAllPages(ApiUrls.UsersGists(user), request.ToParametersDictionary()); + } + + /// + /// Edits a gist + /// + /// + /// http://developer.github.com/v3/gists/#delete-a-gist + /// + /// The id of the gist + /// The update to the gist + public IObservable Edit(string id, GistUpdate gistUpdate) + { + Ensure.ArgumentNotNull(id, "id"); + Ensure.ArgumentNotNull(gistUpdate, "gistUpdate"); + + return _client.Edit(id, gistUpdate).ToObservable(); + } + + /// + /// Stars a gist + /// + /// + /// http://developer.github.com/v3/gists/#star-a-gist + /// + /// The id of the gist + public IObservable Star(string id) + { + return _client.Star(id).ToObservable(); + } + + /// + /// Unstars a gist + /// + /// + /// http://developer.github.com/v3/gists/#unstar-a-gist + /// + /// The id of the gist + public IObservable Unstar(string id) + { + return _client.Unstar(id).ToObservable(); + } + + /// + /// Checks if the gist is starred + /// + /// + /// http://developer.github.com/v3/gists/#check-if-a-gist-is-starred + /// + /// The id of the gist + public IObservable IsStarred(string id) + { + Ensure.ArgumentNotNullOrEmptyString(id, "id"); + + return _client.IsStarred(id).ToObservable(); + } } } \ No newline at end of file diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index a861044d..5956d371 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -602,7 +602,7 @@ namespace Octokit /// public static Uri Feeds() { - return "feeds".FormatUri (); + return "feeds".FormatUri(); } /// diff --git a/Octokit/Models/Request/GistRequest.cs b/Octokit/Models/Request/GistRequest.cs index d37133e7..86989c94 100644 --- a/Octokit/Models/Request/GistRequest.cs +++ b/Octokit/Models/Request/GistRequest.cs @@ -1,8 +1,10 @@ using System; -using Octokit.Internal; +using System.Diagnostics; +using System.Globalization; namespace Octokit { + [DebuggerDisplay("{DebuggerDisplay,nq}")] public class GistRequest : RequestParameters { public GistRequest(DateTimeOffset since) @@ -11,5 +13,13 @@ namespace Octokit } public DateTimeOffset Since { get; set; } + + internal string DebuggerDisplay + { + get + { + return String.Format(CultureInfo.InvariantCulture, "Since: {0}", Since); + } + } } } diff --git a/Octokit/Models/Request/GistUpdate.cs b/Octokit/Models/Request/GistUpdate.cs index 1d89b251..c16fc488 100644 --- a/Octokit/Models/Request/GistUpdate.cs +++ b/Octokit/Models/Request/GistUpdate.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; -using Octokit.Internal; +using System.Diagnostics; +using System.Globalization; namespace Octokit { + [DebuggerDisplay("{DebuggerDisplay,nq}")] public class GistUpdate { public GistUpdate() @@ -13,6 +15,14 @@ namespace Octokit public string Description { get; set; } public IDictionary Files { get; private set; } + + internal string DebuggerDisplay + { + get + { + return String.Format(CultureInfo.InvariantCulture, "Description: {0}", Description); + } + } } public class GistFileUpdate diff --git a/Octokit/Models/Request/NewGist.cs b/Octokit/Models/Request/NewGist.cs index 66726721..71b7fad4 100644 --- a/Octokit/Models/Request/NewGist.cs +++ b/Octokit/Models/Request/NewGist.cs @@ -1,8 +1,12 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Diagnostics; +using System; +using System.Globalization; namespace Octokit { + [DebuggerDisplay("{DebuggerDisplay,nq}")] public class NewGist { public NewGist() @@ -25,5 +29,13 @@ namespace Octokit /// and value as Content /// public IDictionary Files { get; private set; } + + internal string DebuggerDisplay + { + get + { + return String.Format(CultureInfo.InvariantCulture, "Description: {0}", Description); + } + } } } \ No newline at end of file