Implement new Project Card archiving (#1842)

* add Archived to ProjectCard response
add Archived to ProjectCardUpdate
update integration tests

* Add ProjectCardRequest model and update GetAll calls to use it
Update unit tests
Update integration tests

* skip_branch_with_pr still ends up building the branch on the initial push, so let's only build master instead
This commit is contained in:
Ryan Gribble
2018-07-11 20:38:54 +10:00
committed by GitHub
parent 1515dc2a2f
commit 043e64b89f
13 changed files with 467 additions and 17 deletions
@@ -30,6 +30,27 @@ namespace Octokit.Reactive
/// <param name="options">Options for changing the API response</param>
IObservable<ProjectCard> GetAll(int columnId, ApiOptions options);
/// <summary>
/// Gets all cards.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/repos/projects/#list-projects-cards">API documentation</a> for more information.
/// </remarks>
/// <param name="columnId">The id of the column</param>
/// <param name="request">Used to filter the list of project cards returned</param>
IObservable<ProjectCard> GetAll(int columnId, ProjectCardRequest request);
/// <summary>
/// Gets all cards.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/repos/projects/#list-projects-cards">API documentation</a> for more information.
/// </remarks>
/// <param name="columnId">The id of the column</param>
/// <param name="request">Used to filter the list of project cards returned</param>
/// <param name="options">Options for changing the API response</param>
IObservable<ProjectCard> GetAll(int columnId, ProjectCardRequest request, ApiOptions options);
/// <summary>
/// Gets a single card.
/// </summary>
@@ -1,7 +1,6 @@
using Octokit.Reactive.Internal;
using System;
using System.Reactive.Threading.Tasks;
using System.Collections.Generic;
namespace Octokit.Reactive
{
@@ -48,9 +47,41 @@ namespace Octokit.Reactive
{
Ensure.ArgumentNotNull(options, nameof(options));
return GetAll(columnId, new ProjectCardRequest(), options);
}
/// <summary>
/// Gets all cards.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/repos/projects/#list-projects-cards">API documentation</a> for more information.
/// </remarks>
/// <param name="columnId">The id of the column</param>
/// <param name="request">Used to filter the list of project cards returned</param>
public IObservable<ProjectCard> GetAll(int columnId, ProjectCardRequest request)
{
Ensure.ArgumentNotNull(request, nameof(request));
return GetAll(columnId, request, ApiOptions.None);
}
/// <summary>
/// Gets all cards.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/repos/projects/#list-projects-cards">API documentation</a> for more information.
/// </remarks>
/// <param name="columnId">The id of the column</param>
/// <param name="request">Used to filter the list of project cards returned</param>
/// <param name="options">Options for changing the API response</param>
public IObservable<ProjectCard> GetAll(int columnId, ProjectCardRequest request, ApiOptions options)
{
Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(options, nameof(options));
var url = ApiUrls.ProjectCards(columnId);
return _connection.GetAndFlattenAllPages<ProjectCard>(url, new Dictionary<string, string>(), AcceptHeaders.ProjectsApiPreview, options);
return _connection.GetAndFlattenAllPages<ProjectCard>(url, request.ToParametersDictionary(), AcceptHeaders.ProjectsApiPreview, options);
}
/// <summary>
@@ -2,8 +2,6 @@
using Octokit.Tests.Integration;
using Octokit.Tests.Integration.Helpers;
using System;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Xunit;
@@ -33,8 +31,57 @@ public class ProjectCardsClientTests
var result = await _github.Repository.Project.Card.GetAll(column.Id);
Assert.Equal(2, result.Count);
Assert.True(result.FirstOrDefault(x => x.Id == card1.Id).Id == card1.Id);
Assert.True(result.FirstOrDefault(x => x.Id == card2.Id).Id == card2.Id);
Assert.Contains(result, x => x.Id == card1.Id);
Assert.Contains(result, x => x.Id == card2.Id);
}
[IntegrationTest]
public async Task GetsAllArchivedCards()
{
var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId);
var column = await CreateColumnHelper(_github, project.Id);
var card1 = await CreateCardHelper(_github, column.Id);
var card2 = await CreateArchivedCardHelper(_github, column.Id);
var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.Archived);
var result = await _github.Repository.Project.Card.GetAll(column.Id, request);
Assert.Equal(1, result.Count);
Assert.Contains(result, x => x.Id == card2.Id);
}
[IntegrationTest]
public async Task GetsAllNotArchivedCards()
{
var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId);
var column = await CreateColumnHelper(_github, project.Id);
var card1 = await CreateCardHelper(_github, column.Id);
var card2 = await CreateArchivedCardHelper(_github, column.Id);
var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.NotArchived);
var result = await _github.Repository.Project.Card.GetAll(column.Id, request);
Assert.Equal(1, result.Count);
Assert.Contains(result, x => x.Id == card1.Id);
}
[IntegrationTest]
public async Task GetsAllArchivedAndNotArchivedCards()
{
var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId);
var column = await CreateColumnHelper(_github, project.Id);
var card1 = await CreateCardHelper(_github, column.Id);
var card2 = await CreateArchivedCardHelper(_github, column.Id);
var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.All);
var result = await _github.Repository.Project.Card.GetAll(column.Id, request);
Assert.Equal(2, result.Count);
Assert.Contains(result, x => x.Id == card1.Id);
Assert.Contains(result, x => x.Id == card2.Id);
}
[IntegrationTest]
@@ -207,7 +254,10 @@ public class ProjectCardsClientTests
var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId);
var column = await CreateColumnHelper(_github, project.Id);
var card = await CreateCardHelper(_github, column.Id);
var cardUpdate = new ProjectCardUpdate("newNameOfNote");
var cardUpdate = new ProjectCardUpdate
{
Note = "newNameOfNote"
};
var result = await _github.Repository.Project.Card.Update(card.Id, cardUpdate);
@@ -215,6 +265,42 @@ public class ProjectCardsClientTests
Assert.Equal(card.Id, result.Id);
}
[IntegrationTest]
public async Task ArchivesCard()
{
var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId);
var column = await CreateColumnHelper(_github, project.Id);
var card = await CreateCardHelper(_github, column.Id);
var cardUpdate = new ProjectCardUpdate
{
Archived = true
};
var result = await _github.Repository.Project.Card.Update(card.Id, cardUpdate);
Assert.Equal(card.Id, result.Id);
Assert.False(card.Archived);
Assert.True(result.Archived);
}
[IntegrationTest]
public async Task UnarchivesCard()
{
var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId);
var column = await CreateColumnHelper(_github, project.Id);
var card = await CreateArchivedCardHelper(_github, column.Id);
var cardUpdate = new ProjectCardUpdate
{
Archived = false
};
var result = await _github.Repository.Project.Card.Update(card.Id, cardUpdate);
Assert.Equal(card.Id, result.Id);
Assert.True(card.Archived);
Assert.False(result.Archived);
}
public void Dispose()
{
if (_context != null)
@@ -343,6 +429,15 @@ public class ProjectCardsClientTests
return result;
}
private static async Task<ProjectCard> CreateArchivedCardHelper(IGitHubClient githubClient, int columnId)
{
var newCard = new NewProjectCard(Helper.MakeNameWithTimestamp("new-card"));
var card = await githubClient.Repository.Project.Card.Create(columnId, newCard);
var result = await githubClient.Repository.Project.Card.Update(card.Id, new ProjectCardUpdate { Archived = true });
return result;
}
private static async Task<ProjectCard> CreateIssueCardHelper(IGitHubClient githubClient, int issueId, int columnId)
{
var newCard = new NewProjectCard(issueId, ProjectCardContentType.Issue);
@@ -4,7 +4,6 @@ using Octokit.Tests.Integration;
using Octokit.Tests.Integration.Helpers;
using System;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Xunit;
using System.Reactive.Linq;
@@ -39,6 +38,55 @@ public class ObservableProjectCardsClientTests
Assert.True(result.FirstOrDefault(x => x.Id == card2.Id).Id == card2.Id);
}
[IntegrationTest]
public async Task GetsAllArchivedCards()
{
var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId);
var column = await CreateColumnHelper(_github, project.Id);
var card1 = await CreateCardHelper(_github, column.Id);
var card2 = await CreateArchivedCardHelper(_github, column.Id);
var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.Archived);
var result = await _github.Repository.Project.Card.GetAll(column.Id, request).ToList();
Assert.Equal(1, result.Count);
Assert.Contains(result, x => x.Id == card2.Id);
}
[IntegrationTest]
public async Task GetsAllNotArchivedCards()
{
var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId);
var column = await CreateColumnHelper(_github, project.Id);
var card1 = await CreateCardHelper(_github, column.Id);
var card2 = await CreateArchivedCardHelper(_github, column.Id);
var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.NotArchived);
var result = await _github.Repository.Project.Card.GetAll(column.Id, request).ToList();
Assert.Equal(1, result.Count);
Assert.Contains(result, x => x.Id == card1.Id);
}
[IntegrationTest]
public async Task GetsAllArchivedAndNotArchivedCards()
{
var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId);
var column = await CreateColumnHelper(_github, project.Id);
var card1 = await CreateCardHelper(_github, column.Id);
var card2 = await CreateArchivedCardHelper(_github, column.Id);
var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.All);
var result = await _github.Repository.Project.Card.GetAll(column.Id, request).ToList();
Assert.Equal(2, result.Count);
Assert.Contains(result, x => x.Id == card1.Id);
Assert.Contains(result, x => x.Id == card2.Id);
}
[IntegrationTest]
public async Task ReturnsCorrectCountOfCardWithoutStart()
{
@@ -209,7 +257,10 @@ public class ObservableProjectCardsClientTests
var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId);
var column = await CreateColumnHelper(_github, project.Id);
var card = await CreateCardHelper(_github, column.Id);
var cardUpdate = new ProjectCardUpdate("newNameOfNote");
var cardUpdate = new ProjectCardUpdate
{
Note = "newNameOfNote"
};
var result = await _github.Repository.Project.Card.Update(card.Id, cardUpdate);
@@ -217,6 +268,42 @@ public class ObservableProjectCardsClientTests
Assert.Equal(card.Id, result.Id);
}
[IntegrationTest]
public async Task ArchivesCard()
{
var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId);
var column = await CreateColumnHelper(_github, project.Id);
var card = await CreateCardHelper(_github, column.Id);
var cardUpdate = new ProjectCardUpdate
{
Archived = true
};
var result = await _github.Repository.Project.Card.Update(card.Id, cardUpdate);
Assert.Equal(card.Id, result.Id);
Assert.False(card.Archived);
Assert.True(result.Archived);
}
[IntegrationTest]
public async Task UnarchivesCard()
{
var project = await CreateRepositoryProjectHelper(_github, _context.RepositoryId);
var column = await CreateColumnHelper(_github, project.Id);
var card = await CreateArchivedCardHelper(_github, column.Id);
var cardUpdate = new ProjectCardUpdate
{
Archived = false
};
var result = await _github.Repository.Project.Card.Update(card.Id, cardUpdate);
Assert.Equal(card.Id, result.Id);
Assert.True(card.Archived);
Assert.False(result.Archived);
}
public void Dispose()
{
if (_context != null)
@@ -345,6 +432,15 @@ public class ObservableProjectCardsClientTests
return result;
}
private static async Task<ProjectCard> CreateArchivedCardHelper(IObservableGitHubClient githubClient, int columnId)
{
var newCard = new NewProjectCard(Helper.MakeNameWithTimestamp("new-card"));
var card = await githubClient.Repository.Project.Card.Create(columnId, newCard);
var result = await githubClient.Repository.Project.Card.Update(card.Id, new ProjectCardUpdate { Archived = true });
return result;
}
private static async Task<ProjectCard> CreateIssueCardHelper(IObservableGitHubClient githubClient, int issueId, int columnId)
{
var newCard = new NewProjectCard(issueId, ProjectCardContentType.Issue);
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using NSubstitute;
using Xunit;
@@ -33,12 +34,33 @@ namespace Octokit.Tests.Clients
Args.ApiOptions);
}
[Fact]
public async Task SendsAppropriateParameters()
{
var connection = Substitute.For<IApiConnection>();
var client = new ProjectCardsClient(connection);
await client.GetAll(1, new ProjectCardRequest(ProjectCardArchivedStateFilter.NotArchived));
connection.Received().GetAll<ProjectCard>(
Arg.Is<Uri>(u => u.ToString() == "projects/columns/1/cards"),
Arg.Is<Dictionary<string,string>>(x =>
x.Count == 1
&& x["archived_state"] == "not_archived"),
"application/vnd.github.inertia-preview+json",
Args.ApiOptions);
}
[Fact]
public async Task EnsuresNonNullArguments()
{
var client = new ProjectCardsClient(Substitute.For<IApiConnection>());
var request = new ProjectCardRequest();
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(1, null));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(1, (ProjectCardRequest)null));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(1, (ApiOptions)null));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(1, null, ApiOptions.None));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(1, request, null));
}
}
@@ -0,0 +1,28 @@
using Octokit;
using Xunit;
public class ProjectCardRequestTests
{
public class TheToParametersDictionaryMethod
{
[Fact]
public void ContainsSetValues()
{
var request = new ProjectCardRequest(ProjectCardArchivedStateFilter.All);
var parameters = request.ToParametersDictionary();
Assert.Equal("all", parameters["archived_state"]);
}
[Fact]
public void ReturnsDefaultValuesForDefaultRequest()
{
var request = new ProjectCardRequest();
var parameters = request.ToParametersDictionary();
Assert.Empty(parameters);
}
}
}
@@ -37,13 +37,34 @@ namespace Octokit.Tests.Reactive
"application/vnd.github.inertia-preview+json");
}
[Fact]
public async Task SendsAppropriateParameters()
{
var connection = Substitute.For<IConnection>();
var gitHubClient = new GitHubClient(connection);
var client = new ObservableProjectCardsClient(gitHubClient);
client.GetAll(1, new ProjectCardRequest(ProjectCardArchivedStateFilter.NotArchived));
connection.Received().Get<List<ProjectCard>>(
Arg.Is<Uri>(u => u.ToString() == "projects/columns/1/cards"),
Arg.Is<Dictionary<string, string>>(x =>
x.Count == 1
&& x["archived_state"] == "not_archived"),
"application/vnd.github.inertia-preview+json");
}
[Fact]
public async Task EnsuresNonNullArguments()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableProjectCardsClient(gitHubClient);
var request = new ProjectCardRequest();
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(1, null).ToTask());
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(1, (ProjectCardRequest)null).ToTask());
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(1, (ApiOptions)null).ToTask());
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(1, null, ApiOptions.None).ToTask());
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(1, request, null).ToTask());
}
}
+21
View File
@@ -31,6 +31,27 @@ namespace Octokit
/// <param name="options">Options for changing the API response</param>
Task<IReadOnlyList<ProjectCard>> GetAll(int columnId, ApiOptions options);
/// <summary>
/// Gets all cards.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/repos/projects/#list-projects-cards">API documentation</a> for more information.
/// </remarks>
/// <param name="columnId">The id of the column</param>
/// <param name="request">Used to filter the list of project cards returned</param>
Task<IReadOnlyList<ProjectCard>> GetAll(int columnId, ProjectCardRequest request);
/// <summary>
/// Gets all cards.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/repos/projects/#list-projects-cards">API documentation</a> for more information.
/// </remarks>
/// <param name="columnId">The id of the column</param>
/// <param name="request">Used to filter the list of project cards returned</param>
/// <param name="options">Options for changing the API response</param>
Task<IReadOnlyList<ProjectCard>> GetAll(int columnId, ProjectCardRequest request, ApiOptions options);
/// <summary>
/// Gets a single card.
/// </summary>
+33 -1
View File
@@ -41,7 +41,39 @@ namespace Octokit
{
Ensure.ArgumentNotNull(options, nameof(options));
return ApiConnection.GetAll<ProjectCard>(ApiUrls.ProjectCards(columnId), new Dictionary<string, string>(), AcceptHeaders.ProjectsApiPreview, options);
return GetAll(columnId, new ProjectCardRequest(), options);
}
/// <summary>
/// Gets all cards.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/repos/projects/#list-projects-cards">API documentation</a> for more information.
/// </remarks>
/// <param name="columnId">The id of the column</param>
/// <param name="request">Used to filter the list of project cards returned</param>
public Task<IReadOnlyList<ProjectCard>> GetAll(int columnId, ProjectCardRequest request)
{
Ensure.ArgumentNotNull(request, nameof(request));
return GetAll(columnId, request, ApiOptions.None);
}
/// <summary>
/// Gets all cards.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/repos/projects/#list-projects-cards">API documentation</a> for more information.
/// </remarks>
/// <param name="columnId">The id of the column</param>
/// <param name="request">Used to filter the list of project cards returned</param>
/// <param name="options">Options for changing the API response</param>
public Task<IReadOnlyList<ProjectCard>> GetAll(int columnId, ProjectCardRequest request, ApiOptions options)
{
Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(options, nameof(options));
return ApiConnection.GetAll<ProjectCard>(ApiUrls.ProjectCards(columnId), request.ToParametersDictionary(), AcceptHeaders.ProjectsApiPreview, options);
}
/// <summary>
@@ -0,0 +1,64 @@
using System.Diagnostics;
using System.Globalization;
using Octokit.Internal;
namespace Octokit
{
/// <summary>
/// Used to filter requests for lists of projects
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class ProjectCardRequest : RequestParameters
{
/// <summary>
/// Used to filter requests for lists of projects
/// </summary>
public ProjectCardRequest()
{
}
/// <summary>
/// Used to filter requests for lists of projects
/// </summary>
/// <param name="archived">Which project cards to include.</param>
public ProjectCardRequest(ProjectCardArchivedStateFilter archived)
{
ArchivedState = archived;
}
/// <summary>
/// Which project cards to include./>.
/// </summary>
[Parameter(Key = "archived_state")]
public ProjectCardArchivedStateFilter? ArchivedState { get; private set; }
internal string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture, "ArchivedState: {0} ", ArchivedState?.ToString() ?? "null");
}
}
}
public enum ProjectCardArchivedStateFilter
{
/// <summary>
/// Items that are open.
/// </summary>
[Parameter(Value = "not_archived")]
NotArchived,
/// <summary>
/// Items that are closed.
/// </summary>
[Parameter(Value = "archived")]
Archived,
/// <summary>
/// All the items.
/// </summary>
[Parameter(Value = "all")]
All
}
}
+14 -3
View File
@@ -1,4 +1,5 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
using System.Globalization;
namespace Octokit
@@ -6,6 +7,11 @@ namespace Octokit
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class ProjectCardUpdate
{
public ProjectCardUpdate()
{
}
[Obsolete("This constructor will be removed in a future release, due to the 'Note' parameter not being mandatory. Use object initializer syntax instead.")]
public ProjectCardUpdate(string note)
{
Note = note;
@@ -14,13 +20,18 @@ namespace Octokit
/// <summary>
/// The new note of the card.
/// </summary>
public string Note { get; private set; }
public string Note { get; set; }
/// <summary>
/// Archive/Unarchive the card.
/// </summary>
public bool? Archived { get; set; }
internal string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture, "Note: {0}", Note);
return string.Format(CultureInfo.InvariantCulture, "Note: {0}, Archived: {1}", Note, Archived?.ToString() ?? "null");
}
}
}
+7 -1
View File
@@ -9,7 +9,7 @@ namespace Octokit
{
public ProjectCard() { }
public ProjectCard(string columnUrl, string contentUrl, int id, string nodeId, string note, User creator, DateTimeOffset createdAt, DateTimeOffset updatedAt)
public ProjectCard(string columnUrl, string contentUrl, int id, string nodeId, string note, User creator, DateTimeOffset createdAt, DateTimeOffset updatedAt, bool archived)
{
ColumnUrl = columnUrl;
ContentUrl = contentUrl;
@@ -19,6 +19,7 @@ namespace Octokit
Creator = creator;
CreatedAt = createdAt;
UpdatedAt = updatedAt;
Archived = archived;
}
/// <summary>
@@ -61,6 +62,11 @@ namespace Octokit
/// </summary>
public DateTimeOffset UpdatedAt { get; protected set; }
/// <summary>
/// Whether this card is archived.
/// </summary>
public bool Archived { get; protected set; }
internal string DebuggerDisplay
{
get
+3 -1
View File
@@ -1,6 +1,8 @@
image: Visual Studio 2017
skip_branch_with_pr: true
branches:
only:
- master
init:
- git config --global core.autocrlf input