diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000000..5e9a36e70e --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "sourcelink": { + "version": "3.1.1", + "commands": [ + "sourcelink" + ] + } + } +} \ No newline at end of file diff --git a/.github/workflows/netcore.yml b/.github/workflows/netcore.yml new file mode 100644 index 0000000000..87366f2a1a --- /dev/null +++ b/.github/workflows/netcore.yml @@ -0,0 +1,28 @@ +name: CI Build + +on: + pull_request: + branches: + - "master" + push: + branches: + - "master" + +jobs: + build: + + strategy: + matrix: + platform: [ubuntu-latest, macos-latest] + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v1 + - name: Setup .NET Core + uses: actions/setup-dotnet@v1.4.0 + with: + dotnet-version: 3.1.101 + - name: Build with dotnet + run: ./build.sh --linksources=true --verbosity=verbose + shell: bash diff --git a/.gitignore b/.gitignore index efc3a76e7c..4184f93872 100644 --- a/.gitignore +++ b/.gitignore @@ -101,4 +101,8 @@ Backup/ .dotnet/* tools/* !tools/gitversion_wrapper.sh -!tools/LINQPad \ No newline at end of file +!tools/LINQPad +coverage-results/* + +# Rider +**/.idea/* \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d76efdb68f..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: csharp - -matrix: - include: - - os: linux - dist: trusty - sudo: required - dotnet: 2.1.300 - - os: osx - osx_image: xcode8.3 - dotnet: 2.1.300 - -branches: - only: - - "master" - -before_script: - - if test "$TRAVIS_OS_NAME" == "osx"; then export FrameworkPathOverride=/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5/; else export FrameworkPathOverride=/usr/lib/mono/4.5/; fi - -script: - - git fetch --unshallow --tags - - ./build.sh --linksources=true --verbosity=verbose diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000000..f42ed479c9 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,9 @@ + + + true + $([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)')) + + + + + diff --git a/GitVersion.yml b/GitVersion.yml index b5514654e9..b67ea5a1c4 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,11 +1,13 @@ +mode: ContinuousDeployment branches: master: mode: ContinuousDeployment increment: Minor tag: beta - dotnetcore: + develop: mode: ContinuousDeployment increment: Minor tag: alpha + source-branches: ['dotnetcore'] ignore: - sha: [] + sha: [] \ No newline at end of file diff --git a/Octokit.Reactive/Clients/Enterprise/IObservableEnterpriseClient.cs b/Octokit.Reactive/Clients/Enterprise/IObservableEnterpriseClient.cs index 27a7d1a236..f3aa7fdcc3 100644 --- a/Octokit.Reactive/Clients/Enterprise/IObservableEnterpriseClient.cs +++ b/Octokit.Reactive/Clients/Enterprise/IObservableEnterpriseClient.cs @@ -13,7 +13,7 @@ public interface IObservableEnterpriseClient /// /// /// See the Enterprise Admin Stats API documentation for more information. - /// + /// IObservableEnterpriseAdminStatsClient AdminStats { get; } /// @@ -21,7 +21,7 @@ public interface IObservableEnterpriseClient /// /// /// See the Enterprise LDAP API documentation for more information. - /// + /// IObservableEnterpriseLdapClient Ldap { get; } /// @@ -29,15 +29,23 @@ public interface IObservableEnterpriseClient /// /// /// See the Enterprise License API documentation for more information. - /// + /// IObservableEnterpriseLicenseClient License { get; } + /// + /// A client for GitHub's Enterprise Management Console API + /// + /// + /// See the Enterprise Management Console API documentation for more information. + /// + IObservableEnterpriseManagementConsoleClient ManagementConsole { get; } + /// /// A client for GitHub's Enterprise Organization API /// /// /// See the Enterprise Organization API documentation for more information. - /// + /// IObservableEnterpriseOrganizationClient Organization { get; } /// @@ -45,7 +53,7 @@ public interface IObservableEnterpriseClient /// /// /// See the Enterprise Search Indexing API documentation for more information. - /// + /// IObservableEnterpriseSearchIndexingClient SearchIndexing { get; } /// diff --git a/Octokit.Reactive/Clients/Enterprise/IObservableEnterpriseManagementConsoleClient.cs b/Octokit.Reactive/Clients/Enterprise/IObservableEnterpriseManagementConsoleClient.cs new file mode 100644 index 0000000000..816f850e6d --- /dev/null +++ b/Octokit.Reactive/Clients/Enterprise/IObservableEnterpriseManagementConsoleClient.cs @@ -0,0 +1,33 @@ +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Octokit.Reactive +{ + /// + /// A client for GitHub's Enterprise Management Console API + /// + /// + /// See the Enterprise Management Console API documentation for more information. + /// + public interface IObservableEnterpriseManagementConsoleClient + { + /// + /// Gets GitHub Enterprise Maintenance Mode Status + /// + /// + /// https://developer.github.com/v3/enterprise/management_console/#check-maintenance-status + /// + /// The . + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] + IObservable GetMaintenanceMode(string managementConsolePassword); + + /// + /// Sets GitHub Enterprise Maintenance Mode + /// + /// + /// https://developer.github.com/v3/enterprise/management_console/#check-maintenance-status + /// + /// The . + IObservable EditMaintenanceMode(UpdateMaintenanceRequest maintenance, string managementConsolePassword); + } +} diff --git a/Octokit.Reactive/Clients/Enterprise/ObservableEnterpriseClient.cs b/Octokit.Reactive/Clients/Enterprise/ObservableEnterpriseClient.cs index 067e81cf15..e9d01ae29e 100644 --- a/Octokit.Reactive/Clients/Enterprise/ObservableEnterpriseClient.cs +++ b/Octokit.Reactive/Clients/Enterprise/ObservableEnterpriseClient.cs @@ -15,6 +15,7 @@ public ObservableEnterpriseClient(IGitHubClient client) AdminStats = new ObservableEnterpriseAdminStatsClient(client); Ldap = new ObservableEnterpriseLdapClient(client); License = new ObservableEnterpriseLicenseClient(client); + ManagementConsole = new ObservableEnterpriseManagementConsoleClient(client); Organization = new ObservableEnterpriseOrganizationClient(client); SearchIndexing = new ObservableEnterpriseSearchIndexingClient(client); PreReceiveEnvironment = new ObservableEnterprisePreReceiveEnvironmentsClient(client); @@ -25,7 +26,7 @@ public ObservableEnterpriseClient(IGitHubClient client) /// /// /// See the Enterprise Admin Stats API documentation for more information. - /// + /// public IObservableEnterpriseAdminStatsClient AdminStats { get; private set; } /// @@ -33,7 +34,7 @@ public ObservableEnterpriseClient(IGitHubClient client) /// /// /// See the Enterprise LDAP API documentation for more information. - /// + /// public IObservableEnterpriseLdapClient Ldap { get; private set; } /// @@ -41,15 +42,23 @@ public ObservableEnterpriseClient(IGitHubClient client) /// /// /// See the Enterprise License API documentation for more information. - /// + /// public IObservableEnterpriseLicenseClient License { get; private set; } + /// + /// A client for GitHub's Enterprise Management Console API + /// + /// + /// See the Enterprise Management Console API documentation for more information. + /// + public IObservableEnterpriseManagementConsoleClient ManagementConsole { get; private set; } + /// /// A client for GitHub's Enterprise Organization API /// /// /// See the Enterprise Organization API documentation for more information. - /// + /// public IObservableEnterpriseOrganizationClient Organization { get; private set; } /// @@ -57,7 +66,7 @@ public ObservableEnterpriseClient(IGitHubClient client) /// /// /// See the Enterprise Search Indexing API documentation for more information. - /// + /// public IObservableEnterpriseSearchIndexingClient SearchIndexing { get; private set; } /// diff --git a/Octokit.Reactive/Clients/Enterprise/ObservableEnterpriseManagementConsoleClient.cs b/Octokit.Reactive/Clients/Enterprise/ObservableEnterpriseManagementConsoleClient.cs new file mode 100644 index 0000000000..b887da76b9 --- /dev/null +++ b/Octokit.Reactive/Clients/Enterprise/ObservableEnterpriseManagementConsoleClient.cs @@ -0,0 +1,52 @@ +using System; +using System.Reactive.Threading.Tasks; + +namespace Octokit.Reactive +{ + /// + /// A client for GitHub's Enterprise Management Console API + /// + /// + /// See the Enterprise Management Console API documentation for more information. + /// + public class ObservableEnterpriseManagementConsoleClient : IObservableEnterpriseManagementConsoleClient + { + readonly IEnterpriseManagementConsoleClient _client; + + public ObservableEnterpriseManagementConsoleClient(IGitHubClient client) + { + Ensure.ArgumentNotNull(client, "client"); + + _client = client.Enterprise.ManagementConsole; + } + + /// + /// Gets GitHub Enterprise Maintenance Mode Status + /// + /// + /// https://developer.github.com/v3/enterprise/management_console/#check-maintenance-status + /// + /// The . + public IObservable GetMaintenanceMode(string managementConsolePassword) + { + Ensure.ArgumentNotNullOrEmptyString(managementConsolePassword, "managementConsolePassword"); + + return _client.GetMaintenanceMode(managementConsolePassword).ToObservable(); + } + + /// + /// Sets GitHub Enterprise Maintenance Mode + /// + /// + /// https://developer.github.com/v3/enterprise/management_console/#check-maintenance-status + /// + /// The . + public IObservable EditMaintenanceMode(UpdateMaintenanceRequest maintenance, string managementConsolePassword) + { + Ensure.ArgumentNotNull(maintenance, "maintenance"); + Ensure.ArgumentNotNullOrEmptyString(managementConsolePassword, "managementConsolePassword"); + + return _client.EditMaintenanceMode(maintenance, managementConsolePassword).ToObservable(); + } + } +} diff --git a/Octokit.Reactive/Clients/IObservableCheckSuitesClient.cs b/Octokit.Reactive/Clients/IObservableCheckSuitesClient.cs index a40f3853c6..25a2ecc9ec 100644 --- a/Octokit.Reactive/Clients/IObservableCheckSuitesClient.cs +++ b/Octokit.Reactive/Clients/IObservableCheckSuitesClient.cs @@ -101,7 +101,7 @@ public interface IObservableCheckSuitesClient IObservable GetAllForReference(long repositoryId, string reference, CheckSuiteRequest request, ApiOptions options); /// - /// Updates Check Suites prefrences on a repository, such as disabling automatic creation when code is pushed + /// Updates Check Suites preferences on a repository, such as disabling automatic creation when code is pushed /// /// /// See the Check Suites API documentation for more information. @@ -112,7 +112,7 @@ public interface IObservableCheckSuitesClient IObservable UpdatePreferences(string owner, string name, CheckSuitePreferences preferences); /// - /// Updates Check Suites prefrences on a repository, such as disabling automatic creation when code is pushed + /// Updates Check Suites preferences on a repository, such as disabling automatic creation when code is pushed /// /// /// See the Check Suites API documentation for more information. diff --git a/Octokit.Reactive/Clients/IObservableCommitCommentReactionsClient.cs b/Octokit.Reactive/Clients/IObservableCommitCommentReactionsClient.cs index a4df576fff..2488a6fa00 100644 --- a/Octokit.Reactive/Clients/IObservableCommitCommentReactionsClient.cs +++ b/Octokit.Reactive/Clients/IObservableCommitCommentReactionsClient.cs @@ -41,6 +41,17 @@ public interface IObservableCommitCommentReactionsClient /// IObservable GetAll(string owner, string name, int number); + /// + /// List reactions for a specified Commit Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment + /// The owner of the repository + /// The name of the repository + /// The comment id + /// Options for changing the API response + /// + IObservable GetAll(string owner, string name, int number, ApiOptions options); + /// /// List reactions for a specified Commit Comment /// @@ -49,5 +60,15 @@ public interface IObservableCommitCommentReactionsClient /// The comment id /// IObservable GetAll(long repositoryId, int number); + + /// + /// List reactions for a specified Commit Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment + /// The owner of the repository + /// The comment id + /// Options for changing the API response + /// + IObservable GetAll(long repositoryId, int number, ApiOptions options); } } diff --git a/Octokit.Reactive/Clients/IObservableIssueCommentReactionsClient.cs b/Octokit.Reactive/Clients/IObservableIssueCommentReactionsClient.cs index 24294d70b4..6a8f032b90 100644 --- a/Octokit.Reactive/Clients/IObservableIssueCommentReactionsClient.cs +++ b/Octokit.Reactive/Clients/IObservableIssueCommentReactionsClient.cs @@ -38,6 +38,16 @@ public interface IObservableIssueCommentReactionsClient /// The comment id IObservable GetAll(string owner, string name, int number); + /// + /// List reactions for a specified Issue Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment + /// The owner of the repository + /// The name of the repository + /// The comment id + /// Options for changing the API response + IObservable GetAll(string owner, string name, int number, ApiOptions options); + /// /// List reactions for a specified Issue Comment /// @@ -45,5 +55,14 @@ public interface IObservableIssueCommentReactionsClient /// The Id of the repository /// The comment id IObservable GetAll(long repositoryId, int number); + + /// + /// List reactions for a specified Issue Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment + /// The Id of the repository + /// The comment id + /// Options for changing the API response + IObservable GetAll(long repositoryId, int number, ApiOptions options); } } diff --git a/Octokit.Reactive/Clients/IObservableIssueCommentsClient.cs b/Octokit.Reactive/Clients/IObservableIssueCommentsClient.cs index 9f0c2783e8..0744d57a17 100644 --- a/Octokit.Reactive/Clients/IObservableIssueCommentsClient.cs +++ b/Octokit.Reactive/Clients/IObservableIssueCommentsClient.cs @@ -137,6 +137,46 @@ public interface IObservableIssueCommentsClient /// Options for changing the API response IObservable GetAllForIssue(long repositoryId, int number, ApiOptions options); + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The sorting parameters + IObservable GetAllForIssue(string owner, string name, int number, IssueCommentRequest request); + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The Id of the repository + /// The issue number + /// The sorting parameters + IObservable GetAllForIssue(long repositoryId, int number, IssueCommentRequest request); + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The sorting parameters + /// Options for changing the API response + IObservable GetAllForIssue(string owner, string name, int number, IssueCommentRequest request, ApiOptions options); + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The Id of the repository + /// The issue number + /// The sorting parameters + /// Options for changing the API response + IObservable GetAllForIssue(long repositoryId, int number, IssueCommentRequest request, ApiOptions options); + /// /// Creates a new Issue Comment for a specified Issue. /// diff --git a/Octokit.Reactive/Clients/IObservableIssueReactionsClient.cs b/Octokit.Reactive/Clients/IObservableIssueReactionsClient.cs index 4414327365..8d76206408 100644 --- a/Octokit.Reactive/Clients/IObservableIssueReactionsClient.cs +++ b/Octokit.Reactive/Clients/IObservableIssueReactionsClient.cs @@ -19,6 +19,16 @@ public interface IObservableIssueReactionsClient /// The issue id IObservable GetAll(string owner, string name, int number); + /// + /// List reactions for a specified Issue. + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue id + /// Options for changing the API response + IObservable GetAll(string owner, string name, int number, ApiOptions options); + /// /// List reactions for a specified Issue. /// @@ -27,6 +37,15 @@ public interface IObservableIssueReactionsClient /// The issue id IObservable GetAll(long repositoryId, int number); + /// + /// List reactions for a specified Issue. + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue + /// The Id of the repository + /// The issue id + /// Options for changing the API response + IObservable GetAll(long repositoryId, int number, ApiOptions options); + /// /// Creates a reaction for a specified Issue. /// diff --git a/Octokit.Reactive/Clients/IObservableIssuesEventsClient.cs b/Octokit.Reactive/Clients/IObservableIssuesEventsClient.cs index 44c714e3bf..fd59ec338f 100644 --- a/Octokit.Reactive/Clients/IObservableIssuesEventsClient.cs +++ b/Octokit.Reactive/Clients/IObservableIssuesEventsClient.cs @@ -103,10 +103,10 @@ public interface IObservableIssuesEventsClient /// /// The owner of the repository /// The name of the repository - /// The event id + /// The event id [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] - IObservable Get(string owner, string name, int number); + IObservable Get(string owner, string name, long eventId); /// /// Gets a single event @@ -115,9 +115,9 @@ public interface IObservableIssuesEventsClient /// http://developer.github.com/v3/issues/events/#get-a-single-event /// /// The Id of the repository - /// The event id + /// The event id [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] - IObservable Get(long repositoryId, int number); + IObservable Get(long repositoryId, long eventId); } } diff --git a/Octokit.Reactive/Clients/IObservableMigrationsClient.cs b/Octokit.Reactive/Clients/IObservableMigrationsClient.cs index 6174cdfeed..ad44792252 100644 --- a/Octokit.Reactive/Clients/IObservableMigrationsClient.cs +++ b/Octokit.Reactive/Clients/IObservableMigrationsClient.cs @@ -21,7 +21,7 @@ public interface IObservableMigrationsClient /// https://developer.github.com/v3/migration/migrations/#start-a-migration /// /// The organization for which to start a migration. - /// Sprcifies parameters for the migration in a + /// Specifies parameters for the migration in a /// object. /// The started migration. IObservable Start( @@ -29,16 +29,29 @@ IObservable Start( StartMigrationRequest migration); /// - /// Gets the list of the most recent migrations of the the organization. + /// Gets the list of the most recent migrations of the organization. /// /// /// https://developer.github.com/v3/migration/migrations/#get-a-list-of-migrations /// /// The organization of which to list migrations. /// List of most recent s. - IObservable> GetAll( + IObservable GetAll( string org); + /// + /// Gets the list of the most recent migrations of the organization. + /// + /// + /// https://developer.github.com/v3/migration/migrations/#get-a-list-of-migrations + /// + /// The organization of which to list migrations. + /// Options for changing the API response + /// List of most recent s. + IObservable GetAll( + string org, + ApiOptions options); + /// /// Get the status of a migration. /// diff --git a/Octokit.Reactive/Clients/IObservableMiscellaneousClient.cs b/Octokit.Reactive/Clients/IObservableMiscellaneousClient.cs index 25d63bc45f..4fbf18eb66 100644 --- a/Octokit.Reactive/Clients/IObservableMiscellaneousClient.cs +++ b/Octokit.Reactive/Clients/IObservableMiscellaneousClient.cs @@ -53,7 +53,7 @@ public interface IObservableMiscellaneousClient IObservable GetAllLicenses(); /// - /// Retrieves a license based on the license key such as "mit" + /// Retrieves a license based on the license key such as "MIT" /// /// /// A that includes the license key, text, and attributes of the license. diff --git a/Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs b/Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs index 924e7674eb..a775e5f0e7 100644 --- a/Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs +++ b/Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs @@ -265,7 +265,7 @@ public interface IObservableOrganizationMembersClient /// Make the authenticated user's organization membership private. /// /// - /// This method requries authentication. + /// This method requires authentication. /// See the API documentation /// for more information. /// @@ -274,6 +274,50 @@ public interface IObservableOrganizationMembersClient /// IObservable Conceal(string org, string user); + /// + /// Get a user's membership with an organization. + /// + /// + /// This method requires authentication. + /// The authenticated user must be an organization member. + /// See the API documentation + /// for more information. + /// + /// The login for the organization + /// The login for the user + /// + IObservable GetOrganizationMembership(string org, string user); + + /// + /// Add a user to the organization or update the user's role withing the organization. + /// + /// + /// This method requires authentication. + /// The authenticated user must be an organization owner. + /// See the API documentation + /// for more information. + /// + /// The login for the organization + /// The login for the user + /// An instance describing the + /// changes to make to the user's organization membership + /// + IObservable AddOrUpdateOrganizationMembership(string org, string user, OrganizationMembershipUpdate addOrUpdateRequest); + + /// + /// Remove a user's membership with an organization. + /// + /// + /// This method requires authentication. + /// The authenticated user must be an organization owner. + /// See the API documentation + /// for more information. + /// + /// The login for the organization + /// The login for the user + /// + IObservable RemoveOrganizationMembership(string org, string user); + /// /// List all pending invitations for the organization. /// diff --git a/Octokit.Reactive/Clients/IObservableProjectsClient.cs b/Octokit.Reactive/Clients/IObservableProjectsClient.cs index 2172e0868f..19669b426d 100644 --- a/Octokit.Reactive/Clients/IObservableProjectsClient.cs +++ b/Octokit.Reactive/Clients/IObservableProjectsClient.cs @@ -101,7 +101,7 @@ public interface IObservableProjectsClient /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization IObservable GetAllForOrganization(string organization); /// @@ -110,7 +110,7 @@ public interface IObservableProjectsClient /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization /// Used to filter the list of projects returned IObservable GetAllForOrganization(string organization, ProjectRequest request); @@ -120,7 +120,7 @@ public interface IObservableProjectsClient /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization /// Options for changing the API response IObservable GetAllForOrganization(string organization, ApiOptions options); @@ -130,7 +130,7 @@ public interface IObservableProjectsClient /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization /// Used to filter the list of projects returned /// Options for changing the API response IObservable GetAllForOrganization(string organization, ProjectRequest request, ApiOptions options); diff --git a/Octokit.Reactive/Clients/IObservablePullRequestReviewCommentReactionsClient.cs b/Octokit.Reactive/Clients/IObservablePullRequestReviewCommentReactionsClient.cs index 85dff3bb96..ced771bd5c 100644 --- a/Octokit.Reactive/Clients/IObservablePullRequestReviewCommentReactionsClient.cs +++ b/Octokit.Reactive/Clients/IObservablePullRequestReviewCommentReactionsClient.cs @@ -19,6 +19,16 @@ public interface IObservablePullRequestReviewCommentReactionsClient /// The comment id IObservable GetAll(string owner, string name, int number); + /// + /// Get all reactions for a specified Pull Request Review Comment. + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-pull-request-review-comment + /// The owner of the repository + /// The name of the repository + /// The comment id + /// Options for changing the API response + IObservable GetAll(string owner, string name, int number, ApiOptions options); + /// /// Get all reactions for a specified Pull Request Review Comment. /// @@ -27,6 +37,15 @@ public interface IObservablePullRequestReviewCommentReactionsClient /// The comment id IObservable GetAll(long repositoryId, int number); + /// + /// Get all reactions for a specified Pull Request Review Comment. + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-pull-request-review-comment + /// The Id of the repository + /// The comment id + /// Options for changing the API response + IObservable GetAll(long repositoryId, int number, ApiOptions options); + /// /// Creates a reaction for a specified Pull Request Review Comment. /// diff --git a/Octokit.Reactive/Clients/IObservableRepoCollaboratorsClient.cs b/Octokit.Reactive/Clients/IObservableRepoCollaboratorsClient.cs index 49deeb9874..be9e5a3687 100644 --- a/Octokit.Reactive/Clients/IObservableRepoCollaboratorsClient.cs +++ b/Octokit.Reactive/Clients/IObservableRepoCollaboratorsClient.cs @@ -55,6 +55,54 @@ public interface IObservableRepoCollaboratorsClient /// Thrown when a general API error occurs. IObservable GetAll(long repositoryId, ApiOptions options); + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Used to request and filter a list of repository collaborators + /// Thrown when a general API error occurs. + IObservable GetAll(string owner, string name, RepositoryCollaboratorListRequest request); + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the repository + /// Used to request and filter a list of repository collaborators + /// Thrown when a general API error occurs. + IObservable GetAll(long repositoryId, RepositoryCollaboratorListRequest request); + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Used to request and filter a list of repository collaborators + /// Options for changing the API response + /// Thrown when a general API error occurs. + IObservable GetAll(string owner, string name, RepositoryCollaboratorListRequest request, ApiOptions options); + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the repository + /// Used to request and filter a list of repository collaborators + /// Options for changing the API response + /// Thrown when a general API error occurs. + IObservable GetAll(long repositoryId, RepositoryCollaboratorListRequest request, ApiOptions options); + /// /// Checks if a user is a collaborator on a repository. /// diff --git a/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs index 2843a46cb4..7d3218e884 100644 --- a/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs +++ b/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs @@ -201,7 +201,9 @@ public interface IObservableRepositoriesClient IObservableDeploymentsClient Deployment { get; } /// - /// Client for GitHub's Repository Statistics API + /// Client for GitHub's Repository Statistics API. + /// Note that the GitHub API uses caching on these endpoints, + /// see a word about caching for more details. /// /// /// See the Statistics API documentation for more details diff --git a/Octokit.Reactive/Clients/IObservableStatisticsClient.cs b/Octokit.Reactive/Clients/IObservableStatisticsClient.cs index 16460365b9..324fc95170 100644 --- a/Octokit.Reactive/Clients/IObservableStatisticsClient.cs +++ b/Octokit.Reactive/Clients/IObservableStatisticsClient.cs @@ -5,6 +5,8 @@ namespace Octokit.Reactive { /// /// A client for GitHub's Repository Statistics API. + /// Note that the GitHub API uses caching on these endpoints, + /// see a word about caching for more details. /// /// /// See the Repository Statistics API documentation for more information. diff --git a/Octokit.Reactive/Clients/IObservableTagsClient.cs b/Octokit.Reactive/Clients/IObservableTagsClient.cs index 27aca4267b..e2d262f8f4 100644 --- a/Octokit.Reactive/Clients/IObservableTagsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTagsClient.cs @@ -19,7 +19,7 @@ public interface IObservableTagsClient /// /// The owner of the repository /// The name of the repository - /// Tha sha reference of the tag + /// The sha reference of the tag [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] IObservable Get(string owner, string name, string reference); @@ -31,7 +31,7 @@ public interface IObservableTagsClient /// http://developer.github.com/v3/git/tags/#get-a-tag /// /// The Id of the repository - /// Tha sha reference of the tag + /// The sha reference of the tag [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] IObservable Get(long repositoryId, string reference); diff --git a/Octokit.Reactive/Clients/ObservableCommitCommentReactionsClient.cs b/Octokit.Reactive/Clients/ObservableCommitCommentReactionsClient.cs index c17c50057c..8286a52077 100644 --- a/Octokit.Reactive/Clients/ObservableCommitCommentReactionsClient.cs +++ b/Octokit.Reactive/Clients/ObservableCommitCommentReactionsClient.cs @@ -65,11 +65,26 @@ public IObservable Create(long repositoryId, int number, NewReaction r /// The comment id /// public IObservable GetAll(string owner, string name, int number) + { + return GetAll(owner, name, number, ApiOptions.None); + } + + /// + /// List reactions for a specified Commit Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment + /// The owner of the repository + /// The name of the repository + /// The comment id + /// Options for changing the API response + /// + public IObservable GetAll(string owner, string name, int number, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(options, nameof(options)); - return _connection.GetAndFlattenAllPages(ApiUrls.CommitCommentReactions(owner, name, number), null, AcceptHeaders.ReactionsPreview); + return _connection.GetAndFlattenAllPages(ApiUrls.CommitCommentReactions(owner, name, number), null, AcceptHeaders.ReactionsPreview, options); } /// @@ -81,7 +96,22 @@ public IObservable GetAll(string owner, string name, int number) /// public IObservable GetAll(long repositoryId, int number) { - return _connection.GetAndFlattenAllPages(ApiUrls.CommitCommentReactions(repositoryId, number), null, AcceptHeaders.ReactionsPreview); + return GetAll(repositoryId, number, ApiOptions.None); + } + + /// + /// List reactions for a specified Commit Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment + /// The owner of the repository + /// The comment id + /// Options for changing the API response + /// + public IObservable GetAll(long repositoryId, int number, ApiOptions options) + { + Ensure.ArgumentNotNull(options, nameof(options)); + + return _connection.GetAndFlattenAllPages(ApiUrls.CommitCommentReactions(repositoryId, number), null, AcceptHeaders.ReactionsPreview, options); } } } diff --git a/Octokit.Reactive/Clients/ObservableIssueCommentReactionsClient.cs b/Octokit.Reactive/Clients/ObservableIssueCommentReactionsClient.cs index 641e709047..f668948282 100644 --- a/Octokit.Reactive/Clients/ObservableIssueCommentReactionsClient.cs +++ b/Octokit.Reactive/Clients/ObservableIssueCommentReactionsClient.cs @@ -66,7 +66,24 @@ public IObservable GetAll(string owner, string name, int number) Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); - return _connection.GetAndFlattenAllPages(ApiUrls.IssueCommentReactions(owner, name, number), null, AcceptHeaders.ReactionsPreview); + return GetAll(owner, name, number, ApiOptions.None); + } + + /// + /// List reactions for a specified Issue Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment + /// The owner of the repository + /// The name of the repository + /// The comment id + /// Options for changing the API response + public IObservable GetAll(string owner, string name, int number, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(options, nameof(options)); + + return _connection.GetAndFlattenAllPages(ApiUrls.IssueCommentReactions(owner, name, number), null, AcceptHeaders.ReactionsPreview, options); } /// @@ -77,7 +94,21 @@ public IObservable GetAll(string owner, string name, int number) /// The comment id public IObservable GetAll(long repositoryId, int number) { - return _connection.GetAndFlattenAllPages(ApiUrls.IssueCommentReactions(repositoryId, number), null, AcceptHeaders.ReactionsPreview); + return GetAll(repositoryId, number, ApiOptions.None); + } + + /// + /// List reactions for a specified Issue Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment + /// The Id of the repository + /// The comment id + /// Options for changing the API response + public IObservable GetAll(long repositoryId, int number, ApiOptions options) + { + Ensure.ArgumentNotNull(options, nameof(options)); + + return _connection.GetAndFlattenAllPages(ApiUrls.IssueCommentReactions(repositoryId, number), null, AcceptHeaders.ReactionsPreview, options); } } } diff --git a/Octokit.Reactive/Clients/ObservableIssueCommentsClient.cs b/Octokit.Reactive/Clients/ObservableIssueCommentsClient.cs index 5b21cedad9..e87c38bedd 100644 --- a/Octokit.Reactive/Clients/ObservableIssueCommentsClient.cs +++ b/Octokit.Reactive/Clients/ObservableIssueCommentsClient.cs @@ -205,7 +205,7 @@ public IObservable GetAllForIssue(string owner, string name, int n Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNull(options, nameof(options)); - return _connection.GetAndFlattenAllPages(ApiUrls.IssueComments(owner, name, number), null, AcceptHeaders.ReactionsPreview, options); + return GetAllForIssue(owner, name, number, new IssueCommentRequest(), options); } /// @@ -219,7 +219,74 @@ public IObservable GetAllForIssue(long repositoryId, int number, A { Ensure.ArgumentNotNull(options, nameof(options)); - return _connection.GetAndFlattenAllPages(ApiUrls.IssueComments(repositoryId, number), options); + return GetAllForIssue(repositoryId, number, new IssueCommentRequest(), options); + } + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The sorting parameters + public IObservable GetAllForIssue(string owner, string name, int number, IssueCommentRequest request) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAllForIssue(owner, name, number, request, ApiOptions.None); + } + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The Id of the repository + /// The issue number + /// The sorting parameters + public IObservable GetAllForIssue(long repositoryId, int number, IssueCommentRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAllForIssue(repositoryId, number, request, ApiOptions.None); + } + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The sorting parameters + /// Options for changing the API response + public IObservable GetAllForIssue(string owner, string name, int number, IssueCommentRequest request, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + + return _connection.GetAndFlattenAllPages(ApiUrls.IssueComments(owner, name, number), request.ToParametersDictionary(), AcceptHeaders.ReactionsPreview, options); + + } + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The Id of the repository + /// The issue number + /// The sorting parameters + /// Options for changing the API response + public IObservable GetAllForIssue(long repositoryId, int number, IssueCommentRequest request, ApiOptions options) + { + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + + return _connection.GetAndFlattenAllPages(ApiUrls.IssueComments(repositoryId, number), request.ToParametersDictionary(), AcceptHeaders.ReactionsPreview, options); } /// diff --git a/Octokit.Reactive/Clients/ObservableIssueReactionsClient.cs b/Octokit.Reactive/Clients/ObservableIssueReactionsClient.cs index 6d2a3b154b..19de83a003 100644 --- a/Octokit.Reactive/Clients/ObservableIssueReactionsClient.cs +++ b/Octokit.Reactive/Clients/ObservableIssueReactionsClient.cs @@ -31,11 +31,25 @@ public ObservableIssueReactionsClient(IGitHubClient client) /// The name of the repository /// The issue id public IObservable GetAll(string owner, string name, int number) + { + return GetAll(owner, name, number, ApiOptions.None); + } + + /// + /// List reactions for a specified Issue + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue id + /// Options for changing the API response + public IObservable GetAll(string owner, string name, int number, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(options, nameof(options)); - return _connection.GetAndFlattenAllPages(ApiUrls.IssueReactions(owner, name, number), null, AcceptHeaders.ReactionsPreview); + return _connection.GetAndFlattenAllPages(ApiUrls.IssueReactions(owner, name, number), null, AcceptHeaders.ReactionsPreview, options); } /// @@ -46,7 +60,21 @@ public IObservable GetAll(string owner, string name, int number) /// The issue id public IObservable GetAll(long repositoryId, int number) { - return _connection.GetAndFlattenAllPages(ApiUrls.IssueReactions(repositoryId, number), null, AcceptHeaders.ReactionsPreview); + return GetAll(repositoryId, number, ApiOptions.None); + } + + /// + /// List reactions for a specified Issue. + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue + /// The Id of the repository + /// The issue id + /// Options for changing the API response + public IObservable GetAll(long repositoryId, int number, ApiOptions options) + { + Ensure.ArgumentNotNull(options, nameof(options)); + + return _connection.GetAndFlattenAllPages(ApiUrls.IssueReactions(repositoryId, number), null, AcceptHeaders.ReactionsPreview, options); } /// diff --git a/Octokit.Reactive/Clients/ObservableIssuesEventsClient.cs b/Octokit.Reactive/Clients/ObservableIssuesEventsClient.cs index c435c15bb7..8cf89849cc 100644 --- a/Octokit.Reactive/Clients/ObservableIssuesEventsClient.cs +++ b/Octokit.Reactive/Clients/ObservableIssuesEventsClient.cs @@ -157,13 +157,13 @@ public IObservable GetAllForRepository(long repositoryId, ApiOptions /// /// The owner of the repository /// The name of the repository - /// The event id - public IObservable Get(string owner, string name, int number) + /// The event id + public IObservable Get(string owner, string name, long eventId) { Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); - return _client.Get(owner, name, number).ToObservable(); + return _client.Get(owner, name, eventId).ToObservable(); } /// @@ -173,10 +173,10 @@ public IObservable Get(string owner, string name, int number) /// http://developer.github.com/v3/issues/events/#get-a-single-event /// /// The Id of the repository - /// The event id - public IObservable Get(long repositoryId, int number) + /// The event id + public IObservable Get(long repositoryId, long eventId) { - return _client.Get(repositoryId, number).ToObservable(); + return _client.Get(repositoryId, eventId).ToObservable(); } } } \ No newline at end of file diff --git a/Octokit.Reactive/Clients/ObservableMigrationsClient.cs b/Octokit.Reactive/Clients/ObservableMigrationsClient.cs index 93f471af10..fc247b09a0 100644 --- a/Octokit.Reactive/Clients/ObservableMigrationsClient.cs +++ b/Octokit.Reactive/Clients/ObservableMigrationsClient.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Reactive; using System.Reactive.Threading.Tasks; +using Octokit.Reactive.Internal; namespace Octokit.Reactive { @@ -15,6 +16,7 @@ namespace Octokit.Reactive public class ObservableMigrationsClient : IObservableMigrationsClient { private readonly IMigrationsClient _client; + private readonly IConnection _connection; /// /// Instantiates a GitHub Migrations API client. @@ -25,6 +27,7 @@ public ObservableMigrationsClient(IGitHubClient client) Ensure.ArgumentNotNull(client, nameof(client)); _client = client.Migration.Migrations; + _connection = client.Connection; } /// @@ -50,9 +53,16 @@ public IObservable Start(string org, StartMigrationRequest migration) /// /// The organization of which to list migrations. /// List of most recent s. - public IObservable> GetAll(string org) + public IObservable GetAll(string org) { - return _client.GetAll(org).ToObservable(); + return GetAll(org, ApiOptions.None); + } + + public IObservable GetAll(string org, ApiOptions options) + { + Ensure.ArgumentNotNull(options, nameof(options)); + + return _connection.GetAndFlattenAllPages(ApiUrls.EnterpriseMigrations(org), null, AcceptHeaders.MigrationsApiPreview, options); } /// diff --git a/Octokit.Reactive/Clients/ObservableMiscellaneousClient.cs b/Octokit.Reactive/Clients/ObservableMiscellaneousClient.cs index 0795360b15..8bd20c67c0 100644 --- a/Octokit.Reactive/Clients/ObservableMiscellaneousClient.cs +++ b/Octokit.Reactive/Clients/ObservableMiscellaneousClient.cs @@ -78,7 +78,7 @@ public IObservable GetAllLicenses() } /// - /// Retrieves a license based on the license key such as "mit" + /// Retrieves a license based on the license key such as "MIT" /// /// /// A that includes the license key, text, and attributes of the license. diff --git a/Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs b/Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs index 7cf9f03d12..064403740b 100644 --- a/Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs +++ b/Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs @@ -361,7 +361,7 @@ public IObservable Publicize(string org, string user) /// Make the authenticated user's organization membership private. /// /// - /// This method requries authentication. + /// This method requires authentication. /// See the API documentation /// for more information. /// @@ -376,6 +376,69 @@ public IObservable Conceal(string org, string user) return _client.Conceal(org, user).ToObservable(); } + /// + /// Get a user's membership with an organization. + /// + /// + /// This method requires authentication. + /// The authenticated user must be an organization member. + /// See the API documentation + /// for more information. + /// + /// The login for the organization + /// The login for the user + /// + public IObservable GetOrganizationMembership(string org, string user) + { + Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); + Ensure.ArgumentNotNullOrEmptyString(user, nameof(user)); + + return _client.GetOrganizationMembership(org, user).ToObservable(); + } + + /// + /// Add a user to the organization or update the user's role withing the organization. + /// + /// + /// This method requires authentication. + /// The authenticated user must be an organization owner. + /// See the API documentation + /// for more information. + /// + /// The login for the organization + /// The login for the user + /// An instance describing the + /// changes to make to the user's organization membership + /// + public IObservable AddOrUpdateOrganizationMembership(string org, string user, OrganizationMembershipUpdate addOrUpdateRequest) + { + Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); + Ensure.ArgumentNotNullOrEmptyString(user, nameof(user)); + Ensure.ArgumentNotNull(addOrUpdateRequest, nameof(addOrUpdateRequest)); + + return _client.AddOrUpdateOrganizationMembership(org, user, addOrUpdateRequest).ToObservable(); + } + + /// + /// Remove a user's membership with an organization. + /// + /// + /// This method requires authentication. + /// The authenticated user must be an organization owner. + /// See the API documentation + /// for more information. + /// + /// The login for the organization + /// The login for the user + /// + public IObservable RemoveOrganizationMembership(string org, string user) + { + Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); + Ensure.ArgumentNotNullOrEmptyString(user, nameof(user)); + + return _client.RemoveOrganizationMembership(org, user).ToObservable(); + } + /// /// List all pending invitations for the organization. /// diff --git a/Octokit.Reactive/Clients/ObservableProjectsClient.cs b/Octokit.Reactive/Clients/ObservableProjectsClient.cs index 377092d7b6..76d7195400 100644 --- a/Octokit.Reactive/Clients/ObservableProjectsClient.cs +++ b/Octokit.Reactive/Clients/ObservableProjectsClient.cs @@ -175,7 +175,7 @@ public IObservable GetAllForOrganization(string organization) /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization /// Options for changing the API response public IObservable GetAllForOrganization(string organization, ApiOptions options) { @@ -193,7 +193,7 @@ public IObservable GetAllForOrganization(string organization, ApiOption /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization /// Used to filter the list of projects returned public IObservable GetAllForOrganization(string organization, ProjectRequest request) { @@ -206,7 +206,7 @@ public IObservable GetAllForOrganization(string organization, ProjectRe /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization /// Used to filter the list of projects returned /// Options for changing the API response public IObservable GetAllForOrganization(string organization, ProjectRequest request, ApiOptions options) diff --git a/Octokit.Reactive/Clients/ObservablePullRequestReviewCommentReactionsClient.cs b/Octokit.Reactive/Clients/ObservablePullRequestReviewCommentReactionsClient.cs index b81169ad80..1be8335d2d 100644 --- a/Octokit.Reactive/Clients/ObservablePullRequestReviewCommentReactionsClient.cs +++ b/Octokit.Reactive/Clients/ObservablePullRequestReviewCommentReactionsClient.cs @@ -31,11 +31,17 @@ public ObservablePullRequestReviewCommentReactionsClient(IGitHubClient client) /// The name of the repository /// The comment id public IObservable GetAll(string owner, string name, int number) + { + return GetAll(owner, name, number, ApiOptions.None); + } + + public IObservable GetAll(string owner, string name, int number, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(options, nameof(options)); - return _connection.GetAndFlattenAllPages(ApiUrls.PullRequestReviewCommentReaction(owner, name, number), null, AcceptHeaders.ReactionsPreview); + return _connection.GetAndFlattenAllPages(ApiUrls.PullRequestReviewCommentReaction(owner, name, number), null, AcceptHeaders.ReactionsPreview, options); } /// @@ -46,7 +52,21 @@ public IObservable GetAll(string owner, string name, int number) /// The comment id public IObservable GetAll(long repositoryId, int number) { - return _connection.GetAndFlattenAllPages(ApiUrls.PullRequestReviewCommentReaction(repositoryId, number), null, AcceptHeaders.ReactionsPreview); + return GetAll(repositoryId, number, ApiOptions.None); + } + + /// + /// Get all reactions for a specified Pull Request Review Comment. + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-pull-request-review-comment + /// The Id of the repository + /// The comment id + /// Options for changing the API response + public IObservable GetAll(long repositoryId, int number, ApiOptions options) + { + Ensure.ArgumentNotNull(options, nameof(options)); + + return _connection.GetAndFlattenAllPages(ApiUrls.PullRequestReviewCommentReaction(repositoryId, number), null, AcceptHeaders.ReactionsPreview, options); } /// diff --git a/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs b/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs index e6b77d3fae..96a1bd3fa2 100644 --- a/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs +++ b/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs @@ -111,7 +111,7 @@ public IObservable GetAllForRepository(string owner, string name, A Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNull(options, nameof(options)); - return _connection.GetAndFlattenAllPages(ApiUrls.PullRequests(owner, name), options); + return _connection.GetAndFlattenAllPages(ApiUrls.PullRequests(owner, name), null, AcceptHeaders.DraftPullRequestApiPreview, options); } /// @@ -126,7 +126,7 @@ public IObservable GetAllForRepository(long repositoryId, ApiOption { Ensure.ArgumentNotNull(options, nameof(options)); - return _connection.GetAndFlattenAllPages(ApiUrls.PullRequests(repositoryId), options); + return _connection.GetAndFlattenAllPages(ApiUrls.PullRequests(repositoryId), null, AcceptHeaders.DraftPullRequestApiPreview, options); } /// @@ -180,7 +180,7 @@ public IObservable GetAllForRepository(string owner, string name, P Ensure.ArgumentNotNull(options, nameof(options)); return _connection.GetAndFlattenAllPages(ApiUrls.PullRequests(owner, name), - request.ToParametersDictionary(), options); + request.ToParametersDictionary(), AcceptHeaders.DraftPullRequestApiPreview, options); } /// @@ -198,7 +198,7 @@ public IObservable GetAllForRepository(long repositoryId, PullReque Ensure.ArgumentNotNull(options, nameof(options)); return _connection.GetAndFlattenAllPages(ApiUrls.PullRequests(repositoryId), - request.ToParametersDictionary(), options); + request.ToParametersDictionary(), AcceptHeaders.DraftPullRequestApiPreview, options); } /// diff --git a/Octokit.Reactive/Clients/ObservableRepoCollaboratorsClient.cs b/Octokit.Reactive/Clients/ObservableRepoCollaboratorsClient.cs index 719d8614bc..e19666a420 100644 --- a/Octokit.Reactive/Clients/ObservableRepoCollaboratorsClient.cs +++ b/Octokit.Reactive/Clients/ObservableRepoCollaboratorsClient.cs @@ -74,7 +74,7 @@ public IObservable GetAll(string owner, string name, ApiOptions options) Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNull(options, nameof(options)); - return _connection.GetAndFlattenAllPages(ApiUrls.RepoCollaborators(owner, name), options); + return GetAll(owner, name, new RepositoryCollaboratorListRequest(), options); } /// @@ -90,7 +90,81 @@ public IObservable GetAll(long repositoryId, ApiOptions options) { Ensure.ArgumentNotNull(options, nameof(options)); - return _connection.GetAndFlattenAllPages(ApiUrls.RepoCollaborators(repositoryId), options); + return GetAll(repositoryId, new RepositoryCollaboratorListRequest(), options); + } + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Used to request and filter a list of repository collaborators + /// Thrown when a general API error occurs. + public IObservable GetAll(string owner, string name, RepositoryCollaboratorListRequest request) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAll(owner, name, request, ApiOptions.None); + } + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the repository + /// Used to request and filter a list of repository collaborators + /// Thrown when a general API error occurs. + public IObservable GetAll(long repositoryId, RepositoryCollaboratorListRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAll(repositoryId, request, ApiOptions.None); + } + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Used to request and filter a list of repository collaborators + /// Options for changing the API response + /// Thrown when a general API error occurs. + public IObservable GetAll(string owner, string name, RepositoryCollaboratorListRequest request, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + + return _connection.GetAndFlattenAllPages(ApiUrls.RepoCollaborators(owner, name), request.ToParametersDictionary(), AcceptHeaders.NestedTeamsPreview, options); + } + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the repository + /// Used to request and filter a list of repository collaborators + /// Options for changing the API response + /// Thrown when a general API error occurs. + public IObservable GetAll(long repositoryId, RepositoryCollaboratorListRequest request, ApiOptions options) + { + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + + return _connection.GetAndFlattenAllPages(ApiUrls.RepoCollaborators(repositoryId), request.ToParametersDictionary(), AcceptHeaders.NestedTeamsPreview, options); } /// diff --git a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs index e6f07b9daa..1f399145d2 100644 --- a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs +++ b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs @@ -315,6 +315,8 @@ public IObservable GetAllForOrg(string organization, ApiOptions opti /// /// Client for GitHub's Repository Statistics API + /// Note that the GitHub API uses caching on these endpoints, + /// see a word about caching for more details. /// /// /// See the Statistics API documentation for more details diff --git a/Octokit.Reactive/Clients/ObservableSearchClient.cs b/Octokit.Reactive/Clients/ObservableSearchClient.cs index 9f9b2c7f32..ff40d5817e 100644 --- a/Octokit.Reactive/Clients/ObservableSearchClient.cs +++ b/Octokit.Reactive/Clients/ObservableSearchClient.cs @@ -4,7 +4,7 @@ namespace Octokit.Reactive { /// - /// GitHub Search Api Client + /// GitHub Search API Client /// public class ObservableSearchClient : IObservableSearchClient { diff --git a/Octokit.Reactive/Clients/ObservableStatisticsClient.cs b/Octokit.Reactive/Clients/ObservableStatisticsClient.cs index e1f3b3bf88..4f5f98b8c6 100644 --- a/Octokit.Reactive/Clients/ObservableStatisticsClient.cs +++ b/Octokit.Reactive/Clients/ObservableStatisticsClient.cs @@ -6,6 +6,8 @@ namespace Octokit.Reactive { /// /// A client for GitHub's Repository Statistics API. + /// Note that the GitHub API uses caching on these endpoints, + /// see a word about caching for more details. /// /// /// See the Repository Statistics API documentation for more information. diff --git a/Octokit.Reactive/Octokit.Reactive.csproj b/Octokit.Reactive/Octokit.Reactive.csproj index 33b4f859b7..53f67b96c4 100644 --- a/Octokit.Reactive/Octokit.Reactive.csproj +++ b/Octokit.Reactive/Octokit.Reactive.csproj @@ -6,18 +6,27 @@ GitHub 0.0.0-dev true - netstandard1.1;net45 - 1.6.0 + netstandard1.1;netstandard2.0;net45;net46 Octokit.Reactive Octokit.Reactive embedded https://github.com/octokit/octokit.net https://github.com/octokit/octokit.net https://f.cloud.github.com/assets/19977/1510987/64af2b26-4a9d-11e3-89fc-96a185171c75.png + octokit.png + MIT GitHub API Octokit linqpad-samples dotnetcore Copyright GitHub 2017 + + 1.6.0 + + + + 2.0.0 + + 1591;1701;1702;1705 @@ -31,16 +40,20 @@ + + + + - - - + - + + + diff --git a/Octokit.Reactive/images/octokit.png b/Octokit.Reactive/images/octokit.png new file mode 100644 index 0000000000..2efc9cfc0c Binary files /dev/null and b/Octokit.Reactive/images/octokit.png differ diff --git a/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj b/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj index 9ec5bb01ea..7f870ff27a 100644 --- a/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj +++ b/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj @@ -4,7 +4,7 @@ Convention-based tests for Octokit Octokit.Tests.Conventions GitHub - netcoreapp2.0;net452 + netcoreapp3.1;net452 $(NoWarn);CS4014;CS1998 Octokit.Tests.Conventions Octokit.Tests.Conventions @@ -33,9 +33,13 @@ - - - + + + + + + + diff --git a/Octokit.Tests.Integration/Clients/AssigneesClientTests.cs b/Octokit.Tests.Integration/Clients/AssigneesClientTests.cs index cc0c2f3e13..584bd51e7f 100644 --- a/Octokit.Tests.Integration/Clients/AssigneesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/AssigneesClientTests.cs @@ -50,7 +50,7 @@ public async Task CanListAssignees() { // Repository owner is always an assignee var assignees = await _github.Issue.Assignee.GetAllForRepository(_context.RepositoryOwner, _context.RepositoryName); - Assert.True(assignees.Any(u => u.Login == Helper.UserName)); + Assert.Contains(assignees, u => u.Login == Helper.UserName); } [IntegrationTest] @@ -69,19 +69,20 @@ public async Task CanAddAndRemoveAssignees() Assert.IsType(addAssignees); //Check if assignee was added to issue - Assert.True(addAssignees.Assignees.Any(x => x.Login == _context.RepositoryOwner)); + Assert.Contains(addAssignees.Assignees, x => x.Login == _context.RepositoryOwner); //Test to remove assignees var removeAssignees = await _github.Issue.Assignee.RemoveAssignees(_context.RepositoryOwner, _context.RepositoryName, issue.Number, newAssignees); //Check if assignee was removed - Assert.False(removeAssignees.Assignees.Any(x => x.Login == _context.RepositoryOwner)); + Assert.DoesNotContain(removeAssignees.Assignees, x => x.Login == _context.RepositoryOwner); } + [IntegrationTest] public async Task CanListAssigneesWithRepositoryId() { // Repository owner is always an assignee var assignees = await _github.Issue.Assignee.GetAllForRepository(_context.Repository.Id); - Assert.True(assignees.Any(u => u.Login == Helper.UserName)); + Assert.Contains(assignees, u => u.Login == Helper.UserName); } } \ No newline at end of file diff --git a/Octokit.Tests.Integration/Clients/AuthorizationClientTests.cs b/Octokit.Tests.Integration/Clients/AuthorizationClientTests.cs index f84d1b7ebd..2dba512431 100644 --- a/Octokit.Tests.Integration/Clients/AuthorizationClientTests.cs +++ b/Octokit.Tests.Integration/Clients/AuthorizationClientTests.cs @@ -69,7 +69,7 @@ public async Task CannotCreatePersonalTokenWhenUsingOauthTokenCredentials() new[] { "user" }); var error = await Assert.ThrowsAsync(() => github.Authorization.Create(newAuthorization)); - Assert.True(error.Message.Contains("username and password Basic Auth")); + Assert.Contains("username and password Basic Auth", error.Message); } [BasicAuthenticationTest(Skip = "See https://github.com/octokit/octokit.net/issues/1000 for issue to investigate this further")] diff --git a/Octokit.Tests.Integration/Clients/CheckSuitesClientTests.cs b/Octokit.Tests.Integration/Clients/CheckSuitesClientTests.cs index 1512dc8ebf..52a97b03ab 100644 --- a/Octokit.Tests.Integration/Clients/CheckSuitesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/CheckSuitesClientTests.cs @@ -131,7 +131,7 @@ public async Task UpdatesPreferences() Assert.Equal(repoContext.RepositoryId, result.Repository.Id); Assert.Equal(Helper.GitHubAppId, result.Preferences.AutoTriggerChecks[0].AppId); - Assert.Equal(false, result.Preferences.AutoTriggerChecks[0].Setting); + Assert.False(result.Preferences.AutoTriggerChecks[0].Setting); } } @@ -148,7 +148,7 @@ public async Task UpdatesPreferencesWithRepositoryId() Assert.Equal(repoContext.RepositoryId, result.Repository.Id); Assert.Equal(Helper.GitHubAppId, result.Preferences.AutoTriggerChecks[0].AppId); - Assert.Equal(false, result.Preferences.AutoTriggerChecks[0].Setting); + Assert.False(result.Preferences.AutoTriggerChecks[0].Setting); } } } diff --git a/Octokit.Tests.Integration/Clients/CommitCommentReactionsClientTests.cs b/Octokit.Tests.Integration/Clients/CommitCommentReactionsClientTests.cs index 6c3e169c06..ebf204ca19 100644 --- a/Octokit.Tests.Integration/Clients/CommitCommentReactionsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/CommitCommentReactionsClientTests.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Octokit; using Octokit.Tests.Integration; @@ -68,6 +70,110 @@ public async Task CanListReactions() Assert.Equal(reaction.Content, reactions[0].Content); } + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithoutStart() + { + var commit = await SetupCommitForRepository(_github); + + var comment = new NewCommitComment("test"); + + var result = await _github.Repository.Comment.Create(_context.RepositoryOwner, _context.RepositoryName, + commit.Sha, comment); + + Assert.NotNull(result); + + var newReaction = new NewReaction(ReactionType.Confused); + var reaction = await _github.Reaction.CommitComment.Create(_context.RepositoryOwner, _context.RepositoryName, result.Id, newReaction); + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1 + }; + var reactions = await _github.Reaction.CommitComment.GetAll(_context.RepositoryOwner, _context.RepositoryName, result.Id, options); + + Assert.Equal(1, reactions.Count); + + Assert.Equal(reaction.Id, reactions[0].Id); + Assert.Equal(reaction.Content, reactions[0].Content); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithStart() + { + var commit = await SetupCommitForRepository(_github); + + var comment = new NewCommitComment("test"); + + var result = await _github.Repository.Comment.Create(_context.RepositoryOwner, _context.RepositoryName, + commit.Sha, comment); + + Assert.NotNull(result); + + var reactions = new List(); + var reactionsContent = new[] { ReactionType.Confused, ReactionType.Hooray }; + for (var i = 0; i < 2; i++) + { + var newReaction = new NewReaction(reactionsContent[i]); + var reaction = await _github.Reaction.CommitComment.Create(_context.RepositoryOwner, _context.RepositoryName, result.Id, newReaction); + reactions.Add(reaction); + } + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + var reactionsInfo = await _github.Reaction.CommitComment.GetAll(_context.RepositoryOwner, _context.RepositoryName, result.Id, options); + + Assert.Equal(1, reactionsInfo.Count); + + Assert.Equal(reactions.Last().Id, reactionsInfo[0].Id); + Assert.Equal(reactions.Last().Content, reactionsInfo[0].Content); + } + + [IntegrationTest] + public async Task ReturnsDistinctReactionsBasedOnStartPage() + { + var commit = await SetupCommitForRepository(_github); + + var comment = new NewCommitComment("test"); + + var result = await _github.Repository.Comment.Create(_context.RepositoryOwner, _context.RepositoryName, + commit.Sha, comment); + + Assert.NotNull(result); + + var reactionsContent = new[] { ReactionType.Confused, ReactionType.Hooray }; + for (var i = 0; i < 2; i++) + { + var newReaction = new NewReaction(reactionsContent[i]); + var reaction = await _github.Reaction.CommitComment.Create(_context.RepositoryOwner, _context.RepositoryName, result.Id, newReaction); + } + + var startOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 1 + }; + var firstPage = await _github.Reaction.CommitComment.GetAll(_context.RepositoryOwner, _context.RepositoryName, result.Id, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 1 + }; + var secondPage = await _github.Reaction.CommitComment.GetAll(_context.RepositoryOwner, _context.RepositoryName, result.Id, skipStartOptions); + + Assert.Equal(1, firstPage.Count); + Assert.Equal(1, secondPage.Count); + Assert.NotEqual(firstPage[0].Id, secondPage[0].Id); + Assert.NotEqual(firstPage[0].Content, secondPage[0].Content); + } + [IntegrationTest] public async Task CanListReactionsWithRepositoryId() { @@ -92,6 +198,109 @@ public async Task CanListReactionsWithRepositoryId() Assert.Equal(reaction.Content, reactions[0].Content); } + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithoutStartWithRepositoryId() + { + var commit = await SetupCommitForRepository(_github); + + var comment = new NewCommitComment("test"); + + var result = await _github.Repository.Comment.Create(_context.RepositoryOwner, _context.RepositoryName, + commit.Sha, comment); + + Assert.NotNull(result); + + var newReaction = new NewReaction(ReactionType.Confused); + var reaction = await _github.Reaction.CommitComment.Create(_context.Repository.Id, result.Id, newReaction); + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1 + }; + var reactions = await _github.Reaction.CommitComment.GetAll(_context.Repository.Id, result.Id, options); + + Assert.Equal(1, reactions.Count); + + Assert.Equal(reaction.Id, reactions[0].Id); + Assert.Equal(reaction.Content, reactions[0].Content); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithStartWithRepositoryId() + { + var commit = await SetupCommitForRepository(_github); + + var comment = new NewCommitComment("test"); + + var result = await _github.Repository.Comment.Create(_context.RepositoryOwner, _context.RepositoryName, + commit.Sha, comment); + + Assert.NotNull(result); + + var reactions = new List(); + var reactionsContent = new[] { ReactionType.Confused, ReactionType.Hooray }; + for (var i = 0; i < 2; i++) + { + var newReaction = new NewReaction(reactionsContent[i]); + var reaction = await _github.Reaction.CommitComment.Create(_context.Repository.Id, result.Id, newReaction); + reactions.Add(reaction); + } + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + var reactionsInfo = await _github.Reaction.CommitComment.GetAll(_context.Repository.Id, result.Id, options); + + Assert.Equal(1, reactionsInfo.Count); + + Assert.Equal(reactions.Last().Id, reactionsInfo[0].Id); + Assert.Equal(reactions.Last().Content, reactionsInfo[0].Content); + } + + [IntegrationTest] + public async Task ReturnsDistinctReactionsBasedOnStartPageWithRepositoryId() + { + var commit = await SetupCommitForRepository(_github); + + var comment = new NewCommitComment("test"); + + var result = await _github.Repository.Comment.Create(_context.RepositoryOwner, _context.RepositoryName, + commit.Sha, comment); + + Assert.NotNull(result); + + var reactionsContent = new[] { ReactionType.Confused, ReactionType.Hooray }; + for (var i = 0; i < 2; i++) + { + var newReaction = new NewReaction(reactionsContent[i]); + var reaction = await _github.Reaction.CommitComment.Create(_context.Repository.Id, result.Id, newReaction); + } + + var startOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 1 + }; + var firstPage = await _github.Reaction.CommitComment.GetAll(_context.Repository.Id, result.Id, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 1 + }; + var secondPage = await _github.Reaction.CommitComment.GetAll(_context.Repository.Id, result.Id, skipStartOptions); + + Assert.Equal(1, firstPage.Count); + Assert.Equal(1, secondPage.Count); + Assert.NotEqual(firstPage[0].Id, secondPage[0].Id); + Assert.NotEqual(firstPage[0].Content, secondPage[0].Content); + } [IntegrationTest] public async Task CanCreateReaction() { diff --git a/Octokit.Tests.Integration/Clients/CommitsClientTests.cs b/Octokit.Tests.Integration/Clients/CommitsClientTests.cs index c75eb16baa..c2759a7fd7 100644 --- a/Octokit.Tests.Integration/Clients/CommitsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/CommitsClientTests.cs @@ -52,13 +52,13 @@ public async Task CanDeserializeVerificationObjectInResponse() var commit = await github.Git.Commit.Get("noonari", "Signature-Verification", "1965d149ce1151cf411300d15f8d890d9259bd21"); Assert.False(commit.Verification.Verified); - Assert.Equal(commit.Verification.Signature, - "-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v1\n\niQEcBAABAgAGBQJXYT2BAAoJEJyZ1vxIV0+N9ZwIAKlf3dk9n1q1mD5AT3Ahtj9o\nF4H25zsHynJk2lnH4YxVvDBEc/uMCXzX6orihZiSdA5UXE7tPyEEZddQdp8pxulX\ncIsFKcrfQqHJnTbT90z5PhAk94lyN9fFngzPW1tgZZVjp2YiiqgXduBWWm6EREOh\nS1Iu9wBqScQomhTXoksmNZyGTZ0LviSi0pkqRY64pQhKnpLlu1OFXaeDvhYocB+E\nY5URZsXodvIkBuzCkWCu8ra4eaXIIARkas4+jIvn0FIx9CzEVz0Zau/5Fk+BR+Te\n7a3/7JH7yuObPB0hqPSuFYyxtvPfxtayvhkGD3YkQqDAkWCpISGyVFzxrrC7z0Y=\n=kbih\n-----END PGP SIGNATURE-----"); + Assert.Equal("-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v1\n\niQEcBAABAgAGBQJXYT2BAAoJEJyZ1vxIV0+N9ZwIAKlf3dk9n1q1mD5AT3Ahtj9o\nF4H25zsHynJk2lnH4YxVvDBEc/uMCXzX6orihZiSdA5UXE7tPyEEZddQdp8pxulX\ncIsFKcrfQqHJnTbT90z5PhAk94lyN9fFngzPW1tgZZVjp2YiiqgXduBWWm6EREOh\nS1Iu9wBqScQomhTXoksmNZyGTZ0LviSi0pkqRY64pQhKnpLlu1OFXaeDvhYocB+E\nY5URZsXodvIkBuzCkWCu8ra4eaXIIARkas4+jIvn0FIx9CzEVz0Zau/5Fk+BR+Te\n7a3/7JH7yuObPB0hqPSuFYyxtvPfxtayvhkGD3YkQqDAkWCpISGyVFzxrrC7z0Y=\n=kbih\n-----END PGP SIGNATURE-----", + commit.Verification.Signature); - Assert.Equal(commit.Verification.Payload, - "tree c91c844f37974093a3f0a864755441b577e7663a\nparent 6eb645f6badd46de65700b4d7b6fcdb97684ce5a\nauthor noonari 1465990529 +0500\ncommitter noonari 1465990529 +0500\n\ngpg stuff\n"); + Assert.Equal("tree c91c844f37974093a3f0a864755441b577e7663a\nparent 6eb645f6badd46de65700b4d7b6fcdb97684ce5a\nauthor noonari 1465990529 +0500\ncommitter noonari 1465990529 +0500\n\ngpg stuff\n", + commit.Verification.Payload); - Assert.Equal(commit.Verification.Reason, VerificationReason.UnknownKey); + Assert.Equal(VerificationReason.UnknownKey, commit.Verification.Reason); } [IntegrationTest] diff --git a/Octokit.Tests.Integration/Clients/Enterprise/EnterpriseManagementConsoleClientTests.cs b/Octokit.Tests.Integration/Clients/Enterprise/EnterpriseManagementConsoleClientTests.cs new file mode 100644 index 0000000000..c35f3f6769 --- /dev/null +++ b/Octokit.Tests.Integration/Clients/Enterprise/EnterpriseManagementConsoleClientTests.cs @@ -0,0 +1,88 @@ +using System; +using System.Threading.Tasks; +using Octokit; +using Octokit.Tests.Integration; +using Octokit.Tests.Integration.Helpers; +using Xunit; + +public class EnterpriseManagementConsoleClientTests +{ + readonly IGitHubClient _github; + + public EnterpriseManagementConsoleClientTests() + { + _github = EnterpriseHelper.GetAuthenticatedClient(); + } + + [GitHubEnterpriseManagementConsoleTest] + public async Task CanGetMaintenanceMode() + { + var maintenance = await _github.Enterprise.ManagementConsole.GetMaintenanceMode(EnterpriseHelper.ManagementConsolePassword); + + Assert.NotNull(maintenance); + } + + [GitHubEnterpriseManagementConsoleTest] + public async Task CanSetMaintenanceModeOff() + { + using (_github.CreateMaintenanceModeContext(true)) + { + // Set maintenance mode OFF now + var maintenance = await + _github.Enterprise.ManagementConsole.EditMaintenanceMode( + new UpdateMaintenanceRequest(), + EnterpriseHelper.ManagementConsolePassword); + + Assert.Equal(MaintenanceModeStatus.Off, maintenance.Status); + } + } + + [GitHubEnterpriseManagementConsoleTest] + public async Task CanSetMaintenanceModeOnNow() + { + using (_github.CreateMaintenanceModeContext(false)) + { + // Set maintenance mode ON now + var maintenance = await + _github.Enterprise.ManagementConsole.EditMaintenanceMode( + new UpdateMaintenanceRequest( + new UpdateMaintenanceRequestDetails(true)), + EnterpriseHelper.ManagementConsolePassword); + + Assert.Equal(MaintenanceModeStatus.On, maintenance.Status); + } + } + + [GitHubEnterpriseManagementConsoleTest] + public async Task CanScheduleMaintenanceModeOnWithDateTime() + { + using (_github.CreateMaintenanceModeContext(false)) + { + // Schedule maintenance mode ON in 5 minutes + var scheduledTime = DateTimeOffset.Now.AddMinutes(5); + var maintenance = await + _github.Enterprise.ManagementConsole.EditMaintenanceMode( + new UpdateMaintenanceRequest( + new UpdateMaintenanceRequestDetails(true, scheduledTime)), + EnterpriseHelper.ManagementConsolePassword); + + Assert.Equal(MaintenanceModeStatus.Scheduled, maintenance.Status); + } + } + + [GitHubEnterpriseManagementConsoleTest] + public async Task CanScheduleMaintenanceModeOnWithPhrase() + { + using (_github.CreateMaintenanceModeContext(false)) + { + // Schedule maintenance mode ON with phrase + var maintenance = await + _github.Enterprise.ManagementConsole.EditMaintenanceMode( + new UpdateMaintenanceRequest( + new UpdateMaintenanceRequestDetails(true, "tomorrow at 5pm")), + EnterpriseHelper.ManagementConsolePassword); + + Assert.Equal(MaintenanceModeStatus.Scheduled, maintenance.Status); + } + } +} \ No newline at end of file diff --git a/Octokit.Tests.Integration/Clients/FollowersClientTests.cs b/Octokit.Tests.Integration/Clients/FollowersClientTests.cs index 6ced87945f..56b174ec0f 100644 --- a/Octokit.Tests.Integration/Clients/FollowersClientTests.cs +++ b/Octokit.Tests.Integration/Clients/FollowersClientTests.cs @@ -24,7 +24,7 @@ public async Task ReturnsUsersTheCurrentUserIsFollowing() var following = await _github.User.Followers.GetAllFollowingForCurrent(); Assert.NotNull(following); - Assert.True(following.Any(f => f.Login == "alfhenrik")); + Assert.Contains(following, f => f.Login == "alfhenrik"); } [IntegrationTest] @@ -44,7 +44,7 @@ public async Task ReturnsUsersFollowingTheUser() var followers = await _github.User.Followers.GetAll("alfhenrik"); Assert.NotEmpty(followers); - Assert.True(followers.Any(f => f.Login == _currentUser.Login)); + Assert.Contains(followers, f => f.Login == _currentUser.Login); } [IntegrationTest] @@ -73,7 +73,7 @@ public async Task FollowUserNotBeingFollowedByTheUser() Assert.True(result); Assert.NotEmpty(following); - Assert.True(following.Any(f => f.Login == "alfhenrik")); + Assert.Contains(following, f => f.Login == "alfhenrik"); } [IntegrationTest] @@ -81,18 +81,18 @@ public async Task UnfollowUserBeingFollowedByTheUser() { await _github.User.Followers.Follow("alfhenrik"); var followers = await _github.User.Followers.GetAll("alfhenrik"); - Assert.True(followers.Any(f => f.Login == _currentUser.Login)); + Assert.Contains(followers, f => f.Login == _currentUser.Login); await _github.User.Followers.Unfollow("alfhenrik"); followers = await _github.User.Followers.GetAll("alfhenrik"); - Assert.False(followers.Any(f => f.Login == _currentUser.Login)); + Assert.DoesNotContain(followers, f => f.Login == _currentUser.Login); } [IntegrationTest] public async Task UnfollowUserNotBeingFollowedTheUser() { var followers = await _github.User.Followers.GetAll("alfhenrik"); - Assert.False(followers.Any(f => f.Login == _currentUser.Login)); + Assert.DoesNotContain(followers, f => f.Login == _currentUser.Login); await _github.User.Followers.Unfollow("alfhenrik"); } diff --git a/Octokit.Tests.Integration/Clients/GistsClientTests.cs b/Octokit.Tests.Integration/Clients/GistsClientTests.cs index c99c53c02b..8cceb17841 100644 --- a/Octokit.Tests.Integration/Clients/GistsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/GistsClientTests.cs @@ -109,11 +109,11 @@ public async Task CanListGists() var starredGists = await _fixture.GetAllStarred(); Assert.NotNull(starredGists); - Assert.True(starredGists.Any(x => x.Id == createdGist.Id)); + Assert.Contains(starredGists, x => x.Id == createdGist.Id); var starredGistsSinceStartTime = await _fixture.GetAllStarred(startTime); Assert.NotNull(starredGistsSinceStartTime); - Assert.True(starredGistsSinceStartTime.Any(x => x.Id == createdGist.Id)); + Assert.Contains(starredGistsSinceStartTime, x => x.Id == createdGist.Id); await _fixture.Delete(createdGist.Id); } diff --git a/Octokit.Tests.Integration/Clients/GitHubClientTests.cs b/Octokit.Tests.Integration/Clients/GitHubClientTests.cs index 7526afc763..bf3c61900f 100644 --- a/Octokit.Tests.Integration/Clients/GitHubClientTests.cs +++ b/Octokit.Tests.Integration/Clients/GitHubClientTests.cs @@ -32,7 +32,7 @@ public async Task CanRetrieveLastApiInfoWithEtag() Assert.False(string.IsNullOrEmpty(result.Etag)); Assert.True(result.RateLimit.Limit > 0); Assert.True(result.RateLimit.Remaining > -1); - Assert.NotNull(result.RateLimit.Reset); + Assert.NotEqual(default, result.RateLimit.Reset); } } @@ -53,7 +53,7 @@ public async Task CanRetrieveLastApiInfoWithLinks() Assert.False(string.IsNullOrEmpty(result.Etag)); Assert.True(result.RateLimit.Limit > 0); Assert.True(result.RateLimit.Remaining > -1); - Assert.NotNull(result.RateLimit.Reset); + Assert.NotEqual(default, result.RateLimit.Reset); } [PersonalAccessTokenTest] @@ -73,7 +73,7 @@ public async Task CanRetrieveLastApiInfoAcceptedOauth() Assert.False(string.IsNullOrEmpty(result.Etag)); Assert.True(result.RateLimit.Limit > 0); Assert.True(result.RateLimit.Remaining > -1); - Assert.NotNull(result.RateLimit.Reset); + Assert.NotEqual(default, result.RateLimit.Reset); } } } diff --git a/Octokit.Tests.Integration/Clients/IssueCommentReactionsClientTests.cs b/Octokit.Tests.Integration/Clients/IssueCommentReactionsClientTests.cs index 7965c6fe33..472218a010 100644 --- a/Octokit.Tests.Integration/Clients/IssueCommentReactionsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/IssueCommentReactionsClientTests.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Octokit; using Octokit.Tests.Integration; @@ -44,6 +46,109 @@ public async Task CanListReactions() Assert.Equal(reactions[0].Content, issueCommentReaction.Content); } + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithoutStart() + { + var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" }; + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); + + Assert.NotNull(issue); + + var issueComment = await _issuesClient.Comment.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, "A test comment"); + + Assert.NotNull(issueComment); + + var issueCommentReaction = await _github.Reaction.IssueComment.Create(_context.RepositoryOwner, _context.RepositoryName, issueComment.Id, new NewReaction(ReactionType.Heart)); + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1 + }; + + var reactions = await _github.Reaction.IssueComment.GetAll(_context.RepositoryOwner, _context.RepositoryName, issueComment.Id, options); + + Assert.Equal(1, reactions.Count); + + Assert.Equal(reactions[0].Id, issueCommentReaction.Id); + Assert.Equal(reactions[0].Content, issueCommentReaction.Content); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithStart() + { + var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" }; + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); + + Assert.NotNull(issue); + + var issueComment = await _issuesClient.Comment.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, "A test comment"); + + Assert.NotNull(issueComment); + + var reactions = new List(); + var reactionsContent = new[] { ReactionType.Heart, ReactionType.Plus1 }; + for (var i = 0; i < 2; i++) + { + var issueCommentReaction = await _github.Reaction.IssueComment.Create(_context.RepositoryOwner, _context.RepositoryName, issueComment.Id, new NewReaction(reactionsContent[i])); + reactions.Add(issueCommentReaction); + } + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + + var reactionsInfo = await _github.Reaction.IssueComment.GetAll(_context.RepositoryOwner, _context.RepositoryName, issueComment.Id, options); + + Assert.Equal(1, reactionsInfo.Count); + + Assert.Equal(reactionsInfo[0].Id, reactions.Last().Id); + Assert.Equal(reactionsInfo[0].Content, reactions.Last().Content); + } + + [IntegrationTest] + public async Task ReturnsDistinctReactionsBasedOnStartPage() + { + var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" }; + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); + + Assert.NotNull(issue); + + var issueComment = await _issuesClient.Comment.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, "A test comment"); + + Assert.NotNull(issueComment); + + var reactionsContent = new[] { ReactionType.Heart, ReactionType.Plus1 }; + for (var i = 0; i < 2; i++) + { + var issueCommentReaction = await _github.Reaction.IssueComment.Create(_context.RepositoryOwner, _context.RepositoryName, issueComment.Id, new NewReaction(reactionsContent[i])); + } + + var startOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 1 + }; + var firstPage = await _github.Reaction.IssueComment.GetAll(_context.RepositoryOwner, _context.RepositoryName, issueComment.Id, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + var secondPage = await _github.Reaction.IssueComment.GetAll(_context.RepositoryOwner, _context.RepositoryName, issueComment.Id, skipStartOptions); + + Assert.Equal(1, firstPage.Count); + Assert.Equal(1, secondPage.Count); + Assert.NotEqual(firstPage[0].Id, secondPage[0].Id); + Assert.NotEqual(firstPage[0].Content, secondPage[0].Content); + } + [IntegrationTest] public async Task CanListReactionsWithRepositoryId() { @@ -67,6 +172,109 @@ public async Task CanListReactionsWithRepositoryId() Assert.Equal(reactions[0].Content, issueCommentReaction.Content); } + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithoutStartWithRepositoryId() + { + var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" }; + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); + + Assert.NotNull(issue); + + var issueComment = await _issuesClient.Comment.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, "A test comment"); + + Assert.NotNull(issueComment); + + var issueCommentReaction = await _github.Reaction.IssueComment.Create(_context.Repository.Id, issueComment.Id, new NewReaction(ReactionType.Heart)); + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1 + }; + + var reactions = await _github.Reaction.IssueComment.GetAll(_context.Repository.Id, issueComment.Id, options); + + Assert.Equal(1, reactions.Count); + + Assert.Equal(reactions[0].Id, issueCommentReaction.Id); + Assert.Equal(reactions[0].Content, issueCommentReaction.Content); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithStartWithRepositoryId() + { + var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" }; + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); + + Assert.NotNull(issue); + + var issueComment = await _issuesClient.Comment.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, "A test comment"); + + Assert.NotNull(issueComment); + + var reactions = new List(); + var reactionsContent = new[] { ReactionType.Heart, ReactionType.Plus1 }; + for (var i = 0; i < 2; i++) + { + var issueCommentReaction = await _github.Reaction.IssueComment.Create(_context.Repository.Id, issueComment.Id, new NewReaction(reactionsContent[i])); + reactions.Add(issueCommentReaction); + } + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + + var reactionsInfo = await _github.Reaction.IssueComment.GetAll(_context.Repository.Id, issueComment.Id, options); + + Assert.Equal(1, reactionsInfo.Count); + + Assert.Equal(reactionsInfo[0].Id, reactions.Last().Id); + Assert.Equal(reactionsInfo[0].Content, reactions.Last().Content); + } + + [IntegrationTest] + public async Task ReturnsDistinctReactionsBasedOnStartPageWithRepositoryId() + { + var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" }; + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); + + Assert.NotNull(issue); + + var issueComment = await _issuesClient.Comment.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, "A test comment"); + + Assert.NotNull(issueComment); + + var reactionsContent = new[] { ReactionType.Heart, ReactionType.Plus1 }; + for (var i = 0; i < 2; i++) + { + var issueCommentReaction = await _github.Reaction.IssueComment.Create(_context.Repository.Id, issueComment.Id, new NewReaction(reactionsContent[i])); + } + + var startOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 1 + }; + var firstPage = await _github.Reaction.IssueComment.GetAll(_context.Repository.Id, issueComment.Id, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + var secondPage = await _github.Reaction.IssueComment.GetAll(_context.Repository.Id, issueComment.Id, skipStartOptions); + + Assert.Equal(1, firstPage.Count); + Assert.Equal(1, secondPage.Count); + Assert.NotEqual(firstPage[0].Id, secondPage[0].Id); + Assert.NotEqual(firstPage[0].Content, secondPage[0].Content); + } + [IntegrationTest] public async Task CanCreateReaction() { diff --git a/Octokit.Tests.Integration/Clients/IssueReactionsClientTests.cs b/Octokit.Tests.Integration/Clients/IssueReactionsClientTests.cs index f4ffbcb31e..9a396e879f 100644 --- a/Octokit.Tests.Integration/Clients/IssueReactionsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/IssueReactionsClientTests.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Octokit; using Octokit.Tests.Integration; @@ -41,6 +43,99 @@ public async Task CanListReactions() Assert.Equal(issueReaction.Content, issueReactions[0].Content); } + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithoutStart() + { + var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" }; + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); + + Assert.NotNull(issue); + + var issueReaction = await _github.Reaction.Issue.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, new NewReaction(ReactionType.Heart)); + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1 + }; + + var issueReactions = await _github.Reaction.Issue.GetAll(_context.RepositoryOwner, _context.RepositoryName, issue.Number, options); + + Assert.Equal(1, issueReactions.Count); + + Assert.Equal(issueReaction.Id, issueReactions[0].Id); + Assert.Equal(issueReaction.Content, issueReactions[0].Content); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithStart() + { + var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" }; + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); + + Assert.NotNull(issue); + + var reactions = new List(); + var reactionsContent = new[] { ReactionType.Heart, ReactionType.Plus1 }; + for (var i = 0; i < 2; i++) + { + var issueReaction = await _github.Reaction.Issue.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, new NewReaction(reactionsContent[i])); + reactions.Add(issueReaction); + } + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + + var issueReactions = await _github.Reaction.Issue.GetAll(_context.RepositoryOwner, _context.RepositoryName, issue.Number, options); + + Assert.Equal(1, issueReactions.Count); + + Assert.Equal(reactions.Last().Id, issueReactions[0].Id); + Assert.Equal(reactions.Last().Content, issueReactions[0].Content); + } + + [IntegrationTest] + public async Task ReturnsDistinctReactionsBasedOnStartPage() + { + var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" }; + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); + + Assert.NotNull(issue); + + var reactions = new List(); + var reactionsContent = new[] { ReactionType.Heart, ReactionType.Plus1 }; + for (var i = 0; i < 2; i++) + { + var issueReaction = await _github.Reaction.Issue.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, new NewReaction(reactionsContent[i])); + reactions.Add(issueReaction); + } + + var startOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 1 + }; + var firstPage = await _github.Reaction.Issue.GetAll(_context.RepositoryOwner, _context.RepositoryName, issue.Number, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + var secondPage = await _github.Reaction.Issue.GetAll(_context.RepositoryOwner, _context.RepositoryName, issue.Number, skipStartOptions); + + Assert.Equal(1, firstPage.Count); + Assert.Equal(1, secondPage.Count); + Assert.NotEqual(firstPage[0].Id, secondPage[0].Id); + Assert.NotEqual(firstPage[0].Content, secondPage[0].Content); + } + [IntegrationTest] public async Task CanListReactionsWithRepositoryId() { @@ -59,6 +154,99 @@ public async Task CanListReactionsWithRepositoryId() Assert.Equal(issueReaction.Content, issueReactions[0].Content); } + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithoutStartWithRepositoryId() + { + var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" }; + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); + + Assert.NotNull(issue); + + var issueReaction = await _github.Reaction.Issue.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, new NewReaction(ReactionType.Heart)); + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1 + }; + + var issueReactions = await _github.Reaction.Issue.GetAll(_context.Repository.Id, issue.Number, options); + + Assert.Equal(1, issueReactions.Count); + + Assert.Equal(issueReaction.Id, issueReactions[0].Id); + Assert.Equal(issueReaction.Content, issueReactions[0].Content); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithStartWithRepositoryId() + { + var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" }; + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); + + Assert.NotNull(issue); + + var reactions = new List(); + var reactionsContent = new[] { ReactionType.Heart, ReactionType.Plus1 }; + for (var i = 0; i < 2; i++) + { + var issueReaction = await _github.Reaction.Issue.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, new NewReaction(reactionsContent[i])); + reactions.Add(issueReaction); + } + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + + var issueReactions = await _github.Reaction.Issue.GetAll(_context.Repository.Id, issue.Number, options); + + Assert.Equal(1, issueReactions.Count); + + Assert.Equal(reactions.Last().Id, issueReactions[0].Id); + Assert.Equal(reactions.Last().Content, issueReactions[0].Content); + } + + [IntegrationTest] + public async Task ReturnsDistinctReactionsBasedOnStartPageWithRepositoryId() + { + var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" }; + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); + + Assert.NotNull(issue); + + var reactions = new List(); + var reactionsContent = new[] { ReactionType.Heart, ReactionType.Plus1 }; + for (var i = 0; i < 2; i++) + { + var issueReaction = await _github.Reaction.Issue.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, new NewReaction(reactionsContent[i])); + reactions.Add(issueReaction); + } + + var startOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 1 + }; + var firstPage = await _github.Reaction.Issue.GetAll(_context.Repository.Id, issue.Number, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + var secondPage = await _github.Reaction.Issue.GetAll(_context.Repository.Id, issue.Number, skipStartOptions); + + Assert.Equal(1, firstPage.Count); + Assert.Equal(1, secondPage.Count); + Assert.NotEqual(firstPage[0].Id, secondPage[0].Id); + Assert.NotEqual(firstPage[0].Content, secondPage[0].Content); + } + [IntegrationTest] public async Task CanCreateReaction() { diff --git a/Octokit.Tests.Integration/Clients/IssuesClientTests.cs b/Octokit.Tests.Integration/Clients/IssuesClientTests.cs index 54e5187cd5..2d887ed027 100644 --- a/Octokit.Tests.Integration/Clients/IssuesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/IssuesClientTests.cs @@ -200,9 +200,9 @@ public async Task CanCreateRetrieveAndCloseIssue() Assert.True(retrieved.Assignees.Count == 1); Assert.True(retrieved.Assignees[0].Login == _context.RepositoryOwner); var all = await _issuesClient.GetAllForRepository(_context.RepositoryOwner, _context.RepositoryName); - Assert.True(all.Any(i => i.Number == retrieved.Number)); - Assert.True(all.Any(i => i.Assignees.Count == 1)); - Assert.True(all.Any(i => i.Assignees[0].Login == _context.RepositoryOwner)); + Assert.Contains(all, i => i.Number == retrieved.Number); + Assert.Contains(all, i => i.Assignees.Count == 1); + Assert.Contains(all, i => i.Assignees[0].Login == _context.RepositoryOwner); } finally { @@ -225,7 +225,7 @@ public async Task CanCreateRetrieveAndCloseIssueWithRepositoryId() var retrieved = await _issuesClient.Get(_context.Repository.Id, issue.Number); var all = await _issuesClient.GetAllForRepository(_context.Repository.Id); Assert.NotNull(retrieved); - Assert.True(all.Any(i => i.Number == retrieved.Number)); + Assert.Contains(all, i => i.Number == retrieved.Number); } finally { @@ -462,10 +462,10 @@ public async Task CanRetrieveAllIssuesWithApiOptionsWithoutStart() var retrieved = await _issuesClient.GetAllForRepository(_context.RepositoryOwner, _context.RepositoryName, request, options); Assert.Equal(4, retrieved.Count); - Assert.True(retrieved.Any(i => i.Number == issue1.Number)); - Assert.True(retrieved.Any(i => i.Number == issue2.Number)); - Assert.True(retrieved.Any(i => i.Number == issue3.Number)); - Assert.True(retrieved.Any(i => i.Number == issue4.Number)); + Assert.Contains(retrieved, i => i.Number == issue1.Number); + Assert.Contains(retrieved, i => i.Number == issue2.Number); + Assert.Contains(retrieved, i => i.Number == issue3.Number); + Assert.Contains(retrieved, i => i.Number == issue4.Number); } [IntegrationTest] @@ -492,10 +492,10 @@ public async Task CanRetrieveAllIssuesWithApiOptionsWithoutStartWithRepositoryId var retrieved = await _issuesClient.GetAllForRepository(_context.Repository.Id, request, options); Assert.Equal(4, retrieved.Count); - Assert.True(retrieved.Any(i => i.Number == issue1.Number)); - Assert.True(retrieved.Any(i => i.Number == issue2.Number)); - Assert.True(retrieved.Any(i => i.Number == issue3.Number)); - Assert.True(retrieved.Any(i => i.Number == issue4.Number)); + Assert.Contains(retrieved, i => i.Number == issue1.Number); + Assert.Contains(retrieved, i => i.Number == issue2.Number); + Assert.Contains(retrieved, i => i.Number == issue3.Number); + Assert.Contains(retrieved, i => i.Number == issue4.Number); } [IntegrationTest] @@ -523,7 +523,7 @@ public async Task CanRetrieveAllIssuesWithApiOptionsWithStart() var retrieved = await _issuesClient.GetAllForRepository(_context.RepositoryOwner, _context.RepositoryName, request, options); Assert.Equal(1, retrieved.Count); - Assert.True(retrieved.Any(i => i.Number == issue4.Number)); + Assert.Contains(retrieved, i => i.Number == issue4.Number); } [IntegrationTest] @@ -551,7 +551,7 @@ public async Task CanRetrieveAllIssuesWithApiOptionsWithStartWithRepositoryId() var retrieved = await _issuesClient.GetAllForRepository(_context.Repository.Id, request, options); Assert.Equal(1, retrieved.Count); - Assert.True(retrieved.Any(i => i.Number == issue4.Number)); + Assert.Contains(retrieved, i => i.Number == issue4.Number); } [IntegrationTest] @@ -572,10 +572,10 @@ public async Task CanRetrieveAllIssues() var retrieved = await _issuesClient.GetAllForRepository(_context.RepositoryOwner, _context.RepositoryName, request); Assert.Equal(4, retrieved.Count); - Assert.True(retrieved.Any(i => i.Number == issue1.Number)); - Assert.True(retrieved.Any(i => i.Number == issue2.Number)); - Assert.True(retrieved.Any(i => i.Number == issue3.Number)); - Assert.True(retrieved.Any(i => i.Number == issue4.Number)); + Assert.Contains(retrieved, i => i.Number == issue1.Number); + Assert.Contains(retrieved, i => i.Number == issue2.Number); + Assert.Contains(retrieved, i => i.Number == issue3.Number); + Assert.Contains(retrieved, i => i.Number == issue4.Number); } [IntegrationTest] @@ -597,7 +597,7 @@ public async Task CanRetrieveIssuesWithMultipleAssignees() var request = new RepositoryIssueRequest { State = ItemStateFilter.All }; var issues = await _issuesClient.GetAllForRepository(_context.RepositoryOwner, _context.RepositoryName, request); - Assert.True(issues.Any(x => x.Assignees.Count > 0)); + Assert.Contains(issues, x => x.Assignees.Count > 0); } [IntegrationTest] @@ -657,10 +657,10 @@ public async Task CanRetrieveAllIssuesWithRepositoryId() var retrieved = await _issuesClient.GetAllForRepository(_context.Repository.Id, request); Assert.Equal(4, retrieved.Count); - Assert.True(retrieved.Any(i => i.Number == issue1.Number)); - Assert.True(retrieved.Any(i => i.Number == issue2.Number)); - Assert.True(retrieved.Any(i => i.Number == issue3.Number)); - Assert.True(retrieved.Any(i => i.Number == issue4.Number)); + Assert.Contains(retrieved, i => i.Number == issue1.Number); + Assert.Contains(retrieved, i => i.Number == issue2.Number); + Assert.Contains(retrieved, i => i.Number == issue3.Number); + Assert.Contains(retrieved, i => i.Number == issue4.Number); } [IntegrationTest] diff --git a/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs b/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs index 7d6b229a7f..9daa2834fd 100644 --- a/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs @@ -402,7 +402,7 @@ public async Task CanRetrieveIssueEventById() var closed = await _issuesClient.Update(_context.RepositoryOwner, _context.RepositoryName, issue.Number, new IssueUpdate { State = ItemState.Closed }); Assert.NotNull(closed); var issueEvents = await _issuesEventsClient.GetAllForRepository(_context.RepositoryOwner, _context.RepositoryName); - int issueEventId = issueEvents[0].Id; + var issueEventId = issueEvents[0].Id; var issueEventLookupById = await _issuesEventsClient.Get(_context.RepositoryOwner, _context.RepositoryName, issueEventId); @@ -418,7 +418,7 @@ public async Task CanRetrieveIssueEventByIdWithRepositoryId() var closed = await _issuesClient.Update(_context.RepositoryOwner, _context.RepositoryName, issue.Number, new IssueUpdate { State = ItemState.Closed }); Assert.NotNull(closed); var issueEvents = await _issuesEventsClient.GetAllForRepository(_context.Repository.Id); - int issueEventId = issueEvents[0].Id; + var issueEventId = issueEvents[0].Id; var issueEventLookupById = await _issuesEventsClient.Get(_context.Repository.Id, issueEventId); diff --git a/Octokit.Tests.Integration/Clients/MigrationsClientTests.cs b/Octokit.Tests.Integration/Clients/MigrationsClientTests.cs index 3ed7d8bd09..4d1e93b07a 100644 --- a/Octokit.Tests.Integration/Clients/MigrationsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/MigrationsClientTests.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using Octokit; @@ -46,7 +45,7 @@ private async Task CreateTheWorld() })); } - public async Task StartNewMigration() + private async Task StartNewMigration() { var repoNames = _repos.Select(repo => repo.Repository.FullName).ToList(); var migrationRequest = new StartMigrationRequest(repoNames); @@ -68,6 +67,61 @@ public async Task CanGetAllMigrations() Assert.NotEqual(0, migrations.Count); } + [IntegrationTest] + public async Task ReturnsCorrectCountOfMigrationsWithoutStart() + { + var options = new ApiOptions + { + PageCount = 1, + PageSize = 1 + }; + + var migrations = await _gitHub.Migration.Migrations.GetAll(_orgName, options); + + Assert.Equal(1, migrations.Count); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfMigrationsWithStart() + { + var options = new ApiOptions + { + PageCount = 1, + PageSize = 1, + StartPage = 2 + }; + + var migrations = await _gitHub.Migration.Migrations.GetAll(_orgName, options); + + Assert.Equal(1, migrations.Count); + } + + [IntegrationTest] + public async Task ReturnsDistinctMigrationsBasedOnStartPage() + { + var startOptions = new ApiOptions + { + PageCount = 1, + PageSize = 1, + StartPage = 1 + }; + + var firstPage = await _gitHub.Migration.Migrations.GetAll(_orgName, startOptions); + + var skipStartOptions = new ApiOptions + { + PageCount = 1, + PageSize = 1, + StartPage = 2 + }; + var secondPage = await _gitHub.Migration.Migrations.GetAll(_orgName, skipStartOptions); + + Assert.Equal(1, firstPage.Count); + Assert.Equal(1, secondPage.Count); + Assert.NotEqual(firstPage[0].Id, secondPage[0].Id); + Assert.NotEqual(firstPage[0].Repositories, secondPage[0].Repositories); + } + [IntegrationTest] public async Task CanGetMigration() { diff --git a/Octokit.Tests.Integration/Clients/MiscellaneousClientTests.cs b/Octokit.Tests.Integration/Clients/MiscellaneousClientTests.cs index fa8e5eecb2..cebfbe9328 100644 --- a/Octokit.Tests.Integration/Clients/MiscellaneousClientTests.cs +++ b/Octokit.Tests.Integration/Clients/MiscellaneousClientTests.cs @@ -85,21 +85,21 @@ public async Task CanRetrieveResourceRateLimits() Assert.True(result.Resources.Core.Remaining > -1); Assert.True(result.Resources.Core.Remaining <= result.Resources.Core.Limit); Assert.True(result.Resources.Core.ResetAsUtcEpochSeconds > 0); - Assert.NotNull(result.Resources.Core.Reset); + Assert.NotEqual(default, result.Resources.Core.Reset); // Test the search limits Assert.True(result.Resources.Search.Limit > 0); Assert.True(result.Resources.Search.Remaining > -1); Assert.True(result.Resources.Search.Remaining <= result.Resources.Search.Limit); Assert.True(result.Resources.Search.ResetAsUtcEpochSeconds > 0); - Assert.NotNull(result.Resources.Search.Reset); + Assert.NotEqual(default, result.Resources.Search.Reset); // Test the depreciated rate limits Assert.True(result.Rate.Limit > 0); Assert.True(result.Rate.Remaining > -1); Assert.True(result.Rate.Remaining <= result.Rate.Limit); Assert.True(result.Resources.Search.ResetAsUtcEpochSeconds > 0); - Assert.NotNull(result.Resources.Search.Reset); + Assert.NotEqual(default, result.Resources.Search.Reset); } } diff --git a/Octokit.Tests.Integration/Clients/OrganizationMembersClientTests.cs b/Octokit.Tests.Integration/Clients/OrganizationMembersClientTests.cs index bde9817ad8..a86793f3c1 100644 --- a/Octokit.Tests.Integration/Clients/OrganizationMembersClientTests.cs +++ b/Octokit.Tests.Integration/Clients/OrganizationMembersClientTests.cs @@ -121,6 +121,75 @@ public async Task ReturnsMembersWthFilterAndRole() } } + public class TheGetOrganizationMembershipMethod + { + readonly IGitHubClient _gitHub; + + public TheGetOrganizationMembershipMethod() + { + _gitHub = Helper.GetAuthenticatedClient(); + } + + [OrganizationTest] + public async Task ReturnsUsersMembershipOrganizationMembership() + { + using (var teamContext = await _gitHub.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + { + teamContext.InviteMember("alfhenrik-test-2"); + + var organizationMemberhip = await _gitHub.Organization.Member.GetOrganizationMembership(Helper.Organization, "alfhenrik-test-2"); + Assert.Equal(MembershipState.Pending, organizationMemberhip.State); + Assert.Equal(MembershipRole.Member, organizationMemberhip.Role); + } + } + } + + public class TheAddOrUpdateOrganizationMembershipMethod + { + readonly IGitHubClient _gitHub; + + public TheAddOrUpdateOrganizationMembershipMethod() + { + _gitHub = Helper.GetAuthenticatedClient(); + } + + [OrganizationTest] + public async Task ReturnsUsersPendingMemberOrganizationMembership() + { + var organizationMembership = await _gitHub.Organization.Member.AddOrUpdateOrganizationMembership(Helper.Organization, "alfhenrik-test-2", new OrganizationMembershipUpdate()); + Assert.Equal(MembershipState.Pending, organizationMembership.State); + Assert.Equal(MembershipRole.Member, organizationMembership.Role); + await _gitHub.Organization.Member.RemoveOrganizationMembership(Helper.Organization, "alfhenrik-test-2"); + } + + [OrganizationTest] + public async Task ReturnsUsersPendingAdminOrganizationMembership() + { + var organizationMembership = await _gitHub.Organization.Member.AddOrUpdateOrganizationMembership(Helper.Organization, "alfhenrik-test-2", new OrganizationMembershipUpdate { Role = MembershipRole.Admin }); + Assert.Equal(MembershipState.Pending, organizationMembership.State); + Assert.Equal(MembershipRole.Admin, organizationMembership.Role); + await _gitHub.Organization.Member.RemoveOrganizationMembership(Helper.Organization, "alfhenrik-test-2"); + } + } + + public class TheRemoveOrganizationMembershipMethod + { + readonly IGitHubClient _gitHub; + + public TheRemoveOrganizationMembershipMethod() + { + _gitHub = Helper.GetAuthenticatedClient(); + } + + [OrganizationTest] + public async Task RemovesOrganizationMembership() + { + await _gitHub.Organization.Member.AddOrUpdateOrganizationMembership(Helper.Organization, "alfhenrik-test-2", new OrganizationMembershipUpdate()); + await _gitHub.Organization.Member.RemoveOrganizationMembership(Helper.Organization, "alfhenrik-test-2"); + await Assert.ThrowsAsync(() => _gitHub.Organization.Member.GetOrganizationMembership(Helper.Organization, "alfhenrik-test-2")); + } + } + public class TheGetAllPendingInvitationsMethod { readonly IGitHubClient _gitHub; diff --git a/Octokit.Tests.Integration/Clients/OrganizationOutsideCollaboratorsClientTests.cs b/Octokit.Tests.Integration/Clients/OrganizationOutsideCollaboratorsClientTests.cs index 1c71a107b2..57ffce1e88 100644 --- a/Octokit.Tests.Integration/Clients/OrganizationOutsideCollaboratorsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/OrganizationOutsideCollaboratorsClientTests.cs @@ -261,10 +261,7 @@ public async Task CannotRemoveMemberOfOrganizationAsOutsideCollaborator() var ex = await Assert.ThrowsAsync(() => _gitHub.Organization.OutsideCollaborator.Delete(Helper.Organization, Helper.UserName)); - Assert.True(string.Equals( - "You cannot specify an organization member to remove as an outside collaborator.", - ex.Message, - StringComparison.OrdinalIgnoreCase)); + Assert.Equal("You cannot specify an organization member to remove as an outside collaborator.", ex.Message, ignoreCase: true); } } @@ -296,10 +293,7 @@ public async Task CannotConvertNonOrgMemberToOutsideCollaborator() var ex = await Assert.ThrowsAsync(() => _gitHub.Organization.OutsideCollaborator.ConvertFromMember(Helper.Organization, _fixtureCollaborator)); - Assert.True(string.Equals( - $"{_fixtureCollaborator} is not a member of the {Helper.Organization} organization.", - ex.Message, - StringComparison.OrdinalIgnoreCase)); + Assert.Equal($"{_fixtureCollaborator} is not a member of the {Helper.Organization} organization.", ex.Message, ignoreCase: true); } [OrganizationTest] @@ -308,10 +302,7 @@ public async Task CannotConvertLastOrgOwnerToOutsideCollaborator() var ex = await Assert.ThrowsAsync(() => _gitHub.Organization.OutsideCollaborator.ConvertFromMember(Helper.Organization, Helper.UserName)); - Assert.True(string.Equals( - "Cannot convert the last owner to an outside collaborator", - ex.Message, - StringComparison.OrdinalIgnoreCase)); + Assert.Equal("Cannot convert the last owner to an outside collaborator", ex.Message, ignoreCase: true); } } } diff --git a/Octokit.Tests.Integration/Clients/PullRequestReviewCommentReactionsClientTests.cs b/Octokit.Tests.Integration/Clients/PullRequestReviewCommentReactionsClientTests.cs index 4044adde88..9558c1dd07 100644 --- a/Octokit.Tests.Integration/Clients/PullRequestReviewCommentReactionsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/PullRequestReviewCommentReactionsClientTests.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Octokit; using Octokit.Tests.Integration; @@ -49,6 +51,113 @@ public async Task CanListReactions() Assert.Equal(reaction.Content, reactions[0].Content); } + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithoutStart() + { + var pullRequest = await CreatePullRequest(_context); + + const string body = "A review comment message"; + const int position = 1; + + var createdComment = await CreateComment(body, position, pullRequest.Sha, pullRequest.Number); + + var commentFromGitHub = await _client.GetComment(Helper.UserName, _context.RepositoryName, createdComment.Id); + + AssertComment(commentFromGitHub, body, position); + + var reaction = await _github.Reaction.PullRequestReviewComment.Create(_context.RepositoryOwner, _context.RepositoryName, commentFromGitHub.Id, new NewReaction(ReactionType.Heart)); + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1 + }; + + var reactions = await _github.Reaction.PullRequestReviewComment.GetAll(_context.RepositoryOwner, _context.RepositoryName, commentFromGitHub.Id, options); + + Assert.Equal(1, reactions.Count); + Assert.Equal(reaction.Id, reactions[0].Id); + Assert.Equal(reaction.Content, reactions[0].Content); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithStart() + { + var pullRequest = await CreatePullRequest(_context); + + const string body = "A review comment message"; + const int position = 1; + + var createdComment = await CreateComment(body, position, pullRequest.Sha, pullRequest.Number); + + var commentFromGitHub = await _client.GetComment(Helper.UserName, _context.RepositoryName, createdComment.Id); + + AssertComment(commentFromGitHub, body, position); + + var reactions = new List(); + var reactionsContent = new[] { ReactionType.Heart, ReactionType.Hooray }; + for (var i = 0; i < 2; i++) + { + var reaction = await _github.Reaction.PullRequestReviewComment.Create(_context.RepositoryOwner, _context.RepositoryName, commentFromGitHub.Id, new NewReaction(reactionsContent[i])); + reactions.Add(reaction); + } + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + + var reactionsInfo = await _github.Reaction.PullRequestReviewComment.GetAll(_context.RepositoryOwner, _context.RepositoryName, commentFromGitHub.Id, options); + + Assert.Equal(1, reactionsInfo.Count); + Assert.Equal(reactions.Last().Id, reactionsInfo[0].Id); + Assert.Equal(reactions.Last().Content, reactionsInfo[0].Content); + } + + [IntegrationTest] + public async Task ReturnsDistinctReactionsBasedOnStartPage() + { + var pullRequest = await CreatePullRequest(_context); + + const string body = "A review comment message"; + const int position = 1; + + var createdComment = await CreateComment(body, position, pullRequest.Sha, pullRequest.Number); + + var commentFromGitHub = await _client.GetComment(Helper.UserName, _context.RepositoryName, createdComment.Id); + + AssertComment(commentFromGitHub, body, position); + + var reactionsContent = new[] { ReactionType.Heart, ReactionType.Hooray }; + for (var i = 0; i < 2; i++) + { + var reaction = await _github.Reaction.PullRequestReviewComment.Create(_context.RepositoryOwner, _context.RepositoryName, commentFromGitHub.Id, new NewReaction(reactionsContent[i])); + } + + var startOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 1 + }; + var firstPage = await _github.Reaction.PullRequestReviewComment.GetAll(_context.RepositoryOwner, _context.RepositoryName, commentFromGitHub.Id, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + var secondPage = await _github.Reaction.PullRequestReviewComment.GetAll(_context.RepositoryOwner, _context.RepositoryName, commentFromGitHub.Id, skipStartOptions); + + Assert.Equal(1, firstPage.Count); + Assert.Equal(1, secondPage.Count); + Assert.Equal(firstPage[0].Id, secondPage[0].Id); + Assert.Equal(firstPage[0].Content, secondPage[0].Content); + } + [IntegrationTest] public async Task CanListReactionsWithRepositoryId() { @@ -72,6 +181,113 @@ public async Task CanListReactionsWithRepositoryId() Assert.Equal(reaction.Content, reactions[0].Content); } + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithoutStartWithRepositoryId() + { + var pullRequest = await CreatePullRequest(_context); + + const string body = "A review comment message"; + const int position = 1; + + var createdComment = await CreateComment(body, position, pullRequest.Sha, pullRequest.Number); + + var commentFromGitHub = await _client.GetComment(Helper.UserName, _context.RepositoryName, createdComment.Id); + + AssertComment(commentFromGitHub, body, position); + + var reaction = await _github.Reaction.PullRequestReviewComment.Create(_context.RepositoryOwner, _context.RepositoryName, commentFromGitHub.Id, new NewReaction(ReactionType.Heart)); + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1 + }; + + var reactions = await _github.Reaction.PullRequestReviewComment.GetAll(_context.Repository.Id, commentFromGitHub.Id, options); + + Assert.Equal(1, reactions.Count); + Assert.Equal(reaction.Id, reactions[0].Id); + Assert.Equal(reaction.Content, reactions[0].Content); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfReactionsWithStartWithRepositoryId() + { + var pullRequest = await CreatePullRequest(_context); + + const string body = "A review comment message"; + const int position = 1; + + var createdComment = await CreateComment(body, position, pullRequest.Sha, pullRequest.Number); + + var commentFromGitHub = await _client.GetComment(Helper.UserName, _context.RepositoryName, createdComment.Id); + + AssertComment(commentFromGitHub, body, position); + + var reactions = new List(); + var reactionsContent = new[] { ReactionType.Heart, ReactionType.Hooray }; + for (var i = 0; i < 2; i++) + { + var reaction = await _github.Reaction.PullRequestReviewComment.Create(_context.RepositoryOwner, _context.RepositoryName, commentFromGitHub.Id, new NewReaction(reactionsContent[i])); + reactions.Add(reaction); + } + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + + var reactionsInfo = await _github.Reaction.PullRequestReviewComment.GetAll(_context.Repository.Id, commentFromGitHub.Id, options); + + Assert.Equal(1, reactionsInfo.Count); + Assert.Equal(reactions.Last().Id, reactionsInfo[0].Id); + Assert.Equal(reactions.Last().Content, reactionsInfo[0].Content); + } + + [IntegrationTest] + public async Task ReturnsDistinctReactionsBasedOnStartPageWithRepositoryId() + { + var pullRequest = await CreatePullRequest(_context); + + const string body = "A review comment message"; + const int position = 1; + + var createdComment = await CreateComment(body, position, pullRequest.Sha, pullRequest.Number); + + var commentFromGitHub = await _client.GetComment(Helper.UserName, _context.RepositoryName, createdComment.Id); + + AssertComment(commentFromGitHub, body, position); + + var reactionsContent = new[] { ReactionType.Heart, ReactionType.Hooray }; + for (var i = 0; i < 2; i++) + { + var reaction = await _github.Reaction.PullRequestReviewComment.Create(_context.RepositoryOwner, _context.RepositoryName, commentFromGitHub.Id, new NewReaction(reactionsContent[i])); + } + + var startOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 1 + }; + var firstPage = await _github.Reaction.PullRequestReviewComment.GetAll(_context.Repository.Id, commentFromGitHub.Id, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 2 + }; + var secondPage = await _github.Reaction.PullRequestReviewComment.GetAll(_context.Repository.Id, commentFromGitHub.Id, skipStartOptions); + + Assert.Equal(1, firstPage.Count); + Assert.Equal(1, secondPage.Count); + Assert.Equal(firstPage[0].Id, secondPage[0].Id); + Assert.Equal(firstPage[0].Content, secondPage[0].Content); + } + [IntegrationTest] public async Task CanCreateReaction() { diff --git a/Octokit.Tests.Integration/Clients/PullRequestReviewsClientTests.cs b/Octokit.Tests.Integration/Clients/PullRequestReviewsClientTests.cs index 8505687cbd..3b7d521750 100644 --- a/Octokit.Tests.Integration/Clients/PullRequestReviewsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/PullRequestReviewsClientTests.cs @@ -398,7 +398,7 @@ public async Task CanDeleteReview() var retrievedReviews = await _client.GetAll(context.RepositoryOwner, context.RepositoryName, pullRequest.Number); - Assert.False(retrievedReviews.Any(x => x.Id == createdReview.Id)); + Assert.DoesNotContain(retrievedReviews, x => x.Id == createdReview.Id); } } @@ -415,7 +415,7 @@ public async Task CanDeleteReviewWithRepositoryId() var retrievedReviews = await _client.GetAll(context.RepositoryId, pullRequest.Number); - Assert.False(retrievedReviews.Any(x => x.Id == createdReview.Id)); + Assert.DoesNotContain(retrievedReviews, x => x.Id == createdReview.Id); } } } diff --git a/Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs b/Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs index 8b5b2b8fa6..c3f0ac4dcf 100644 --- a/Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs @@ -16,6 +16,7 @@ public class PullRequestsClientTests : IDisposable const string branchName = "my-branch"; const string otherBranchName = "my-other-branch"; + const string labelName = "my-label"; public PullRequestsClientTests() { @@ -37,6 +38,17 @@ public async Task CanCreate() Assert.Equal("a pull request", result.Title); } + [IntegrationTest] + public async Task CanCreateDraft() + { + await CreateTheWorld(); + + var newPullRequest = new NewPullRequest("a draft pull request", branchName, "master") { Draft = true }; + var result = await _fixture.Create(Helper.UserName, _context.RepositoryName, newPullRequest); + Assert.Equal("a draft pull request", result.Title); + Assert.True(result.Draft); + } + [IntegrationTest] public async Task CanCreateWithRepositoryId() { @@ -47,6 +59,17 @@ public async Task CanCreateWithRepositoryId() Assert.Equal("a pull request", result.Title); } + [IntegrationTest] + public async Task CanCreateDraftWithRepositoryId() + { + await CreateTheWorld(); + + var newPullRequest = new NewPullRequest("a draft pull request", branchName, "master") { Draft = true }; + var result = await _fixture.Create(_context.Repository.Id, newPullRequest); + Assert.Equal("a draft pull request", result.Title); + Assert.True(result.Draft); + } + [IntegrationTest] public async Task CanGetForRepository() { @@ -62,6 +85,22 @@ public async Task CanGetForRepository() Assert.True(pullRequests[0].Id > 0); } + [IntegrationTest] + public async Task CanGetDraftForRepository() + { + await CreateTheWorld(); + + var newPullRequest = new NewPullRequest("a draft pull request", branchName, "master") { Draft = true }; + var result = await _fixture.Create(Helper.UserName, _context.RepositoryName, newPullRequest); + + var pullRequests = await _fixture.GetAllForRepository(Helper.UserName, _context.RepositoryName); + + Assert.Equal(1, pullRequests.Count); + Assert.Equal(result.Title, pullRequests[0].Title); + Assert.Equal(result.Draft, pullRequests[0].Draft); + Assert.True(pullRequests[0].Id > 0); + } + [IntegrationTest] public async Task CanGetForRepositoryWithRepositoryId() { @@ -76,6 +115,22 @@ public async Task CanGetForRepositoryWithRepositoryId() Assert.Equal(result.Title, pullRequests[0].Title); } + [IntegrationTest] + public async Task CanGetDraftForRepositoryWithRepositoryId() + { + await CreateTheWorld(); + + var newPullRequest = new NewPullRequest("a draft pull request", branchName, "master") { Draft = true }; + var result = await _fixture.Create(_context.Repository.Id, newPullRequest); + + var pullRequests = await _fixture.GetAllForRepository(_context.Repository.Id); + + Assert.Equal(1, pullRequests.Count); + Assert.Equal(result.Title, pullRequests[0].Title); + Assert.Equal(result.Draft, pullRequests[0].Draft); + Assert.True(pullRequests[0].Id > 0); + } + [IntegrationTest] public async Task CanGetWithAssigneesForRepository() { @@ -96,7 +151,7 @@ public async Task CanGetWithAssigneesForRepository() Assert.Equal(result.Title, pullRequests[0].Title); Assert.Equal(Helper.UserName, pullRequests[0].Assignee.Login); Assert.Equal(1, pullRequests[0].Assignees.Count); - Assert.True(pullRequests[0].Assignees.Any(x => x.Login == Helper.UserName)); + Assert.Contains(pullRequests[0].Assignees, x => x.Login == Helper.UserName); } [IntegrationTest] @@ -119,7 +174,53 @@ public async Task CanGetWithAssigneesForRepositoryWithRepositoryId() Assert.Equal(result.Title, pullRequests[0].Title); Assert.Equal(Helper.UserName, pullRequests[0].Assignee.Login); Assert.Equal(1, pullRequests[0].Assignees.Count); - Assert.True(pullRequests[0].Assignees.Any(x => x.Login == Helper.UserName)); + Assert.Contains(pullRequests[0].Assignees, x => x.Login == Helper.UserName); + } + + [IntegrationTest] + public async Task CanGetWithLabelsForRepository() + { + await CreateTheWorld(); + + var newPullRequest = new NewPullRequest("a pull request", branchName, "master"); + var result = await _fixture.Create(Helper.UserName, _context.RepositoryName, newPullRequest); + + // Add a label + var issueUpdate = new IssueUpdate(); + issueUpdate.AddLabel(labelName); + await _github.Issue.Update(Helper.UserName, _context.RepositoryName, result.Number, issueUpdate); + + // Retrieve the Pull Requests + var pullRequests = await _fixture.GetAllForRepository(Helper.UserName, _context.RepositoryName); + + Assert.Equal(1, pullRequests.Count); + Assert.Equal(result.Title, pullRequests[0].Title); + Assert.Equal(Helper.UserName, pullRequests[0].Assignee.Login); + Assert.Equal(1, pullRequests[0].Labels.Count); + Assert.Contains(pullRequests[0].Labels, x => x.Name == labelName); + } + + [IntegrationTest] + public async Task CanGetWithLabelsForRepositoryWithRepositoryId() + { + await CreateTheWorld(); + + var newPullRequest = new NewPullRequest("a pull request", branchName, "master"); + var result = await _fixture.Create(_context.Repository.Id, newPullRequest); + + // Add a label + var issueUpdate = new IssueUpdate(); + issueUpdate.AddLabel(labelName); + await _github.Issue.Update(_context.Repository.Id, result.Number, issueUpdate); + + // Retrieve the Pull Requests + var pullRequests = await _fixture.GetAllForRepository(_context.Repository.Id); + + Assert.Equal(1, pullRequests.Count); + Assert.Equal(result.Title, pullRequests[0].Title); + Assert.Equal(Helper.UserName, pullRequests[0].Assignee.Login); + Assert.Equal(1, pullRequests[0].Labels.Count); + Assert.Contains(pullRequests[0].Labels, x => x.Name == labelName); } [IntegrationTest] @@ -728,7 +829,7 @@ public async Task CannotBeMergedDueMismatchConflict() var merge = new MergePullRequest { Sha = fakeSha }; var ex = await Assert.ThrowsAsync(() => _fixture.Merge(Helper.UserName, _context.RepositoryName, pullRequest.Number, merge)); - Assert.True(ex.Message.StartsWith("Head branch was modified")); + Assert.StartsWith("Head branch was modified", ex.Message); } [IntegrationTest] @@ -749,12 +850,12 @@ public async Task CannotBeMergedDueNotInMergeableState() var updatedPullRequest = await _fixture.Get(Helper.UserName, _context.RepositoryName, pullRequest.Number); Assert.False(updatedPullRequest.Mergeable); - Assert.Equal(updatedPullRequest.MergeableState, MergeableState.Dirty); + Assert.Equal(MergeableState.Dirty, updatedPullRequest.MergeableState); var merge = new MergePullRequest { Sha = pullRequest.Head.Sha }; var ex = await Assert.ThrowsAsync(() => _fixture.Merge(Helper.UserName, _context.RepositoryName, pullRequest.Number, merge)); - Assert.True(ex.Message.Equals("Pull Request is not mergeable")); + Assert.Equal("Pull Request is not mergeable", ex.Message); } [IntegrationTest] diff --git a/Octokit.Tests.Integration/Clients/ReferencesClientTests.cs b/Octokit.Tests.Integration/Clients/ReferencesClientTests.cs index 35299d203d..ff6f930aca 100644 --- a/Octokit.Tests.Integration/Clients/ReferencesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/ReferencesClientTests.cs @@ -111,7 +111,7 @@ public async Task ReturnsDistinctReferencesBasedOnStartPage() var firstRefsPage = await _fixture.GetAll("octokit", "octokit.net", startOptions); var secondRefsPage = await _fixture.GetAll("octokit", "octokit.net", skipStartOptions); - Assert.False(firstRefsPage.Any(x => secondRefsPage.Contains(x))); + Assert.DoesNotContain(firstRefsPage, x => secondRefsPage.Contains(x)); } [IntegrationTest(Skip = "This is paging for a long long time")] @@ -169,7 +169,7 @@ public async Task ReturnsDistinctReferencesWithRepositoryIdBasedOnStartPage() var firstRefsPage = await _fixture.GetAll(7528679, startOptions); var secondRefsPage = await _fixture.GetAll(7528679, skipStartOptions); - Assert.False(firstRefsPage.Any(x => secondRefsPage.Contains(x))); + Assert.DoesNotContain(firstRefsPage, x => secondRefsPage.Contains(x)); } [IntegrationTest] @@ -227,7 +227,7 @@ public async Task ReturnsDistinctReferencesInNamespaceBasedOnStartPage() var firstRefsPage = await _fixture.GetAllForSubNamespace("octokit", "octokit.net", "heads", startOptions); var secondRefsPage = await _fixture.GetAllForSubNamespace("octokit", "octokit.net", "heads", skipStartOptions); - Assert.False(firstRefsPage.Any(x => secondRefsPage.Contains(x))); + Assert.DoesNotContain(firstRefsPage, x => secondRefsPage.Contains(x)); } [IntegrationTest] @@ -285,7 +285,7 @@ public async Task ReturnsDistinctReferencesInNamespaceWithRepositoryIdBasedOnSta var firstRefsPage = await _fixture.GetAllForSubNamespace(7528679, "heads", startOptions); var secondRefsPage = await _fixture.GetAllForSubNamespace(7528679, "heads", skipStartOptions); - Assert.False(firstRefsPage.Any(x => secondRefsPage.Contains(x))); + Assert.DoesNotContain(firstRefsPage, x => secondRefsPage.Contains(x)); } [IntegrationTest] diff --git a/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs b/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs index 176fd9245b..7a9c08e28e 100644 --- a/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs @@ -124,7 +124,7 @@ public async Task ReturnsReleases() var releases = await _releaseClient.GetAll("git-tfs", "git-tfs"); Assert.True(releases.Count > 5); - Assert.True(releases.Any(release => release.TagName == "v0.18.0")); + Assert.Contains(releases, release => release.TagName == "v0.18.0"); } [IntegrationTest] @@ -133,7 +133,7 @@ public async Task ReturnsReleasesWithRepositoryId() var releases = await _releaseClient.GetAll(252774); Assert.True(releases.Count > 5); - Assert.True(releases.Any(release => release.TagName == "v0.18.0")); + Assert.Contains(releases, release => release.TagName == "v0.18.0"); } [IntegrationTest] @@ -184,9 +184,9 @@ public async Task ReturnsReleaseByTag() { var releaseByTag = await _releaseClient.Get("octokit", "octokit.net", "v0.28.0"); - Assert.Equal(releaseByTag.Id, 8396883); - Assert.Equal(releaseByTag.Name, "v0.28 - Get to the Chopper!!!"); - Assert.Equal(releaseByTag.TagName, "v0.28.0"); + Assert.Equal(8396883, releaseByTag.Id); + Assert.Equal("v0.28 - Get to the Chopper!!!", releaseByTag.Name); + Assert.Equal("v0.28.0", releaseByTag.TagName); } [IntegrationTest] @@ -194,9 +194,9 @@ public async Task ReturnsReleaseWithRepositoryIdByTag() { var releaseByTag = await _releaseClient.Get(7528679, "v0.28.0"); - Assert.Equal(releaseByTag.Id, 8396883); - Assert.Equal(releaseByTag.Name, "v0.28 - Get to the Chopper!!!"); - Assert.Equal(releaseByTag.TagName, "v0.28.0"); + Assert.Equal(8396883, releaseByTag.Id); + Assert.Equal("v0.28 - Get to the Chopper!!!", releaseByTag.Name); + Assert.Equal("v0.28.0", releaseByTag.TagName); } [IntegrationTest] diff --git a/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs index aaad44d229..820b56cad3 100644 --- a/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs @@ -460,7 +460,7 @@ public async Task UpdatesPrivate() _repository = await github.Repository.Edit(Helper.UserName, repoName, update); - Assert.Equal(true, _repository.Private); + Assert.True(_repository.Private); } [PaidAccountTest] @@ -480,7 +480,7 @@ public async Task UpdatesPrivateWithRepositoryId() _repository = await github.Repository.Edit(_repository.Id, update); - Assert.Equal(true, _repository.Private); + Assert.True(_repository.Private); } [IntegrationTest] @@ -493,7 +493,7 @@ public async Task UpdatesHasDownloads() _repository = await github.Repository.Edit(Helper.UserName, repoName, update); - Assert.Equal(false, _repository.HasDownloads); + Assert.False(_repository.HasDownloads); } [IntegrationTest] @@ -506,7 +506,7 @@ public async Task UpdatesHasDownloadsWithRepositoryId() _repository = await github.Repository.Edit(_repository.Id, update); - Assert.Equal(false, _repository.HasDownloads); + Assert.False(_repository.HasDownloads); } [IntegrationTest] @@ -519,7 +519,7 @@ public async Task UpdatesHasIssues() _repository = await github.Repository.Edit(Helper.UserName, repoName, update); - Assert.Equal(false, _repository.HasIssues); + Assert.False(_repository.HasIssues); } [IntegrationTest] @@ -532,7 +532,7 @@ public async Task UpdatesHasIssuesWithRepositoryId() _repository = await github.Repository.Edit(_repository.Id, update); - Assert.Equal(false, _repository.HasIssues); + Assert.False(_repository.HasIssues); } [IntegrationTest] @@ -545,7 +545,7 @@ public async Task UpdatesHasWiki() _repository = await github.Repository.Edit(Helper.UserName, repoName, update); - Assert.Equal(false, _repository.HasWiki); + Assert.False(_repository.HasWiki); } [IntegrationTest] @@ -558,7 +558,7 @@ public async Task UpdatesHasWikiWithRepositoryId() _repository = await github.Repository.Edit(_repository.Id, update); - Assert.Equal(false, _repository.HasWiki); + Assert.False(_repository.HasWiki); } [IntegrationTest] @@ -933,7 +933,7 @@ public async Task GetsContributors() var contributors = await github.Repository.GetAllContributors("octokit", "octokit.net"); - Assert.True(contributors.Any(c => c.Login == "pmacn")); + Assert.Contains(contributors, c => c.Login == "pmacn"); } [IntegrationTest] @@ -943,7 +943,7 @@ public async Task GetsContributorsWithRepositoryId() var contributors = await github.Repository.GetAllContributors(7528679); - Assert.True(contributors.Any(c => c.Login == "pmacn")); + Assert.Contains(contributors, c => c.Login == "pmacn"); } [IntegrationTest] @@ -1085,7 +1085,7 @@ public async Task GetsContributorsIncludeAnonymous() var contributors = await github.Repository.GetAllContributors("ruby", "ruby", true); - Assert.True(contributors.Any(c => c.Type == "Anonymous")); + Assert.Contains(contributors, c => c.Type == "Anonymous"); } [IntegrationTest] @@ -1095,7 +1095,7 @@ public async Task GetsContributorsIncludeAnonymousWithRepositoryId() var contributors = await github.Repository.GetAllContributors(538746, true); - Assert.True(contributors.Any(c => c.Type == "Anonymous")); + Assert.Contains(contributors, c => c.Type == "Anonymous"); } [IntegrationTest] @@ -1330,7 +1330,7 @@ public async Task GetsLanguages() var languages = await github.Repository.GetAllLanguages("octokit", "octokit.net"); Assert.NotEmpty(languages); - Assert.True(languages.Any(l => l.Name == "C#")); + Assert.Contains(languages, l => l.Name == "C#"); } [IntegrationTest] @@ -1341,7 +1341,7 @@ public async Task GetsLanguagesWithRepositoryId() var languages = await github.Repository.GetAllLanguages(7528679); Assert.NotEmpty(languages); - Assert.True(languages.Any(l => l.Name == "C#")); + Assert.Contains(languages, l => l.Name == "C#"); } [IntegrationTest] @@ -1378,7 +1378,7 @@ public async Task GetsTags() var tags = await github.Repository.GetAllTags("octokit", "octokit.net"); - Assert.True(tags.Any(t => t.Name == "v0.1.0")); + Assert.Contains(tags, t => t.Name == "v0.1.0"); } [IntegrationTest] @@ -1388,7 +1388,7 @@ public async Task GetsTagsWithRepositoryId() var tags = await github.Repository.GetAllTags(7528679); - Assert.True(tags.Any(t => t.Name == "v0.1.0")); + Assert.Contains(tags, t => t.Name == "v0.1.0"); } [IntegrationTest] diff --git a/Octokit.Tests.Integration/Clients/RepositoryBranchesClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoryBranchesClientTests.cs index 5c5dba03a6..b4bb14819c 100644 --- a/Octokit.Tests.Integration/Clients/RepositoryBranchesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/RepositoryBranchesClientTests.cs @@ -318,7 +318,7 @@ public async Task UpdatesBranchProtection() var repoName = _userRepoContext.RepositoryName; var update = new BranchProtectionSettingsUpdate( new BranchProtectionRequiredStatusChecksUpdate(false, new[] { "new" }), - new BranchProtectionRequiredReviewsUpdate(false, true), + new BranchProtectionRequiredReviewsUpdate(false, true, 2), false); var protection = await _client.UpdateBranchProtection(repoOwner, repoName, "master", update); @@ -329,6 +329,7 @@ public async Task UpdatesBranchProtection() Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions); Assert.False(protection.RequiredPullRequestReviews.DismissStaleReviews); Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews); + Assert.Equal(2, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount); Assert.Null(protection.Restrictions); @@ -341,7 +342,7 @@ public async Task UpdatesBranchProtectionWithRepositoryId() var repoId = _userRepoContext.RepositoryId; var update = new BranchProtectionSettingsUpdate( new BranchProtectionRequiredStatusChecksUpdate(false, new[] { "new" }), - new BranchProtectionRequiredReviewsUpdate(false, true), + new BranchProtectionRequiredReviewsUpdate(false, true, 2), false); var protection = await _client.UpdateBranchProtection(repoId, "master", update); @@ -352,6 +353,7 @@ public async Task UpdatesBranchProtectionWithRepositoryId() Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions); Assert.False(protection.RequiredPullRequestReviews.DismissStaleReviews); Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews); + Assert.Equal(2, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount); Assert.Null(protection.Restrictions); @@ -365,7 +367,7 @@ public async Task UpdatesBranchProtectionForOrgRepo() var repoName = _orgRepoContext.RepositoryContext.RepositoryName; var update = new BranchProtectionSettingsUpdate( new BranchProtectionRequiredStatusChecksUpdate(false, new[] { "new" }), - new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, false), + new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, false, 2), new BranchProtectionPushRestrictionsUpdate(), false); @@ -377,6 +379,7 @@ public async Task UpdatesBranchProtectionForOrgRepo() Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions); Assert.False(protection.RequiredPullRequestReviews.DismissStaleReviews); Assert.False(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews); + Assert.Equal(2, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount); Assert.Empty(protection.Restrictions.Teams); Assert.Empty(protection.Restrictions.Users); @@ -390,7 +393,7 @@ public async Task UpdatesBranchProtectionForOrgRepoWithRepositoryId() var repoId = _orgRepoContext.RepositoryContext.RepositoryId; var update = new BranchProtectionSettingsUpdate( new BranchProtectionRequiredStatusChecksUpdate(false, new[] { "new" }), - new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, false), + new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, false, 2), new BranchProtectionPushRestrictionsUpdate(), false); @@ -402,6 +405,7 @@ public async Task UpdatesBranchProtectionForOrgRepoWithRepositoryId() Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions); Assert.False(protection.RequiredPullRequestReviews.DismissStaleReviews); Assert.False(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews); + Assert.Equal(2, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount); Assert.Empty(protection.Restrictions.Teams); Assert.Empty(protection.Restrictions.Users); @@ -549,7 +553,7 @@ public async Task UpdateRequiredStatusChecks() Assert.NotNull(requiredStatusChecks); Assert.NotNull(requiredStatusChecks.Contexts); - Assert.True(requiredStatusChecks.Contexts.Contains("new")); + Assert.Contains("new", requiredStatusChecks.Contexts); Assert.True(requiredStatusChecks.Strict); Assert.Equal(1, requiredStatusChecks.Contexts.Count); } @@ -563,7 +567,7 @@ public async Task UpdatesRequiredStatusChecksWithRepositoryId() Assert.NotNull(requiredStatusChecks); Assert.NotNull(requiredStatusChecks.Contexts); - Assert.True(requiredStatusChecks.Contexts.Contains("new")); + Assert.Contains("new", requiredStatusChecks.Contexts); Assert.True(requiredStatusChecks.Strict); Assert.Equal(1, requiredStatusChecks.Contexts.Count); } @@ -716,7 +720,6 @@ public async Task AddsRequiredStatusChecksContexts() var requiredStatusChecksContexts = await _client.AddRequiredStatusChecksContexts(repoOwner, repoName, "master", update); Assert.NotNull(requiredStatusChecksContexts); - Assert.NotNull(requiredStatusChecksContexts.Count); Assert.Equal(4, requiredStatusChecksContexts.Count); } @@ -728,7 +731,6 @@ public async Task AddsRequiredStatusChecksContextsWithRepositoryId() var requiredStatusChecksContexts = await _client.AddRequiredStatusChecksContexts(repoId, "master", update); Assert.NotNull(requiredStatusChecksContexts); - Assert.NotNull(requiredStatusChecksContexts.Count); Assert.Equal(4, requiredStatusChecksContexts.Count); } @@ -761,7 +763,7 @@ public async Task DeletesRequiredStatusChecksContexts() var deleted = await _client.DeleteRequiredStatusChecksContexts(repoOwner, repoName, "master", contextsToRemove); Assert.NotNull(deleted); - Assert.True(deleted.Contains("test")); + Assert.Contains("test", deleted); } } @@ -775,7 +777,7 @@ public async Task DeletesRequiredStatusChecksContextsWithRepositoryId() var deleted = await _client.DeleteRequiredStatusChecksContexts(repoId, "master", contextsToRemove); Assert.NotNull(deleted); - Assert.True(deleted.Contains("test")); + Assert.Contains("test", deleted); } } } @@ -873,26 +875,28 @@ public async Task UpdatesReviewEnforcement() { var repoOwner = _userRepoContext.RepositoryOwner; var repoName = _userRepoContext.RepositoryName; - var update = new BranchProtectionRequiredReviewsUpdate(false, true); + var update = new BranchProtectionRequiredReviewsUpdate(false, true, 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoOwner, repoName, "master", update); Assert.Null(requiredReviews.DismissalRestrictions); Assert.False(requiredReviews.DismissStaleReviews); Assert.True(requiredReviews.RequireCodeOwnerReviews); + Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); } [IntegrationTest] public async Task UpdatesReviewEnforcementWithRepositoryId() { var repoId = _userRepoContext.RepositoryId; - var update = new BranchProtectionRequiredReviewsUpdate(false, true); + var update = new BranchProtectionRequiredReviewsUpdate(false, true, 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoId, "master", update); Assert.Null(requiredReviews.DismissalRestrictions); Assert.False(requiredReviews.DismissStaleReviews); Assert.True(requiredReviews.RequireCodeOwnerReviews); + Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); } [IntegrationTest] @@ -903,13 +907,15 @@ public async Task UpdatesReviewEnforcementForOrgRepo() var update = new BranchProtectionRequiredReviewsUpdate( new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, - false); + false, + 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoOwner, repoName, "master", update); Assert.Null(requiredReviews.DismissalRestrictions); Assert.False(requiredReviews.DismissStaleReviews); Assert.False(requiredReviews.RequireCodeOwnerReviews); + Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); } [IntegrationTest] @@ -919,13 +925,15 @@ public async Task UpdatesReviewEnforcementForOrgRepoWithRepositoryId() var update = new BranchProtectionRequiredReviewsUpdate( new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, - false); + false, + 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoId, "master", update); Assert.Null(requiredReviews.DismissalRestrictions); Assert.False(requiredReviews.DismissStaleReviews); Assert.False(requiredReviews.RequireCodeOwnerReviews); + Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); } [IntegrationTest] @@ -936,7 +944,8 @@ public async Task UpdatesReviewEnforcementForOrgRepoWithAdminOnly() var update = new BranchProtectionRequiredReviewsUpdate( new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(true), false, - false); + false, + 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoOwner, repoName, "master", update); @@ -944,6 +953,7 @@ public async Task UpdatesReviewEnforcementForOrgRepoWithAdminOnly() Assert.Empty(requiredReviews.DismissalRestrictions.Users); Assert.False(requiredReviews.DismissStaleReviews); Assert.False(requiredReviews.RequireCodeOwnerReviews); + Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); } [IntegrationTest] @@ -953,7 +963,8 @@ public async Task UpdatesReviewEnforcementForOrgRepoWithAdminOnlyWithRepositoryI var update = new BranchProtectionRequiredReviewsUpdate( new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(true), false, - false); + false, + 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoId, "master", update); @@ -961,6 +972,7 @@ public async Task UpdatesReviewEnforcementForOrgRepoWithAdminOnlyWithRepositoryI Assert.Empty(requiredReviews.DismissalRestrictions.Users); Assert.False(requiredReviews.DismissStaleReviews); Assert.False(requiredReviews.RequireCodeOwnerReviews); + Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); } public void Dispose() diff --git a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs index eb6aff0e02..3332d56d64 100644 --- a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs @@ -59,7 +59,7 @@ public async Task CanGetCommitWithFiles() { var commit = await _fixture.Get(octokitNetRepositoryOwner, octokitNetRepositorName, "65a22f4d2cff94a286ac3e96440c810c5509196f"); - Assert.True(commit.Files.Any(file => file.Filename.EndsWith("IConnection.cs"))); + Assert.Contains(commit.Files, file => file.Filename.EndsWith("IConnection.cs")); } [IntegrationTest] @@ -67,7 +67,7 @@ public async Task CanGetCommitWithFilesWithRepositoryId() { var commit = await _fixture.Get(octokitNetRepositoryId, "65a22f4d2cff94a286ac3e96440c810c5509196f"); - Assert.True(commit.Files.Any(file => file.Filename.EndsWith("IConnection.cs"))); + Assert.Contains(commit.Files, file => file.Filename.EndsWith("IConnection.cs")); } [IntegrationTest] diff --git a/Octokit.Tests.Integration/Clients/RepositoryContentsClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoryContentsClientTests.cs index 6d7f653ac2..2afea59ccf 100644 --- a/Octokit.Tests.Integration/Clients/RepositoryContentsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/RepositoryContentsClientTests.cs @@ -18,7 +18,7 @@ public async Task ReturnsReadmeForSeeGit() var readme = await github.Repository.Content.GetReadme("octokit", "octokit.net"); Assert.Equal("README.md", readme.Name); string readmeHtml = await readme.GetHtmlContent(); - Assert.True(readmeHtml.StartsWith("
x), hook.Config.Keys.OrderBy(x => x)); Assert.Equal(webHookConfig.Values.OrderBy(x => x), hook.Config.Values.OrderBy(x => x)); - Assert.Equal(false, hook.Active); + Assert.False(hook.Active); } [IntegrationTest] @@ -277,11 +277,11 @@ public async Task CreateAWebHookForTestRepositoryWithRepositoryId() Assert.Equal(baseHookUrl, hook.Url); Assert.Equal(baseHookUrl + "/test", hook.TestUrl); Assert.Equal(baseHookUrl + "/pings", hook.PingUrl); - Assert.NotNull(hook.CreatedAt); - Assert.NotNull(hook.UpdatedAt); + Assert.NotEqual(default, hook.CreatedAt); + Assert.NotEqual(default, hook.UpdatedAt); Assert.Equal(webHookConfig.Keys.OrderBy(x => x), hook.Config.Keys.OrderBy(x => x)); Assert.Equal(webHookConfig.Values.OrderBy(x => x), hook.Config.Values.OrderBy(x => x)); - Assert.Equal(false, hook.Active); + Assert.False(hook.Active); } Dictionary CreateExpectedConfigDictionary(Dictionary config, string url, WebHookContentType contentType, string secret) diff --git a/Octokit.Tests.Integration/Clients/SearchClientTests.cs b/Octokit.Tests.Integration/Clients/SearchClientTests.cs index a4104878cb..616b04ae06 100644 --- a/Octokit.Tests.Integration/Clients/SearchClientTests.cs +++ b/Octokit.Tests.Integration/Clients/SearchClientTests.cs @@ -32,7 +32,7 @@ public async Task SearchForForkedRepositories() }; var repos = await _gitHubClient.Search.SearchRepo(request); - Assert.True(repos.Items.Any(x => x.Fork)); + Assert.Contains(repos.Items, x => x.Fork); } [IntegrationTest] @@ -112,7 +112,7 @@ public async Task SearchForLanguageInCode() foreach (var code in searchResults.Items) { - Assert.True(code.Name.EndsWith(".cs")); + Assert.EndsWith(".cs", code.Name); } } diff --git a/Octokit.Tests.Integration/Clients/TagsClientTests.cs b/Octokit.Tests.Integration/Clients/TagsClientTests.cs index a74320cd84..3fc83ee5f6 100644 --- a/Octokit.Tests.Integration/Clients/TagsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TagsClientTests.cs @@ -36,8 +36,8 @@ public async Task CreatesTagForRepository() var tag = await fixture.Create(context.Repository.Id, newTag); - Assert.Equal(tag.Object.Type, TaggedType.Blob); - Assert.Equal(tag.Message, "Hello"); + Assert.Equal(TaggedType.Blob, tag.Object.Type); + Assert.Equal("Hello", tag.Message); Assert.Equal(tag.Object.Sha, sha); } @@ -48,8 +48,8 @@ public async Task CreatesTagForRepositoryWithRepositoryId() var tag = await fixture.Create(context.Repository.Id, newTag); - Assert.Equal(tag.Object.Type, TaggedType.Blob); - Assert.Equal(tag.Message, "Hello"); + Assert.Equal(TaggedType.Blob, tag.Object.Type); + Assert.Equal("Hello", tag.Message); Assert.Equal(tag.Object.Sha, sha); } } @@ -86,8 +86,8 @@ public async Task CreatesTagForRepository() var gitTag = await fixture.Get(context.RepositoryOwner, context.RepositoryName, tag.Sha); Assert.NotNull(gitTag); - Assert.Equal(gitTag.Object.Type, TaggedType.Blob); - Assert.Equal(gitTag.Message, "Hello"); + Assert.Equal(TaggedType.Blob, gitTag.Object.Type); + Assert.Equal("Hello", gitTag.Message); Assert.Equal(gitTag.Object.Sha, sha); } @@ -103,8 +103,8 @@ public async Task CreatesTagForRepositoryWithRepositoryId() var gitTag = await github.Git.Tag.Get(context.Repository.Id, tag.Sha); Assert.NotNull(gitTag); - Assert.Equal(gitTag.Object.Type, TaggedType.Blob); - Assert.Equal(gitTag.Message, "Hello"); + Assert.Equal(TaggedType.Blob, gitTag.Object.Type); + Assert.Equal("Hello", gitTag.Message); Assert.Equal(gitTag.Object.Sha, sha); } @@ -122,7 +122,7 @@ public async Task DeserializeTagSignatureVerification() Assert.NotNull(gitTag); Assert.False(gitTag.Verification.Verified); - Assert.Equal(gitTag.Verification.Reason, VerificationReason.Unsigned); + Assert.Equal(VerificationReason.Unsigned, gitTag.Verification.Reason); Assert.Null(gitTag.Verification.Signature); Assert.Null(gitTag.Verification.Payload); } diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index bc6563ca6b..ec6252c0e4 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -72,8 +72,8 @@ public async Task GetsAllChildTeams() var teams = await _github.Organization.Team.GetAllChildTeams(parentTeamContext.TeamId); Assert.Equal(2, teams.Count); - Assert.True(teams.Any(x => x.Id == team1.Id)); - Assert.True(teams.Any(x => x.Id == team2.Id)); + Assert.Contains(teams, x => x.Id == team1.Id); + Assert.Contains(teams, x => x.Id == team2.Id); } } diff --git a/Octokit.Tests.Integration/Clients/UserGpgKeysClientTests.cs b/Octokit.Tests.Integration/Clients/UserGpgKeysClientTests.cs index 18beafa68a..b0b270fc1d 100644 --- a/Octokit.Tests.Integration/Clients/UserGpgKeysClientTests.cs +++ b/Octokit.Tests.Integration/Clients/UserGpgKeysClientTests.cs @@ -44,7 +44,7 @@ public async Task CanGetAllForCurrentUser() Assert.NotEmpty(keys); var first = keys[0]; - Assert.NotNull(first.Id); + Assert.NotEqual(default, first.Id); Assert.NotNull(first.KeyId); Assert.NotNull(first.PublicKey); Assert.Null(first.PrimaryKeyId); @@ -81,7 +81,7 @@ public async Task CanCreateAndDeleteKey() // Verify key no longer exists var keys = await github.User.GpgKey.GetAllForCurrent(); - Assert.False(keys.Any(k => k.KeyId == knownKeyId && k.PublicKey == knownPublicKey)); + Assert.DoesNotContain(keys, k => k.KeyId == knownKeyId && k.PublicKey == knownPublicKey); } [IntegrationTest] @@ -96,7 +96,7 @@ public async Task CanNotCreateSameKeyTwice() await github.User.GpgKey.Delete(key.Id); var keys = await github.User.GpgKey.GetAllForCurrent(); - Assert.False(keys.Any(k => k.KeyId == knownKeyId && k.PublicKey == knownPublicKey)); + Assert.DoesNotContain(keys, k => k.KeyId == knownKeyId && k.PublicKey == knownPublicKey); } } } diff --git a/Octokit.Tests.Integration/Clients/UserKeysClientTests.cs b/Octokit.Tests.Integration/Clients/UserKeysClientTests.cs index 4bf48d3a18..4ca95d49b0 100644 --- a/Octokit.Tests.Integration/Clients/UserKeysClientTests.cs +++ b/Octokit.Tests.Integration/Clients/UserKeysClientTests.cs @@ -18,7 +18,7 @@ public async Task CanGetAllForCurrentUser() Assert.NotEmpty(keys); var first = keys[0]; - Assert.NotNull(first.Id); + Assert.NotEqual(default, first.Id); Assert.NotNull(first.Key); Assert.NotNull(first.Title); Assert.NotNull(first.Url); @@ -34,7 +34,7 @@ public async Task CanGetAllForGivenUser() Assert.NotEmpty(keys); var first = keys[0]; - Assert.NotNull(first.Id); + Assert.NotEqual(default, first.Id); Assert.NotNull(first.Key); Assert.Null(first.Title); Assert.Null(first.Url); @@ -75,7 +75,7 @@ public async Task CanCreateAndDeleteKey() // Verify key no longer exists var keys = await github.User.GitSshKey.GetAllForCurrent(); - Assert.False(keys.Any(k => k.Title == keyTitle && k.Key == keyData)); + Assert.DoesNotContain(keys, k => k.Title == keyTitle && k.Key == keyData); } } } diff --git a/Octokit.Tests.Integration/EnterpriseHelper.cs b/Octokit.Tests.Integration/EnterpriseHelper.cs index 6db9437991..bd9f5cde1e 100644 --- a/Octokit.Tests.Integration/EnterpriseHelper.cs +++ b/Octokit.Tests.Integration/EnterpriseHelper.cs @@ -69,7 +69,7 @@ public static class EnterpriseHelper static EnterpriseHelper() { // Force reading of environment variables. - // This wasn't happening if UserName/Organization were + // This wasn't happening if UserName/Organization were // retrieved before Credentials. Debug.WriteIf(Credentials == null, "No credentials specified."); } @@ -108,10 +108,9 @@ public static string ClientSecret get { return Environment.GetEnvironmentVariable("OCTOKIT_GHE_CLIENTSECRET"); } } - public static void DeleteUser(IConnection connection, User user) + public static string ManagementConsolePassword { - if (user != null) - DeleteUser(connection, user.Login); + get { return Environment.GetEnvironmentVariable("OCTOKIT_GHE_CONSOLEPASSWORD"); } } public static void DeleteUser(IConnection connection, string username) @@ -162,6 +161,19 @@ public static void DeletePreReceiveEnvironment(IConnection connection, PreReceiv } } + public static void SetMaintenanceMode(IConnection connection, bool enabled) + { + try + { + var client = new GitHubClient(connection); + client.Enterprise.ManagementConsole.EditMaintenanceMode( + new UpdateMaintenanceRequest(new UpdateMaintenanceRequestDetails(enabled)), + EnterpriseHelper.ManagementConsolePassword) + .Wait(TimeSpan.FromSeconds(15)); + } + catch { } + } + public static IGitHubClient GetAuthenticatedClient() { return new GitHubClient(new ProductHeaderValue("OctokitEnterpriseTests"), GitHubEnterpriseUrl) diff --git a/Octokit.Tests.Integration/Helpers/ApplicationTestAttribute.cs b/Octokit.Tests.Integration/Helpers/ApplicationTestAttribute.cs index b51693c5e7..f460ebf191 100644 --- a/Octokit.Tests.Integration/Helpers/ApplicationTestAttribute.cs +++ b/Octokit.Tests.Integration/Helpers/ApplicationTestAttribute.cs @@ -25,7 +25,7 @@ public IEnumerable Discover(ITestFrameworkDiscoveryOptions disco return Enumerable.Empty(); } - return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod) }; + return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) }; } } diff --git a/Octokit.Tests.Integration/Helpers/BasicAuthenticationTestAttribute.cs b/Octokit.Tests.Integration/Helpers/BasicAuthenticationTestAttribute.cs index e1ced81883..2719603a3f 100644 --- a/Octokit.Tests.Integration/Helpers/BasicAuthenticationTestAttribute.cs +++ b/Octokit.Tests.Integration/Helpers/BasicAuthenticationTestAttribute.cs @@ -22,7 +22,7 @@ public IEnumerable Discover(ITestFrameworkDiscoveryOptions disco return Enumerable.Empty(); } - return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod) }; + return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) }; } } diff --git a/Octokit.Tests.Integration/Helpers/DualAccountTestAttribute.cs b/Octokit.Tests.Integration/Helpers/DualAccountTestAttribute.cs index 9d93604da5..79235d3988 100644 --- a/Octokit.Tests.Integration/Helpers/DualAccountTestAttribute.cs +++ b/Octokit.Tests.Integration/Helpers/DualAccountTestAttribute.cs @@ -22,7 +22,7 @@ public IEnumerable Discover(ITestFrameworkDiscoveryOptions disco return Enumerable.Empty(); } - return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod) }; + return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) }; } } diff --git a/Octokit.Tests.Integration/Helpers/GitHubAppsTestAttribute.cs b/Octokit.Tests.Integration/Helpers/GitHubAppsTestAttribute.cs index cdecf74ac7..9ae83eb9d1 100644 --- a/Octokit.Tests.Integration/Helpers/GitHubAppsTestAttribute.cs +++ b/Octokit.Tests.Integration/Helpers/GitHubAppsTestAttribute.cs @@ -35,7 +35,7 @@ public IEnumerable Discover(ITestFrameworkDiscoveryOptions disco return Enumerable.Empty(); } - return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod) }; + return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) }; } } diff --git a/Octokit.Tests.Integration/Helpers/GitHubEnterpriseManagementConsoleTestAttribute.cs b/Octokit.Tests.Integration/Helpers/GitHubEnterpriseManagementConsoleTestAttribute.cs new file mode 100644 index 0000000000..61f48df010 --- /dev/null +++ b/Octokit.Tests.Integration/Helpers/GitHubEnterpriseManagementConsoleTestAttribute.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace Octokit.Tests.Integration +{ + public class GitHubEnterpriseManagementConsoleTestDiscoverer : IXunitTestCaseDiscoverer + { + readonly IMessageSink diagnosticMessageSink; + + public GitHubEnterpriseManagementConsoleTestDiscoverer(IMessageSink diagnosticMessageSink) + { + this.diagnosticMessageSink = diagnosticMessageSink; + } + + public IEnumerable Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute) + { + if (Helper.Credentials == null) + return Enumerable.Empty(); + + if (!EnterpriseHelper.IsGitHubEnterpriseEnabled) + return Enumerable.Empty(); + + if (String.IsNullOrEmpty(EnterpriseHelper.ManagementConsolePassword)) + return Enumerable.Empty(); + + return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) }; + } + } + + [XunitTestCaseDiscoverer("Octokit.Tests.Integration.GitHubEnterpriseManagementConsoleTestDiscoverer", "Octokit.Tests.Integration")] + public class GitHubEnterpriseManagementConsoleTestAttribute : FactAttribute + { + } +} \ No newline at end of file diff --git a/Octokit.Tests.Integration/Helpers/GitHubEnterpriseTestAttribute.cs b/Octokit.Tests.Integration/Helpers/GitHubEnterpriseTestAttribute.cs index 938bfb4641..c53df6e153 100644 --- a/Octokit.Tests.Integration/Helpers/GitHubEnterpriseTestAttribute.cs +++ b/Octokit.Tests.Integration/Helpers/GitHubEnterpriseTestAttribute.cs @@ -23,7 +23,7 @@ public IEnumerable Discover(ITestFrameworkDiscoveryOptions disco if (!EnterpriseHelper.IsGitHubEnterpriseEnabled) return Enumerable.Empty(); - return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod) }; + return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) }; } } diff --git a/Octokit.Tests.Integration/Helpers/GithubClientExtensions.cs b/Octokit.Tests.Integration/Helpers/GithubClientExtensions.cs index 1dbd2d6854..329b6360ea 100644 --- a/Octokit.Tests.Integration/Helpers/GithubClientExtensions.cs +++ b/Octokit.Tests.Integration/Helpers/GithubClientExtensions.cs @@ -79,5 +79,10 @@ internal static async Task CreateGpgKeyContext(this IGitHubClient return new GpgKeyContext(client.Connection, key); } + + internal static MaintenanceModeContext CreateMaintenanceModeContext(this IGitHubClient client, bool enabled) + { + return new MaintenanceModeContext(client.Connection, enabled); + } } } \ No newline at end of file diff --git a/Octokit.Tests.Integration/Helpers/IntegrationTestAttribute.cs b/Octokit.Tests.Integration/Helpers/IntegrationTestAttribute.cs index 15efa98022..fd7ec2435f 100644 --- a/Octokit.Tests.Integration/Helpers/IntegrationTestAttribute.cs +++ b/Octokit.Tests.Integration/Helpers/IntegrationTestAttribute.cs @@ -19,7 +19,7 @@ public IEnumerable Discover(ITestFrameworkDiscoveryOptions disco { return Helper.Credentials == null ? Enumerable.Empty() - : new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod) }; + : new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) }; } } diff --git a/Octokit.Tests.Integration/Helpers/MaintenanceModeContext.cs b/Octokit.Tests.Integration/Helpers/MaintenanceModeContext.cs new file mode 100644 index 0000000000..26c405356a --- /dev/null +++ b/Octokit.Tests.Integration/Helpers/MaintenanceModeContext.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Octokit.Reactive; + +namespace Octokit.Tests.Integration.Helpers +{ + internal sealed class MaintenanceModeContext : IDisposable + { + internal MaintenanceModeContext(IConnection connection, bool enabled) + { + _connection = connection; + + // Ensure maintenance mode is in the desired initial state + EnterpriseHelper.SetMaintenanceMode(_connection, enabled); + } + + private IConnection _connection; + + public void Dispose() + { + // Ensure maintenance mode is OFF + EnterpriseHelper.SetMaintenanceMode(_connection, false); + } + } +} diff --git a/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs b/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs index c3656a0b07..5c52a61246 100644 --- a/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs +++ b/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs @@ -81,5 +81,10 @@ internal static async Task CreateGpgKeyContext(this IObservableGi return new GpgKeyContext(client.Connection, key); } + + internal static MaintenanceModeContext CreateMaintenanceModeContext(this IObservableGitHubClient client, bool enabled) + { + return new MaintenanceModeContext(client.Connection, enabled); + } } } \ No newline at end of file diff --git a/Octokit.Tests.Integration/Helpers/OrganizationRepositoryWithTeamContext.cs b/Octokit.Tests.Integration/Helpers/OrganizationRepositoryWithTeamContext.cs index 7322913bda..8c36d50389 100644 --- a/Octokit.Tests.Integration/Helpers/OrganizationRepositoryWithTeamContext.cs +++ b/Octokit.Tests.Integration/Helpers/OrganizationRepositoryWithTeamContext.cs @@ -32,7 +32,7 @@ internal async static Task CreateRepositoryWithProtectedBranc // Protect master branch var update = new BranchProtectionSettingsUpdate( new BranchProtectionRequiredStatusChecksUpdate(true, new[] { "build", "test" }), - new BranchProtectionRequiredReviewsUpdate(true, true), + new BranchProtectionRequiredReviewsUpdate(true, true, 3), null, true); @@ -60,7 +60,7 @@ await client.Organization.Team.AddRepository( // Protect master branch var protection = new BranchProtectionSettingsUpdate( new BranchProtectionRequiredStatusChecksUpdate(true, new[] { "build", "test" }), - new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(new BranchProtectionTeamCollection { contextOrgTeam.TeamName }), true, true), + new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(new BranchProtectionTeamCollection { contextOrgTeam.TeamName }), true, true, 3), new BranchProtectionPushRestrictionsUpdate(new BranchProtectionTeamCollection { contextOrgTeam.TeamName }), true); await client.Repository.Branch.UpdateBranchProtection(contextOrgRepo.RepositoryOwner, contextOrgRepo.RepositoryName, "master", protection); diff --git a/Octokit.Tests.Integration/Helpers/OrganizationTestAttribute.cs b/Octokit.Tests.Integration/Helpers/OrganizationTestAttribute.cs index 9798ecb55b..2d886f0783 100644 --- a/Octokit.Tests.Integration/Helpers/OrganizationTestAttribute.cs +++ b/Octokit.Tests.Integration/Helpers/OrganizationTestAttribute.cs @@ -22,7 +22,7 @@ public IEnumerable Discover(ITestFrameworkDiscoveryOptions disco return Enumerable.Empty(); } - return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod) }; + return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) }; } } diff --git a/Octokit.Tests.Integration/Helpers/PaidAccountTestAttribute.cs b/Octokit.Tests.Integration/Helpers/PaidAccountTestAttribute.cs index 332fec10e0..01d1ae16fa 100644 --- a/Octokit.Tests.Integration/Helpers/PaidAccountTestAttribute.cs +++ b/Octokit.Tests.Integration/Helpers/PaidAccountTestAttribute.cs @@ -23,7 +23,7 @@ public IEnumerable Discover(ITestFrameworkDiscoveryOptions disco if (!Helper.IsPaidAccount) return Enumerable.Empty(); - return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod) }; + return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) }; } } diff --git a/Octokit.Tests.Integration/Helpers/PersonalAccessTokenTestAttribute.cs b/Octokit.Tests.Integration/Helpers/PersonalAccessTokenTestAttribute.cs index fabd5b9023..87f5d9e09f 100644 --- a/Octokit.Tests.Integration/Helpers/PersonalAccessTokenTestAttribute.cs +++ b/Octokit.Tests.Integration/Helpers/PersonalAccessTokenTestAttribute.cs @@ -18,7 +18,7 @@ public PersonalAccessTokenTestDiscoverer(IMessageSink diagnosticMessageSink) public IEnumerable Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute) { return Helper.IsUsingToken - ? new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod) } + ? new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) } : Enumerable.Empty(); } } diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index c38f326981..29e43af0e7 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -4,7 +4,7 @@ Integration tests for Octokit Octokit.Tests.Integration GitHub - netcoreapp2.0;net452 + netcoreapp3.1;net452 $(NoWarn);CS4014;CS1998 Octokit.Tests.Integration Octokit.Tests.Integration @@ -19,7 +19,7 @@ false - + $(DefineConstants);GITHUBJWT_HELPER_AVAILABLE @@ -36,19 +36,21 @@ - - - + + + - - - 0.0.2 - + + + + + + diff --git a/Octokit.Tests.Integration/Reactive/Enterprise/ObservableEnterpriseManagementConsoleTests.cs b/Octokit.Tests.Integration/Reactive/Enterprise/ObservableEnterpriseManagementConsoleTests.cs new file mode 100644 index 0000000000..9311f5a88b --- /dev/null +++ b/Octokit.Tests.Integration/Reactive/Enterprise/ObservableEnterpriseManagementConsoleTests.cs @@ -0,0 +1,92 @@ +using System; +using System.Linq; +using System.Reactive.Linq; +using System.Threading.Tasks; +using Octokit.Reactive; +using Octokit.Tests.Integration.Helpers; +using Xunit; + +namespace Octokit.Tests.Integration +{ + public class ObservableEnterpriseManagementConsoleTests + { + readonly IObservableGitHubClient _github; + + public ObservableEnterpriseManagementConsoleTests() + { + _github = new ObservableGitHubClient(EnterpriseHelper.GetAuthenticatedClient()); + } + + [GitHubEnterpriseManagementConsoleTest] + public async Task CanGetMaintenanceMode() + { + var maintenance = await _github.Enterprise.ManagementConsole.GetMaintenanceMode(EnterpriseHelper.ManagementConsolePassword); + + Assert.NotNull(maintenance); + } + + [GitHubEnterpriseManagementConsoleTest] + public async Task CanSetMaintenanceModeOff() + { + using (_github.CreateMaintenanceModeContext(true)) + { + // Set maintenance mode OFF now + var maintenance = await + _github.Enterprise.ManagementConsole.EditMaintenanceMode( + new UpdateMaintenanceRequest(), + EnterpriseHelper.ManagementConsolePassword); + + Assert.Equal(MaintenanceModeStatus.Off, maintenance.Status); + } + } + + [GitHubEnterpriseManagementConsoleTest] + public async Task CanSetMaintenanceModeOnNow() + { + using (_github.CreateMaintenanceModeContext(false)) + { + // Set maintenance mode ON now + var maintenance = await + _github.Enterprise.ManagementConsole.EditMaintenanceMode( + new UpdateMaintenanceRequest( + new UpdateMaintenanceRequestDetails(true)), + EnterpriseHelper.ManagementConsolePassword); + + Assert.Equal(MaintenanceModeStatus.On, maintenance.Status); + } + } + + [GitHubEnterpriseManagementConsoleTest] + public async Task CanScheduleMaintenanceModeOnWithDateTime() + { + using (_github.CreateMaintenanceModeContext(false)) + { + // Schedule maintenance mode ON in 5 minutes + var scheduledTime = DateTimeOffset.Now.AddMinutes(5); + var maintenance = await + _github.Enterprise.ManagementConsole.EditMaintenanceMode( + new UpdateMaintenanceRequest( + new UpdateMaintenanceRequestDetails(true, scheduledTime)), + EnterpriseHelper.ManagementConsolePassword); + + Assert.Equal(MaintenanceModeStatus.Scheduled, maintenance.Status); + } + } + + [GitHubEnterpriseManagementConsoleTest] + public async Task CanScheduleMaintenanceModeOnWithPhrase() + { + using (_github.CreateMaintenanceModeContext(false)) + { + // Schedule maintenance mode ON with phrase + var maintenance = await + _github.Enterprise.ManagementConsole.EditMaintenanceMode( + new UpdateMaintenanceRequest( + new UpdateMaintenanceRequestDetails(true, "tomorrow at 5pm")), + EnterpriseHelper.ManagementConsolePassword); + + Assert.Equal(MaintenanceModeStatus.Scheduled, maintenance.Status); + } + } + } +} \ No newline at end of file diff --git a/Octokit.Tests.Integration/Reactive/ObservableCheckSuitesClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableCheckSuitesClientTests.cs index f4e752d65d..68cc68df07 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableCheckSuitesClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableCheckSuitesClientTests.cs @@ -133,7 +133,7 @@ public async Task UpdatesPreferences() Assert.Equal(repoContext.RepositoryId, result.Repository.Id); Assert.Equal(Helper.GitHubAppId, result.Preferences.AutoTriggerChecks[0].AppId); - Assert.Equal(false, result.Preferences.AutoTriggerChecks[0].Setting); + Assert.False(result.Preferences.AutoTriggerChecks[0].Setting); } } @@ -150,7 +150,7 @@ public async Task UpdatesPreferencesWithRepositoryId() Assert.Equal(repoContext.RepositoryId, result.Repository.Id); Assert.Equal(Helper.GitHubAppId, result.Preferences.AutoTriggerChecks[0].AppId); - Assert.Equal(false, result.Preferences.AutoTriggerChecks[0].Setting); + Assert.False(result.Preferences.AutoTriggerChecks[0].Setting); } } } diff --git a/Octokit.Tests.Integration/Reactive/ObservableOrganizationMembersClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableOrganizationMembersClientTests.cs index aea37f8470..6095584ba3 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableOrganizationMembersClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableOrganizationMembersClientTests.cs @@ -1,4 +1,5 @@ using System.Reactive.Linq; +using System.Reactive.Threading.Tasks; using System.Threading.Tasks; using Octokit.Reactive; using Octokit.Tests.Integration.Helpers; @@ -8,6 +9,78 @@ namespace Octokit.Tests.Integration.Reactive { public class ObservableOrganizationMembersClientTests { + public class TheGetOrganizationMembershipMethod + { + readonly IGitHubClient _gitHub; + readonly ObservableOrganizationMembersClient _client; + + public TheGetOrganizationMembershipMethod() + { + _gitHub = Helper.GetAuthenticatedClient(); + _client = new ObservableOrganizationMembersClient(_gitHub); + } + + [OrganizationTest] + public async Task ReturnsUsersMembershipOrganizationMembership() + { + using (var teamContext = await _gitHub.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + { + teamContext.InviteMember("alfhenrik-test-2"); + + var organizationMemberhip = await _client.GetOrganizationMembership(Helper.Organization, "alfhenrik-test-2"); + Assert.Equal(MembershipState.Pending, organizationMemberhip.State); + Assert.Equal(MembershipRole.Member, organizationMemberhip.Role); + await _client.RemoveOrganizationMembership(Helper.Organization, "alfhenrik-test-2"); + } + } + } + + public class TheAddOrUpdateOrganizationMembershipMethod + { + readonly ObservableOrganizationMembersClient _client; + + public TheAddOrUpdateOrganizationMembershipMethod() + { + _client = new ObservableOrganizationMembersClient(Helper.GetAuthenticatedClient()); + } + + [OrganizationTest] + public async Task ReturnsUsersPendingMemberOrganizationMembership() + { + var organizationMembership = await _client.AddOrUpdateOrganizationMembership(Helper.Organization, "alfhenrik-test-2", new OrganizationMembershipUpdate()); + Assert.Equal(MembershipState.Pending, organizationMembership.State); + Assert.Equal(MembershipRole.Member, organizationMembership.Role); + await _client.RemoveOrganizationMembership(Helper.Organization, "alfhenrik-test-2"); + } + + [OrganizationTest] + public async Task ReturnsUsersPendingAdminOrganizationMembership() + { + var organizationMembership = await _client.AddOrUpdateOrganizationMembership(Helper.Organization, "alfhenrik-test-2", new OrganizationMembershipUpdate { Role = MembershipRole.Admin }); + Assert.Equal(MembershipState.Pending, organizationMembership.State); + Assert.Equal(MembershipRole.Admin, organizationMembership.Role); + await _client.RemoveOrganizationMembership(Helper.Organization, "alfhenrik-test-2"); + } + } + + public class TheRemoveOrganizationMembershipMethod + { + readonly ObservableOrganizationMembersClient _client; + + public TheRemoveOrganizationMembershipMethod() + { + _client = new ObservableOrganizationMembersClient(Helper.GetAuthenticatedClient()); + } + + [OrganizationTest] + public async Task RemovesOrganizationMembership() + { + await _client.AddOrUpdateOrganizationMembership(Helper.Organization, "alfhenrik-test-2", new OrganizationMembershipUpdate()); + await _client.RemoveOrganizationMembership(Helper.Organization, "alfhenrik-test-2"); + await Assert.ThrowsAsync(() => _client.GetOrganizationMembership(Helper.Organization, "alfhenrik-test-2").ToTask()); + } + } + public class TheGetAllPendingInvitationsMethod { readonly IGitHubClient _gitHub; diff --git a/Octokit.Tests.Integration/Reactive/ObservableReleaseClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableReleaseClientTests.cs index c5349c8571..537ba78298 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableReleaseClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableReleaseClientTests.cs @@ -101,9 +101,9 @@ public async Task ReturnsReleaseByTag() { var releaseByTag = await _releaseClient.Get("octokit", "octokit.net", "v0.28.0"); - Assert.Equal(releaseByTag.Id, 8396883); - Assert.Equal(releaseByTag.Name, "v0.28 - Get to the Chopper!!!"); - Assert.Equal(releaseByTag.TagName, "v0.28.0"); + Assert.Equal(8396883, releaseByTag.Id); + Assert.Equal("v0.28 - Get to the Chopper!!!", releaseByTag.Name); + Assert.Equal("v0.28.0", releaseByTag.TagName); } [IntegrationTest] @@ -111,9 +111,9 @@ public async Task ReturnsReleaseWithRepositoryIdByTag() { var releaseByTag = await _releaseClient.Get(7528679, "v0.28.0"); - Assert.Equal(releaseByTag.Id, 8396883); - Assert.Equal(releaseByTag.Name, "v0.28 - Get to the Chopper!!!"); - Assert.Equal(releaseByTag.TagName, "v0.28.0"); + Assert.Equal(8396883, releaseByTag.Id); + Assert.Equal("v0.28 - Get to the Chopper!!!", releaseByTag.Name); + Assert.Equal("v0.28.0", releaseByTag.TagName); } [IntegrationTest] diff --git a/Octokit.Tests.Integration/Reactive/ObservableRepositoryBranchesClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableRepositoryBranchesClientTests.cs index db4ea1b58e..8cbac07c59 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableRepositoryBranchesClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableRepositoryBranchesClientTests.cs @@ -38,6 +38,7 @@ public async Task GetsBranchProtection() Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions); Assert.True(protection.RequiredPullRequestReviews.DismissStaleReviews); Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews); + Assert.Equal(3, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount); Assert.Null(protection.Restrictions); @@ -56,6 +57,7 @@ public async Task GetsBranchProtectionWithRepositoryId() Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions); Assert.True(protection.RequiredPullRequestReviews.DismissStaleReviews); Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews); + Assert.Equal(3, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount); Assert.Null(protection.Restrictions); @@ -76,6 +78,7 @@ public async Task GetsBranchProtectionForOrgRepo() Assert.Equal(0, protection.RequiredPullRequestReviews.DismissalRestrictions.Users.Count); Assert.True(protection.RequiredPullRequestReviews.DismissStaleReviews); Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews); + Assert.Equal(3, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount); Assert.Equal(1, protection.Restrictions.Teams.Count); Assert.Equal(0, protection.Restrictions.Users.Count); @@ -96,6 +99,7 @@ public async Task GetsBranchProtectionForOrgRepoWithRepositoryId() Assert.Equal(0, protection.RequiredPullRequestReviews.DismissalRestrictions.Users.Count); Assert.True(protection.RequiredPullRequestReviews.DismissStaleReviews); Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews); + Assert.Equal(3, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount); Assert.Equal(1, protection.Restrictions.Teams.Count); Assert.Equal(0, protection.Restrictions.Users.Count); @@ -135,7 +139,7 @@ public async Task UpdatesBranchProtection() var repoName = _userRepoContext.RepositoryName; var update = new BranchProtectionSettingsUpdate( new BranchProtectionRequiredStatusChecksUpdate(false, new[] { "new" }), - new BranchProtectionRequiredReviewsUpdate(false, true), + new BranchProtectionRequiredReviewsUpdate(false, true, 2), false); var protection = await _client.UpdateBranchProtection(repoOwner, repoName, "master", update); @@ -146,6 +150,7 @@ public async Task UpdatesBranchProtection() Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions); Assert.False(protection.RequiredPullRequestReviews.DismissStaleReviews); Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews); + Assert.Equal(2, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount); Assert.Null(protection.Restrictions); @@ -158,7 +163,7 @@ public async Task UpdatesBranchProtectionWithRepositoryId() var repoId = _userRepoContext.RepositoryId; var update = new BranchProtectionSettingsUpdate( new BranchProtectionRequiredStatusChecksUpdate(false, new[] { "new" }), - new BranchProtectionRequiredReviewsUpdate(false, true), + new BranchProtectionRequiredReviewsUpdate(false, true, 2), false); var protection = await _client.UpdateBranchProtection(repoId, "master", update); @@ -169,6 +174,7 @@ public async Task UpdatesBranchProtectionWithRepositoryId() Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions); Assert.False(protection.RequiredPullRequestReviews.DismissStaleReviews); Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews); + Assert.Equal(2, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount); Assert.Null(protection.Restrictions); @@ -182,7 +188,7 @@ public async Task UpdatesBranchProtectionForOrgRepo() var repoName = _orgRepoContext.RepositoryContext.RepositoryName; var update = new BranchProtectionSettingsUpdate( new BranchProtectionRequiredStatusChecksUpdate(false, new[] { "new" }), - new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, false), + new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, false, 2), new BranchProtectionPushRestrictionsUpdate(), false); @@ -194,6 +200,7 @@ public async Task UpdatesBranchProtectionForOrgRepo() Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions); Assert.False(protection.RequiredPullRequestReviews.DismissStaleReviews); Assert.False(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews); + Assert.Equal(2, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount); Assert.Empty(protection.Restrictions.Teams); Assert.Empty(protection.Restrictions.Users); @@ -207,7 +214,7 @@ public async Task UpdatesBranchProtectionForOrgRepoWithRepositoryId() var repoId = _orgRepoContext.RepositoryContext.RepositoryId; var update = new BranchProtectionSettingsUpdate( new BranchProtectionRequiredStatusChecksUpdate(false, new[] { "new" }), - new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, false), + new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, false, 2), new BranchProtectionPushRestrictionsUpdate(), false); @@ -219,6 +226,7 @@ public async Task UpdatesBranchProtectionForOrgRepoWithRepositoryId() Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions); Assert.False(protection.RequiredPullRequestReviews.DismissStaleReviews); Assert.False(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews); + Assert.Equal(2, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount); Assert.Empty(protection.Restrictions.Teams); Assert.Empty(protection.Restrictions.Users); @@ -391,26 +399,28 @@ public async Task UpdatesReviewEnforcement() { var repoOwner = _userRepoContext.RepositoryOwner; var repoName = _userRepoContext.RepositoryName; - var update = new BranchProtectionRequiredReviewsUpdate(false, true); + var update = new BranchProtectionRequiredReviewsUpdate(false, true, 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoOwner, repoName, "master", update); Assert.Null(requiredReviews.DismissalRestrictions); Assert.False(requiredReviews.DismissStaleReviews); Assert.True(requiredReviews.RequireCodeOwnerReviews); + Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); } [IntegrationTest] public async Task UpdatesReviewEnforcementWithRepositoryId() { var repoId = _userRepoContext.RepositoryId; - var update = new BranchProtectionRequiredReviewsUpdate(false, true); + var update = new BranchProtectionRequiredReviewsUpdate(false, true, 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoId, "master", update); Assert.Null(requiredReviews.DismissalRestrictions); Assert.False(requiredReviews.DismissStaleReviews); Assert.True(requiredReviews.RequireCodeOwnerReviews); + Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); } [IntegrationTest] @@ -421,13 +431,15 @@ public async Task UpdatesReviewEnforcementForOrgRepo() var update = new BranchProtectionRequiredReviewsUpdate( new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, - false); + false, + 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoOwner, repoName, "master", update); Assert.Null(requiredReviews.DismissalRestrictions); Assert.False(requiredReviews.DismissStaleReviews); Assert.False(requiredReviews.RequireCodeOwnerReviews); + Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); } [IntegrationTest] @@ -437,13 +449,15 @@ public async Task UpdatesReviewEnforcementForOrgRepoWithRepositoryId() var update = new BranchProtectionRequiredReviewsUpdate( new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, - false); + false, + 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoId, "master", update); Assert.Null(requiredReviews.DismissalRestrictions); Assert.False(requiredReviews.DismissStaleReviews); Assert.False(requiredReviews.RequireCodeOwnerReviews); + Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); } [IntegrationTest] @@ -454,7 +468,8 @@ public async Task UpdatesReviewEnforcementForOrgRepoWithAdminOnly() var update = new BranchProtectionRequiredReviewsUpdate( new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(true), false, - false); + false, + 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoOwner, repoName, "master", update); @@ -471,7 +486,8 @@ public async Task UpdatesReviewEnforcementForOrgRepoWithAdminOnlyWithRepositoryI var update = new BranchProtectionRequiredReviewsUpdate( new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(true), false, - false); + false, + 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoId, "master", update); @@ -479,6 +495,7 @@ public async Task UpdatesReviewEnforcementForOrgRepoWithAdminOnlyWithRepositoryI Assert.Empty(requiredReviews.DismissalRestrictions.Users); Assert.False(requiredReviews.DismissStaleReviews); Assert.False(requiredReviews.RequireCodeOwnerReviews); + Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); } public void Dispose() diff --git a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs index bcc97ec37f..0e8133659d 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs @@ -30,8 +30,8 @@ public async Task GetsChildTeams() var teams = await _github.Organization.Team.GetAllChildTeams(parentTeamContext.TeamId).ToList(); Assert.Equal(2, teams.Count); - Assert.True(teams.Any(x => x.Id == team1.Id)); - Assert.True(teams.Any(x => x.Id == team2.Id)); + Assert.Contains(teams, x => x.Id == team1.Id); + Assert.Contains(teams, x => x.Id == team2.Id); } } diff --git a/Octokit.Tests.Integration/Reactive/ObservableUserGpgKeysClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableUserGpgKeysClientTests.cs index 0d6878c44d..eb10a3c59a 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableUserGpgKeysClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableUserGpgKeysClientTests.cs @@ -33,7 +33,7 @@ public async Task CanGetAllForCurrentUser() Assert.NotEmpty(keys); var first = keys[0]; - Assert.NotNull(first.Id); + Assert.NotEqual(default, first.Id); Assert.Null(first.PrimaryKeyId); Assert.NotNull(first.KeyId); Assert.NotNull(first.PublicKey); @@ -89,7 +89,7 @@ public async Task CanCreateAndDeleteKey() // Verify key no longer exists var keys = await _gitHubClient.User.GpgKey.GetAllForCurrent().ToList(); - Assert.False(keys.Any(k => k.KeyId == knownKeyId && k.PublicKey == knownPublicKey)); + Assert.DoesNotContain(keys, k => k.KeyId == knownKeyId && k.PublicKey == knownPublicKey); } } } diff --git a/Octokit.Tests.Integration/Reactive/ObservableUserKeysClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableUserKeysClientTests.cs index 61cbf8628e..d35aee12aa 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableUserKeysClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableUserKeysClientTests.cs @@ -27,7 +27,7 @@ public async Task CanGetAllForCurrentUser() Assert.NotEmpty(keys); var first = keys[0]; - Assert.NotNull(first.Id); + Assert.True(first.Id > 0); Assert.NotNull(first.Key); Assert.NotNull(first.Title); Assert.NotNull(first.Url); @@ -43,7 +43,7 @@ public async Task CanGetAllForGivenUser() Assert.NotEmpty(keys); var first = keys[0]; - Assert.NotNull(first.Id); + Assert.True(first.Id > 0); Assert.NotNull(first.Key); Assert.Null(first.Title); Assert.Null(first.Url); @@ -81,7 +81,7 @@ public async Task CanCreateAndDeleteKey() // Verify key no longer exists var keys = await _github.User.GitSshKey.GetAllForCurrent().ToList(); - Assert.False(keys.Any(k => k.Title == keyTitle && k.Key == keyData)); + Assert.DoesNotContain(keys, k => k.Title == keyTitle && k.Key == keyData); } } } diff --git a/Octokit.Tests.Integration/RedirectTests.cs b/Octokit.Tests.Integration/RedirectTests.cs index 012be7a8c3..a024399d87 100644 --- a/Octokit.Tests.Integration/RedirectTests.cs +++ b/Octokit.Tests.Integration/RedirectTests.cs @@ -31,7 +31,7 @@ public async Task CanCreateIssueOnRedirectedRepository() var issue = await client.Issue.Create(owner, oldRepoName, newIssue); Assert.NotNull(issue); - Assert.True(issue.Url.Contains("repository-after-rename")); + Assert.Contains("repository-after-rename", issue.Url); var resolvedIssue = await client.Issue.Get(owner, newRepoName, issue.Number); diff --git a/Octokit.Tests/Clients/AuthorizationsClientTests.cs b/Octokit.Tests/Clients/AuthorizationsClientTests.cs index 8314fddafd..5851071246 100644 --- a/Octokit.Tests/Clients/AuthorizationsClientTests.cs +++ b/Octokit.Tests/Clients/AuthorizationsClientTests.cs @@ -271,7 +271,7 @@ public async Task GetsOrCreatesAuthenticationWithFingerprintAtCorrectUrl() authEndpoint.GetOrCreateApplicationAuthentication("clientId", "secret", data); Assert.NotNull(calledUri); - Assert.Equal(calledUri.ToString(), "authorizations/clients/clientId"); + Assert.Equal("authorizations/clients/clientId", calledUri.ToString()); Assert.NotNull(calledBody); var fingerprintProperty = ((IEnumerable)calledBody.GetType().DeclaredProperties).FirstOrDefault(x => x.Name == "fingerprint"); diff --git a/Octokit.Tests/Clients/CommitCommentReactionsClientTests.cs b/Octokit.Tests/Clients/CommitCommentReactionsClientTests.cs index 0f55c0e8a4..fe9dc39b35 100644 --- a/Octokit.Tests/Clients/CommitCommentReactionsClientTests.cs +++ b/Octokit.Tests/Clients/CommitCommentReactionsClientTests.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.InteropServices.ComTypes; using System.Threading.Tasks; using NSubstitute; using Xunit; @@ -26,7 +27,25 @@ public async Task RequestsCorrectUrl() await client.GetAll("fake", "repo", 42); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/comments/42/reactions"), "application/vnd.github.squirrel-girl-preview"); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/comments/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlApiOptions() + { + var connection = Substitute.For(); + var client = new CommitCommentReactionsClient(connection); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1, + PageSize = 1 + }; + + await client.GetAll("fake", "repo", 42, options); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/comments/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", options); } [Fact] @@ -37,7 +56,25 @@ public async Task RequestsCorrectUrlWithRepositoryId() await client.GetAll(1, 42); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/comments/42/reactions"), "application/vnd.github.squirrel-girl-preview"); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/comments/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryIdApiOptions() + { + var connection = Substitute.For(); + var client = new CommitCommentReactionsClient(connection); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1, + PageSize = 1 + }; + + await client.GetAll(1, 42, options); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/comments/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", options); } [Fact] @@ -48,10 +85,20 @@ public async Task EnsuresNotNullArguments() await Assert.ThrowsAsync(() => client.GetAll(null, "name", 1)); await Assert.ThrowsAsync(() => client.GetAll("owner", null, 1)); + await Assert.ThrowsAsync(() => client.GetAll("owner", "name", 1, null)); await Assert.ThrowsAsync(() => client.GetAll("", "name", 1)); await Assert.ThrowsAsync(() => client.GetAll("owner", "", 1)); } + + [Fact] + public async Task EnsuresNotNullArgumentsWithRepositoryId() + { + var connection = Substitute.For(); + var client = new CommitCommentReactionsClient(connection); + + await Assert.ThrowsAsync(() => client.GetAll(1, 1, null)); + } } public class TheCreateMethod diff --git a/Octokit.Tests/Clients/Enterprise/EnterpriseManagementConsoleClientTests.cs b/Octokit.Tests/Clients/Enterprise/EnterpriseManagementConsoleClientTests.cs new file mode 100644 index 0000000000..6ba091b80c --- /dev/null +++ b/Octokit.Tests/Clients/Enterprise/EnterpriseManagementConsoleClientTests.cs @@ -0,0 +1,102 @@ +using System; +using System.Threading.Tasks; +using NSubstitute; +using Xunit; + +namespace Octokit.Tests.Clients +{ + public class EnterpriseManagementConsoleClientTests + { + public class TheGetMaintenanceModeMethod + { + [Fact] + public void RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new EnterpriseManagementConsoleClient(connection); + + string expectedUri = "setup/api/maintenance?api_key=Password01"; + client.GetMaintenanceMode("Password01"); + + connection.Received().Get(Arg.Is(u => u.ToString() == expectedUri)); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new EnterpriseManagementConsoleClient(connection); + + await Assert.ThrowsAsync(() => client.GetMaintenanceMode(null)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var connection = Substitute.For(); + var client = new EnterpriseManagementConsoleClient(connection); + + await Assert.ThrowsAsync(() => client.GetMaintenanceMode("")); + } + } + + public class TheEditMaintenanceModeMethod + { + [Fact] + public void RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new EnterpriseManagementConsoleClient(connection); + + string expectedUri = "setup/api/maintenance?api_key=Password01"; + client.EditMaintenanceMode(new UpdateMaintenanceRequest(), "Password01"); + + connection.Received().Post( + Arg.Is(u => u.ToString() == expectedUri), + Arg.Any()); + } + + [Fact] + public void PassesRequestObject() + { + var connection = Substitute.For(); + var client = new EnterpriseManagementConsoleClient(connection); + + client.EditMaintenanceMode(new UpdateMaintenanceRequest(new UpdateMaintenanceRequestDetails(true)), "Password01"); + + connection.Received().Post( + Arg.Any(), + Arg.Is(a => + a == "maintenance={\"enabled\":true,\"when\":\"now\"}")); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new EnterpriseManagementConsoleClient(connection); + + await Assert.ThrowsAsync(() => client.EditMaintenanceMode(null, "Password01")); + await Assert.ThrowsAsync(() => client.EditMaintenanceMode(new UpdateMaintenanceRequest(), null)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var connection = Substitute.For(); + var client = new EnterpriseManagementConsoleClient(connection); + + await Assert.ThrowsAsync(() => client.EditMaintenanceMode(new UpdateMaintenanceRequest(), "")); + } + } + + public class TheCtor + { + [Fact] + public void EnsuresNonNullArguments() + { + Assert.Throws(() => new EnterpriseManagementConsoleClient(null)); + } + } + } +} diff --git a/Octokit.Tests/Clients/EventsClientTests.cs b/Octokit.Tests/Clients/EventsClientTests.cs index 99a65a7cd4..fb38f29252 100644 --- a/Octokit.Tests/Clients/EventsClientTests.cs +++ b/Octokit.Tests/Clients/EventsClientTests.cs @@ -556,6 +556,8 @@ public async Task EnsuresNonNullArguments() {"CheckRunEvent", typeof(CheckRunEventPayload)}, {"CheckSuiteEvent", typeof(CheckSuiteEventPayload)}, {"CommitCommentEvent", typeof(CommitCommentPayload)}, + {"CreateEvent", typeof(CreateEventPayload)}, + {"DeleteEvent", typeof(DeleteEventPayload)}, {"ForkEvent", typeof(ForkEventPayload)}, {"IssueCommentEvent", typeof(IssueCommentPayload)}, {"IssuesEvent", typeof(IssueEventPayload)}, @@ -623,6 +625,54 @@ public async Task DeserializesCommitCommentEventCorrectly() Assert.Equal(1337, payload.Comment.Id); } + [Fact] + public async Task DeserializesCreateEventCorrectly() + { + var jsonObj = new JsonObject + { + { "type", "CreateEvent" }, + { + "payload", new + { + @ref = "master", + ref_type = "branch", + } + } + }; + + var client = GetTestingEventsClient(jsonObj); + var activities = await client.GetAll(); + Assert.Equal(1, activities.Count); + + var payload = activities.FirstOrDefault().Payload as CreateEventPayload; + Assert.Equal("master", payload.Ref); + Assert.Equal(RefType.Branch, payload.RefType); + } + + [Fact] + public async Task DeserializesDeleteEventCorrectly() + { + var jsonObj = new JsonObject + { + { "type", "DeleteEvent" }, + { + "payload", new + { + @ref = "master", + ref_type = "branch", + } + } + }; + + var client = GetTestingEventsClient(jsonObj); + var activities = await client.GetAll(); + Assert.Equal(1, activities.Count); + + var payload = activities.FirstOrDefault().Payload as DeleteEventPayload; + Assert.Equal("master", payload.Ref); + Assert.Equal(RefType.Branch, payload.RefType); + } + [Fact] public async Task DeserializesForkEventCorrectly() { diff --git a/Octokit.Tests/Clients/IssueCommentReactionsClientTests.cs b/Octokit.Tests/Clients/IssueCommentReactionsClientTests.cs index 971fc225c6..ed64332c64 100644 --- a/Octokit.Tests/Clients/IssueCommentReactionsClientTests.cs +++ b/Octokit.Tests/Clients/IssueCommentReactionsClientTests.cs @@ -26,7 +26,25 @@ public async Task RequestsCorrectUrl() await client.GetAll("fake", "repo", 42); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/comments/42/reactions"), "application/vnd.github.squirrel-girl-preview"); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/comments/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlApiOptions() + { + var connection = Substitute.For(); + var client = new IssueCommentReactionsClient(connection); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1, + PageSize = 1 + }; + + await client.GetAll("fake", "repo", 42, options); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/comments/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", options); } [Fact] @@ -37,7 +55,25 @@ public async Task RequestsCorrectUrlWithRepositoryId() await client.GetAll(1, 42); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/issues/comments/42/reactions"), "application/vnd.github.squirrel-girl-preview"); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/issues/comments/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryIdApiOptions() + { + var connection = Substitute.For(); + var client = new IssueCommentReactionsClient(connection); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1, + PageSize = 1 + }; + + await client.GetAll(1, 42, options); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/issues/comments/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", options); } [Fact] @@ -48,10 +84,20 @@ public async Task EnsuresNonNullArguments() await Assert.ThrowsAsync(() => client.GetAll(null, "name", 1)); await Assert.ThrowsAsync(() => client.GetAll("owner", null, 1)); + await Assert.ThrowsAsync(() => client.GetAll("owner", "name", 1, null)); await Assert.ThrowsAsync(() => client.GetAll("", "name", 1)); await Assert.ThrowsAsync(() => client.GetAll("owner", "", 1)); } + + [Fact] + public async Task EnsuresNonNullArgumentsWithRepositoryId() + { + var connection = Substitute.For(); + var client = new IssueCommentReactionsClient(connection); + + await Assert.ThrowsAsync(() => client.GetAll(1, 1, null)); + } } public class TheCreateMethod diff --git a/Octokit.Tests/Clients/IssueCommentsClientTests.cs b/Octokit.Tests/Clients/IssueCommentsClientTests.cs index ff5a5ef9f3..884b22f191 100644 --- a/Octokit.Tests/Clients/IssueCommentsClientTests.cs +++ b/Octokit.Tests/Clients/IssueCommentsClientTests.cs @@ -180,6 +180,45 @@ public async Task RequestsCorrectUrlWithRepositoryId() Args.ApiOptions); } + [Fact] + public async Task RequestsCorrectUrlWithIssueCommentRequest() + { + var connection = Substitute.For(); + var client = new IssueCommentsClient(connection); + + var request = new IssueCommentRequest() + { + Since = new DateTimeOffset(2016, 11, 23, 11, 11, 11, 00, new TimeSpan()), + }; + + await client.GetAllForIssue("fake", "repo", 3, request); + + connection.Received().GetAll( + Arg.Is(u => u.ToString() == "repos/fake/repo/issues/3/comments"), + Arg.Any>(), + "application/vnd.github.squirrel-girl-preview", + Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryIdWithIssueCommentRequest() + { + var connection = Substitute.For(); + var client = new IssueCommentsClient(connection); + + var request = new IssueCommentRequest() + { + Since = new DateTimeOffset(2016, 11, 23, 11, 11, 11, 00, new TimeSpan()), + }; + + await client.GetAllForIssue(1, 3, request); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/issues/3/comments"), + Arg.Any>(), + "application/vnd.github.squirrel-girl-preview", + Args.ApiOptions); + } + [Fact] public async Task RequestsCorrectUrlWithApiOptions() { @@ -233,9 +272,13 @@ public async Task EnsuresNonNullArguments() await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", null, 1)); await Assert.ThrowsAsync(() => client.GetAllForIssue(null, "name", 1, ApiOptions.None)); await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", null, 1, ApiOptions.None)); - await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", "name", 1, null)); + await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", "name", 1, options: null)); + await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", "name", 1, request: null)); + await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", "name", 1, null, ApiOptions.None)); - await Assert.ThrowsAsync(() => client.GetAllForIssue(1, 1, null)); + await Assert.ThrowsAsync(() => client.GetAllForIssue(1, 1, options: null)); + await Assert.ThrowsAsync(() => client.GetAllForIssue(1, 1, request: null)); + await Assert.ThrowsAsync(() => client.GetAllForIssue(1, 1, null, ApiOptions.None)); await Assert.ThrowsAsync(() => client.GetAllForIssue("", "name", 1)); await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", "", 1)); diff --git a/Octokit.Tests/Clients/IssueReactionsClientTests.cs b/Octokit.Tests/Clients/IssueReactionsClientTests.cs index 3c0ab6be6c..cbe9e390f8 100644 --- a/Octokit.Tests/Clients/IssueReactionsClientTests.cs +++ b/Octokit.Tests/Clients/IssueReactionsClientTests.cs @@ -26,7 +26,25 @@ public async Task RequestsCorrectUrl() await client.GetAll("fake", "repo", 42); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/42/reactions"), "application/vnd.github.squirrel-girl-preview"); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlApiOptions() + { + var connection = Substitute.For(); + var client = new IssueReactionsClient(connection); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1, + PageSize = 1 + }; + + await client.GetAll("fake", "repo", 42, options); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", options); } [Fact] @@ -37,7 +55,25 @@ public async Task RequestsCorrectUrlWithRepositoryId() await client.GetAll(1, 42); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/issues/42/reactions"), "application/vnd.github.squirrel-girl-preview"); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/issues/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryIdApiOptions() + { + var connection = Substitute.For(); + var client = new IssueReactionsClient(connection); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1, + PageSize = 1 + }; + + await client.GetAll(1, 42, options); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/issues/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", options); } [Fact] @@ -48,10 +84,20 @@ public async Task EnsuresNonNullArguments() await Assert.ThrowsAsync(() => client.Issue.GetAll(null, "name", 1)); await Assert.ThrowsAsync(() => client.Issue.GetAll("owner", null, 1)); + await Assert.ThrowsAsync(() => client.Issue.GetAll("owner", "name", 1, null)); await Assert.ThrowsAsync(() => client.Issue.GetAll("", "name", 1)); await Assert.ThrowsAsync(() => client.Issue.GetAll("owner", "", 1)); } + + [Fact] + public async Task EnsuresNonNullArgumentsWithRepositoryId() + { + var connection = Substitute.For(); + var client = new ReactionsClient(connection); + + await Assert.ThrowsAsync(() => client.Issue.GetAll(1, 1, null)); + } } public class TheCreateMethod diff --git a/Octokit.Tests/Clients/MigrationsClientTests.cs b/Octokit.Tests/Clients/MigrationsClientTests.cs index a1d610a254..5dac36012b 100644 --- a/Octokit.Tests/Clients/MigrationsClientTests.cs +++ b/Octokit.Tests/Clients/MigrationsClientTests.cs @@ -55,10 +55,32 @@ public void RequestsCorrectUrl() client.GetAll("fake"); - connection.Received().Get>( + connection.Received().GetAll( Arg.Is(u => u.ToString() == "orgs/fake/migrations"), null, - AcceptHeaders.MigrationsApiPreview); + AcceptHeaders.MigrationsApiPreview, + Args.ApiOptions); + } + + [Fact] + public void RequestsCorrectUrlApiOptions() + { + var connection = Substitute.For(); + var client = new MigrationsClient(connection); + + var options = new ApiOptions + { + PageCount = 1, + PageSize = 1 + }; + + client.GetAll("fake", options); + + connection.Received().GetAll( + Arg.Is(u => u.ToString() == "orgs/fake/migrations"), + null, + AcceptHeaders.MigrationsApiPreview, + options); } [Fact] @@ -68,6 +90,7 @@ public async Task EnsuresNonNullAndNonEmptyArguments() var client = new MigrationsClient(connection); await Assert.ThrowsAsync(() => client.GetAll(null)); + await Assert.ThrowsAsync(() => client.GetAll("fake", null)); await Assert.ThrowsAsync(() => client.GetAll("")); } } diff --git a/Octokit.Tests/Clients/MiscellaneousClientTests.cs b/Octokit.Tests/Clients/MiscellaneousClientTests.cs index 07e50660ed..dd4c02820c 100644 --- a/Octokit.Tests/Clients/MiscellaneousClientTests.cs +++ b/Octokit.Tests/Clients/MiscellaneousClientTests.cs @@ -160,8 +160,8 @@ public async Task RequestsTheMetadataEndpoint() var result = await client.GetMetadata(); - Assert.Equal(result.VerifiablePasswordAuthentication, false); - Assert.Equal(result.GitHubServicesSha, "12345ABCDE"); + Assert.False(result.VerifiablePasswordAuthentication); + Assert.Equal("12345ABCDE", result.GitHubServicesSha); Assert.Equal(result.Hooks, new[] { "1.1.1.1/24", "1.1.1.2/24" }); Assert.Equal(result.Git, new[] { "1.1.2.1/24", "1.1.2.2/24" }); Assert.Equal(result.Pages, new[] { "1.1.3.1/24", "1.1.3.2/24" }); diff --git a/Octokit.Tests/Clients/OauthClientTests.cs b/Octokit.Tests/Clients/OauthClientTests.cs index b4155f9abf..b2bf4228ac 100644 --- a/Octokit.Tests/Clients/OauthClientTests.cs +++ b/Octokit.Tests/Clients/OauthClientTests.cs @@ -44,8 +44,10 @@ public void ReturnsUrlWithAllParameters() var request = new OauthLoginRequest("secret") { RedirectUri = new Uri("https://example.com/foo?foo=bar"), + Login = "johnDOE", Scopes = { "foo", "bar" }, - State = "canARY" + State = "canARY", + AllowSignup = false }; var connection = Substitute.For(); connection.BaseAddress.Returns(new Uri("https://api.github.com")); @@ -54,7 +56,7 @@ public void ReturnsUrlWithAllParameters() var result = client.GetGitHubLoginUrl(request); Assert.Equal("/login/oauth/authorize", result.AbsolutePath); - Assert.Equal("?client_id=secret&redirect_uri=https%3A%2F%2Fexample.com%2Ffoo%3Ffoo%3Dbar&scope=foo%2Cbar&state=canARY", result.Query); + Assert.Equal("?client_id=secret&redirect_uri=https%3A%2F%2Fexample.com%2Ffoo%3Ffoo%3Dbar&login=johnDOE&scope=foo%2Cbar&state=canARY&allow_signup=false", result.Query); } } @@ -138,10 +140,10 @@ public async Task DeserializesOAuthScopeFormat() var token = strategy.Deserialize(responseText); - Assert.Equal(token.AccessToken, "token-goes-here"); - Assert.Equal(token.TokenType, "bearer"); - Assert.True(token.Scope.Contains("notifications")); - Assert.True(token.Scope.Contains("user:email")); + Assert.Equal("token-goes-here", token.AccessToken); + Assert.Equal("bearer", token.TokenType); + Assert.Contains("notifications", token.Scope); + Assert.Contains("user:email", token.Scope); } } } diff --git a/Octokit.Tests/Clients/OrganizationMembersClientTests.cs b/Octokit.Tests/Clients/OrganizationMembersClientTests.cs index 09383ebfe2..d519c10611 100644 --- a/Octokit.Tests/Clients/OrganizationMembersClientTests.cs +++ b/Octokit.Tests/Clients/OrganizationMembersClientTests.cs @@ -495,6 +495,85 @@ public async Task EnsureNonNullArguments() } } + public class TheGetOrganizationMembershipMethod + { + [Fact] + public void RequestsTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new OrganizationMembersClient(connection); + + client.GetOrganizationMembership("org", "username"); + + connection.Received().Get(Arg.Is(u => u.ToString() == "orgs/org/memberships/username")); + } + + [Fact] + public async Task EnsureNonNullArguments() + { + var client = new OrganizationMembersClient(Substitute.For()); + + await Assert.ThrowsAsync(() => client.GetOrganizationMembership(null, "username")); + await Assert.ThrowsAsync(() => client.GetOrganizationMembership("", "username")); + await Assert.ThrowsAsync(() => client.GetOrganizationMembership("org", null)); + await Assert.ThrowsAsync(() => client.GetOrganizationMembership("org", "")); + } + } + + public class TheAddOrUpdateOrganizationMembershipMethod + { + [Fact] + public void PostsToTheCorrectUrl() + { + var orgMembershipUpdate = new OrganizationMembershipUpdate(); + + var connection = Substitute.For(); + var client = new OrganizationMembersClient(connection); + + client.AddOrUpdateOrganizationMembership("org", "username", orgMembershipUpdate); + + connection.Received().Put(Arg.Is(u => u.ToString() == "orgs/org/memberships/username"), Arg.Any()); + } + + [Fact] + public async Task EnsureNonNullArguments() + { + var client = new OrganizationMembersClient(Substitute.For()); + var orgMembershipUpdate = new OrganizationMembershipUpdate(); + + await Assert.ThrowsAsync(() => client.AddOrUpdateOrganizationMembership(null, "username", orgMembershipUpdate)); + await Assert.ThrowsAsync(() => client.AddOrUpdateOrganizationMembership("", "username", orgMembershipUpdate)); + await Assert.ThrowsAsync(() => client.AddOrUpdateOrganizationMembership("org", null, orgMembershipUpdate)); + await Assert.ThrowsAsync(() => client.AddOrUpdateOrganizationMembership("org", "", orgMembershipUpdate)); + await Assert.ThrowsAsync(() => client.AddOrUpdateOrganizationMembership("org", "username", null)); + } + } + + public class TheDeleteOrganizationMembershipMethod + { + [Fact] + public void PostsToTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new OrganizationMembersClient(connection); + + client.RemoveOrganizationMembership("org", "username"); + + connection.Received().Delete(Arg.Is(u => u.ToString() == "orgs/org/memberships/username")); + } + + [Fact] + public async Task EnsureNonNullArguments() + { + var client = new OrganizationMembersClient(Substitute.For()); + + await Assert.ThrowsAsync(() => client.RemoveOrganizationMembership(null, "username")); + await Assert.ThrowsAsync(() => client.RemoveOrganizationMembership("", "username")); + await Assert.ThrowsAsync(() => client.RemoveOrganizationMembership("org", null)); + await Assert.ThrowsAsync(() => client.RemoveOrganizationMembership("org", "")); + } + } + public class TheGetAllPendingInvitationsMethod { [Fact] diff --git a/Octokit.Tests/Clients/PullRequestReviewCommentReactionsClientTests.cs b/Octokit.Tests/Clients/PullRequestReviewCommentReactionsClientTests.cs index 054ef7dd85..d0eb73c3e4 100644 --- a/Octokit.Tests/Clients/PullRequestReviewCommentReactionsClientTests.cs +++ b/Octokit.Tests/Clients/PullRequestReviewCommentReactionsClientTests.cs @@ -26,7 +26,24 @@ public async Task RequestsCorrectUrl() await client.GetAll("fake", "repo", 42); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/pulls/comments/42/reactions"), "application/vnd.github.squirrel-girl-preview"); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/pulls/comments/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlApiOptions() + { + var connection = Substitute.For(); + var client = new PullRequestReviewCommentReactionsClient(connection); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1 + }; + + await client.GetAll("fake", "repo", 42, options); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/pulls/comments/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", options); } [Fact] @@ -37,7 +54,24 @@ public async Task RequestsCorrectUrlWithRepositoryId() await client.GetAll(1, 42); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/pulls/comments/42/reactions"), "application/vnd.github.squirrel-girl-preview"); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/pulls/comments/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryIdApiOptions() + { + var connection = Substitute.For(); + var client = new PullRequestReviewCommentReactionsClient(connection); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1 + }; + + await client.GetAll(1, 42, options); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/pulls/comments/42/reactions"), null, "application/vnd.github.squirrel-girl-preview", options); } [Fact] @@ -48,10 +82,20 @@ public async Task EnsuresNonNullArguments() await Assert.ThrowsAsync(() => client.GetAll(null, "name", 1)); await Assert.ThrowsAsync(() => client.GetAll("owner", null, 1)); + await Assert.ThrowsAsync(() => client.GetAll("owner", "name", 1, null)); await Assert.ThrowsAsync(() => client.GetAll("", "name", 1)); await Assert.ThrowsAsync(() => client.GetAll("owner", "", 1)); } + + [Fact] + public async Task EnsuresNonNullArgumentsWithRepositoryId() + { + var connection = Substitute.For(); + var client = new PullRequestReviewCommentReactionsClient(connection); + + await Assert.ThrowsAsync(() => client.GetAll(1, 1, null)); + } } public class TheCreateMethod diff --git a/Octokit.Tests/Clients/PullRequestsClientTests.cs b/Octokit.Tests/Clients/PullRequestsClientTests.cs index f30d2e89ca..fe0a411905 100644 --- a/Octokit.Tests/Clients/PullRequestsClientTests.cs +++ b/Octokit.Tests/Clients/PullRequestsClientTests.cs @@ -18,7 +18,7 @@ public async Task RequestsCorrectUrl() await client.Get("fake", "repo", 42); - connection.Received().Get(Arg.Is(u => u.ToString() == "repos/fake/repo/pulls/42")); + connection.Received().Get(Arg.Is(u => u.ToString() == "repos/fake/repo/pulls/42"), Arg.Any>(), "application/vnd.github.shadow-cat-preview+json"); } [Fact] @@ -29,7 +29,7 @@ public async Task RequestsCorrectUrlWithRepositoryId() await client.Get(1, 42); - connection.Received().Get(Arg.Is(u => u.ToString() == "repositories/1/pulls/42")); + connection.Received().Get(Arg.Is(u => u.ToString() == "repositories/1/pulls/42"), Arg.Any>(), "application/vnd.github.shadow-cat-preview+json"); } [Fact] @@ -56,7 +56,7 @@ public async Task RequestsCorrectUrl() await client.GetAllForRepository("fake", "repo"); connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/pulls"), - Arg.Any>(), Args.ApiOptions); + Arg.Any>(), "application/vnd.github.shadow-cat-preview+json", Args.ApiOptions); } [Fact] @@ -68,7 +68,7 @@ public async Task RequestsCorrectUrlWithRepositoryId() await client.GetAllForRepository(1); connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/pulls"), - Arg.Any>(), Args.ApiOptions); + Arg.Any>(), "application/vnd.github.shadow-cat-preview+json", Args.ApiOptions); } [Fact] @@ -87,7 +87,7 @@ public async Task RequestsCorrectUrlWithApiOptions() await client.GetAllForRepository("fake", "repo", options); connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/pulls"), - Arg.Any>(), options); + Arg.Any>(), "application/vnd.github.shadow-cat-preview+json", options); } [Fact] @@ -106,7 +106,7 @@ public async Task RequestsCorrectUrlWithApiOptionsWithRepositoryId() await client.GetAllForRepository(1, options); connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/pulls"), - Arg.Any>(), options); + Arg.Any>(), "application/vnd.github.shadow-cat-preview+json", options); } [Fact] @@ -123,7 +123,7 @@ public async Task SendsAppropriateParameters() && d["state"] == "open" && d["base"] == "fake_base_branch" && d["sort"] == "created" - && d["direction"] == "desc"), Args.ApiOptions); + && d["direction"] == "desc"), "application/vnd.github.shadow-cat-preview+json", Args.ApiOptions); } [Fact] @@ -140,7 +140,7 @@ public async Task SendsAppropriateParametersWithRepositoryId() && d["state"] == "open" && d["base"] == "fake_base_branch" && d["sort"] == "created" - && d["direction"] == "desc"), Args.ApiOptions); + && d["direction"] == "desc"), "application/vnd.github.shadow-cat-preview+json", Args.ApiOptions); } [Fact] @@ -164,7 +164,7 @@ public async Task SendsAppropriateParametersWithApiOptions() && d["state"] == "open" && d["base"] == "fake_base_branch" && d["sort"] == "created" - && d["direction"] == "desc"), options); + && d["direction"] == "desc"), "application/vnd.github.shadow-cat-preview+json", options); } [Fact] @@ -188,7 +188,7 @@ public async Task SendsAppropriateParametersWithApiOptionsWithRepositoryId() && d["state"] == "open" && d["base"] == "fake_base_branch" && d["sort"] == "created" - && d["direction"] == "desc"), options); + && d["direction"] == "desc"), "application/vnd.github.shadow-cat-preview+json", options); } [Fact] @@ -243,7 +243,7 @@ public async Task PostsToCorrectUrl() await client.Create("fake", "repo", newPullRequest); connection.Received().Post(Arg.Is(u => u.ToString() == "repos/fake/repo/pulls"), - newPullRequest); + newPullRequest, "application/vnd.github.shadow-cat-preview+json"); } [Fact] @@ -256,7 +256,7 @@ public async Task PostsToCorrectUrlWithRepositoryId() await client.Create(1, newPullRequest); connection.Received().Post(Arg.Is(u => u.ToString() == "repositories/1/pulls"), - newPullRequest); + newPullRequest, "application/vnd.github.shadow-cat-preview+json"); } [Fact] @@ -288,7 +288,7 @@ public async Task PostsToCorrectUrl() await client.Update("fake", "repo", 42, pullRequestUpdate); connection.Received().Patch(Arg.Is(u => u.ToString() == "repos/fake/repo/pulls/42"), - pullRequestUpdate); + pullRequestUpdate, "application/vnd.github.shadow-cat-preview+json"); } [Fact] @@ -301,7 +301,7 @@ public async Task PostsToCorrectUrlWithRepositoryId() await client.Update(1, 42, pullRequestUpdate); connection.Received().Patch(Arg.Is(u => u.ToString() == "repositories/1/pulls/42"), - pullRequestUpdate); + pullRequestUpdate, "application/vnd.github.shadow-cat-preview+json"); } [Fact] diff --git a/Octokit.Tests/Clients/RepoCollaboratorsClientTests.cs b/Octokit.Tests/Clients/RepoCollaboratorsClientTests.cs index edd87c8944..a4e7a5c1c4 100644 --- a/Octokit.Tests/Clients/RepoCollaboratorsClientTests.cs +++ b/Octokit.Tests/Clients/RepoCollaboratorsClientTests.cs @@ -33,7 +33,11 @@ public void RequestsCorrectUrl() client.GetAll("owner", "test"); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/owner/test/collaborators"), Args.ApiOptions); + connection.Received().GetAll( + Arg.Is(u => u.ToString() == "repos/owner/test/collaborators"), + Arg.Any>(), + "application/vnd.github.hellcat-preview+json", + Args.ApiOptions); } [Fact] @@ -44,7 +48,11 @@ public void RequestsCorrectUrlWithRepositoryId() client.GetAll(1); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/collaborators"), Args.ApiOptions); + connection.Received().GetAll( + Arg.Is(u => u.ToString() == "repositories/1/collaborators"), + Arg.Any>(), + "application/vnd.github.hellcat-preview+json", + Args.ApiOptions); } [Fact] @@ -63,7 +71,53 @@ public void RequestsCorrectUrlWithApiOptions() client.GetAll("owner", "test", options); connection.Received() - .GetAll(Arg.Is(u => u.ToString() == "repos/owner/test/collaborators"), options); + .GetAll(Arg.Is(u => u.ToString() == "repos/owner/test/collaborators"), + Arg.Any>(), + "application/vnd.github.hellcat-preview+json", + options); + } + + [Fact] + public void RequestsCorrectUrlWithCollaboratorFilter() + { + var connection = Substitute.For(); + var client = new RepoCollaboratorsClient(connection); + + var request = new RepositoryCollaboratorListRequest(); + + client.GetAll("owner", "test", request); + + connection.Received() + .GetAll(Arg.Is(u => u.ToString() == "repos/owner/test/collaborators"), + Arg.Is>(d => d["affiliation"] == "all"), + "application/vnd.github.hellcat-preview+json", + Args.ApiOptions); + + request = new RepositoryCollaboratorListRequest + { + Affiliation = CollaboratorAffiliation.Direct + }; + + client.GetAll("owner", "test", request); + + connection.Received() + .GetAll(Arg.Is(u => u.ToString() == "repos/owner/test/collaborators"), + Arg.Is>(d => d["affiliation"] == "direct"), + "application/vnd.github.hellcat-preview+json", + Args.ApiOptions); + + request = new RepositoryCollaboratorListRequest + { + Affiliation = CollaboratorAffiliation.Outside + }; + + client.GetAll("owner", "test", request); + + connection.Received() + .GetAll(Arg.Is(u => u.ToString() == "repos/owner/test/collaborators"), + Arg.Is>(d => d["affiliation"] == "outside"), + "application/vnd.github.hellcat-preview+json", + Args.ApiOptions); } [Fact] @@ -82,7 +136,57 @@ public void RequestsCorrectUrlWithApiOptionsAndRepositoryId() client.GetAll(1, options); connection.Received() - .GetAll(Arg.Is(u => u.ToString() == "repositories/1/collaborators"), options); + .GetAll( + Arg.Is(u => u.ToString() == "repositories/1/collaborators"), + Arg.Any>(), + "application/vnd.github.hellcat-preview+json", + options); + } + + [Fact] + public void RequestsCorrectUrlWithCollaboratorFilterAndRepositoryId() + { + var connection = Substitute.For(); + var client = new RepoCollaboratorsClient(connection); + + var request = new RepositoryCollaboratorListRequest(); + + client.GetAll(1, request); + + connection.Received() + .GetAll( + Arg.Is(u => u.ToString() == "repositories/1/collaborators"), + Arg.Is>(d => d["affiliation"] == "all"), + "application/vnd.github.hellcat-preview+json", + Args.ApiOptions); + + request = new RepositoryCollaboratorListRequest + { + Affiliation = CollaboratorAffiliation.Direct + }; + + client.GetAll(1, request); + + connection.Received() + .GetAll( + Arg.Is(u => u.ToString() == "repositories/1/collaborators"), + Arg.Is>(d => d["affiliation"] == "direct"), + "application/vnd.github.hellcat-preview+json", + Args.ApiOptions); + + request = new RepositoryCollaboratorListRequest + { + Affiliation = CollaboratorAffiliation.Outside + }; + + client.GetAll(1, request); + + connection.Received() + .GetAll( + Arg.Is(u => u.ToString() == "repositories/1/collaborators"), + Arg.Is>(d => d["affiliation"] == "outside"), + "application/vnd.github.hellcat-preview+json", + Args.ApiOptions); } [Fact] @@ -97,9 +201,11 @@ public async Task EnsuresNonNullArguments() await Assert.ThrowsAsync(() => client.GetAll(null, "test", ApiOptions.None)); await Assert.ThrowsAsync(() => client.GetAll("owner", null, ApiOptions.None)); - await Assert.ThrowsAsync(() => client.GetAll("owner", "test", null)); + await Assert.ThrowsAsync(() => client.GetAll("owner", "test", options: null)); + await Assert.ThrowsAsync(() => client.GetAll("owner", "test", request: null)); - await Assert.ThrowsAsync(() => client.GetAll(1, null)); + await Assert.ThrowsAsync(() => client.GetAll(1, options: null)); + await Assert.ThrowsAsync(() => client.GetAll(1, request: null)); } } diff --git a/Octokit.Tests/Clients/RepositoryBranchesClientTests.cs b/Octokit.Tests/Clients/RepositoryBranchesClientTests.cs index 28f0415366..40a5602a6f 100644 --- a/Octokit.Tests/Clients/RepositoryBranchesClientTests.cs +++ b/Octokit.Tests/Clients/RepositoryBranchesClientTests.cs @@ -33,7 +33,7 @@ public async Task RequestsTheCorrectUrl() await client.GetAll("owner", "name"); connection.Received() - .GetAll(Arg.Is(u => u.ToString() == "repos/owner/name/branches"), null, "application/vnd.github.loki-preview+json", Args.ApiOptions); + .GetAll(Arg.Is(u => u.ToString() == "repos/owner/name/branches"), null, "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json", Args.ApiOptions); } [Fact] @@ -45,7 +45,7 @@ public async Task RequestsTheCorrectUrlWithRepositoryId() await client.GetAll(1); connection.Received() - .GetAll(Arg.Is(u => u.ToString() == "repositories/1/branches"), null, "application/vnd.github.loki-preview+json", Args.ApiOptions); + .GetAll(Arg.Is(u => u.ToString() == "repositories/1/branches"), null, "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json", Args.ApiOptions); } [Fact] @@ -64,7 +64,7 @@ public async Task RequestsTheCorrectUrlWithApiOptions() await client.GetAll("owner", "name", options); connection.Received() - .GetAll(Arg.Is(u => u.ToString() == "repos/owner/name/branches"), null, "application/vnd.github.loki-preview+json", options); + .GetAll(Arg.Is(u => u.ToString() == "repos/owner/name/branches"), null, "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json", options); } [Fact] @@ -83,7 +83,7 @@ public async Task RequestsTheCorrectUrlWithRepositoryIdWithApiOptions() await client.GetAll(1, options); connection.Received() - .GetAll(Arg.Is(u => u.ToString() == "repositories/1/branches"), null, "application/vnd.github.loki-preview+json", options); + .GetAll(Arg.Is(u => u.ToString() == "repositories/1/branches"), null, "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json", options); } [Fact] @@ -118,7 +118,7 @@ public async Task RequestsTheCorrectUrl() await client.Get("owner", "repo", "branch"); connection.Received() - .Get(Arg.Is(u => u.ToString() == "repos/owner/repo/branches/branch"), null, "application/vnd.github.loki-preview+json"); + .Get(Arg.Is(u => u.ToString() == "repos/owner/repo/branches/branch"), null, "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"); } [Fact] @@ -130,7 +130,7 @@ public async Task RequestsTheCorrectUrlWithRepositoryId() await client.Get(1, "branch"); connection.Received() - .Get(Arg.Is(u => u.ToString() == "repositories/1/branches/branch"), null, "application/vnd.github.loki-preview+json"); + .Get(Arg.Is(u => u.ToString() == "repositories/1/branches/branch"), null, "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"); } [Fact] @@ -157,7 +157,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetBranchProtection("owner", "repo", "branch"); @@ -170,7 +170,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetBranchProtection(1, "branch"); @@ -206,7 +206,7 @@ public void RequestsTheCorrectUrl() var client = new RepositoryBranchesClient(connection); var update = new BranchProtectionSettingsUpdate( new BranchProtectionRequiredStatusChecksUpdate(true, new[] { "test" })); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.UpdateBranchProtection("owner", "repo", "branch", update); @@ -221,7 +221,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() var client = new RepositoryBranchesClient(connection); var update = new BranchProtectionSettingsUpdate( new BranchProtectionRequiredStatusChecksUpdate(true, new[] { "test" })); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.UpdateBranchProtection(1, "branch", update); @@ -259,7 +259,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.DeleteBranchProtection("owner", "repo", "branch"); @@ -272,7 +272,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.DeleteBranchProtection(1, "branch"); @@ -306,7 +306,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetRequiredStatusChecks("owner", "repo", "branch"); @@ -319,7 +319,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetRequiredStatusChecks(1, "branch"); @@ -354,7 +354,7 @@ public void RequestsTheCorrectUrl() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var update = new BranchProtectionRequiredStatusChecksUpdate(true, new[] { "test" }); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.UpdateRequiredStatusChecks("owner", "repo", "branch", update); @@ -368,7 +368,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var update = new BranchProtectionRequiredStatusChecksUpdate(true, new[] { "test" }); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.UpdateRequiredStatusChecks(1, "branch", update); @@ -405,7 +405,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.DeleteRequiredStatusChecks("owner", "repo", "branch"); @@ -418,7 +418,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.DeleteRequiredStatusChecks(1, "branch"); @@ -452,7 +452,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetAllRequiredStatusChecksContexts("owner", "repo", "branch"); @@ -465,7 +465,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetAllRequiredStatusChecksContexts(1, "branch"); @@ -500,7 +500,7 @@ public void RequestsTheCorrectUrl() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var update = new List() { "test" }; - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.UpdateRequiredStatusChecksContexts("owner", "repo", "branch", update); @@ -514,7 +514,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var update = new List() { "test" }; - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.UpdateRequiredStatusChecksContexts(1, "branch", update); @@ -552,7 +552,7 @@ public void RequestsTheCorrectUrl() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var newContexts = new List() { "test" }; - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.AddRequiredStatusChecksContexts("owner", "repo", "branch", newContexts); @@ -566,7 +566,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var newContexts = new List() { "test" }; - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.AddRequiredStatusChecksContexts(1, "branch", newContexts); @@ -604,7 +604,7 @@ public void RequestsTheCorrectUrl() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var contextsToRemove = new List() { "test" }; - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.DeleteRequiredStatusChecksContexts("owner", "repo", "branch", contextsToRemove); @@ -618,7 +618,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var contextsToRemove = new List() { "test" }; - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.DeleteRequiredStatusChecksContexts(1, "branch", contextsToRemove); @@ -655,7 +655,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetReviewEnforcement("owner", "repo", "branch"); @@ -668,7 +668,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetReviewEnforcement(1, "branch"); @@ -702,8 +702,8 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - var update = new BranchProtectionRequiredReviewsUpdate(false, false); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + var update = new BranchProtectionRequiredReviewsUpdate(false, false, 2); + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.UpdateReviewEnforcement("owner", "repo", "branch", update); @@ -716,8 +716,8 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - var update = new BranchProtectionRequiredReviewsUpdate(false, false); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + var update = new BranchProtectionRequiredReviewsUpdate(false, false, 2); + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.UpdateReviewEnforcement(1, "branch", update); @@ -730,7 +730,7 @@ public async Task EnsuresNonNullArguments() { var client = new RepositoryBranchesClient(Substitute.For()); - var update = new BranchProtectionRequiredReviewsUpdate(false, false); + var update = new BranchProtectionRequiredReviewsUpdate(false, false, 2); await Assert.ThrowsAsync(() => client.UpdateReviewEnforcement(null, "repo", "branch", update)); await Assert.ThrowsAsync(() => client.UpdateReviewEnforcement("owner", null, "branch", update)); @@ -755,7 +755,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.RemoveReviewEnforcement("owner", "repo", "branch"); @@ -768,7 +768,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.RemoveReviewEnforcement(1, "branch"); @@ -802,7 +802,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetAdminEnforcement("owner", "repo", "branch"); @@ -815,7 +815,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetAdminEnforcement(1, "branch"); @@ -849,7 +849,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.AddAdminEnforcement("owner", "repo", "branch"); @@ -862,7 +862,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.AddAdminEnforcement(1, "branch"); @@ -896,7 +896,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.RemoveAdminEnforcement("owner", "repo", "branch"); @@ -909,7 +909,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.RemoveAdminEnforcement(1, "branch"); @@ -943,7 +943,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetProtectedBranchRestrictions("owner", "repo", "branch"); @@ -956,7 +956,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetProtectedBranchRestrictions(1, "branch"); @@ -990,7 +990,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.DeleteProtectedBranchRestrictions("owner", "repo", "branch"); @@ -1003,7 +1003,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.DeleteProtectedBranchRestrictions(1, "branch"); @@ -1044,7 +1044,7 @@ public void RequestsTheCorrectUrl() .Get>( Arg.Is(u => u.ToString() == "repos/owner/repo/branches/branch/protection/restrictions/teams"), null, - "application/vnd.github.loki-preview+json,application/vnd.github.hellcat-preview+json"); + "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json,application/vnd.github.hellcat-preview+json"); } [Fact] @@ -1059,7 +1059,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() .Get>( Arg.Is(u => u.ToString() == "repositories/1/branches/branch/protection/restrictions/teams"), null, - "application/vnd.github.loki-preview+json,application/vnd.github.hellcat-preview+json"); + "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json,application/vnd.github.hellcat-preview+json"); } [Fact] @@ -1097,7 +1097,7 @@ public void RequestsTheCorrectUrl() Arg.Is(u => u.ToString() == "repos/owner/repo/branches/branch/protection/restrictions/teams"), Arg.Any>(), null, - "application/vnd.github.loki-preview+json,application/vnd.github.hellcat-preview+json"); + "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json,application/vnd.github.hellcat-preview+json"); } [Fact] @@ -1114,7 +1114,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() Arg.Is(u => u.ToString() == "repositories/1/branches/branch/protection/restrictions/teams"), Arg.Any>(), null, - "application/vnd.github.loki-preview+json,application/vnd.github.hellcat-preview+json"); + "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json,application/vnd.github.hellcat-preview+json"); } [Fact] @@ -1154,7 +1154,7 @@ public void RequestsTheCorrectUrl() .Post>( Arg.Is(u => u.ToString() == "repos/owner/repo/branches/branch/protection/restrictions/teams"), Arg.Any>(), - "application/vnd.github.loki-preview+json,application/vnd.github.hellcat-preview+json"); + "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json,application/vnd.github.hellcat-preview+json"); } [Fact] @@ -1170,7 +1170,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() .Post>( Arg.Is(u => u.ToString() == "repositories/1/branches/branch/protection/restrictions/teams"), Arg.Any>(), - "application/vnd.github.loki-preview+json,application/vnd.github.hellcat-preview+json"); + "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json,application/vnd.github.hellcat-preview+json"); } [Fact] @@ -1210,7 +1210,7 @@ public void RequestsTheCorrectUrl() .Delete>( Arg.Is(u => u.ToString() == "repos/owner/repo/branches/branch/protection/restrictions/teams"), Arg.Any(), - "application/vnd.github.loki-preview+json,application/vnd.github.hellcat-preview+json"); + "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json,application/vnd.github.hellcat-preview+json"); } [Fact] @@ -1226,7 +1226,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() .Delete>( Arg.Is(u => u.ToString() == "repositories/1/branches/branch/protection/restrictions/teams"), Arg.Any>(), - "application/vnd.github.loki-preview+json,application/vnd.github.hellcat-preview+json"); + "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json,application/vnd.github.hellcat-preview+json"); } [Fact] @@ -1258,7 +1258,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetAllProtectedBranchUserRestrictions("owner", "repo", "branch"); @@ -1271,7 +1271,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.GetAllProtectedBranchUserRestrictions(1, "branch"); @@ -1306,7 +1306,7 @@ public void RequestsTheCorrectUrl() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var newUsers = new BranchProtectionUserCollection() { "test" }; - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.UpdateProtectedBranchUserRestrictions("owner", "repo", "branch", newUsers); @@ -1320,7 +1320,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var newUsers = new BranchProtectionUserCollection() { "test" }; - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.UpdateProtectedBranchUserRestrictions(1, "branch", newUsers); @@ -1358,7 +1358,7 @@ public void RequestsTheCorrectUrl() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var newUsers = new BranchProtectionUserCollection() { "test" }; - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.AddProtectedBranchUserRestrictions("owner", "repo", "branch", newUsers); @@ -1372,7 +1372,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var newUsers = new BranchProtectionUserCollection() { "test" }; - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.AddProtectedBranchUserRestrictions(1, "branch", newUsers); @@ -1410,7 +1410,7 @@ public void RequestsTheCorrectUrl() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var usersToRemove = new BranchProtectionUserCollection() { "test" }; - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.DeleteProtectedBranchUserRestrictions("owner", "repo", "branch", usersToRemove); @@ -1424,7 +1424,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() var connection = Substitute.For(); var client = new RepositoryBranchesClient(connection); var usersToRemove = new BranchProtectionUserCollection() { "test" }; - const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; + const string previewAcceptsHeader = "application/vnd.github.loki-preview+json,application/vnd.github.luke-cage-preview+json"; client.DeleteProtectedBranchUserRestrictions(1, "branch", usersToRemove); diff --git a/Octokit.Tests/Clients/SearchClientTests.cs b/Octokit.Tests/Clients/SearchClientTests.cs index ace933ddc1..c2ebdabf5a 100644 --- a/Octokit.Tests/Clients/SearchClientTests.cs +++ b/Octokit.Tests/Clients/SearchClientTests.cs @@ -200,13 +200,13 @@ public void TestingTheLanguageQualifier() { var connection = Substitute.For(); var client = new SearchClient(connection); - //get users who have mostly repos where language is Ruby + //get users who have mostly repos where language is Literate Haskell var request = new SearchUsersRequest("github"); - request.Language = Language.Ruby; + request.Language = Language.LiterateHaskell; client.SearchUsers(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/users"), - Arg.Is>(d => d["q"] == "github+language:Ruby")); + Arg.Is>(d => d["q"] == "github+language:\"Literate Haskell\"")); } [Fact] @@ -215,11 +215,11 @@ public void TestingTheCreatedQualifier_GreaterThan() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchUsersRequest("github"); - request.Created = DateRange.GreaterThan(new DateTime(2014, 1, 1)); + request.Created = DateRange.GreaterThan(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchUsers(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/users"), - Arg.Is>(d => d["q"] == "github+created:>2014-01-01")); + Arg.Is>(d => d["q"] == "github+created:>2014-01-01T00:00:00+00:00")); } [Fact] @@ -228,11 +228,11 @@ public void TestingTheCreatedQualifier_GreaterThanOrEqualTo() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchUsersRequest("github"); - request.Created = DateRange.GreaterThanOrEquals(new DateTime(2014, 1, 1)); + request.Created = DateRange.GreaterThanOrEquals(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchUsers(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/users"), - Arg.Is>(d => d["q"] == "github+created:>=2014-01-01")); + Arg.Is>(d => d["q"] == "github+created:>=2014-01-01T00:00:00+00:00")); } [Fact] @@ -241,11 +241,11 @@ public void TestingTheCreatedQualifier_LessThanOrEqualTo() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchUsersRequest("github"); - request.Created = DateRange.LessThanOrEquals(new DateTime(2014, 1, 1)); + request.Created = DateRange.LessThanOrEquals(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchUsers(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/users"), - Arg.Is>(d => d["q"] == "github+created:<=2014-01-01")); + Arg.Is>(d => d["q"] == "github+created:<=2014-01-01T00:00:00+00:00")); } [Fact] @@ -254,11 +254,11 @@ public void TestingTheCreatedQualifier_LessThan() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchUsersRequest("github"); - request.Created = DateRange.LessThan(new DateTime(2014, 1, 1)); + request.Created = DateRange.LessThan(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchUsers(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/users"), - Arg.Is>(d => d["q"] == "github+created:<2014-01-01")); + Arg.Is>(d => d["q"] == "github+created:<2014-01-01T00:00:00+00:00")); } [Fact] @@ -267,11 +267,15 @@ public void TestingTheCreatedQualifier_Between() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchUsersRequest("github"); - request.Created = DateRange.Between(new DateTime(2014, 1, 1), new DateTime(2014, 2, 1)); + request.Created = DateRange.Between( + new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero), + new DateTimeOffset(new DateTime(2014, 2, 1), TimeSpan.Zero)); + client.SearchUsers(request); + connection.Received().Get( Arg.Is(u => u.ToString() == "search/users"), - Arg.Is>(d => d["q"] == "github+created:2014-01-01..2014-02-01")); + Arg.Is>(d => d["q"] == "github+created:2014-01-01T00:00:00+00:00..2014-02-01T00:00:00+00:00")); } [Fact] @@ -458,12 +462,12 @@ public void TestingTheLangaugeQualifier() { var connection = Substitute.For(); var client = new SearchClient(connection); - //get repos who's language is Ruby + //get repos who's language is Literate Haskell var request = new SearchRepositoriesRequest("github"); - request.Language = Language.Ruby; + request.Language = Language.LiterateHaskell; client.SearchRepo(request); connection.Received().Get(Arg.Is(u => u.ToString() == "search/repositories"), - Arg.Is>(d => d["q"] == "github+language:Ruby")); + Arg.Is>(d => d["q"] == "github+language:\"Literate Haskell\"")); } [Fact] @@ -525,10 +529,10 @@ public void TestingTheCreatedQualifier() var client = new SearchClient(connection); //get repos where the search contains 'github' and has been created after year jan 1 2011 var request = new SearchRepositoriesRequest("github"); - request.Created = DateRange.GreaterThan(new DateTime(2011, 1, 1)); + request.Created = DateRange.GreaterThan(new DateTimeOffset(new DateTime(2011, 1, 1), TimeSpan.Zero)); client.SearchRepo(request); connection.Received().Get(Arg.Is(u => u.ToString() == "search/repositories"), - Arg.Is>(d => d["q"] == "github+created:>2011-01-01")); + Arg.Is>(d => d["q"] == "github+created:>2011-01-01T00:00:00+00:00")); } [Fact] @@ -538,10 +542,10 @@ public void TestingTheCreatedQualifier_GreaterThanOrEquals() var client = new SearchClient(connection); //get repos where the search contains 'github' and has been created after year jan 1 2011 var request = new SearchRepositoriesRequest("github"); - request.Created = DateRange.GreaterThanOrEquals(new DateTime(2011, 1, 1)); + request.Created = DateRange.GreaterThanOrEquals(new DateTimeOffset(new DateTime(2011, 1, 1), TimeSpan.Zero)); client.SearchRepo(request); connection.Received().Get(Arg.Is(u => u.ToString() == "search/repositories"), - Arg.Is>(d => d["q"] == "github+created:>=2011-01-01")); + Arg.Is>(d => d["q"] == "github+created:>=2011-01-01T00:00:00+00:00")); } [Fact] @@ -551,10 +555,10 @@ public void TestingTheCreatedQualifier_LessThan() var client = new SearchClient(connection); //get repos where the search contains 'github' and has been created after year jan 1 2011 var request = new SearchRepositoriesRequest("github"); - request.Created = DateRange.LessThan(new DateTime(2011, 1, 1)); + request.Created = DateRange.LessThan(new DateTimeOffset(new DateTime(2011, 1, 1), TimeSpan.Zero)); client.SearchRepo(request); connection.Received().Get(Arg.Is(u => u.ToString() == "search/repositories"), - Arg.Is>(d => d["q"] == "github+created:<2011-01-01")); + Arg.Is>(d => d["q"] == "github+created:<2011-01-01T00:00:00+00:00")); } @@ -565,10 +569,10 @@ public void TestingTheCreatedQualifier_LessThanOrEquals() var client = new SearchClient(connection); //get repos where the search contains 'github' and has been created after year jan 1 2011 var request = new SearchRepositoriesRequest("github"); - request.Created = DateRange.LessThanOrEquals(new DateTime(2011, 1, 1)); + request.Created = DateRange.LessThanOrEquals(new DateTimeOffset(new DateTime(2011, 1, 1), TimeSpan.Zero)); client.SearchRepo(request); connection.Received().Get(Arg.Is(u => u.ToString() == "search/repositories"), - Arg.Is>(d => d["q"] == "github+created:<=2011-01-01")); + Arg.Is>(d => d["q"] == "github+created:<=2011-01-01T00:00:00+00:00")); } [Fact] @@ -577,10 +581,14 @@ public void TestingTheCreatedQualifier_Between() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchRepositoriesRequest("github"); - request.Created = DateRange.Between(new DateTime(2011, 1, 1), new DateTime(2012, 11, 11)); + request.Created = DateRange.Between( + new DateTimeOffset(new DateTime(2011, 1, 1), TimeSpan.Zero), + new DateTimeOffset(new DateTime(2012, 11, 11), TimeSpan.Zero)); + client.SearchRepo(request); + connection.Received().Get(Arg.Is(u => u.ToString() == "search/repositories"), - Arg.Is>(d => d["q"] == "github+created:2011-01-01..2012-11-11")); + Arg.Is>(d => d["q"] == "github+created:2011-01-01T00:00:00+00:00..2012-11-11T00:00:00+00:00")); } [Fact] @@ -590,10 +598,10 @@ public void TestingTheUpdatedQualifier() var client = new SearchClient(connection); //get repos where the search contains 'github' and has been pushed before year jan 1 2013 var request = new SearchRepositoriesRequest("github"); - request.Updated = DateRange.GreaterThan(new DateTime(2013, 1, 1)); + request.Updated = DateRange.GreaterThan(new DateTimeOffset(new DateTime(2013, 1, 1), TimeSpan.Zero)); client.SearchRepo(request); connection.Received().Get(Arg.Is(u => u.ToString() == "search/repositories"), - Arg.Is>(d => d["q"] == "github+pushed:>2013-01-01")); + Arg.Is>(d => d["q"] == "github+pushed:>2013-01-01T00:00:00+00:00")); } [Fact] @@ -603,10 +611,10 @@ public void TestingTheUpdatedQualifier_GreaterThanOrEquals() var client = new SearchClient(connection); //get repos where the search contains 'github' and has been pushed before year jan 1 2013 var request = new SearchRepositoriesRequest("github"); - request.Updated = DateRange.GreaterThanOrEquals(new DateTime(2013, 1, 1)); + request.Updated = DateRange.GreaterThanOrEquals(new DateTimeOffset(new DateTime(2013, 1, 1), TimeSpan.Zero)); client.SearchRepo(request); connection.Received().Get(Arg.Is(u => u.ToString() == "search/repositories"), - Arg.Is>(d => d["q"] == "github+pushed:>=2013-01-01")); + Arg.Is>(d => d["q"] == "github+pushed:>=2013-01-01T00:00:00+00:00")); } [Fact] @@ -616,10 +624,10 @@ public void TestingTheUpdatedQualifier_LessThan() var client = new SearchClient(connection); //get repos where the search contains 'github' and has been pushed before year jan 1 2013 var request = new SearchRepositoriesRequest("github"); - request.Updated = DateRange.LessThan(new DateTime(2013, 1, 1)); + request.Updated = DateRange.LessThan(new DateTimeOffset(new DateTime(2013, 1, 1), TimeSpan.Zero)); client.SearchRepo(request); connection.Received().Get(Arg.Is(u => u.ToString() == "search/repositories"), - Arg.Is>(d => d["q"] == "github+pushed:<2013-01-01")); + Arg.Is>(d => d["q"] == "github+pushed:<2013-01-01T00:00:00+00:00")); } [Fact] @@ -629,10 +637,10 @@ public void TestingTheUpdatedQualifier_LessThanOrEquals() var client = new SearchClient(connection); //get repos where the search contains 'github' and has been pushed before year jan 1 2013 var request = new SearchRepositoriesRequest("github"); - request.Updated = DateRange.LessThanOrEquals(new DateTime(2013, 1, 1)); + request.Updated = DateRange.LessThanOrEquals(new DateTimeOffset(new DateTime(2013, 1, 1), TimeSpan.Zero)); client.SearchRepo(request); connection.Received().Get(Arg.Is(u => u.ToString() == "search/repositories"), - Arg.Is>(d => d["q"] == "github+pushed:<=2013-01-01")); + Arg.Is>(d => d["q"] == "github+pushed:<=2013-01-01T00:00:00+00:00")); } [Fact] @@ -641,10 +649,14 @@ public void TestingTheUpdatedQualifier_Between() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchRepositoriesRequest("github"); - request.Updated = DateRange.Between(new DateTime(2012, 4, 30), new DateTime(2012, 7, 4)); + request.Updated = DateRange.Between( + new DateTimeOffset(new DateTime(2012, 4, 30), TimeSpan.Zero), + new DateTimeOffset(new DateTime(2012, 7, 4), TimeSpan.Zero)); + client.SearchRepo(request); + connection.Received().Get(Arg.Is(u => u.ToString() == "search/repositories"), - Arg.Is>(d => d["q"] == "github+pushed:2012-04-30..2012-07-04")); + Arg.Is>(d => d["q"] == "github+pushed:2012-04-30T00:00:00+00:00..2012-07-04T00:00:00+00:00")); } [Fact] @@ -950,7 +962,7 @@ public void TestingTheLabelsQualifier() connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+label:bug")); + Arg.Is>(d => d["q"] == "something+label:\"bug\"")); } [Fact] @@ -965,7 +977,7 @@ public void TestingTheLabelsQualifier_Multiple() connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+label:bug+label:feature")); + Arg.Is>(d => d["q"] == "something+label:\"bug\"+label:\"feature\"")); } [Fact] @@ -974,13 +986,13 @@ public void TestingTheLanguageQualifier() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Language = Language.CSharp; + request.Language = Language.LiterateHaskell; client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+language:CSharp")); + Arg.Is>(d => d["q"] == "something+language:\"Literate Haskell\"")); } [Fact] @@ -989,13 +1001,13 @@ public void TestingTheCreatedQualifier_GreaterThan() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Created = DateRange.GreaterThan(new DateTime(2014, 1, 1)); + request.Created = DateRange.GreaterThan(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+created:>2014-01-01")); + Arg.Is>(d => d["q"] == "something+created:>2014-01-01T00:00:00+00:00")); } [Fact] @@ -1004,13 +1016,13 @@ public void TestingTheCreatedQualifier_GreaterThanOrEquals() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Created = DateRange.GreaterThanOrEquals(new DateTime(2014, 1, 1)); + request.Created = DateRange.GreaterThanOrEquals(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+created:>=2014-01-01")); + Arg.Is>(d => d["q"] == "something+created:>=2014-01-01T00:00:00+00:00")); } [Fact] @@ -1019,13 +1031,13 @@ public void TestingTheCreatedQualifier_LessThan() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Created = DateRange.LessThan(new DateTime(2014, 1, 1)); + request.Created = DateRange.LessThan(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+created:<2014-01-01")); + Arg.Is>(d => d["q"] == "something+created:<2014-01-01T00:00:00+00:00")); } [Fact] @@ -1034,13 +1046,13 @@ public void TestingTheCreatedQualifier_LessThanOrEquals() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Created = DateRange.LessThanOrEquals(new DateTime(2014, 1, 1)); + request.Created = DateRange.LessThanOrEquals(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+created:<=2014-01-01")); + Arg.Is>(d => d["q"] == "something+created:<=2014-01-01T00:00:00+00:00")); } [Fact] @@ -1049,13 +1061,15 @@ public void TestingTheCreatedQualifier_Between() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Created = DateRange.Between(new DateTime(2014, 1, 1), new DateTime(2014, 2, 2)); + request.Created = DateRange.Between( + new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero), + new DateTimeOffset(new DateTime(2014, 2, 2), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+created:2014-01-01..2014-02-02")); + Arg.Is>(d => d["q"] == "something+created:2014-01-01T00:00:00+00:00..2014-02-02T00:00:00+00:00")); } [Fact] @@ -1064,13 +1078,13 @@ public void TestingTheMergedQualifier_GreaterThan() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Merged = DateRange.GreaterThan(new DateTime(2014, 1, 1)); + request.Merged = DateRange.GreaterThan(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+merged:>2014-01-01")); + Arg.Is>(d => d["q"] == "something+merged:>2014-01-01T00:00:00+00:00")); } [Fact] @@ -1079,13 +1093,13 @@ public void TestingTheMergedQualifier_GreaterThanOrEquals() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Merged = DateRange.GreaterThanOrEquals(new DateTime(2014, 1, 1)); + request.Merged = DateRange.GreaterThanOrEquals(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+merged:>=2014-01-01")); + Arg.Is>(d => d["q"] == "something+merged:>=2014-01-01T00:00:00+00:00")); } [Fact] @@ -1094,13 +1108,13 @@ public void TestingTheMergedQualifier_LessThan() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Merged = DateRange.LessThan(new DateTime(2014, 1, 1)); + request.Merged = DateRange.LessThan(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+merged:<2014-01-01")); + Arg.Is>(d => d["q"] == "something+merged:<2014-01-01T00:00:00+00:00")); } [Fact] @@ -1109,13 +1123,13 @@ public void TestingTheMergedQualifier_LessThanOrEquals() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Merged = DateRange.LessThanOrEquals(new DateTime(2014, 1, 1)); + request.Merged = DateRange.LessThanOrEquals(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+merged:<=2014-01-01")); + Arg.Is>(d => d["q"] == "something+merged:<=2014-01-01T00:00:00+00:00")); } [Fact] @@ -1124,13 +1138,15 @@ public void TestingTheMergedQualifier_Between() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Merged = DateRange.Between(new DateTime(2014, 1, 1), new DateTime(2014, 2, 2)); + request.Merged = DateRange.Between( + new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero), + new DateTimeOffset(new DateTime(2014, 2, 2), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+merged:2014-01-01..2014-02-02")); + Arg.Is>(d => d["q"] == "something+merged:2014-01-01T00:00:00+00:00..2014-02-02T00:00:00+00:00")); } [Fact] @@ -1139,13 +1155,13 @@ public void TestingTheUpdatedQualifier_GreaterThan() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Updated = DateRange.GreaterThan(new DateTime(2014, 1, 1)); + request.Updated = DateRange.GreaterThan(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+updated:>2014-01-01")); + Arg.Is>(d => d["q"] == "something+updated:>2014-01-01T00:00:00+00:00")); } [Fact] @@ -1154,13 +1170,13 @@ public void TestingTheUpdatedQualifier_GreaterThanOrEquals() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Updated = DateRange.GreaterThanOrEquals(new DateTime(2014, 1, 1)); + request.Updated = DateRange.GreaterThanOrEquals(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+updated:>=2014-01-01")); + Arg.Is>(d => d["q"] == "something+updated:>=2014-01-01T00:00:00+00:00")); } [Fact] @@ -1169,13 +1185,13 @@ public void TestingTheUpdatedQualifier_LessThan() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Updated = DateRange.LessThan(new DateTime(2014, 1, 1)); + request.Updated = DateRange.LessThan(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+updated:<2014-01-01")); + Arg.Is>(d => d["q"] == "something+updated:<2014-01-01T00:00:00+00:00")); } [Fact] @@ -1184,13 +1200,226 @@ public void TestingTheUpdatedQualifier_LessThanOrEquals() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchIssuesRequest("something"); - request.Updated = DateRange.LessThanOrEquals(new DateTime(2014, 1, 1)); + request.Updated = DateRange.LessThanOrEquals(new DateTimeOffset(new DateTime(2014, 1, 1), TimeSpan.Zero)); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+updated:<=2014-01-01T00:00:00+00:00")); + } + + [Fact] + public void TestingTheCreatedQualifier_GreaterThanDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Created = DateRange.GreaterThan(new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+created:>2014-01-01T02:04:06+10:00")); + } + + [Fact] + public void TestingTheCreatedQualifier_GreaterThanOrEqualsDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Created = DateRange.GreaterThanOrEquals(new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+created:>=2014-01-01T02:04:06+10:00")); + } + [Fact] + public void TestingTheCreatedQualifier_LessThanDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Created = DateRange.LessThan(new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0))); client.SearchIssues(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), - Arg.Is>(d => d["q"] == "something+updated:<=2014-01-01")); + Arg.Is>(d => d["q"] == "something+created:<2014-01-01T02:04:06+10:00")); + } + + [Fact] + public void TestingTheCreatedQualifier_LessThanOrEqualsDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Created = DateRange.LessThanOrEquals(new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+created:<=2014-01-01T02:04:06+10:00")); + } + + [Fact] + public void TestingTheCreatedQualifier_BetweenDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Created = DateRange.Between( + new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0)), + new DateTimeOffset(2014, 2, 2, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+created:2014-01-01T02:04:06+10:00..2014-02-02T02:04:06+10:00")); + } + + [Fact] + public void TestingTheMergedQualifier_GreaterThanDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Merged = DateRange.GreaterThan(new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+merged:>2014-01-01T02:04:06+10:00")); + } + + [Fact] + public void TestingTheMergedQualifier_GreaterThanOrEqualsDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Merged = DateRange.GreaterThanOrEquals(new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+merged:>=2014-01-01T02:04:06+10:00")); + } + + [Fact] + public void TestingTheMergedQualifier_LessThanDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Merged = DateRange.LessThan(new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+merged:<2014-01-01T02:04:06+10:00")); + } + + [Fact] + public void TestingTheMergedQualifier_LessThanOrEqualsDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Merged = DateRange.LessThanOrEquals(new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+merged:<=2014-01-01T02:04:06+10:00")); + } + + [Fact] + public void TestingTheMergedQualifier_BetweenDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Merged = DateRange.Between( + new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0)), + new DateTimeOffset(2014, 2, 2, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+merged:2014-01-01T02:04:06+10:00..2014-02-02T02:04:06+10:00")); + } + + [Fact] + public void TestingTheUpdatedQualifier_GreaterThanDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Updated = DateRange.GreaterThan(new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+updated:>2014-01-01T02:04:06+10:00")); + } + + [Fact] + public void TestingTheUpdatedQualifier_GreaterThanOrEqualsDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Updated = DateRange.GreaterThanOrEquals(new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+updated:>=2014-01-01T02:04:06+10:00")); + } + + [Fact] + public void TestingTheUpdatedQualifier_LessThanDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Updated = DateRange.LessThan(new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+updated:<2014-01-01T02:04:06+10:00")); + } + + [Fact] + public void TestingTheUpdatedQualifier_LessThanOrEqualsDateTime() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchIssuesRequest("something"); + request.Updated = DateRange.LessThanOrEquals(new DateTimeOffset(2014, 1, 1, 2, 4, 6, new TimeSpan(10, 0, 0))); + + client.SearchIssues(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/issues"), + Arg.Is>(d => d["q"] == "something+updated:<=2014-01-01T02:04:06+10:00")); } [Fact] @@ -1331,7 +1560,7 @@ public void TestingTheRepoAndUserAndLabelQualifier() connection.Received().Get( Arg.Is(u => u.ToString() == "search/issues"), Arg.Is>(d => d["q"] == - "something+label:bug+user:alfhenrik+repo:octokit/octokit.net")); + "something+label:\"bug\"+user:alfhenrik+repo:octokit/octokit.net")); } } @@ -1453,13 +1682,13 @@ public void TestingTheLanguageQualifier() var connection = Substitute.For(); var client = new SearchClient(connection); var request = new SearchCodeRequest("something"); - request.Language = Language.CSharp; + request.Language = Language.LiterateHaskell; client.SearchCode(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/code"), - Arg.Is>(d => d["q"] == "something+language:CSharp")); + Arg.Is>(d => d["q"] == "something+language:\"Literate Haskell\"")); } [Fact] @@ -1572,14 +1801,33 @@ public void TestingTheExtensionQualifier() { var connection = Substitute.For(); var client = new SearchClient(connection); - var request = new SearchCodeRequest("something"); - request.Extension = "cs"; + var request = new SearchCodeRequest("something") + { + Extensions = new[] { "txt" } + }; client.SearchCode(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/code"), - Arg.Is>(d => d["q"] == "something+extension:cs")); + Arg.Is>(d => d["q"] == "something+extension:txt")); + } + + [Fact] + public void TestingTheExtensionQualifier_Multiple() + { + var connection = Substitute.For(); + var client = new SearchClient(connection); + var request = new SearchCodeRequest("something") + { + Extensions = new[] { "cs", "lol" } + }; + + client.SearchCode(request); + + connection.Received().Get( + Arg.Is(u => u.ToString() == "search/code"), + Arg.Is>(d => d["q"] == "something+extension:cs+extension:lol")); } [Fact] @@ -1646,16 +1894,18 @@ public void TestingTheRepoAndPathAndExtensionQualifiers() { var connection = Substitute.For(); var client = new SearchClient(connection); - var request = new SearchCodeRequest("something", "octokit", "octokit.net"); + var request = new SearchCodeRequest("something", "octokit", "octokit.net") + { + Extensions = new[] { "fs", "cs" } + }; request.Path = "tools/FAKE.core"; - request.Extension = "fs"; client.SearchCode(request); connection.Received().Get( Arg.Is(u => u.ToString() == "search/code"), Arg.Is>(d => - d["q"] == "something+path:tools/FAKE.core+extension:fs+repo:octokit/octokit.net")); + d["q"] == "something+path:tools/FAKE.core+extension:fs+extension:cs+repo:octokit/octokit.net")); } [Fact] @@ -1782,4 +2032,4 @@ public void TestingTheRepositoryIdParameter() } } } -} +} \ No newline at end of file diff --git a/Octokit.Tests/Helpers/StringExtensionsTests.cs b/Octokit.Tests/Helpers/StringExtensionsTests.cs index c90d94685e..f342199ef9 100644 --- a/Octokit.Tests/Helpers/StringExtensionsTests.cs +++ b/Octokit.Tests/Helpers/StringExtensionsTests.cs @@ -70,7 +70,7 @@ public class EscapeDoubleQuotesMethod [Fact] public void EscapeDoubleQuotesReturnsNullForNullInput() { - Assert.Equal(null, (null as string).EscapeDoubleQuotes()); + Assert.Null((null as string).EscapeDoubleQuotes()); } [Fact] diff --git a/Octokit.Tests/Http/ApiConnectionTests.cs b/Octokit.Tests/Http/ApiConnectionTests.cs index 5f3b7d2271..b74011c066 100644 --- a/Octokit.Tests/Http/ApiConnectionTests.cs +++ b/Octokit.Tests/Http/ApiConnectionTests.cs @@ -342,7 +342,7 @@ public async Task WhenGetReturnsOkThenBodyAsObjectIsReturned() .Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); - var actualResult = await apiConnection.GetQueuedOperation(queuedOperationUrl, Args.CancellationToken); + var actualResult = await apiConnection.GetQueuedOperation(queuedOperationUrl, CancellationToken.None); Assert.Same(actualResult, result); } @@ -361,7 +361,7 @@ public async Task WhenGetReturnsNoContentThenReturnsEmptyCollection() .Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); - var actualResult = await apiConnection.GetQueuedOperation(queuedOperationUrl, Args.CancellationToken); + var actualResult = await apiConnection.GetQueuedOperation(queuedOperationUrl, CancellationToken.None); Assert.Empty(actualResult); } @@ -388,6 +388,7 @@ public async Task GetIsRepeatedUntilHttpStatusCodeOkIsReturned() connection.Received(3).GetResponse>(queuedOperationUrl, Args.CancellationToken); } + [Fact(Skip = "Test triggers deadlock when run, needs to be investigated")] public async Task CanCancelQueuedOperation() { var queuedOperationUrl = new Uri("anything", UriKind.Relative); diff --git a/Octokit.Tests/Http/ApiInfoParserTests.cs b/Octokit.Tests/Http/ApiInfoParserTests.cs index 5fbb3bf145..00e3215b4e 100644 --- a/Octokit.Tests/Http/ApiInfoParserTests.cs +++ b/Octokit.Tests/Http/ApiInfoParserTests.cs @@ -86,7 +86,7 @@ public void ParsesLinkHeader() public class ThePageUrlMethods { [Theory] - [MemberData("PagingMethods")] + [MemberData(nameof(PagingMethods))] public void RetrievesTheCorrectPagePage(string linkName, Func pagingMethod) { var pageUri = new Uri("https://api.github.com/user/repos?page=2"); @@ -100,8 +100,10 @@ public void RetrievesTheCorrectPagePage(string linkName, Func pagi } [Theory] - [MemberData("PagingMethods")] + [MemberData(nameof(PagingMethods))] +#pragma warning disable xUnit1026 // Theory methods should use all of their parameters public void ReturnsNullIfThereIsNoMatchingPagingLink(string ignored, Func pagingMethod) +#pragma warning restore xUnit1026 // Theory methods should use all of their parameters { var links = new Dictionary(); var info = BuildApiInfo(links); diff --git a/Octokit.Tests/Http/ApiInfoTests.cs b/Octokit.Tests/Http/ApiInfoTests.cs index 97bbe314e0..21fedeba91 100644 --- a/Octokit.Tests/Http/ApiInfoTests.cs +++ b/Octokit.Tests/Http/ApiInfoTests.cs @@ -86,13 +86,9 @@ public void CanClone() Assert.NotSame(original.RateLimit, clone.RateLimit); Assert.Equal(original.RateLimit.Limit, clone.RateLimit.Limit); - Assert.NotSame(original.RateLimit.Limit, clone.RateLimit.Limit); Assert.Equal(original.RateLimit.Remaining, clone.RateLimit.Remaining); - Assert.NotSame(original.RateLimit.Remaining, clone.RateLimit.Remaining); Assert.Equal(original.RateLimit.ResetAsUtcEpochSeconds, clone.RateLimit.ResetAsUtcEpochSeconds); - Assert.NotSame(original.RateLimit.ResetAsUtcEpochSeconds, clone.RateLimit.ResetAsUtcEpochSeconds); Assert.Equal(original.RateLimit.Reset, clone.RateLimit.Reset); - Assert.NotSame(original.RateLimit.Reset, clone.RateLimit.Reset); } [Fact] diff --git a/Octokit.Tests/Http/ConnectionTests.cs b/Octokit.Tests/Http/ConnectionTests.cs index f6c0618ef2..2f1edef9dd 100644 --- a/Octokit.Tests/Http/ConnectionTests.cs +++ b/Octokit.Tests/Http/ConnectionTests.cs @@ -753,7 +753,7 @@ public void CreatesConnectionWithBaseAddress() var connection = new Connection(new ProductHeaderValue("OctokitTests"), new Uri("https://github.com/")); Assert.Equal(new Uri("https://github.com/"), connection.BaseAddress); - Assert.True(connection.UserAgent.StartsWith("OctokitTests (")); + Assert.StartsWith("OctokitTests (", connection.UserAgent); } } diff --git a/Octokit.Tests/Http/JsonHttpPipelineTests.cs b/Octokit.Tests/Http/JsonHttpPipelineTests.cs index 704665a487..874cb4e312 100644 --- a/Octokit.Tests/Http/JsonHttpPipelineTests.cs +++ b/Octokit.Tests/Http/JsonHttpPipelineTests.cs @@ -149,7 +149,7 @@ public void DeserializesSingleObjectResponseIntoCollectionWithOneItem() var response = jsonPipeline.DeserializeResponse>(httpResponse); - Assert.Equal(1, response.Body.Count); + Assert.Single(response.Body); Assert.Equal("Haack", response.Body.First().Name); } diff --git a/Octokit.Tests/Http/RateLimitTests.cs b/Octokit.Tests/Http/RateLimitTests.cs index c538f1ea45..2012ec29ec 100644 --- a/Octokit.Tests/Http/RateLimitTests.cs +++ b/Octokit.Tests/Http/RateLimitTests.cs @@ -117,17 +117,13 @@ public void CanClone() var clone = original.Clone(); - // Note the use of Assert.NotSame tests for value types - this should continue to test should the underlying - // model are changed to Object types + // We want to ensure the original and clone are different objects but with + // the same values populated Assert.NotSame(original, clone); Assert.Equal(original.Limit, clone.Limit); - Assert.NotSame(original.Limit, clone.Limit); Assert.Equal(original.Remaining, clone.Remaining); - Assert.NotSame(original.Remaining, clone.Remaining); Assert.Equal(original.ResetAsUtcEpochSeconds, clone.ResetAsUtcEpochSeconds); - Assert.NotSame(original.ResetAsUtcEpochSeconds, clone.ResetAsUtcEpochSeconds); Assert.Equal(original.Reset, clone.Reset); - Assert.NotSame(original.Reset, clone.Reset); } } } diff --git a/Octokit.Tests/Http/RedirectHandlerTests.cs b/Octokit.Tests/Http/RedirectHandlerTests.cs index 87d271df65..fca1a901f8 100644 --- a/Octokit.Tests/Http/RedirectHandlerTests.cs +++ b/Octokit.Tests/Http/RedirectHandlerTests.cs @@ -21,8 +21,8 @@ public async Task OkStatusShouldPassThrough() var response = await adapter.SendAsync(httpRequestMessage, new CancellationToken()); - Assert.Equal(response.StatusCode, HttpStatusCode.OK); - Assert.Same(response.RequestMessage, httpRequestMessage); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Same(httpRequestMessage, response.RequestMessage); } [Theory] diff --git a/Octokit.Tests/Models/MigrationTests.cs b/Octokit.Tests/Models/MigrationTests.cs index 128606dc13..c4765a3585 100644 --- a/Octokit.Tests/Models/MigrationTests.cs +++ b/Octokit.Tests/Models/MigrationTests.cs @@ -152,7 +152,7 @@ public void CanBeDeserialized() Assert.Equal("octocat/Hello-World", _migrationReuqest.Repositories[0]); Assert.Equal(1, _migrationReuqest.Repositories.Count); - Assert.Equal(true, _migrationReuqest.LockRepositories); + Assert.True(_migrationReuqest.LockRepositories); } } } diff --git a/Octokit.Tests/Models/NewReferenceTests.cs b/Octokit.Tests/Models/NewReferenceTests.cs index 48cc90cacf..7f56d45d3f 100644 --- a/Octokit.Tests/Models/NewReferenceTests.cs +++ b/Octokit.Tests/Models/NewReferenceTests.cs @@ -11,7 +11,7 @@ public void EnforcesRefsPrefix() { var create = new NewReference("heads/develop", "sha"); - Assert.Equal(create.Ref, "refs/heads/develop"); + Assert.Equal("refs/heads/develop", create.Ref); } [Fact] diff --git a/Octokit.Tests/Models/NewRepositoryWebHookTests.cs b/Octokit.Tests/Models/NewRepositoryWebHookTests.cs index 287e8aa4de..4633278350 100644 --- a/Octokit.Tests/Models/NewRepositoryWebHookTests.cs +++ b/Octokit.Tests/Models/NewRepositoryWebHookTests.cs @@ -11,23 +11,23 @@ public class TheCtor public void UsesDefaultValuesForDefaultConfig() { var create = new NewRepositoryWebHook("windowsazure", new Dictionary(), "http://test.com/example"); - Assert.Equal(create.Url, "http://test.com/example"); - Assert.Equal(create.ContentType, WebHookContentType.Form); + Assert.Equal("http://test.com/example", create.Url); + Assert.Equal(WebHookContentType.Form, create.ContentType); Assert.Empty(create.Secret); Assert.False(create.InsecureSsl); var request = create.ToRequest(); - Assert.Equal(request.Config.Count, 4); + Assert.Equal(4, request.Config.Count); Assert.True(request.Config.ContainsKey("url")); Assert.True(request.Config.ContainsKey("content_type")); Assert.True(request.Config.ContainsKey("secret")); Assert.True(request.Config.ContainsKey("insecure_ssl")); - Assert.Equal(request.Config["url"], "http://test.com/example"); + Assert.Equal("http://test.com/example", request.Config["url"]); Assert.Equal(request.Config["content_type"], WebHookContentType.Form.ToParameter()); - Assert.Equal(request.Config["secret"], ""); - Assert.Equal(request.Config["insecure_ssl"], "False"); + Assert.Equal("", request.Config["secret"]); + Assert.Equal("False", request.Config["insecure_ssl"]); } [Fact] @@ -47,23 +47,23 @@ public void CombinesUserSpecifiedContentTypeWithConfig() InsecureSsl = true }; - Assert.Equal(create.Url, "http://test.com/example"); - Assert.Equal(create.ContentType, WebHookContentType.Json); + Assert.Equal("http://test.com/example", create.Url); + Assert.Equal(WebHookContentType.Json, create.ContentType); Assert.Empty(create.Secret); Assert.True(create.InsecureSsl); var request = create.ToRequest(); - Assert.Equal(request.Config.Count, 7); + Assert.Equal(7, request.Config.Count); Assert.True(request.Config.ContainsKey("url")); Assert.True(request.Config.ContainsKey("content_type")); Assert.True(request.Config.ContainsKey("secret")); Assert.True(request.Config.ContainsKey("insecure_ssl")); - Assert.Equal(request.Config["url"], "http://test.com/example"); + Assert.Equal("http://test.com/example", request.Config["url"]); Assert.Equal(request.Config["content_type"], WebHookContentType.Json.ToParameter()); - Assert.Equal(request.Config["secret"], ""); + Assert.Equal("", request.Config["secret"]); Assert.Equal(request.Config["insecure_ssl"], true.ToString()); Assert.True(request.Config.ContainsKey("hostname")); @@ -130,8 +130,8 @@ public void ShouldNotContainDuplicateConfigEntriesOnSubsequentRequests() var request = create.ToRequest(); var requestRepeated = create.ToRequest(); - Assert.Equal(request.Config.Count, 4); - Assert.Equal(requestRepeated.Config.Count, 4); + Assert.Equal(4, request.Config.Count); + Assert.Equal(4, requestRepeated.Config.Count); } [Fact] @@ -151,8 +151,8 @@ public void ShouldNotContainDuplicateConfigEntriesOnSubsequentRequestsWithCustom var requestRepeated = create.ToRequest(); //This is not 8, because `url` used in config, is already part of the base config - Assert.Equal(request.Config.Count, 7); - Assert.Equal(requestRepeated.Config.Count, 7); + Assert.Equal(7, request.Config.Count); + Assert.Equal(7, requestRepeated.Config.Count); } [Fact] @@ -167,10 +167,10 @@ public void PropertiesShouldTakePrecedenceOverConfigPassedIn() var request = create.ToRequest(); - Assert.Equal(request.Config["url"], "http://test.com/example"); + Assert.Equal("http://test.com/example", request.Config["url"]); var subsequentRequest = create.ToRequest(); - Assert.Equal(subsequentRequest.Config["url"], "http://test.com/example"); + Assert.Equal("http://test.com/example", subsequentRequest.Config["url"]); } } } diff --git a/Octokit.Tests/Models/SearchIssuesRequestExclusionsTests.cs b/Octokit.Tests/Models/SearchIssuesRequestExclusionsTests.cs index 2b31db6fd2..fdbaab560f 100644 --- a/Octokit.Tests/Models/SearchIssuesRequestExclusionsTests.cs +++ b/Octokit.Tests/Models/SearchIssuesRequestExclusionsTests.cs @@ -28,7 +28,7 @@ public void HandlesStringAttributesCorrectly() var request = new SearchIssuesRequestExclusions(); // Ensure the specified parameter does not exist when not set - Assert.False(request.MergedQualifiers().Any(x => x.Contains(property.Key))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains(property.Key)); // Set the parameter property.Value(request, "blah"); @@ -42,61 +42,61 @@ public void HandlesStringAttributesCorrectly() public void HandlesStateAttributeCorrectly() { var request = new SearchIssuesRequestExclusions(); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("-state:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("-state:")); request.State = ItemState.Closed; - Assert.True(request.MergedQualifiers().Contains("-state:closed")); + Assert.Contains("-state:closed", request.MergedQualifiers()); } [Fact] public void HandlesExcludeLabelsAttributeCorrectly() { var request = new SearchIssuesRequestExclusions(); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("-label:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("-label:")); request.Labels = new[] { "label1", "label2" }; - Assert.True(request.MergedQualifiers().Contains("-label:label1")); - Assert.True(request.MergedQualifiers().Contains("-label:label2")); + Assert.Contains("-label:label1", request.MergedQualifiers()); + Assert.Contains("-label:label2", request.MergedQualifiers()); } [Fact] public void HandlesLanguageAttributeCorrectly() { var request = new SearchIssuesRequestExclusions(); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("-language:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("-language:")); request.Language = Language.CSharp; - Assert.True(request.MergedQualifiers().Contains("-language:CSharp")); + Assert.Contains("-language:\"CSharp\"", request.MergedQualifiers()); } [Fact] public void HandlesStatusAttributeCorrectly() { var request = new SearchIssuesRequestExclusions(); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("-status:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("-status:")); request.Status = CommitState.Error; - Assert.True(request.MergedQualifiers().Contains("-status:error")); + Assert.Contains("-status:error", request.MergedQualifiers()); } [Fact] public void HandlesMilestoneAttributeWithoutQuotes() { var request = new SearchIssuesRequestExclusions(); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("-milestone:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("-milestone:")); request.Milestone = "testMilestone"; - Assert.True(request.MergedQualifiers().Contains("-milestone:\"testMilestone\"")); + Assert.Contains("-milestone:\"testMilestone\"", request.MergedQualifiers()); } [Fact] public void DoesntWrapMilestoneWithDoubleQuotesForQuotedMilestone() { var request = new SearchIssuesRequestExclusions(); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("-milestone:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("-milestone:")); request.Milestone = "\"testMilestone\""; Assert.Contains("-milestone:\"\\\"testMilestone\\\"\"", request.MergedQualifiers()); diff --git a/Octokit.Tests/Models/SearchIssuesRequestTests.cs b/Octokit.Tests/Models/SearchIssuesRequestTests.cs index 13bcbb3201..9227e7a8e0 100644 --- a/Octokit.Tests/Models/SearchIssuesRequestTests.cs +++ b/Octokit.Tests/Models/SearchIssuesRequestTests.cs @@ -4,6 +4,8 @@ using Octokit; using Octokit.Tests.Helpers; using Xunit; +// hack because Travis on LInux is somehow upgraded to a version of .NET (Core?) that also has System.Range +using Range = Octokit.Range; public class SearchIssuesRequestTests { @@ -50,7 +52,7 @@ public void HandlesStringAttributesCorrectly() var request = new SearchIssuesRequest("query"); // Ensure the specified parameter does not exist when not set - Assert.False(request.MergedQualifiers().Any(x => x.Contains(property.Key))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains(property.Key)); // Set the parameter property.Value(request, "blah"); @@ -76,10 +78,10 @@ public void HandlesDateRangeAttributesCorrectly() var request = new SearchIssuesRequest("query"); // Ensure the specified parameter does not exist when not set - Assert.False(request.MergedQualifiers().Any(x => x.Contains(property.Key))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains(property.Key)); // Set the parameter - property.Value(request, DateRange.GreaterThan(DateTime.Today.AddDays(-7))); + property.Value(request, DateRange.GreaterThan(new DateTimeOffset(DateTime.Today.AddDays(-7)))); // Ensure the specified parameter now exists Assert.True(request.MergedQualifiers().Count(x => x.Contains(property.Key)) == 1); @@ -90,48 +92,48 @@ public void HandlesDateRangeAttributesCorrectly() public void HandlesInAttributeCorrectly() { var request = new SearchIssuesRequest("test"); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("in:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("in:")); request.In = new List { IssueInQualifier.Body, IssueInQualifier.Comment }; - Assert.True(request.MergedQualifiers().Contains("in:body,comment")); + Assert.Contains("in:body,comment", request.MergedQualifiers()); } [Fact] public void HandlesStateAttributeCorrectly() { var request = new SearchIssuesRequest("test"); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("state:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("state:")); request.State = ItemState.Closed; - Assert.True(request.MergedQualifiers().Contains("state:closed")); + Assert.Contains("state:closed", request.MergedQualifiers()); } [Fact] public void HandlesLabelsAttributeCorrectly() { var request = new SearchIssuesRequest("test"); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("label:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("label:")); - request.Labels = new[] { "label1", "label2" }; - Assert.True(request.MergedQualifiers().Contains("label:label1")); - Assert.True(request.MergedQualifiers().Contains("label:label2")); + request.Labels = new[] { "label1", "label 2" }; + Assert.Contains("label:\"label1\"", request.MergedQualifiers()); + Assert.Contains("label:\"label 2\"", request.MergedQualifiers()); } [Fact] public void HandlesMilestoneAttributeWithoutQuotes() { var request = new SearchIssuesRequest("text"); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("milestone:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("milestone:")); request.Milestone = "testMilestone"; - Assert.True(request.MergedQualifiers().Contains("milestone:\"testMilestone\"")); + Assert.Contains("milestone:\"testMilestone\"", request.MergedQualifiers()); } [Fact] public void DoesntWrapMilestoneWithDoubleQuotesForQuotedMilestone() { var request = new SearchIssuesRequest("text"); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("milestone:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("milestone:")); request.Milestone = "\"testMilestone\""; Assert.Contains("milestone:\"\\\"testMilestone\\\"\"", request.MergedQualifiers()); @@ -141,63 +143,63 @@ public void DoesntWrapMilestoneWithDoubleQuotesForQuotedMilestone() public void HandlesNoMetadataAttributeCorrectly() { var request = new SearchIssuesRequest("test"); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("no:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("no:")); request.No = IssueNoMetadataQualifier.Milestone; - Assert.True(request.MergedQualifiers().Contains("no:milestone")); + Assert.Contains("no:milestone", request.MergedQualifiers()); } [Fact] public void HandlesLanguageAttributeCorrectly() { var request = new SearchIssuesRequest("test"); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("language:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("language:")); request.Language = Language.CSharp; - Assert.True(request.MergedQualifiers().Contains("language:CSharp")); + Assert.Contains("language:\"CSharp\"", request.MergedQualifiers()); } [Fact] public void HandlesIsAttributeCorrectly() { var request = new SearchIssuesRequest("test"); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("is:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("is:")); request.Is = new List { IssueIsQualifier.Merged, IssueIsQualifier.PullRequest }; - Assert.True(request.MergedQualifiers().Contains("is:merged")); - Assert.True(request.MergedQualifiers().Contains("is:pr")); + Assert.Contains("is:merged", request.MergedQualifiers()); + Assert.Contains("is:pr", request.MergedQualifiers()); } [Fact] public void HandlesStatusAttributeCorrectly() { var request = new SearchIssuesRequest("test"); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("status:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("status:")); request.Status = CommitState.Error; - Assert.True(request.MergedQualifiers().Contains("status:error")); + Assert.Contains("status:error", request.MergedQualifiers()); } [Fact] public void HandlesCommentsAttributeCorrectly() { var request = new SearchIssuesRequest("test"); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("comments:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("comments:")); request.Comments = Range.GreaterThan(5); - Assert.True(request.MergedQualifiers().Contains("comments:>5")); + Assert.Contains("comments:>5", request.MergedQualifiers()); } [Fact] public void HandlesRepoAttributeCorrectly() { var request = new SearchIssuesRequest("test"); - Assert.False(request.MergedQualifiers().Any(x => x.Contains("repo:"))); + Assert.DoesNotContain(request.MergedQualifiers(), x => x.Contains("repo:")); request.Repos.Add("myorg", "repo1"); request.Repos.Add("myorg", "repo2"); - Assert.True(request.MergedQualifiers().Contains("repo:myorg/repo1")); - Assert.True(request.MergedQualifiers().Contains("repo:myorg/repo2")); + Assert.Contains("repo:myorg/repo1", request.MergedQualifiers()); + Assert.Contains("repo:myorg/repo2", request.MergedQualifiers()); } } } \ No newline at end of file diff --git a/Octokit.Tests/Models/SearchRepositoryRequestTests.cs b/Octokit.Tests/Models/SearchRepositoryRequestTests.cs index e49d9d151b..ebeda46282 100644 --- a/Octokit.Tests/Models/SearchRepositoryRequestTests.cs +++ b/Octokit.Tests/Models/SearchRepositoryRequestTests.cs @@ -25,5 +25,13 @@ public void SortNotSpecifiedByDefault() Assert.True(string.IsNullOrWhiteSpace(request.Sort)); Assert.False(request.Parameters.ContainsKey("sort")); } + + [Fact] + public void LanguageUsesParameterTranslation() + { + var request = new SearchRepositoriesRequest() { Language = Language.CPlusPlus }; + var result = request.MergedQualifiers(); + Assert.Contains(result, x => string.Equals(x, "language:\"cpp\"")); + } } } diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj index d53e8befbe..f5dcb2c732 100644 --- a/Octokit.Tests/Octokit.Tests.csproj +++ b/Octokit.Tests/Octokit.Tests.csproj @@ -4,7 +4,7 @@ Tests for Octokit Octokit.Tests GitHub - netcoreapp2.0;net452 + netcoreapp3.1;net452 $(NoWarn);CS4014;CS1998 Octokit.Tests Octokit.Tests @@ -29,22 +29,23 @@ - + - + $(DefineConstants);NO_SERIALIZABLE;HAS_TYPEINFO - - - + + + + diff --git a/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseManagementConsoleClientTests.cs b/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseManagementConsoleClientTests.cs new file mode 100644 index 0000000000..c02bdeb017 --- /dev/null +++ b/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseManagementConsoleClientTests.cs @@ -0,0 +1,92 @@ +using System; +using NSubstitute; +using Octokit.Reactive; +using Xunit; + +namespace Octokit.Tests +{ + public class ObservableEnterpriseManagementConsoleClientTests + { + public class TheGetMaintenanceModeMethod + { + [Fact] + public void CallsIntoClient() + { + var github = Substitute.For(); + var client = new ObservableEnterpriseManagementConsoleClient(github); + + client.GetMaintenanceMode("Password01"); + + github.Enterprise.ManagementConsole.Received(1). + GetMaintenanceMode(Arg.Is("Password01")); + } + + [Fact] + public void EnsuresNonNullArguments() + { + var github = Substitute.For(); + var client = new ObservableEnterpriseManagementConsoleClient(github); + + Assert.Throws(() => client.GetMaintenanceMode(null)); + } + + [Fact] + public void EnsuresNonEmptyArguments() + { + var github = Substitute.For(); + var client = new ObservableEnterpriseManagementConsoleClient(github); + + Assert.Throws(() => client.GetMaintenanceMode("")); + } + } + + public class TheEditMaintenanceModeMethod + { + [Fact] + public void CallsIntoClient() + { + var github = Substitute.For(); + var client = new ObservableEnterpriseManagementConsoleClient(github); + + client.EditMaintenanceMode( + new UpdateMaintenanceRequest(new UpdateMaintenanceRequestDetails(true)), + "Password01"); + + github.Enterprise.ManagementConsole.Received(1). + EditMaintenanceMode( + Arg.Is(a => + a.Maintenance.Enabled == true && + a.Maintenance.When == "now"), + Arg.Is("Password01")); + } + + [Fact] + public void EnsuresNonNullArguments() + { + var github = Substitute.For(); + var client = new ObservableEnterpriseManagementConsoleClient(github); + + Assert.Throws(() => client.EditMaintenanceMode(null, "Password01")); + Assert.Throws(() => client.EditMaintenanceMode(new UpdateMaintenanceRequest(), null)); + } + + [Fact] + public void EnsuresNonEmptyArguments() + { + var github = Substitute.For(); + var client = new ObservableEnterpriseManagementConsoleClient(github); + + Assert.Throws(() => client.EditMaintenanceMode(new UpdateMaintenanceRequest(), "")); + } + } + + public class TheCtor + { + [Fact] + public void EnsuresNonNullArguments() + { + Assert.Throws(() => new ObservableEnterpriseManagementConsoleClient(null)); + } + } + } +} diff --git a/Octokit.Tests/Reactive/ObservableCommitCommentReactionsClientTests.cs b/Octokit.Tests/Reactive/ObservableCommitCommentReactionsClientTests.cs index 021e9f24d7..903d80ffc2 100644 --- a/Octokit.Tests/Reactive/ObservableCommitCommentReactionsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableCommitCommentReactionsClientTests.cs @@ -29,6 +29,24 @@ public void RequestsCorrectUrl() gitHubClient.Received().Reaction.CommitComment.GetAll("fake", "repo", 42); } + [Fact] + public void RequestsCorrectUrlApiOptions() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCommitCommentReactionsClient(gitHubClient); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1, + PageSize = 1 + }; + + client.GetAll("fake", "repo", 42, options); + + gitHubClient.Received().Reaction.CommitComment.GetAll("fake", "repo", 42, options); + } + [Fact] public void RequestsCorrectUrlWithRepositoryId() { @@ -40,6 +58,24 @@ public void RequestsCorrectUrlWithRepositoryId() gitHubClient.Received().Reaction.CommitComment.GetAll(1, 42); } + [Fact] + public void RequestsCorrectUrlWithRepositoryIdApiOptions() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCommitCommentReactionsClient(gitHubClient); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1, + PageSize = 1 + }; + + client.GetAll(1, 42, options); + + gitHubClient.Received().Reaction.CommitComment.GetAll(1, 42, options); + } + [Fact] public void EnsuresNotNullArguments() { @@ -48,10 +84,20 @@ public void EnsuresNotNullArguments() Assert.Throws(() => client.GetAll(null, "name", 1)); Assert.Throws(() => client.GetAll("owner", null, 1)); + Assert.Throws(() => client.GetAll("owner", "name", 1, null)); Assert.Throws(() => client.GetAll("", "name", 1)); Assert.Throws(() => client.GetAll("owner", "", 1)); } + + [Fact] + public void EnsuresNotNullArgumentsWithRepositoryId() + { + var gitHubClient = Substitute.For(); + var client = new ObservableCommitCommentReactionsClient(gitHubClient); + + Assert.Throws(() => client.GetAll(1, 1, null)); + } } public class TheCreateMethod diff --git a/Octokit.Tests/Reactive/ObservableDeploymentStatusClientTests.cs b/Octokit.Tests/Reactive/ObservableDeploymentStatusClientTests.cs index 6fd20001b5..7a7402963d 100644 --- a/Octokit.Tests/Reactive/ObservableDeploymentStatusClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableDeploymentStatusClientTests.cs @@ -125,12 +125,12 @@ public class TheCreateMethod readonly IGitHubClient _githubClient = Substitute.For(); ObservableDeploymentStatusClient _client; - public void SetupWithoutNonReactiveClient() + private void SetupWithoutNonReactiveClient() { _client = new ObservableDeploymentStatusClient(_githubClient); } - public void SetupWithNonReactiveClient() + private void SetupWithNonReactiveClient() { var deploymentStatusClient = new DeploymentStatusClient(Substitute.For()); _githubClient.Repository.Deployment.Status.Returns(deploymentStatusClient); diff --git a/Octokit.Tests/Reactive/ObservableIssueCommentReactionsClientTests.cs b/Octokit.Tests/Reactive/ObservableIssueCommentReactionsClientTests.cs index 1081d3b926..be3841ec15 100644 --- a/Octokit.Tests/Reactive/ObservableIssueCommentReactionsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableIssueCommentReactionsClientTests.cs @@ -26,7 +26,25 @@ public void RequestsCorrectUrl() client.GetAll("fake", "repo", 42); - gitHubClient.Received().Reaction.IssueComment.GetAll("fake", "repo", 42); + gitHubClient.Received().Reaction.IssueComment.GetAll("fake", "repo", 42, Args.ApiOptions); + } + + [Fact] + public void RequestsCorrectUrlApiOptions() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentReactionsClient(gitHubClient); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1, + PageSize = 1 + }; + + client.GetAll("fake", "repo", 42, options); + + gitHubClient.Received().Reaction.IssueComment.GetAll("fake", "repo", 42, options); } [Fact] @@ -37,7 +55,25 @@ public void RequestsCorrectUrlWithRepositoryId() client.GetAll(1, 42); - gitHubClient.Received().Reaction.IssueComment.GetAll(1, 42); + gitHubClient.Received().Reaction.IssueComment.GetAll(1, 42, Args.ApiOptions); + } + + [Fact] + public void RequestsCorrectUrlWithRepositoryIdApiOptions() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentReactionsClient(gitHubClient); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1, + PageSize = 1 + }; + + client.GetAll(1, 42, options); + + gitHubClient.Received().Reaction.IssueComment.GetAll(1, 42, options); } [Fact] @@ -48,10 +84,20 @@ public void EnsuresArgumentsNotNull() Assert.Throws(() => client.GetAll(null, "name", 1)); Assert.Throws(() => client.GetAll("owner", null, 1)); + Assert.Throws(() => client.GetAll("owner", "name", 1, null)); Assert.Throws(() => client.GetAll("", "name", 1)); Assert.Throws(() => client.GetAll("owner", "", 1)); } + + [Fact] + public void EnsuresArgumentsNotNullWithRepositoryId() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentReactionsClient(gitHubClient); + + Assert.Throws(() => client.GetAll(1, 1, null)); + } } public class TheCreateMethod diff --git a/Octokit.Tests/Reactive/ObservableIssueCommentsClientTests.cs b/Octokit.Tests/Reactive/ObservableIssueCommentsClientTests.cs index e420a4ffe9..d5057064e8 100644 --- a/Octokit.Tests/Reactive/ObservableIssueCommentsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableIssueCommentsClientTests.cs @@ -171,7 +171,7 @@ public void RequestsCorrectUrl() gitHubClient.Connection.Received(1).Get>( new Uri("repos/fake/repo/issues/3/comments", UriKind.Relative), - Args.EmptyDictionary, + Arg.Any>(), "application/vnd.github.squirrel-girl-preview"); } @@ -184,7 +184,47 @@ public void RequestsCorrectUrlWithRepositoryId() client.GetAllForIssue(1, 3); gitHubClient.Connection.Received(1).Get>( - new Uri("repositories/1/issues/3/comments", UriKind.Relative), Args.EmptyDictionary, null); + new Uri("repositories/1/issues/3/comments", UriKind.Relative), Arg.Any>(), "application/vnd.github.squirrel-girl-preview"); + } + + [Fact] + public void RequestsCorrectUrlWithIssueCommentRequest() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentsClient(gitHubClient); + + var request = new IssueCommentRequest() + { + Since = new DateTimeOffset(2016, 11, 23, 11, 11, 11, 00, new TimeSpan()), + }; + + client.GetAllForIssue("fake", "repo", 3, request); + + gitHubClient.Connection.Received(1).Get>( + new Uri("repos/fake/repo/issues/3/comments", UriKind.Relative), + Arg.Is>(d => d.Count == 3 + && d["since"] == "2016-11-23T11:11:11Z"), + "application/vnd.github.squirrel-girl-preview"); + } + + [Fact] + public void RequestsCorrectUrlWithRepositoryIdWithIssueCommentRequest() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentsClient(gitHubClient); + + var request = new IssueCommentRequest() + { + Since = new DateTimeOffset(2016, 11, 23, 11, 11, 11, 00, new TimeSpan()), + }; + + client.GetAllForIssue(1, 3, request); + + gitHubClient.Connection.Received(1).Get>( + new Uri("repositories/1/issues/3/comments", UriKind.Relative), + Arg.Is>(d => d.Count == 3 + && d["since"] == "2016-11-23T11:11:11Z"), + "application/vnd.github.squirrel-girl-preview"); } [Fact] @@ -203,7 +243,9 @@ public void RequestsCorrectUrlWithApiOptions() client.GetAllForIssue("fake", "repo", 3, options); gitHubClient.Connection.Received(1).Get>( - new Uri("repos/fake/repo/issues/3/comments", UriKind.Relative), Arg.Is>(d => d.Count == 2), "application/vnd.github.squirrel-girl-preview"); + new Uri("repos/fake/repo/issues/3/comments", UriKind.Relative), + Arg.Is>(d => d.Count == 4), + "application/vnd.github.squirrel-girl-preview"); } [Fact] @@ -222,7 +264,9 @@ public void RequestsCorrectUrlWithRepositoryIdWithApiOptions() client.GetAllForIssue(1, 3, options); gitHubClient.Connection.Received(1).Get>( - new Uri("repositories/1/issues/3/comments", UriKind.Relative), Arg.Is>(d => d.Count == 2), null); + new Uri("repositories/1/issues/3/comments", UriKind.Relative), + Arg.Is>(d => d.Count == 4), + "application/vnd.github.squirrel-girl-preview"); } [Fact] @@ -235,9 +279,13 @@ public async Task EnsuresNonNullArguments() Assert.Throws(() => client.GetAllForIssue("owner", null, 1)); Assert.Throws(() => client.GetAllForIssue(null, "name", 1, ApiOptions.None)); Assert.Throws(() => client.GetAllForIssue("owner", null, 1, ApiOptions.None)); - Assert.Throws(() => client.GetAllForIssue("owner", "name", 1, null)); + Assert.Throws(() => client.GetAllForIssue("owner", "name", 1, options: null)); + Assert.Throws(() => client.GetAllForIssue("owner", "name", 1, request: null)); + Assert.Throws(() => client.GetAllForIssue("owner", "name", 1, null, ApiOptions.None)); - Assert.Throws(() => client.GetAllForIssue(1, 1, null)); + Assert.Throws(() => client.GetAllForIssue(1, 1, options: null)); + Assert.Throws(() => client.GetAllForIssue(1, 1, request: null)); + Assert.Throws(() => client.GetAllForIssue(1, 1, null, ApiOptions.None)); Assert.Throws(() => client.GetAllForIssue("", "name", 1)); Assert.Throws(() => client.GetAllForIssue("owner", "", 1)); diff --git a/Octokit.Tests/Reactive/ObservableIssueReactionsClientTests.cs b/Octokit.Tests/Reactive/ObservableIssueReactionsClientTests.cs index 1e47649403..5e38f877e6 100644 --- a/Octokit.Tests/Reactive/ObservableIssueReactionsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableIssueReactionsClientTests.cs @@ -25,7 +25,24 @@ public void RequestsCorrectUrl() var client = new ObservableIssueReactionsClient(gitHubClient); client.GetAll("fake", "repo", 42); - gitHubClient.Received().Reaction.Issue.GetAll("fake", "repo", 42); + gitHubClient.Received().Reaction.Issue.GetAll("fake", "repo", 42, Args.ApiOptions); + } + + [Fact] + public void RequestsCorrectUrlApiOptions() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueReactionsClient(gitHubClient); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1, + PageSize = 1 + }; + + client.GetAll("fake", "repo", 42, options); + gitHubClient.Received().Reaction.Issue.GetAll("fake", "repo", 42, options); } [Fact] @@ -35,7 +52,24 @@ public void RequestsCorrectUrlWithRepositoryId() var client = new ObservableIssueReactionsClient(gitHubClient); client.GetAll(1, 42); - gitHubClient.Received().Reaction.Issue.GetAll(1, 42); + gitHubClient.Received().Reaction.Issue.GetAll(1, 42, Args.ApiOptions); + } + + [Fact] + public void RequestsCorrectUrlWithRepositoryIdApiOptions() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueReactionsClient(gitHubClient); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1, + PageSize = 1 + }; + + client.GetAll(1, 42, options); + gitHubClient.Received().Reaction.Issue.GetAll(1, 42, options); } [Fact] @@ -46,10 +80,20 @@ public void EnsuresNonNullArguments() Assert.Throws(() => client.GetAll(null, "name", 1)); Assert.Throws(() => client.GetAll("owner", null, 1)); + Assert.Throws(() => client.GetAll("owner", "name", 1, null)); Assert.Throws(() => client.GetAll("", "name", 1)); Assert.Throws(() => client.GetAll("owner", "", 1)); } + + [Fact] + public void EnsuresNonNullArgumentsWithRepositoryId() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueReactionsClient(gitHubClient); + + Assert.Throws(() => client.GetAll(1, 1, null)); + } } public class TheCreateMethod diff --git a/Octokit.Tests/Reactive/ObservableMigrationsClientTests.cs b/Octokit.Tests/Reactive/ObservableMigrationsClientTests.cs index 90be692fc4..d06bb6c86e 100644 --- a/Octokit.Tests/Reactive/ObservableMigrationsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableMigrationsClientTests.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using NSubstitute; using Octokit.Reactive; +using Octokit.Reactive.Internal; using Xunit; namespace Octokit.Tests.Reactive @@ -46,7 +48,23 @@ public void CallsIntoClient() var client = new ObservableMigrationsClient(github); client.GetAll("fake"); - github.Migration.Migrations.Received(1).GetAll("fake"); + github.Received().Migration.Migrations.GetAll("fake", Args.ApiOptions); + } + + [Fact] + public void CallsIntoClientApiOptions() + { + var github = Substitute.For(); + var client = new ObservableMigrationsClient(github); + var options = new ApiOptions + { + PageCount = 1, + PageSize = 1 + }; + + client.GetAll("fake", options); + + github.Received().Migration.Migrations.GetAll("fake", options); } } diff --git a/Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs b/Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs index 740a7339db..f64c1e8775 100644 --- a/Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs @@ -308,6 +308,85 @@ public async Task EnsuresNonNullArguments() } } + public class TheGetOrganizationMembershipMethod + { + [Fact] + public void RequestsTheCorrectUrl() + { + var gitHubClient = Substitute.For(); + var client = new ObservableOrganizationMembersClient(gitHubClient); + + client.GetOrganizationMembership("org", "username"); + + gitHubClient.Organization.Member.Received().GetOrganizationMembership("org", "username"); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var client = new ObservableOrganizationMembersClient(Substitute.For()); + + await Assert.ThrowsAsync(() => client.GetOrganizationMembership(null, "username").ToTask()); + await Assert.ThrowsAsync(() => client.GetOrganizationMembership("", "username").ToTask()); + await Assert.ThrowsAsync(() => client.GetOrganizationMembership("org", null).ToTask()); + await Assert.ThrowsAsync(() => client.GetOrganizationMembership("org", "").ToTask()); + } + } + + public class TheAddOrUpdateOrganizationMembershipMethod + { + [Fact] + public void PostsToTheCorrectUrl() + { + var orgMembershipUpdate = new OrganizationMembershipUpdate(); + + var gitHubClient = Substitute.For(); + var client = new ObservableOrganizationMembersClient(gitHubClient); + + client.AddOrUpdateOrganizationMembership("org", "username", orgMembershipUpdate); + + gitHubClient.Organization.Member.Received().AddOrUpdateOrganizationMembership("org", "username", orgMembershipUpdate); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var orgMembershipUpdate = new OrganizationMembershipUpdate(); + var client = new ObservableOrganizationMembersClient(Substitute.For()); + + await Assert.ThrowsAsync(() => client.AddOrUpdateOrganizationMembership(null, "username", orgMembershipUpdate).ToTask()); + await Assert.ThrowsAsync(() => client.AddOrUpdateOrganizationMembership("", "username", orgMembershipUpdate).ToTask()); + await Assert.ThrowsAsync(() => client.AddOrUpdateOrganizationMembership("org", null, orgMembershipUpdate).ToTask()); + await Assert.ThrowsAsync(() => client.AddOrUpdateOrganizationMembership("org", "", orgMembershipUpdate).ToTask()); + await Assert.ThrowsAsync(() => client.AddOrUpdateOrganizationMembership("org", "username", null).ToTask()); + } + } + + public class TheDeleteOrganizationMembershipMethod + { + [Fact] + public void PostsToTheCorrectUrl() + { + var gitHubClient = Substitute.For(); + var client = new ObservableOrganizationMembersClient(gitHubClient); + + client.RemoveOrganizationMembership("org", "username"); + + gitHubClient.Organization.Member.Received().RemoveOrganizationMembership("org", "username"); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var client = new ObservableOrganizationMembersClient(Substitute.For()); + + await Assert.ThrowsAsync(() => client.RemoveOrganizationMembership(null, "username").ToTask()); + await Assert.ThrowsAsync(() => client.RemoveOrganizationMembership("", "username").ToTask()); + await Assert.ThrowsAsync(() => client.RemoveOrganizationMembership("org", null).ToTask()); + await Assert.ThrowsAsync(() => client.RemoveOrganizationMembership("org", "").ToTask()); + } + } + public class TheGetAllPendingInvitationsMethod { [Fact] diff --git a/Octokit.Tests/Reactive/ObservablePullRequestReviewCommentReactionsClientTests.cs b/Octokit.Tests/Reactive/ObservablePullRequestReviewCommentReactionsClientTests.cs index b26ce47c9c..5dfd98f600 100644 --- a/Octokit.Tests/Reactive/ObservablePullRequestReviewCommentReactionsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservablePullRequestReviewCommentReactionsClientTests.cs @@ -29,6 +29,23 @@ public void RequestsCorrectUrl() gitHubClient.Received().Reaction.PullRequestReviewComment.GetAll("fake", "repo", 42); } + [Fact] + public void RequestsCorrectUrlApiOptions() + { + var gitHubClient = Substitute.For(); + var client = new ObservablePullRequestReviewCommentReactionsClient(gitHubClient); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1 + }; + + client.GetAll("fake", "repo", 42, options); + + gitHubClient.Received().Reaction.PullRequestReviewComment.GetAll("fake", "repo", 42, options); + } + [Fact] public void RequestsCorrectUrlWithRepositoryId() { @@ -40,6 +57,23 @@ public void RequestsCorrectUrlWithRepositoryId() gitHubClient.Received().Reaction.PullRequestReviewComment.GetAll(1, 42); } + [Fact] + public void RequestsCorrectUrlWithRepositoryIdApiOptions() + { + var gitHubClient = Substitute.For(); + var client = new ObservablePullRequestReviewCommentReactionsClient(gitHubClient); + + var options = new ApiOptions + { + PageCount = 1, + StartPage = 1 + }; + + client.GetAll(1, 42, options); + + gitHubClient.Received().Reaction.PullRequestReviewComment.GetAll(1, 42, options); + } + [Fact] public void EnsuresNonNullArguments() { @@ -48,10 +82,20 @@ public void EnsuresNonNullArguments() Assert.Throws(() => client.GetAll(null, "name", 1)); Assert.Throws(() => client.GetAll("owner", null, 1)); + Assert.Throws(() => client.GetAll("owner", "name", 1, null)); Assert.Throws(() => client.GetAll("", "name", 1)); Assert.Throws(() => client.GetAll("owner", "", 1)); } + + [Fact] + public void EnsuresNonNullArgumentsWithRepositoryId() + { + var gitHubClient = Substitute.For(); + var client = new ObservablePullRequestReviewCommentReactionsClient(gitHubClient); + + Assert.Throws(() => client.GetAll(1, 1, null)); + } } public class TheCreateMethod diff --git a/Octokit.Tests/Reactive/ObservablePullRequestsClientTests.cs b/Octokit.Tests/Reactive/ObservablePullRequestsClientTests.cs index b76e89bdf2..4109c2d1ff 100644 --- a/Octokit.Tests/Reactive/ObservablePullRequestsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservablePullRequestsClientTests.cs @@ -209,11 +209,11 @@ public async Task ReturnsEveryPageOfPullRequests() } ); var gitHubClient = Substitute.For(); - gitHubClient.Connection.Get>(firstPageUrl, Args.EmptyDictionary, null) + gitHubClient.Connection.Get>(firstPageUrl, Args.EmptyDictionary, "application/vnd.github.shadow-cat-preview+json") .Returns(Task.Factory.StartNew>>(() => firstPageResponse)); - gitHubClient.Connection.Get>(secondPageUrl, Args.EmptyDictionary, null) + gitHubClient.Connection.Get>(secondPageUrl, Args.EmptyDictionary, "application/vnd.github.shadow-cat-preview+json") .Returns(Task.Factory.StartNew>>(() => secondPageResponse)); - gitHubClient.Connection.Get>(thirdPageUrl, Args.EmptyDictionary, null) + gitHubClient.Connection.Get>(thirdPageUrl, Args.EmptyDictionary, "application/vnd.github.shadow-cat-preview+json") .Returns(Task.Factory.StartNew>>(() => lastPageResponse)); var client = new ObservablePullRequestsClient(gitHubClient); @@ -262,11 +262,11 @@ public async Task ReturnsEveryPageOfPullRequestsWithRepositoryId() } ); var gitHubClient = Substitute.For(); - gitHubClient.Connection.Get>(firstPageUrl, Args.EmptyDictionary, null) + gitHubClient.Connection.Get>(firstPageUrl, Args.EmptyDictionary, "application/vnd.github.shadow-cat-preview+json") .Returns(Task.Factory.StartNew>>(() => firstPageResponse)); - gitHubClient.Connection.Get>(secondPageUrl, Args.EmptyDictionary, null) + gitHubClient.Connection.Get>(secondPageUrl, Args.EmptyDictionary, "application/vnd.github.shadow-cat-preview+json") .Returns(Task.Factory.StartNew>>(() => secondPageResponse)); - gitHubClient.Connection.Get>(thirdPageUrl, Args.EmptyDictionary, null) + gitHubClient.Connection.Get>(thirdPageUrl, Args.EmptyDictionary, "application/vnd.github.shadow-cat-preview+json") .Returns(Task.Factory.StartNew>>(() => lastPageResponse)); var client = new ObservablePullRequestsClient(gitHubClient); @@ -321,21 +321,21 @@ public async Task SendsAppropriateParametersMulti() && d["state"] == "open" && d["base"] == "fake_base_branch" && d["sort"] == "created" - && d["direction"] == "desc"), Arg.Any()) + && d["direction"] == "desc"), "application/vnd.github.shadow-cat-preview+json") .Returns(Task.Factory.StartNew>>(() => firstPageResponse)); gitHubClient.Connection.Get>(secondPageUrl, Arg.Is>(d => d.Count == 5 && d["head"] == "user:ref-name" && d["state"] == "open" && d["base"] == "fake_base_branch" && d["sort"] == "created" - && d["direction"] == "desc"), null) + && d["direction"] == "desc"), "application/vnd.github.shadow-cat-preview+json") .Returns(Task.Factory.StartNew>>(() => secondPageResponse)); gitHubClient.Connection.Get>(thirdPageUrl, Arg.Is>(d => d.Count == 5 && d["head"] == "user:ref-name" && d["state"] == "open" && d["base"] == "fake_base_branch" && d["sort"] == "created" - && d["direction"] == "desc"), null) + && d["direction"] == "desc"), "application/vnd.github.shadow-cat-preview+json") .Returns(Task.Factory.StartNew>>(() => lastPageResponse)); var client = new ObservablePullRequestsClient(gitHubClient); @@ -390,21 +390,21 @@ public async Task SendsAppropriateParametersMultiWithRepositoryId() && d["state"] == "open" && d["base"] == "fake_base_branch" && d["sort"] == "created" - && d["direction"] == "desc"), Arg.Any()) + && d["direction"] == "desc"), "application/vnd.github.shadow-cat-preview+json") .Returns(Task.Factory.StartNew>>(() => firstPageResponse)); gitHubClient.Connection.Get>(secondPageUrl, Arg.Is>(d => d.Count == 5 && d["head"] == "user:ref-name" && d["state"] == "open" && d["base"] == "fake_base_branch" && d["sort"] == "created" - && d["direction"] == "desc"), null) + && d["direction"] == "desc"), "application/vnd.github.shadow-cat-preview+json") .Returns(Task.Factory.StartNew>>(() => secondPageResponse)); gitHubClient.Connection.Get>(thirdPageUrl, Arg.Is>(d => d.Count == 5 && d["head"] == "user:ref-name" && d["state"] == "open" && d["base"] == "fake_base_branch" && d["sort"] == "created" - && d["direction"] == "desc"), null) + && d["direction"] == "desc"), "application/vnd.github.shadow-cat-preview+json") .Returns(Task.Factory.StartNew>>(() => lastPageResponse)); var client = new ObservablePullRequestsClient(gitHubClient); diff --git a/Octokit.Tests/Reactive/ObservableRepoCollaboratorsClientTests.cs b/Octokit.Tests/Reactive/ObservableRepoCollaboratorsClientTests.cs index 57d2231981..9eceeadcf6 100644 --- a/Octokit.Tests/Reactive/ObservableRepoCollaboratorsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableRepoCollaboratorsClientTests.cs @@ -39,8 +39,10 @@ public void EnsuresNonNullArguments() { Assert.Throws(() => _client.GetAll(null, name)); Assert.Throws(() => _client.GetAll(owner, null)); - Assert.Throws(() => _client.GetAll(owner, name, null)); - Assert.Throws(() => _client.GetAll(repositoryId, null)); + Assert.Throws(() => _client.GetAll(owner, name, options: null)); + Assert.Throws(() => _client.GetAll(repositoryId, options: null)); + Assert.Throws(() => _client.GetAll(owner, name, request: null)); + Assert.Throws(() => _client.GetAll(repositoryId, request: null)); } [Fact] @@ -67,8 +69,8 @@ public void RequestsCorrectUrl() _client.GetAll(owner, name); _githubClient.Connection.Received(1) .Get>(Arg.Is(u => u.ToString() == expectedUrl), - Arg.Is>(dictionary => dictionary.Count == 0), - Arg.Any()); + Arg.Is>(dictionary => dictionary.Count == 1), + "application/vnd.github.hellcat-preview+json"); } [Fact] @@ -79,8 +81,8 @@ public void RequestsCorrectUrlWithRepositoryId() _client.GetAll(repositoryId); _githubClient.Connection.Received(1) .Get>(Arg.Is(u => u.ToString() == expectedUrl), - Arg.Is>(dictionary => dictionary.Count == 0), - Arg.Any()); + Arg.Is>(dictionary => dictionary.Count == 1), + "application/vnd.github.hellcat-preview+json"); } [Fact] @@ -99,8 +101,8 @@ public void RequestsCorrectUrlWithApiOptions() _client.GetAll(owner, name, options); _githubClient.Connection.Received(1) .Get>(Arg.Is(u => u.ToString() == expectedUrl), - Arg.Is>(dictionary => dictionary.Count == 2), - null); + Arg.Is>(dictionary => dictionary.Count == 3), + "application/vnd.github.hellcat-preview+json"); // StartPage is setted => only 1 option (StartPage) in dictionary options = new ApiOptions @@ -111,8 +113,8 @@ public void RequestsCorrectUrlWithApiOptions() _client.GetAll(owner, name, options); _githubClient.Connection.Received(1) .Get>(Arg.Is(u => u.ToString() == expectedUrl), - Arg.Is>(dictionary => dictionary.Count == 1), - null); + Arg.Is>(dictionary => dictionary.Count == 2), + "application/vnd.github.hellcat-preview+json"); // PageCount is setted => none of options in dictionary options = new ApiOptions @@ -123,8 +125,45 @@ public void RequestsCorrectUrlWithApiOptions() _client.GetAll(owner, name, options); _githubClient.Connection.Received(1) .Get>(Arg.Is(u => u.ToString() == expectedUrl), - Arg.Is>(dictionary => dictionary.Count == 0), - null); + Arg.Is>(dictionary => dictionary.Count == 1), + "application/vnd.github.hellcat-preview+json"); + } + + [Fact] + public void RequestsCorrectUrlWithCollaboratorFilter() + { + var expectedUrl = string.Format("repos/{0}/{1}/collaborators", owner, name); + + var request = new RepositoryCollaboratorListRequest(); + + _client.GetAll(owner, name, request); + _githubClient.Connection.Received(1) + .Get>(Arg.Is(u => u.ToString() == expectedUrl), + Arg.Is>(d => d["affiliation"] == "all"), + "application/vnd.github.hellcat-preview+json"); + + request = new RepositoryCollaboratorListRequest + { + Affiliation = CollaboratorAffiliation.Direct + }; + + _client.GetAll(owner, name, request); + _githubClient.Connection.Received(1) + .Get>(Arg.Is(u => u.ToString() == expectedUrl), + Arg.Is>(d => d["affiliation"] == "direct"), + "application/vnd.github.hellcat-preview+json"); + + // PageCount is setted => none of options in dictionary + request = new RepositoryCollaboratorListRequest + { + Affiliation = CollaboratorAffiliation.Outside + }; + + _client.GetAll(owner, name, request); + _githubClient.Connection.Received(1) + .Get>(Arg.Is(u => u.ToString() == expectedUrl), + Arg.Is>(d => d["affiliation"] == "outside"), + "application/vnd.github.hellcat-preview+json"); } [Fact] @@ -143,8 +182,8 @@ public void RequestsCorrectUrlWithApiOptionsAndRepositoryId() _client.GetAll(repositoryId, options); _githubClient.Connection.Received(1) .Get>(Arg.Is(u => u.ToString() == expectedUrl), - Arg.Is>(dictionary => dictionary.Count == 2), - null); + Arg.Is>(dictionary => dictionary.Count == 3), + "application/vnd.github.hellcat-preview+json"); // StartPage is setted => only 1 option (StartPage) in dictionary options = new ApiOptions @@ -155,8 +194,8 @@ public void RequestsCorrectUrlWithApiOptionsAndRepositoryId() _client.GetAll(repositoryId, options); _githubClient.Connection.Received(1) .Get>(Arg.Is(u => u.ToString() == expectedUrl), - Arg.Is>(dictionary => dictionary.Count == 1), - null); + Arg.Is>(dictionary => dictionary.Count == 2), + "application/vnd.github.hellcat-preview+json"); // PageCount is setted => none of options in dictionary options = new ApiOptions @@ -167,8 +206,44 @@ public void RequestsCorrectUrlWithApiOptionsAndRepositoryId() _client.GetAll(repositoryId, options); _githubClient.Connection.Received(1) .Get>(Arg.Is(u => u.ToString() == expectedUrl), - Arg.Is>(dictionary => dictionary.Count == 0), - null); + Arg.Is>(dictionary => dictionary.Count == 1), + "application/vnd.github.hellcat-preview+json"); + } + + [Fact] + public void RequestsCorrectUrlWithCollaboratorFilterAndRepositoryId() + { + var expectedUrl = string.Format("repositories/{0}/collaborators", repositoryId); + + var request = new RepositoryCollaboratorListRequest(); + + _client.GetAll(repositoryId, request); + _githubClient.Connection.Received(1) + .Get>(Arg.Is(u => u.ToString() == expectedUrl), + Arg.Is>(d => d["affiliation"] == "all"), + "application/vnd.github.hellcat-preview+json"); + + request = new RepositoryCollaboratorListRequest + { + Affiliation = CollaboratorAffiliation.Direct + }; + + _client.GetAll(repositoryId, request); + _githubClient.Connection.Received(1) + .Get>(Arg.Is(u => u.ToString() == expectedUrl), + Arg.Is>(d => d["affiliation"] == "direct"), + "application/vnd.github.hellcat-preview+json"); + + request = new RepositoryCollaboratorListRequest + { + Affiliation = CollaboratorAffiliation.Outside + }; + + _client.GetAll(repositoryId, request); + _githubClient.Connection.Received(1) + .Get>(Arg.Is(u => u.ToString() == expectedUrl), + Arg.Is>(d => d["affiliation"] == "outside"), + "application/vnd.github.hellcat-preview+json"); } } diff --git a/Octokit.Tests/Reactive/ObservableRepositoryBranchesClientTests.cs b/Octokit.Tests/Reactive/ObservableRepositoryBranchesClientTests.cs index 32fab8fbf9..0001c8c425 100644 --- a/Octokit.Tests/Reactive/ObservableRepositoryBranchesClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableRepositoryBranchesClientTests.cs @@ -674,7 +674,7 @@ public void RequestsTheCorrectUrl() { var gitHubClient = Substitute.For(); var client = new ObservableRepositoryBranchesClient(gitHubClient); - var update = new BranchProtectionRequiredReviewsUpdate(false, false); + var update = new BranchProtectionRequiredReviewsUpdate(false, false, 2); client.UpdateReviewEnforcement("owner", "repo", "branch", update); @@ -686,7 +686,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() { var gitHubClient = Substitute.For(); var client = new ObservableRepositoryBranchesClient(gitHubClient); - var update = new BranchProtectionRequiredReviewsUpdate(false, false); + var update = new BranchProtectionRequiredReviewsUpdate(false, false, 2); client.UpdateReviewEnforcement(1, "branch", update); @@ -697,7 +697,7 @@ public void RequestsTheCorrectUrlWithRepositoryId() public async Task EnsuresNonNullArguments() { var client = new ObservableRepositoryBranchesClient(Substitute.For()); - var update = new BranchProtectionRequiredReviewsUpdate(false, false); + var update = new BranchProtectionRequiredReviewsUpdate(false, false, 2); Assert.Throws(() => client.UpdateReviewEnforcement(null, "repo", "branch", update)); Assert.Throws(() => client.UpdateReviewEnforcement("owner", null, "branch", update)); diff --git a/Octokit.Tests/SimpleJsonSerializerTests.cs b/Octokit.Tests/SimpleJsonSerializerTests.cs index 0d7be5098d..daa1e8d049 100644 --- a/Octokit.Tests/SimpleJsonSerializerTests.cs +++ b/Octokit.Tests/SimpleJsonSerializerTests.cs @@ -91,7 +91,7 @@ public void HandleUnicodeCharacters() var deserializeData = new SimpleJsonSerializer().Deserialize(json); - Assert.True(lastTabCharacter.ToString().Equals("\\t")); + Assert.Equal("\\t", lastTabCharacter.ToString()); Assert.Equal(data, deserializeData); } @@ -313,7 +313,7 @@ public void DefaultsMissingParameters() var sample = new SimpleJsonSerializer().Deserialize(json); Assert.Equal(0, sample.Id); - Assert.Equal(null, sample.FirstName); + Assert.Null(sample.FirstName); Assert.False(sample.IsSomething); Assert.True(sample.Private); } diff --git a/Octokit/Clients/CheckSuitesClient.cs b/Octokit/Clients/CheckSuitesClient.cs index 71affd3375..26275dc0ce 100644 --- a/Octokit/Clients/CheckSuitesClient.cs +++ b/Octokit/Clients/CheckSuitesClient.cs @@ -171,7 +171,7 @@ public async Task GetAllForReference(long repositoryId, str } /// - /// Updates Check Suites prefrences on a repository, such as disabling automatic creation when code is pushed + /// Updates Check Suites preferences on a repository, such as disabling automatic creation when code is pushed /// /// /// See the Check Suites API documentation for more information. @@ -189,7 +189,7 @@ public Task UpdatePreferences(string owner, strin } /// - /// Updates Check Suites prefrences on a repository, such as disabling automatic creation when code is pushed + /// Updates Check Suites preferences on a repository, such as disabling automatic creation when code is pushed /// /// /// See the Check Suites API documentation for more information. diff --git a/Octokit/Clients/CommitCommentReactionsClient.cs b/Octokit/Clients/CommitCommentReactionsClient.cs index 6decd357bc..7b97705b39 100644 --- a/Octokit/Clients/CommitCommentReactionsClient.cs +++ b/Octokit/Clients/CommitCommentReactionsClient.cs @@ -58,11 +58,26 @@ public Task Create(long repositoryId, int number, NewReaction reaction /// The comment id /// public Task> GetAll(string owner, string name, int number) + { + return GetAll(owner, name, number, ApiOptions.None); + } + + /// + /// Get all reactions for a specified Commit Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment + /// The owner of the repository + /// The name of the repository + /// The comment id + /// Options for changing the API response + /// + public Task> GetAll(string owner, string name, int number, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(options, nameof(options)); - return ApiConnection.GetAll(ApiUrls.CommitCommentReactions(owner, name, number), AcceptHeaders.ReactionsPreview); + return ApiConnection.GetAll(ApiUrls.CommitCommentReactions(owner, name, number), null, AcceptHeaders.ReactionsPreview, options); } /// @@ -74,7 +89,22 @@ public Task> GetAll(string owner, string name, int numbe /// public Task> GetAll(long repositoryId, int number) { - return ApiConnection.GetAll(ApiUrls.CommitCommentReactions(repositoryId, number), AcceptHeaders.ReactionsPreview); + return GetAll(repositoryId, number, ApiOptions.None); + } + + /// + /// Get all reactions for a specified Commit Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment + /// The owner of the repository + /// The comment id + /// Options for changing the API response + /// + public Task> GetAll(long repositoryId, int number, ApiOptions options) + { + Ensure.ArgumentNotNull(options, nameof(options)); + + return ApiConnection.GetAll(ApiUrls.CommitCommentReactions(repositoryId, number), null, AcceptHeaders.ReactionsPreview, options); } } } diff --git a/Octokit/Clients/Enterprise/EnterpriseClient.cs b/Octokit/Clients/Enterprise/EnterpriseClient.cs index d5b6d30bf0..d3d37fd42f 100644 --- a/Octokit/Clients/Enterprise/EnterpriseClient.cs +++ b/Octokit/Clients/Enterprise/EnterpriseClient.cs @@ -17,6 +17,7 @@ public EnterpriseClient(IApiConnection apiConnection) : base(apiConnection) AdminStats = new EnterpriseAdminStatsClient(apiConnection); Ldap = new EnterpriseLdapClient(apiConnection); License = new EnterpriseLicenseClient(apiConnection); + ManagementConsole = new EnterpriseManagementConsoleClient(apiConnection); Organization = new EnterpriseOrganizationClient(apiConnection); SearchIndexing = new EnterpriseSearchIndexingClient(apiConnection); PreReceiveEnvironment = new EnterprisePreReceiveEnvironmentsClient(apiConnection); @@ -27,7 +28,7 @@ public EnterpriseClient(IApiConnection apiConnection) : base(apiConnection) /// /// /// See the Enterprise Admin Stats API documentation for more information. - /// + /// public IEnterpriseAdminStatsClient AdminStats { get; private set; } /// @@ -35,7 +36,7 @@ public EnterpriseClient(IApiConnection apiConnection) : base(apiConnection) /// /// /// See the Enterprise LDAP API documentation for more information. - /// + /// public IEnterpriseLdapClient Ldap { get; private set; } /// @@ -43,15 +44,23 @@ public EnterpriseClient(IApiConnection apiConnection) : base(apiConnection) /// /// /// See the Enterprise License API documentation for more information. - /// + /// public IEnterpriseLicenseClient License { get; private set; } + /// + /// A client for GitHub's Enterprise Management Console API + /// + /// + /// See the Enterprise Management Console API documentation for more information. + /// + public IEnterpriseManagementConsoleClient ManagementConsole { get; private set; } + /// /// A client for GitHub's Enterprise Organization API /// /// /// See the Enterprise Organization API documentation for more information. - /// + /// public IEnterpriseOrganizationClient Organization { get; private set; } /// @@ -59,7 +68,7 @@ public EnterpriseClient(IApiConnection apiConnection) : base(apiConnection) /// /// /// See the Enterprise Search Indexing API documentation for more information. - /// + /// public IEnterpriseSearchIndexingClient SearchIndexing { get; private set; } /// diff --git a/Octokit/Clients/Enterprise/EnterpriseManagementConsoleClient.cs b/Octokit/Clients/Enterprise/EnterpriseManagementConsoleClient.cs new file mode 100644 index 0000000000..7a3ada73cd --- /dev/null +++ b/Octokit/Clients/Enterprise/EnterpriseManagementConsoleClient.cs @@ -0,0 +1,50 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + /// + /// A client for GitHub's Enterprise Management Console API + /// + /// + /// See the Enterprise Management Console API documentation for more information. + /// + public class EnterpriseManagementConsoleClient : ApiClient, IEnterpriseManagementConsoleClient + { + public EnterpriseManagementConsoleClient(IApiConnection apiConnection) + : base(apiConnection) + { } + + /// + /// Gets GitHub Enterprise Maintenance Mode Status + /// + /// + /// https://developer.github.com/v3/enterprise/management_console/#check-maintenance-status + /// + /// The . + public Task GetMaintenanceMode(string managementConsolePassword) + { + Ensure.ArgumentNotNullOrEmptyString(managementConsolePassword, "managementConsolePassword"); + + var endpoint = ApiUrls.EnterpriseManagementConsoleMaintenance(managementConsolePassword, ApiConnection.Connection.BaseAddress); + + return ApiConnection.Get(endpoint); + } + + /// + /// Sets GitHub Enterprise Maintenance Mode + /// + /// + /// https://developer.github.com/v3/enterprise/management_console/#check-maintenance-status + /// + /// The . + public Task EditMaintenanceMode(UpdateMaintenanceRequest maintenance, string managementConsolePassword) + { + Ensure.ArgumentNotNull(maintenance, "maintenance"); + Ensure.ArgumentNotNullOrEmptyString(managementConsolePassword, "managementConsolePassword"); + + var endpoint = ApiUrls.EnterpriseManagementConsoleMaintenance(managementConsolePassword, ApiConnection.Connection.BaseAddress); + + return ApiConnection.Post(endpoint, maintenance.ToFormUrlEncodedParameterString()); + } + } +} diff --git a/Octokit/Clients/Enterprise/IEnterpriseClient.cs b/Octokit/Clients/Enterprise/IEnterpriseClient.cs index 8f3ace37bf..8a7841d5e0 100644 --- a/Octokit/Clients/Enterprise/IEnterpriseClient.cs +++ b/Octokit/Clients/Enterprise/IEnterpriseClient.cs @@ -13,7 +13,7 @@ public interface IEnterpriseClient /// /// /// See the Enterprise Admin Stats API documentation for more information. - /// + /// IEnterpriseAdminStatsClient AdminStats { get; } /// @@ -21,7 +21,7 @@ public interface IEnterpriseClient /// /// /// See the Enterprise LDAP API documentation for more information. - /// + /// IEnterpriseLdapClient Ldap { get; } /// @@ -29,15 +29,23 @@ public interface IEnterpriseClient /// /// /// See the Enterprise License API documentation for more information. - /// + /// IEnterpriseLicenseClient License { get; } + /// + /// A client for GitHub's Enterprise Management Console API + /// + /// + /// See the Enterprise Management Console API documentation for more information. + /// + IEnterpriseManagementConsoleClient ManagementConsole { get; } + /// /// A client for GitHub's Enterprise Organization API /// /// /// See the Enterprise Organization API documentation for more information. - /// + /// IEnterpriseOrganizationClient Organization { get; } /// @@ -45,7 +53,7 @@ public interface IEnterpriseClient /// /// /// See the Enterprise Search Indexing API documentation for more information. - /// + /// IEnterpriseSearchIndexingClient SearchIndexing { get; } /// diff --git a/Octokit/Clients/Enterprise/IEnterpriseManagementConsoleClient.cs b/Octokit/Clients/Enterprise/IEnterpriseManagementConsoleClient.cs new file mode 100644 index 0000000000..00e4607548 --- /dev/null +++ b/Octokit/Clients/Enterprise/IEnterpriseManagementConsoleClient.cs @@ -0,0 +1,31 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + /// + /// A client for GitHub's Enterprise Management Console API + /// + /// + /// See the Enterprise Management Console API documentation for more information. + /// + public interface IEnterpriseManagementConsoleClient + { + /// + /// Gets GitHub Enterprise Maintenance Mode Status + /// + /// + /// https://developer.github.com/v3/enterprise/management_console/#check-maintenance-status + /// + /// The . + Task GetMaintenanceMode(string managementConsolePassword); + + /// + /// Sets GitHub Enterprise Maintenance Mode + /// + /// + /// https://developer.github.com/v3/enterprise/management_console/#check-maintenance-status + /// + /// The . + Task EditMaintenanceMode(UpdateMaintenanceRequest maintenance, string managementConsolePassword); + } +} diff --git a/Octokit/Clients/ICommitCommentReactionsClient.cs b/Octokit/Clients/ICommitCommentReactionsClient.cs index 7725f9df2d..c64c25fa19 100644 --- a/Octokit/Clients/ICommitCommentReactionsClient.cs +++ b/Octokit/Clients/ICommitCommentReactionsClient.cs @@ -40,9 +40,19 @@ public interface ICommitCommentReactionsClient /// The name of the repository /// The comment id /// - [ExcludeFromPaginationApiOptionsConventionTest("TODO: Implement pagination for this method")] Task> GetAll(string owner, string name, int number); + /// + /// Get all reactions for a specified Commit Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment + /// The owner of the repository + /// The name of the repository + /// The comment id + /// Options for changing the API response + /// + Task> GetAll(string owner, string name, int number, ApiOptions options); + /// /// Get all reactions for a specified Commit Comment /// @@ -50,7 +60,16 @@ public interface ICommitCommentReactionsClient /// The owner of the repository /// The comment id /// - [ExcludeFromPaginationApiOptionsConventionTest("TODO: Implement pagination for this method")] Task> GetAll(long repositoryId, int number); + + /// + /// Get all reactions for a specified Commit Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment + /// The owner of the repository + /// The comment id + /// Options for changing the API response + /// + Task> GetAll(long repositoryId, int number, ApiOptions options); } } diff --git a/Octokit/Clients/IIssueCommentReactionsClient.cs b/Octokit/Clients/IIssueCommentReactionsClient.cs index c2eec16264..4fd60ba45d 100644 --- a/Octokit/Clients/IIssueCommentReactionsClient.cs +++ b/Octokit/Clients/IIssueCommentReactionsClient.cs @@ -37,16 +37,33 @@ public interface IIssueCommentReactionsClient /// The owner of the repository /// The name of the repository /// The comment id - [ExcludeFromPaginationApiOptionsConventionTest("TODO: Implement pagination for this method")] Task> GetAll(string owner, string name, int number); + /// + /// Get all reactions for a specified Issue Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment + /// The owner of the repository + /// The name of the repository + /// The comment id + /// Options for changing the API response + Task> GetAll(string owner, string name, int number, ApiOptions options); + /// /// Get all reactions for a specified Issue Comment /// /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment /// The Id of the repository /// The comment id - [ExcludeFromPaginationApiOptionsConventionTest("TODO: Implement pagination for this method")] Task> GetAll(long repositoryId, int number); + + /// + /// Get all reactions for a specified Issue Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment + /// The Id of the repository + /// The comment id + /// Options for changing the API response + Task> GetAll(long repositoryId, int number, ApiOptions options); } } diff --git a/Octokit/Clients/IIssueCommentsClient.cs b/Octokit/Clients/IIssueCommentsClient.cs index 0f75296dec..bd1a05e93d 100644 --- a/Octokit/Clients/IIssueCommentsClient.cs +++ b/Octokit/Clients/IIssueCommentsClient.cs @@ -137,6 +137,46 @@ public interface IIssueCommentsClient /// Options for changing the API response Task> GetAllForIssue(long repositoryId, int number, ApiOptions options); + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The sorting parameters + Task> GetAllForIssue(string owner, string name, int number, IssueCommentRequest request); + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The Id of the repository + /// The issue number + /// The sorting parameters + Task> GetAllForIssue(long repositoryId, int number, IssueCommentRequest request); + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The sorting parameters + /// Options for changing the API response + Task> GetAllForIssue(string owner, string name, int number, IssueCommentRequest request, ApiOptions options); + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The Id of the repository + /// The issue number + /// The sorting parameters + /// Options for changing the API response + Task> GetAllForIssue(long repositoryId, int number, IssueCommentRequest request, ApiOptions options); + /// /// Creates a new Issue Comment for a specified Issue. /// diff --git a/Octokit/Clients/IIssueReactionsClient.cs b/Octokit/Clients/IIssueReactionsClient.cs index ffc7cc56e6..0de3feff55 100644 --- a/Octokit/Clients/IIssueReactionsClient.cs +++ b/Octokit/Clients/IIssueReactionsClient.cs @@ -18,18 +18,35 @@ public interface IIssueReactionsClient /// The owner of the repository /// The name of the repository /// The issue id - [ExcludeFromPaginationApiOptionsConventionTest("TODO: Implement pagination for this method")] Task> GetAll(string owner, string name, int number); + /// + /// Get all reactions for a specified Issue + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue id + /// Options for changing the API response + Task> GetAll(string owner, string name, int number, ApiOptions options); + /// /// Get all reactions for a specified Issue /// /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue /// The Id of the repository /// The issue id - [ExcludeFromPaginationApiOptionsConventionTest("TODO: Implement pagination for this method")] Task> GetAll(long repositoryId, int number); + /// + /// Get all reactions for a specified Issue + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue + /// The Id of the repository + /// The issue id + /// Options for changing the API response + Task> GetAll(long repositoryId, int number, ApiOptions options); + /// /// Creates a reaction for a specified Issue /// diff --git a/Octokit/Clients/IIssuesEventsClient.cs b/Octokit/Clients/IIssuesEventsClient.cs index 62905aea7a..f153c90772 100644 --- a/Octokit/Clients/IIssuesEventsClient.cs +++ b/Octokit/Clients/IIssuesEventsClient.cs @@ -104,10 +104,10 @@ public interface IIssuesEventsClient /// /// The owner of the repository /// The name of the repository - /// The event id + /// The event id [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] - Task Get(string owner, string name, int number); + Task Get(string owner, string name, long eventId); /// /// Gets a single event @@ -116,9 +116,9 @@ public interface IIssuesEventsClient /// http://developer.github.com/v3/issues/events/#get-a-single-event /// /// The Id of the repository - /// The event id + /// The event id [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] - Task Get(long repositoryId, int number); + Task Get(long repositoryId, long eventId); } } diff --git a/Octokit/Clients/IMigrationsClient.cs b/Octokit/Clients/IMigrationsClient.cs index 6980483b54..cbc6de80f7 100644 --- a/Octokit/Clients/IMigrationsClient.cs +++ b/Octokit/Clients/IMigrationsClient.cs @@ -20,7 +20,7 @@ public interface IMigrationsClient /// https://developer.github.com/v3/migration/migrations/#start-a-migration /// /// The organization for which to start a migration. - /// Sprcifies parameters for the migration in a + /// Specifies parameters for the migration in a /// object. /// The started migration. Task Start( @@ -28,17 +28,29 @@ Task Start( StartMigrationRequest migration); /// - /// Gets the list of the most recent migrations of the the organization. + /// Gets the list of the most recent migrations of the organization. /// /// /// https://developer.github.com/v3/migration/migrations/#get-a-list-of-migrations /// /// The organization of which to list migrations. /// List of most recent s. - [ExcludeFromPaginationApiOptionsConventionTest("TODO: Implement pagination for this method")] - Task> GetAll( + Task> GetAll( string org); + /// + /// Gets the list of the most recent migrations of the organization. + /// + /// + /// https://developer.github.com/v3/migration/migrations/#get-a-list-of-migrations + /// + /// The organization of which to list migrations. + /// Options for changing the API response + /// List of most recent s. + Task> GetAll( + string org, + ApiOptions options); + /// /// Get the status of a migration /// diff --git a/Octokit/Clients/IMiscellaneousClient.cs b/Octokit/Clients/IMiscellaneousClient.cs index 78cb2e9e56..0f6ae3073f 100644 --- a/Octokit/Clients/IMiscellaneousClient.cs +++ b/Octokit/Clients/IMiscellaneousClient.cs @@ -63,7 +63,7 @@ public interface IMiscellaneousClient Task> GetAllLicenses(); /// - /// Retrieves a license based on the license key such as "mit" + /// Retrieves a license based on the license key such as "MIT" /// /// /// A that includes the license key, text, and attributes of the license. diff --git a/Octokit/Clients/IOrganizationMembersClient.cs b/Octokit/Clients/IOrganizationMembersClient.cs index 258228182b..cb33f5aed7 100644 --- a/Octokit/Clients/IOrganizationMembersClient.cs +++ b/Octokit/Clients/IOrganizationMembersClient.cs @@ -271,7 +271,7 @@ public interface IOrganizationMembersClient /// Make the authenticated user's organization membership private. /// /// - /// This method requries authentication. + /// This method requires authentication. /// See the API documentation /// for more information. /// @@ -280,6 +280,50 @@ public interface IOrganizationMembersClient /// Task Conceal(string org, string user); + /// + /// Get a user's membership with an organization. + /// + /// + /// This method requires authentication. + /// The authenticated user must be an organization member. + /// See the API documentation + /// for more information. + /// + /// The login for the organization + /// The login for the user + /// + Task GetOrganizationMembership(string org, string user); + + /// + /// Add a user to the organization or update the user's role withing the organization. + /// + /// + /// This method requires authentication. + /// The authenticated user must be an organization owner. + /// See the API documentation + /// for more information. + /// + /// The login for the organization + /// The login for the user + /// An instance describing the + /// changes to make to the user's organization membership + /// + Task AddOrUpdateOrganizationMembership(string org, string user, OrganizationMembershipUpdate addOrUpdateRequest); + + /// + /// Remove a user's membership with an organization. + /// + /// + /// This method requires authentication. + /// The authenticated user must be an organization owner. + /// See the API documentation + /// for more information. + /// + /// The login for the organization + /// The login for the user + /// + Task RemoveOrganizationMembership(string org, string user); + /// /// List all pending invitations for the organization. /// diff --git a/Octokit/Clients/IProjectsClient.cs b/Octokit/Clients/IProjectsClient.cs index 3e75e2f35f..5a56a406d6 100644 --- a/Octokit/Clients/IProjectsClient.cs +++ b/Octokit/Clients/IProjectsClient.cs @@ -102,7 +102,7 @@ public interface IProjectsClient /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization Task> GetAllForOrganization(string organization); /// @@ -111,7 +111,7 @@ public interface IProjectsClient /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization /// Used to filter the list of projects returned Task> GetAllForOrganization(string organization, ProjectRequest request); @@ -121,7 +121,7 @@ public interface IProjectsClient /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization /// Options for changing the API response Task> GetAllForOrganization(string organization, ApiOptions options); @@ -131,7 +131,7 @@ public interface IProjectsClient /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization /// Used to filter the list of projects returned /// Options for changing the API response Task> GetAllForOrganization(string organization, ProjectRequest request, ApiOptions options); diff --git a/Octokit/Clients/IPullRequestReviewCommentReactionsClient.cs b/Octokit/Clients/IPullRequestReviewCommentReactionsClient.cs index 10e3dbad00..96a47395e5 100644 --- a/Octokit/Clients/IPullRequestReviewCommentReactionsClient.cs +++ b/Octokit/Clients/IPullRequestReviewCommentReactionsClient.cs @@ -18,18 +18,35 @@ public interface IPullRequestReviewCommentReactionsClient /// The owner of the repository /// The name of the repository /// The comment id - [ExcludeFromPaginationApiOptionsConventionTest("TODO: Implement pagination for this method")] Task> GetAll(string owner, string name, int number); + /// + /// Get all reactions for a specified Pull Request Review Comment. + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-pull-request-review-comment + /// The owner of the repository + /// The name of the repository + /// The comment id + /// Options for changing the API response + Task> GetAll(string owner, string name, int number, ApiOptions options); + /// /// Get all reactions for a specified Pull Request Review Comment. /// /// https://developer.github.com/v3/reactions/#list-reactions-for-a-pull-request-review-comment /// The Id of the repository /// The comment id - [ExcludeFromPaginationApiOptionsConventionTest("TODO: Implement pagination for this method")] Task> GetAll(long repositoryId, int number); + /// + /// Get all reactions for a specified Pull Request Review Comment. + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-pull-request-review-comment + /// The Id of the repository + /// The comment id + /// Options for changing the API response + Task> GetAll(long repositoryId, int number, ApiOptions options); + /// /// Creates a reaction for a specified Pull Request Review Comment. /// diff --git a/Octokit/Clients/IRepoCollaboratorsClient.cs b/Octokit/Clients/IRepoCollaboratorsClient.cs index 2986795f54..d117d414bd 100644 --- a/Octokit/Clients/IRepoCollaboratorsClient.cs +++ b/Octokit/Clients/IRepoCollaboratorsClient.cs @@ -55,6 +55,54 @@ public interface IRepoCollaboratorsClient /// Thrown when a general API error occurs. Task> GetAll(long repositoryId, ApiOptions options); + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Used to request and filter a list of repository collaborators + /// Thrown when a general API error occurs. + Task> GetAll(string owner, string name, RepositoryCollaboratorListRequest request); + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the repository + /// Used to request and filter a list of repository collaborators + /// Thrown when a general API error occurs. + Task> GetAll(long repositoryId, RepositoryCollaboratorListRequest request); + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Used to request and filter a list of repository collaborators + /// Options for changing the API response + /// Thrown when a general API error occurs. + Task> GetAll(string owner, string name, RepositoryCollaboratorListRequest request, ApiOptions options); + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the repository + /// Used to request and filter a list of repository collaborators + /// Options for changing the API response + /// Thrown when a general API error occurs. + Task> GetAll(long repositoryId, RepositoryCollaboratorListRequest request, ApiOptions options); + /// /// Checks if a user is a collaborator on a repository. /// diff --git a/Octokit/Clients/IRepositoriesClient.cs b/Octokit/Clients/IRepositoriesClient.cs index 617b93c2fb..ab9e31fb94 100644 --- a/Octokit/Clients/IRepositoriesClient.cs +++ b/Octokit/Clients/IRepositoriesClient.cs @@ -316,7 +316,9 @@ public interface IRepositoriesClient IDeploymentsClient Deployment { get; } /// - /// Client for GitHub's Repository Statistics API + /// Client for GitHub's Repository Statistics API. + /// Note that the GitHub API uses caching on these endpoints, + /// see a word about caching for more details. /// /// /// See the Statistics API documentation for more details diff --git a/Octokit/Clients/IStatisticsClient.cs b/Octokit/Clients/IStatisticsClient.cs index 9802ef752f..f7731c86d7 100644 --- a/Octokit/Clients/IStatisticsClient.cs +++ b/Octokit/Clients/IStatisticsClient.cs @@ -6,6 +6,8 @@ namespace Octokit { /// /// A client for GitHub's Repository Statistics API. + /// Note that the GitHub API uses caching on these endpoints, + /// see a word about caching for more details. /// /// /// See the Repository Statistics API documentation for more information. diff --git a/Octokit/Clients/IssueCommentReactionsClient.cs b/Octokit/Clients/IssueCommentReactionsClient.cs index 6f3f7ebac4..b8c552959d 100644 --- a/Octokit/Clients/IssueCommentReactionsClient.cs +++ b/Octokit/Clients/IssueCommentReactionsClient.cs @@ -55,11 +55,25 @@ public Task Create(long repositoryId, int number, NewReaction reaction /// The name of the repository /// The comment id public Task> GetAll(string owner, string name, int number) + { + return GetAll(owner, name, number, ApiOptions.None); + } + + /// + /// Get all reactions for a specified Issue Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment + /// The owner of the repository + /// The name of the repository + /// The comment id + /// Options for changing the API response + public Task> GetAll(string owner, string name, int number, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(options, nameof(options)); - return ApiConnection.GetAll(ApiUrls.IssueCommentReactions(owner, name, number), AcceptHeaders.ReactionsPreview); + return ApiConnection.GetAll(ApiUrls.IssueCommentReactions(owner, name, number), null, AcceptHeaders.ReactionsPreview, options); } /// @@ -70,7 +84,21 @@ public Task> GetAll(string owner, string name, int numbe /// The comment id public Task> GetAll(long repositoryId, int number) { - return ApiConnection.GetAll(ApiUrls.IssueCommentReactions(repositoryId, number), AcceptHeaders.ReactionsPreview); + return GetAll(repositoryId, number, ApiOptions.None); + } + + /// + /// Get all reactions for a specified Issue Comment + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment + /// The Id of the repository + /// The comment id + /// Options for changing the API response + public Task> GetAll(long repositoryId, int number, ApiOptions options) + { + Ensure.ArgumentNotNull(options, nameof(options)); + + return ApiConnection.GetAll(ApiUrls.IssueCommentReactions(repositoryId, number), null, AcceptHeaders.ReactionsPreview, options); } } } diff --git a/Octokit/Clients/IssueCommentsClient.cs b/Octokit/Clients/IssueCommentsClient.cs index 1c527d4b23..41fda35ab9 100644 --- a/Octokit/Clients/IssueCommentsClient.cs +++ b/Octokit/Clients/IssueCommentsClient.cs @@ -200,7 +200,7 @@ public Task> GetAllForIssue(string owner, string nam Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNull(options, nameof(options)); - return ApiConnection.GetAll(ApiUrls.IssueComments(owner, name, number), null, AcceptHeaders.ReactionsPreview, options); + return GetAllForIssue(owner, name, number, new IssueCommentRequest(), options); } /// @@ -214,7 +214,73 @@ public Task> GetAllForIssue(long repositoryId, int n { Ensure.ArgumentNotNull(options, nameof(options)); - return ApiConnection.GetAll(ApiUrls.IssueComments(repositoryId, number), null, AcceptHeaders.ReactionsPreview, options); + return GetAllForIssue(repositoryId, number, new IssueCommentRequest(), options); + } + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The sorting parameters + public Task> GetAllForIssue(string owner, string name, int number, IssueCommentRequest request) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAllForIssue(owner, name, number, request, ApiOptions.None); + } + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The Id of the repository + /// The issue number + /// The sorting parameters + public Task> GetAllForIssue(long repositoryId, int number, IssueCommentRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAllForIssue(repositoryId, number, request, ApiOptions.None); + } + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The sorting parameters + /// Options for changing the API response + public Task> GetAllForIssue(string owner, string name, int number, IssueCommentRequest request, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + + return ApiConnection.GetAll(ApiUrls.IssueComments(owner, name, number), request.ToParametersDictionary(), AcceptHeaders.ReactionsPreview, options); + } + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The Id of the repository + /// The issue number + /// The sorting parameters + /// Options for changing the API response + public Task> GetAllForIssue(long repositoryId, int number, IssueCommentRequest request, ApiOptions options) + { + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + + return ApiConnection.GetAll(ApiUrls.IssueComments(repositoryId, number), request.ToParametersDictionary(), AcceptHeaders.ReactionsPreview, options); } /// diff --git a/Octokit/Clients/IssueReactionsClient.cs b/Octokit/Clients/IssueReactionsClient.cs index 6b0dd40667..02b826d26c 100644 --- a/Octokit/Clients/IssueReactionsClient.cs +++ b/Octokit/Clients/IssueReactionsClient.cs @@ -24,11 +24,25 @@ public IssueReactionsClient(IApiConnection apiConnection) /// The name of the repository /// The issue id public Task> GetAll(string owner, string name, int number) + { + return GetAll(owner, name, number, ApiOptions.None); + } + + /// + /// Get all reactions for a specified Issue + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue id + /// Options for changing the API response + public Task> GetAll(string owner, string name, int number, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(options, nameof(options)); - return ApiConnection.GetAll(ApiUrls.IssueReactions(owner, name, number), AcceptHeaders.ReactionsPreview); + return ApiConnection.GetAll(ApiUrls.IssueReactions(owner, name, number), null, AcceptHeaders.ReactionsPreview, options); } /// @@ -39,7 +53,21 @@ public Task> GetAll(string owner, string name, int numbe /// The issue id public Task> GetAll(long repositoryId, int number) { - return ApiConnection.GetAll(ApiUrls.IssueReactions(repositoryId, number), AcceptHeaders.ReactionsPreview); + return GetAll(repositoryId, number, ApiOptions.None); + } + + /// + /// Get all reactions for a specified Issue + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-an-issue + /// The Id of the repository + /// The issue id + /// Options for changing the API response + public Task> GetAll(long repositoryId, int number, ApiOptions options) + { + Ensure.ArgumentNotNull(options, nameof(options)); + + return ApiConnection.GetAll(ApiUrls.IssueReactions(repositoryId, number), null, AcceptHeaders.ReactionsPreview, options); } /// diff --git a/Octokit/Clients/IssuesEventsClient.cs b/Octokit/Clients/IssuesEventsClient.cs index d27f92e34d..6f9f9b188f 100644 --- a/Octokit/Clients/IssuesEventsClient.cs +++ b/Octokit/Clients/IssuesEventsClient.cs @@ -149,13 +149,13 @@ public Task> GetAllForRepository(long repositoryId, Ap /// /// The owner of the repository /// The name of the repository - /// The event id - public Task Get(string owner, string name, int number) + /// The event id + public Task Get(string owner, string name, long eventId) { Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); - return ApiConnection.Get(ApiUrls.IssuesEvent(owner, name, number)); + return ApiConnection.Get(ApiUrls.IssuesEvent(owner, name, eventId)); } /// @@ -165,10 +165,10 @@ public Task Get(string owner, string name, int number) /// http://developer.github.com/v3/issues/events/#get-a-single-event /// /// The Id of the repository - /// The event id - public Task Get(long repositoryId, int number) + /// The event id + public Task Get(long repositoryId, long eventId) { - return ApiConnection.Get(ApiUrls.IssuesEvent(repositoryId, number)); + return ApiConnection.Get(ApiUrls.IssuesEvent(repositoryId, eventId)); } } } \ No newline at end of file diff --git a/Octokit/Clients/MigrationsClient.cs b/Octokit/Clients/MigrationsClient.cs index d4475207c7..659eef8348 100644 --- a/Octokit/Clients/MigrationsClient.cs +++ b/Octokit/Clients/MigrationsClient.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace Octokit @@ -47,13 +48,28 @@ public async Task Start(string org, StartMigrationRequest migration) /// /// The organization of which to list migrations. /// List of most recent s. - public async Task> GetAll(string org) + public async Task> GetAll(string org) + { + return await GetAll(org, ApiOptions.None); + } + + /// + /// Gets the list of the most recent migrations of the the organization. + /// + /// + /// https://developer.github.com/v3/migration/migrations/#get-a-list-of-migrations + /// + /// The organization of which to list migrations. + /// Options for changing the API response + /// List of most recent s. + public async Task> GetAll(string org, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); + Ensure.ArgumentNotNull(options, nameof(options)); var endpoint = ApiUrls.EnterpriseMigrations(org); - return await ApiConnection.Get>(endpoint, null, AcceptHeaders.MigrationsApiPreview).ConfigureAwait(false); + return await ApiConnection.GetAll(endpoint, null, AcceptHeaders.MigrationsApiPreview, options).ConfigureAwait(false); } /// diff --git a/Octokit/Clients/OrganizationMembersClient.cs b/Octokit/Clients/OrganizationMembersClient.cs index e735bbcb26..8f13526eaa 100644 --- a/Octokit/Clients/OrganizationMembersClient.cs +++ b/Octokit/Clients/OrganizationMembersClient.cs @@ -37,6 +37,14 @@ public enum OrganizationMembersRole Member } + public enum MembershipRole + { + [Parameter(Value = "admin")] + Admin, + [Parameter(Value = "member")] + Member + } + /// /// A client for GitHub's Organization Members API. /// @@ -428,7 +436,7 @@ public async Task Publicize(string org, string user) /// Make the authenticated user's organization membership private. /// /// - /// This method requries authentication. + /// This method requires authentication. /// See the API documentation /// for more information. /// @@ -443,6 +451,69 @@ public Task Conceal(string org, string user) return ApiConnection.Delete(ApiUrls.OrganizationMembership(org, user)); } + /// + /// Get a user's membership with an organization. + /// + /// + /// This method requires authentication. + /// The authenticated user must be an organization member. + /// See the API documentation + /// for more information. + /// + /// The login for the organization + /// The login for the user + /// + public Task GetOrganizationMembership(string org, string user) + { + Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); + Ensure.ArgumentNotNullOrEmptyString(user, nameof(user)); + + return ApiConnection.Get(ApiUrls.OrganizationMemberships(org, user)); + } + + /// + /// Add a user to the organization or update the user's role withing the organization. + /// + /// + /// This method requires authentication. + /// The authenticated user must be an organization owner. + /// See the API documentation + /// for more information. + /// + /// The login for the organization + /// The login for the user + /// An instance describing the + /// changes to make to the user's organization membership + /// + public Task AddOrUpdateOrganizationMembership(string org, string user, OrganizationMembershipUpdate addOrUpdateRequest) + { + Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); + Ensure.ArgumentNotNullOrEmptyString(user, nameof(user)); + Ensure.ArgumentNotNull(addOrUpdateRequest, nameof(addOrUpdateRequest)); + + return ApiConnection.Put(ApiUrls.OrganizationMemberships(org, user), addOrUpdateRequest); + } + + /// + /// Remove a user's membership with an organization. + /// + /// + /// This method requires authentication. + /// The authenticated user must be an organization owner. + /// See the API documentation + /// for more information. + /// + /// The login for the organization + /// The login for the user + /// + public Task RemoveOrganizationMembership(string org, string user) + { + Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); + Ensure.ArgumentNotNullOrEmptyString(user, nameof(user)); + + return ApiConnection.Delete(ApiUrls.OrganizationMemberships(org, user)); + } + /// /// List all pending invitations for the organization. /// diff --git a/Octokit/Clients/ProjectsClient.cs b/Octokit/Clients/ProjectsClient.cs index 5afd714461..6487c3a3ea 100644 --- a/Octokit/Clients/ProjectsClient.cs +++ b/Octokit/Clients/ProjectsClient.cs @@ -148,7 +148,7 @@ public Task> GetAllForRepository(long repositoryId, Proje /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization public Task> GetAllForOrganization(string organization) { return GetAllForOrganization(organization, ApiOptions.None); @@ -160,7 +160,7 @@ public Task> GetAllForOrganization(string organization) /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization /// Options for changing the API response public Task> GetAllForOrganization(string organization, ApiOptions options) { @@ -177,7 +177,7 @@ public Task> GetAllForOrganization(string organization, A /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization /// Used to filter the list of projects returned public Task> GetAllForOrganization(string organization, ProjectRequest request) { @@ -193,7 +193,7 @@ public Task> GetAllForOrganization(string organization, P /// /// See the API documentation for more information. /// - /// The name of the organziation + /// The name of the organization /// Used to filter the list of projects returned /// Options for changing the API response public Task> GetAllForOrganization(string organization, ProjectRequest request, ApiOptions options) diff --git a/Octokit/Clients/PullRequestReviewCommentReactionsClient.cs b/Octokit/Clients/PullRequestReviewCommentReactionsClient.cs index 251d9acdd0..5af9c2ba0b 100644 --- a/Octokit/Clients/PullRequestReviewCommentReactionsClient.cs +++ b/Octokit/Clients/PullRequestReviewCommentReactionsClient.cs @@ -24,11 +24,25 @@ public PullRequestReviewCommentReactionsClient(IApiConnection apiConnection) /// The name of the repository /// The comment id public Task> GetAll(string owner, string name, int number) + { + return GetAll(owner, name, number, ApiOptions.None); + } + + /// + /// Get all reactions for a specified Pull Request Review Comment. + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-pull-request-review-comment + /// The owner of the repository + /// The name of the repository + /// The comment id + /// Options for changing the API response + public Task> GetAll(string owner, string name, int number, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(options, nameof(options)); - return ApiConnection.GetAll(ApiUrls.PullRequestReviewCommentReaction(owner, name, number), AcceptHeaders.ReactionsPreview); + return ApiConnection.GetAll(ApiUrls.PullRequestReviewCommentReaction(owner, name, number), null, AcceptHeaders.ReactionsPreview, options); } /// @@ -39,7 +53,21 @@ public Task> GetAll(string owner, string name, int numbe /// The comment id public Task> GetAll(long repositoryId, int number) { - return ApiConnection.GetAll(ApiUrls.PullRequestReviewCommentReaction(repositoryId, number), AcceptHeaders.ReactionsPreview); + return GetAll(repositoryId, number, ApiOptions.None); + } + + /// + /// Get all reactions for a specified Pull Request Review Comment. + /// + /// https://developer.github.com/v3/reactions/#list-reactions-for-a-pull-request-review-comment + /// The Id of the repository + /// The comment id + /// Options for changing the API response + public Task> GetAll(long repositoryId, int number, ApiOptions options) + { + Ensure.ArgumentNotNull(options, nameof(options)); + + return ApiConnection.GetAll(ApiUrls.PullRequestReviewCommentReaction(repositoryId, number), null, AcceptHeaders.ReactionsPreview, options); } /// diff --git a/Octokit/Clients/PullRequestsClient.cs b/Octokit/Clients/PullRequestsClient.cs index 844dd8f337..91c2b5ab38 100644 --- a/Octokit/Clients/PullRequestsClient.cs +++ b/Octokit/Clients/PullRequestsClient.cs @@ -46,7 +46,7 @@ public Task Get(string owner, string name, int number) Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); - return ApiConnection.Get(ApiUrls.PullRequest(owner, name, number)); + return ApiConnection.Get(ApiUrls.PullRequest(owner, name, number), null, AcceptHeaders.DraftPullRequestApiPreview); } /// @@ -57,7 +57,7 @@ public Task Get(string owner, string name, int number) /// public Task Get(long repositoryId, int number) { - return ApiConnection.Get(ApiUrls.PullRequest(repositoryId, number)); + return ApiConnection.Get(ApiUrls.PullRequest(repositoryId, number), null, AcceptHeaders.DraftPullRequestApiPreview); } /// @@ -172,7 +172,7 @@ public Task> GetAllForRepository(string owner, string Ensure.ArgumentNotNull(options, nameof(options)); return ApiConnection.GetAll(ApiUrls.PullRequests(owner, name), - request.ToParametersDictionary(), options); + request.ToParametersDictionary(), AcceptHeaders.DraftPullRequestApiPreview, options); } /// @@ -190,7 +190,7 @@ public Task> GetAllForRepository(long repositoryId, P Ensure.ArgumentNotNull(options, nameof(options)); return ApiConnection.GetAll(ApiUrls.PullRequests(repositoryId), - request.ToParametersDictionary(), options); + request.ToParametersDictionary(), AcceptHeaders.DraftPullRequestApiPreview, options); } /// @@ -206,7 +206,7 @@ public Task Create(string owner, string name, NewPullRequest newPul Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNull(newPullRequest, nameof(newPullRequest)); - return ApiConnection.Post(ApiUrls.PullRequests(owner, name), newPullRequest); + return ApiConnection.Post(ApiUrls.PullRequests(owner, name), newPullRequest, AcceptHeaders.DraftPullRequestApiPreview); } /// @@ -219,7 +219,7 @@ public Task Create(long repositoryId, NewPullRequest newPullRequest { Ensure.ArgumentNotNull(newPullRequest, nameof(newPullRequest)); - return ApiConnection.Post(ApiUrls.PullRequests(repositoryId), newPullRequest); + return ApiConnection.Post(ApiUrls.PullRequests(repositoryId), newPullRequest, AcceptHeaders.DraftPullRequestApiPreview); } /// @@ -237,7 +237,7 @@ public Task Update(string owner, string name, int number, PullReque Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNull(pullRequestUpdate, nameof(pullRequestUpdate)); - return ApiConnection.Patch(ApiUrls.PullRequest(owner, name, number), pullRequestUpdate); + return ApiConnection.Patch(ApiUrls.PullRequest(owner, name, number), pullRequestUpdate, AcceptHeaders.DraftPullRequestApiPreview); } /// @@ -252,7 +252,7 @@ public Task Update(long repositoryId, int number, PullRequestUpdate { Ensure.ArgumentNotNull(pullRequestUpdate, nameof(pullRequestUpdate)); - return ApiConnection.Patch(ApiUrls.PullRequest(repositoryId, number), pullRequestUpdate); + return ApiConnection.Patch(ApiUrls.PullRequest(repositoryId, number), pullRequestUpdate, AcceptHeaders.DraftPullRequestApiPreview); } /// diff --git a/Octokit/Clients/RepoCollaboratorsClient.cs b/Octokit/Clients/RepoCollaboratorsClient.cs index fd3afe2a9a..6b1e1e8463 100644 --- a/Octokit/Clients/RepoCollaboratorsClient.cs +++ b/Octokit/Clients/RepoCollaboratorsClient.cs @@ -66,7 +66,7 @@ public Task> GetAll(string owner, string name, ApiOptions op Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNull(options, nameof(options)); - return ApiConnection.GetAll(ApiUrls.RepoCollaborators(owner, name), options); + return GetAll(owner, name, new RepositoryCollaboratorListRequest(), options); } /// @@ -82,7 +82,82 @@ public Task> GetAll(long repositoryId, ApiOptions options) { Ensure.ArgumentNotNull(options, nameof(options)); - return ApiConnection.GetAll(ApiUrls.RepoCollaborators(repositoryId), options); + return GetAll(repositoryId, new RepositoryCollaboratorListRequest(), options); + } + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Used to request and filter a list of repository collaborators + /// Thrown when a general API error occurs. + public Task> GetAll(string owner, string name, RepositoryCollaboratorListRequest request) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAll(owner, name, request, ApiOptions.None); + } + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the repository + /// Used to request and filter a list of repository collaborators + /// Thrown when a general API error occurs. + public Task> GetAll(long repositoryId, RepositoryCollaboratorListRequest request) + { + Ensure.ArgumentNotNull(request, nameof(request)); + + return GetAll(repositoryId, request, ApiOptions.None); + } + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The owner of the repository + /// The name of the repository + /// Used to request and filter a list of repository collaborators + /// Options for changing the API response + /// Thrown when a general API error occurs. + public Task> GetAll(string owner, string name, RepositoryCollaboratorListRequest request, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + + return ApiConnection.GetAll(ApiUrls.RepoCollaborators(owner, name), request.ToParametersDictionary(), AcceptHeaders.NestedTeamsPreview, options); + + } + + /// + /// Gets all the collaborators on a repository. + /// + /// + /// See the API documentation for more information. + /// + /// The id of the repository + /// Used to request and filter a list of repository collaborators + /// Options for changing the API response + /// Thrown when a general API error occurs. + public Task> GetAll(long repositoryId, RepositoryCollaboratorListRequest request, ApiOptions options) + { + Ensure.ArgumentNotNull(request, nameof(request)); + Ensure.ArgumentNotNull(options, nameof(options)); + + return ApiConnection.GetAll(ApiUrls.RepoCollaborators(repositoryId), request.ToParametersDictionary(), AcceptHeaders.NestedTeamsPreview, options); } /// diff --git a/Octokit/Clients/RepositoriesClient.cs b/Octokit/Clients/RepositoriesClient.cs index b31065710e..20574b12b6 100644 --- a/Octokit/Clients/RepositoriesClient.cs +++ b/Octokit/Clients/RepositoriesClient.cs @@ -471,6 +471,8 @@ public Task> GetAllForOrg(string organization, ApiOpti /// /// Client for GitHub's Repository Statistics API + /// Note that the GitHub API uses caching on these endpoints, + /// see a word about caching for more details. /// /// /// See the Statistics API documentation for more details diff --git a/Octokit/Clients/RepositoryBranchesClient.cs b/Octokit/Clients/RepositoryBranchesClient.cs index b0e50d8246..46e1bf6883 100644 --- a/Octokit/Clients/RepositoryBranchesClient.cs +++ b/Octokit/Clients/RepositoryBranchesClient.cs @@ -13,6 +13,8 @@ namespace Octokit /// public class RepositoryBranchesClient : ApiClient, IRepositoryBranchesClient { + private string protectedBranchesPreviewHeaders = AcceptHeaders.Concat(AcceptHeaders.ProtectedBranchesApiPreview, AcceptHeaders.ProtectedBranchesRequiredApprovingApiPreview); + /// /// Initializes a new GitHub Repository Branches API client. /// @@ -66,7 +68,7 @@ public Task> GetAll(string owner, string name, ApiOptions Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNull(options, nameof(options)); - return ApiConnection.GetAll(ApiUrls.RepoBranches(owner, name), null, AcceptHeaders.ProtectedBranchesApiPreview, options); + return ApiConnection.GetAll(ApiUrls.RepoBranches(owner, name), null, protectedBranchesPreviewHeaders, options); } /// @@ -81,7 +83,7 @@ public Task> GetAll(long repositoryId, ApiOptions options) { Ensure.ArgumentNotNull(options, nameof(options)); - return ApiConnection.GetAll(ApiUrls.RepoBranches(repositoryId), null, AcceptHeaders.ProtectedBranchesApiPreview, options); + return ApiConnection.GetAll(ApiUrls.RepoBranches(repositoryId), null, protectedBranchesPreviewHeaders, options); } /// @@ -99,7 +101,7 @@ public Task Get(string owner, string name, string branch) Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get(ApiUrls.RepoBranch(owner, name, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get(ApiUrls.RepoBranch(owner, name, branch), null, protectedBranchesPreviewHeaders); } /// @@ -114,7 +116,7 @@ public Task Get(long repositoryId, string branch) { Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get(ApiUrls.RepoBranch(repositoryId, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get(ApiUrls.RepoBranch(repositoryId, branch), null, protectedBranchesPreviewHeaders); } /// @@ -132,7 +134,7 @@ public Task GetBranchProtection(string owner, string n Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get(ApiUrls.RepoBranchProtection(owner, name, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get(ApiUrls.RepoBranchProtection(owner, name, branch), null, protectedBranchesPreviewHeaders); } /// @@ -147,7 +149,7 @@ public Task GetBranchProtection(long repositoryId, str { Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get(ApiUrls.RepoBranchProtection(repositoryId, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get(ApiUrls.RepoBranchProtection(repositoryId, branch), null, protectedBranchesPreviewHeaders); } /// @@ -167,7 +169,7 @@ public Task UpdateBranchProtection(string owner, strin Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(update, nameof(update)); - return ApiConnection.Put(ApiUrls.RepoBranchProtection(owner, name, branch), update, null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Put(ApiUrls.RepoBranchProtection(owner, name, branch), update, null, protectedBranchesPreviewHeaders); } /// @@ -184,7 +186,7 @@ public Task UpdateBranchProtection(long repositoryId, Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(update, nameof(update)); - return ApiConnection.Put(ApiUrls.RepoBranchProtection(repositoryId, branch), update, null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Put(ApiUrls.RepoBranchProtection(repositoryId, branch), update, null, protectedBranchesPreviewHeaders); } /// @@ -205,7 +207,7 @@ public async Task DeleteBranchProtection(string owner, string name, string var endpoint = ApiUrls.RepoBranchProtection(owner, name, branch); try { - var httpStatusCode = await Connection.Delete(endpoint, null, AcceptHeaders.ProtectedBranchesApiPreview).ConfigureAwait(false); + var httpStatusCode = await Connection.Delete(endpoint, null, protectedBranchesPreviewHeaders).ConfigureAwait(false); return httpStatusCode == HttpStatusCode.NoContent; } catch (NotFoundException) @@ -229,7 +231,7 @@ public async Task DeleteBranchProtection(long repositoryId, string branch) var endpoint = ApiUrls.RepoBranchProtection(repositoryId, branch); try { - var httpStatusCode = await Connection.Delete(endpoint, null, AcceptHeaders.ProtectedBranchesApiPreview).ConfigureAwait(false); + var httpStatusCode = await Connection.Delete(endpoint, null, protectedBranchesPreviewHeaders).ConfigureAwait(false); return httpStatusCode == HttpStatusCode.NoContent; } catch (NotFoundException) @@ -253,7 +255,7 @@ public Task GetRequiredStatusChecks(string Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get(ApiUrls.RepoRequiredStatusChecks(owner, name, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get(ApiUrls.RepoRequiredStatusChecks(owner, name, branch), null, protectedBranchesPreviewHeaders); } /// @@ -268,7 +270,7 @@ public Task GetRequiredStatusChecks(long r { Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get(ApiUrls.RepoRequiredStatusChecks(repositoryId, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get(ApiUrls.RepoRequiredStatusChecks(repositoryId, branch), null, protectedBranchesPreviewHeaders); } /// @@ -288,7 +290,7 @@ public Task UpdateRequiredStatusChecks(str Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(update, nameof(update)); - return ApiConnection.Patch(ApiUrls.RepoRequiredStatusChecks(owner, name, branch), update, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Patch(ApiUrls.RepoRequiredStatusChecks(owner, name, branch), update, protectedBranchesPreviewHeaders); } /// @@ -305,7 +307,7 @@ public Task UpdateRequiredStatusChecks(lon Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(update, nameof(update)); - return ApiConnection.Patch(ApiUrls.RepoRequiredStatusChecks(repositoryId, branch), update, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Patch(ApiUrls.RepoRequiredStatusChecks(repositoryId, branch), update, protectedBranchesPreviewHeaders); } /// @@ -327,7 +329,7 @@ public async Task DeleteRequiredStatusChecks(string owner, string name, st try { - var httpStatusCode = await Connection.Delete(endpoint, null, AcceptHeaders.ProtectedBranchesApiPreview).ConfigureAwait(false); + var httpStatusCode = await Connection.Delete(endpoint, null, protectedBranchesPreviewHeaders).ConfigureAwait(false); return httpStatusCode == HttpStatusCode.NoContent; } catch (NotFoundException) @@ -352,7 +354,7 @@ public async Task DeleteRequiredStatusChecks(long repositoryId, string bra try { - var httpStatusCode = await Connection.Delete(endpoint, null, AcceptHeaders.ProtectedBranchesApiPreview).ConfigureAwait(false); + var httpStatusCode = await Connection.Delete(endpoint, null, protectedBranchesPreviewHeaders).ConfigureAwait(false); return httpStatusCode == HttpStatusCode.NoContent; } catch (NotFoundException) @@ -376,7 +378,7 @@ public Task> GetAllRequiredStatusChecksContexts(string own Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get>(ApiUrls.RepoRequiredStatusChecksContexts(owner, name, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get>(ApiUrls.RepoRequiredStatusChecksContexts(owner, name, branch), null, protectedBranchesPreviewHeaders); } /// @@ -391,7 +393,7 @@ public Task> GetAllRequiredStatusChecksContexts(long repos { Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get>(ApiUrls.RepoRequiredStatusChecksContexts(repositoryId, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get>(ApiUrls.RepoRequiredStatusChecksContexts(repositoryId, branch), null, protectedBranchesPreviewHeaders); } /// @@ -411,7 +413,7 @@ public Task> UpdateRequiredStatusChecksContexts(string own Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(contexts, nameof(contexts)); - return ApiConnection.Put>(ApiUrls.RepoRequiredStatusChecksContexts(owner, name, branch), contexts, null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Put>(ApiUrls.RepoRequiredStatusChecksContexts(owner, name, branch), contexts, null, protectedBranchesPreviewHeaders); } /// @@ -428,7 +430,7 @@ public Task> UpdateRequiredStatusChecksContexts(long repos Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(contexts, nameof(contexts)); - return ApiConnection.Put>(ApiUrls.RepoRequiredStatusChecksContexts(repositoryId, branch), contexts, null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Put>(ApiUrls.RepoRequiredStatusChecksContexts(repositoryId, branch), contexts, null, protectedBranchesPreviewHeaders); } /// @@ -448,7 +450,7 @@ public Task> AddRequiredStatusChecksContexts(string owner, Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(contexts, nameof(contexts)); - return ApiConnection.Post>(ApiUrls.RepoRequiredStatusChecksContexts(owner, name, branch), contexts, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Post>(ApiUrls.RepoRequiredStatusChecksContexts(owner, name, branch), contexts, protectedBranchesPreviewHeaders); } /// @@ -465,7 +467,7 @@ public Task> AddRequiredStatusChecksContexts(long reposito Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(contexts, nameof(contexts)); - return ApiConnection.Post>(ApiUrls.RepoRequiredStatusChecksContexts(repositoryId, branch), contexts, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Post>(ApiUrls.RepoRequiredStatusChecksContexts(repositoryId, branch), contexts, protectedBranchesPreviewHeaders); } /// @@ -485,7 +487,7 @@ public Task> DeleteRequiredStatusChecksContexts(string own Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(contexts, nameof(contexts)); - return ApiConnection.Delete>(ApiUrls.RepoRequiredStatusChecksContexts(owner, name, branch), contexts, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Delete>(ApiUrls.RepoRequiredStatusChecksContexts(owner, name, branch), contexts, protectedBranchesPreviewHeaders); } /// @@ -502,7 +504,7 @@ public Task> DeleteRequiredStatusChecksContexts(long repos Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(contexts, nameof(contexts)); - return ApiConnection.Delete>(ApiUrls.RepoRequiredStatusChecksContexts(repositoryId, branch), contexts, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Delete>(ApiUrls.RepoRequiredStatusChecksContexts(repositoryId, branch), contexts, protectedBranchesPreviewHeaders); } /// @@ -520,7 +522,7 @@ public Task GetReviewEnforcement(string owner, Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get(ApiUrls.RepoProtectedBranchReviewEnforcement(owner, name, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get(ApiUrls.RepoProtectedBranchReviewEnforcement(owner, name, branch), null, protectedBranchesPreviewHeaders); } /// @@ -535,7 +537,7 @@ public Task GetReviewEnforcement(long repositor { Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get(ApiUrls.RepoProtectedBranchReviewEnforcement(repositoryId, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get(ApiUrls.RepoProtectedBranchReviewEnforcement(repositoryId, branch), null, protectedBranchesPreviewHeaders); } /// @@ -555,7 +557,7 @@ public Task UpdateReviewEnforcement(string owne Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(update, nameof(update)); - return ApiConnection.Patch(ApiUrls.RepoProtectedBranchReviewEnforcement(owner, name, branch), update, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Patch(ApiUrls.RepoProtectedBranchReviewEnforcement(owner, name, branch), update, protectedBranchesPreviewHeaders); } /// @@ -572,7 +574,7 @@ public Task UpdateReviewEnforcement(long reposi Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(update, nameof(update)); - return ApiConnection.Patch(ApiUrls.RepoProtectedBranchReviewEnforcement(repositoryId, branch), update, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Patch(ApiUrls.RepoProtectedBranchReviewEnforcement(repositoryId, branch), update, protectedBranchesPreviewHeaders); } /// @@ -594,7 +596,7 @@ public async Task RemoveReviewEnforcement(string owner, string name, strin try { - var httpStatusCode = await Connection.Delete(endpoint, null, AcceptHeaders.ProtectedBranchesApiPreview).ConfigureAwait(false); + var httpStatusCode = await Connection.Delete(endpoint, null, protectedBranchesPreviewHeaders).ConfigureAwait(false); return httpStatusCode == HttpStatusCode.NoContent; } catch (NotFoundException) @@ -619,7 +621,7 @@ public async Task RemoveReviewEnforcement(long repositoryId, string branch try { - var httpStatusCode = await Connection.Delete(endpoint, null, AcceptHeaders.ProtectedBranchesApiPreview).ConfigureAwait(false); + var httpStatusCode = await Connection.Delete(endpoint, null, protectedBranchesPreviewHeaders).ConfigureAwait(false); return httpStatusCode == HttpStatusCode.NoContent; } catch (NotFoundException) @@ -643,7 +645,7 @@ public Task GetAdminEnforcement(string owner, string name, string Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get(ApiUrls.RepoProtectedBranchAdminEnforcement(owner, name, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get(ApiUrls.RepoProtectedBranchAdminEnforcement(owner, name, branch), null, protectedBranchesPreviewHeaders); } /// @@ -658,7 +660,7 @@ public Task GetAdminEnforcement(long repositoryId, string branch) { Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get(ApiUrls.RepoProtectedBranchAdminEnforcement(repositoryId, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get(ApiUrls.RepoProtectedBranchAdminEnforcement(repositoryId, branch), null, protectedBranchesPreviewHeaders); } /// @@ -676,7 +678,7 @@ public Task AddAdminEnforcement(string owner, string name, string Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Post(ApiUrls.RepoProtectedBranchAdminEnforcement(owner, name, branch), new object(), AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Post(ApiUrls.RepoProtectedBranchAdminEnforcement(owner, name, branch), new object(), protectedBranchesPreviewHeaders); } /// @@ -691,7 +693,7 @@ public Task AddAdminEnforcement(long repositoryId, string branch) { Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Post(ApiUrls.RepoProtectedBranchAdminEnforcement(repositoryId, branch), new object(), AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Post(ApiUrls.RepoProtectedBranchAdminEnforcement(repositoryId, branch), new object(), protectedBranchesPreviewHeaders); } /// @@ -713,7 +715,7 @@ public async Task RemoveAdminEnforcement(string owner, string name, string try { - var httpStatusCode = await Connection.Delete(endpoint, null, AcceptHeaders.ProtectedBranchesApiPreview).ConfigureAwait(false); + var httpStatusCode = await Connection.Delete(endpoint, null, protectedBranchesPreviewHeaders).ConfigureAwait(false); return httpStatusCode == HttpStatusCode.NoContent; } catch (NotFoundException) @@ -738,7 +740,7 @@ public async Task RemoveAdminEnforcement(long repositoryId, string branch) try { - var httpStatusCode = await Connection.Delete(endpoint, null, AcceptHeaders.ProtectedBranchesApiPreview).ConfigureAwait(false); + var httpStatusCode = await Connection.Delete(endpoint, null, protectedBranchesPreviewHeaders).ConfigureAwait(false); return httpStatusCode == HttpStatusCode.NoContent; } catch (NotFoundException) @@ -762,7 +764,7 @@ public Task GetProtectedBranchRestrictions(str Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get(ApiUrls.RepoRestrictions(owner, name, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get(ApiUrls.RepoRestrictions(owner, name, branch), null, protectedBranchesPreviewHeaders); } /// @@ -777,7 +779,7 @@ public Task GetProtectedBranchRestrictions(lon { Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get(ApiUrls.RepoRestrictions(repositoryId, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get(ApiUrls.RepoRestrictions(repositoryId, branch), null, protectedBranchesPreviewHeaders); } /// @@ -799,7 +801,7 @@ public async Task DeleteProtectedBranchRestrictions(string owner, string n try { - var httpStatusCode = await Connection.Delete(endpoint, null, AcceptHeaders.ProtectedBranchesApiPreview).ConfigureAwait(false); + var httpStatusCode = await Connection.Delete(endpoint, null, protectedBranchesPreviewHeaders).ConfigureAwait(false); return httpStatusCode == HttpStatusCode.NoContent; } catch (NotFoundException) @@ -824,7 +826,7 @@ public async Task DeleteProtectedBranchRestrictions(long repositoryId, str try { - var httpStatusCode = await Connection.Delete(endpoint, null, AcceptHeaders.ProtectedBranchesApiPreview).ConfigureAwait(false); + var httpStatusCode = await Connection.Delete(endpoint, null, protectedBranchesPreviewHeaders).ConfigureAwait(false); return httpStatusCode == HttpStatusCode.NoContent; } catch (NotFoundException) @@ -848,7 +850,7 @@ public Task> GetAllProtectedBranchTeamRestrictions(string ow Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get>(ApiUrls.RepoRestrictionsTeams(owner, name, branch), null, AcceptHeaders.Concat(AcceptHeaders.ProtectedBranchesApiPreview, AcceptHeaders.NestedTeamsPreview)); + return ApiConnection.Get>(ApiUrls.RepoRestrictionsTeams(owner, name, branch), null, AcceptHeaders.Concat(protectedBranchesPreviewHeaders, AcceptHeaders.NestedTeamsPreview)); } /// @@ -863,7 +865,7 @@ public Task> GetAllProtectedBranchTeamRestrictions(long repo { Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get>(ApiUrls.RepoRestrictionsTeams(repositoryId, branch), null, AcceptHeaders.Concat(AcceptHeaders.ProtectedBranchesApiPreview, AcceptHeaders.NestedTeamsPreview)); + return ApiConnection.Get>(ApiUrls.RepoRestrictionsTeams(repositoryId, branch), null, AcceptHeaders.Concat(protectedBranchesPreviewHeaders, AcceptHeaders.NestedTeamsPreview)); } /// @@ -883,7 +885,7 @@ public Task> UpdateProtectedBranchTeamRestrictions(string ow Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(teams, nameof(teams)); - return ApiConnection.Put>(ApiUrls.RepoRestrictionsTeams(owner, name, branch), teams, null, AcceptHeaders.Concat(AcceptHeaders.ProtectedBranchesApiPreview, AcceptHeaders.NestedTeamsPreview)); + return ApiConnection.Put>(ApiUrls.RepoRestrictionsTeams(owner, name, branch), teams, null, AcceptHeaders.Concat(protectedBranchesPreviewHeaders, AcceptHeaders.NestedTeamsPreview)); } /// @@ -900,7 +902,7 @@ public Task> UpdateProtectedBranchTeamRestrictions(long repo Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(teams, nameof(teams)); - return ApiConnection.Put>(ApiUrls.RepoRestrictionsTeams(repositoryId, branch), teams, null, AcceptHeaders.Concat(AcceptHeaders.ProtectedBranchesApiPreview, AcceptHeaders.NestedTeamsPreview)); + return ApiConnection.Put>(ApiUrls.RepoRestrictionsTeams(repositoryId, branch), teams, null, AcceptHeaders.Concat(protectedBranchesPreviewHeaders, AcceptHeaders.NestedTeamsPreview)); } /// @@ -920,7 +922,7 @@ public Task> AddProtectedBranchTeamRestrictions(string owner Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(teams, nameof(teams)); - return ApiConnection.Post>(ApiUrls.RepoRestrictionsTeams(owner, name, branch), teams, AcceptHeaders.Concat(AcceptHeaders.ProtectedBranchesApiPreview, AcceptHeaders.NestedTeamsPreview)); + return ApiConnection.Post>(ApiUrls.RepoRestrictionsTeams(owner, name, branch), teams, AcceptHeaders.Concat(protectedBranchesPreviewHeaders, AcceptHeaders.NestedTeamsPreview)); } /// @@ -937,7 +939,7 @@ public Task> AddProtectedBranchTeamRestrictions(long reposit Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(teams, nameof(teams)); - return ApiConnection.Post>(ApiUrls.RepoRestrictionsTeams(repositoryId, branch), teams, AcceptHeaders.Concat(AcceptHeaders.ProtectedBranchesApiPreview, AcceptHeaders.NestedTeamsPreview)); + return ApiConnection.Post>(ApiUrls.RepoRestrictionsTeams(repositoryId, branch), teams, AcceptHeaders.Concat(protectedBranchesPreviewHeaders, AcceptHeaders.NestedTeamsPreview)); } /// @@ -957,7 +959,7 @@ public Task> DeleteProtectedBranchTeamRestrictions(string ow Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(teams, nameof(teams)); - return ApiConnection.Delete>(ApiUrls.RepoRestrictionsTeams(owner, name, branch), teams, AcceptHeaders.Concat(AcceptHeaders.ProtectedBranchesApiPreview, AcceptHeaders.NestedTeamsPreview)); + return ApiConnection.Delete>(ApiUrls.RepoRestrictionsTeams(owner, name, branch), teams, AcceptHeaders.Concat(protectedBranchesPreviewHeaders, AcceptHeaders.NestedTeamsPreview)); } /// @@ -974,7 +976,7 @@ public Task> DeleteProtectedBranchTeamRestrictions(long repo Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(teams, nameof(teams)); - return ApiConnection.Delete>(ApiUrls.RepoRestrictionsTeams(repositoryId, branch), teams, AcceptHeaders.Concat(AcceptHeaders.ProtectedBranchesApiPreview, AcceptHeaders.NestedTeamsPreview)); + return ApiConnection.Delete>(ApiUrls.RepoRestrictionsTeams(repositoryId, branch), teams, AcceptHeaders.Concat(protectedBranchesPreviewHeaders, AcceptHeaders.NestedTeamsPreview)); } /// @@ -992,7 +994,7 @@ public Task> GetAllProtectedBranchUserRestrictions(string ow Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get>(ApiUrls.RepoRestrictionsUsers(owner, name, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get>(ApiUrls.RepoRestrictionsUsers(owner, name, branch), null, protectedBranchesPreviewHeaders); } /// @@ -1007,7 +1009,7 @@ public Task> GetAllProtectedBranchUserRestrictions(long repo { Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); - return ApiConnection.Get>(ApiUrls.RepoRestrictionsUsers(repositoryId, branch), null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Get>(ApiUrls.RepoRestrictionsUsers(repositoryId, branch), null, protectedBranchesPreviewHeaders); } /// @@ -1027,7 +1029,7 @@ public Task> UpdateProtectedBranchUserRestrictions(string ow Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(users, nameof(users)); - return ApiConnection.Put>(ApiUrls.RepoRestrictionsUsers(owner, name, branch), users, null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Put>(ApiUrls.RepoRestrictionsUsers(owner, name, branch), users, null, protectedBranchesPreviewHeaders); } /// @@ -1044,7 +1046,7 @@ public Task> UpdateProtectedBranchUserRestrictions(long repo Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(users, nameof(users)); - return ApiConnection.Put>(ApiUrls.RepoRestrictionsUsers(repositoryId, branch), users, null, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Put>(ApiUrls.RepoRestrictionsUsers(repositoryId, branch), users, null, protectedBranchesPreviewHeaders); } /// @@ -1064,7 +1066,7 @@ public Task> AddProtectedBranchUserRestrictions(string owner Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(users, nameof(users)); - return ApiConnection.Post>(ApiUrls.RepoRestrictionsUsers(owner, name, branch), users, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Post>(ApiUrls.RepoRestrictionsUsers(owner, name, branch), users, protectedBranchesPreviewHeaders); } /// @@ -1081,7 +1083,7 @@ public Task> AddProtectedBranchUserRestrictions(long reposit Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(users, nameof(users)); - return ApiConnection.Post>(ApiUrls.RepoRestrictionsUsers(repositoryId, branch), users, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Post>(ApiUrls.RepoRestrictionsUsers(repositoryId, branch), users, protectedBranchesPreviewHeaders); } /// @@ -1101,7 +1103,7 @@ public Task> DeleteProtectedBranchUserRestrictions(string ow Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(users, nameof(users)); - return ApiConnection.Delete>(ApiUrls.RepoRestrictionsUsers(owner, name, branch), users, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Delete>(ApiUrls.RepoRestrictionsUsers(owner, name, branch), users, protectedBranchesPreviewHeaders); } /// @@ -1118,7 +1120,7 @@ public Task> DeleteProtectedBranchUserRestrictions(long repo Ensure.ArgumentNotNullOrEmptyString(branch, nameof(branch)); Ensure.ArgumentNotNull(users, nameof(users)); - return ApiConnection.Delete>(ApiUrls.RepoRestrictionsUsers(repositoryId, branch), users, AcceptHeaders.ProtectedBranchesApiPreview); + return ApiConnection.Delete>(ApiUrls.RepoRestrictionsUsers(repositoryId, branch), users, protectedBranchesPreviewHeaders); } } } diff --git a/Octokit/Clients/StatisticsClient.cs b/Octokit/Clients/StatisticsClient.cs index 99a190778e..057e890071 100644 --- a/Octokit/Clients/StatisticsClient.cs +++ b/Octokit/Clients/StatisticsClient.cs @@ -7,6 +7,8 @@ namespace Octokit { /// /// A client for GitHub's Repository Statistics API. + /// Note that the GitHub API uses caching on these endpoints, + /// see a word about caching for more details. /// /// /// See the Repository Statistics API documentation for more information. diff --git a/Octokit/Exceptions/AbuseException.cs b/Octokit/Exceptions/AbuseException.cs index 624559e95a..8fceec4f3a 100644 --- a/Octokit/Exceptions/AbuseException.cs +++ b/Octokit/Exceptions/AbuseException.cs @@ -11,7 +11,7 @@ namespace Octokit { /// /// Represents a subset of the HTTP 403 - Forbidden response returned from the API when the forbidden response is related to an abuse detection mechanism. - /// Containts the amount of seconds after which it's safe to retry the request. + /// Contains the amount of seconds after which it's safe to retry the request. /// #if !NO_SERIALIZABLE [Serializable] diff --git a/Octokit/Exceptions/ApiException.cs b/Octokit/Exceptions/ApiException.cs index d7b49d8540..4dd08d27e4 100644 --- a/Octokit/Exceptions/ApiException.cs +++ b/Octokit/Exceptions/ApiException.cs @@ -109,7 +109,7 @@ public override string Message } /// - /// The HTTP status code associated with the repsonse + /// The HTTP status code associated with the response /// public HttpStatusCode StatusCode { get; private set; } diff --git a/Octokit/Exceptions/PullRequestMismatchException.cs b/Octokit/Exceptions/PullRequestMismatchException.cs index f94ab78c96..83df68cc66 100644 --- a/Octokit/Exceptions/PullRequestMismatchException.cs +++ b/Octokit/Exceptions/PullRequestMismatchException.cs @@ -20,7 +20,7 @@ namespace Octokit public class PullRequestMismatchException : ApiException { /// - /// Constructs an instace of . + /// Constructs an instance of . /// /// public PullRequestMismatchException(IResponse response) : this(response, null) diff --git a/Octokit/Helpers/AcceptHeaders.cs b/Octokit/Helpers/AcceptHeaders.cs index ec20b33b44..b03f5bc715 100644 --- a/Octokit/Helpers/AcceptHeaders.cs +++ b/Octokit/Helpers/AcceptHeaders.cs @@ -49,6 +49,8 @@ public static class AcceptHeaders public const string PullRequestReviewsApiPreview = "application/vnd.github.black-cat-preview+json"; + public const string DraftPullRequestApiPreview = "application/vnd.github.shadow-cat-preview+json"; + public const string ProjectsApiPreview = "application/vnd.github.inertia-preview+json"; public const string OrganizationMembershipPreview = "application/vnd.github.korra-preview+json"; @@ -67,6 +69,8 @@ public static class AcceptHeaders public const string DeploymentStatusesPreview = "application/vnd.github.flash-preview+json"; + public const string ProtectedBranchesRequiredApprovingApiPreview = "application/vnd.github.luke-cage-preview+json"; + /// /// Combines multiple preview headers. GitHub API supports Accept header with multiple /// values separated by comma. diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index 1b77364a74..48cf5db7e1 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -374,7 +374,7 @@ public static Uri UserInstallations() } /// - /// Returns the that returns all the repositores + /// Returns the that returns all the repositories /// /// public static Uri InstallationRepositories() @@ -622,7 +622,7 @@ public static Uri Assignees(string owner, string name) /// /// Returns the that returns a 204 if the login belongs to an assignee of the repository. - /// Otherwire returns a 404. + /// Otherwise returns a 404. /// /// The owner of the repository /// The name of the repository @@ -750,6 +750,17 @@ public static Uri OrganizationMembership(string org, string name) return "orgs/{0}/public_members/{1}".FormatUri(org, name); } + /// + /// Returns the for the organization memberships + /// + /// The name of the organization + /// The name of the user + /// + public static Uri OrganizationMemberships(string org, string name) + { + return "orgs/{0}/memberships/{1}".FormatUri(org, name); + } + /// /// Returns the for the organizations pending invitations /// @@ -827,7 +838,7 @@ public static Uri IssuesEvents(string owner, string name) /// The name of the repository /// The event id /// - public static Uri IssuesEvent(string owner, string name, int id) + public static Uri IssuesEvent(string owner, string name, long id) { return "repos/{0}/{1}/issues/events/{2}".FormatUri(owner, name, id); } @@ -1266,7 +1277,7 @@ public static Uri PullRequestFiles(string owner, string name, int number) } /// - /// Returns the for a spesific comment for the specified commit. + /// Returns the for a specific comment for the specified commit. /// /// The id of the gist /// The id of the comment @@ -2548,6 +2559,18 @@ public static Uri EnterpriseMigrationUnlockRepository(string org, int id, string return "orgs/{0}/migrations/{1}/repos/{2}/lock".FormatUri(org, id, repo); } + public static Uri EnterpriseManagementConsoleMaintenance(string managementConsolePassword, Uri baseAddress) + { + if (baseAddress != null + && baseAddress.ToString().EndsWith("/api/v3/", StringComparison.OrdinalIgnoreCase)) + { + // note: leading slash here means the /api/v3/ prefix inherited from baseAddress is ignored + return "/setup/api/maintenance?api_key={0}".FormatUri(managementConsolePassword); + } + + return "setup/api/maintenance?api_key={0}".FormatUri(managementConsolePassword); + } + public static Uri EnterpriseOrganization() { return "admin/organizations".FormatUri(); @@ -2687,11 +2710,11 @@ public static Uri Blob(long repositoryId, string reference) } /// - /// Returns the that returns a 204 if the login belongs to an assignee of the repository. Otherwire returns a 404. + /// Returns the that returns a 204 if the login belongs to an assignee of the repository. Otherwise returns a 404. /// /// The Id of the repository /// The login for the user - /// The that returns a 204 if the login belongs to an assignee of the repository. Otherwire returns a 404. + /// The that returns a 204 if the login belongs to an assignee of the repository. Otherwise returns a 404. public static Uri CheckAssignee(long repositoryId, string login) { return "repositories/{0}/assignees/{1}".FormatUri(repositoryId, login); @@ -2948,7 +2971,7 @@ public static Uri Issues(long repositoryId) /// The Id of the repository /// The event id /// The that returns the issue/pull request event and issue info for the specified event. - public static Uri IssuesEvent(long repositoryId, int id) + public static Uri IssuesEvent(long repositoryId, long id) { return "repositories/{0}/issues/events/{1}".FormatUri(repositoryId, id); } @@ -3670,7 +3693,7 @@ public static Uri RepositoryTrafficReferrers(string owner, string repo) } /// - /// Returns the for repository traffice referrers. + /// Returns the for repository traffic referrers. /// /// The id of the repository /// The for repository traffic referrers. @@ -3680,7 +3703,7 @@ public static Uri RepositoryTrafficReferrers(long repositoryId) } /// - /// Returns the for repository traffice paths. + /// Returns the for repository traffic paths. /// /// The owner of repo /// The name of repo @@ -3691,7 +3714,7 @@ public static Uri RepositoryTrafficPaths(string owner, string repo) } /// - /// Returns the for repository traffice paths. + /// Returns the for repository traffic paths. /// /// The id of the repository /// The for repository traffic paths. @@ -3701,7 +3724,7 @@ public static Uri RepositoryTrafficPaths(long repositoryId) } /// - /// Returns the for repository traffice views. + /// Returns the for repository traffic views. /// /// The owner of repo /// The name of repo @@ -3712,7 +3735,7 @@ public static Uri RepositoryTrafficViews(string owner, string repo) } /// - /// Returns the for repository traffice views. + /// Returns the for repository traffic views. /// /// The id of the repository /// The for repository traffic views. @@ -3722,7 +3745,7 @@ public static Uri RepositoryTrafficViews(long repositoryId) } /// - /// Returns the for repository traffice clones. + /// Returns the for repository traffic clones. /// /// The owner of repo /// The name of repo @@ -3733,7 +3756,7 @@ public static Uri RepositoryTrafficClones(string owner, string repo) } /// - /// Returns the for repository traffice clones. + /// Returns the for repository traffic clones. /// /// The id of the repository /// The for repository traffic clones. diff --git a/Octokit/Helpers/ReferenceExtensions.cs b/Octokit/Helpers/ReferenceExtensions.cs index fe3917b664..97c5ba8205 100644 --- a/Octokit/Helpers/ReferenceExtensions.cs +++ b/Octokit/Helpers/ReferenceExtensions.cs @@ -26,7 +26,7 @@ public static async Task CreateBranch(this IReferencesClient referenc if (branchName.StartsWith("refs/heads")) { - throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The specified branch name '{0}' appears to be a ref name and not a branch name because it starts with the string 'refs/heads'. Either specify just the branch name or use the Create method if you need to specify the full ref name", branchName), "branchName"); + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The specified branch name '{0}' appears to be a ref name and not a branch name because it starts with the string 'refs/heads'. Either specify just the branch name or use the Create method if you need to specify the full ref name", branchName), "branchName"); } var newReference = new NewReference("refs/heads/" + branchName, baseReference.Object.Sha); @@ -48,7 +48,7 @@ public static async Task CreateBranch(this IReferencesClient referenc if (branchName.StartsWith("refs/heads")) { - throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The specified branch name '{0}' appears to be a ref name and not a branch name because it starts with the string 'refs/heads'. Either specify just the branch name or use the Create method if you need to specify the full ref name", branchName), "branchName"); + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The specified branch name '{0}' appears to be a ref name and not a branch name because it starts with the string 'refs/heads'. Either specify just the branch name or use the Create method if you need to specify the full ref name", branchName), "branchName"); } var baseBranch = await referencesClient.Get(owner, name, "heads/master").ConfigureAwait(false); diff --git a/Octokit/Http/HttpClientAdapter.cs b/Octokit/Http/HttpClientAdapter.cs index 873ab75272..8b997a50ab 100644 --- a/Octokit/Http/HttpClientAdapter.cs +++ b/Octokit/Http/HttpClientAdapter.cs @@ -28,7 +28,28 @@ public HttpClientAdapter(Func getHandler) Ensure.ArgumentNotNull(getHandler, nameof(getHandler)); #if HAS_SERVICEPOINTMANAGER - ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; + // GitHub API requires TLS1.2 as of February 2018 + // + // .NET Framework before 4.6 did not enable TLS1.2 by default + // + // Even though this is an AppDomain wide setting, the decision was made for Octokit to + // ensure that TLS1.2 is enabled so that existing applications using Octokit did not need to + // make changes outside Octokit to continue to work with GitHub API + // + // *Update* + // .NET Framework 4.7 introduced a new value (SecurityProtocolType.SystemDefault = 0) + // which defers enabled protocols to operating system defaults + // If this is the current value we shouldn't do anything, as that would cause TLS1.2 to be the ONLY enabled protocol! + // + // See https://docs.microsoft.com/en-us/dotnet/api/system.net.securityprotocoltype?view=netframework-4.7 + // See https://github.com/octokit/octokit.net/issues/1914 + + // Only apply when current setting is not SystemDefault (0) added in .NET 4.7 + if ((int)ServicePointManager.SecurityProtocol != 0) + { + // Add Tls1.2 to the existing enabled protocols + ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; + } #endif _http = new HttpClient(new RedirectHandler { InnerHandler = getHandler() }); diff --git a/Octokit/Http/IApiConnection.cs b/Octokit/Http/IApiConnection.cs index 4dd711562b..616dbfead0 100644 --- a/Octokit/Http/IApiConnection.cs +++ b/Octokit/Http/IApiConnection.cs @@ -67,7 +67,7 @@ public interface IApiConnection /// /// Type of the API resource in the list. /// URI of the API resource to get - /// of the The API resources in the list. + /// of the API resources in the list. /// Thrown when an API error occurs. Task> GetAll(Uri uri); @@ -77,7 +77,7 @@ public interface IApiConnection /// Type of the API resource in the list. /// URI of the API resource to get /// Options for changing the API response - /// of the The API resources in the list. + /// of the API resources in the list. /// Thrown when an API error occurs. Task> GetAll(Uri uri, ApiOptions options); @@ -87,7 +87,7 @@ public interface IApiConnection /// Type of the API resource in the list. /// URI of the API resource to get /// Parameters to add to the API request - /// of the The API resources in the list. + /// of the API resources in the list. /// Thrown when an API error occurs. Task> GetAll(Uri uri, IDictionary parameters); @@ -97,7 +97,7 @@ public interface IApiConnection /// Type of the API resource in the list. /// URI of the API resource to get /// Accept header to use for the API request - /// of the The API resources in the list. + /// of the API resources in the list. /// Thrown when an API error occurs. Task> GetAll(Uri uri, string accepts); @@ -108,7 +108,7 @@ public interface IApiConnection /// URI of the API resource to get /// Parameters to add to the API request /// Options for changing the API response - /// of the The API resources in the list. + /// of the API resources in the list. /// Thrown when an API error occurs. Task> GetAll(Uri uri, IDictionary parameters, ApiOptions options); @@ -119,7 +119,7 @@ public interface IApiConnection /// URI of the API resource to get /// Parameters to add to the API request /// Accept header to use for the API request - /// of the The API resources in the list. + /// of the API resources in the list. /// Thrown when an API error occurs. Task> GetAll(Uri uri, IDictionary parameters, string accepts); @@ -131,7 +131,7 @@ public interface IApiConnection /// Parameters to add to the API request /// Accept header to use for the API request /// Options for changing the API response - /// of the The API resources in the list. + /// of the API resources in the list. /// Thrown when an API error occurs. Task> GetAll(Uri uri, IDictionary parameters, string accepts, ApiOptions options); diff --git a/Octokit/Http/IApiInfoProvider.cs b/Octokit/Http/IApiInfoProvider.cs index 8221682ac3..7d51689613 100644 --- a/Octokit/Http/IApiInfoProvider.cs +++ b/Octokit/Http/IApiInfoProvider.cs @@ -8,7 +8,7 @@ public interface IApiInfoProvider /// /// Gets the latest API Info - this will be null if no API calls have been made /// - /// representing the information returned as part of an Api call + /// representing the information returned as part of an API call [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] ApiInfo GetLastApiInfo(); } diff --git a/Octokit/Http/IHttpClient.cs b/Octokit/Http/IHttpClient.cs index 584bef9f79..bda7a0409f 100644 --- a/Octokit/Http/IHttpClient.cs +++ b/Octokit/Http/IHttpClient.cs @@ -22,7 +22,7 @@ public interface IHttpClient : IDisposable /// - /// Set the GitHub Api request timeout. + /// Set the GitHub API request timeout. /// /// The Timeout value void SetRequestTimeout(TimeSpan timeout); diff --git a/Octokit/Http/JsonHttpPipeline.cs b/Octokit/Http/JsonHttpPipeline.cs index 81548df58f..80830a9a30 100644 --- a/Octokit/Http/JsonHttpPipeline.cs +++ b/Octokit/Http/JsonHttpPipeline.cs @@ -54,7 +54,7 @@ public IApiResponse DeserializeResponse(IResponse response) var responseIsObject = body.StartsWith("{", StringComparison.Ordinal); // If we're expecting an array, but we get a single object, just wrap it. - // This supports an api that dynamically changes the return type based on the content. + // This supports an API that dynamically changes the return type based on the content. if (!typeIsDictionary && typeIsEnumerable && responseIsObject) { body = "[" + body + "]"; diff --git a/Octokit/Http/SimpleJsonSerializer.cs b/Octokit/Http/SimpleJsonSerializer.cs index 0e6aa45ba3..319a343b5a 100644 --- a/Octokit/Http/SimpleJsonSerializer.cs +++ b/Octokit/Http/SimpleJsonSerializer.cs @@ -71,7 +71,7 @@ protected override bool TrySerializeUnknownTypes(object input, out object output if (ReflectionUtils.IsStringEnumWrapper(type)) { // Handle StringEnum by getting the underlying enum value, then using the enum serializer - // Note this will throw if the StringEnum was initialised using a string that is not a valid enum member + // Note this will throw if the StringEnum was initialized using a string that is not a valid enum member var inputEnum = (getters["value"](input) as Enum); if (inputEnum != null) { @@ -212,6 +212,10 @@ private static Type GetPayloadType(string activityType) return typeof(CheckSuiteEventPayload); case "CommitCommentEvent": return typeof(CommitCommentPayload); + case "CreateEvent": + return typeof(CreateEventPayload); + case "DeleteEvent": + return typeof(DeleteEventPayload); case "ForkEvent": return typeof(ForkEventPayload); case "IssueCommentEvent": diff --git a/Octokit/IGitHubClient.cs b/Octokit/IGitHubClient.cs index 032536b634..d6aa599f8a 100644 --- a/Octokit/IGitHubClient.cs +++ b/Octokit/IGitHubClient.cs @@ -3,12 +3,12 @@ namespace Octokit { /// - /// A Client for the GitHub API v3. You can read more about the api here: http://developer.github.com. + /// A Client for the GitHub API v3. You can read more about the API here: http://developer.github.com. /// public interface IGitHubClient : IApiInfoProvider { /// - /// Set the GitHub Api request timeout. + /// Set the GitHub API request timeout. /// Useful to set a specific timeout for lengthy operations, such as uploading release assets /// /// diff --git a/Octokit/Models/Common/AuthorAssociation.cs b/Octokit/Models/Common/AuthorAssociation.cs new file mode 100644 index 0000000000..2661c6d487 --- /dev/null +++ b/Octokit/Models/Common/AuthorAssociation.cs @@ -0,0 +1,52 @@ +using Octokit.Internal; + +namespace Octokit +{ + /// + /// States of a Team/Organization Membership + /// + public enum AuthorAssociation + { + /// + /// Author has been invited to collaborate on the repository. + /// + [Parameter(Value = "COLLABORATOR")] + Collaborator, + + /// + /// Author has previously committed to the repository. + /// + [Parameter(Value = "CONTRIBUTOR")] + Contributor, + + /// + /// Author has not previously committed to GitHub. + /// + [Parameter(Value = "FIRST_TIMER")] + FirstTimer, + + /// + /// Author has not previously committed to the repository. + /// + [Parameter(Value = "FIRST_TIME_CONTRIBUTOR")] + FirstTimeContributor, + + /// + /// Author is a member of the organization that owns the repository. + /// + [Parameter(Value = "MEMBER")] + Member, + + /// + /// Author is the owner of the repository. + /// + [Parameter(Value = "OWNER")] + Owner, + + /// + /// Author has no association with the repository. + /// + [Parameter(Value = "NONE")] + None + } +} diff --git a/Octokit/Models/Common/CheckStatus.cs b/Octokit/Models/Common/CheckStatus.cs index 2d22b9afa3..2c109a918d 100644 --- a/Octokit/Models/Common/CheckStatus.cs +++ b/Octokit/Models/Common/CheckStatus.cs @@ -34,6 +34,12 @@ public enum CheckConclusion [Parameter(Value = "action_required")] ActionRequired, + + [Parameter(Value = "skipped")] + Skipped, + + [Parameter(Value = "stale")] + Stale, } public enum CheckAnnotationLevel diff --git a/Octokit/Models/README.md b/Octokit/Models/README.md index e0c4eee38b..e91f979051 100644 --- a/Octokit/Models/README.md +++ b/Octokit/Models/README.md @@ -13,7 +13,7 @@ The general design principle for request models are: 1. They represent the body of a request. 2. Properties that are _required_ by the API should be required by the model and passed in via the constructor. -3. Required porperties should not have a setter since they will be set by the constructor. +3. Required properties should not have a setter since they will be set by the constructor. 4. All other properties should have both a getter and setter. Note that Octokit.net automatically converts property name to the Ruby casing required by the GitHub API. Thus a diff --git a/Octokit/Models/Request/BranchProtectionUpdate.cs b/Octokit/Models/Request/BranchProtectionUpdate.cs index eda3c0a813..227730c3da 100644 --- a/Octokit/Models/Request/BranchProtectionUpdate.cs +++ b/Octokit/Models/Request/BranchProtectionUpdate.cs @@ -184,7 +184,7 @@ public BranchProtectionPushRestrictionsUpdate() /// /// Specify teams (in addition to Administrators) allowed to push to this branch. Required status checks will still prevent these people from merging if the checks fail /// - /// Teams allowed to push to this branch + /// List of Team slugs allowed to push to this branch public BranchProtectionPushRestrictionsUpdate(BranchProtectionTeamCollection teams) { Ensure.ArgumentNotNull(teams, nameof(teams)); @@ -196,7 +196,7 @@ public BranchProtectionPushRestrictionsUpdate(BranchProtectionTeamCollection tea /// /// Specify people (in addition to Administrators) allowed to push to this branch. Required status checks will still prevent these people from merging if the checks fail /// - /// Users allowed to push to this branch + /// List of User logins allowed to push to this branch public BranchProtectionPushRestrictionsUpdate(BranchProtectionUserCollection users) { Ensure.ArgumentNotNull(users, nameof(users)); @@ -208,8 +208,8 @@ public BranchProtectionPushRestrictionsUpdate(BranchProtectionUserCollection use /// /// Specify teams and/or people (in addition to Administrators) allowed to push to this branch. Required status checks will still prevent these people from merging if the checks fail /// - /// Teams allowed to push to this branch - /// Users allowed to push to this branch + /// List of Team slugs allowed to push to this branch + /// List of User logins allowed to push to this branch public BranchProtectionPushRestrictionsUpdate(BranchProtectionTeamCollection teams, BranchProtectionUserCollection users) { Ensure.ArgumentNotNull(teams, nameof(teams)); @@ -220,12 +220,12 @@ public BranchProtectionPushRestrictionsUpdate(BranchProtectionTeamCollection tea } /// - /// Teams allowed to push to this branch + /// List of Team slugs allowed to push to this branch /// public BranchProtectionTeamCollection Teams { get; private set; } /// - /// Users allowed to push to this branch + /// List of User logins allowed to push to this branch /// public BranchProtectionUserCollection Users { get; private set; } @@ -288,10 +288,12 @@ public class BranchProtectionRequiredReviewsUpdate /// /// Dismiss approved reviews automatically when a new commit is pushed. /// Blocks merge until code owners have reviewed. - public BranchProtectionRequiredReviewsUpdate(bool dismissStaleReviews, bool requireCodeOwnerReviews) + /// Specify the number of reviewers required to approve pull requests. Use a number between 1 and 6. + public BranchProtectionRequiredReviewsUpdate(bool dismissStaleReviews, bool requireCodeOwnerReviews, int requiredApprovingReviewCount) { DismissStaleReviews = dismissStaleReviews; RequireCodeOwnerReviews = requireCodeOwnerReviews; + RequiredApprovingReviewCount = requiredApprovingReviewCount; } /// @@ -300,13 +302,15 @@ public BranchProtectionRequiredReviewsUpdate(bool dismissStaleReviews, bool requ /// Specify which users and teams can dismiss pull request reviews (applies only to Organization owned repositories). /// Dismiss approved reviews automatically when a new commit is pushed. /// Blocks merge until code owners have reviewed. - public BranchProtectionRequiredReviewsUpdate(BranchProtectionRequiredReviewsDismissalRestrictionsUpdate dismissalRestrictions, bool dismissStaleReviews, bool requireCodeOwnerReviews) + /// Specify the number of reviewers required to approve pull requests. Use a number between 1 and 6. + public BranchProtectionRequiredReviewsUpdate(BranchProtectionRequiredReviewsDismissalRestrictionsUpdate dismissalRestrictions, bool dismissStaleReviews, bool requireCodeOwnerReviews, int requiredApprovingReviewCount) { Ensure.ArgumentNotNull(dismissalRestrictions, nameof(dismissalRestrictions)); DismissalRestrictions = dismissalRestrictions; DismissStaleReviews = dismissStaleReviews; RequireCodeOwnerReviews = requireCodeOwnerReviews; + RequiredApprovingReviewCount = requiredApprovingReviewCount; } /// @@ -324,14 +328,20 @@ public BranchProtectionRequiredReviewsUpdate(BranchProtectionRequiredReviewsDism /// public bool RequireCodeOwnerReviews { get; protected set; } + /// + /// Specify the number of reviewers required to approve pull requests. Use a number between 1 and 6. + /// + public int RequiredApprovingReviewCount { get; protected set; } + internal string DebuggerDisplay { get { - return string.Format(CultureInfo.InvariantCulture, "DismissalRestrictions: {0} DismissStaleReviews: {1} RequireCodeOwnerReviews: {2}", + return string.Format(CultureInfo.InvariantCulture, "DismissalRestrictions: {0} DismissStaleReviews: {1} RequireCodeOwnerReviews: {2} RequiredApprovingReviewCount: {3}", DismissalRestrictions?.DebuggerDisplay ?? "disabled", DismissStaleReviews, - RequireCodeOwnerReviews); + RequireCodeOwnerReviews, + RequiredApprovingReviewCount); } } } @@ -365,7 +375,7 @@ public BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(bool enabled) /// /// Restrict dismissing reviews to the specified teams (in addition to Administrators). /// - /// Teams allowed to dismiss reviews + /// List of Team slugs allowed to dismiss reviews public BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(BranchProtectionTeamCollection teams) { Ensure.ArgumentNotNull(teams, nameof(teams)); @@ -377,7 +387,7 @@ public BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(BranchProtecti /// /// Restrict dismissing reviews to the specified people (in addition to Administrators). /// - /// Users allowed to dismiss reviews + /// List of User logins allowed to dismiss reviews public BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(BranchProtectionUserCollection users) { Ensure.ArgumentNotNull(users, nameof(users)); @@ -389,8 +399,8 @@ public BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(BranchProtecti /// /// Restrict dismissing reviews to the specified teams and people (in addition to Administrators). /// - /// Teams allowed to dismiss reviews - /// Users allowed to dismiss reviews + /// List of Team slugs allowed to dismiss reviews + /// List of User logins allowed to dismiss reviews public BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(BranchProtectionTeamCollection teams, BranchProtectionUserCollection users) { Ensure.ArgumentNotNull(teams, nameof(teams)); @@ -401,12 +411,12 @@ public BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(BranchProtecti } /// - /// Teams allowed to dismiss reviews + /// List of Team slugs allowed to dismiss reviews /// public BranchProtectionTeamCollection Teams { get; private set; } /// - /// Users allowed to dismiss reviews + /// List of User logins allowed to dismiss reviews /// public BranchProtectionUserCollection Users { get; private set; } diff --git a/Octokit/Models/Request/Enterprise/UpdateMaintenanceRequest.cs b/Octokit/Models/Request/Enterprise/UpdateMaintenanceRequest.cs new file mode 100644 index 0000000000..f1cc7abbb5 --- /dev/null +++ b/Octokit/Models/Request/Enterprise/UpdateMaintenanceRequest.cs @@ -0,0 +1,107 @@ +using System; +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class UpdateMaintenanceRequest : FormUrlEncodedParameters + { + /// + /// Maintenance request with default details (results in Maintenance mode being turned off immediately) + /// + public UpdateMaintenanceRequest() + { + Maintenance = new UpdateMaintenanceRequestDetails(); + } + + /// + /// Maintenance request with specific details + /// + public UpdateMaintenanceRequest(UpdateMaintenanceRequestDetails maintenance) + { + Ensure.ArgumentNotNull(maintenance, "maintenance"); + + Maintenance = maintenance; + } + + /// + /// Details for the maintenance request + /// + public UpdateMaintenanceRequestDetails Maintenance { get; protected set; } + + internal string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, "Maintenance: {0}", this.Maintenance.DebuggerDisplay); + } + } + } + + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class UpdateMaintenanceRequestDetails + { + /// + /// Maintenance request details with default values (results in Maintenance mode being turned off immediately) + /// + public UpdateMaintenanceRequestDetails() + { } + + /// + /// Maintenance request details to enable/disable maintenance mode immediately + /// + /// true to enable, false to disable + public UpdateMaintenanceRequestDetails(bool enabled) + { + Enabled = enabled; + When = "now"; + } + + /// + /// Maintenance request details to enable/disable maintenance at a specified time (only applicable when enabling maintenance) + /// + /// true to enable, false to disable + /// A phrase specifying when maintenance mode will be enabled. Phrase uses humanized forms supported by the mojombo/chronic library used by the GitHub API + /// such as "this friday at 5pm" or "5 minutes before midday tomorrow" + /// If enabled is false, the when parameter is ignored and maintenance is turned off immediately + public UpdateMaintenanceRequestDetails(bool enabled, string when) + { + Ensure.ArgumentNotNullOrEmptyString(when, "when"); + + Enabled = enabled; + When = when; + } + + /// + /// Maintenance request details to enable/disable maintenance at a specified time (only applicable when enabling maintenance) + /// + /// true to enable, false to disable + /// A specifying when maintenance mode will be enabled. + /// If enabled is false, the when parameter is ignored and maintenance is turned off immediately + public UpdateMaintenanceRequestDetails(bool enabled, DateTimeOffset when) + { + Enabled = enabled; + When = when.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ", + CultureInfo.InvariantCulture); + } + + /// + /// Whether maintenance mode is enabled or disabled + /// + public bool Enabled { get; protected set; } + + /// + /// When maintenance mode will take effect (only applicable when enabling maintenance) + /// + public string When { get; protected set; } + + internal string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, "Enabled: {0} When: {1}", this.Enabled, this.When); + } + } + } +} diff --git a/Octokit/Models/Request/FormUrlEncodedParameters.cs b/Octokit/Models/Request/FormUrlEncodedParameters.cs new file mode 100644 index 0000000000..7b615d5295 --- /dev/null +++ b/Octokit/Models/Request/FormUrlEncodedParameters.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Linq; +using System.Reflection; +using Octokit.Internal; + +namespace Octokit +{ + /// + /// Base class for classes which represent UrlFormEncoded parameters to certain API endpoints. + /// + public abstract class FormUrlEncodedParameters + { + /// + /// Converts the derived object into a UrlFormEncoded parameter string containing named parameters and their json serialized values + /// This format is required for particular API calls (eg the GitHub Enterprise Management Console API) that take a parameter formatted as json but not in the request body + /// + [SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings")] + public string ToFormUrlEncodedParameterString() + { + var parameters = new List(); + foreach (var prop in GetPropertyParametersForType(this.GetType())) + { + parameters.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", prop.Key, prop.GetValue(this))); + } + + return string.Join("&", parameters); + } + + static List GetPropertyParametersForType(Type type) + { + return type.GetAllProperties() + .Where(p => p.Name != "DebuggerDisplay") + .Select(p => new JsonParameter(p)) + .ToList(); + } + + class JsonParameter + { + readonly PropertyInfo _property; + public JsonParameter(PropertyInfo property) + { + _property = property; + Key = GetParameterKeyFromProperty(property); + } + + public string Key { get; private set; } + + public string GetValue(object instance) + { + var value = _property.GetValue(instance, null); + return value != null ? new SimpleJsonSerializer().Serialize(value) : null; + } + + [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", + Justification = "GitHub API depends on lower case strings")] + static string GetParameterKeyFromProperty(PropertyInfo property) + { + var attribute = property.GetCustomAttributes(typeof(ParameterAttribute), false) + .Cast() + .FirstOrDefault(attr => attr.Key != null); + + return attribute == null + ? property.Name.ToLowerInvariant() + : attribute.Key; + } + } + } +} diff --git a/Octokit/Models/Request/NewDeployment.cs b/Octokit/Models/Request/NewDeployment.cs index 1e24f95cbe..b844ceffc1 100644 --- a/Octokit/Models/Request/NewDeployment.cs +++ b/Octokit/Models/Request/NewDeployment.cs @@ -96,7 +96,7 @@ internal string DebuggerDisplay } /// - /// The types of deployments tasks that are availabel. + /// The types of deployments tasks that are available. /// public enum DeployTask { diff --git a/Octokit/Models/Request/NewPullRequest.cs b/Octokit/Models/Request/NewPullRequest.cs index d383b227a7..d2dd58218b 100644 --- a/Octokit/Models/Request/NewPullRequest.cs +++ b/Octokit/Models/Request/NewPullRequest.cs @@ -51,6 +51,11 @@ public NewPullRequest(string title, string head, string baseRef) /// public string Body { get; set; } + /// + /// Whether the pull request is in a draft state or not (optional) + /// + public bool? Draft { get; set; } + internal string DebuggerDisplay { get diff --git a/Octokit/Models/Request/OauthLoginRequest.cs b/Octokit/Models/Request/OauthLoginRequest.cs index 54fe1911f7..5c4a3b48ad 100644 --- a/Octokit/Models/Request/OauthLoginRequest.cs +++ b/Octokit/Models/Request/OauthLoginRequest.cs @@ -40,6 +40,12 @@ public OauthLoginRequest(string clientId) [Parameter(Key = "redirect_uri")] public Uri RedirectUri { get; set; } + /// + /// Suggests a specific account to use for signing in and authorizing the app. + /// + [Parameter(Key = "login")] + public string Login { get; set; } + /// /// A set of scopes to request. If not provided, scope defaults to an empty list of scopes for users that don’t /// have a valid token for the app. For users who do already have a valid token for the app, the user won’t be @@ -60,6 +66,13 @@ public OauthLoginRequest(string clientId) [Parameter(Key = "state")] public string State { get; set; } + /// + /// Whether or not unauthenticated users will be offered an option to sign up for GitHub during the OAuth flow. + /// The default is true. Use false in the case that a policy prohibits signups. + /// + [Parameter(Key = "allow_signup")] + public bool? AllowSignup { get; set; } + internal string DebuggerDisplay { get diff --git a/Octokit/Models/Request/OrganizationMembershipUpdate.cs b/Octokit/Models/Request/OrganizationMembershipUpdate.cs new file mode 100644 index 0000000000..fdd73b2160 --- /dev/null +++ b/Octokit/Models/Request/OrganizationMembershipUpdate.cs @@ -0,0 +1,20 @@ +using System.Diagnostics; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class OrganizationMembershipUpdate + { + public OrganizationMembershipUpdate() + { + Role = MembershipRole.Member; + } + + /// + /// The role to give the user in the organization. The default is . + /// + public MembershipRole Role { get; set; } + + internal string DebuggerDisplay => $"{Role}"; + } +} diff --git a/Octokit/Models/Request/OrganizationRequest.cs b/Octokit/Models/Request/OrganizationRequest.cs index 7b51898b0d..2e73e2e970 100644 --- a/Octokit/Models/Request/OrganizationRequest.cs +++ b/Octokit/Models/Request/OrganizationRequest.cs @@ -10,7 +10,7 @@ namespace Octokit public class OrganizationRequest : RequestParameters { /// - /// Intializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The integer Id of the last Organization that you've seen. public OrganizationRequest(int since) diff --git a/Octokit/Models/Request/RepositoryCollaboratorListRequest.cs b/Octokit/Models/Request/RepositoryCollaboratorListRequest.cs new file mode 100644 index 0000000000..6f5a8a4f4c --- /dev/null +++ b/Octokit/Models/Request/RepositoryCollaboratorListRequest.cs @@ -0,0 +1,57 @@ +using System.Diagnostics; +using System.Globalization; +using Octokit.Internal; + +namespace Octokit +{ + /// + /// Used to request and filter a list of repository collaborators + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class RepositoryCollaboratorListRequest : RequestParameters + { + /// + /// Initializes a new instance of the class. + /// + public RepositoryCollaboratorListRequest() + { + Affiliation = CollaboratorAffiliation.All; // Default in accordance with the documentation + } + + /// + /// Gets or sets the collaborator affiliation property. + /// + /// + /// The collaborator affiliation + /// + public CollaboratorAffiliation Affiliation { get; set; } + + internal string DebuggerDisplay + { + get { return string.Format(CultureInfo.InvariantCulture, "Affiliation: {0}", Affiliation); } + } + } + + /// + /// The collaborator affiliation + /// + public enum CollaboratorAffiliation + { + /// + /// All collaborators the authenticated user can see. + /// + [Parameter(Value = "all")] + All, + /// + /// All collaborators with permissions to an organization-owned repository, + /// regardless of organization membership status. + /// + [Parameter(Value = "direct")] + Direct, + /// + /// All outside collaborators of an organization-owned repository. + /// + [Parameter(Value = "outside")] + Outside + } +} diff --git a/Octokit/Models/Request/SearchCodeRequest.cs b/Octokit/Models/Request/SearchCodeRequest.cs index e281b48a80..9c4795fa67 100644 --- a/Octokit/Models/Request/SearchCodeRequest.cs +++ b/Octokit/Models/Request/SearchCodeRequest.cs @@ -116,12 +116,12 @@ public IEnumerable In public string Path { get; set; } /// - /// Matches files with a certain extension. + /// Matches files with a certain extensions. /// /// /// https://help.github.com/articles/searching-code#extension /// - public string Extension { get; set; } + public IEnumerable Extensions { get; set; } = new List(); /// /// Matches specific file names @@ -169,7 +169,7 @@ public override IReadOnlyList MergedQualifiers() if (Language != null) { - parameters.Add(string.Format(CultureInfo.InvariantCulture, "language:{0}", Language.ToParameter())); + parameters.Add(string.Format(CultureInfo.InvariantCulture, "language:\"{0}\"", Language.ToParameter())); } if (Forks != null) @@ -189,9 +189,12 @@ public override IReadOnlyList MergedQualifiers() parameters.Add(string.Format(CultureInfo.InvariantCulture, "path:{0}", Path)); } - if (Extension.IsNotBlank()) + if (Extensions.Any()) { - parameters.Add(string.Format(CultureInfo.InvariantCulture, "extension:{0}", Extension)); + foreach (var extension in Extensions) + { + parameters.Add(string.Format(CultureInfo.InvariantCulture, "extension:{0}", extension)); + } } if (FileName.IsNotBlank()) diff --git a/Octokit/Models/Request/SearchIssuesRequest.cs b/Octokit/Models/Request/SearchIssuesRequest.cs index a644cdc6b0..5b5508a34a 100644 --- a/Octokit/Models/Request/SearchIssuesRequest.cs +++ b/Octokit/Models/Request/SearchIssuesRequest.cs @@ -328,7 +328,7 @@ public override IReadOnlyList MergedQualifiers() if (Labels != null) { - parameters.AddRange(Labels.Select(label => string.Format(CultureInfo.InvariantCulture, "label:{0}", label))); + parameters.AddRange(Labels.Select(label => string.Format(CultureInfo.InvariantCulture, "label:\"{0}\"", label))); } if (No.HasValue) @@ -338,7 +338,7 @@ public override IReadOnlyList MergedQualifiers() if (Language != null) { - parameters.Add(string.Format(CultureInfo.InvariantCulture, "language:{0}", Language.ToParameter())); + parameters.Add(string.Format(CultureInfo.InvariantCulture, "language:\"{0}\"", Language.ToParameter())); } if (Is != null) diff --git a/Octokit/Models/Request/SearchIssuesRequestExclusions.cs b/Octokit/Models/Request/SearchIssuesRequestExclusions.cs index 38815a2a65..4362c3e206 100644 --- a/Octokit/Models/Request/SearchIssuesRequestExclusions.cs +++ b/Octokit/Models/Request/SearchIssuesRequestExclusions.cs @@ -170,7 +170,7 @@ public IReadOnlyList MergedQualifiers() if (Language != null) { - parameters.Add(string.Format(CultureInfo.InvariantCulture, "-language:{0}", Language.ToParameter())); + parameters.Add(string.Format(CultureInfo.InvariantCulture, "-language:\"{0}\"", Language.ToParameter())); } if (Status.HasValue) diff --git a/Octokit/Models/Request/SearchRepositoriesRequest.cs b/Octokit/Models/Request/SearchRepositoriesRequest.cs index f4101dde1b..48d0964535 100644 --- a/Octokit/Models/Request/SearchRepositoriesRequest.cs +++ b/Octokit/Models/Request/SearchRepositoriesRequest.cs @@ -83,7 +83,7 @@ public IEnumerable In public Range Size { get; set; } /// - /// Searches repositories based on the language they’re written in. + /// Searches repositories based on the language they’re written in. /// https://help.github.com/articles/searching-repositories#languages /// public Language? Language { get; set; } @@ -148,7 +148,7 @@ public override IReadOnlyList MergedQualifiers() if (Language != null) { - parameters.Add(string.Format(CultureInfo.InvariantCulture, "language:{0}", Language)); + parameters.Add(string.Format(CultureInfo.InvariantCulture, "language:\"{0}\"", Language.ToParameter())); } if (User.IsNotBlank()) @@ -298,27 +298,31 @@ public override string ToString() [DebuggerDisplay("{DebuggerDisplay,nq}")] public class DateRange { + public const string DateTimePattern = "yyyy-MM-dd'T'HH:mm:sszzz"; + public const string DatePattern = "yyyy-MM-dd"; + private readonly string query = string.Empty; /// /// Matches repositories with regards to the . /// We will use the to see what operator will be applied to the date qualifier /// + [Obsolete("This ctor does not support the time component or timezone and will be removed in a future release. Please use the DateTimeOffset overload instead")] public DateRange(DateTime date, SearchQualifierOperator op) { switch (op) { case SearchQualifierOperator.GreaterThan: - query = string.Format(CultureInfo.InvariantCulture, ">{0:yyyy-MM-dd}", date); + query = date.ToString($">{DatePattern}", CultureInfo.InvariantCulture); break; case SearchQualifierOperator.LessThan: - query = string.Format(CultureInfo.InvariantCulture, "<{0:yyyy-MM-dd}", date); + query = date.ToString($"<{DatePattern}", CultureInfo.InvariantCulture); break; case SearchQualifierOperator.LessThanOrEqualTo: - query = string.Format(CultureInfo.InvariantCulture, "<={0:yyyy-MM-dd}", date); + query = date.ToString($"<={DatePattern}", CultureInfo.InvariantCulture); break; case SearchQualifierOperator.GreaterThanOrEqualTo: - query = string.Format(CultureInfo.InvariantCulture, ">={0:yyyy-MM-dd}", date); + query = date.ToString($">={DatePattern}", CultureInfo.InvariantCulture); break; } } @@ -326,9 +330,41 @@ public DateRange(DateTime date, SearchQualifierOperator op) /// /// Matches repositories with regards to both the and dates. /// + [Obsolete("This ctor does not support the time component or timezone and will be removed in a future release. Please use the DateTimeOffset overload instead")] public DateRange(DateTime from, DateTime to) { - query = string.Format(CultureInfo.InvariantCulture, "{0:yyyy-MM-dd}..{1:yyyy-MM-dd}", from, to); + query = $"{from.ToString(DatePattern, CultureInfo.InvariantCulture)}..{to.ToString(DatePattern, CultureInfo.InvariantCulture)}"; + } + + /// + /// Matches repositories with regards to both the and date and time values. + /// + public DateRange(DateTimeOffset from, DateTimeOffset to) + { + query = $"{from.ToString(DateTimePattern, CultureInfo.InvariantCulture)}..{to.ToString(DateTimePattern, CultureInfo.InvariantCulture)}"; + } + + /// + /// Matches repositories with regards to the . + /// We will use the to see what operator will be applied to the date qualifier + /// + public DateRange(DateTimeOffset dateTime, SearchQualifierOperator op) + { + switch (op) + { + case SearchQualifierOperator.GreaterThan: + query = dateTime.ToString($">{DateTimePattern}", CultureInfo.InvariantCulture); + break; + case SearchQualifierOperator.LessThan: + query = dateTime.ToString($"<{DateTimePattern}", CultureInfo.InvariantCulture); + break; + case SearchQualifierOperator.LessThanOrEqualTo: + query = dateTime.ToString($"<={DateTimePattern}", CultureInfo.InvariantCulture); + break; + case SearchQualifierOperator.GreaterThanOrEqualTo: + query = dateTime.ToString($">={DateTimePattern}", CultureInfo.InvariantCulture); + break; + } } internal string DebuggerDisplay @@ -342,6 +378,7 @@ internal string DebuggerDisplay /// /// date to be used for comparison (times are ignored) /// + [Obsolete("This method does not support the time component or timezone and will be removed in a future release. Please use the DateTimeOffset overload instead")] public static DateRange LessThan(DateTime date) { return new DateRange(date, SearchQualifierOperator.LessThan); @@ -353,6 +390,7 @@ public static DateRange LessThan(DateTime date) /// /// date to be used for comparison (times are ignored) /// + [Obsolete("This method does not support the time component or timezone and will be removed in a future release. Please use the DateTimeOffset overload instead")] public static DateRange LessThanOrEquals(DateTime date) { return new DateRange(date, SearchQualifierOperator.LessThanOrEqualTo); @@ -364,6 +402,7 @@ public static DateRange LessThanOrEquals(DateTime date) /// /// date to be used for comparison (times are ignored) /// + [Obsolete("This method does not support the time component or timezone and will be removed in a future release. Please use the DateTimeOffset overload instead")] public static DateRange GreaterThan(DateTime date) { return new DateRange(date, SearchQualifierOperator.GreaterThan); @@ -375,6 +414,7 @@ public static DateRange GreaterThan(DateTime date) /// /// date to be used for comparison (times are ignored) /// + [Obsolete("This method does not support the time component or timezone and will be removed in a future release. Please use the DateTimeOffset overload instead")] public static DateRange GreaterThanOrEquals(DateTime date) { return new DateRange(date, SearchQualifierOperator.GreaterThanOrEqualTo); @@ -387,11 +427,68 @@ public static DateRange GreaterThanOrEquals(DateTime date) /// earlier date of the two /// latter date of the two /// + [Obsolete("This method does not support the time component or timezone and will be removed in a future release. Please use the DateTimeOffset overload instead")] public static DateRange Between(DateTime from, DateTime to) { return new DateRange(from, to); } + /// + /// helper method to create a LessThan DateTime Comparison + /// e.g. < 2011 + /// + /// datetime to be used for comparison (times are ignored) + /// + public static DateRange LessThan(DateTimeOffset dateTime) + { + return new DateRange(dateTime, SearchQualifierOperator.LessThan); + } + + /// + /// helper method to create a LessThanOrEqualTo DateTime Comparison + /// e.g. <= 2011 + /// + /// datetime to be used for comparison (times are ignored) + /// + public static DateRange LessThanOrEquals(DateTimeOffset dateTime) + { + return new DateRange(dateTime, SearchQualifierOperator.LessThanOrEqualTo); + } + + /// + /// helper method to create a GreaterThan DateTime Comparison + /// e.g. > 2011 + /// + /// datetime to be used for comparison (times are ignored) + /// + public static DateRange GreaterThan(DateTimeOffset dateTime) + { + return new DateRange(dateTime, SearchQualifierOperator.GreaterThan); + } + + /// + /// helper method to create a GreaterThanOrEqualTo DateTime Comparison + /// e.g. >= 2011 + /// + /// datetime to be used for comparison (times are ignored) + /// + public static DateRange GreaterThanOrEquals(DateTimeOffset dateTime) + { + return new DateRange(dateTime, SearchQualifierOperator.GreaterThanOrEqualTo); + } + + /// + /// helper method to create a bounded DateTime Comparison + /// e.g. 2015-08-01..2015-10-31 + /// + /// earlier datetime of the two + /// latter datetime of the two + /// + public static DateRange Between(DateTimeOffset from, DateTimeOffset to) + { + return new DateRange(from, to); + } + public override string ToString() { return query; @@ -460,7 +557,7 @@ public enum Language ColdFusion, CommonLisp, Coq, - [Parameter(Value = "C++")] + [Parameter(Value = "cpp")] CPlusPlus, [Parameter(Value = "CSharp")] CSharp, @@ -568,6 +665,8 @@ public enum Language JavaScript, Json, Julia, + [Parameter(Value = "Jupyter Notebook")] + JupyterNotebook, [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Kotlin")] Kotlin, Lasso, @@ -799,4 +898,4 @@ public enum ForkQualifier [Parameter(Value = "true")] IncludeForks } -} \ No newline at end of file +} diff --git a/Octokit/Models/Request/SearchUsersRequest.cs b/Octokit/Models/Request/SearchUsersRequest.cs index 3d8d783647..760ac87322 100644 --- a/Octokit/Models/Request/SearchUsersRequest.cs +++ b/Octokit/Models/Request/SearchUsersRequest.cs @@ -117,7 +117,7 @@ public override IReadOnlyList MergedQualifiers() if (Language != null) { - parameters.Add(string.Format(CultureInfo.InvariantCulture, "language:{0}", Language)); + parameters.Add(string.Format(CultureInfo.InvariantCulture, "language:\"{0}\"", Language.ToParameter())); } if (Created != null) diff --git a/Octokit/Models/Request/UpdateTeam.cs b/Octokit/Models/Request/UpdateTeam.cs index b23000072d..960019094d 100644 --- a/Octokit/Models/Request/UpdateTeam.cs +++ b/Octokit/Models/Request/UpdateTeam.cs @@ -5,7 +5,7 @@ namespace Octokit { /// - /// Used to update a teamm. + /// Used to update a team. /// [DebuggerDisplay("{DebuggerDisplay,nq}")] public class UpdateTeam diff --git a/Octokit/Models/Response/Account.cs b/Octokit/Models/Response/Account.cs index 9e242b9e9e..ce508c6b28 100644 --- a/Octokit/Models/Response/Account.cs +++ b/Octokit/Models/Response/Account.cs @@ -79,7 +79,7 @@ protected Account(string avatarUrl, string bio, string blog, int collaborators, public string Email { get; protected set; } /// - /// Number of follwers the account has. + /// Number of followers the account has. /// public int Followers { get; protected set; } diff --git a/Octokit/Models/Response/ActivityPayloads/CreateEventPayload.cs b/Octokit/Models/Response/ActivityPayloads/CreateEventPayload.cs new file mode 100644 index 0000000000..4abae7b97c --- /dev/null +++ b/Octokit/Models/Response/ActivityPayloads/CreateEventPayload.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Diagnostics; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class CreateEventPayload : ActivityPayload + { + public string Ref { get; protected set; } + + public StringEnum RefType { get; protected set; } + + public string MasterBranch { get; protected set; } + + public string Description { get; protected set; } + } +} diff --git a/Octokit/Models/Response/ActivityPayloads/DeleteEventPayload.cs b/Octokit/Models/Response/ActivityPayloads/DeleteEventPayload.cs new file mode 100644 index 0000000000..6abd970c01 --- /dev/null +++ b/Octokit/Models/Response/ActivityPayloads/DeleteEventPayload.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Diagnostics; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class DeleteEventPayload : ActivityPayload + { + public string Ref { get; protected set; } + + public StringEnum RefType { get; protected set; } + } +} diff --git a/Octokit/Models/Response/ApiError.cs b/Octokit/Models/Response/ApiError.cs index 609fb37b3b..be5650c9f6 100644 --- a/Octokit/Models/Response/ApiError.cs +++ b/Octokit/Models/Response/ApiError.cs @@ -6,7 +6,7 @@ namespace Octokit { /// - /// Error payload from the API reposnse + /// Error payload from the API response /// #if !NO_SERIALIZABLE [Serializable] diff --git a/Octokit/Models/Response/BranchProtection.cs b/Octokit/Models/Response/BranchProtection.cs index 0b823581ad..e73e864507 100644 --- a/Octokit/Models/Response/BranchProtection.cs +++ b/Octokit/Models/Response/BranchProtection.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.Linq; -using Octokit.Internal; namespace Octokit { @@ -165,11 +163,12 @@ public class BranchProtectionRequiredReviews { public BranchProtectionRequiredReviews() { } - public BranchProtectionRequiredReviews(BranchProtectionRequiredReviewsDismissalRestrictions dismissalRestrictions, bool dismissStaleReviews, bool requireCodeOwnerReviews) + public BranchProtectionRequiredReviews(BranchProtectionRequiredReviewsDismissalRestrictions dismissalRestrictions, bool dismissStaleReviews, bool requireCodeOwnerReviews, int requiredApprovingReviewCount) { DismissalRestrictions = dismissalRestrictions; DismissStaleReviews = dismissStaleReviews; RequireCodeOwnerReviews = requireCodeOwnerReviews; + RequiredApprovingReviewCount = requiredApprovingReviewCount; } /// @@ -187,14 +186,20 @@ public BranchProtectionRequiredReviews(BranchProtectionRequiredReviewsDismissalR /// public bool RequireCodeOwnerReviews { get; protected set; } + /// + /// Specify the number of reviewers required to approve pull requests. Use a number between 1 and 6. + /// + public int RequiredApprovingReviewCount { get; protected set; } + internal string DebuggerDisplay { get { - return string.Format(CultureInfo.InvariantCulture, "DismissalRestrictions: {0} DismissStaleReviews: {1} RequireCodeOwnerReviews: {2}", + return string.Format(CultureInfo.InvariantCulture, "DismissalRestrictions: {0} DismissStaleReviews: {1} RequireCodeOwnerReviews: {2} RequiredApprovingReviewCount: {3}", DismissalRestrictions?.DebuggerDisplay ?? "disabled", DismissStaleReviews, - RequireCodeOwnerReviews); + RequireCodeOwnerReviews, + RequiredApprovingReviewCount); } } } diff --git a/Octokit/Models/Response/Enterprise/AdminStats.cs b/Octokit/Models/Response/Enterprise/AdminStats.cs index 67e3dc7128..8affd73db2 100644 --- a/Octokit/Models/Response/Enterprise/AdminStats.cs +++ b/Octokit/Models/Response/Enterprise/AdminStats.cs @@ -100,7 +100,7 @@ internal string DebuggerDisplay Comments != null ? "Comments," : "" ).Trim(','); - return String.Format(CultureInfo.InvariantCulture, "Statistics: {0}", fieldsPresent); + return string.Format(CultureInfo.InvariantCulture, "Statistics: {0}", fieldsPresent); } } } diff --git a/Octokit/Models/Response/Enterprise/AdminStatsComments.cs b/Octokit/Models/Response/Enterprise/AdminStatsComments.cs index 2502b9a92f..1b900f7922 100644 --- a/Octokit/Models/Response/Enterprise/AdminStatsComments.cs +++ b/Octokit/Models/Response/Enterprise/AdminStatsComments.cs @@ -45,7 +45,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "TotalCommitComments: {0} TotalGistComments: {1} TotalIssueComments: {2} TotalPullRequestComments: {3}", TotalCommitComments, TotalGistComments, TotalIssueComments, TotalPullRequestComments); + return string.Format(CultureInfo.InvariantCulture, "TotalCommitComments: {0} TotalGistComments: {1} TotalIssueComments: {2} TotalPullRequestComments: {3}", TotalCommitComments, TotalGistComments, TotalIssueComments, TotalPullRequestComments); } } } diff --git a/Octokit/Models/Response/Enterprise/AdminStatsGists.cs b/Octokit/Models/Response/Enterprise/AdminStatsGists.cs index 2b6488c205..379b867fb9 100644 --- a/Octokit/Models/Response/Enterprise/AdminStatsGists.cs +++ b/Octokit/Models/Response/Enterprise/AdminStatsGists.cs @@ -38,7 +38,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "TotalGists: {0} PrivateGists: {1} PublicGists: {2}", TotalGists, PrivateGists, PublicGists); + return string.Format(CultureInfo.InvariantCulture, "TotalGists: {0} PrivateGists: {1} PublicGists: {2}", TotalGists, PrivateGists, PublicGists); } } } diff --git a/Octokit/Models/Response/Enterprise/AdminStatsHooks.cs b/Octokit/Models/Response/Enterprise/AdminStatsHooks.cs index b960d6d44f..96fa12a983 100644 --- a/Octokit/Models/Response/Enterprise/AdminStatsHooks.cs +++ b/Octokit/Models/Response/Enterprise/AdminStatsHooks.cs @@ -38,7 +38,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "TotalHooks: {0} ActiveHooks: {1} InactiveHooks: {2}", TotalHooks, ActiveHooks, InactiveHooks); + return string.Format(CultureInfo.InvariantCulture, "TotalHooks: {0} ActiveHooks: {1} InactiveHooks: {2}", TotalHooks, ActiveHooks, InactiveHooks); } } } diff --git a/Octokit/Models/Response/Enterprise/AdminStatsIssues.cs b/Octokit/Models/Response/Enterprise/AdminStatsIssues.cs index 1b02ae759b..b95e359a7f 100644 --- a/Octokit/Models/Response/Enterprise/AdminStatsIssues.cs +++ b/Octokit/Models/Response/Enterprise/AdminStatsIssues.cs @@ -38,7 +38,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "TotalIssues: {0} OpenIssues: {1} ClosedIssues: {2}", TotalIssues, OpenIssues, ClosedIssues); + return string.Format(CultureInfo.InvariantCulture, "TotalIssues: {0} OpenIssues: {1} ClosedIssues: {2}", TotalIssues, OpenIssues, ClosedIssues); } } } diff --git a/Octokit/Models/Response/Enterprise/AdminStatsMilestones.cs b/Octokit/Models/Response/Enterprise/AdminStatsMilestones.cs index 2fd1e8e865..4b5d58b0ab 100644 --- a/Octokit/Models/Response/Enterprise/AdminStatsMilestones.cs +++ b/Octokit/Models/Response/Enterprise/AdminStatsMilestones.cs @@ -38,7 +38,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "TotalMilestones: {0} OpenMilestones: {1} ClosedMilestones: {2}", TotalMilestones, OpenMilestones, ClosedMilestones); + return string.Format(CultureInfo.InvariantCulture, "TotalMilestones: {0} OpenMilestones: {1} ClosedMilestones: {2}", TotalMilestones, OpenMilestones, ClosedMilestones); } } } diff --git a/Octokit/Models/Response/Enterprise/AdminStatsOrgs.cs b/Octokit/Models/Response/Enterprise/AdminStatsOrgs.cs index 2149227a9b..e63d4005d5 100644 --- a/Octokit/Models/Response/Enterprise/AdminStatsOrgs.cs +++ b/Octokit/Models/Response/Enterprise/AdminStatsOrgs.cs @@ -45,7 +45,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "TotalOrgs: {0} DisabledOrgs: {1} TotalTeams: {2} TotalTeamMembers: {3}", TotalOrgs, DisabledOrgs, TotalTeams, TotalTeamMembers); + return string.Format(CultureInfo.InvariantCulture, "TotalOrgs: {0} DisabledOrgs: {1} TotalTeams: {2} TotalTeamMembers: {3}", TotalOrgs, DisabledOrgs, TotalTeams, TotalTeamMembers); } } } diff --git a/Octokit/Models/Response/Enterprise/AdminStatsPages.cs b/Octokit/Models/Response/Enterprise/AdminStatsPages.cs index 4f0965ec3b..9b6e222353 100644 --- a/Octokit/Models/Response/Enterprise/AdminStatsPages.cs +++ b/Octokit/Models/Response/Enterprise/AdminStatsPages.cs @@ -24,7 +24,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "TotalPages: {0}", TotalPages); + return string.Format(CultureInfo.InvariantCulture, "TotalPages: {0}", TotalPages); } } } diff --git a/Octokit/Models/Response/Enterprise/AdminStatsPulls.cs b/Octokit/Models/Response/Enterprise/AdminStatsPulls.cs index 44e6cf34e9..286470a350 100644 --- a/Octokit/Models/Response/Enterprise/AdminStatsPulls.cs +++ b/Octokit/Models/Response/Enterprise/AdminStatsPulls.cs @@ -48,7 +48,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "TotalPulls: {0} MergedPulls: {1} MergeablePulls: {2} UnmergeablePulls: {3}", TotalPulls, MergedPulls, MergeablePulls, UnmergeablePulls); + return string.Format(CultureInfo.InvariantCulture, "TotalPulls: {0} MergedPulls: {1} MergeablePulls: {2} UnmergeablePulls: {3}", TotalPulls, MergedPulls, MergeablePulls, UnmergeablePulls); } } } diff --git a/Octokit/Models/Response/Enterprise/AdminStatsRepos.cs b/Octokit/Models/Response/Enterprise/AdminStatsRepos.cs index 3895389b60..23dcab03dd 100644 --- a/Octokit/Models/Response/Enterprise/AdminStatsRepos.cs +++ b/Octokit/Models/Response/Enterprise/AdminStatsRepos.cs @@ -59,7 +59,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "TotalRepos: {0} RootRepos: {1} ForkRepos: {2} OrgRepos: {3} TotalPushes: {4} TotalWikis: {5}", TotalRepos, RootRepos, ForkRepos, OrgRepos, TotalPushes, TotalWikis); + return string.Format(CultureInfo.InvariantCulture, "TotalRepos: {0} RootRepos: {1} ForkRepos: {2} OrgRepos: {3} TotalPushes: {4} TotalWikis: {5}", TotalRepos, RootRepos, ForkRepos, OrgRepos, TotalPushes, TotalWikis); } } } diff --git a/Octokit/Models/Response/Enterprise/AdminStatsUsers.cs b/Octokit/Models/Response/Enterprise/AdminStatsUsers.cs index 4dcc8242d7..34347f37b0 100644 --- a/Octokit/Models/Response/Enterprise/AdminStatsUsers.cs +++ b/Octokit/Models/Response/Enterprise/AdminStatsUsers.cs @@ -38,7 +38,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "TotalUsers: {0} AdminUsers: {1} SuspendedUsers: {2}", TotalUsers, AdminUsers, SuspendedUsers); + return string.Format(CultureInfo.InvariantCulture, "TotalUsers: {0} AdminUsers: {1} SuspendedUsers: {2}", TotalUsers, AdminUsers, SuspendedUsers); } } } diff --git a/Octokit/Models/Response/Enterprise/LdapSyncResponse.cs b/Octokit/Models/Response/Enterprise/LdapSyncResponse.cs index 3ee598a112..c3aabdda03 100644 --- a/Octokit/Models/Response/Enterprise/LdapSyncResponse.cs +++ b/Octokit/Models/Response/Enterprise/LdapSyncResponse.cs @@ -24,7 +24,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "Status: {0}", Status); + return string.Format(CultureInfo.InvariantCulture, "Status: {0}", Status); } } } diff --git a/Octokit/Models/Response/Enterprise/LicenseInfo.cs b/Octokit/Models/Response/Enterprise/LicenseInfo.cs index 03bd174c04..1805ffe431 100644 --- a/Octokit/Models/Response/Enterprise/LicenseInfo.cs +++ b/Octokit/Models/Response/Enterprise/LicenseInfo.cs @@ -59,7 +59,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "Seats: {0} SeatsUsed: {1} DaysUntilExpiration: {2}", Seats, SeatsUsed, DaysUntilExpiration); + return string.Format(CultureInfo.InvariantCulture, "Seats: {0} SeatsUsed: {1} DaysUntilExpiration: {2}", Seats, SeatsUsed, DaysUntilExpiration); } } } diff --git a/Octokit/Models/Response/Enterprise/MaintenanceModeActiveProcesses.cs b/Octokit/Models/Response/Enterprise/MaintenanceModeActiveProcesses.cs new file mode 100644 index 0000000000..57b475c87f --- /dev/null +++ b/Octokit/Models/Response/Enterprise/MaintenanceModeActiveProcesses.cs @@ -0,0 +1,34 @@ +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class MaintenanceModeActiveProcesses + { + public MaintenanceModeActiveProcesses() { } + + public MaintenanceModeActiveProcesses(string name, int number) + { + Name = name; + Number = number; + } + + public string Name { get; protected set; } + + public int Number { get; protected set; } + + public override string ToString() + { + return string.Format(CultureInfo.InvariantCulture, "{0} ({1})", Name, Number); + } + + internal string DebuggerDisplay + { + get + { + return this.ToString(); + } + } + } +} diff --git a/Octokit/Models/Response/Enterprise/MaintenanceModeResponse.cs b/Octokit/Models/Response/Enterprise/MaintenanceModeResponse.cs new file mode 100644 index 0000000000..127aa509eb --- /dev/null +++ b/Octokit/Models/Response/Enterprise/MaintenanceModeResponse.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using Octokit.Internal; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class MaintenanceModeResponse + { + public MaintenanceModeResponse() { } + + public MaintenanceModeResponse(MaintenanceModeStatus status, string scheduledTime, IReadOnlyList activeProcesses) + { + Status = status; + ScheduledTime = scheduledTime; + ActiveProcesses = activeProcesses; + } + + public StringEnum Status + { + get; + private set; + } + + public string ScheduledTime + { + get; + private set; + } + + [Parameter(Key = "connection_services")] + public IReadOnlyList ActiveProcesses + { + get; + private set; + } + + internal string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, + "Status: {0} ScheduledTime: {1} Connections: {2}", + Status, + ScheduledTime ?? "", + string.Join(", ", ActiveProcesses)); + } + } + } + + public enum MaintenanceModeStatus + { + [Parameter(Value = "off")] + Off, + [Parameter(Value = "on")] + On, + [Parameter(Value = "scheduled")] + Scheduled + } +} \ No newline at end of file diff --git a/Octokit/Models/Response/Enterprise/SearchIndexingResponse.cs b/Octokit/Models/Response/Enterprise/SearchIndexingResponse.cs index 6b5b194dc2..fbb46eecf8 100644 --- a/Octokit/Models/Response/Enterprise/SearchIndexingResponse.cs +++ b/Octokit/Models/Response/Enterprise/SearchIndexingResponse.cs @@ -25,7 +25,7 @@ internal string DebuggerDisplay { get { - return String.Format(CultureInfo.InvariantCulture, "Message: {0}", string.Join("\r\n", Message)); + return string.Format(CultureInfo.InvariantCulture, "Message: {0}", string.Join("\r\n", Message)); } } } diff --git a/Octokit/Models/Response/EventInfo.cs b/Octokit/Models/Response/EventInfo.cs index 3e5c31d91b..4512ef610c 100644 --- a/Octokit/Models/Response/EventInfo.cs +++ b/Octokit/Models/Response/EventInfo.cs @@ -11,7 +11,7 @@ public class EventInfo { public EventInfo() { } - public EventInfo(int id, string nodeId, string url, User actor, User assignee, Label label, EventInfoState @event, string commitId, DateTimeOffset createdAt) + public EventInfo(long id, string nodeId, string url, User actor, User assignee, Label label, EventInfoState @event, string commitId, DateTimeOffset createdAt) { Id = id; NodeId = nodeId; @@ -27,7 +27,7 @@ public EventInfo(int id, string nodeId, string url, User actor, User assignee, L /// /// The id of the issue/pull request event. /// - public int Id { get; protected set; } + public long Id { get; protected set; } /// /// GraphQL Node Id @@ -186,6 +186,12 @@ public enum EventInfoState [Parameter(Value = "head_ref_restored")] HeadRefRestored, + /// + /// The pull request’s branch was force pushed to. + /// + [Parameter(Value = "head_ref_force_pushed")] + HeadRefForcePushed, + /// /// The actor dismissed a review from the pull request. /// @@ -263,7 +269,7 @@ public enum EventInfoState Crossreferenced, /// - /// The issue was reveiewed. + /// The issue was reviewed. /// [Parameter(Value = "reviewed")] Reviewed, @@ -296,6 +302,12 @@ public enum EventInfoState /// An issue comment was deleted. /// [Parameter(Value = "comment_deleted")] - CommentDeleted + CommentDeleted, + + /// + /// An issue was transferred. + /// + [Parameter(Value = "transferred")] + Transferred } } diff --git a/Octokit/Models/Response/Installation.cs b/Octokit/Models/Response/Installation.cs index 66ccaea8e9..83a7817a0c 100644 --- a/Octokit/Models/Response/Installation.cs +++ b/Octokit/Models/Response/Installation.cs @@ -65,7 +65,7 @@ public Installation(long id, User account, string accessTokenUrl, string reposit public IReadOnlyList Events { get; private set; } /// - /// The single file the GitHub App can managem (when Permissions.SingleFile is set to read or write) + /// The single file the GitHub App can manage (when Permissions.SingleFile is set to read or write) /// public string SingleFileName { get; protected set; } diff --git a/Octokit/Models/Response/IssueComment.cs b/Octokit/Models/Response/IssueComment.cs index 989fe65ea7..9ef576f89d 100644 --- a/Octokit/Models/Response/IssueComment.cs +++ b/Octokit/Models/Response/IssueComment.cs @@ -10,7 +10,7 @@ public class IssueComment { public IssueComment() { } - public IssueComment(int id, string nodeId, string url, string htmlUrl, string body, DateTimeOffset createdAt, DateTimeOffset? updatedAt, User user, ReactionSummary reactions) + public IssueComment(int id, string nodeId, string url, string htmlUrl, string body, DateTimeOffset createdAt, DateTimeOffset? updatedAt, User user, ReactionSummary reactions, AuthorAssociation authorAssociation) { Id = id; NodeId = nodeId; @@ -21,6 +21,7 @@ public IssueComment(int id, string nodeId, string url, string htmlUrl, string bo UpdatedAt = updatedAt; User = user; Reactions = reactions; + AuthorAssociation = authorAssociation; } /// @@ -63,6 +64,11 @@ public IssueComment(int id, string nodeId, string url, string htmlUrl, string bo /// public User User { get; protected set; } + /// + /// The comment author association with repository. + /// + public StringEnum AuthorAssociation { get; protected set; } + /// /// The reaction summary for this comment. /// diff --git a/Octokit/Models/Response/IssueEvent.cs b/Octokit/Models/Response/IssueEvent.cs index e26d50c080..bd186b0aca 100644 --- a/Octokit/Models/Response/IssueEvent.cs +++ b/Octokit/Models/Response/IssueEvent.cs @@ -9,7 +9,7 @@ public class IssueEvent { public IssueEvent() { } - public IssueEvent(int id, string nodeId, string url, User actor, User assignee, Label label, EventInfoState @event, string commitId, DateTimeOffset createdAt, Issue issue, string commitUrl) + public IssueEvent(long id, string nodeId, string url, User actor, User assignee, Label label, EventInfoState @event, string commitId, DateTimeOffset createdAt, Issue issue, string commitUrl) { Id = id; NodeId = nodeId; @@ -27,7 +27,7 @@ public IssueEvent(int id, string nodeId, string url, User actor, User assignee, /// /// The id of the issue/pull request event. /// - public int Id { get; protected set; } + public long Id { get; protected set; } /// /// GraphQL Node Id diff --git a/Octokit/Models/Response/Label.cs b/Octokit/Models/Response/Label.cs index 095bd2a23b..af23eda7e0 100644 --- a/Octokit/Models/Response/Label.cs +++ b/Octokit/Models/Response/Label.cs @@ -8,8 +8,9 @@ public class Label { public Label() { } - public Label(string url, string name, string nodeId, string color, string description, bool @default) + public Label(long id, string url, string name, string nodeId, string color, string description, bool @default) { + Id = id; Url = url; Name = name; NodeId = nodeId; @@ -18,6 +19,11 @@ public Label(string url, string name, string nodeId, string color, string descri Default = @default; } + /// + /// Id of the label + /// + public long Id { get; protected set; } + /// /// Url of the label /// diff --git a/Octokit/Models/Response/Milestone.cs b/Octokit/Models/Response/Milestone.cs index 3d1b77b755..aa67e362f8 100644 --- a/Octokit/Models/Response/Milestone.cs +++ b/Octokit/Models/Response/Milestone.cs @@ -14,10 +14,11 @@ public Milestone(int number) Number = number; } - public Milestone(string url, string htmlUrl, int number, string nodeId, ItemState state, string title, string description, User creator, int openIssues, int closedIssues, DateTimeOffset createdAt, DateTimeOffset? dueOn, DateTimeOffset? closedAt, DateTimeOffset? updatedAt) + public Milestone(string url, string htmlUrl, long id, int number, string nodeId, ItemState state, string title, string description, User creator, int openIssues, int closedIssues, DateTimeOffset createdAt, DateTimeOffset? dueOn, DateTimeOffset? closedAt, DateTimeOffset? updatedAt) { Url = url; HtmlUrl = htmlUrl; + Id = id; Number = number; NodeId = nodeId; State = state; @@ -42,6 +43,11 @@ public Milestone(string url, string htmlUrl, int number, string nodeId, ItemStat /// public string HtmlUrl { get; protected set; } + /// + /// The ID for this milestone. + /// + public long Id { get; protected set; } + /// /// The milestone number. /// diff --git a/Octokit/Models/Response/OrganizationMembership.cs b/Octokit/Models/Response/OrganizationMembership.cs new file mode 100644 index 0000000000..3ecc185eb7 --- /dev/null +++ b/Octokit/Models/Response/OrganizationMembership.cs @@ -0,0 +1,32 @@ +using System.Diagnostics; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class OrganizationMembership + { + public OrganizationMembership() + { + + } + + public OrganizationMembership(string url, StringEnum state, StringEnum role, string organizationUrl, Organization organization, User user) + { + Url = url; + State = state; + Role = role; + OrganizationUrl = organizationUrl; + Organization = organization; + User = user; + } + + public string Url { get; protected set; } + public StringEnum State { get; protected set; } + public StringEnum Role { get; protected set; } + public string OrganizationUrl { get; protected set; } + public Organization Organization { get; protected set; } + public User User { get; protected set; } + + internal string DebuggerDisplay => $"{nameof(OrganizationMembership)}: User: {User.Login}; Organization: {Organization.Login}; State: {State}; Role: {Role}"; + } +} diff --git a/Octokit/Models/Response/PagesBuild.cs b/Octokit/Models/Response/PagesBuild.cs index 64c5c4aebd..46c8fd0054 100644 --- a/Octokit/Models/Response/PagesBuild.cs +++ b/Octokit/Models/Response/PagesBuild.cs @@ -37,7 +37,7 @@ public PagesBuild(string url, PagesBuildStatus status, ApiError error, User push /// public ApiError Error { get; protected set; } /// - /// The user whose commit intiated the build. + /// The user whose commit initiated the build. /// public User Pusher { get; protected set; } /// diff --git a/Octokit/Models/Response/PullRequest.cs b/Octokit/Models/Response/PullRequest.cs index 99fab52019..eeef21d45a 100644 --- a/Octokit/Models/Response/PullRequest.cs +++ b/Octokit/Models/Response/PullRequest.cs @@ -16,7 +16,7 @@ public PullRequest(int number) Number = number; } - public PullRequest(long id, string nodeId, string url, string htmlUrl, string diffUrl, string patchUrl, string issueUrl, string statusesUrl, int number, ItemState state, string title, string body, DateTimeOffset createdAt, DateTimeOffset updatedAt, DateTimeOffset? closedAt, DateTimeOffset? mergedAt, GitReference head, GitReference @base, User user, User assignee, IReadOnlyList assignees, bool? mergeable, MergeableState? mergeableState, User mergedBy, string mergeCommitSha, int comments, int commits, int additions, int deletions, int changedFiles, Milestone milestone, bool locked, bool? maintainerCanModify, IReadOnlyList requestedReviewers) + public PullRequest(long id, string nodeId, string url, string htmlUrl, string diffUrl, string patchUrl, string issueUrl, string statusesUrl, int number, ItemState state, string title, string body, DateTimeOffset createdAt, DateTimeOffset updatedAt, DateTimeOffset? closedAt, DateTimeOffset? mergedAt, GitReference head, GitReference @base, User user, User assignee, IReadOnlyList assignees, bool draft, bool? mergeable, MergeableState? mergeableState, User mergedBy, string mergeCommitSha, int comments, int commits, int additions, int deletions, int changedFiles, Milestone milestone, bool locked, bool? maintainerCanModify, IReadOnlyList requestedReviewers, IReadOnlyList public IReadOnlyList RequestedReviewers { get; protected set; } + public IReadOnlyList public string NodeId { get; protected set; } + /// + /// team slug + /// + public string Slug { get; protected set; } + /// /// team name /// diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index a8e824d5fe..1d63045313 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -6,23 +6,33 @@ GitHub 0.0.0-dev true - netstandard1.1;net45 - 1.6.0 + netstandard1.1;netstandard2.0;net45;net46 Octokit Octokit embedded https://github.com/octokit/octokit.net https://github.com/octokit/octokit.net https://f.cloud.github.com/assets/19977/1510987/64af2b26-4a9d-11e3-89fc-96a185171c75.png + octokit.png + MIT GitHub API Octokit linqpad-samples dotnetcore Copyright GitHub 2017 + + $(DefineConstants);HAS_TYPEINFO;SIMPLE_JSON_INTERNAL;SIMPLE_JSON_OBJARRAYINTERNAL;SIMPLE_JSON_READONLY_COLLECTIONS;SIMPLE_JSON_TYPEINFO + + - $(DefineConstants);HAS_TYPEINFO;SIMPLE_JSON_INTERNAL;SIMPLE_JSON_OBJARRAYINTERNAL;SIMPLE_JSON_READONLY_COLLECTIONS;SIMPLE_JSON_TYPEINFO;NO_SERIALIZABLE + $(DefineConstants);NO_SERIALIZABLE + 1.6.0 - + + 2.0.0 + + + $(DefineConstants);HAS_ENVIRONMENT;HAS_REGEX_COMPILED_OPTIONS;SIMPLE_JSON_INTERNAL;SIMPLE_JSON_OBJARRAYINTERNAL;SIMPLE_JSON_READONLY_COLLECTIONS;HAS_SERVICEPOINTMANAGER @@ -30,16 +40,19 @@ 1591;1701;1702;1705 - + + + + + + - - - + diff --git a/Octokit/images/octokit.png b/Octokit/images/octokit.png new file mode 100644 index 0000000000..2efc9cfc0c Binary files /dev/null and b/Octokit/images/octokit.png differ diff --git a/README.md b/README.md index 2ccf3d55e2..a6aec83cb8 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,17 @@ # Octokit - GitHub API Client Library for .NET -[![Build status](https://ci.appveyor.com/api/projects/status/cego2g42yw26th26/branch/master?svg=true)](https://ci.appveyor.com/project/github-windows/octokit-net/branch/master) [![Build Status]( https://travis-ci.org/octokit/octokit.net.svg)]( https://travis-ci.org/octokit/octokit.net) [![Join the chat at https://gitter.im/octokit/octokit.net](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/octokit/octokit.net?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +![Build status](https://github.com/octokit/octokit.net/workflows/CI%20Build/badge.svg) +[![Build status](https://ci.appveyor.com/api/projects/status/cego2g42yw26th26/branch/master?svg=true)](https://ci.appveyor.com/project/github-windows/octokit-net/branch/master) +[![codecov](https://codecov.io/gh/octokit/octokit.net/branch/master/graph/badge.svg)](https://codecov.io/gh/octokit/octokit.net) +[![Join the chat at https://gitter.im/octokit/octokit.net](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/octokit/octokit.net?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![NuGet](http://img.shields.io/nuget/v/Octokit.svg)](https://www.nuget.org/packages/Octokit) +[![NuGet](http://img.shields.io/nuget/v/Octokit.Reactive.svg)](https://www.nuget.org/packages/Octokit.Reactive) ![logo](octokit-dotnet_2.png) -Octokit is a client library targeting .NET 4.5 and above that provides an easy -way to interact with the [GitHub API](http://developer.github.com/v3/). +Octokit is a client library targeting .NET Framework 4.5+ and .NET Standard 1+ +and above that provides an easy way to interact with the +[GitHub API](http://developer.github.com/v3/). ## Usage examples @@ -19,8 +25,8 @@ Console.WriteLine(user.Followers + " folks love the half ogre!"); ## Supported Platforms -* .NET 4.5 (Desktop / Server) -* [.NET Standard 1.1](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) +* .NET 4.5 (Desktop / Server) or greater +* [.NET Standard 1.1](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) or greater ## Getting Started @@ -73,8 +79,7 @@ for more details. All contributors are expected to follow our ## Problems? -Octokit is 100% certified to be bug free. If you find an issue with our -certification, please visit the [issue tracker](https://github.com/octokit/octokit.net/issues) +If you find an issue with our library, please visit the [issue tracker](https://github.com/octokit/octokit.net/issues) and report the issue. Please be kind and search to see if the issue is already logged before creating @@ -92,7 +97,7 @@ problem. ## Related Projects - - [ScriptCs.OctoKit](https://github.com/alfhenrik/ScriptCs.OctoKit) - a [script pack](https://github.com/scriptcs/scriptcs/wiki/Script-Packs) to use Octokit in scriptcs + - [ScriptCs.OctoKit](https://github.com/hnrkndrssn/ScriptCs.OctoKit) - a [script pack](https://github.com/scriptcs/scriptcs/wiki/Script-Packs) to use Octokit in scriptcs - [ScriptCs.OctokitLibrary](https://github.com/ryanrousseau/ScriptCs.OctokitLibrary) - a [script library](https://github.com/scriptcs/scriptcs/wiki/Script-Libraries) to use Octokit in scriptcs ## Copyright and License diff --git a/appveyor.yml b/appveyor.yml index 6d09d6be6b..4235f56e5e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -image: Visual Studio 2017 +image: Visual Studio 2019 branches: only: @@ -9,10 +9,11 @@ init: build_script: - dotnet --info + - dotnet tool install --global coverlet.console - ps: .\build.ps1 -LinkSources -Verbosity Verbose test: off artifacts: - path: 'packaging\octokit*.nupkg' - name: OctokitPackages \ No newline at end of file + name: OctokitPackages diff --git a/build.ps1 b/build.ps1 index 9826e3b2f6..c9d1cbf897 100644 --- a/build.ps1 +++ b/build.ps1 @@ -103,6 +103,13 @@ $Arguments = @{ dryrun=$WhatIf; }.GetEnumerator() | %{"--{0}=`"{1}`"" -f $_.key, $_.value }; +Write-Host "Restoring global tools..." +Invoke-Expression "dotnet tool restore" +if($LASTEXITCODE -ne 0) { + Pop-Location; + exit $LASTEXITCODE; +} + # Start Cake Push-Location Set-Location build diff --git a/build.sh b/build.sh index db1aeb14a7..4393a1eed8 100755 --- a/build.sh +++ b/build.sh @@ -6,10 +6,13 @@ if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then echo "new limit: `ulimit -n`" fi +echo "Restoring global tools" +dotnet tool restore + cd build echo "Preparing Cake.Frosting build runner..." dotnet restore echo "Executing Cake.Frosting build runner..." echo "dotnet run -- $@" -dotnet run -- "$@" \ No newline at end of file +dotnet run -- "$@" diff --git a/build/.vscode/launch.json b/build/.vscode/launch.json index b097db5239..1c67c5f4c1 100644 --- a/build/.vscode/launch.json +++ b/build/.vscode/launch.json @@ -10,7 +10,7 @@ "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceFolder}/bin/Debug/netcoreapp2.0/Build.dll", + "program": "${workspaceFolder}/bin/Debug/netcoreapp3.1/Build.dll", "args": [], "cwd": "${workspaceFolder}", // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window @@ -25,4 +25,4 @@ "processId": "${command:pickProcess}" } ,] -} \ No newline at end of file +} diff --git a/build/Build.csproj b/build/Build.csproj index fd8fc3b0c1..02360e683f 100644 --- a/build/Build.csproj +++ b/build/Build.csproj @@ -2,11 +2,14 @@ Exe - netcoreapp2.0 + netcoreapp3.1 - + + + + diff --git a/build/Context.cs b/build/Context.cs index 12f6cb437f..dc5685f624 100644 --- a/build/Context.cs +++ b/build/Context.cs @@ -8,11 +8,13 @@ public class Context : FrostingContext { public string Target { get; set; } - public string Configuration { get; set; } + public new string Configuration { get; set; } public bool LinkSources { get; set; } + public bool FormatCode { get; set; } public BuildVersion Version { get; set; } public DirectoryPath Artifacts { get; set; } + public DirectoryPath CodeCoverage { get; set; } public bool IsLocalBuild { get; set; } public bool IsPullRequest { get; set; } @@ -22,10 +24,13 @@ public class Context : FrostingContext public bool ForcePublish { get; set; } public bool AppVeyor { get; set; } - public bool TravisCI { get; set; } + public bool GitHubActions { get; set; } public Project[] Projects { get; set; } + public FilePath DotNetFormatToolPath { get; set; } + public FilePath GitVersionToolPath { get; set; } + public DotNetCoreTestSettings GetTestSettings() { var settings = new DotNetCoreTestSettings @@ -36,7 +41,7 @@ public DotNetCoreTestSettings GetTestSettings() if (!this.IsRunningOnWindows()) { - var testFramework = "netcoreapp2.0"; + var testFramework = "netcoreapp3.1"; this.Information($"Running tests against {testFramework} only as we're not on Windows."); settings.Framework = testFramework; @@ -49,4 +54,4 @@ public Context(ICakeContext context) : base(context) { } -} \ No newline at end of file +} diff --git a/build/Lifetime.cs b/build/Lifetime.cs index b899a09d9d..0075dd74ec 100644 --- a/build/Lifetime.cs +++ b/build/Lifetime.cs @@ -12,15 +12,17 @@ public override void Setup(Context context) context.Target = context.Argument("target", "Default"); context.Configuration = context.Argument("configuration", "Release"); context.LinkSources = context.Argument("linkSources", false); + context.FormatCode = context.Argument("formatCode", false); context.Artifacts = "./packaging/"; + context.CodeCoverage = "./coverage-results/"; // Build system information. var buildSystem = context.BuildSystem(); context.IsLocalBuild = buildSystem.IsLocalBuild; + context.GitHubActions = buildSystem.GitHubActions.IsRunningOnGitHubActions; context.AppVeyor = buildSystem.AppVeyor.IsRunningOnAppVeyor; - context.TravisCI = buildSystem.TravisCI.IsRunningOnTravisCI; context.IsTagged = IsBuildTagged(buildSystem); if (context.AppVeyor) @@ -29,11 +31,11 @@ public override void Setup(Context context) context.IsOriginalRepo = StringComparer.OrdinalIgnoreCase.Equals("octokit/octokit.net", buildSystem.AppVeyor.Environment.Repository.Name); context.IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals("master", buildSystem.AppVeyor.Environment.Repository.Branch); } - else if (context.TravisCI) + else if (context.GitHubActions) { - context.IsPullRequest = !string.IsNullOrEmpty(buildSystem.TravisCI.Environment.Repository.PullRequest); - context.IsOriginalRepo = StringComparer.OrdinalIgnoreCase.Equals("octokit/octokit.net", buildSystem.TravisCI.Environment.Repository.Slug); - context.IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals("master", buildSystem.TravisCI.Environment.Build.Branch); + context.IsPullRequest = buildSystem.GitHubActions.Environment.PullRequest.IsPullRequest; + context.IsOriginalRepo = StringComparer.OrdinalIgnoreCase.Equals("octokit/octokit.net", buildSystem.GitHubActions.Environment.Workflow.Repository); + context.IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals("master", buildSystem.GitHubActions.Environment.Workflow.Ref); } // Force publish? @@ -49,10 +51,8 @@ public override void Setup(Context context) new Project { Name = "Octokit.Tests.Integration", Path = "./Octokit.Tests.Integration/Octokit.Tests.Integration.csproj", IntegrationTests = true } }; - // Install tools - context.Information("Installing tools..."); - ToolInstaller.Install(context, "GitVersion.CommandLine", "3.6.2"); - ToolInstaller.Install(context, "Octokit.CodeFormatter", "1.0.0-preview"); + context.DotNetFormatToolPath = ToolInstaller.DotNetCoreToolInstall(context, "dotnet-format", "3.1.37601", "dotnet-format"); + context.GitVersionToolPath = ToolInstaller.DotNetCoreToolInstall(context, "GitVersion.Tool", "5.1.3", "dotnet-gitversion"); // Calculate semantic version. context.Version = BuildVersion.Calculate(context); @@ -65,7 +65,7 @@ public override void Setup(Context context) context.Information("LinkSources: {0}", context.LinkSources); context.Information("Target: {0}", context.Target); context.Information("AppVeyor: {0}", context.AppVeyor); - context.Information("TravisCI: {0}", context.TravisCI); + context.Information("GitHub Actions: {0}", context.GitHubActions); } private static bool IsBuildTagged(BuildSystem buildSystem) @@ -83,4 +83,4 @@ private static string GetEnvironmentValueOrArgument(Context context, string envi } return arg; } -} \ No newline at end of file +} diff --git a/build/Tasks/Build.cs b/build/Tasks/Build.cs index 68035fc0bd..67c76bf6b4 100644 --- a/build/Tasks/Build.cs +++ b/build/Tasks/Build.cs @@ -4,6 +4,7 @@ using Cake.Frosting; [Dependency(typeof(Restore))] +[Dependency(typeof(FormatCode))] public class Build : FrostingTask { public override void Run(Context context) @@ -13,7 +14,7 @@ public override void Run(Context context) Configuration = context.Configuration, ArgumentCustomization = args => args .Append("/p:Version={0}", context.Version.GetSemanticVersion()) - .Append("/p:SourceLinkCreate={0}", context.LinkSources.ToString().ToLower()) + .Append("/p:SourceLinkCreate={0}", context.LinkSources.ToString().ToLower()), }); } -} \ No newline at end of file +} diff --git a/build/Tasks/Clean.cs b/build/Tasks/Clean.cs index 8975abb2c6..f0a82f1473 100644 --- a/build/Tasks/Clean.cs +++ b/build/Tasks/Clean.cs @@ -1,13 +1,20 @@ using Cake.Common.IO; +using Cake.Core.IO; using Cake.Frosting; public sealed class Clean : FrostingTask { public override void Run(Context context) { - var directories = context.GetDirectories("./**/bin", x => !x.Path.FullPath.Contains("/build/")) - + context.GetDirectories("./**/obj", x => !x.Path.FullPath.Contains("/build/")) - + context.Artifacts; + var globberSettings = new GlobberSettings + { + Predicate = x => !x.Path.FullPath.Contains("/build/") + }; + + var directories = context.GetDirectories("./**/bin", globberSettings) + + context.GetDirectories("./**/obj", globberSettings) + + context.Artifacts + + context.CodeCoverage; foreach (var directory in directories) { diff --git a/build/Tasks/CodeCoverage.cs b/build/Tasks/CodeCoverage.cs new file mode 100644 index 0000000000..e972a12116 --- /dev/null +++ b/build/Tasks/CodeCoverage.cs @@ -0,0 +1,75 @@ +using System.Collections.Generic; +using System.Linq; +using Cake.Codecov; +using Cake.Common; +using Cake.Common.Build; +using Cake.Common.Diagnostics; +using Cake.Core.IO; +using Cake.Frosting; + +[Dependency(typeof(Build))] +public sealed class CodeCoverage : FrostingTask +{ + public override void Run(Context context) + { + var coverageFiles = new List(); + + if (context.AppVeyor) + { + foreach (var project in context.Projects.Where(x => x.UnitTests)) + { + context.Information("Executing Code Coverage for Project {0}...", project.Name); + + var dotNetCoreCoverage = context.CodeCoverage + .CombineWithFilePath(project.Name + "-netcoreapp3.1.xml"); + coverageFiles.Add(dotNetCoreCoverage); + + context.Coverlet(project, new CoverletToolSettings() + { + Configuration = context.Configuration, + Framework = "netcoreapp3.1", + Output = dotNetCoreCoverage.FullPath + }); + + if (context.IsRunningOnWindows()) + { + var dotNetFrameworkCoverage = context.CodeCoverage + .CombineWithFilePath(project.Name + "-net46.xml"); + coverageFiles.Add(dotNetFrameworkCoverage); + + context.Coverlet(project, new CoverletToolSettings + { + Configuration = context.Configuration, + Framework = "net452", + Output = dotNetFrameworkCoverage.FullPath + }); + } + + context.Information("Uploading Coverage Files: {0}", string.Join(",", coverageFiles.Select(path => path.GetFilename().ToString()))); + + var buildVersion = $"{context.Version.FullSemVer}.build.{context.EnvironmentVariable("APPVEYOR_BUILD_NUMBER")}"; + + var userProfilePath = context.EnvironmentVariable("USERPROFILE"); + var codecovPath = new DirectoryPath(userProfilePath) + .CombineWithFilePath(".nuget\\packages\\codecov\\1.10.0\\tools\\codecov.exe"); + + context.Tools.RegisterFile(codecovPath); + + foreach (var coverageFile in coverageFiles) + { + var settings = new CodecovSettings + { + Files = new[] { coverageFile.MakeAbsolute(context.Environment).FullPath }, + Verbose = true, + EnvironmentVariables = new Dictionary() + { + { "APPVEYOR_BUILD_VERSION", buildVersion} + } + }; + + context.Codecov(settings); + } + } + } + } +} diff --git a/build/Tasks/FormatCode.cs b/build/Tasks/FormatCode.cs index 57f44b9415..49353a336e 100644 --- a/build/Tasks/FormatCode.cs +++ b/build/Tasks/FormatCode.cs @@ -1,74 +1,20 @@ using System; -using System.IO; -using System.Linq; using Cake.Common; -using Cake.Common.Diagnostics; -using Cake.Core; -using Cake.Core.IO; using Cake.Frosting; public sealed class FormatCode : FrostingTask { public override void Run(Context context) { - var codeFormatterExe = context.FileSystem - .GetDirectory("tools") - .GetFiles("CodeFormatter.exe", SearchScope.Recursive) - .First() - .Path - .MakeAbsolute(context.Environment); - - foreach (var project in context.Projects) + int result = context.StartProcess(context.DotNetFormatToolPath); + if (result != 0) { - context.Information("Formatting code of {0}", project.Name); - - var tempCsprojFile = CreateTempCsproj(context, project.Name); - context.Information("Generated temporary {0} file to run the formatter", new FilePath(tempCsprojFile).GetFilename()); - - var exitCode = context.StartProcess( - codeFormatterExe, - $"{tempCsprojFile} /nocopyright /nounicode"); - - if (exitCode != 0) - { - throw new CakeException($"An error occured while formatting code of {project.Name}"); - } + throw new Exception($"Failed to execute {context.DotNetFormatToolPath} ({result})"); } - - context.Information("Successfully formatted code of all the projects"); } public override bool ShouldRun(Context context) { - return context.IsRunningOnWindows(); - } - - private static string CreateTempCsproj(Context context, string projectName) - { - DirectoryPath tempFolder = System.IO.Path.GetTempPath(); - var projectCsproj = tempFolder.CombineWithFilePath($"{projectName}.csproj").FullPath; - - var files = context.FileSystem - .GetDirectory(projectName) - .GetFiles("*.cs", SearchScope.Recursive) - .Select(x => x.Path.MakeAbsolute(context.Environment)) - .ToArray(); - - var compileElements = files - .Select(x => $"") - .ToArray(); - - var csprojContent = -$@" - - - {string.Join(Environment.NewLine, compileElements)} - - -"; - - File.WriteAllText(projectCsproj, csprojContent); - - return projectCsproj; + return context.FormatCode; } } diff --git a/build/Tasks/Package.cs b/build/Tasks/Package.cs index 34f423522f..6562842685 100644 --- a/build/Tasks/Package.cs +++ b/build/Tasks/Package.cs @@ -6,6 +6,7 @@ [Dependency(typeof(UnitTests))] [Dependency(typeof(ConventionTests))] +[Dependency(typeof(CodeCoverage))] [Dependency(typeof(ValidateLINQPadSamples))] public sealed class Package : FrostingTask { @@ -21,9 +22,10 @@ public override void Run(Context context) Configuration = context.Configuration, NoBuild = true, OutputDirectory = context.Artifacts, - ArgumentCustomization = args => args.Append("/p:Version={0}", context.Version.GetSemanticVersion()) + ArgumentCustomization = args => args + .Append("/p:Version={0}", context.Version.GetSemanticVersion()), }); } } } -} \ No newline at end of file +} diff --git a/build/Tools/Coverlet.cs b/build/Tools/Coverlet.cs new file mode 100644 index 0000000000..8b94f29713 --- /dev/null +++ b/build/Tools/Coverlet.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using Cake.Common.Diagnostics; +using Cake.Core; +using Cake.Core.Annotations; +using Cake.Core.IO; +using Cake.Core.Tooling; + +public class CoverletTool : Tool +{ + private readonly ICakeEnvironment _environment; + + public CoverletTool(IFileSystem fileSystem, ICakeEnvironment environment, IProcessRunner runner, IToolLocator tools) + : base(fileSystem, environment, runner, tools) + { + _environment = environment; + } + + public void Coverlet(Project project, CoverletToolSettings settings) + { + var arguments = new ProcessArgumentBuilder(); + + var filePath = FilePath.FromString($"bin\\{settings.Configuration}\\{settings.Framework}\\{project.Name}.dll"); + var fullPath = project.Path.GetDirectory().CombineWithFilePath(filePath).MakeAbsolute(_environment); + + arguments.Append($"\"{fullPath}\" --target \"dotnet\" --targetargs \"test -c {settings.Configuration} {project.Path.FullPath} --no-build\" --format opencover --output \"{settings.Output}\""); + + Run(settings, arguments); + } + + protected override string GetToolName() + { + return "Coverlet"; + } + + protected override IEnumerable GetToolExecutableNames() + { + return new[] { "coverlet", "coverlet.exe" }; + } +} + +public class CoverletToolSettings : ToolSettings +{ + public string Configuration { get; set; } + public string Framework { get; set; } + public string Output { get; set; } +} + +public static class CoverletAliases +{ + [CakeMethodAlias] + public static void Coverlet(this ICakeContext context, Project project, CoverletToolSettings settings = null) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + if (settings == null) + throw new ArgumentNullException(nameof(settings)); + + new CoverletTool(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools).Coverlet(project, settings); + } +} \ No newline at end of file diff --git a/build/Utilities/BuildVersion.cs b/build/Utilities/BuildVersion.cs index e945b1a8de..7c4985981c 100644 --- a/build/Utilities/BuildVersion.cs +++ b/build/Utilities/BuildVersion.cs @@ -6,11 +6,13 @@ public class BuildVersion { public string Prefix { get; set; } public string Suffix { get; set; } + public string FullSemVer { get; set; } - public BuildVersion(string version, string suffix) + public BuildVersion(string version, string suffix, string fullSemVer) { Prefix = version; Suffix = suffix; + FullSemVer = fullSemVer; if (string.IsNullOrWhiteSpace(Suffix)) { @@ -31,8 +33,10 @@ public static BuildVersion Calculate(Context context) { string version = null; string semVersion = null; + string fullSemVer = null; context.Information("Calculating semantic version..."); + if (!context.IsLocalBuild) { // Run to set the version properties inside the CI server @@ -44,12 +48,13 @@ public static BuildVersion Calculate(Context context) version = assertedversions.MajorMinorPatch; semVersion = assertedversions.LegacySemVerPadded; + fullSemVer = assertedversions.FullSemVer; if (string.IsNullOrWhiteSpace(version)) { throw new CakeException("Could not calculate version of build."); } - return new BuildVersion(version, semVersion.Substring(version.Length).TrimStart('-')); + return new BuildVersion(version, semVersion.Substring(version.Length).TrimStart('-'), fullSemVer); } } \ No newline at end of file diff --git a/build/Utilities/GitVersionRunner.cs b/build/Utilities/GitVersionRunner.cs index d91de55237..17d5e5caf6 100644 --- a/build/Utilities/GitVersionRunner.cs +++ b/build/Utilities/GitVersionRunner.cs @@ -1,29 +1,13 @@ -using Cake.Common; -using Cake.Common.Diagnostics; -using Cake.Common.Tools.GitVersion; -using Cake.Core; +using Cake.Common.Tools.GitVersion; public static class GitVersionRunner { - public static GitVersion Run(ICakeContext context, GitVersionOutput outputType) + public static GitVersion Run(Context context, GitVersionOutput outputType) { - if (context.IsRunningOnWindows()) + return context.GitVersion(new GitVersionSettings { - return context.GitVersion(new GitVersionSettings - { - OutputType = outputType - }); - } - else - { - // On non windows platform, point the GitVersion task at our wrapper script that uses mono to run GitVersion.exe - context.Information("Overriding GitVersion ToolPath to /bin/sh ./tools/gitversion_wrapper.sh"); - return context.GitVersion(new GitVersionSettings - { - OutputType = outputType, - ToolPath = "/bin/sh", - ArgumentCustomization = args => args.Prepend("./tools/gitversion_wrapper.sh") - }); - } + OutputType = outputType, + ToolPath = context.GitVersionToolPath + }); } } \ No newline at end of file diff --git a/build/Utilities/ToolInstaller.cs b/build/Utilities/ToolInstaller.cs index e61e248b8b..1a03d21526 100644 --- a/build/Utilities/ToolInstaller.cs +++ b/build/Utilities/ToolInstaller.cs @@ -1,16 +1,76 @@ -using Cake.Common.Tools.NuGet; +using Cake.Common.IO; +using Cake.Common.Tools.DotNetCore; +using Cake.Common.Tools.DotNetCore.Tool; +using Cake.Common.Tools.NuGet; using Cake.Common.Tools.NuGet.Install; using Cake.Core; +using Cake.Core.IO; public static class ToolInstaller { + private static DirectoryPath ToolsPath { get; } = "./tools"; public static void Install(ICakeContext context, string package, string version) { context.NuGetInstall(package, new NuGetInstallSettings { Version = version, ExcludeVersion = true, - OutputDirectory = "./tools" + OutputDirectory = ToolsPath }); } + + public static FilePath DotNetCoreToolInstall( + this ICakeContext context, + string package, + string version, + string toolName) + { + context.EnsureDirectoryExists(ToolsPath); + + var toolsPath = context.MakeAbsolute(ToolsPath); + + var toolInstallPath = toolsPath + .Combine(".store") + .Combine(package.ToLowerInvariant()) + .Combine(version.ToLowerInvariant()); + + var toolPath = toolsPath.CombineWithFilePath( + string.Concat( + toolName, + context.Environment.Platform.IsUnix() + ? string.Empty + : ".exe" + ) + ); + + if (!context.DirectoryExists(toolInstallPath) && context.FileExists(toolPath)) + { + context.DotNetCoreTool("tool", new DotNetCoreToolSettings + { + ArgumentCustomization = args => args + .Append("uninstall") + .AppendSwitchQuoted("--tool-path", toolsPath.FullPath) + .AppendQuoted(package) + }); + } + + if (!context.FileExists(toolPath)) + { + context.DotNetCoreTool("tool", new DotNetCoreToolSettings + { + ArgumentCustomization = args => args + .Append("install") + .AppendSwitchQuoted("--version", version) + .AppendSwitchQuoted("--tool-path", toolsPath.FullPath) + .AppendQuoted(package) + }); + } + + if (!context.FileExists(toolPath)) + { + throw new System.Exception($"Failed to install .NET Core tool {package} ({version})."); + } + + return toolPath; + } } \ No newline at end of file diff --git a/build/nuget.config b/build/nuget.config deleted file mode 100644 index 09f2371f41..0000000000 --- a/build/nuget.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000000..6d84812d82 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,29 @@ +codecov: + notify: + require_ci_to_pass: yes + +coverage: + precision: 2 + round: down + range: "70...100" + + status: + project: yes + patch: yes + changes: no + +parsers: + gcov: + branch_detection: + conditional: yes + loop: yes + method: no + macro: no + +comment: + layout: "header, diff, files" + behavior: once + require_changes: no + +fixes: + - "/C/projects/octokit-net/::" diff --git a/docs/demos/exploring-pull-requests.md b/docs/demos/exploring-pull-requests.md index 231cfe929b..577cae3318 100644 --- a/docs/demos/exploring-pull-requests.md +++ b/docs/demos/exploring-pull-requests.md @@ -1,3 +1,24 @@ +### Creating new pull request from a fork +**Scenario:** +Creating a pull request from a fork/branch (head) and pulling into octokit.net/master (base) +When you are opening a PR against a repository within an organization, owner is the name of the organization +In this scenario as we are merging to octokit/octokit.net:master, owner=octokit + +```csharp +public async Task CreatePullRequestFromFork() +{ + GitHubClient ghClient = new GitHubClient(new ProductHeaderValue("MyLib", "v2.0.0")); + ghClient.Credentials = new Credentials("apiToken"); + + NewPullRequest newPr = new NewPullRequest("PrTitle", "forkName:branchName", "master"); + var octokitRepo = await ghClient.Repository.Get("octokit", "ocktokit.net"); + + var pullRequest = await ghClient.PullRequest.Create("octokit", "octokit.net", newPr); + // Or + var alternatePr = await ghClient.PullRequest.Create(octokitRepo.Id, newPr); +} +``` + **Scenario:** I have a lot of small pull requests to review, but things are a mess - old pull requests which might be superseded by new ones, and it's hard to see from the descriptions what the changes actually represent. diff --git a/docs/enterprise-administration.md b/docs/enterprise-administration.md new file mode 100644 index 0000000000..b4c99060eb --- /dev/null +++ b/docs/enterprise-administration.md @@ -0,0 +1,73 @@ +# GitHub Enterprise Administration + +Octokit also ships with support for the administration APIs that GitHub +Enterprise includes to script tasks for administrators. + +```c# +var enterprise = new Uri("https://github.myenterprise.com/"); +var github = new GitHubClient("some app name", enterprise); +github.Credentials = new Credentials("some-token-here"); + +var stats = await github.Enterprise.AdminStats.GetStatisticsUsers(); +Console.WriteLine($"Found {stats.AdminUsers} admins, {stats.TotalUsers} total users and {stats.SuspendedUsers} suspended users"); +``` + +Some caveats on using these APIs that you should be aware of: + + - only administrators of the GitHub Enterprise instance are able to access + these APIs + - administrators creating OAuth tokens to use this endpoint must ensure the + `site_admin` scope is set + - the [Management Console API](https://developer.github.com/enterprise/2.18/v3/enterprise/management_console/) + also require providing the password created during setup of the GitHub + Enterprise installation to confirm the action + +You can read more about this support [on the GitHub website](https://developer.github.com/enterprise/2.18/v3/enterprise-admin/). + + +## Management console + +To view the maintenance mode status of a GitHub Enteprise installation: + +```C# +var maintenance = await github.Enterprise.ManagementConsole.GetMaintenanceMode("management-console-password"); +``` + +To put the GitHub Enterprise installation into maintenance mode immediately: + +```C# +var request = new UpdateMaintenanceRequest(new UpdateMaintenanceRequestDetails(true)); +var maintenance = await github.Enterprise.ManagementConsole.EditMaintenanceMode( + request, + "management-console-password"); +``` + +You can also provide a human-friendly phrase based on the rules in +[`mojombo/chronic`](https://github.com/mojombo/chronic): + +```C# +var request = new UpdateMaintenanceRequest(new UpdateMaintenanceRequestDetails(true, "tomorrow at 5pm")); +var maintenance = await github.Enterprise.ManagementConsole.EditMaintenanceMode( + request, + "management-console-password"); +``` + +To put the GitHub Enterprise installation into maintenance mode after a period +of time: + +```C# +var scheduledTime = DateTimeOffset.Now.AddMinutes(10); +var request = new UpdateMaintenanceRequest(new UpdateMaintenanceRequestDetails(true, scheduledTime)); +var maintenance = await github.Enterprise.ManagementConsole.EditMaintenanceMode( + request, + "management-console-password"); +``` + +To disable maintenance mode, simple pass in `false` or leave the `request` +constructor empty: + +```c# +var maintenance = await github.Enterprise.ManagementConsole.EditMaintenanceMode( + new UpdateMaintenanceRequest(), // off by default if nothing specified + "management-console-password"); +``` diff --git a/docs/github-apps.md b/docs/github-apps.md index 89787aaa15..06dc6759e7 100644 --- a/docs/github-apps.md +++ b/docs/github-apps.md @@ -35,9 +35,9 @@ Each GitHub App has a private certificate (PEM file) which is [generated via the The first step in the authentication process, is to generate a temporary JWT token, signed by the GitHub App's private certificate. It also needs to include the GitHub App's unique Id, which is obtainable from the GitHub website. -:bulb: There are several ways to generate JWT tokens in .NET and this library aims to have minimal depdendencies on other libraries. Therefore the expectation is that your app will create the JWT token however you see fit, and pass it in to Octokit.net. The example below contains a hardcoded JWT token string as an example. See the Additional Notes section for one recommended library, to generate the JWT token. +:bulb: There are several ways to generate JWT tokens in .NET and this library aims to have minimal dependencies on other libraries. Therefore the expectation is that your app will create the JWT token however you see fit, and pass it in to Octokit.net. The example below contains a hardcoded JWT token string as an example. See the Additional Notes section for one recommended library, to generate the JWT token. -:warning: GitHub enforces that the JWT token used can only be valid for a maximum of 10 minutes - a new token will be required after this time. In the future, Octokit.net may provide hooks/helpers to help you take care of this, but for now your appliction will need to handle this itself. +:warning: GitHub enforces that the JWT token used can only be valid for a maximum of 10 minutes - a new token will be required after this time. In the future, Octokit.net may provide hooks/helpers to help you take care of this, but for now your application will need to handle this itself. ``` csharp // A time based JWT token, signed by the GitHub App's private certificate @@ -68,7 +68,7 @@ In order to do more than top level calls, a `GitHubApp` needs to authenticate as :bulb: The example below includes a hardcoded Installation Id, but this would typically come from a webhook payload (so a GitHub App knows which Installation it needs to authenticate as, to deal with the received webhook). See the Additional Notes section for more details on Installation Id's in webhooks. -:warning: These temporary Installation Tokens are only valid for 1 hour, and a new Installation Token will be required after this time. In the future, Octokit.net may provide hooks/helpers to help you take care of this, but for now your appliction will need to handle this itself. +:warning: These temporary Installation Tokens are only valid for 1 hour, and a new Installation Token will be required after this time. In the future, Octokit.net may provide hooks/helpers to help you take care of this, but for now your application will need to handle this itself. ``` csharp // Create an Installation token for Insallation Id 123 @@ -98,7 +98,7 @@ That concludes the walkthrough! ## Additional Notes ### A Note on JWT Tokens -Octokit.net aims to have no external dependencies, therefore we do not curently have the ability to generate/sign JWT tokens for you, and instead expect that you will pass in the appropriately signed JWT token required to authenticate the `GitHubApp`. +Octokit.net aims to have no external dependencies, therefore we do not currently have the ability to generate/sign JWT tokens for you, and instead expect that you will pass in the appropriately signed JWT token required to authenticate the `GitHubApp`. Luckily one of our contributors [@adriangodong](https://github.com/adriangodong) has created a library `GitHubJwt` ( [GitHub](https://github.com/adriangodong/githubjwt) | [NuGet](https://www.nuget.org/packages/githubjwt) ) which you can use as per the following example. diff --git a/docs/issues.md b/docs/issues.md index fa872c1ef7..e69fc0f653 100644 --- a/docs/issues.md +++ b/docs/issues.md @@ -109,7 +109,7 @@ With this issue, you can transform it into an `IssueUpdate` using the extension var update = issue.ToUpdate(); ``` -This creates an `IssueUpdate` which lets you specify the neccessary changes. +This creates an `IssueUpdate` which lets you specify the necessary changes. Label changes probably requires some explanation: - by default, no labels are set in an `IssueUpdate` - this is to indicate diff --git a/docs/releases.md b/docs/releases.md index 2fa4760fbf..950c5b6ed0 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -5,7 +5,7 @@ To retrieve all releases for a repository: ```csharp -var releases = client.Repository.Release.GetAll("octokit", "octokit.net"); +var releases = await client.Repository.Release.GetAll("octokit", "octokit.net"); var latest = releases[0]; Console.WriteLine( "The latest release is tagged at {0} and is named {1}", diff --git a/docs/search.md b/docs/search.md index da259e6ca0..bead98bcb8 100644 --- a/docs/search.md +++ b/docs/search.md @@ -212,7 +212,7 @@ var request = new SearchCodeRequest("auth") Path = "app/assets", // we may want to restrict the file based on file extension - Extension = "json", + Extensions = new[] { "json", "sql" }, // restrict search to a specific file name FileName = "app.json", diff --git a/global.json b/global.json new file mode 100644 index 0000000000..c685cffc7a --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "3.1.101" + } +} diff --git a/script/configure-integration-tests.ps1 b/script/configure-integration-tests.ps1 index e06dacb83b..4a3d6cdd6d 100644 --- a/script/configure-integration-tests.ps1 +++ b/script/configure-integration-tests.ps1 @@ -109,6 +109,7 @@ if (AskYesNoQuestion "Do you wish to enable GitHub Enterprise (GHE) Integration { VerifyEnvironmentVariable "GitHub Enterprise account name" "OCTOKIT_GHE_USERNAME" VerifyEnvironmentVariable "GitHub Enterprise account password" "OCTOKIT_GHE_PASSWORD" $true + VerifyEnvironmentVariable "GitHub Enterprise Management Console password" "OCTOKIT_GHE_CONSOLEPASSWORD" $true VerifyEnvironmentVariable "GitHub Enterprise OAuth token" "OCTOKIT_GHE_OAUTHTOKEN" VerifyEnvironmentVariable "GitHub Enterprise organization name" "OCTOKIT_GHE_ORGANIZATION" $true diff --git a/tools/gitversion_wrapper.sh b/tools/gitversion_wrapper.sh deleted file mode 100755 index bf0e49d947..0000000000 --- a/tools/gitversion_wrapper.sh +++ /dev/null @@ -1 +0,0 @@ -mono ./tools/GitVersion.CommandLine/tools/GitVersion.exe "$@" \ No newline at end of file